diff --git a/composer.lock b/composer.lock index e4cb72e4e7345f4793d567427850d70beae1e716..87176746d239b1eefb33aacde21b479258c62fd2 100644 --- a/composer.lock +++ b/composer.lock @@ -1,23 +1,23 @@ { "_readme": [ "This file locks the dependencies of your project to a known state", - "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", + "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], "content-hash": "d908f7b1863f5836c88a010d83d20bb3", "packages": [ { "name": "guzzlehttp/guzzle", - "version": "6.3.0", + "version": "6.3.3", "source": { "type": "git", "url": "https://github.com/guzzle/guzzle.git", - "reference": "f4db5a78a5ea468d4831de7f0bf9d9415e348699" + "reference": "407b0cb880ace85c9b63c5f9551db498cb2d50ba" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/guzzle/zipball/f4db5a78a5ea468d4831de7f0bf9d9415e348699", - "reference": "f4db5a78a5ea468d4831de7f0bf9d9415e348699", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/407b0cb880ace85c9b63c5f9551db498cb2d50ba", + "reference": "407b0cb880ace85c9b63c5f9551db498cb2d50ba", "shasum": "" }, "require": { @@ -27,7 +27,7 @@ }, "require-dev": { "ext-curl": "*", - "phpunit/phpunit": "^4.0 || ^5.0", + "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.4 || ^7.0", "psr/log": "^1.0" }, "suggest": { @@ -36,7 +36,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "6.2-dev" + "dev-master": "6.3-dev" } }, "autoload": { @@ -69,7 +69,7 @@ "rest", "web service" ], - "time": "2017-06-22T18:50:49+00:00" + "time": "2018-04-22T15:46:56+00:00" }, { "name": "guzzlehttp/promises", @@ -124,32 +124,37 @@ }, { "name": "guzzlehttp/psr7", - "version": "1.4.2", + "version": "1.6.1", "source": { "type": "git", "url": "https://github.com/guzzle/psr7.git", - "reference": "f5b8a8512e2b58b0071a7280e39f14f72e05d87c" + "reference": "239400de7a173fe9901b9ac7c06497751f00727a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/psr7/zipball/f5b8a8512e2b58b0071a7280e39f14f72e05d87c", - "reference": "f5b8a8512e2b58b0071a7280e39f14f72e05d87c", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/239400de7a173fe9901b9ac7c06497751f00727a", + "reference": "239400de7a173fe9901b9ac7c06497751f00727a", "shasum": "" }, "require": { "php": ">=5.4.0", - "psr/http-message": "~1.0" + "psr/http-message": "~1.0", + "ralouphie/getallheaders": "^2.0.5 || ^3.0.0" }, "provide": { "psr/http-message-implementation": "1.0" }, "require-dev": { - "phpunit/phpunit": "~4.0" + "ext-zlib": "*", + "phpunit/phpunit": "~4.8.36 || ^5.7.27 || ^6.5.8" + }, + "suggest": { + "zendframework/zend-httphandlerrunner": "Emit PSR-7 responses" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.4-dev" + "dev-master": "1.6-dev" } }, "autoload": { @@ -179,13 +184,14 @@ "keywords": [ "http", "message", + "psr-7", "request", "response", "stream", "uri", "url" ], - "time": "2017-03-20T17:10:46+00:00" + "time": "2019-07-01T23:21:34+00:00" }, { "name": "hab/paginator", @@ -209,7 +215,7 @@ "source": { "type": "git", "url": "git@github.com:dmj/php-solr.git", - "reference": "f16f0026296c6a4ea61601d51cf1b070ce1e0742" + "reference": "a54f2c7495dacc5cd0964fba25e1fa2b89cc03fe" }, "require": { "guzzlehttp/guzzle": "~6.0" @@ -220,55 +226,7 @@ "HAB": "src/" } }, - "time": "2017-07-20T13:50:14+00:00" - }, - { - "name": "paragonie/random_compat", - "version": "v2.0.11", - "source": { - "type": "git", - "url": "https://github.com/paragonie/random_compat.git", - "reference": "5da4d3c796c275c55f057af5a643ae297d96b4d8" - }, - "dist": { - "type": "zip", - "url": "https://api.github.com/repos/paragonie/random_compat/zipball/5da4d3c796c275c55f057af5a643ae297d96b4d8", - "reference": "5da4d3c796c275c55f057af5a643ae297d96b4d8", - "shasum": "" - }, - "require": { - "php": ">=5.2.0" - }, - "require-dev": { - "phpunit/phpunit": "4.*|5.*" - }, - "suggest": { - "ext-libsodium": "Provides a modern crypto API that can be used to generate random bytes." - }, - "type": "library", - "autoload": { - "files": [ - "lib/random.php" - ] - }, - "notification-url": "https://packagist.org/downloads/", - "license": [ - "MIT" - ], - "authors": [ - { - "name": "Paragon Initiative Enterprises", - "email": "security@paragonie.com", - "homepage": "https://paragonie.com" - } - ], - "description": "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7", - "keywords": [ - "csprng", - "pseudorandom", - "random" - ], - "time": "2017-09-27T21:40:39+00:00" + "time": "2019-08-07T06:46:21+00:00" }, { "name": "pimple/pimple", @@ -421,16 +379,16 @@ }, { "name": "psr/log", - "version": "1.0.2", + "version": "1.1.0", "source": { "type": "git", "url": "https://github.com/php-fig/log.git", - "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d" + "reference": "6c001f1daafa3a3ac1d8ff69ee4db8e799a654dd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/log/zipball/4ebe3a8bf773a19edfe0a84b6585ba3d401b724d", - "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d", + "url": "https://api.github.com/repos/php-fig/log/zipball/6c001f1daafa3a3ac1d8ff69ee4db8e799a654dd", + "reference": "6c001f1daafa3a3ac1d8ff69ee4db8e799a654dd", "shasum": "" }, "require": { @@ -464,69 +422,106 @@ "psr", "psr-3" ], - "time": "2016-10-10T12:19:37+00:00" + "time": "2018-11-20T15:27:04+00:00" + }, + { + "name": "ralouphie/getallheaders", + "version": "3.0.3", + "source": { + "type": "git", + "url": "https://github.com/ralouphie/getallheaders.git", + "reference": "120b605dfeb996808c31b6477290a714d356e822" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ralouphie/getallheaders/zipball/120b605dfeb996808c31b6477290a714d356e822", + "reference": "120b605dfeb996808c31b6477290a714d356e822", + "shasum": "" + }, + "require": { + "php": ">=5.6" + }, + "require-dev": { + "php-coveralls/php-coveralls": "^2.1", + "phpunit/phpunit": "^5 || ^6.5" + }, + "type": "library", + "autoload": { + "files": [ + "src/getallheaders.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ralph Khattar", + "email": "ralph.khattar@gmail.com" + } + ], + "description": "A polyfill for getallheaders.", + "time": "2019-03-08T08:55:37+00:00" }, { "name": "silex/silex", - "version": "v2.2.3", + "version": "v2.3.0", "source": { "type": "git", "url": "https://github.com/silexphp/Silex.git", - "reference": "90c80c3e5ef86c54b8769feca0320154c6e63f7c" + "reference": "6bc31c1b8c4ef614a7115320fd2d3b958032f131" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/silexphp/Silex/zipball/90c80c3e5ef86c54b8769feca0320154c6e63f7c", - "reference": "90c80c3e5ef86c54b8769feca0320154c6e63f7c", + "url": "https://api.github.com/repos/silexphp/Silex/zipball/6bc31c1b8c4ef614a7115320fd2d3b958032f131", + "reference": "6bc31c1b8c4ef614a7115320fd2d3b958032f131", "shasum": "" }, "require": { - "php": ">=5.5.9", - "pimple/pimple": "~3.0", - "symfony/event-dispatcher": "~2.8|^3.0", - "symfony/http-foundation": "~2.8|^3.0", - "symfony/http-kernel": "~2.8|^3.0", - "symfony/routing": "~2.8|^3.0" - }, - "conflict": { - "phpunit/phpunit": "<4.8.35 || >= 5.0, <5.4.3" + "php": ">=7.1.3", + "pimple/pimple": "^3.0", + "symfony/event-dispatcher": "^4.0", + "symfony/http-foundation": "^4.0", + "symfony/http-kernel": "^4.0", + "symfony/routing": "^4.0" }, "replace": { "silex/api": "self.version", "silex/providers": "self.version" }, "require-dev": { - "doctrine/dbal": "~2.2", + "doctrine/dbal": "^2.2", "monolog/monolog": "^1.4.1", - "swiftmailer/swiftmailer": "~5", - "symfony/asset": "~2.8|^3.0", - "symfony/browser-kit": "~2.8|^3.0", - "symfony/config": "~2.8|^3.0", - "symfony/css-selector": "~2.8|^3.0", - "symfony/debug": "~2.8|^3.0", - "symfony/doctrine-bridge": "~2.8|^3.0", - "symfony/dom-crawler": "~2.8|^3.0", - "symfony/expression-language": "~2.8|^3.0", - "symfony/finder": "~2.8|^3.0", - "symfony/form": "~2.8|^3.0", - "symfony/intl": "~2.8|^3.0", - "symfony/monolog-bridge": "~2.8|^3.0", - "symfony/options-resolver": "~2.8|^3.0", + "swiftmailer/swiftmailer": "^5", + "symfony/asset": "^4.0", + "symfony/browser-kit": "^4.0", + "symfony/config": "^4.0", + "symfony/css-selector": "^4.0", + "symfony/debug": "^4.0", + "symfony/doctrine-bridge": "^4.0", + "symfony/dom-crawler": "^4.0", + "symfony/expression-language": "^4.0", + "symfony/finder": "^4.0", + "symfony/form": "^4.0", + "symfony/intl": "^4.0", + "symfony/monolog-bridge": "^4.0", + "symfony/options-resolver": "^4.0", "symfony/phpunit-bridge": "^3.2", - "symfony/process": "~2.8|^3.0", - "symfony/security": "~2.8|^3.0", - "symfony/serializer": "~2.8|^3.0", - "symfony/translation": "~2.8|^3.0", - "symfony/twig-bridge": "~2.8|^3.0", - "symfony/validator": "~2.8|^3.0", - "symfony/var-dumper": "~2.8|^3.0", - "symfony/web-link": "^3.3", - "twig/twig": "~1.28|~2.0" + "symfony/process": "^4.0", + "symfony/security": "^4.0", + "symfony/serializer": "^4.0", + "symfony/translation": "^4.0", + "symfony/twig-bridge": "^4.0", + "symfony/validator": "^4.0", + "symfony/var-dumper": "^4.0", + "symfony/web-link": "^4.0", + "twig/twig": "^2.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "2.2.x-dev" + "dev-master": "2.3.x-dev" } }, "autoload": { @@ -553,36 +548,37 @@ "keywords": [ "microframework" ], - "time": "2018-02-25T11:21:42+00:00" + "abandoned": "symfony/flex", + "time": "2018-04-20T05:17:01+00:00" }, { "name": "symfony/debug", - "version": "v3.4.4", + "version": "v4.3.5", "source": { "type": "git", "url": "https://github.com/symfony/debug.git", - "reference": "53f6af2805daf52a43b393b93d2f24925d35c937" + "reference": "cc5c1efd0edfcfd10b354750594a46b3dd2afbbe" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/debug/zipball/53f6af2805daf52a43b393b93d2f24925d35c937", - "reference": "53f6af2805daf52a43b393b93d2f24925d35c937", + "url": "https://api.github.com/repos/symfony/debug/zipball/cc5c1efd0edfcfd10b354750594a46b3dd2afbbe", + "reference": "cc5c1efd0edfcfd10b354750594a46b3dd2afbbe", "shasum": "" }, "require": { - "php": "^5.5.9|>=7.0.8", + "php": "^7.1.3", "psr/log": "~1.0" }, "conflict": { - "symfony/http-kernel": ">=2.3,<2.3.24|~2.4.0|>=2.5,<2.5.9|>=2.6,<2.6.2" + "symfony/http-kernel": "<3.4" }, "require-dev": { - "symfony/http-kernel": "~2.8|~3.0|~4.0" + "symfony/http-kernel": "~3.4|~4.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.4-dev" + "dev-master": "4.3-dev" } }, "autoload": { @@ -609,34 +605,41 @@ ], "description": "Symfony Debug Component", "homepage": "https://symfony.com", - "time": "2018-01-18T22:16:57+00:00" + "time": "2019-09-19T15:51:53+00:00" }, { "name": "symfony/event-dispatcher", - "version": "v3.4.4", + "version": "v4.3.5", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "26b87b6bca8f8f797331a30b76fdae5342dc26ca" + "reference": "6229f58993e5a157f6096fc7145c0717d0be8807" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/26b87b6bca8f8f797331a30b76fdae5342dc26ca", - "reference": "26b87b6bca8f8f797331a30b76fdae5342dc26ca", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/6229f58993e5a157f6096fc7145c0717d0be8807", + "reference": "6229f58993e5a157f6096fc7145c0717d0be8807", "shasum": "" }, "require": { - "php": "^5.5.9|>=7.0.8" + "php": "^7.1.3", + "symfony/event-dispatcher-contracts": "^1.1" }, "conflict": { - "symfony/dependency-injection": "<3.3" + "symfony/dependency-injection": "<3.4" + }, + "provide": { + "psr/event-dispatcher-implementation": "1.0", + "symfony/event-dispatcher-implementation": "1.1" }, "require-dev": { "psr/log": "~1.0", - "symfony/config": "~2.8|~3.0|~4.0", - "symfony/dependency-injection": "~3.3|~4.0", - "symfony/expression-language": "~2.8|~3.0|~4.0", - "symfony/stopwatch": "~2.8|~3.0|~4.0" + "symfony/config": "~3.4|~4.0", + "symfony/dependency-injection": "~3.4|~4.0", + "symfony/expression-language": "~3.4|~4.0", + "symfony/http-foundation": "^3.4|^4.0", + "symfony/service-contracts": "^1.1", + "symfony/stopwatch": "~3.4|~4.0" }, "suggest": { "symfony/dependency-injection": "", @@ -645,7 +648,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "3.4-dev" + "dev-master": "4.3-dev" } }, "autoload": { @@ -672,34 +675,93 @@ ], "description": "Symfony EventDispatcher Component", "homepage": "https://symfony.com", - "time": "2018-01-03T07:37:34+00:00" + "time": "2019-10-01T16:40:32+00:00" + }, + { + "name": "symfony/event-dispatcher-contracts", + "version": "v1.1.7", + "source": { + "type": "git", + "url": "https://github.com/symfony/event-dispatcher-contracts.git", + "reference": "c43ab685673fb6c8d84220c77897b1d6cdbe1d18" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/c43ab685673fb6c8d84220c77897b1d6cdbe1d18", + "reference": "c43ab685673fb6c8d84220c77897b1d6cdbe1d18", + "shasum": "" + }, + "require": { + "php": "^7.1.3" + }, + "suggest": { + "psr/event-dispatcher": "", + "symfony/event-dispatcher-implementation": "" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.1-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Contracts\\EventDispatcher\\": "" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Generic abstractions related to dispatching event", + "homepage": "https://symfony.com", + "keywords": [ + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" + ], + "time": "2019-09-17T09:54:03+00:00" }, { "name": "symfony/http-foundation", - "version": "v3.4.4", + "version": "v4.3.5", "source": { "type": "git", "url": "https://github.com/symfony/http-foundation.git", - "reference": "8c39071ac9cc7e6d8dab1d556c990dc0d2cc3d30" + "reference": "76590ced16d4674780863471bae10452b79210a5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/8c39071ac9cc7e6d8dab1d556c990dc0d2cc3d30", - "reference": "8c39071ac9cc7e6d8dab1d556c990dc0d2cc3d30", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/76590ced16d4674780863471bae10452b79210a5", + "reference": "76590ced16d4674780863471bae10452b79210a5", "shasum": "" }, "require": { - "php": "^5.5.9|>=7.0.8", - "symfony/polyfill-mbstring": "~1.1", - "symfony/polyfill-php70": "~1.6" + "php": "^7.1.3", + "symfony/mime": "^4.3", + "symfony/polyfill-mbstring": "~1.1" }, "require-dev": { - "symfony/expression-language": "~2.8|~3.0|~4.0" + "predis/predis": "~1.0", + "symfony/expression-language": "~3.4|~4.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.4-dev" + "dev-master": "4.3-dev" } }, "autoload": { @@ -726,33 +788,37 @@ ], "description": "Symfony HttpFoundation Component", "homepage": "https://symfony.com", - "time": "2018-01-29T09:03:43+00:00" + "time": "2019-10-04T19:48:13+00:00" }, { "name": "symfony/http-kernel", - "version": "v3.4.4", + "version": "v4.3.5", "source": { "type": "git", "url": "https://github.com/symfony/http-kernel.git", - "reference": "911d2e5dd4beb63caad9a72e43857de984301907" + "reference": "5f08141850932e8019c01d8988bf3ed6367d2991" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/911d2e5dd4beb63caad9a72e43857de984301907", - "reference": "911d2e5dd4beb63caad9a72e43857de984301907", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/5f08141850932e8019c01d8988bf3ed6367d2991", + "reference": "5f08141850932e8019c01d8988bf3ed6367d2991", "shasum": "" }, "require": { - "php": "^5.5.9|>=7.0.8", + "php": "^7.1.3", "psr/log": "~1.0", - "symfony/debug": "~2.8|~3.0|~4.0", - "symfony/event-dispatcher": "~2.8|~3.0|~4.0", - "symfony/http-foundation": "^3.4.4|^4.0.4" + "symfony/debug": "~3.4|~4.0", + "symfony/event-dispatcher": "^4.3", + "symfony/http-foundation": "^4.1.1", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-php73": "^1.9" }, "conflict": { - "symfony/config": "<2.8", - "symfony/dependency-injection": "<3.4", - "symfony/var-dumper": "<3.3", + "symfony/browser-kit": "<4.3", + "symfony/config": "<3.4", + "symfony/dependency-injection": "<4.3", + "symfony/translation": "<4.2", + "symfony/var-dumper": "<4.1.1", "twig/twig": "<1.34|<2.4,>=2" }, "provide": { @@ -760,34 +826,34 @@ }, "require-dev": { "psr/cache": "~1.0", - "symfony/browser-kit": "~2.8|~3.0|~4.0", - "symfony/class-loader": "~2.8|~3.0", - "symfony/config": "~2.8|~3.0|~4.0", - "symfony/console": "~2.8|~3.0|~4.0", - "symfony/css-selector": "~2.8|~3.0|~4.0", - "symfony/dependency-injection": "~3.4|~4.0", - "symfony/dom-crawler": "~2.8|~3.0|~4.0", - "symfony/expression-language": "~2.8|~3.0|~4.0", - "symfony/finder": "~2.8|~3.0|~4.0", - "symfony/process": "~2.8|~3.0|~4.0", + "symfony/browser-kit": "^4.3", + "symfony/config": "~3.4|~4.0", + "symfony/console": "~3.4|~4.0", + "symfony/css-selector": "~3.4|~4.0", + "symfony/dependency-injection": "^4.3", + "symfony/dom-crawler": "~3.4|~4.0", + "symfony/expression-language": "~3.4|~4.0", + "symfony/finder": "~3.4|~4.0", + "symfony/process": "~3.4|~4.0", "symfony/routing": "~3.4|~4.0", - "symfony/stopwatch": "~2.8|~3.0|~4.0", - "symfony/templating": "~2.8|~3.0|~4.0", - "symfony/translation": "~2.8|~3.0|~4.0", - "symfony/var-dumper": "~3.3|~4.0" + "symfony/stopwatch": "~3.4|~4.0", + "symfony/templating": "~3.4|~4.0", + "symfony/translation": "~4.2", + "symfony/translation-contracts": "^1.1", + "symfony/var-dumper": "^4.1.1", + "twig/twig": "^1.34|^2.4" }, "suggest": { "symfony/browser-kit": "", "symfony/config": "", "symfony/console": "", "symfony/dependency-injection": "", - "symfony/finder": "", "symfony/var-dumper": "" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "3.4-dev" + "dev-master": "4.3-dev" } }, "autoload": { @@ -814,20 +880,199 @@ ], "description": "Symfony HttpKernel Component", "homepage": "https://symfony.com", - "time": "2018-01-29T12:29:46+00:00" + "time": "2019-10-07T15:06:41+00:00" + }, + { + "name": "symfony/mime", + "version": "v4.3.5", + "source": { + "type": "git", + "url": "https://github.com/symfony/mime.git", + "reference": "32f71570547b91879fdbd9cf50317d556ae86916" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/mime/zipball/32f71570547b91879fdbd9cf50317d556ae86916", + "reference": "32f71570547b91879fdbd9cf50317d556ae86916", + "shasum": "" + }, + "require": { + "php": "^7.1.3", + "symfony/polyfill-intl-idn": "^1.10", + "symfony/polyfill-mbstring": "^1.0" + }, + "require-dev": { + "egulias/email-validator": "^2.1.10", + "symfony/dependency-injection": "~3.4|^4.1" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.3-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\Mime\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "A library to manipulate MIME messages", + "homepage": "https://symfony.com", + "keywords": [ + "mime", + "mime-type" + ], + "time": "2019-09-19T17:00:15+00:00" + }, + { + "name": "symfony/polyfill-ctype", + "version": "v1.12.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-ctype.git", + "reference": "550ebaac289296ce228a706d0867afc34687e3f4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/550ebaac289296ce228a706d0867afc34687e3f4", + "reference": "550ebaac289296ce228a706d0867afc34687e3f4", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "suggest": { + "ext-ctype": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.12-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Ctype\\": "" + }, + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Gert de Pagter", + "email": "BackEndTea@gmail.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for ctype functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "ctype", + "polyfill", + "portable" + ], + "time": "2019-08-06T08:03:45+00:00" + }, + { + "name": "symfony/polyfill-intl-idn", + "version": "v1.12.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-intl-idn.git", + "reference": "6af626ae6fa37d396dc90a399c0ff08e5cfc45b2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/6af626ae6fa37d396dc90a399c0ff08e5cfc45b2", + "reference": "6af626ae6fa37d396dc90a399c0ff08e5cfc45b2", + "shasum": "" + }, + "require": { + "php": ">=5.3.3", + "symfony/polyfill-mbstring": "^1.3", + "symfony/polyfill-php72": "^1.9" + }, + "suggest": { + "ext-intl": "For best performance" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.12-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Intl\\Idn\\": "" + }, + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Laurent Bassin", + "email": "laurent@bassin.info" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for intl's idn_to_ascii and idn_to_utf8 functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "idn", + "intl", + "polyfill", + "portable", + "shim" + ], + "time": "2019-08-06T08:03:45+00:00" }, { "name": "symfony/polyfill-mbstring", - "version": "v1.7.0", + "version": "v1.12.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "78be803ce01e55d3491c1397cf1c64beb9c1b63b" + "reference": "b42a2f66e8f1b15ccf25652c3424265923eb4f17" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/78be803ce01e55d3491c1397cf1c64beb9c1b63b", - "reference": "78be803ce01e55d3491c1397cf1c64beb9c1b63b", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/b42a2f66e8f1b15ccf25652c3424265923eb4f17", + "reference": "b42a2f66e8f1b15ccf25652c3424265923eb4f17", "shasum": "" }, "require": { @@ -839,7 +1084,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.7-dev" + "dev-master": "1.12-dev" } }, "autoload": { @@ -873,35 +1118,89 @@ "portable", "shim" ], - "time": "2018-01-30T19:27:44+00:00" + "time": "2019-08-06T08:03:45+00:00" }, { - "name": "symfony/polyfill-php70", - "version": "v1.7.0", + "name": "symfony/polyfill-php72", + "version": "v1.12.0", "source": { "type": "git", - "url": "https://github.com/symfony/polyfill-php70.git", - "reference": "3532bfcd8f933a7816f3a0a59682fc404776600f" + "url": "https://github.com/symfony/polyfill-php72.git", + "reference": "04ce3335667451138df4307d6a9b61565560199e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php70/zipball/3532bfcd8f933a7816f3a0a59682fc404776600f", - "reference": "3532bfcd8f933a7816f3a0a59682fc404776600f", + "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/04ce3335667451138df4307d6a9b61565560199e", + "reference": "04ce3335667451138df4307d6a9b61565560199e", "shasum": "" }, "require": { - "paragonie/random_compat": "~1.0|~2.0", "php": ">=5.3.3" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.7-dev" + "dev-master": "1.12-dev" } }, "autoload": { "psr-4": { - "Symfony\\Polyfill\\Php70\\": "" + "Symfony\\Polyfill\\Php72\\": "" + }, + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 7.2+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "time": "2019-08-06T08:03:45+00:00" + }, + { + "name": "symfony/polyfill-php73", + "version": "v1.12.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php73.git", + "reference": "2ceb49eaccb9352bff54d22570276bb75ba4a188" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/2ceb49eaccb9352bff54d22570276bb75ba4a188", + "reference": "2ceb49eaccb9352bff54d22570276bb75ba4a188", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.12-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Php73\\": "" }, "files": [ "bootstrap.php" @@ -924,7 +1223,7 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony polyfill backporting some PHP 7.0+ features to lower PHP versions", + "description": "Symfony polyfill backporting some PHP 7.3+ features to lower PHP versions", "homepage": "https://symfony.com", "keywords": [ "compatibility", @@ -932,44 +1231,42 @@ "portable", "shim" ], - "time": "2018-01-30T19:27:44+00:00" + "time": "2019-08-06T08:03:45+00:00" }, { "name": "symfony/routing", - "version": "v3.4.4", + "version": "v4.3.5", "source": { "type": "git", "url": "https://github.com/symfony/routing.git", - "reference": "235d01730d553a97732990588407eaf6779bb4b2" + "reference": "3b174ef04fe66696524efad1e5f7a6c663d822ea" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/routing/zipball/235d01730d553a97732990588407eaf6779bb4b2", - "reference": "235d01730d553a97732990588407eaf6779bb4b2", + "url": "https://api.github.com/repos/symfony/routing/zipball/3b174ef04fe66696524efad1e5f7a6c663d822ea", + "reference": "3b174ef04fe66696524efad1e5f7a6c663d822ea", "shasum": "" }, "require": { - "php": "^5.5.9|>=7.0.8" + "php": "^7.1.3" }, "conflict": { - "symfony/config": "<2.8", - "symfony/dependency-injection": "<3.3", + "symfony/config": "<4.2", + "symfony/dependency-injection": "<3.4", "symfony/yaml": "<3.4" }, "require-dev": { - "doctrine/annotations": "~1.0", - "doctrine/common": "~2.2", + "doctrine/annotations": "~1.2", "psr/log": "~1.0", - "symfony/config": "~2.8|~3.0|~4.0", - "symfony/dependency-injection": "~3.3|~4.0", - "symfony/expression-language": "~2.8|~3.0|~4.0", - "symfony/http-foundation": "~2.8|~3.0|~4.0", + "symfony/config": "~4.2", + "symfony/dependency-injection": "~3.4|~4.0", + "symfony/expression-language": "~3.4|~4.0", + "symfony/http-foundation": "~3.4|~4.0", "symfony/yaml": "~3.4|~4.0" }, "suggest": { "doctrine/annotations": "For using the annotation loader", "symfony/config": "For using the all-in-one router or any loader", - "symfony/dependency-injection": "For loading routes from a service", "symfony/expression-language": "For using expression matching", "symfony/http-foundation": "For using a Symfony Request object", "symfony/yaml": "For using the YAML loader" @@ -977,7 +1274,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "3.4-dev" + "dev-master": "4.3-dev" } }, "autoload": { @@ -1010,42 +1307,43 @@ "uri", "url" ], - "time": "2018-01-16T18:03:57+00:00" + "time": "2019-10-04T20:57:10+00:00" }, { "name": "symfony/twig-bridge", - "version": "v3.4.4", + "version": "v3.4.32", "source": { "type": "git", "url": "https://github.com/symfony/twig-bridge.git", - "reference": "a69e3f21f2f652ae3da0937914e3f3830cc6eae9" + "reference": "9f55b34b539a3a0ea51c2ed96609173c5b326259" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/twig-bridge/zipball/a69e3f21f2f652ae3da0937914e3f3830cc6eae9", - "reference": "a69e3f21f2f652ae3da0937914e3f3830cc6eae9", + "url": "https://api.github.com/repos/symfony/twig-bridge/zipball/9f55b34b539a3a0ea51c2ed96609173c5b326259", + "reference": "9f55b34b539a3a0ea51c2ed96609173c5b326259", "shasum": "" }, "require": { "php": "^5.5.9|>=7.0.8", - "twig/twig": "^1.35|^2.4.4" + "twig/twig": "^1.41|^2.10" }, "conflict": { "symfony/console": "<3.4", - "symfony/form": "<3.4" + "symfony/form": "<3.4.31|>=4.0,<4.3.4" }, "require-dev": { + "fig/link-util": "^1.0", "symfony/asset": "~2.8|~3.0|~4.0", "symfony/console": "~3.4|~4.0", "symfony/dependency-injection": "~2.8|~3.0|~4.0", "symfony/expression-language": "~2.8|~3.0|~4.0", "symfony/finder": "~2.8|~3.0|~4.0", - "symfony/form": "~3.4|~4.0", + "symfony/form": "^3.4.31|^4.3.4", "symfony/http-foundation": "^3.3.11|~4.0", "symfony/http-kernel": "~3.2|~4.0", "symfony/polyfill-intl-icu": "~1.0", "symfony/routing": "~2.8|~3.0|~4.0", - "symfony/security": "~2.8|~3.0|~4.0", + "symfony/security": "^2.8.31|^3.3.13|~4.0", "symfony/security-acl": "~2.8|~3.0", "symfony/stopwatch": "~2.8|~3.0|~4.0", "symfony/templating": "~2.8|~3.0|~4.0", @@ -1100,34 +1398,35 @@ ], "description": "Symfony Twig Bridge", "homepage": "https://symfony.com", - "time": "2018-01-17T07:49:55+00:00" + "time": "2019-10-01T15:13:36+00:00" }, { "name": "twig/twig", - "version": "v1.35.0", + "version": "v1.42.3", "source": { "type": "git", "url": "https://github.com/twigphp/Twig.git", - "reference": "daa657073e55b0a78cce8fdd22682fddecc6385f" + "reference": "201baee843e0ffe8b0b956f336dd42b2a92fae4e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/twigphp/Twig/zipball/daa657073e55b0a78cce8fdd22682fddecc6385f", - "reference": "daa657073e55b0a78cce8fdd22682fddecc6385f", + "url": "https://api.github.com/repos/twigphp/Twig/zipball/201baee843e0ffe8b0b956f336dd42b2a92fae4e", + "reference": "201baee843e0ffe8b0b956f336dd42b2a92fae4e", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": ">=5.5.0", + "symfony/polyfill-ctype": "^1.8" }, "require-dev": { "psr/container": "^1.0", - "symfony/debug": "~2.7", - "symfony/phpunit-bridge": "~3.3@dev" + "symfony/debug": "^3.4|^4.2", + "symfony/phpunit-bridge": "^4.4@dev|^5.0" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "1.35-dev" + "dev-master": "1.42-dev" } }, "autoload": { @@ -1149,23 +1448,23 @@ "homepage": "http://fabien.potencier.org", "role": "Lead Developer" }, + { + "name": "Twig Team", + "homepage": "https://twig.symfony.com/contributors", + "role": "Contributors" + }, { "name": "Armin Ronacher", "email": "armin.ronacher@active-4.com", "role": "Project Founder" - }, - { - "name": "Twig Team", - "homepage": "http://twig.sensiolabs.org/contributors", - "role": "Contributors" } ], "description": "Twig, the flexible, fast, and secure template language for PHP", - "homepage": "http://twig.sensiolabs.org", + "homepage": "https://twig.symfony.com", "keywords": [ "templating" ], - "time": "2017-09-27T18:06:46+00:00" + "time": "2019-08-24T12:51:03+00:00" } ], "packages-dev": [], diff --git a/vendor/composer/ClassLoader.php b/vendor/composer/ClassLoader.php index 4626994fd4d8ac4c5489670d85b09af1b6d8aab0..fce8549f0781bafdc7da2301b84d048286757445 100644 --- a/vendor/composer/ClassLoader.php +++ b/vendor/composer/ClassLoader.php @@ -279,7 +279,7 @@ class ClassLoader */ public function setApcuPrefix($apcuPrefix) { - $this->apcuPrefix = function_exists('apcu_fetch') && ini_get('apc.enabled') ? $apcuPrefix : null; + $this->apcuPrefix = function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null; } /** @@ -374,10 +374,14 @@ class ClassLoader $first = $class[0]; if (isset($this->prefixLengthsPsr4[$first])) { - foreach ($this->prefixLengthsPsr4[$first] as $prefix => $length) { - if (0 === strpos($class, $prefix)) { - foreach ($this->prefixDirsPsr4[$prefix] as $dir) { - if (file_exists($file = $dir . DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $length))) { + $subPath = $class; + while (false !== $lastPos = strrpos($subPath, '\\')) { + $subPath = substr($subPath, 0, $lastPos); + $search = $subPath . '\\'; + if (isset($this->prefixDirsPsr4[$search])) { + $pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1); + foreach ($this->prefixDirsPsr4[$search] as $dir) { + if (file_exists($file = $dir . $pathEnd)) { return $file; } } diff --git a/vendor/composer/LICENSE b/vendor/composer/LICENSE index 1a28124886db89f1ca3e4fa674cb69a9a17585b3..f27399a042d95c4708af3a8c74d35d338763cf8f 100644 --- a/vendor/composer/LICENSE +++ b/vendor/composer/LICENSE @@ -1,5 +1,5 @@ -Copyright (c) 2016 Nils Adermann, Jordi Boggiano +Copyright (c) Nils Adermann, Jordi Boggiano Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/vendor/composer/autoload_classmap.php b/vendor/composer/autoload_classmap.php index 3a1416586929fd3c2294d13d5c5f8fc3dfb6cda5..5db5c9773020f5c97a96b2be20c9dd954abb3458 100644 --- a/vendor/composer/autoload_classmap.php +++ b/vendor/composer/autoload_classmap.php @@ -6,11 +6,5 @@ $vendorDir = dirname(dirname(__FILE__)); $baseDir = dirname($vendorDir); return array( - 'ArithmeticError' => $vendorDir . '/symfony/polyfill-php70/Resources/stubs/ArithmeticError.php', - 'AssertionError' => $vendorDir . '/symfony/polyfill-php70/Resources/stubs/AssertionError.php', - 'DivisionByZeroError' => $vendorDir . '/symfony/polyfill-php70/Resources/stubs/DivisionByZeroError.php', - 'Error' => $vendorDir . '/symfony/polyfill-php70/Resources/stubs/Error.php', - 'ParseError' => $vendorDir . '/symfony/polyfill-php70/Resources/stubs/ParseError.php', - 'SessionUpdateTimestampHandlerInterface' => $vendorDir . '/symfony/polyfill-php70/Resources/stubs/SessionUpdateTimestampHandlerInterface.php', - 'TypeError' => $vendorDir . '/symfony/polyfill-php70/Resources/stubs/TypeError.php', + 'JsonException' => $vendorDir . '/symfony/polyfill-php73/Resources/stubs/JsonException.php', ); diff --git a/vendor/composer/autoload_files.php b/vendor/composer/autoload_files.php index 90cd12da3e67cb21f65b7620e03fcbc6ca710580..78110623d87caf34799d5e507cd8232a32965a52 100644 --- a/vendor/composer/autoload_files.php +++ b/vendor/composer/autoload_files.php @@ -6,9 +6,12 @@ $vendorDir = dirname(dirname(__FILE__)); $baseDir = dirname($vendorDir); return array( - '5255c38a0faeba867671b61dfda6d864' => $vendorDir . '/paragonie/random_compat/lib/random.php', - '023d27dca8066ef29e6739335ea73bad' => $vendorDir . '/symfony/polyfill-php70/bootstrap.php', '0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php', + '25072dd6e2470089de65ae7bf11d3109' => $vendorDir . '/symfony/polyfill-php72/bootstrap.php', + 'f598d06aa772fa33d905e87be6398fb1' => $vendorDir . '/symfony/polyfill-intl-idn/bootstrap.php', + '320cde22f66dd4f5d3fd621d3e88b98f' => $vendorDir . '/symfony/polyfill-ctype/bootstrap.php', + '0d59ee240a4cd96ddbb4ff164fccea4d' => $vendorDir . '/symfony/polyfill-php73/bootstrap.php', + '7b11c4dc42b3b3023073cb14e519683c' => $vendorDir . '/ralouphie/getallheaders/src/getallheaders.php', 'c964ee0ededf28c96ebd9db5099ef910' => $vendorDir . '/guzzlehttp/promises/src/functions_include.php', 'a0edc8309cc5e1d60e3047b5df6b7052' => $vendorDir . '/guzzlehttp/psr7/src/functions_include.php', '37a3dc5111fe8f707ab4c132ef1dbc62' => $vendorDir . '/guzzlehttp/guzzle/src/functions_include.php', diff --git a/vendor/composer/autoload_psr4.php b/vendor/composer/autoload_psr4.php index 7c118c862ebcd8d795cad1888e8c07982bec0596..8f5ae4033a05dccfefcd4eb6dce4211d00a0e165 100644 --- a/vendor/composer/autoload_psr4.php +++ b/vendor/composer/autoload_psr4.php @@ -7,9 +7,14 @@ $baseDir = dirname($vendorDir); return array( 'Twig\\' => array($vendorDir . '/twig/twig/src'), - 'Symfony\\Polyfill\\Php70\\' => array($vendorDir . '/symfony/polyfill-php70'), + 'Symfony\\Polyfill\\Php73\\' => array($vendorDir . '/symfony/polyfill-php73'), + 'Symfony\\Polyfill\\Php72\\' => array($vendorDir . '/symfony/polyfill-php72'), 'Symfony\\Polyfill\\Mbstring\\' => array($vendorDir . '/symfony/polyfill-mbstring'), + 'Symfony\\Polyfill\\Intl\\Idn\\' => array($vendorDir . '/symfony/polyfill-intl-idn'), + 'Symfony\\Polyfill\\Ctype\\' => array($vendorDir . '/symfony/polyfill-ctype'), + 'Symfony\\Contracts\\EventDispatcher\\' => array($vendorDir . '/symfony/event-dispatcher-contracts'), 'Symfony\\Component\\Routing\\' => array($vendorDir . '/symfony/routing'), + 'Symfony\\Component\\Mime\\' => array($vendorDir . '/symfony/mime'), 'Symfony\\Component\\HttpKernel\\' => array($vendorDir . '/symfony/http-kernel'), 'Symfony\\Component\\HttpFoundation\\' => array($vendorDir . '/symfony/http-foundation'), 'Symfony\\Component\\EventDispatcher\\' => array($vendorDir . '/symfony/event-dispatcher'), diff --git a/vendor/composer/autoload_static.php b/vendor/composer/autoload_static.php index 6bb107e7acafe2caa5d17074cfe9c24bd95819aa..b33df1c81aeac4daefe475179ca243c3b41d671d 100644 --- a/vendor/composer/autoload_static.php +++ b/vendor/composer/autoload_static.php @@ -7,9 +7,12 @@ namespace Composer\Autoload; class ComposerStaticInit8a9318ad96e1e6602a968c996fe31931 { public static $files = array ( - '5255c38a0faeba867671b61dfda6d864' => __DIR__ . '/..' . '/paragonie/random_compat/lib/random.php', - '023d27dca8066ef29e6739335ea73bad' => __DIR__ . '/..' . '/symfony/polyfill-php70/bootstrap.php', '0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/bootstrap.php', + '25072dd6e2470089de65ae7bf11d3109' => __DIR__ . '/..' . '/symfony/polyfill-php72/bootstrap.php', + 'f598d06aa772fa33d905e87be6398fb1' => __DIR__ . '/..' . '/symfony/polyfill-intl-idn/bootstrap.php', + '320cde22f66dd4f5d3fd621d3e88b98f' => __DIR__ . '/..' . '/symfony/polyfill-ctype/bootstrap.php', + '0d59ee240a4cd96ddbb4ff164fccea4d' => __DIR__ . '/..' . '/symfony/polyfill-php73/bootstrap.php', + '7b11c4dc42b3b3023073cb14e519683c' => __DIR__ . '/..' . '/ralouphie/getallheaders/src/getallheaders.php', 'c964ee0ededf28c96ebd9db5099ef910' => __DIR__ . '/..' . '/guzzlehttp/promises/src/functions_include.php', 'a0edc8309cc5e1d60e3047b5df6b7052' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/functions_include.php', '37a3dc5111fe8f707ab4c132ef1dbc62' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/functions_include.php', @@ -22,9 +25,14 @@ class ComposerStaticInit8a9318ad96e1e6602a968c996fe31931 ), 'S' => array ( - 'Symfony\\Polyfill\\Php70\\' => 23, + 'Symfony\\Polyfill\\Php73\\' => 23, + 'Symfony\\Polyfill\\Php72\\' => 23, 'Symfony\\Polyfill\\Mbstring\\' => 26, + 'Symfony\\Polyfill\\Intl\\Idn\\' => 26, + 'Symfony\\Polyfill\\Ctype\\' => 23, + 'Symfony\\Contracts\\EventDispatcher\\' => 34, 'Symfony\\Component\\Routing\\' => 26, + 'Symfony\\Component\\Mime\\' => 23, 'Symfony\\Component\\HttpKernel\\' => 29, 'Symfony\\Component\\HttpFoundation\\' => 33, 'Symfony\\Component\\EventDispatcher\\' => 34, @@ -55,18 +63,38 @@ class ComposerStaticInit8a9318ad96e1e6602a968c996fe31931 array ( 0 => __DIR__ . '/..' . '/twig/twig/src', ), - 'Symfony\\Polyfill\\Php70\\' => + 'Symfony\\Polyfill\\Php73\\' => array ( - 0 => __DIR__ . '/..' . '/symfony/polyfill-php70', + 0 => __DIR__ . '/..' . '/symfony/polyfill-php73', + ), + 'Symfony\\Polyfill\\Php72\\' => + array ( + 0 => __DIR__ . '/..' . '/symfony/polyfill-php72', ), 'Symfony\\Polyfill\\Mbstring\\' => array ( 0 => __DIR__ . '/..' . '/symfony/polyfill-mbstring', ), + 'Symfony\\Polyfill\\Intl\\Idn\\' => + array ( + 0 => __DIR__ . '/..' . '/symfony/polyfill-intl-idn', + ), + 'Symfony\\Polyfill\\Ctype\\' => + array ( + 0 => __DIR__ . '/..' . '/symfony/polyfill-ctype', + ), + 'Symfony\\Contracts\\EventDispatcher\\' => + array ( + 0 => __DIR__ . '/..' . '/symfony/event-dispatcher-contracts', + ), 'Symfony\\Component\\Routing\\' => array ( 0 => __DIR__ . '/..' . '/symfony/routing', ), + 'Symfony\\Component\\Mime\\' => + array ( + 0 => __DIR__ . '/..' . '/symfony/mime', + ), 'Symfony\\Component\\HttpKernel\\' => array ( 0 => __DIR__ . '/..' . '/symfony/http-kernel', @@ -150,13 +178,7 @@ class ComposerStaticInit8a9318ad96e1e6602a968c996fe31931 ); public static $classMap = array ( - 'ArithmeticError' => __DIR__ . '/..' . '/symfony/polyfill-php70/Resources/stubs/ArithmeticError.php', - 'AssertionError' => __DIR__ . '/..' . '/symfony/polyfill-php70/Resources/stubs/AssertionError.php', - 'DivisionByZeroError' => __DIR__ . '/..' . '/symfony/polyfill-php70/Resources/stubs/DivisionByZeroError.php', - 'Error' => __DIR__ . '/..' . '/symfony/polyfill-php70/Resources/stubs/Error.php', - 'ParseError' => __DIR__ . '/..' . '/symfony/polyfill-php70/Resources/stubs/ParseError.php', - 'SessionUpdateTimestampHandlerInterface' => __DIR__ . '/..' . '/symfony/polyfill-php70/Resources/stubs/SessionUpdateTimestampHandlerInterface.php', - 'TypeError' => __DIR__ . '/..' . '/symfony/polyfill-php70/Resources/stubs/TypeError.php', + 'JsonException' => __DIR__ . '/..' . '/symfony/polyfill-php73/Resources/stubs/JsonException.php', ); public static function getInitializer(ClassLoader $loader) diff --git a/vendor/composer/installed.json b/vendor/composer/installed.json index 621516fb3bc94b72c568642bdce2f789f8593c17..0ec583028611acdb6d60844fe6da1b99ea5aaefd 100644 --- a/vendor/composer/installed.json +++ b/vendor/composer/installed.json @@ -1,40 +1,47 @@ [ { - "name": "guzzlehttp/promises", - "version": "v1.3.1", - "version_normalized": "1.3.1.0", + "name": "guzzlehttp/guzzle", + "version": "6.3.3", + "version_normalized": "6.3.3.0", "source": { "type": "git", - "url": "https://github.com/guzzle/promises.git", - "reference": "a59da6cf61d80060647ff4d3eb2c03a2bc694646" + "url": "https://github.com/guzzle/guzzle.git", + "reference": "407b0cb880ace85c9b63c5f9551db498cb2d50ba" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/promises/zipball/a59da6cf61d80060647ff4d3eb2c03a2bc694646", - "reference": "a59da6cf61d80060647ff4d3eb2c03a2bc694646", + "url": "https://api.github.com/repos/guzzle/guzzle/zipball/407b0cb880ace85c9b63c5f9551db498cb2d50ba", + "reference": "407b0cb880ace85c9b63c5f9551db498cb2d50ba", "shasum": "" }, "require": { - "php": ">=5.5.0" + "guzzlehttp/promises": "^1.0", + "guzzlehttp/psr7": "^1.4", + "php": ">=5.5" }, "require-dev": { - "phpunit/phpunit": "^4.0" + "ext-curl": "*", + "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.4 || ^7.0", + "psr/log": "^1.0" }, - "time": "2016-12-20T10:07:11+00:00", + "suggest": { + "psr/log": "Required for using the Log middleware" + }, + "time": "2018-04-22T15:46:56+00:00", "type": "library", "extra": { "branch-alias": { - "dev-master": "1.4-dev" + "dev-master": "6.3-dev" } }, "installation-source": "dist", "autoload": { - "psr-4": { - "GuzzleHttp\\Promise\\": "src/" - }, "files": [ "src/functions_include.php" - ] + ], + "psr-4": { + "GuzzleHttp\\": "src/" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -47,41 +54,54 @@ "homepage": "https://github.com/mtdowling" } ], - "description": "Guzzle promises library", + "description": "Guzzle is a PHP HTTP client library", + "homepage": "http://guzzlephp.org/", "keywords": [ - "promise" + "client", + "curl", + "framework", + "http", + "http client", + "rest", + "web service" ] }, { - "name": "psr/http-message", - "version": "1.0.1", - "version_normalized": "1.0.1.0", + "name": "guzzlehttp/promises", + "version": "v1.3.1", + "version_normalized": "1.3.1.0", "source": { "type": "git", - "url": "https://github.com/php-fig/http-message.git", - "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363" + "url": "https://github.com/guzzle/promises.git", + "reference": "a59da6cf61d80060647ff4d3eb2c03a2bc694646" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363", - "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363", + "url": "https://api.github.com/repos/guzzle/promises/zipball/a59da6cf61d80060647ff4d3eb2c03a2bc694646", + "reference": "a59da6cf61d80060647ff4d3eb2c03a2bc694646", "shasum": "" }, "require": { - "php": ">=5.3.0" + "php": ">=5.5.0" }, - "time": "2016-08-06T14:39:51+00:00", + "require-dev": { + "phpunit/phpunit": "^4.0" + }, + "time": "2016-12-20T10:07:11+00:00", "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "1.4-dev" } }, "installation-source": "dist", "autoload": { "psr-4": { - "Psr\\Http\\Message\\": "src/" - } + "GuzzleHttp\\Promise\\": "src/" + }, + "files": [ + "src/functions_include.php" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -89,51 +109,51 @@ ], "authors": [ { - "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" + "name": "Michael Dowling", + "email": "mtdowling@gmail.com", + "homepage": "https://github.com/mtdowling" } ], - "description": "Common interface for HTTP messages", - "homepage": "https://github.com/php-fig/http-message", + "description": "Guzzle promises library", "keywords": [ - "http", - "http-message", - "psr", - "psr-7", - "request", - "response" + "promise" ] }, { "name": "guzzlehttp/psr7", - "version": "1.4.2", - "version_normalized": "1.4.2.0", + "version": "1.6.1", + "version_normalized": "1.6.1.0", "source": { "type": "git", "url": "https://github.com/guzzle/psr7.git", - "reference": "f5b8a8512e2b58b0071a7280e39f14f72e05d87c" + "reference": "239400de7a173fe9901b9ac7c06497751f00727a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/psr7/zipball/f5b8a8512e2b58b0071a7280e39f14f72e05d87c", - "reference": "f5b8a8512e2b58b0071a7280e39f14f72e05d87c", + "url": "https://api.github.com/repos/guzzle/psr7/zipball/239400de7a173fe9901b9ac7c06497751f00727a", + "reference": "239400de7a173fe9901b9ac7c06497751f00727a", "shasum": "" }, "require": { "php": ">=5.4.0", - "psr/http-message": "~1.0" + "psr/http-message": "~1.0", + "ralouphie/getallheaders": "^2.0.5 || ^3.0.0" }, "provide": { "psr/http-message-implementation": "1.0" }, "require-dev": { - "phpunit/phpunit": "~4.0" + "ext-zlib": "*", + "phpunit/phpunit": "~4.8.36 || ^5.7.27 || ^6.5.8" + }, + "suggest": { + "zendframework/zend-httphandlerrunner": "Emit PSR-7 responses" }, - "time": "2017-03-20T17:10:46+00:00", + "time": "2019-07-01T23:21:34+00:00", "type": "library", "extra": { "branch-alias": { - "dev-master": "1.4-dev" + "dev-master": "1.6-dev" } }, "installation-source": "dist", @@ -164,6 +184,7 @@ "keywords": [ "http", "message", + "psr-7", "request", "response", "stream", @@ -190,47 +211,59 @@ } }, { - "name": "guzzlehttp/guzzle", - "version": "6.3.0", - "version_normalized": "6.3.0.0", + "name": "hab/solr", + "version": "dev-master", + "version_normalized": "9999999-dev", "source": { "type": "git", - "url": "https://github.com/guzzle/guzzle.git", - "reference": "f4db5a78a5ea468d4831de7f0bf9d9415e348699" + "url": "git@github.com:dmj/php-solr.git", + "reference": "a54f2c7495dacc5cd0964fba25e1fa2b89cc03fe" + }, + "require": { + "guzzlehttp/guzzle": "~6.0" + }, + "time": "2019-08-07T06:46:21+00:00", + "type": "library", + "installation-source": "source", + "autoload": { + "psr-0": { + "HAB": "src/" + } + } + }, + { + "name": "pimple/pimple", + "version": "v3.2.3", + "version_normalized": "3.2.3.0", + "source": { + "type": "git", + "url": "https://github.com/silexphp/Pimple.git", + "reference": "9e403941ef9d65d20cba7d54e29fe906db42cf32" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/guzzle/guzzle/zipball/f4db5a78a5ea468d4831de7f0bf9d9415e348699", - "reference": "f4db5a78a5ea468d4831de7f0bf9d9415e348699", + "url": "https://api.github.com/repos/silexphp/Pimple/zipball/9e403941ef9d65d20cba7d54e29fe906db42cf32", + "reference": "9e403941ef9d65d20cba7d54e29fe906db42cf32", "shasum": "" }, "require": { - "guzzlehttp/promises": "^1.0", - "guzzlehttp/psr7": "^1.4", - "php": ">=5.5" + "php": ">=5.3.0", + "psr/container": "^1.0" }, "require-dev": { - "ext-curl": "*", - "phpunit/phpunit": "^4.0 || ^5.0", - "psr/log": "^1.0" - }, - "suggest": { - "psr/log": "Required for using the Log middleware" + "symfony/phpunit-bridge": "^3.2" }, - "time": "2017-06-22T18:50:49+00:00", + "time": "2018-01-21T07:42:36+00:00", "type": "library", "extra": { "branch-alias": { - "dev-master": "6.2-dev" + "dev-master": "3.2.x-dev" } }, "installation-source": "dist", "autoload": { - "files": [ - "src/functions_include.php" - ], - "psr-4": { - "GuzzleHttp\\": "src/" + "psr-0": { + "Pimple": "src/" } }, "notification-url": "https://packagist.org/downloads/", @@ -239,44 +272,17 @@ ], "authors": [ { - "name": "Michael Dowling", - "email": "mtdowling@gmail.com", - "homepage": "https://github.com/mtdowling" + "name": "Fabien Potencier", + "email": "fabien@symfony.com" } ], - "description": "Guzzle is a PHP HTTP client library", - "homepage": "http://guzzlephp.org/", + "description": "Pimple, a simple Dependency Injection Container", + "homepage": "http://pimple.sensiolabs.org", "keywords": [ - "client", - "curl", - "framework", - "http", - "http client", - "rest", - "web service" + "container", + "dependency injection" ] }, - { - "name": "hab/solr", - "version": "dev-master", - "version_normalized": "9999999-dev", - "source": { - "type": "git", - "url": "git@github.com:dmj/php-solr.git", - "reference": "f16f0026296c6a4ea61601d51cf1b070ce1e0742" - }, - "require": { - "guzzlehttp/guzzle": "~6.0" - }, - "time": "2017-07-20T13:50:14+00:00", - "type": "library", - "installation-source": "source", - "autoload": { - "psr-0": { - "HAB": "src/" - } - } - }, { "name": "psr/container", "version": "1.0.0", @@ -329,61 +335,35 @@ ] }, { - "name": "symfony/routing", - "version": "v3.4.4", - "version_normalized": "3.4.4.0", + "name": "psr/http-message", + "version": "1.0.1", + "version_normalized": "1.0.1.0", "source": { "type": "git", - "url": "https://github.com/symfony/routing.git", - "reference": "235d01730d553a97732990588407eaf6779bb4b2" + "url": "https://github.com/php-fig/http-message.git", + "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/routing/zipball/235d01730d553a97732990588407eaf6779bb4b2", - "reference": "235d01730d553a97732990588407eaf6779bb4b2", + "url": "https://api.github.com/repos/php-fig/http-message/zipball/f6561bf28d520154e4b0ec72be95418abe6d9363", + "reference": "f6561bf28d520154e4b0ec72be95418abe6d9363", "shasum": "" }, "require": { - "php": "^5.5.9|>=7.0.8" - }, - "conflict": { - "symfony/config": "<2.8", - "symfony/dependency-injection": "<3.3", - "symfony/yaml": "<3.4" - }, - "require-dev": { - "doctrine/annotations": "~1.0", - "doctrine/common": "~2.2", - "psr/log": "~1.0", - "symfony/config": "~2.8|~3.0|~4.0", - "symfony/dependency-injection": "~3.3|~4.0", - "symfony/expression-language": "~2.8|~3.0|~4.0", - "symfony/http-foundation": "~2.8|~3.0|~4.0", - "symfony/yaml": "~3.4|~4.0" - }, - "suggest": { - "doctrine/annotations": "For using the annotation loader", - "symfony/config": "For using the all-in-one router or any loader", - "symfony/dependency-injection": "For loading routes from a service", - "symfony/expression-language": "For using expression matching", - "symfony/http-foundation": "For using a Symfony Request object", - "symfony/yaml": "For using the YAML loader" + "php": ">=5.3.0" }, - "time": "2018-01-16T18:03:57+00:00", + "time": "2016-08-06T14:39:51+00:00", "type": "library", "extra": { "branch-alias": { - "dev-master": "3.4-dev" + "dev-master": "1.0.x-dev" } }, "installation-source": "dist", "autoload": { "psr-4": { - "Symfony\\Component\\Routing\\": "" - }, - "exclude-from-classmap": [ - "/Tests/" - ] + "Psr\\Http\\Message\\": "src/" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -391,54 +371,51 @@ ], "authors": [ { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" } ], - "description": "Symfony Routing Component", - "homepage": "https://symfony.com", + "description": "Common interface for HTTP messages", + "homepage": "https://github.com/php-fig/http-message", "keywords": [ - "router", - "routing", - "uri", - "url" + "http", + "http-message", + "psr", + "psr-7", + "request", + "response" ] }, { - "name": "paragonie/random_compat", - "version": "v2.0.11", - "version_normalized": "2.0.11.0", + "name": "psr/log", + "version": "1.1.0", + "version_normalized": "1.1.0.0", "source": { "type": "git", - "url": "https://github.com/paragonie/random_compat.git", - "reference": "5da4d3c796c275c55f057af5a643ae297d96b4d8" + "url": "https://github.com/php-fig/log.git", + "reference": "6c001f1daafa3a3ac1d8ff69ee4db8e799a654dd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/paragonie/random_compat/zipball/5da4d3c796c275c55f057af5a643ae297d96b4d8", - "reference": "5da4d3c796c275c55f057af5a643ae297d96b4d8", + "url": "https://api.github.com/repos/php-fig/log/zipball/6c001f1daafa3a3ac1d8ff69ee4db8e799a654dd", + "reference": "6c001f1daafa3a3ac1d8ff69ee4db8e799a654dd", "shasum": "" }, "require": { - "php": ">=5.2.0" - }, - "require-dev": { - "phpunit/phpunit": "4.*|5.*" - }, - "suggest": { - "ext-libsodium": "Provides a modern crypto API that can be used to generate random bytes." + "php": ">=5.3.0" }, - "time": "2017-09-27T21:40:39+00:00", + "time": "2018-11-20T15:27:04+00:00", "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0.x-dev" + } + }, "installation-source": "dist", "autoload": { - "files": [ - "lib/random.php" - ] + "psr-4": { + "Psr\\Log\\": "Psr/Log/" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -446,54 +423,46 @@ ], "authors": [ { - "name": "Paragon Initiative Enterprises", - "email": "security@paragonie.com", - "homepage": "https://paragonie.com" + "name": "PHP-FIG", + "homepage": "http://www.php-fig.org/" } ], - "description": "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7", + "description": "Common interface for logging libraries", + "homepage": "https://github.com/php-fig/log", "keywords": [ - "csprng", - "pseudorandom", - "random" + "log", + "psr", + "psr-3" ] }, { - "name": "symfony/polyfill-php70", - "version": "v1.7.0", - "version_normalized": "1.7.0.0", + "name": "ralouphie/getallheaders", + "version": "3.0.3", + "version_normalized": "3.0.3.0", "source": { "type": "git", - "url": "https://github.com/symfony/polyfill-php70.git", - "reference": "3532bfcd8f933a7816f3a0a59682fc404776600f" + "url": "https://github.com/ralouphie/getallheaders.git", + "reference": "120b605dfeb996808c31b6477290a714d356e822" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php70/zipball/3532bfcd8f933a7816f3a0a59682fc404776600f", - "reference": "3532bfcd8f933a7816f3a0a59682fc404776600f", + "url": "https://api.github.com/repos/ralouphie/getallheaders/zipball/120b605dfeb996808c31b6477290a714d356e822", + "reference": "120b605dfeb996808c31b6477290a714d356e822", "shasum": "" }, "require": { - "paragonie/random_compat": "~1.0|~2.0", - "php": ">=5.3.3" + "php": ">=5.6" }, - "time": "2018-01-30T19:27:44+00:00", - "type": "library", - "extra": { - "branch-alias": { - "dev-master": "1.7-dev" - } + "require-dev": { + "php-coveralls/php-coveralls": "^2.1", + "phpunit/phpunit": "^5 || ^6.5" }, + "time": "2019-03-08T08:55:37+00:00", + "type": "library", "installation-source": "dist", "autoload": { - "psr-4": { - "Symfony\\Polyfill\\Php70\\": "" - }, "files": [ - "bootstrap.php" - ], - "classmap": [ - "Resources/stubs" + "src/getallheaders.php" ] }, "notification-url": "https://packagist.org/downloads/", @@ -502,59 +471,79 @@ ], "authors": [ { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" - }, - { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" + "name": "Ralph Khattar", + "email": "ralph.khattar@gmail.com" } ], - "description": "Symfony polyfill backporting some PHP 7.0+ features to lower PHP versions", - "homepage": "https://symfony.com", - "keywords": [ - "compatibility", - "polyfill", - "portable", - "shim" - ] + "description": "A polyfill for getallheaders." }, { - "name": "symfony/polyfill-mbstring", - "version": "v1.7.0", - "version_normalized": "1.7.0.0", + "name": "silex/silex", + "version": "v2.3.0", + "version_normalized": "2.3.0.0", "source": { "type": "git", - "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "78be803ce01e55d3491c1397cf1c64beb9c1b63b" + "url": "https://github.com/silexphp/Silex.git", + "reference": "6bc31c1b8c4ef614a7115320fd2d3b958032f131" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/78be803ce01e55d3491c1397cf1c64beb9c1b63b", - "reference": "78be803ce01e55d3491c1397cf1c64beb9c1b63b", + "url": "https://api.github.com/repos/silexphp/Silex/zipball/6bc31c1b8c4ef614a7115320fd2d3b958032f131", + "reference": "6bc31c1b8c4ef614a7115320fd2d3b958032f131", "shasum": "" }, "require": { - "php": ">=5.3.3" + "php": ">=7.1.3", + "pimple/pimple": "^3.0", + "symfony/event-dispatcher": "^4.0", + "symfony/http-foundation": "^4.0", + "symfony/http-kernel": "^4.0", + "symfony/routing": "^4.0" }, - "suggest": { - "ext-mbstring": "For best performance" + "replace": { + "silex/api": "self.version", + "silex/providers": "self.version" }, - "time": "2018-01-30T19:27:44+00:00", + "require-dev": { + "doctrine/dbal": "^2.2", + "monolog/monolog": "^1.4.1", + "swiftmailer/swiftmailer": "^5", + "symfony/asset": "^4.0", + "symfony/browser-kit": "^4.0", + "symfony/config": "^4.0", + "symfony/css-selector": "^4.0", + "symfony/debug": "^4.0", + "symfony/doctrine-bridge": "^4.0", + "symfony/dom-crawler": "^4.0", + "symfony/expression-language": "^4.0", + "symfony/finder": "^4.0", + "symfony/form": "^4.0", + "symfony/intl": "^4.0", + "symfony/monolog-bridge": "^4.0", + "symfony/options-resolver": "^4.0", + "symfony/phpunit-bridge": "^3.2", + "symfony/process": "^4.0", + "symfony/security": "^4.0", + "symfony/serializer": "^4.0", + "symfony/translation": "^4.0", + "symfony/twig-bridge": "^4.0", + "symfony/validator": "^4.0", + "symfony/var-dumper": "^4.0", + "symfony/web-link": "^4.0", + "twig/twig": "^2.0" + }, + "time": "2018-04-20T05:17:01+00:00", "type": "library", "extra": { "branch-alias": { - "dev-master": "1.7-dev" + "dev-master": "2.3.x-dev" } }, "installation-source": "dist", "autoload": { "psr-4": { - "Symfony\\Polyfill\\Mbstring\\": "" - }, - "files": [ - "bootstrap.php" - ] + "Silex\\": "src/Silex" + } }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -562,58 +551,57 @@ ], "authors": [ { - "name": "Nicolas Grekas", - "email": "p@tchwork.com" + "name": "Fabien Potencier", + "email": "fabien@symfony.com" }, { - "name": "Symfony Community", - "homepage": "https://symfony.com/contributors" + "name": "Igor Wiedler", + "email": "igor@wiedler.ch" } ], - "description": "Symfony polyfill for the Mbstring extension", - "homepage": "https://symfony.com", + "description": "The PHP micro-framework based on the Symfony Components", + "homepage": "http://silex.sensiolabs.org", "keywords": [ - "compatibility", - "mbstring", - "polyfill", - "portable", - "shim" - ] + "microframework" + ], + "abandoned": "symfony/flex" }, { - "name": "symfony/http-foundation", - "version": "v3.4.4", - "version_normalized": "3.4.4.0", + "name": "symfony/debug", + "version": "v4.3.5", + "version_normalized": "4.3.5.0", "source": { "type": "git", - "url": "https://github.com/symfony/http-foundation.git", - "reference": "8c39071ac9cc7e6d8dab1d556c990dc0d2cc3d30" + "url": "https://github.com/symfony/debug.git", + "reference": "cc5c1efd0edfcfd10b354750594a46b3dd2afbbe" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-foundation/zipball/8c39071ac9cc7e6d8dab1d556c990dc0d2cc3d30", - "reference": "8c39071ac9cc7e6d8dab1d556c990dc0d2cc3d30", + "url": "https://api.github.com/repos/symfony/debug/zipball/cc5c1efd0edfcfd10b354750594a46b3dd2afbbe", + "reference": "cc5c1efd0edfcfd10b354750594a46b3dd2afbbe", "shasum": "" }, "require": { - "php": "^5.5.9|>=7.0.8", - "symfony/polyfill-mbstring": "~1.1", - "symfony/polyfill-php70": "~1.6" + "php": "^7.1.3", + "psr/log": "~1.0" + }, + "conflict": { + "symfony/http-kernel": "<3.4" }, "require-dev": { - "symfony/expression-language": "~2.8|~3.0|~4.0" + "symfony/http-kernel": "~3.4|~4.0" }, - "time": "2018-01-29T09:03:43+00:00", + "time": "2019-09-19T15:51:53+00:00", "type": "library", "extra": { "branch-alias": { - "dev-master": "3.4-dev" + "dev-master": "4.3-dev" } }, "installation-source": "dist", "autoload": { "psr-4": { - "Symfony\\Component\\HttpFoundation\\": "" + "Symfony\\Component\\Debug\\": "" }, "exclude-from-classmap": [ "/Tests/" @@ -633,46 +621,53 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony HttpFoundation Component", + "description": "Symfony Debug Component", "homepage": "https://symfony.com" }, { "name": "symfony/event-dispatcher", - "version": "v3.4.4", - "version_normalized": "3.4.4.0", + "version": "v4.3.5", + "version_normalized": "4.3.5.0", "source": { "type": "git", "url": "https://github.com/symfony/event-dispatcher.git", - "reference": "26b87b6bca8f8f797331a30b76fdae5342dc26ca" + "reference": "6229f58993e5a157f6096fc7145c0717d0be8807" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/26b87b6bca8f8f797331a30b76fdae5342dc26ca", - "reference": "26b87b6bca8f8f797331a30b76fdae5342dc26ca", + "url": "https://api.github.com/repos/symfony/event-dispatcher/zipball/6229f58993e5a157f6096fc7145c0717d0be8807", + "reference": "6229f58993e5a157f6096fc7145c0717d0be8807", "shasum": "" }, "require": { - "php": "^5.5.9|>=7.0.8" + "php": "^7.1.3", + "symfony/event-dispatcher-contracts": "^1.1" }, "conflict": { - "symfony/dependency-injection": "<3.3" + "symfony/dependency-injection": "<3.4" + }, + "provide": { + "psr/event-dispatcher-implementation": "1.0", + "symfony/event-dispatcher-implementation": "1.1" }, "require-dev": { "psr/log": "~1.0", - "symfony/config": "~2.8|~3.0|~4.0", - "symfony/dependency-injection": "~3.3|~4.0", - "symfony/expression-language": "~2.8|~3.0|~4.0", - "symfony/stopwatch": "~2.8|~3.0|~4.0" + "symfony/config": "~3.4|~4.0", + "symfony/dependency-injection": "~3.4|~4.0", + "symfony/expression-language": "~3.4|~4.0", + "symfony/http-foundation": "^3.4|^4.0", + "symfony/service-contracts": "^1.1", + "symfony/stopwatch": "~3.4|~4.0" }, "suggest": { "symfony/dependency-injection": "", "symfony/http-kernel": "" }, - "time": "2018-01-03T07:37:34+00:00", + "time": "2019-10-01T16:40:32+00:00", "type": "library", "extra": { "branch-alias": { - "dev-master": "3.4-dev" + "dev-master": "4.3-dev" } }, "installation-source": "dist", @@ -702,34 +697,38 @@ "homepage": "https://symfony.com" }, { - "name": "psr/log", - "version": "1.0.2", - "version_normalized": "1.0.2.0", + "name": "symfony/event-dispatcher-contracts", + "version": "v1.1.7", + "version_normalized": "1.1.7.0", "source": { "type": "git", - "url": "https://github.com/php-fig/log.git", - "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d" + "url": "https://github.com/symfony/event-dispatcher-contracts.git", + "reference": "c43ab685673fb6c8d84220c77897b1d6cdbe1d18" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/php-fig/log/zipball/4ebe3a8bf773a19edfe0a84b6585ba3d401b724d", - "reference": "4ebe3a8bf773a19edfe0a84b6585ba3d401b724d", + "url": "https://api.github.com/repos/symfony/event-dispatcher-contracts/zipball/c43ab685673fb6c8d84220c77897b1d6cdbe1d18", + "reference": "c43ab685673fb6c8d84220c77897b1d6cdbe1d18", "shasum": "" }, "require": { - "php": ">=5.3.0" + "php": "^7.1.3" + }, + "suggest": { + "psr/event-dispatcher": "", + "symfony/event-dispatcher-implementation": "" }, - "time": "2016-10-10T12:19:37+00:00", + "time": "2019-09-17T09:54:03+00:00", "type": "library", "extra": { "branch-alias": { - "dev-master": "1.0.x-dev" + "dev-master": "1.1-dev" } }, "installation-source": "dist", "autoload": { "psr-4": { - "Psr\\Log\\": "Psr/Log/" + "Symfony\\Contracts\\EventDispatcher\\": "" } }, "notification-url": "https://packagist.org/downloads/", @@ -738,54 +737,60 @@ ], "authors": [ { - "name": "PHP-FIG", - "homepage": "http://www.php-fig.org/" + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" } ], - "description": "Common interface for logging libraries", - "homepage": "https://github.com/php-fig/log", + "description": "Generic abstractions related to dispatching event", + "homepage": "https://symfony.com", "keywords": [ - "log", - "psr", - "psr-3" + "abstractions", + "contracts", + "decoupling", + "interfaces", + "interoperability", + "standards" ] }, { - "name": "symfony/debug", - "version": "v3.4.4", - "version_normalized": "3.4.4.0", + "name": "symfony/http-foundation", + "version": "v4.3.5", + "version_normalized": "4.3.5.0", "source": { "type": "git", - "url": "https://github.com/symfony/debug.git", - "reference": "53f6af2805daf52a43b393b93d2f24925d35c937" + "url": "https://github.com/symfony/http-foundation.git", + "reference": "76590ced16d4674780863471bae10452b79210a5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/debug/zipball/53f6af2805daf52a43b393b93d2f24925d35c937", - "reference": "53f6af2805daf52a43b393b93d2f24925d35c937", + "url": "https://api.github.com/repos/symfony/http-foundation/zipball/76590ced16d4674780863471bae10452b79210a5", + "reference": "76590ced16d4674780863471bae10452b79210a5", "shasum": "" }, "require": { - "php": "^5.5.9|>=7.0.8", - "psr/log": "~1.0" - }, - "conflict": { - "symfony/http-kernel": ">=2.3,<2.3.24|~2.4.0|>=2.5,<2.5.9|>=2.6,<2.6.2" + "php": "^7.1.3", + "symfony/mime": "^4.3", + "symfony/polyfill-mbstring": "~1.1" }, "require-dev": { - "symfony/http-kernel": "~2.8|~3.0|~4.0" + "predis/predis": "~1.0", + "symfony/expression-language": "~3.4|~4.0" }, - "time": "2018-01-18T22:16:57+00:00", + "time": "2019-10-04T19:48:13+00:00", "type": "library", "extra": { "branch-alias": { - "dev-master": "3.4-dev" + "dev-master": "4.3-dev" } }, "installation-source": "dist", "autoload": { "psr-4": { - "Symfony\\Component\\Debug\\": "" + "Symfony\\Component\\HttpFoundation\\": "" }, "exclude-from-classmap": [ "/Tests/" @@ -805,35 +810,39 @@ "homepage": "https://symfony.com/contributors" } ], - "description": "Symfony Debug Component", + "description": "Symfony HttpFoundation Component", "homepage": "https://symfony.com" }, { "name": "symfony/http-kernel", - "version": "v3.4.4", - "version_normalized": "3.4.4.0", + "version": "v4.3.5", + "version_normalized": "4.3.5.0", "source": { "type": "git", "url": "https://github.com/symfony/http-kernel.git", - "reference": "911d2e5dd4beb63caad9a72e43857de984301907" + "reference": "5f08141850932e8019c01d8988bf3ed6367d2991" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-kernel/zipball/911d2e5dd4beb63caad9a72e43857de984301907", - "reference": "911d2e5dd4beb63caad9a72e43857de984301907", + "url": "https://api.github.com/repos/symfony/http-kernel/zipball/5f08141850932e8019c01d8988bf3ed6367d2991", + "reference": "5f08141850932e8019c01d8988bf3ed6367d2991", "shasum": "" }, "require": { - "php": "^5.5.9|>=7.0.8", + "php": "^7.1.3", "psr/log": "~1.0", - "symfony/debug": "~2.8|~3.0|~4.0", - "symfony/event-dispatcher": "~2.8|~3.0|~4.0", - "symfony/http-foundation": "^3.4.4|^4.0.4" + "symfony/debug": "~3.4|~4.0", + "symfony/event-dispatcher": "^4.3", + "symfony/http-foundation": "^4.1.1", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-php73": "^1.9" }, "conflict": { - "symfony/config": "<2.8", - "symfony/dependency-injection": "<3.4", - "symfony/var-dumper": "<3.3", + "symfony/browser-kit": "<4.3", + "symfony/config": "<3.4", + "symfony/dependency-injection": "<4.3", + "symfony/translation": "<4.2", + "symfony/var-dumper": "<4.1.1", "twig/twig": "<1.34|<2.4,>=2" }, "provide": { @@ -841,35 +850,35 @@ }, "require-dev": { "psr/cache": "~1.0", - "symfony/browser-kit": "~2.8|~3.0|~4.0", - "symfony/class-loader": "~2.8|~3.0", - "symfony/config": "~2.8|~3.0|~4.0", - "symfony/console": "~2.8|~3.0|~4.0", - "symfony/css-selector": "~2.8|~3.0|~4.0", - "symfony/dependency-injection": "~3.4|~4.0", - "symfony/dom-crawler": "~2.8|~3.0|~4.0", - "symfony/expression-language": "~2.8|~3.0|~4.0", - "symfony/finder": "~2.8|~3.0|~4.0", - "symfony/process": "~2.8|~3.0|~4.0", + "symfony/browser-kit": "^4.3", + "symfony/config": "~3.4|~4.0", + "symfony/console": "~3.4|~4.0", + "symfony/css-selector": "~3.4|~4.0", + "symfony/dependency-injection": "^4.3", + "symfony/dom-crawler": "~3.4|~4.0", + "symfony/expression-language": "~3.4|~4.0", + "symfony/finder": "~3.4|~4.0", + "symfony/process": "~3.4|~4.0", "symfony/routing": "~3.4|~4.0", - "symfony/stopwatch": "~2.8|~3.0|~4.0", - "symfony/templating": "~2.8|~3.0|~4.0", - "symfony/translation": "~2.8|~3.0|~4.0", - "symfony/var-dumper": "~3.3|~4.0" + "symfony/stopwatch": "~3.4|~4.0", + "symfony/templating": "~3.4|~4.0", + "symfony/translation": "~4.2", + "symfony/translation-contracts": "^1.1", + "symfony/var-dumper": "^4.1.1", + "twig/twig": "^1.34|^2.4" }, "suggest": { "symfony/browser-kit": "", "symfony/config": "", "symfony/console": "", "symfony/dependency-injection": "", - "symfony/finder": "", "symfony/var-dumper": "" }, - "time": "2018-01-29T12:29:46+00:00", + "time": "2019-10-07T15:06:41+00:00", "type": "library", "extra": { "branch-alias": { - "dev-master": "3.4-dev" + "dev-master": "4.3-dev" } }, "installation-source": "dist", @@ -899,39 +908,44 @@ "homepage": "https://symfony.com" }, { - "name": "pimple/pimple", - "version": "v3.2.3", - "version_normalized": "3.2.3.0", + "name": "symfony/mime", + "version": "v4.3.5", + "version_normalized": "4.3.5.0", "source": { "type": "git", - "url": "https://github.com/silexphp/Pimple.git", - "reference": "9e403941ef9d65d20cba7d54e29fe906db42cf32" + "url": "https://github.com/symfony/mime.git", + "reference": "32f71570547b91879fdbd9cf50317d556ae86916" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/silexphp/Pimple/zipball/9e403941ef9d65d20cba7d54e29fe906db42cf32", - "reference": "9e403941ef9d65d20cba7d54e29fe906db42cf32", + "url": "https://api.github.com/repos/symfony/mime/zipball/32f71570547b91879fdbd9cf50317d556ae86916", + "reference": "32f71570547b91879fdbd9cf50317d556ae86916", "shasum": "" }, "require": { - "php": ">=5.3.0", - "psr/container": "^1.0" + "php": "^7.1.3", + "symfony/polyfill-intl-idn": "^1.10", + "symfony/polyfill-mbstring": "^1.0" }, "require-dev": { - "symfony/phpunit-bridge": "^3.2" + "egulias/email-validator": "^2.1.10", + "symfony/dependency-injection": "~3.4|^4.1" }, - "time": "2018-01-21T07:42:36+00:00", + "time": "2019-09-19T17:00:15+00:00", "type": "library", "extra": { "branch-alias": { - "dev-master": "3.2.x-dev" + "dev-master": "4.3-dev" } }, "installation-source": "dist", "autoload": { - "psr-0": { - "Pimple": "src/" - } + "psr-4": { + "Symfony\\Component\\Mime\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] }, "notification-url": "https://packagist.org/downloads/", "license": [ @@ -941,208 +955,435 @@ { "name": "Fabien Potencier", "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" } ], - "description": "Pimple, a simple Dependency Injection Container", - "homepage": "http://pimple.sensiolabs.org", + "description": "A library to manipulate MIME messages", + "homepage": "https://symfony.com", "keywords": [ - "container", - "dependency injection" + "mime", + "mime-type" ] }, { - "name": "silex/silex", - "version": "v2.2.3", - "version_normalized": "2.2.3.0", + "name": "symfony/polyfill-ctype", + "version": "v1.12.0", + "version_normalized": "1.12.0.0", "source": { "type": "git", - "url": "https://github.com/silexphp/Silex.git", - "reference": "90c80c3e5ef86c54b8769feca0320154c6e63f7c" + "url": "https://github.com/symfony/polyfill-ctype.git", + "reference": "550ebaac289296ce228a706d0867afc34687e3f4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/silexphp/Silex/zipball/90c80c3e5ef86c54b8769feca0320154c6e63f7c", - "reference": "90c80c3e5ef86c54b8769feca0320154c6e63f7c", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/550ebaac289296ce228a706d0867afc34687e3f4", + "reference": "550ebaac289296ce228a706d0867afc34687e3f4", "shasum": "" }, "require": { - "php": ">=5.5.9", - "pimple/pimple": "~3.0", - "symfony/event-dispatcher": "~2.8|^3.0", - "symfony/http-foundation": "~2.8|^3.0", - "symfony/http-kernel": "~2.8|^3.0", - "symfony/routing": "~2.8|^3.0" - }, - "conflict": { - "phpunit/phpunit": "<4.8.35 || >= 5.0, <5.4.3" + "php": ">=5.3.3" }, - "replace": { - "silex/api": "self.version", - "silex/providers": "self.version" + "suggest": { + "ext-ctype": "For best performance" }, - "require-dev": { - "doctrine/dbal": "~2.2", - "monolog/monolog": "^1.4.1", - "swiftmailer/swiftmailer": "~5", - "symfony/asset": "~2.8|^3.0", - "symfony/browser-kit": "~2.8|^3.0", - "symfony/config": "~2.8|^3.0", - "symfony/css-selector": "~2.8|^3.0", - "symfony/debug": "~2.8|^3.0", - "symfony/doctrine-bridge": "~2.8|^3.0", - "symfony/dom-crawler": "~2.8|^3.0", - "symfony/expression-language": "~2.8|^3.0", - "symfony/finder": "~2.8|^3.0", - "symfony/form": "~2.8|^3.0", - "symfony/intl": "~2.8|^3.0", - "symfony/monolog-bridge": "~2.8|^3.0", - "symfony/options-resolver": "~2.8|^3.0", - "symfony/phpunit-bridge": "^3.2", - "symfony/process": "~2.8|^3.0", - "symfony/security": "~2.8|^3.0", - "symfony/serializer": "~2.8|^3.0", - "symfony/translation": "~2.8|^3.0", - "symfony/twig-bridge": "~2.8|^3.0", - "symfony/validator": "~2.8|^3.0", - "symfony/var-dumper": "~2.8|^3.0", - "symfony/web-link": "^3.3", - "twig/twig": "~1.28|~2.0" - }, - "time": "2018-02-25T11:21:42+00:00", + "time": "2019-08-06T08:03:45+00:00", "type": "library", "extra": { "branch-alias": { - "dev-master": "2.2.x-dev" + "dev-master": "1.12-dev" } }, "installation-source": "dist", "autoload": { "psr-4": { - "Silex\\": "src/Silex" + "Symfony\\Polyfill\\Ctype\\": "" + }, + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Gert de Pagter", + "email": "BackEndTea@gmail.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for ctype functions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "ctype", + "polyfill", + "portable" + ] + }, + { + "name": "symfony/polyfill-intl-idn", + "version": "v1.12.0", + "version_normalized": "1.12.0.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-intl-idn.git", + "reference": "6af626ae6fa37d396dc90a399c0ff08e5cfc45b2" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-intl-idn/zipball/6af626ae6fa37d396dc90a399c0ff08e5cfc45b2", + "reference": "6af626ae6fa37d396dc90a399c0ff08e5cfc45b2", + "shasum": "" + }, + "require": { + "php": ">=5.3.3", + "symfony/polyfill-mbstring": "^1.3", + "symfony/polyfill-php72": "^1.9" + }, + "suggest": { + "ext-intl": "For best performance" + }, + "time": "2019-08-06T08:03:45+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.12-dev" } }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Intl\\Idn\\": "" + }, + "files": [ + "bootstrap.php" + ] + }, "notification-url": "https://packagist.org/downloads/", "license": [ "MIT" ], "authors": [ { - "name": "Fabien Potencier", - "email": "fabien@symfony.com" + "name": "Laurent Bassin", + "email": "laurent@bassin.info" }, { - "name": "Igor Wiedler", - "email": "igor@wiedler.ch" + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" } ], - "description": "The PHP micro-framework based on the Symfony Components", - "homepage": "http://silex.sensiolabs.org", + "description": "Symfony polyfill for intl's idn_to_ascii and idn_to_utf8 functions", + "homepage": "https://symfony.com", "keywords": [ - "microframework" + "compatibility", + "idn", + "intl", + "polyfill", + "portable", + "shim" ] }, { - "name": "twig/twig", - "version": "v1.35.0", - "version_normalized": "1.35.0.0", + "name": "symfony/polyfill-mbstring", + "version": "v1.12.0", + "version_normalized": "1.12.0.0", "source": { "type": "git", - "url": "https://github.com/twigphp/Twig.git", - "reference": "daa657073e55b0a78cce8fdd22682fddecc6385f" + "url": "https://github.com/symfony/polyfill-mbstring.git", + "reference": "b42a2f66e8f1b15ccf25652c3424265923eb4f17" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/twigphp/Twig/zipball/daa657073e55b0a78cce8fdd22682fddecc6385f", - "reference": "daa657073e55b0a78cce8fdd22682fddecc6385f", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/b42a2f66e8f1b15ccf25652c3424265923eb4f17", + "reference": "b42a2f66e8f1b15ccf25652c3424265923eb4f17", "shasum": "" }, "require": { "php": ">=5.3.3" }, - "require-dev": { - "psr/container": "^1.0", - "symfony/debug": "~2.7", - "symfony/phpunit-bridge": "~3.3@dev" + "suggest": { + "ext-mbstring": "For best performance" }, - "time": "2017-09-27T18:06:46+00:00", + "time": "2019-08-06T08:03:45+00:00", "type": "library", "extra": { "branch-alias": { - "dev-master": "1.35-dev" + "dev-master": "1.12-dev" } }, "installation-source": "dist", "autoload": { - "psr-0": { - "Twig_": "lib/" + "psr-4": { + "Symfony\\Polyfill\\Mbstring\\": "" }, + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill for the Mbstring extension", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "mbstring", + "polyfill", + "portable", + "shim" + ] + }, + { + "name": "symfony/polyfill-php72", + "version": "v1.12.0", + "version_normalized": "1.12.0.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php72.git", + "reference": "04ce3335667451138df4307d6a9b61565560199e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/04ce3335667451138df4307d6a9b61565560199e", + "reference": "04ce3335667451138df4307d6a9b61565560199e", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "time": "2019-08-06T08:03:45+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.12-dev" + } + }, + "installation-source": "dist", + "autoload": { "psr-4": { - "Twig\\": "src/" + "Symfony\\Polyfill\\Php72\\": "" + }, + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 7.2+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ] + }, + { + "name": "symfony/polyfill-php73", + "version": "v1.12.0", + "version_normalized": "1.12.0.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php73.git", + "reference": "2ceb49eaccb9352bff54d22570276bb75ba4a188" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/2ceb49eaccb9352bff54d22570276bb75ba4a188", + "reference": "2ceb49eaccb9352bff54d22570276bb75ba4a188", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "time": "2019-08-06T08:03:45+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.12-dev" } }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Php73\\": "" + }, + "files": [ + "bootstrap.php" + ], + "classmap": [ + "Resources/stubs" + ] + }, "notification-url": "https://packagist.org/downloads/", "license": [ - "BSD-3-Clause" + "MIT" ], "authors": [ { - "name": "Fabien Potencier", - "email": "fabien@symfony.com", - "homepage": "http://fabien.potencier.org", - "role": "Lead Developer" + "name": "Nicolas Grekas", + "email": "p@tchwork.com" }, { - "name": "Armin Ronacher", - "email": "armin.ronacher@active-4.com", - "role": "Project Founder" + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 7.3+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ] + }, + { + "name": "symfony/routing", + "version": "v4.3.5", + "version_normalized": "4.3.5.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/routing.git", + "reference": "3b174ef04fe66696524efad1e5f7a6c663d822ea" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/routing/zipball/3b174ef04fe66696524efad1e5f7a6c663d822ea", + "reference": "3b174ef04fe66696524efad1e5f7a6c663d822ea", + "shasum": "" + }, + "require": { + "php": "^7.1.3" + }, + "conflict": { + "symfony/config": "<4.2", + "symfony/dependency-injection": "<3.4", + "symfony/yaml": "<3.4" + }, + "require-dev": { + "doctrine/annotations": "~1.2", + "psr/log": "~1.0", + "symfony/config": "~4.2", + "symfony/dependency-injection": "~3.4|~4.0", + "symfony/expression-language": "~3.4|~4.0", + "symfony/http-foundation": "~3.4|~4.0", + "symfony/yaml": "~3.4|~4.0" + }, + "suggest": { + "doctrine/annotations": "For using the annotation loader", + "symfony/config": "For using the all-in-one router or any loader", + "symfony/expression-language": "For using expression matching", + "symfony/http-foundation": "For using a Symfony Request object", + "symfony/yaml": "For using the YAML loader" + }, + "time": "2019-10-04T20:57:10+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "4.3-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-4": { + "Symfony\\Component\\Routing\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" }, { - "name": "Twig Team", - "homepage": "http://twig.sensiolabs.org/contributors", - "role": "Contributors" + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" } ], - "description": "Twig, the flexible, fast, and secure template language for PHP", - "homepage": "http://twig.sensiolabs.org", + "description": "Symfony Routing Component", + "homepage": "https://symfony.com", "keywords": [ - "templating" + "router", + "routing", + "uri", + "url" ] }, { "name": "symfony/twig-bridge", - "version": "v3.4.4", - "version_normalized": "3.4.4.0", + "version": "v3.4.32", + "version_normalized": "3.4.32.0", "source": { "type": "git", "url": "https://github.com/symfony/twig-bridge.git", - "reference": "a69e3f21f2f652ae3da0937914e3f3830cc6eae9" + "reference": "9f55b34b539a3a0ea51c2ed96609173c5b326259" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/twig-bridge/zipball/a69e3f21f2f652ae3da0937914e3f3830cc6eae9", - "reference": "a69e3f21f2f652ae3da0937914e3f3830cc6eae9", + "url": "https://api.github.com/repos/symfony/twig-bridge/zipball/9f55b34b539a3a0ea51c2ed96609173c5b326259", + "reference": "9f55b34b539a3a0ea51c2ed96609173c5b326259", "shasum": "" }, "require": { "php": "^5.5.9|>=7.0.8", - "twig/twig": "^1.35|^2.4.4" + "twig/twig": "^1.41|^2.10" }, "conflict": { "symfony/console": "<3.4", - "symfony/form": "<3.4" + "symfony/form": "<3.4.31|>=4.0,<4.3.4" }, "require-dev": { + "fig/link-util": "^1.0", "symfony/asset": "~2.8|~3.0|~4.0", "symfony/console": "~3.4|~4.0", "symfony/dependency-injection": "~2.8|~3.0|~4.0", "symfony/expression-language": "~2.8|~3.0|~4.0", "symfony/finder": "~2.8|~3.0|~4.0", - "symfony/form": "~3.4|~4.0", + "symfony/form": "^3.4.31|^4.3.4", "symfony/http-foundation": "^3.3.11|~4.0", "symfony/http-kernel": "~3.2|~4.0", "symfony/polyfill-intl-icu": "~1.0", "symfony/routing": "~2.8|~3.0|~4.0", - "symfony/security": "~2.8|~3.0|~4.0", + "symfony/security": "^2.8.31|^3.3.13|~4.0", "symfony/security-acl": "~2.8|~3.0", "symfony/stopwatch": "~2.8|~3.0|~4.0", "symfony/templating": "~2.8|~3.0|~4.0", @@ -1167,7 +1408,7 @@ "symfony/web-link": "For using the WebLinkExtension", "symfony/yaml": "For using the YamlExtension" }, - "time": "2018-01-17T07:49:55+00:00", + "time": "2019-10-01T15:13:36+00:00", "type": "symfony-bridge", "extra": { "branch-alias": { @@ -1199,5 +1440,73 @@ ], "description": "Symfony Twig Bridge", "homepage": "https://symfony.com" + }, + { + "name": "twig/twig", + "version": "v1.42.3", + "version_normalized": "1.42.3.0", + "source": { + "type": "git", + "url": "https://github.com/twigphp/Twig.git", + "reference": "201baee843e0ffe8b0b956f336dd42b2a92fae4e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/twigphp/Twig/zipball/201baee843e0ffe8b0b956f336dd42b2a92fae4e", + "reference": "201baee843e0ffe8b0b956f336dd42b2a92fae4e", + "shasum": "" + }, + "require": { + "php": ">=5.5.0", + "symfony/polyfill-ctype": "^1.8" + }, + "require-dev": { + "psr/container": "^1.0", + "symfony/debug": "^3.4|^4.2", + "symfony/phpunit-bridge": "^4.4@dev|^5.0" + }, + "time": "2019-08-24T12:51:03+00:00", + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.42-dev" + } + }, + "installation-source": "dist", + "autoload": { + "psr-0": { + "Twig_": "lib/" + }, + "psr-4": { + "Twig\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com", + "homepage": "http://fabien.potencier.org", + "role": "Lead Developer" + }, + { + "name": "Twig Team", + "homepage": "https://twig.symfony.com/contributors", + "role": "Contributors" + }, + { + "name": "Armin Ronacher", + "email": "armin.ronacher@active-4.com", + "role": "Project Founder" + } + ], + "description": "Twig, the flexible, fast, and secure template language for PHP", + "homepage": "https://twig.symfony.com", + "keywords": [ + "templating" + ] } ] diff --git a/vendor/guzzlehttp/guzzle/CHANGELOG.md b/vendor/guzzlehttp/guzzle/CHANGELOG.md index b265cbcd1afdd1710371ebe9f756b929b2039fdd..17badd756062b2fbb6d893750da457b88117d2f1 100644 --- a/vendor/guzzlehttp/guzzle/CHANGELOG.md +++ b/vendor/guzzlehttp/guzzle/CHANGELOG.md @@ -1,4 +1,27 @@ -# CHANGELOG +# Change Log + +## 6.3.3 - 2018-04-22 + +* Fix: Default headers when decode_content is specified + + +## 6.3.2 - 2018-03-26 + +* Fix: Release process + + +## 6.3.1 - 2018-03-26 + +* Bug fix: Parsing 0 epoch expiry times in cookies [#2014](https://github.com/guzzle/guzzle/pull/2014) +* Improvement: Better ConnectException detection [#2012](https://github.com/guzzle/guzzle/pull/2012) +* Bug fix: Malformed domain that contains a "/" [#1999](https://github.com/guzzle/guzzle/pull/1999) +* Bug fix: Undefined offset when a cookie has no first key-value pair [#1998](https://github.com/guzzle/guzzle/pull/1998) +* Improvement: Support PHPUnit 6 [#1953](https://github.com/guzzle/guzzle/pull/1953) +* Bug fix: Support empty headers [#1915](https://github.com/guzzle/guzzle/pull/1915) +* Bug fix: Ignore case during header modifications [#1916](https://github.com/guzzle/guzzle/pull/1916) + ++ Minor code cleanups, documentation fixes and clarifications. + ## 6.3.0 - 2017-06-22 diff --git a/vendor/guzzlehttp/guzzle/LICENSE b/vendor/guzzlehttp/guzzle/LICENSE index ea7f07c54cdd915063011b69358fac8fa7773c0e..50a177b0320c3f1f201fe6c57d4ecc0971017037 100644 --- a/vendor/guzzlehttp/guzzle/LICENSE +++ b/vendor/guzzlehttp/guzzle/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2011-2016 Michael Dowling, https://github.com/mtdowling <mtdowling@gmail.com> +Copyright (c) 2011-2018 Michael Dowling, https://github.com/mtdowling <mtdowling@gmail.com> Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/vendor/guzzlehttp/guzzle/README.md b/vendor/guzzlehttp/guzzle/README.md index 2f614d6f3ae3806fb9de478638f94c3910ffbd7e..bcd18b8e718bcfb922288cf6350eced1dbae966d 100644 --- a/vendor/guzzlehttp/guzzle/README.md +++ b/vendor/guzzlehttp/guzzle/README.md @@ -1,7 +1,9 @@ Guzzle, PHP HTTP client ======================= -[](https://travis-ci.org/guzzle/guzzle) +[](https://github.com/guzzle/guzzle/releases) +[](https://travis-ci.org/guzzle/guzzle) +[](https://packagist.org/packages/guzzlehttp/guzzle) Guzzle is a PHP HTTP client that makes it easy to send HTTP requests and trivial to integrate with web services. diff --git a/vendor/guzzlehttp/guzzle/composer.json b/vendor/guzzlehttp/guzzle/composer.json index 65687a58219e682d850d2c87b7127e17612ed942..1f328e308cdbf05fd63eac1be11099a194d3cb1c 100644 --- a/vendor/guzzlehttp/guzzle/composer.json +++ b/vendor/guzzlehttp/guzzle/composer.json @@ -19,7 +19,7 @@ }, "require-dev": { "ext-curl": "*", - "phpunit/phpunit": "^4.0 || ^5.0", + "phpunit/phpunit": "^4.8.35 || ^5.7 || ^6.4 || ^7.0", "psr/log": "^1.0" }, "autoload": { @@ -38,7 +38,7 @@ }, "extra": { "branch-alias": { - "dev-master": "6.2-dev" + "dev-master": "6.3-dev" } } } diff --git a/vendor/guzzlehttp/guzzle/src/Client.php b/vendor/guzzlehttp/guzzle/src/Client.php index de4df8a5ca144db7192d89f72f7cbba742573906..80417918d053c720a6079496dc9dbf40d19c41d7 100644 --- a/vendor/guzzlehttp/guzzle/src/Client.php +++ b/vendor/guzzlehttp/guzzle/src/Client.php @@ -290,7 +290,14 @@ class Client implements ClientInterface */ private function applyOptions(RequestInterface $request, array &$options) { - $modify = []; + $modify = [ + 'set_headers' => [], + ]; + + if (isset($options['headers'])) { + $modify['set_headers'] = $options['headers']; + unset($options['headers']); + } if (isset($options['form_params'])) { if (isset($options['multipart'])) { @@ -302,6 +309,8 @@ class Client implements ClientInterface } $options['body'] = http_build_query($options['form_params'], '', '&'); unset($options['form_params']); + // Ensure that we don't have the header in different case and set the new value. + $options['_conditional'] = Psr7\_caseless_remove(['Content-Type'], $options['_conditional']); $options['_conditional']['Content-Type'] = 'application/x-www-form-urlencoded'; } @@ -313,24 +322,19 @@ class Client implements ClientInterface if (isset($options['json'])) { $options['body'] = \GuzzleHttp\json_encode($options['json']); unset($options['json']); + // Ensure that we don't have the header in different case and set the new value. + $options['_conditional'] = Psr7\_caseless_remove(['Content-Type'], $options['_conditional']); $options['_conditional']['Content-Type'] = 'application/json'; } if (!empty($options['decode_content']) && $options['decode_content'] !== true ) { + // Ensure that we don't have the header in different case and set the new value. + $options['_conditional'] = Psr7\_caseless_remove(['Accept-Encoding'], $options['_conditional']); $modify['set_headers']['Accept-Encoding'] = $options['decode_content']; } - if (isset($options['headers'])) { - if (isset($modify['set_headers'])) { - $modify['set_headers'] = $options['headers'] + $modify['set_headers']; - } else { - $modify['set_headers'] = $options['headers']; - } - unset($options['headers']); - } - if (isset($options['body'])) { if (is_array($options['body'])) { $this->invalidBody(); @@ -344,6 +348,8 @@ class Client implements ClientInterface $type = isset($value[2]) ? strtolower($value[2]) : 'basic'; switch ($type) { case 'basic': + // Ensure that we don't have the header in different case and set the new value. + $modify['set_headers'] = Psr7\_caseless_remove(['Authorization'], $modify['set_headers']); $modify['set_headers']['Authorization'] = 'Basic ' . base64_encode("$value[0]:$value[1]"); break; @@ -382,6 +388,8 @@ class Client implements ClientInterface $request = Psr7\modify_request($request, $modify); if ($request->getBody() instanceof Psr7\MultipartStream) { // Use a multipart/form-data POST if a Content-Type is not set. + // Ensure that we don't have the header in different case and set the new value. + $options['_conditional'] = Psr7\_caseless_remove(['Content-Type'], $options['_conditional']); $options['_conditional']['Content-Type'] = 'multipart/form-data; boundary=' . $request->getBody()->getBoundary(); } diff --git a/vendor/guzzlehttp/guzzle/src/ClientInterface.php b/vendor/guzzlehttp/guzzle/src/ClientInterface.php index 5a67b66bf866504129f91c95d12c64e09f8bfe36..2dbcffa492d0c4ade0b8bf7ba73756cdede249a0 100644 --- a/vendor/guzzlehttp/guzzle/src/ClientInterface.php +++ b/vendor/guzzlehttp/guzzle/src/ClientInterface.php @@ -12,7 +12,7 @@ use Psr\Http\Message\UriInterface; */ interface ClientInterface { - const VERSION = '6.2.1'; + const VERSION = '6.3.3'; /** * Send an HTTP request. diff --git a/vendor/guzzlehttp/guzzle/src/Cookie/CookieJar.php b/vendor/guzzlehttp/guzzle/src/Cookie/CookieJar.php index 1c17b5a436ffa190c2af26d08b7250317eedfe46..78f2b79fecb55316ad3b974e3293206d66e81590 100644 --- a/vendor/guzzlehttp/guzzle/src/Cookie/CookieJar.php +++ b/vendor/guzzlehttp/guzzle/src/Cookie/CookieJar.php @@ -95,11 +95,11 @@ class CookieJar implements CookieJarInterface public function getCookieByName($name) { // don't allow a null name - if($name === null) { + if ($name === null) { return null; } - foreach($this->cookies as $cookie) { - if($cookie->getName() !== null && strcasecmp($cookie->getName(), $name) === 0) { + foreach ($this->cookies as $cookie) { + if ($cookie->getName() !== null && strcasecmp($cookie->getName(), $name) === 0) { return $cookie; } } diff --git a/vendor/guzzlehttp/guzzle/src/Cookie/SessionCookieJar.php b/vendor/guzzlehttp/guzzle/src/Cookie/SessionCookieJar.php index e4bfafd4fb034451f4e71b44c45a55f1f5810a2b..4497bcf03e24ec69b443eff05ac56b2c94e62c9f 100644 --- a/vendor/guzzlehttp/guzzle/src/Cookie/SessionCookieJar.php +++ b/vendor/guzzlehttp/guzzle/src/Cookie/SessionCookieJar.php @@ -15,7 +15,7 @@ class SessionCookieJar extends CookieJar /** * Create a new SessionCookieJar object * - * @param string $sessionKey Session key name to store the cookie + * @param string $sessionKey Session key name to store the cookie * data in session * @param bool $storeSessionCookies Set to true to store session cookies * in the cookie jar. diff --git a/vendor/guzzlehttp/guzzle/src/Cookie/SetCookie.php b/vendor/guzzlehttp/guzzle/src/Cookie/SetCookie.php index c911e2a3fca459736020d178964a5106de886c4c..f6993943e747c2d56218b343c74d7444bcb98cd8 100644 --- a/vendor/guzzlehttp/guzzle/src/Cookie/SetCookie.php +++ b/vendor/guzzlehttp/guzzle/src/Cookie/SetCookie.php @@ -35,14 +35,13 @@ class SetCookie $data = self::$defaults; // Explode the cookie string using a series of semicolons $pieces = array_filter(array_map('trim', explode(';', $cookie))); - // The name of the cookie (first kvp) must include an equal sign. - if (empty($pieces) || !strpos($pieces[0], '=')) { + // The name of the cookie (first kvp) must exist and include an equal sign. + if (empty($pieces[0]) || !strpos($pieces[0], '=')) { return new self($data); } // Add the cookie pieces into the parsed data array foreach ($pieces as $part) { - $cookieParts = explode('=', $part, 2); $key = trim($cookieParts[0]); $value = isset($cookieParts[1]) @@ -349,7 +348,7 @@ class SetCookie return false; } - return (bool) preg_match('/\.' . preg_quote($cookieDomain) . '$/', $domain); + return (bool) preg_match('/\.' . preg_quote($cookieDomain, '/') . '$/', $domain); } /** @@ -359,7 +358,7 @@ class SetCookie */ public function isExpired() { - return $this->getExpires() && time() > $this->getExpires(); + return $this->getExpires() !== null && time() > $this->getExpires(); } /** @@ -378,8 +377,8 @@ class SetCookie // Check if any of the invalid characters are present in the cookie name if (preg_match( '/[\x00-\x20\x22\x28-\x29\x2c\x2f\x3a-\x40\x5c\x7b\x7d\x7f]/', - $name) - ) { + $name + )) { return 'Cookie name must not contain invalid characters: ASCII ' . 'Control characters (0-31;127), space, tab and the ' . 'following characters: ()<>@,;:\"/?={}'; diff --git a/vendor/guzzlehttp/guzzle/src/Exception/GuzzleException.php b/vendor/guzzlehttp/guzzle/src/Exception/GuzzleException.php index c82998e0d7ef06fad4bbf048e2a61fc921b768ed..510778f6eb2f6800eef95d903d0b5b3ff139b415 100644 --- a/vendor/guzzlehttp/guzzle/src/Exception/GuzzleException.php +++ b/vendor/guzzlehttp/guzzle/src/Exception/GuzzleException.php @@ -1,4 +1,13 @@ <?php namespace GuzzleHttp\Exception; +/** + * @method string getMessage() + * @method \Throwable|null getPrevious() + * @method mixed getCode() + * @method string getFile() + * @method int getLine() + * @method array getTrace() + * @method string getTraceAsString() + */ interface GuzzleException {} diff --git a/vendor/guzzlehttp/guzzle/src/Handler/CurlFactory.php b/vendor/guzzlehttp/guzzle/src/Handler/CurlFactory.php index 49808e5c44679c724ecaacb3856973f3937a0607..e0923714306af0cc5c92bfbd838503e872e4fc68 100644 --- a/vendor/guzzlehttp/guzzle/src/Handler/CurlFactory.php +++ b/vendor/guzzlehttp/guzzle/src/Handler/CurlFactory.php @@ -4,7 +4,6 @@ namespace GuzzleHttp\Handler; use GuzzleHttp\Exception\RequestException; use GuzzleHttp\Exception\ConnectException; use GuzzleHttp\Promise\FulfilledPromise; -use GuzzleHttp\Promise\RejectedPromise; use GuzzleHttp\Psr7; use GuzzleHttp\Psr7\LazyOpenStream; use GuzzleHttp\TransferStats; @@ -288,7 +287,14 @@ class CurlFactory implements CurlFactoryInterface { foreach ($conf['_headers'] as $name => $values) { foreach ($values as $value) { - $conf[CURLOPT_HTTPHEADER][] = "$name: $value"; + $value = (string) $value; + if ($value === '') { + // cURL requires a special format for empty headers. + // See https://github.com/guzzle/guzzle/issues/1882 for more details. + $conf[CURLOPT_HTTPHEADER][] = "$name;"; + } else { + $conf[CURLOPT_HTTPHEADER][] = "$name: $value"; + } } } @@ -388,7 +394,7 @@ class CurlFactory implements CurlFactoryInterface if (isset($options['force_ip_resolve'])) { if ('v4' === $options['force_ip_resolve']) { $conf[CURLOPT_IPRESOLVE] = CURL_IPRESOLVE_V4; - } else if ('v6' === $options['force_ip_resolve']) { + } elseif ('v6' === $options['force_ip_resolve']) { $conf[CURLOPT_IPRESOLVE] = CURL_IPRESOLVE_V6; } } diff --git a/vendor/guzzlehttp/guzzle/src/Handler/CurlMultiHandler.php b/vendor/guzzlehttp/guzzle/src/Handler/CurlMultiHandler.php index 945d06ee4e2adae1fa28d5202b5b97efd62ad4ab..2754d8e4378d92530e1a3767c92cc3b673660161 100644 --- a/vendor/guzzlehttp/guzzle/src/Handler/CurlMultiHandler.php +++ b/vendor/guzzlehttp/guzzle/src/Handler/CurlMultiHandler.php @@ -65,7 +65,9 @@ class CurlMultiHandler $promise = new Promise( [$this, 'execute'], - function () use ($id) { return $this->cancel($id); } + function () use ($id) { + return $this->cancel($id); + } ); $this->addRequest(['easy' => $easy, 'deferred' => $promise]); diff --git a/vendor/guzzlehttp/guzzle/src/Handler/StreamHandler.php b/vendor/guzzlehttp/guzzle/src/Handler/StreamHandler.php index b12bfd942398a63b3e6430e227dd05fa482e5a50..b686545ea7f1d44d0de79ee0343524fc2b68128f 100644 --- a/vendor/guzzlehttp/guzzle/src/Handler/StreamHandler.php +++ b/vendor/guzzlehttp/guzzle/src/Handler/StreamHandler.php @@ -4,7 +4,6 @@ namespace GuzzleHttp\Handler; use GuzzleHttp\Exception\RequestException; use GuzzleHttp\Exception\ConnectException; use GuzzleHttp\Promise\FulfilledPromise; -use GuzzleHttp\Promise\RejectedPromise; use GuzzleHttp\Promise\PromiseInterface; use GuzzleHttp\Psr7; use GuzzleHttp\TransferStats; @@ -61,6 +60,7 @@ class StreamHandler if (strpos($message, 'getaddrinfo') // DNS lookup failed || strpos($message, 'Connection refused') || strpos($message, "couldn't connect to host") // error on HHVM + || strpos($message, "connection attempt failed") ) { $e = new ConnectException($e->getMessage(), $request, $e); } @@ -103,7 +103,7 @@ class StreamHandler $status = $parts[1]; $reason = isset($parts[2]) ? $parts[2] : null; $headers = \GuzzleHttp\headers_from_lines($hdrs); - list ($stream, $headers) = $this->checkDecode($options, $headers, $stream); + list($stream, $headers) = $this->checkDecode($options, $headers, $stream); $stream = Psr7\stream_for($stream); $sink = $stream; @@ -276,7 +276,7 @@ class StreamHandler } $params = []; - $context = $this->getDefaultContext($request, $options); + $context = $this->getDefaultContext($request); if (isset($options['on_headers']) && !is_callable($options['on_headers'])) { throw new \InvalidArgumentException('on_headers must be callable'); @@ -307,7 +307,6 @@ class StreamHandler && isset($options['auth'][2]) && 'ntlm' == $options['auth'][2] ) { - throw new \InvalidArgumentException('Microsoft NTLM authentication only supported with curl handler'); } diff --git a/vendor/guzzlehttp/guzzle/src/HandlerStack.php b/vendor/guzzlehttp/guzzle/src/HandlerStack.php index a72e38a532b2ee6a8f4da4a4f7ba49fdbf5be0a3..24c46fd9fea30c28a93137325f39bc18e9c8873c 100644 --- a/vendor/guzzlehttp/guzzle/src/HandlerStack.php +++ b/vendor/guzzlehttp/guzzle/src/HandlerStack.php @@ -22,7 +22,7 @@ class HandlerStack * Creates a default handler stack that can be used by clients. * * The returned handler will wrap the provided handler or use the most - * appropriate default handler for you system. The returned HandlerStack has + * appropriate default handler for your system. The returned HandlerStack has * support for cookies, redirects, HTTP error exceptions, and preparing a body * before sending. * diff --git a/vendor/guzzlehttp/guzzle/src/MessageFormatter.php b/vendor/guzzlehttp/guzzle/src/MessageFormatter.php index 6b090a977391a3903e580b05ff882965239a388d..663ac7391632645eb2f6b926123a1d669c1b9e69 100644 --- a/vendor/guzzlehttp/guzzle/src/MessageFormatter.php +++ b/vendor/guzzlehttp/guzzle/src/MessageFormatter.php @@ -19,7 +19,6 @@ use Psr\Http\Message\ResponseInterface; * - {host}: Host of the request * - {method}: Method of the request * - {uri}: URI of the request - * - {host}: Host of the request * - {version}: Protocol version * - {target}: Request target of the request (path + query + fragment) * - {hostname}: Hostname of the machine that sent the request @@ -74,7 +73,6 @@ class MessageFormatter return preg_replace_callback( '/{\s*([A-Za-z_\-\.0-9]+)\s*}/', function (array $matches) use ($request, $response, $error, &$cache) { - if (isset($cache[$matches[1]])) { return $cache[$matches[1]]; } diff --git a/vendor/guzzlehttp/guzzle/src/Middleware.php b/vendor/guzzlehttp/guzzle/src/Middleware.php index 9d79bd26e8ae31006a0ce68204b5393208398967..d4ad75c94f333a43b97f42e973e3c5962572d606 100644 --- a/vendor/guzzlehttp/guzzle/src/Middleware.php +++ b/vendor/guzzlehttp/guzzle/src/Middleware.php @@ -34,10 +34,11 @@ final class Middleware $cookieJar = $options['cookies']; $request = $cookieJar->withCookieHeader($request); return $handler($request, $options) - ->then(function ($response) use ($cookieJar, $request) { - $cookieJar->extractCookies($request, $response); - return $response; - } + ->then( + function ($response) use ($cookieJar, $request) { + $cookieJar->extractCookies($request, $response); + return $response; + } ); }; }; @@ -72,7 +73,7 @@ final class Middleware /** * Middleware that pushes history data to an ArrayAccess container. * - * @param array $container Container to hold the history (by reference). + * @param array|\ArrayAccess $container Container to hold the history (by reference). * * @return callable Returns a function that accepts the next handler. * @throws \InvalidArgumentException if container is not an array or ArrayAccess. diff --git a/vendor/guzzlehttp/guzzle/src/UriTemplate.php b/vendor/guzzlehttp/guzzle/src/UriTemplate.php index 0b1623ecaca007facc98ad039cf08037a213e98c..96dcfd09cd71fb4a2c40b38445faee78568ba0cc 100644 --- a/vendor/guzzlehttp/guzzle/src/UriTemplate.php +++ b/vendor/guzzlehttp/guzzle/src/UriTemplate.php @@ -107,7 +107,6 @@ class UriTemplate $useQuery = self::$operatorHash[$parsed['operator']]['query']; foreach ($parsed['values'] as $value) { - if (!isset($this->variables[$value['value']])) { continue; } @@ -117,11 +116,9 @@ class UriTemplate $expanded = ''; if (is_array($variable)) { - $isAssoc = $this->isAssoc($variable); $kvp = []; foreach ($variable as $key => $var) { - if ($isAssoc) { $key = rawurlencode($key); $isNestedArray = is_array($var); @@ -179,7 +176,6 @@ class UriTemplate } $expanded = implode(',', $kvp); } - } else { if ($value['modifier'] === ':') { $variable = substr($variable, 0, $value['position']); diff --git a/vendor/guzzlehttp/guzzle/src/functions.php b/vendor/guzzlehttp/guzzle/src/functions.php index 59e212edfad829c2b0a016cac8a2fdc9352b5da7..a3ac450db94cfe1409f5ec052d2710e6426e469e 100644 --- a/vendor/guzzlehttp/guzzle/src/functions.php +++ b/vendor/guzzlehttp/guzzle/src/functions.php @@ -302,7 +302,8 @@ function json_decode($json, $assoc = false, $depth = 512, $options = 0) $data = \json_decode($json, $assoc, $depth, $options); if (JSON_ERROR_NONE !== json_last_error()) { throw new \InvalidArgumentException( - 'json_decode error: ' . json_last_error_msg()); + 'json_decode error: ' . json_last_error_msg() + ); } return $data; @@ -324,7 +325,8 @@ function json_encode($value, $options = 0, $depth = 512) $json = \json_encode($value, $options, $depth); if (JSON_ERROR_NONE !== json_last_error()) { throw new \InvalidArgumentException( - 'json_encode error: ' . json_last_error_msg()); + 'json_encode error: ' . json_last_error_msg() + ); } return $json; diff --git a/vendor/guzzlehttp/psr7/CHANGELOG.md b/vendor/guzzlehttp/psr7/CHANGELOG.md index 5c252b3a208313cd73f7a84d63b752800edd96ff..8a3743dba5c5e88be197b4c38104cefbe56d96a2 100644 --- a/vendor/guzzlehttp/psr7/CHANGELOG.md +++ b/vendor/guzzlehttp/psr7/CHANGELOG.md @@ -1,32 +1,102 @@ -# CHANGELOG +# Change Log -## 1.4.2 - 2017-03-20 -* Reverted BC break to `Uri::resolve` and `Uri::removeDotSegments` by removing +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) +and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). + + +## [Unreleased] + + +## [1.6.0] + +### Added + +- Allowed version `^3.0` of `ralouphie/getallheaders` dependency (#244) +- Added MIME type for WEBP image format (#246) +- Added more validation of values according to PSR-7 and RFC standards, e.g. status code range (#250, #272) + +### Changed + +- Tests don't pass with HHVM 4.0, so HHVM support got dropped. Other libraries like composer have done the same. (#262) +- Accept port number 0 to be valid (#270) + +### Fixed + +- Fixed subsequent reads from `php://input` in ServerRequest (#247) +- Fixed readable/writable detection for certain stream modes (#248) +- Fixed encoding of special characters in the `userInfo` component of an URI (#253) + + +## [1.5.2] - 2018-12-04 + +### Fixed + +- Check body size when getting the message summary + + +## [1.5.1] - 2018-12-04 + +### Fixed + +- Get the summary of a body only if it is readable + + +## [1.5.0] - 2018-12-03 + +### Added + +- Response first-line to response string exception (fixes #145) +- A test for #129 behavior +- `get_message_body_summary` function in order to get the message summary +- `3gp` and `mkv` mime types + +### Changed + +- Clarify exception message when stream is detached + +### Deprecated + +- Deprecated parsing folded header lines as per RFC 7230 + +### Fixed + +- Fix `AppendStream::detach` to not close streams +- `InflateStream` preserves `isSeekable` attribute of the underlying stream +- `ServerRequest::getUriFromGlobals` to support URLs in query parameters + + +Several other fixes and improvements. + + +## [1.4.2] - 2017-03-20 + +### Fixed + +- Reverted BC break to `Uri::resolve` and `Uri::removeDotSegments` by removing calls to `trigger_error` when deprecated methods are invoked. -## 1.4.1 - 2017-02-27 -* Reverted BC break by reintroducing behavior to automagically fix a URI with a +## [1.4.1] - 2017-02-27 + +### Added + +- Rriggering of silenced deprecation warnings. + +### Fixed + +- Reverted BC break by reintroducing behavior to automagically fix a URI with a relative path and an authority by adding a leading slash to the path. It's only deprecated now. -* Added triggering of silenced deprecation warnings. -## 1.4.0 - 2017-02-21 -* Fix `Stream::read` when length parameter <= 0. -* `copy_to_stream` reads bytes in chunks instead of `maxLen` into memory. -* Fix `ServerRequest::getUriFromGlobals` when `Host` header contains port. -* Ensure `ServerRequest::getUriFromGlobals` returns a URI in absolute form. -* Allow `parse_response` to parse a response without delimiting space and reason. -* Ensure each URI modification results in a valid URI according to PSR-7 discussions. - Invalid modifications will throw an exception instead of returning a wrong URI or - doing some magic. - - `(new Uri)->withPath('foo')->withHost('example.com')` will throw an exception - because the path of a URI with an authority must start with a slash "/" or be empty - - `(new Uri())->withScheme('http')` will return `'http://localhost'` -* Fix compatibility of URIs with `file` scheme and empty host. -* Added common URI utility methods based on RFC 3986 (see documentation in the readme): +## [1.4.0] - 2017-02-21 + +### Added + +- Added common URI utility methods based on RFC 3986 (see documentation in the readme): - `Uri::isDefaultPort` - `Uri::isAbsolute` - `Uri::isNetworkPathReference` @@ -37,69 +107,117 @@ - `UriNormalizer::normalize` - `UriNormalizer::isEquivalent` - `UriResolver::relativize` -* Deprecated `Uri::resolve` in favor of `UriResolver::resolve` -* Deprecated `Uri::removeDotSegments` in favor of `UriResolver::removeDotSegments` -## 1.3.1 - 2016-06-25 +### Changed + +- Ensure `ServerRequest::getUriFromGlobals` returns a URI in absolute form. +- Allow `parse_response` to parse a response without delimiting space and reason. +- Ensure each URI modification results in a valid URI according to PSR-7 discussions. + Invalid modifications will throw an exception instead of returning a wrong URI or + doing some magic. + - `(new Uri)->withPath('foo')->withHost('example.com')` will throw an exception + because the path of a URI with an authority must start with a slash "/" or be empty + - `(new Uri())->withScheme('http')` will return `'http://localhost'` + +### Deprecated + +- `Uri::resolve` in favor of `UriResolver::resolve` +- `Uri::removeDotSegments` in favor of `UriResolver::removeDotSegments` + +### Fixed + +- `Stream::read` when length parameter <= 0. +- `copy_to_stream` reads bytes in chunks instead of `maxLen` into memory. +- `ServerRequest::getUriFromGlobals` when `Host` header contains port. +- Compatibility of URIs with `file` scheme and empty host. + + +## [1.3.1] - 2016-06-25 + +### Fixed -* Fix `Uri::__toString` for network path references, e.g. `//example.org`. -* Fix missing lowercase normalization for host. -* Fix handling of URI components in case they are `'0'` in a lot of places, +- `Uri::__toString` for network path references, e.g. `//example.org`. +- Missing lowercase normalization for host. +- Handling of URI components in case they are `'0'` in a lot of places, e.g. as a user info password. -* Fix `Uri::withAddedHeader` to correctly merge headers with different case. -* Fix trimming of header values in `Uri::withAddedHeader`. Header values may +- `Uri::withAddedHeader` to correctly merge headers with different case. +- Trimming of header values in `Uri::withAddedHeader`. Header values may be surrounded by whitespace which should be ignored according to RFC 7230 Section 3.2.4. This does not apply to header names. -* Fix `Uri::withAddedHeader` with an array of header values. -* Fix `Uri::resolve` when base path has no slash and handling of fragment. -* Fix handling of encoding in `Uri::with(out)QueryValue` so one can pass the +- `Uri::withAddedHeader` with an array of header values. +- `Uri::resolve` when base path has no slash and handling of fragment. +- Handling of encoding in `Uri::with(out)QueryValue` so one can pass the key/value both in encoded as well as decoded form to those methods. This is consistent with withPath, withQuery etc. -* Fix `ServerRequest::withoutAttribute` when attribute value is null. +- `ServerRequest::withoutAttribute` when attribute value is null. -## 1.3.0 - 2016-04-13 -* Added remaining interfaces needed for full PSR7 compatibility +## [1.3.0] - 2016-04-13 + +### Added + +- Remaining interfaces needed for full PSR7 compatibility (ServerRequestInterface, UploadedFileInterface, etc.). -* Added support for stream_for from scalars. -* Can now extend Uri. -* Fixed a bug in validating request methods by making it more permissive. +- Support for stream_for from scalars. + +### Changed + +- Can now extend Uri. + +### Fixed +- A bug in validating request methods by making it more permissive. -## 1.2.3 - 2016-02-18 -* Fixed support in `GuzzleHttp\Psr7\CachingStream` for seeking forward on remote +## [1.2.3] - 2016-02-18 + +### Fixed + +- Support in `GuzzleHttp\Psr7\CachingStream` for seeking forward on remote streams, which can sometimes return fewer bytes than requested with `fread`. -* Fixed handling of gzipped responses with FNAME headers. +- Handling of gzipped responses with FNAME headers. + + +## [1.2.2] - 2016-01-22 + +### Added -## 1.2.2 - 2016-01-22 +- Support for URIs without any authority. +- Support for HTTP 451 'Unavailable For Legal Reasons.' +- Support for using '0' as a filename. +- Support for including non-standard ports in Host headers. -* Added support for URIs without any authority. -* Added support for HTTP 451 'Unavailable For Legal Reasons.' -* Added support for using '0' as a filename. -* Added support for including non-standard ports in Host headers. -## 1.2.1 - 2015-11-02 +## [1.2.1] - 2015-11-02 -* Now supporting negative offsets when seeking to SEEK_END. +### Changes -## 1.2.0 - 2015-08-15 +- Now supporting negative offsets when seeking to SEEK_END. -* Body as `"0"` is now properly added to a response. -* Now allowing forward seeking in CachingStream. -* Now properly parsing HTTP requests that contain proxy targets in + +## [1.2.0] - 2015-08-15 + +### Changed + +- Body as `"0"` is now properly added to a response. +- Now allowing forward seeking in CachingStream. +- Now properly parsing HTTP requests that contain proxy targets in `parse_request`. -* functions.php is now conditionally required. -* user-info is no longer dropped when resolving URIs. +- functions.php is now conditionally required. +- user-info is no longer dropped when resolving URIs. + + +## [1.1.0] - 2015-06-24 -## 1.1.0 - 2015-06-24 +### Changed -* URIs can now be relative. -* `multipart/form-data` headers are now overridden case-insensitively. -* URI paths no longer encode the following characters because they are allowed +- URIs can now be relative. +- `multipart/form-data` headers are now overridden case-insensitively. +- URI paths no longer encode the following characters because they are allowed in URIs: "(", ")", "*", "!", "'" -* A port is no longer added to a URI when the scheme is missing and no port is +- A port is no longer added to a URI when the scheme is missing and no port is present. + ## 1.0.0 - 2015-05-19 Initial release. @@ -108,3 +226,21 @@ Currently unsupported: - `Psr\Http\Message\ServerRequestInterface` - `Psr\Http\Message\UploadedFileInterface` + + + +[Unreleased]: https://github.com/guzzle/psr7/compare/1.6.0...HEAD +[1.6.0]: https://github.com/guzzle/psr7/compare/1.5.2...1.6.0 +[1.5.2]: https://github.com/guzzle/psr7/compare/1.5.1...1.5.2 +[1.5.1]: https://github.com/guzzle/psr7/compare/1.5.0...1.5.1 +[1.5.0]: https://github.com/guzzle/psr7/compare/1.4.2...1.5.0 +[1.4.2]: https://github.com/guzzle/psr7/compare/1.4.1...1.4.2 +[1.4.1]: https://github.com/guzzle/psr7/compare/1.4.0...1.4.1 +[1.4.0]: https://github.com/guzzle/psr7/compare/1.3.1...1.4.0 +[1.3.1]: https://github.com/guzzle/psr7/compare/1.3.0...1.3.1 +[1.3.0]: https://github.com/guzzle/psr7/compare/1.2.3...1.3.0 +[1.2.3]: https://github.com/guzzle/psr7/compare/1.2.2...1.2.3 +[1.2.2]: https://github.com/guzzle/psr7/compare/1.2.1...1.2.2 +[1.2.1]: https://github.com/guzzle/psr7/compare/1.2.0...1.2.1 +[1.2.0]: https://github.com/guzzle/psr7/compare/1.1.0...1.2.0 +[1.1.0]: https://github.com/guzzle/psr7/compare/1.0.0...1.1.0 diff --git a/vendor/guzzlehttp/psr7/README.md b/vendor/guzzlehttp/psr7/README.md index 16499358ea102a6d05d5cc44fcdb7abba19083ab..c60a6a38d3306f5c4b2e9ab7c1e19c5b65495c27 100644 --- a/vendor/guzzlehttp/psr7/README.md +++ b/vendor/guzzlehttp/psr7/README.md @@ -372,7 +372,7 @@ This method accepts the following `$resource` types: $stream = GuzzleHttp\Psr7\stream_for('foo'); $stream = GuzzleHttp\Psr7\stream_for(fopen('/path/to/file', 'r')); -$generator function ($bytes) { +$generator = function ($bytes) { for ($i = 0; $i < $bytes; $i++) { yield ' '; } @@ -606,6 +606,12 @@ Creates a new URI with a specific query string value. Any existing query string provided key are removed and replaced with the given key value pair. A value of null will set the query string key without a value, e.g. "key" instead of "key=value". +### `GuzzleHttp\Psr7\Uri::withQueryValues` + +`public static function withQueryValues(UriInterface $uri, array $keyValueArray): UriInterface` + +Creates a new URI with multiple query string values. It has the same behavior as `withQueryValue()` but for an +associative array of key => value. ### `GuzzleHttp\Psr7\Uri::withoutQueryValue` diff --git a/vendor/guzzlehttp/psr7/composer.json b/vendor/guzzlehttp/psr7/composer.json index b1c5a90ba71569e748dd46146a1cd31dd3509a5a..168a055b06bb295153fdeb876c51d1c66e2d7366 100644 --- a/vendor/guzzlehttp/psr7/composer.json +++ b/vendor/guzzlehttp/psr7/composer.json @@ -2,7 +2,7 @@ "name": "guzzlehttp/psr7", "type": "library", "description": "PSR-7 message implementation that also provides common utility methods", - "keywords": ["request", "response", "message", "stream", "http", "uri", "url"], + "keywords": ["request", "response", "message", "stream", "http", "uri", "url", "psr-7"], "license": "MIT", "authors": [ { @@ -17,23 +17,33 @@ ], "require": { "php": ">=5.4.0", - "psr/http-message": "~1.0" + "psr/http-message": "~1.0", + "ralouphie/getallheaders": "^2.0.5 || ^3.0.0" }, "require-dev": { - "phpunit/phpunit": "~4.0" + "phpunit/phpunit": "~4.8.36 || ^5.7.27 || ^6.5.8", + "ext-zlib": "*" }, "provide": { "psr/http-message-implementation": "1.0" }, + "suggest": { + "zendframework/zend-httphandlerrunner": "Emit PSR-7 responses" + }, "autoload": { "psr-4": { "GuzzleHttp\\Psr7\\": "src/" }, "files": ["src/functions_include.php"] }, + "autoload-dev": { + "psr-4": { + "GuzzleHttp\\Tests\\Psr7\\": "tests/" + } + }, "extra": { "branch-alias": { - "dev-master": "1.4-dev" + "dev-master": "1.6-dev" } } } diff --git a/vendor/guzzlehttp/psr7/src/AppendStream.php b/vendor/guzzlehttp/psr7/src/AppendStream.php index 23039fd794bbcaaf1fda658301e90d0a4b209c46..472a0d61ba47c1010aa61bd99a67ef0418efc24b 100644 --- a/vendor/guzzlehttp/psr7/src/AppendStream.php +++ b/vendor/guzzlehttp/psr7/src/AppendStream.php @@ -16,7 +16,6 @@ class AppendStream implements StreamInterface private $seekable = true; private $current = 0; private $pos = 0; - private $detached = false; /** * @param StreamInterface[] $streams Streams to decorate. Each stream must @@ -73,6 +72,7 @@ class AppendStream implements StreamInterface public function close() { $this->pos = $this->current = 0; + $this->seekable = true; foreach ($this->streams as $stream) { $stream->close(); @@ -82,14 +82,22 @@ class AppendStream implements StreamInterface } /** - * Detaches each attached stream + * Detaches each attached stream. + * + * Returns null as it's not clear which underlying stream resource to return. * * {@inheritdoc} */ public function detach() { - $this->close(); - $this->detached = true; + $this->pos = $this->current = 0; + $this->seekable = true; + + foreach ($this->streams as $stream) { + $stream->detach(); + } + + $this->streams = []; } public function tell() diff --git a/vendor/guzzlehttp/psr7/src/FnStream.php b/vendor/guzzlehttp/psr7/src/FnStream.php index cc9b4453f716150dacb93db04289b65a014c9186..73daea6f375c41cb49169dd0751d24a82f6a6abb 100644 --- a/vendor/guzzlehttp/psr7/src/FnStream.php +++ b/vendor/guzzlehttp/psr7/src/FnStream.php @@ -52,6 +52,15 @@ class FnStream implements StreamInterface } } + /** + * An unserialize would allow the __destruct to run when the unserialized value goes out of scope. + * @throws \LogicException + */ + public function __wakeup() + { + throw new \LogicException('FnStream should never be unserialized'); + } + /** * Adds custom functionality to an underlying stream by intercepting * specific method calls. diff --git a/vendor/guzzlehttp/psr7/src/InflateStream.php b/vendor/guzzlehttp/psr7/src/InflateStream.php index 0051d3fec5a8bdd2d906f85bad4c6120949c7f4b..5e4f6028ca0baaadcfc1facf71c02c8bb4c586d4 100644 --- a/vendor/guzzlehttp/psr7/src/InflateStream.php +++ b/vendor/guzzlehttp/psr7/src/InflateStream.php @@ -27,7 +27,7 @@ class InflateStream implements StreamInterface $stream = new LimitStream($stream, -1, 10 + $filenameHeaderLength); $resource = StreamWrapper::getResource($stream); stream_filter_append($resource, 'zlib.inflate', STREAM_FILTER_READ); - $this->stream = new Stream($resource); + $this->stream = $stream->isSeekable() ? new Stream($resource) : new NoSeekStream(new Stream($resource)); } /** diff --git a/vendor/guzzlehttp/psr7/src/LimitStream.php b/vendor/guzzlehttp/psr7/src/LimitStream.php index 3c13d4f41155dc292b81be222a4bde4d027a63fd..e4f239e30f8c5b5611b34f6d93923029a987848a 100644 --- a/vendor/guzzlehttp/psr7/src/LimitStream.php +++ b/vendor/guzzlehttp/psr7/src/LimitStream.php @@ -72,7 +72,7 @@ class LimitStream implements StreamInterface { if ($whence !== SEEK_SET || $offset < 0) { throw new \RuntimeException(sprintf( - 'Cannot seek to offset % with whence %s', + 'Cannot seek to offset %s with whence %s', $offset, $whence )); diff --git a/vendor/guzzlehttp/psr7/src/MessageTrait.php b/vendor/guzzlehttp/psr7/src/MessageTrait.php index 1e4da649ad5279f94c351f3ef95cc64a3cf837e3..a7966d10cfb57779358ad01604b547d3e9dfe1d1 100644 --- a/vendor/guzzlehttp/psr7/src/MessageTrait.php +++ b/vendor/guzzlehttp/psr7/src/MessageTrait.php @@ -66,11 +66,8 @@ trait MessageTrait public function withHeader($header, $value) { - if (!is_array($value)) { - $value = [$value]; - } - - $value = $this->trimHeaderValues($value); + $this->assertHeader($header); + $value = $this->normalizeHeaderValue($value); $normalized = strtolower($header); $new = clone $this; @@ -85,11 +82,8 @@ trait MessageTrait public function withAddedHeader($header, $value) { - if (!is_array($value)) { - $value = [$value]; - } - - $value = $this->trimHeaderValues($value); + $this->assertHeader($header); + $value = $this->normalizeHeaderValue($value); $normalized = strtolower($header); $new = clone $this; @@ -144,11 +138,13 @@ trait MessageTrait { $this->headerNames = $this->headers = []; foreach ($headers as $header => $value) { - if (!is_array($value)) { - $value = [$value]; + if (is_int($header)) { + // Numeric array keys are converted to int by PHP but having a header name '123' is not forbidden by the spec + // and also allowed in withHeader(). So we need to cast it to string again for the following assertion to pass. + $header = (string) $header; } - - $value = $this->trimHeaderValues($value); + $this->assertHeader($header); + $value = $this->normalizeHeaderValue($value); $normalized = strtolower($header); if (isset($this->headerNames[$normalized])) { $header = $this->headerNames[$normalized]; @@ -160,6 +156,19 @@ trait MessageTrait } } + private function normalizeHeaderValue($value) + { + if (!is_array($value)) { + return $this->trimHeaderValues([$value]); + } + + if (count($value) === 0) { + throw new \InvalidArgumentException('Header value can not be an empty array.'); + } + + return $this->trimHeaderValues($value); + } + /** * Trims whitespace from the header values. * @@ -177,7 +186,28 @@ trait MessageTrait private function trimHeaderValues(array $values) { return array_map(function ($value) { - return trim($value, " \t"); + if (!is_scalar($value) && null !== $value) { + throw new \InvalidArgumentException(sprintf( + 'Header value must be scalar or null but %s provided.', + is_object($value) ? get_class($value) : gettype($value) + )); + } + + return trim((string) $value, " \t"); }, $values); } + + private function assertHeader($header) + { + if (!is_string($header)) { + throw new \InvalidArgumentException(sprintf( + 'Header name must be a string but %s provided.', + is_object($header) ? get_class($header) : gettype($header) + )); + } + + if ($header === '') { + throw new \InvalidArgumentException('Header name can not be empty.'); + } + } } diff --git a/vendor/guzzlehttp/psr7/src/Request.php b/vendor/guzzlehttp/psr7/src/Request.php index 08285484da22d738e3b7bc2781ef06e81d7f6b19..59f337db11d45efcdad5f2f6f0fe2ea7f8952048 100644 --- a/vendor/guzzlehttp/psr7/src/Request.php +++ b/vendor/guzzlehttp/psr7/src/Request.php @@ -36,6 +36,7 @@ class Request implements RequestInterface $body = null, $version = '1.1' ) { + $this->assertMethod($method); if (!($uri instanceof UriInterface)) { $uri = new Uri($uri); } @@ -45,7 +46,7 @@ class Request implements RequestInterface $this->setHeaders($headers); $this->protocol = $version; - if (!$this->hasHeader('Host')) { + if (!isset($this->headerNames['host'])) { $this->updateHostFromUri(); } @@ -91,6 +92,7 @@ class Request implements RequestInterface public function withMethod($method) { + $this->assertMethod($method); $new = clone $this; $new->method = strtoupper($method); return $new; @@ -110,7 +112,7 @@ class Request implements RequestInterface $new = clone $this; $new->uri = $uri; - if (!$preserveHost) { + if (!$preserveHost || !isset($this->headerNames['host'])) { $new->updateHostFromUri(); } @@ -139,4 +141,11 @@ class Request implements RequestInterface // See: http://tools.ietf.org/html/rfc7230#section-5.4 $this->headers = [$header => [$host]] + $this->headers; } + + private function assertMethod($method) + { + if (!is_string($method) || $method === '') { + throw new \InvalidArgumentException('Method must be a non-empty string.'); + } + } } diff --git a/vendor/guzzlehttp/psr7/src/Response.php b/vendor/guzzlehttp/psr7/src/Response.php index 2830c6c9ee10229c613e94f7b4360d6796c3e752..e7e04d86a6593c3fc310be047b1a1ef06cc71b6d 100644 --- a/vendor/guzzlehttp/psr7/src/Response.php +++ b/vendor/guzzlehttp/psr7/src/Response.php @@ -93,7 +93,11 @@ class Response implements ResponseInterface $version = '1.1', $reason = null ) { - $this->statusCode = (int) $status; + $this->assertStatusCodeIsInteger($status); + $status = (int) $status; + $this->assertStatusCodeRange($status); + + $this->statusCode = $status; if ($body !== '' && $body !== null) { $this->stream = stream_for($body); @@ -121,12 +125,30 @@ class Response implements ResponseInterface public function withStatus($code, $reasonPhrase = '') { + $this->assertStatusCodeIsInteger($code); + $code = (int) $code; + $this->assertStatusCodeRange($code); + $new = clone $this; - $new->statusCode = (int) $code; + $new->statusCode = $code; if ($reasonPhrase == '' && isset(self::$phrases[$new->statusCode])) { $reasonPhrase = self::$phrases[$new->statusCode]; } $new->reasonPhrase = $reasonPhrase; return $new; } + + private function assertStatusCodeIsInteger($statusCode) + { + if (filter_var($statusCode, FILTER_VALIDATE_INT) === false) { + throw new \InvalidArgumentException('Status code must be an integer value.'); + } + } + + private function assertStatusCodeRange($statusCode) + { + if ($statusCode < 100 || $statusCode >= 600) { + throw new \InvalidArgumentException('Status code must be an integer value between 1xx and 5xx.'); + } + } } diff --git a/vendor/guzzlehttp/psr7/src/Rfc7230.php b/vendor/guzzlehttp/psr7/src/Rfc7230.php new file mode 100644 index 0000000000000000000000000000000000000000..505e4742b6e749f85e69499c013617df20f7232e --- /dev/null +++ b/vendor/guzzlehttp/psr7/src/Rfc7230.php @@ -0,0 +1,18 @@ +<?php + +namespace GuzzleHttp\Psr7; + +final class Rfc7230 +{ + /** + * Header related regular expressions (copied from amphp/http package) + * (Note: once we require PHP 7.x we could just depend on the upstream package) + * + * Note: header delimiter (\r\n) is modified to \r?\n to accept line feed only delimiters for BC reasons. + * + * @link https://github.com/amphp/http/blob/v1.0.1/src/Rfc7230.php#L12-L15 + * @license https://github.com/amphp/http/blob/v1.0.1/LICENSE + */ + const HEADER_REGEX = "(^([^()<>@,;:\\\"/[\]?={}\x01-\x20\x7F]++):[ \t]*+((?:[ \t]*+[\x21-\x7E\x80-\xFF]++)*+)[ \t]*+\r?\n)m"; + const HEADER_FOLD_REGEX = "(\r?\n[ \t]++)"; +} diff --git a/vendor/guzzlehttp/psr7/src/ServerRequest.php b/vendor/guzzlehttp/psr7/src/ServerRequest.php index 575aab8489a60279366f1b1cca29d93ad77287cd..1a09a6c87c3af3ca9e315e48aee1e4da64c4eb31 100644 --- a/vendor/guzzlehttp/psr7/src/ServerRequest.php +++ b/vendor/guzzlehttp/psr7/src/ServerRequest.php @@ -166,9 +166,9 @@ class ServerRequest extends Request implements ServerRequestInterface public static function fromGlobals() { $method = isset($_SERVER['REQUEST_METHOD']) ? $_SERVER['REQUEST_METHOD'] : 'GET'; - $headers = function_exists('getallheaders') ? getallheaders() : []; + $headers = getallheaders(); $uri = self::getUriFromGlobals(); - $body = new LazyOpenStream('php://input', 'r+'); + $body = new CachingStream(new LazyOpenStream('php://input', 'r+')); $protocol = isset($_SERVER['SERVER_PROTOCOL']) ? str_replace('HTTP/', '', $_SERVER['SERVER_PROTOCOL']) : '1.1'; $serverRequest = new ServerRequest($method, $uri, $headers, $body, $protocol, $_SERVER); @@ -180,23 +180,41 @@ class ServerRequest extends Request implements ServerRequestInterface ->withUploadedFiles(self::normalizeFiles($_FILES)); } + private static function extractHostAndPortFromAuthority($authority) + { + $uri = 'http://'.$authority; + $parts = parse_url($uri); + if (false === $parts) { + return [null, null]; + } + + $host = isset($parts['host']) ? $parts['host'] : null; + $port = isset($parts['port']) ? $parts['port'] : null; + + return [$host, $port]; + } + /** * Get a Uri populated with values from $_SERVER. * * @return UriInterface */ - public static function getUriFromGlobals() { + public static function getUriFromGlobals() + { $uri = new Uri(''); $uri = $uri->withScheme(!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' ? 'https' : 'http'); $hasPort = false; if (isset($_SERVER['HTTP_HOST'])) { - $hostHeaderParts = explode(':', $_SERVER['HTTP_HOST']); - $uri = $uri->withHost($hostHeaderParts[0]); - if (isset($hostHeaderParts[1])) { + list($host, $port) = self::extractHostAndPortFromAuthority($_SERVER['HTTP_HOST']); + if ($host !== null) { + $uri = $uri->withHost($host); + } + + if ($port !== null) { $hasPort = true; - $uri = $uri->withPort($hostHeaderParts[1]); + $uri = $uri->withPort($port); } } elseif (isset($_SERVER['SERVER_NAME'])) { $uri = $uri->withHost($_SERVER['SERVER_NAME']); @@ -210,7 +228,7 @@ class ServerRequest extends Request implements ServerRequestInterface $hasQuery = false; if (isset($_SERVER['REQUEST_URI'])) { - $requestUriParts = explode('?', $_SERVER['REQUEST_URI']); + $requestUriParts = explode('?', $_SERVER['REQUEST_URI'], 2); $uri = $uri->withPath($requestUriParts[0]); if (isset($requestUriParts[1])) { $hasQuery = true; diff --git a/vendor/guzzlehttp/psr7/src/Stream.php b/vendor/guzzlehttp/psr7/src/Stream.php index e33662879ffbac5ee1fc971f1dc17fdedfd8979f..d9e7409c7c070d94a88ad8cc4d44d26fa243dc91 100644 --- a/vendor/guzzlehttp/psr7/src/Stream.php +++ b/vendor/guzzlehttp/psr7/src/Stream.php @@ -10,6 +10,17 @@ use Psr\Http\Message\StreamInterface; */ class Stream implements StreamInterface { + /** + * Resource modes. + * + * @var string + * + * @see http://php.net/manual/function.fopen.php + * @see http://php.net/manual/en/function.gzopen.php + */ + const READABLE_MODES = '/r|a\+|ab\+|w\+|wb\+|x\+|xb\+|c\+|cb\+/'; + const WRITABLE_MODES = '/a|w|r\+|rb\+|rw|x|c/'; + private $stream; private $size; private $seekable; @@ -18,22 +29,6 @@ class Stream implements StreamInterface private $uri; private $customMetadata; - /** @var array Hash of readable and writable stream types */ - private static $readWriteHash = [ - 'read' => [ - 'r' => true, 'w+' => true, 'r+' => true, 'x+' => true, 'c+' => true, - 'rb' => true, 'w+b' => true, 'r+b' => true, 'x+b' => true, - 'c+b' => true, 'rt' => true, 'w+t' => true, 'r+t' => true, - 'x+t' => true, 'c+t' => true, 'a+' => true - ], - 'write' => [ - 'w' => true, 'w+' => true, 'rw' => true, 'r+' => true, 'x+' => true, - 'c+' => true, 'wb' => true, 'w+b' => true, 'r+b' => true, - 'x+b' => true, 'c+b' => true, 'w+t' => true, 'r+t' => true, - 'x+t' => true, 'c+t' => true, 'a' => true, 'a+' => true - ] - ]; - /** * This constructor accepts an associative array of options. * @@ -65,20 +60,11 @@ class Stream implements StreamInterface $this->stream = $stream; $meta = stream_get_meta_data($this->stream); $this->seekable = $meta['seekable']; - $this->readable = isset(self::$readWriteHash['read'][$meta['mode']]); - $this->writable = isset(self::$readWriteHash['write'][$meta['mode']]); + $this->readable = (bool)preg_match(self::READABLE_MODES, $meta['mode']); + $this->writable = (bool)preg_match(self::WRITABLE_MODES, $meta['mode']); $this->uri = $this->getMetadata('uri'); } - public function __get($name) - { - if ($name == 'stream') { - throw new \RuntimeException('The stream is detached'); - } - - throw new \BadMethodCallException('No value for ' . $name); - } - /** * Closes the stream when the destructed */ @@ -99,6 +85,10 @@ class Stream implements StreamInterface public function getContents() { + if (!isset($this->stream)) { + throw new \RuntimeException('Stream is detached'); + } + $contents = stream_get_contents($this->stream); if ($contents === false) { @@ -173,11 +163,19 @@ class Stream implements StreamInterface public function eof() { - return !$this->stream || feof($this->stream); + if (!isset($this->stream)) { + throw new \RuntimeException('Stream is detached'); + } + + return feof($this->stream); } public function tell() { + if (!isset($this->stream)) { + throw new \RuntimeException('Stream is detached'); + } + $result = ftell($this->stream); if ($result === false) { @@ -194,9 +192,15 @@ class Stream implements StreamInterface public function seek($offset, $whence = SEEK_SET) { + $whence = (int) $whence; + + if (!isset($this->stream)) { + throw new \RuntimeException('Stream is detached'); + } if (!$this->seekable) { throw new \RuntimeException('Stream is not seekable'); - } elseif (fseek($this->stream, $offset, $whence) === -1) { + } + if (fseek($this->stream, $offset, $whence) === -1) { throw new \RuntimeException('Unable to seek to stream position ' . $offset . ' with whence ' . var_export($whence, true)); } @@ -204,6 +208,9 @@ class Stream implements StreamInterface public function read($length) { + if (!isset($this->stream)) { + throw new \RuntimeException('Stream is detached'); + } if (!$this->readable) { throw new \RuntimeException('Cannot read from non-readable stream'); } @@ -225,6 +232,9 @@ class Stream implements StreamInterface public function write($string) { + if (!isset($this->stream)) { + throw new \RuntimeException('Stream is detached'); + } if (!$this->writable) { throw new \RuntimeException('Cannot write to a non-writable stream'); } diff --git a/vendor/guzzlehttp/psr7/src/StreamWrapper.php b/vendor/guzzlehttp/psr7/src/StreamWrapper.php index cf7b2232e463e21dc3eb6de440fdef70c6d057e7..0f3a2856a2e592c1d57940fe6bb5be3cc8e46228 100644 --- a/vendor/guzzlehttp/psr7/src/StreamWrapper.php +++ b/vendor/guzzlehttp/psr7/src/StreamWrapper.php @@ -38,9 +38,21 @@ class StreamWrapper . 'writable, or both.'); } - return fopen('guzzle://stream', $mode, null, stream_context_create([ + return fopen('guzzle://stream', $mode, null, self::createStreamContext($stream)); + } + + /** + * Creates a stream context that can be used to open a stream as a php stream resource. + * + * @param StreamInterface $stream + * + * @return resource + */ + public static function createStreamContext(StreamInterface $stream) + { + return stream_context_create([ 'guzzle' => ['stream' => $stream] - ])); + ]); } /** @@ -94,12 +106,21 @@ class StreamWrapper return true; } + public function stream_cast($cast_as) + { + $stream = clone($this->stream); + + return $stream->detach(); + } + public function stream_stat() { static $modeMap = [ 'r' => 33060, + 'rb' => 33060, 'r+' => 33206, - 'w' => 33188 + 'w' => 33188, + 'wb' => 33188 ]; return [ @@ -118,4 +139,23 @@ class StreamWrapper 'blocks' => 0 ]; } + + public function url_stat($path, $flags) + { + return [ + 'dev' => 0, + 'ino' => 0, + 'mode' => 0, + 'nlink' => 0, + 'uid' => 0, + 'gid' => 0, + 'rdev' => 0, + 'size' => 0, + 'atime' => 0, + 'mtime' => 0, + 'ctime' => 0, + 'blksize' => 0, + 'blocks' => 0 + ]; + } } diff --git a/vendor/guzzlehttp/psr7/src/Uri.php b/vendor/guzzlehttp/psr7/src/Uri.php index f46c1db9e07812e8d0069a4d9beb145ea3bfbf31..825a25eedb8270dcaeba9ca152c3e0621bab068c 100644 --- a/vendor/guzzlehttp/psr7/src/Uri.php +++ b/vendor/guzzlehttp/psr7/src/Uri.php @@ -301,15 +301,7 @@ class Uri implements UriInterface */ public static function withoutQueryValue(UriInterface $uri, $key) { - $current = $uri->getQuery(); - if ($current === '') { - return $uri; - } - - $decodedKey = rawurldecode($key); - $result = array_filter(explode('&', $current), function ($part) use ($decodedKey) { - return rawurldecode(explode('=', $part)[0]) !== $decodedKey; - }); + $result = self::getFilteredQueryString($uri, [$key]); return $uri->withQuery(implode('&', $result)); } @@ -331,26 +323,29 @@ class Uri implements UriInterface */ public static function withQueryValue(UriInterface $uri, $key, $value) { - $current = $uri->getQuery(); + $result = self::getFilteredQueryString($uri, [$key]); - if ($current === '') { - $result = []; - } else { - $decodedKey = rawurldecode($key); - $result = array_filter(explode('&', $current), function ($part) use ($decodedKey) { - return rawurldecode(explode('=', $part)[0]) !== $decodedKey; - }); - } + $result[] = self::generateQueryString($key, $value); - // Query string separators ("=", "&") within the key or value need to be encoded - // (while preventing double-encoding) before setting the query string. All other - // chars that need percent-encoding will be encoded by withQuery(). - $key = strtr($key, self::$replaceQuery); + return $uri->withQuery(implode('&', $result)); + } - if ($value !== null) { - $result[] = $key . '=' . strtr($value, self::$replaceQuery); - } else { - $result[] = $key; + /** + * Creates a new URI with multiple specific query string values. + * + * It has the same behavior as withQueryValue() but for an associative array of key => value. + * + * @param UriInterface $uri URI to use as a base. + * @param array $keyValueArray Associative array of key and values + * + * @return UriInterface + */ + public static function withQueryValues(UriInterface $uri, array $keyValueArray) + { + $result = self::getFilteredQueryString($uri, array_keys($keyValueArray)); + + foreach ($keyValueArray as $key => $value) { + $result[] = self::generateQueryString($key, $value); } return $uri->withQuery(implode('&', $result)); @@ -442,9 +437,9 @@ class Uri implements UriInterface public function withUserInfo($user, $password = null) { - $info = $user; - if ($password != '') { - $info .= ':' . $password; + $info = $this->filterUserInfoComponent($user); + if ($password !== null) { + $info .= ':' . $this->filterUserInfoComponent($password); } if ($this->userInfo === $info) { @@ -542,7 +537,9 @@ class Uri implements UriInterface $this->scheme = isset($parts['scheme']) ? $this->filterScheme($parts['scheme']) : ''; - $this->userInfo = isset($parts['user']) ? $parts['user'] : ''; + $this->userInfo = isset($parts['user']) + ? $this->filterUserInfoComponent($parts['user']) + : ''; $this->host = isset($parts['host']) ? $this->filterHost($parts['host']) : ''; @@ -559,7 +556,7 @@ class Uri implements UriInterface ? $this->filterQueryAndFragment($parts['fragment']) : ''; if (isset($parts['pass'])) { - $this->userInfo .= ':' . $parts['pass']; + $this->userInfo .= ':' . $this->filterUserInfoComponent($parts['pass']); } $this->removeDefaultPort(); @@ -581,6 +578,26 @@ class Uri implements UriInterface return strtolower($scheme); } + /** + * @param string $component + * + * @return string + * + * @throws \InvalidArgumentException If the user info is invalid. + */ + private function filterUserInfoComponent($component) + { + if (!is_string($component)) { + throw new \InvalidArgumentException('User info must be a string'); + } + + return preg_replace_callback( + '/(?:[^%' . self::$charUnreserved . self::$charSubDelims . ']+|%(?![A-Fa-f0-9]{2}))/', + [$this, 'rawurlencodeMatchZero'], + $component + ); + } + /** * @param string $host * @@ -611,15 +628,56 @@ class Uri implements UriInterface } $port = (int) $port; - if (1 > $port || 0xffff < $port) { + if (0 > $port || 0xffff < $port) { throw new \InvalidArgumentException( - sprintf('Invalid port: %d. Must be between 1 and 65535', $port) + sprintf('Invalid port: %d. Must be between 0 and 65535', $port) ); } return $port; } + /** + * @param UriInterface $uri + * @param array $keys + * + * @return array + */ + private static function getFilteredQueryString(UriInterface $uri, array $keys) + { + $current = $uri->getQuery(); + + if ($current === '') { + return []; + } + + $decodedKeys = array_map('rawurldecode', $keys); + + return array_filter(explode('&', $current), function ($part) use ($decodedKeys) { + return !in_array(rawurldecode(explode('=', $part)[0]), $decodedKeys, true); + }); + } + + /** + * @param string $key + * @param string|null $value + * + * @return string + */ + private static function generateQueryString($key, $value) + { + // Query string separators ("=", "&") within the key or value need to be encoded + // (while preventing double-encoding) before setting the query string. All other + // chars that need percent-encoding will be encoded by withQuery(). + $queryString = strtr($key, self::$replaceQuery); + + if ($value !== null) { + $queryString .= '=' . strtr($value, self::$replaceQuery); + } + + return $queryString; + } + private function removeDefaultPort() { if ($this->port !== null && self::isDefaultPort($this)) { diff --git a/vendor/guzzlehttp/psr7/src/functions.php b/vendor/guzzlehttp/psr7/src/functions.php index e40348d6abdee0bafd739cae12f99f033b131da8..8e6dafe68ea0d4c53820faeac5f75de452e1c906 100644 --- a/vendor/guzzlehttp/psr7/src/functions.php +++ b/vendor/guzzlehttp/psr7/src/functions.php @@ -69,10 +69,10 @@ function uri_for($uri) * - metadata: Array of custom metadata. * - size: Size of the stream. * - * @param resource|string|null|int|float|bool|StreamInterface|callable $resource Entity body data - * @param array $options Additional options + * @param resource|string|null|int|float|bool|StreamInterface|callable|\Iterator $resource Entity body data + * @param array $options Additional options * - * @return Stream + * @return StreamInterface * @throws \InvalidArgumentException if the $resource arg is not valid. */ function stream_for($resource = '', array $options = []) @@ -238,7 +238,7 @@ function modify_request(RequestInterface $request, array $changes) } if ($request instanceof ServerRequestInterface) { - return new ServerRequest( + return (new ServerRequest( isset($changes['method']) ? $changes['method'] : $request->getMethod(), $uri, $headers, @@ -247,7 +247,11 @@ function modify_request(RequestInterface $request, array $changes) ? $changes['version'] : $request->getProtocolVersion(), $request->getServerParams() - ); + )) + ->withParsedBody($request->getParsedBody()) + ->withQueryParams($request->getQueryParams()) + ->withCookieParams($request->getCookieParams()) + ->withUploadedFiles($request->getUploadedFiles()); } return new Request( @@ -431,7 +435,7 @@ function hash( * @param StreamInterface $stream Stream to read from * @param int $maxLength Maximum buffer length * - * @return string|bool + * @return string */ function readline(StreamInterface $stream, $maxLength = null) { @@ -495,7 +499,7 @@ function parse_response($message) // between status-code and reason-phrase is required. But browsers accept // responses without space and reason as well. if (!preg_match('/^HTTP\/.* [0-9]{3}( .*|$)/', $data['start-line'])) { - throw new \InvalidArgumentException('Invalid response string'); + throw new \InvalidArgumentException('Invalid response string: ' . $data['start-line']); } $parts = explode(' ', $data['start-line'], 3); @@ -516,8 +520,8 @@ function parse_response($message) * PHP style arrays into an associative array (e.g., foo[a]=1&foo[b]=2 will * be parsed into ['foo[a]' => '1', 'foo[b]' => '2']). * - * @param string $str Query string to parse - * @param bool|string $urlEncoding How the query string is encoded + * @param string $str Query string to parse + * @param int|bool $urlEncoding How the query string is encoded * * @return array */ @@ -533,9 +537,9 @@ function parse_query($str, $urlEncoding = true) $decoder = function ($value) { return rawurldecode(str_replace('+', ' ', $value)); }; - } elseif ($urlEncoding == PHP_QUERY_RFC3986) { + } elseif ($urlEncoding === PHP_QUERY_RFC3986) { $decoder = 'rawurldecode'; - } elseif ($urlEncoding == PHP_QUERY_RFC1738) { + } elseif ($urlEncoding === PHP_QUERY_RFC1738) { $decoder = 'urldecode'; } else { $decoder = function ($str) { return $str; }; @@ -633,6 +637,7 @@ function mimetype_from_filename($filename) function mimetype_from_extension($extension) { static $mimetypes = [ + '3gp' => 'video/3gpp', '7z' => 'application/x-7z-compressed', 'aac' => 'audio/x-aac', 'ai' => 'application/postscript', @@ -680,6 +685,7 @@ function mimetype_from_extension($extension) 'mid' => 'audio/midi', 'midi' => 'audio/midi', 'mov' => 'video/quicktime', + 'mkv' => 'video/x-matroska', 'mp3' => 'audio/mpeg', 'mp4' => 'video/mp4', 'mp4a' => 'audio/mp4', @@ -718,6 +724,7 @@ function mimetype_from_extension($extension) 'txt' => 'text/plain', 'wav' => 'audio/x-wav', 'webm' => 'video/webm', + 'webp' => 'image/webp', 'wma' => 'audio/x-ms-wma', 'wmv' => 'video/x-ms-wmv', 'woff' => 'application/x-font-woff', @@ -758,29 +765,53 @@ function _parse_message($message) throw new \InvalidArgumentException('Invalid message'); } - // Iterate over each line in the message, accounting for line endings - $lines = preg_split('/(\\r?\\n)/', $message, -1, PREG_SPLIT_DELIM_CAPTURE); - $result = ['start-line' => array_shift($lines), 'headers' => [], 'body' => '']; - array_shift($lines); + $message = ltrim($message, "\r\n"); - for ($i = 0, $totalLines = count($lines); $i < $totalLines; $i += 2) { - $line = $lines[$i]; - // If two line breaks were encountered, then this is the end of body - if (empty($line)) { - if ($i < $totalLines - 1) { - $result['body'] = implode('', array_slice($lines, $i + 2)); - } - break; - } - if (strpos($line, ':')) { - $parts = explode(':', $line, 2); - $key = trim($parts[0]); - $value = isset($parts[1]) ? trim($parts[1]) : ''; - $result['headers'][$key][] = $value; + $messageParts = preg_split("/\r?\n\r?\n/", $message, 2); + + if ($messageParts === false || count($messageParts) !== 2) { + throw new \InvalidArgumentException('Invalid message: Missing header delimiter'); + } + + list($rawHeaders, $body) = $messageParts; + $rawHeaders .= "\r\n"; // Put back the delimiter we split previously + $headerParts = preg_split("/\r?\n/", $rawHeaders, 2); + + if ($headerParts === false || count($headerParts) !== 2) { + throw new \InvalidArgumentException('Invalid message: Missing status line'); + } + + list($startLine, $rawHeaders) = $headerParts; + + if (preg_match("/(?:^HTTP\/|^[A-Z]+ \S+ HTTP\/)(\d+(?:\.\d+)?)/i", $startLine, $matches) && $matches[1] === '1.0') { + // Header folding is deprecated for HTTP/1.1, but allowed in HTTP/1.0 + $rawHeaders = preg_replace(Rfc7230::HEADER_FOLD_REGEX, ' ', $rawHeaders); + } + + /** @var array[] $headerLines */ + $count = preg_match_all(Rfc7230::HEADER_REGEX, $rawHeaders, $headerLines, PREG_SET_ORDER); + + // If these aren't the same, then one line didn't match and there's an invalid header. + if ($count !== substr_count($rawHeaders, "\n")) { + // Folding is deprecated, see https://tools.ietf.org/html/rfc7230#section-3.2.4 + if (preg_match(Rfc7230::HEADER_FOLD_REGEX, $rawHeaders)) { + throw new \InvalidArgumentException('Invalid header syntax: Obsolete line folding'); } + + throw new \InvalidArgumentException('Invalid header syntax'); } - return $result; + $headers = []; + + foreach ($headerLines as $headerLine) { + $headers[$headerLine[1]][] = $headerLine[2]; + } + + return [ + 'start-line' => $startLine, + 'headers' => $headers, + 'body' => $body, + ]; } /** @@ -809,6 +840,46 @@ function _parse_request_uri($path, array $headers) return $scheme . '://' . $host . '/' . ltrim($path, '/'); } +/** + * Get a short summary of the message body + * + * Will return `null` if the response is not printable. + * + * @param MessageInterface $message The message to get the body summary + * @param int $truncateAt The maximum allowed size of the summary + * + * @return null|string + */ +function get_message_body_summary(MessageInterface $message, $truncateAt = 120) +{ + $body = $message->getBody(); + + if (!$body->isSeekable() || !$body->isReadable()) { + return null; + } + + $size = $body->getSize(); + + if ($size === 0) { + return null; + } + + $summary = $body->read($truncateAt); + $body->rewind(); + + if ($size > $truncateAt) { + $summary .= ' (truncated...)'; + } + + // Matches any printable character, including unicode characters: + // letters, marks, numbers, punctuation, spacing, and separators. + if (preg_match('/[^\pL\pM\pN\pP\pS\pZ\n\r\t]/', $summary)) { + return null; + } + + return $summary; +} + /** @internal */ function _caseless_remove($keys, array $data) { diff --git a/vendor/hab/solr b/vendor/hab/solr index f16f0026296c6a4ea61601d51cf1b070ce1e0742..a54f2c7495dacc5cd0964fba25e1fa2b89cc03fe 160000 --- a/vendor/hab/solr +++ b/vendor/hab/solr @@ -1 +1 @@ -Subproject commit f16f0026296c6a4ea61601d51cf1b070ce1e0742 +Subproject commit a54f2c7495dacc5cd0964fba25e1fa2b89cc03fe diff --git a/vendor/paragonie/random_compat/build-phar.sh b/vendor/paragonie/random_compat/build-phar.sh deleted file mode 100644 index b4a5ba31cc7bbd042027b4c111e224c4c99f4fc5..0000000000000000000000000000000000000000 --- a/vendor/paragonie/random_compat/build-phar.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/usr/bin/env bash - -basedir=$( dirname $( readlink -f ${BASH_SOURCE[0]} ) ) - -php -dphar.readonly=0 "$basedir/other/build_phar.php" $* \ No newline at end of file diff --git a/vendor/paragonie/random_compat/composer.json b/vendor/paragonie/random_compat/composer.json deleted file mode 100644 index 1c5978c6fbce9c3466a223748b85bc05a9682221..0000000000000000000000000000000000000000 --- a/vendor/paragonie/random_compat/composer.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "name": "paragonie/random_compat", - "description": "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7", - "keywords": [ - "csprng", - "random", - "pseudorandom" - ], - "license": "MIT", - "type": "library", - "authors": [ - { - "name": "Paragon Initiative Enterprises", - "email": "security@paragonie.com", - "homepage": "https://paragonie.com" - } - ], - "support": { - "issues": "https://github.com/paragonie/random_compat/issues", - "email": "info@paragonie.com", - "source": "https://github.com/paragonie/random_compat" - }, - "require": { - "php": ">=5.2.0" - }, - "require-dev": { - "phpunit/phpunit": "4.*|5.*" - }, - "suggest": { - "ext-libsodium": "Provides a modern crypto API that can be used to generate random bytes." - }, - "autoload": { - "files": [ - "lib/random.php" - ] - } -} diff --git a/vendor/paragonie/random_compat/dist/random_compat.phar.pubkey b/vendor/paragonie/random_compat/dist/random_compat.phar.pubkey deleted file mode 100644 index eb50ebfcd6d53169b6ddcf0013977f3ffa1542e8..0000000000000000000000000000000000000000 --- a/vendor/paragonie/random_compat/dist/random_compat.phar.pubkey +++ /dev/null @@ -1,5 +0,0 @@ ------BEGIN PUBLIC KEY----- -MHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEEd+wCqJDrx5B4OldM0dQE0ZMX+lx1ZWm -pui0SUqD4G29L3NGsz9UhJ/0HjBdbnkhIK5xviT0X5vtjacF6ajgcCArbTB+ds+p -+h7Q084NuSuIpNb6YPfoUFgC/CL9kAoc ------END PUBLIC KEY----- diff --git a/vendor/paragonie/random_compat/dist/random_compat.phar.pubkey.asc b/vendor/paragonie/random_compat/dist/random_compat.phar.pubkey.asc deleted file mode 100644 index 6a1d7f300675f3b42775d0b5aae49fc40768bc56..0000000000000000000000000000000000000000 --- a/vendor/paragonie/random_compat/dist/random_compat.phar.pubkey.asc +++ /dev/null @@ -1,11 +0,0 @@ ------BEGIN PGP SIGNATURE----- -Version: GnuPG v2.0.22 (MingW32) - -iQEcBAABAgAGBQJWtW1hAAoJEGuXocKCZATaJf0H+wbZGgskK1dcRTsuVJl9IWip -QwGw/qIKI280SD6/ckoUMxKDCJiFuPR14zmqnS36k7N5UNPnpdTJTS8T11jttSpg -1LCmgpbEIpgaTah+cELDqFCav99fS+bEiAL5lWDAHBTE/XPjGVCqeehyPYref4IW -NDBIEsvnHPHPLsn6X5jq4+Yj5oUixgxaMPiR+bcO4Sh+RzOVB6i2D0upWfRXBFXA -NNnsg9/zjvoC7ZW73y9uSH+dPJTt/Vgfeiv52/v41XliyzbUyLalf02GNPY+9goV -JHG1ulEEBJOCiUD9cE1PUIJwHA/HqyhHIvV350YoEFiHl8iSwm7SiZu5kPjaq74= -=B6+8 ------END PGP SIGNATURE----- diff --git a/vendor/paragonie/random_compat/lib/byte_safe_strings.php b/vendor/paragonie/random_compat/lib/byte_safe_strings.php deleted file mode 100644 index 3de86b223c5b130016dee7b84055d8a0f890ca7a..0000000000000000000000000000000000000000 --- a/vendor/paragonie/random_compat/lib/byte_safe_strings.php +++ /dev/null @@ -1,181 +0,0 @@ -<?php -/** - * Random_* Compatibility Library - * for using the new PHP 7 random_* API in PHP 5 projects - * - * The MIT License (MIT) - * - * Copyright (c) 2015 - 2017 Paragon Initiative Enterprises - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -if (!is_callable('RandomCompat_strlen')) { - if ( - defined('MB_OVERLOAD_STRING') && - ini_get('mbstring.func_overload') & MB_OVERLOAD_STRING - ) { - /** - * strlen() implementation that isn't brittle to mbstring.func_overload - * - * This version uses mb_strlen() in '8bit' mode to treat strings as raw - * binary rather than UTF-8, ISO-8859-1, etc - * - * @param string $binary_string - * - * @throws TypeError - * - * @return int - */ - function RandomCompat_strlen($binary_string) - { - if (!is_string($binary_string)) { - throw new TypeError( - 'RandomCompat_strlen() expects a string' - ); - } - - return (int) mb_strlen($binary_string, '8bit'); - } - - } else { - /** - * strlen() implementation that isn't brittle to mbstring.func_overload - * - * This version just used the default strlen() - * - * @param string $binary_string - * - * @throws TypeError - * - * @return int - */ - function RandomCompat_strlen($binary_string) - { - if (!is_string($binary_string)) { - throw new TypeError( - 'RandomCompat_strlen() expects a string' - ); - } - return (int) strlen($binary_string); - } - } -} - -if (!is_callable('RandomCompat_substr')) { - - if ( - defined('MB_OVERLOAD_STRING') - && - ini_get('mbstring.func_overload') & MB_OVERLOAD_STRING - ) { - /** - * substr() implementation that isn't brittle to mbstring.func_overload - * - * This version uses mb_substr() in '8bit' mode to treat strings as raw - * binary rather than UTF-8, ISO-8859-1, etc - * - * @param string $binary_string - * @param int $start - * @param int $length (optional) - * - * @throws TypeError - * - * @return string - */ - function RandomCompat_substr($binary_string, $start, $length = null) - { - if (!is_string($binary_string)) { - throw new TypeError( - 'RandomCompat_substr(): First argument should be a string' - ); - } - - if (!is_int($start)) { - throw new TypeError( - 'RandomCompat_substr(): Second argument should be an integer' - ); - } - - if ($length === null) { - /** - * mb_substr($str, 0, NULL, '8bit') returns an empty string on - * PHP 5.3, so we have to find the length ourselves. - */ - $length = RandomCompat_strlen($binary_string) - $start; - } elseif (!is_int($length)) { - throw new TypeError( - 'RandomCompat_substr(): Third argument should be an integer, or omitted' - ); - } - - // Consistency with PHP's behavior - if ($start === RandomCompat_strlen($binary_string) && $length === 0) { - return ''; - } - if ($start > RandomCompat_strlen($binary_string)) { - return ''; - } - - return (string) mb_substr($binary_string, $start, $length, '8bit'); - } - - } else { - - /** - * substr() implementation that isn't brittle to mbstring.func_overload - * - * This version just uses the default substr() - * - * @param string $binary_string - * @param int $start - * @param int $length (optional) - * - * @throws TypeError - * - * @return string - */ - function RandomCompat_substr($binary_string, $start, $length = null) - { - if (!is_string($binary_string)) { - throw new TypeError( - 'RandomCompat_substr(): First argument should be a string' - ); - } - - if (!is_int($start)) { - throw new TypeError( - 'RandomCompat_substr(): Second argument should be an integer' - ); - } - - if ($length !== null) { - if (!is_int($length)) { - throw new TypeError( - 'RandomCompat_substr(): Third argument should be an integer, or omitted' - ); - } - - return (string) substr($binary_string, $start, $length); - } - - return (string) substr($binary_string, $start); - } - } -} diff --git a/vendor/paragonie/random_compat/lib/cast_to_int.php b/vendor/paragonie/random_compat/lib/cast_to_int.php deleted file mode 100644 index 9a4fab99197125859b0c08484c1fe0abb284ad9d..0000000000000000000000000000000000000000 --- a/vendor/paragonie/random_compat/lib/cast_to_int.php +++ /dev/null @@ -1,75 +0,0 @@ -<?php -/** - * Random_* Compatibility Library - * for using the new PHP 7 random_* API in PHP 5 projects - * - * The MIT License (MIT) - * - * Copyright (c) 2015 - 2017 Paragon Initiative Enterprises - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -if (!is_callable('RandomCompat_intval')) { - - /** - * Cast to an integer if we can, safely. - * - * If you pass it a float in the range (~PHP_INT_MAX, PHP_INT_MAX) - * (non-inclusive), it will sanely cast it to an int. If you it's equal to - * ~PHP_INT_MAX or PHP_INT_MAX, we let it fail as not an integer. Floats - * lose precision, so the <= and => operators might accidentally let a float - * through. - * - * @param int|float $number The number we want to convert to an int - * @param bool $fail_open Set to true to not throw an exception - * - * @return float|int - * @psalm-suppress InvalidReturnType - * - * @throws TypeError - */ - function RandomCompat_intval($number, $fail_open = false) - { - if (is_int($number) || is_float($number)) { - $number += 0; - } elseif (is_numeric($number)) { - $number += 0; - } - - if ( - is_float($number) - && - $number > ~PHP_INT_MAX - && - $number < PHP_INT_MAX - ) { - $number = (int) $number; - } - - if (is_int($number)) { - return (int) $number; - } elseif (!$fail_open) { - throw new TypeError( - 'Expected an integer.' - ); - } - return $number; - } -} diff --git a/vendor/paragonie/random_compat/lib/error_polyfill.php b/vendor/paragonie/random_compat/lib/error_polyfill.php deleted file mode 100644 index 6a91990ce6b7c13e98826257a31eb113ce7c5afc..0000000000000000000000000000000000000000 --- a/vendor/paragonie/random_compat/lib/error_polyfill.php +++ /dev/null @@ -1,49 +0,0 @@ -<?php -/** - * Random_* Compatibility Library - * for using the new PHP 7 random_* API in PHP 5 projects - * - * The MIT License (MIT) - * - * Copyright (c) 2015 - 2017 Paragon Initiative Enterprises - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -if (!class_exists('Error', false)) { - // We can't really avoid making this extend Exception in PHP 5. - class Error extends Exception - { - - } -} - -if (!class_exists('TypeError', false)) { - if (is_subclass_of('Error', 'Exception')) { - class TypeError extends Error - { - - } - } else { - class TypeError extends Exception - { - - } - } -} diff --git a/vendor/paragonie/random_compat/lib/random.php b/vendor/paragonie/random_compat/lib/random.php deleted file mode 100644 index df74c8a4b624fa410ec45c5e8f1678cdc73f33a0..0000000000000000000000000000000000000000 --- a/vendor/paragonie/random_compat/lib/random.php +++ /dev/null @@ -1,223 +0,0 @@ -<?php -/** - * Random_* Compatibility Library - * for using the new PHP 7 random_* API in PHP 5 projects - * - * @version 2.0.10 - * @released 2017-03-13 - * - * The MIT License (MIT) - * - * Copyright (c) 2015 - 2017 Paragon Initiative Enterprises - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -if (!defined('PHP_VERSION_ID')) { - // This constant was introduced in PHP 5.2.7 - $RandomCompatversion = array_map('intval', explode('.', PHP_VERSION)); - define( - 'PHP_VERSION_ID', - $RandomCompatversion[0] * 10000 - + $RandomCompatversion[1] * 100 - + $RandomCompatversion[2] - ); - $RandomCompatversion = null; -} - -/** - * PHP 7.0.0 and newer have these functions natively. - */ -if (PHP_VERSION_ID >= 70000) { - return; -} - -if (!defined('RANDOM_COMPAT_READ_BUFFER')) { - define('RANDOM_COMPAT_READ_BUFFER', 8); -} - -$RandomCompatDIR = dirname(__FILE__); - -require_once $RandomCompatDIR . '/byte_safe_strings.php'; -require_once $RandomCompatDIR . '/cast_to_int.php'; -require_once $RandomCompatDIR . '/error_polyfill.php'; - -if (!is_callable('random_bytes')) { - /** - * PHP 5.2.0 - 5.6.x way to implement random_bytes() - * - * We use conditional statements here to define the function in accordance - * to the operating environment. It's a micro-optimization. - * - * In order of preference: - * 1. Use libsodium if available. - * 2. fread() /dev/urandom if available (never on Windows) - * 3. mcrypt_create_iv($bytes, MCRYPT_DEV_URANDOM) - * 4. COM('CAPICOM.Utilities.1')->GetRandom() - * - * See RATIONALE.md for our reasoning behind this particular order - */ - if (extension_loaded('libsodium')) { - // See random_bytes_libsodium.php - if (PHP_VERSION_ID >= 50300 && is_callable('\\Sodium\\randombytes_buf')) { - require_once $RandomCompatDIR . '/random_bytes_libsodium.php'; - } elseif (method_exists('Sodium', 'randombytes_buf')) { - require_once $RandomCompatDIR . '/random_bytes_libsodium_legacy.php'; - } - } - - /** - * Reading directly from /dev/urandom: - */ - if (DIRECTORY_SEPARATOR === '/') { - // DIRECTORY_SEPARATOR === '/' on Unix-like OSes -- this is a fast - // way to exclude Windows. - $RandomCompatUrandom = true; - $RandomCompat_basedir = ini_get('open_basedir'); - - if (!empty($RandomCompat_basedir)) { - $RandomCompat_open_basedir = explode( - PATH_SEPARATOR, - strtolower($RandomCompat_basedir) - ); - $RandomCompatUrandom = (array() !== array_intersect( - array('/dev', '/dev/', '/dev/urandom'), - $RandomCompat_open_basedir - )); - $RandomCompat_open_basedir = null; - } - - if ( - !is_callable('random_bytes') - && - $RandomCompatUrandom - && - @is_readable('/dev/urandom') - ) { - // Error suppression on is_readable() in case of an open_basedir - // or safe_mode failure. All we care about is whether or not we - // can read it at this point. If the PHP environment is going to - // panic over trying to see if the file can be read in the first - // place, that is not helpful to us here. - - // See random_bytes_dev_urandom.php - require_once $RandomCompatDIR . '/random_bytes_dev_urandom.php'; - } - // Unset variables after use - $RandomCompat_basedir = null; - } else { - $RandomCompatUrandom = false; - } - - /** - * mcrypt_create_iv() - * - * We only want to use mcypt_create_iv() if: - * - * - random_bytes() hasn't already been defined - * - the mcrypt extensions is loaded - * - One of these two conditions is true: - * - We're on Windows (DIRECTORY_SEPARATOR !== '/') - * - We're not on Windows and /dev/urandom is readabale - * (i.e. we're not in a chroot jail) - * - Special case: - * - If we're not on Windows, but the PHP version is between - * 5.6.10 and 5.6.12, we don't want to use mcrypt. It will - * hang indefinitely. This is bad. - * - If we're on Windows, we want to use PHP >= 5.3.7 or else - * we get insufficient entropy errors. - */ - if ( - !is_callable('random_bytes') - && - // Windows on PHP < 5.3.7 is broken, but non-Windows is not known to be. - (DIRECTORY_SEPARATOR === '/' || PHP_VERSION_ID >= 50307) - && - // Prevent this code from hanging indefinitely on non-Windows; - // see https://bugs.php.net/bug.php?id=69833 - ( - DIRECTORY_SEPARATOR !== '/' || - (PHP_VERSION_ID <= 50609 || PHP_VERSION_ID >= 50613) - ) - && - extension_loaded('mcrypt') - ) { - // See random_bytes_mcrypt.php - require_once $RandomCompatDIR . '/random_bytes_mcrypt.php'; - } - $RandomCompatUrandom = null; - - /** - * This is a Windows-specific fallback, for when the mcrypt extension - * isn't loaded. - */ - if ( - !is_callable('random_bytes') - && - extension_loaded('com_dotnet') - && - class_exists('COM') - ) { - $RandomCompat_disabled_classes = preg_split( - '#\s*,\s*#', - strtolower(ini_get('disable_classes')) - ); - - if (!in_array('com', $RandomCompat_disabled_classes)) { - try { - $RandomCompatCOMtest = new COM('CAPICOM.Utilities.1'); - if (method_exists($RandomCompatCOMtest, 'GetRandom')) { - // See random_bytes_com_dotnet.php - require_once $RandomCompatDIR . '/random_bytes_com_dotnet.php'; - } - } catch (com_exception $e) { - // Don't try to use it. - } - } - $RandomCompat_disabled_classes = null; - $RandomCompatCOMtest = null; - } - - /** - * throw new Exception - */ - if (!is_callable('random_bytes')) { - /** - * We don't have any more options, so let's throw an exception right now - * and hope the developer won't let it fail silently. - * - * @param mixed $length - * @return void - * @throws Exception - */ - function random_bytes($length) - { - unset($length); // Suppress "variable not used" warnings. - throw new Exception( - 'There is no suitable CSPRNG installed on your system' - ); - } - } -} - -if (!is_callable('random_int')) { - require_once $RandomCompatDIR . '/random_int.php'; -} - -$RandomCompatDIR = null; diff --git a/vendor/paragonie/random_compat/lib/random_bytes_com_dotnet.php b/vendor/paragonie/random_compat/lib/random_bytes_com_dotnet.php deleted file mode 100644 index fc1926e5cac064e4f8d6190338ea3857cffa0cdf..0000000000000000000000000000000000000000 --- a/vendor/paragonie/random_compat/lib/random_bytes_com_dotnet.php +++ /dev/null @@ -1,88 +0,0 @@ -<?php -/** - * Random_* Compatibility Library - * for using the new PHP 7 random_* API in PHP 5 projects - * - * The MIT License (MIT) - * - * Copyright (c) 2015 - 2017 Paragon Initiative Enterprises - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -if (!is_callable('random_bytes')) { - /** - * Windows with PHP < 5.3.0 will not have the function - * openssl_random_pseudo_bytes() available, so let's use - * CAPICOM to work around this deficiency. - * - * @param int $bytes - * - * @throws Exception - * - * @return string - */ - function random_bytes($bytes) - { - try { - $bytes = RandomCompat_intval($bytes); - } catch (TypeError $ex) { - throw new TypeError( - 'random_bytes(): $bytes must be an integer' - ); - } - - if ($bytes < 1) { - throw new Error( - 'Length must be greater than 0' - ); - } - - $buf = ''; - if (!class_exists('COM')) { - throw new Error( - 'COM does not exist' - ); - } - $util = new COM('CAPICOM.Utilities.1'); - $execCount = 0; - - /** - * Let's not let it loop forever. If we run N times and fail to - * get N bytes of random data, then CAPICOM has failed us. - */ - do { - $buf .= base64_decode($util->GetRandom($bytes, 0)); - if (RandomCompat_strlen($buf) >= $bytes) { - /** - * Return our random entropy buffer here: - */ - return RandomCompat_substr($buf, 0, $bytes); - } - ++$execCount; - } while ($execCount < $bytes); - - /** - * If we reach here, PHP has failed us. - */ - throw new Exception( - 'Could not gather sufficient random data' - ); - } -} \ No newline at end of file diff --git a/vendor/paragonie/random_compat/lib/random_bytes_dev_urandom.php b/vendor/paragonie/random_compat/lib/random_bytes_dev_urandom.php deleted file mode 100644 index df5b91524e893831af5598318e89cd8ee0c5876f..0000000000000000000000000000000000000000 --- a/vendor/paragonie/random_compat/lib/random_bytes_dev_urandom.php +++ /dev/null @@ -1,167 +0,0 @@ -<?php -/** - * Random_* Compatibility Library - * for using the new PHP 7 random_* API in PHP 5 projects - * - * The MIT License (MIT) - * - * Copyright (c) 2015 - 2017 Paragon Initiative Enterprises - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -if (!defined('RANDOM_COMPAT_READ_BUFFER')) { - define('RANDOM_COMPAT_READ_BUFFER', 8); -} - -if (!is_callable('random_bytes')) { - /** - * Unless open_basedir is enabled, use /dev/urandom for - * random numbers in accordance with best practices - * - * Why we use /dev/urandom and not /dev/random - * @ref http://sockpuppet.org/blog/2014/02/25/safely-generate-random-numbers - * - * @param int $bytes - * - * @throws Exception - * - * @return string - */ - function random_bytes($bytes) - { - static $fp = null; - /** - * This block should only be run once - */ - if (empty($fp)) { - /** - * We use /dev/urandom if it is a char device. - * We never fall back to /dev/random - */ - $fp = fopen('/dev/urandom', 'rb'); - if (!empty($fp)) { - $st = fstat($fp); - if (($st['mode'] & 0170000) !== 020000) { - fclose($fp); - $fp = false; - } - } - - if (!empty($fp)) { - /** - * stream_set_read_buffer() does not exist in HHVM - * - * If we don't set the stream's read buffer to 0, PHP will - * internally buffer 8192 bytes, which can waste entropy - * - * stream_set_read_buffer returns 0 on success - */ - if (is_callable('stream_set_read_buffer')) { - stream_set_read_buffer($fp, RANDOM_COMPAT_READ_BUFFER); - } - if (is_callable('stream_set_chunk_size')) { - stream_set_chunk_size($fp, RANDOM_COMPAT_READ_BUFFER); - } - } - } - - try { - $bytes = RandomCompat_intval($bytes); - } catch (TypeError $ex) { - throw new TypeError( - 'random_bytes(): $bytes must be an integer' - ); - } - - if ($bytes < 1) { - throw new Error( - 'Length must be greater than 0' - ); - } - - /** - * This if() block only runs if we managed to open a file handle - * - * It does not belong in an else {} block, because the above - * if (empty($fp)) line is logic that should only be run once per - * page load. - */ - if (!empty($fp)) { - /** - * @var int - */ - $remaining = $bytes; - - /** - * @var string|bool - */ - $buf = ''; - - /** - * We use fread() in a loop to protect against partial reads - */ - do { - /** - * @var string|bool - */ - $read = fread($fp, $remaining); - if (!is_string($read)) { - if ($read === false) { - /** - * We cannot safely read from the file. Exit the - * do-while loop and trigger the exception condition - * - * @var string|bool - */ - $buf = false; - break; - } - } - /** - * Decrease the number of bytes returned from remaining - */ - $remaining -= RandomCompat_strlen($read); - /** - * @var string|bool - */ - $buf = $buf . $read; - } while ($remaining > 0); - - /** - * Is our result valid? - */ - if (is_string($buf)) { - if (RandomCompat_strlen($buf) === $bytes) { - /** - * Return our random entropy buffer here: - */ - return $buf; - } - } - } - - /** - * If we reach here, PHP has failed us. - */ - throw new Exception( - 'Error reading from source device' - ); - } -} diff --git a/vendor/paragonie/random_compat/lib/random_bytes_libsodium.php b/vendor/paragonie/random_compat/lib/random_bytes_libsodium.php deleted file mode 100644 index 4af1a242279f7e2f759f13e4d45336d1e2889b9c..0000000000000000000000000000000000000000 --- a/vendor/paragonie/random_compat/lib/random_bytes_libsodium.php +++ /dev/null @@ -1,88 +0,0 @@ -<?php -/** - * Random_* Compatibility Library - * for using the new PHP 7 random_* API in PHP 5 projects - * - * The MIT License (MIT) - * - * Copyright (c) 2015 - 2017 Paragon Initiative Enterprises - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -if (!is_callable('random_bytes')) { - /** - * If the libsodium PHP extension is loaded, we'll use it above any other - * solution. - * - * libsodium-php project: - * @ref https://github.com/jedisct1/libsodium-php - * - * @param int $bytes - * - * @throws Exception - * - * @return string - */ - function random_bytes($bytes) - { - try { - $bytes = RandomCompat_intval($bytes); - } catch (TypeError $ex) { - throw new TypeError( - 'random_bytes(): $bytes must be an integer' - ); - } - - if ($bytes < 1) { - throw new Error( - 'Length must be greater than 0' - ); - } - - /** - * \Sodium\randombytes_buf() doesn't allow more than 2147483647 bytes to be - * generated in one invocation. - */ - if ($bytes > 2147483647) { - $buf = ''; - for ($i = 0; $i < $bytes; $i += 1073741824) { - $n = ($bytes - $i) > 1073741824 - ? 1073741824 - : $bytes - $i; - $buf .= \Sodium\randombytes_buf($n); - } - } else { - $buf = \Sodium\randombytes_buf($bytes); - } - - if ($buf !== false) { - if (RandomCompat_strlen($buf) === $bytes) { - return $buf; - } - } - - /** - * If we reach here, PHP has failed us. - */ - throw new Exception( - 'Could not gather sufficient random data' - ); - } -} diff --git a/vendor/paragonie/random_compat/lib/random_bytes_libsodium_legacy.php b/vendor/paragonie/random_compat/lib/random_bytes_libsodium_legacy.php deleted file mode 100644 index 705af5262bde0e092ca26aff660ae38b8a6e3e87..0000000000000000000000000000000000000000 --- a/vendor/paragonie/random_compat/lib/random_bytes_libsodium_legacy.php +++ /dev/null @@ -1,92 +0,0 @@ -<?php -/** - * Random_* Compatibility Library - * for using the new PHP 7 random_* API in PHP 5 projects - * - * The MIT License (MIT) - * - * Copyright (c) 2015 - 2017 Paragon Initiative Enterprises - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -if (!is_callable('random_bytes')) { - /** - * If the libsodium PHP extension is loaded, we'll use it above any other - * solution. - * - * libsodium-php project: - * @ref https://github.com/jedisct1/libsodium-php - * - * @param int $bytes - * - * @throws Exception - * - * @return string - */ - function random_bytes($bytes) - { - try { - $bytes = RandomCompat_intval($bytes); - } catch (TypeError $ex) { - throw new TypeError( - 'random_bytes(): $bytes must be an integer' - ); - } - - if ($bytes < 1) { - throw new Error( - 'Length must be greater than 0' - ); - } - - /** - * @var string - */ - $buf = ''; - - /** - * \Sodium\randombytes_buf() doesn't allow more than 2147483647 bytes to be - * generated in one invocation. - */ - if ($bytes > 2147483647) { - for ($i = 0; $i < $bytes; $i += 1073741824) { - $n = ($bytes - $i) > 1073741824 - ? 1073741824 - : $bytes - $i; - $buf .= Sodium::randombytes_buf((int) $n); - } - } else { - $buf .= Sodium::randombytes_buf((int) $bytes); - } - - if (is_string($buf)) { - if (RandomCompat_strlen($buf) === $bytes) { - return $buf; - } - } - - /** - * If we reach here, PHP has failed us. - */ - throw new Exception( - 'Could not gather sufficient random data' - ); - } -} diff --git a/vendor/paragonie/random_compat/lib/random_bytes_mcrypt.php b/vendor/paragonie/random_compat/lib/random_bytes_mcrypt.php deleted file mode 100644 index aac9c013d4d71037eca77fce585efad4e14d84dc..0000000000000000000000000000000000000000 --- a/vendor/paragonie/random_compat/lib/random_bytes_mcrypt.php +++ /dev/null @@ -1,77 +0,0 @@ -<?php -/** - * Random_* Compatibility Library - * for using the new PHP 7 random_* API in PHP 5 projects - * - * The MIT License (MIT) - * - * Copyright (c) 2015 - 2017 Paragon Initiative Enterprises - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -if (!is_callable('random_bytes')) { - /** - * Powered by ext/mcrypt (and thankfully NOT libmcrypt) - * - * @ref https://bugs.php.net/bug.php?id=55169 - * @ref https://github.com/php/php-src/blob/c568ffe5171d942161fc8dda066bce844bdef676/ext/mcrypt/mcrypt.c#L1321-L1386 - * - * @param int $bytes - * - * @throws Exception - * - * @return string - */ - function random_bytes($bytes) - { - try { - $bytes = RandomCompat_intval($bytes); - } catch (TypeError $ex) { - throw new TypeError( - 'random_bytes(): $bytes must be an integer' - ); - } - - if ($bytes < 1) { - throw new Error( - 'Length must be greater than 0' - ); - } - - $buf = @mcrypt_create_iv($bytes, MCRYPT_DEV_URANDOM); - if ( - $buf !== false - && - RandomCompat_strlen($buf) === $bytes - ) { - /** - * Return our random entropy buffer here: - */ - return $buf; - } - - /** - * If we reach here, PHP has failed us. - */ - throw new Exception( - 'Could not gather sufficient random data' - ); - } -} diff --git a/vendor/paragonie/random_compat/lib/random_int.php b/vendor/paragonie/random_compat/lib/random_int.php deleted file mode 100644 index 5b2143a16297a5ee79ba48f997ef2f39e5d97696..0000000000000000000000000000000000000000 --- a/vendor/paragonie/random_compat/lib/random_int.php +++ /dev/null @@ -1,190 +0,0 @@ -<?php - -if (!is_callable('random_int')) { - /** - * Random_* Compatibility Library - * for using the new PHP 7 random_* API in PHP 5 projects - * - * The MIT License (MIT) - * - * Copyright (c) 2015 - 2017 Paragon Initiative Enterprises - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - - /** - * Fetch a random integer between $min and $max inclusive - * - * @param int $min - * @param int $max - * - * @throws Exception - * - * @return int - */ - function random_int($min, $max) - { - /** - * Type and input logic checks - * - * If you pass it a float in the range (~PHP_INT_MAX, PHP_INT_MAX) - * (non-inclusive), it will sanely cast it to an int. If you it's equal to - * ~PHP_INT_MAX or PHP_INT_MAX, we let it fail as not an integer. Floats - * lose precision, so the <= and => operators might accidentally let a float - * through. - */ - - try { - $min = RandomCompat_intval($min); - } catch (TypeError $ex) { - throw new TypeError( - 'random_int(): $min must be an integer' - ); - } - - try { - $max = RandomCompat_intval($max); - } catch (TypeError $ex) { - throw new TypeError( - 'random_int(): $max must be an integer' - ); - } - - /** - * Now that we've verified our weak typing system has given us an integer, - * let's validate the logic then we can move forward with generating random - * integers along a given range. - */ - if ($min > $max) { - throw new Error( - 'Minimum value must be less than or equal to the maximum value' - ); - } - - if ($max === $min) { - return (int) $min; - } - - /** - * Initialize variables to 0 - * - * We want to store: - * $bytes => the number of random bytes we need - * $mask => an integer bitmask (for use with the &) operator - * so we can minimize the number of discards - */ - $attempts = $bits = $bytes = $mask = $valueShift = 0; - - /** - * At this point, $range is a positive number greater than 0. It might - * overflow, however, if $max - $min > PHP_INT_MAX. PHP will cast it to - * a float and we will lose some precision. - */ - $range = $max - $min; - - /** - * Test for integer overflow: - */ - if (!is_int($range)) { - - /** - * Still safely calculate wider ranges. - * Provided by @CodesInChaos, @oittaa - * - * @ref https://gist.github.com/CodesInChaos/03f9ea0b58e8b2b8d435 - * - * We use ~0 as a mask in this case because it generates all 1s - * - * @ref https://eval.in/400356 (32-bit) - * @ref http://3v4l.org/XX9r5 (64-bit) - */ - $bytes = PHP_INT_SIZE; - $mask = ~0; - - } else { - - /** - * $bits is effectively ceil(log($range, 2)) without dealing with - * type juggling - */ - while ($range > 0) { - if ($bits % 8 === 0) { - ++$bytes; - } - ++$bits; - $range >>= 1; - $mask = $mask << 1 | 1; - } - $valueShift = $min; - } - - $val = 0; - /** - * Now that we have our parameters set up, let's begin generating - * random integers until one falls between $min and $max - */ - do { - /** - * The rejection probability is at most 0.5, so this corresponds - * to a failure probability of 2^-128 for a working RNG - */ - if ($attempts > 128) { - throw new Exception( - 'random_int: RNG is broken - too many rejections' - ); - } - - /** - * Let's grab the necessary number of random bytes - */ - $randomByteString = random_bytes($bytes); - - /** - * Let's turn $randomByteString into an integer - * - * This uses bitwise operators (<< and |) to build an integer - * out of the values extracted from ord() - * - * Example: [9F] | [6D] | [32] | [0C] => - * 159 + 27904 + 3276800 + 201326592 => - * 204631455 - */ - $val &= 0; - for ($i = 0; $i < $bytes; ++$i) { - $val |= ord($randomByteString[$i]) << ($i * 8); - } - - /** - * Apply mask - */ - $val &= $mask; - $val += $valueShift; - - ++$attempts; - /** - * If $val overflows to a floating point number, - * ... or is larger than $max, - * ... or smaller than $min, - * then try again. - */ - } while (!is_int($val) || $val > $max || $val < $min); - - return (int) $val; - } -} diff --git a/vendor/paragonie/random_compat/other/build_phar.php b/vendor/paragonie/random_compat/other/build_phar.php deleted file mode 100644 index 70ef4b2ed838a6bf32d64e3da4c26f9d367e6ab5..0000000000000000000000000000000000000000 --- a/vendor/paragonie/random_compat/other/build_phar.php +++ /dev/null @@ -1,57 +0,0 @@ -<?php -$dist = dirname(__DIR__).'/dist'; -if (!is_dir($dist)) { - mkdir($dist, 0755); -} -if (file_exists($dist.'/random_compat.phar')) { - unlink($dist.'/random_compat.phar'); -} -$phar = new Phar( - $dist.'/random_compat.phar', - FilesystemIterator::CURRENT_AS_FILEINFO | \FilesystemIterator::KEY_AS_FILENAME, - 'random_compat.phar' -); -rename( - dirname(__DIR__).'/lib/random.php', - dirname(__DIR__).'/lib/index.php' -); -$phar->buildFromDirectory(dirname(__DIR__).'/lib'); -rename( - dirname(__DIR__).'/lib/index.php', - dirname(__DIR__).'/lib/random.php' -); - -/** - * If we pass an (optional) path to a private key as a second argument, we will - * sign the Phar with OpenSSL. - * - * If you leave this out, it will produce an unsigned .phar! - */ -if ($argc > 1) { - if (!@is_readable($argv[1])) { - echo 'Could not read the private key file:', $argv[1], "\n"; - exit(255); - } - $pkeyFile = file_get_contents($argv[1]); - - $private = openssl_get_privatekey($pkeyFile); - if ($private !== false) { - $pkey = ''; - openssl_pkey_export($private, $pkey); - $phar->setSignatureAlgorithm(Phar::OPENSSL, $pkey); - - /** - * Save the corresponding public key to the file - */ - if (!@is_readable($dist.'/random_compat.phar.pubkey')) { - $details = openssl_pkey_get_details($private); - file_put_contents( - $dist.'/random_compat.phar.pubkey', - $details['key'] - ); - } - } else { - echo 'An error occurred reading the private key from OpenSSL.', "\n"; - exit(255); - } -} diff --git a/vendor/paragonie/random_compat/psalm-autoload.php b/vendor/paragonie/random_compat/psalm-autoload.php deleted file mode 100644 index d71d1b818c311072207e3ee4abff9f82a10d2fa9..0000000000000000000000000000000000000000 --- a/vendor/paragonie/random_compat/psalm-autoload.php +++ /dev/null @@ -1,9 +0,0 @@ -<?php - -require_once 'lib/byte_safe_strings.php'; -require_once 'lib/cast_to_int.php'; -require_once 'lib/error_polyfill.php'; -require_once 'other/ide_stubs/libsodium.php'; -require_once 'lib/random.php'; - -$int = random_int(0, 65536); diff --git a/vendor/paragonie/random_compat/psalm.xml b/vendor/paragonie/random_compat/psalm.xml deleted file mode 100644 index 1e91409894aee32a49ef399b0ce6bdd40a93682a..0000000000000000000000000000000000000000 --- a/vendor/paragonie/random_compat/psalm.xml +++ /dev/null @@ -1,16 +0,0 @@ -<?xml version="1.0"?> -<psalm - autoloader="psalm-autoload.php" - stopOnFirstError="false" - useDocblockTypes="true" -> - <projectFiles> - <directory name="lib" /> - </projectFiles> - <issueHandlers> - <DuplicateClass errorLevel="info" /> - <InvalidOperand errorLevel="info" /> - <UndefinedConstant errorLevel="info" /> - <MissingReturnType errorLevel="info" /> - </issueHandlers> -</psalm> diff --git a/vendor/psr/log/Psr/Log/Test/LoggerInterfaceTest.php b/vendor/psr/log/Psr/Log/Test/LoggerInterfaceTest.php index a0391a52b8fc10b727c2258a19520c65791fc1ae..4b861c3ef6c31bf99c0fc78d0fc2fbc2711d88aa 100644 --- a/vendor/psr/log/Psr/Log/Test/LoggerInterfaceTest.php +++ b/vendor/psr/log/Psr/Log/Test/LoggerInterfaceTest.php @@ -101,6 +101,9 @@ abstract class LoggerInterfaceTest extends \PHPUnit_Framework_TestCase public function testContextCanContainAnything() { + $closed = fopen('php://memory', 'r'); + fclose($closed); + $context = array( 'bool' => true, 'null' => null, @@ -110,6 +113,7 @@ abstract class LoggerInterfaceTest extends \PHPUnit_Framework_TestCase 'nested' => array('with object' => new DummyTest), 'object' => new \DateTime, 'resource' => fopen('php://memory', 'r'), + 'closed' => $closed, ); $this->getLogger()->warning('Crazy context data', $context); diff --git a/vendor/psr/log/Psr/Log/Test/TestLogger.php b/vendor/psr/log/Psr/Log/Test/TestLogger.php new file mode 100644 index 0000000000000000000000000000000000000000..0cdffe4f9263b98f870b9615c07b005f54b14ca7 --- /dev/null +++ b/vendor/psr/log/Psr/Log/Test/TestLogger.php @@ -0,0 +1,146 @@ +<?php + +namespace Psr\Log\Test; + +use Psr\Log\AbstractLogger; + +/** + * Used for testing purposes. + * + * It records all records and gives you access to them for verification. + * + * @method bool hasEmergency($record) + * @method bool hasAlert($record) + * @method bool hasCritical($record) + * @method bool hasError($record) + * @method bool hasWarning($record) + * @method bool hasNotice($record) + * @method bool hasInfo($record) + * @method bool hasDebug($record) + * + * @method bool hasEmergencyRecords() + * @method bool hasAlertRecords() + * @method bool hasCriticalRecords() + * @method bool hasErrorRecords() + * @method bool hasWarningRecords() + * @method bool hasNoticeRecords() + * @method bool hasInfoRecords() + * @method bool hasDebugRecords() + * + * @method bool hasEmergencyThatContains($message) + * @method bool hasAlertThatContains($message) + * @method bool hasCriticalThatContains($message) + * @method bool hasErrorThatContains($message) + * @method bool hasWarningThatContains($message) + * @method bool hasNoticeThatContains($message) + * @method bool hasInfoThatContains($message) + * @method bool hasDebugThatContains($message) + * + * @method bool hasEmergencyThatMatches($message) + * @method bool hasAlertThatMatches($message) + * @method bool hasCriticalThatMatches($message) + * @method bool hasErrorThatMatches($message) + * @method bool hasWarningThatMatches($message) + * @method bool hasNoticeThatMatches($message) + * @method bool hasInfoThatMatches($message) + * @method bool hasDebugThatMatches($message) + * + * @method bool hasEmergencyThatPasses($message) + * @method bool hasAlertThatPasses($message) + * @method bool hasCriticalThatPasses($message) + * @method bool hasErrorThatPasses($message) + * @method bool hasWarningThatPasses($message) + * @method bool hasNoticeThatPasses($message) + * @method bool hasInfoThatPasses($message) + * @method bool hasDebugThatPasses($message) + */ +class TestLogger extends AbstractLogger +{ + /** + * @var array + */ + public $records = []; + + public $recordsByLevel = []; + + /** + * @inheritdoc + */ + public function log($level, $message, array $context = []) + { + $record = [ + 'level' => $level, + 'message' => $message, + 'context' => $context, + ]; + + $this->recordsByLevel[$record['level']][] = $record; + $this->records[] = $record; + } + + public function hasRecords($level) + { + return isset($this->recordsByLevel[$level]); + } + + public function hasRecord($record, $level) + { + if (is_string($record)) { + $record = ['message' => $record]; + } + return $this->hasRecordThatPasses(function ($rec) use ($record) { + if ($rec['message'] !== $record['message']) { + return false; + } + if (isset($record['context']) && $rec['context'] !== $record['context']) { + return false; + } + return true; + }, $level); + } + + public function hasRecordThatContains($message, $level) + { + return $this->hasRecordThatPasses(function ($rec) use ($message) { + return strpos($rec['message'], $message) !== false; + }, $level); + } + + public function hasRecordThatMatches($regex, $level) + { + return $this->hasRecordThatPasses(function ($rec) use ($regex) { + return preg_match($regex, $rec['message']) > 0; + }, $level); + } + + public function hasRecordThatPasses(callable $predicate, $level) + { + if (!isset($this->recordsByLevel[$level])) { + return false; + } + foreach ($this->recordsByLevel[$level] as $i => $rec) { + if (call_user_func($predicate, $rec, $i)) { + return true; + } + } + return false; + } + + public function __call($method, $args) + { + if (preg_match('/(.*)(Debug|Info|Notice|Warning|Error|Critical|Alert|Emergency)(.*)/', $method, $matches) > 0) { + $genericMethod = $matches[1] . ('Records' !== $matches[3] ? 'Record' : '') . $matches[3]; + $level = strtolower($matches[2]); + if (method_exists($this, $genericMethod)) { + $args[] = $level; + return call_user_func_array([$this, $genericMethod], $args); + } + } + throw new \BadMethodCallException('Call to undefined method ' . get_class($this) . '::' . $method . '()'); + } + + public function reset() + { + $this->records = []; + } +} diff --git a/vendor/psr/log/README.md b/vendor/psr/log/README.md index 574bc1cb2a82ffa07bcc2f7ffee3656eb086ba29..5571a25e8df01732f1b7141b3ccc6835b3bb429c 100644 --- a/vendor/psr/log/README.md +++ b/vendor/psr/log/README.md @@ -7,6 +7,13 @@ This repository holds all interfaces/classes/traits related to Note that this is not a logger of its own. It is merely an interface that describes a logger. See the specification for more details. +Installation +------------ + +```bash +composer require psr/log +``` + Usage ----- diff --git a/vendor/paragonie/random_compat/LICENSE b/vendor/ralouphie/getallheaders/LICENSE similarity index 95% rename from vendor/paragonie/random_compat/LICENSE rename to vendor/ralouphie/getallheaders/LICENSE index 45c7017dfb33dd003ee038cc9232d2430ffbf9a2..be5540c2af759b6e32172cbdcda5ccdf58816f2a 100644 --- a/vendor/paragonie/random_compat/LICENSE +++ b/vendor/ralouphie/getallheaders/LICENSE @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2015 Paragon Initiative Enterprises +Copyright (c) 2014 Ralph Khattar Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal @@ -19,4 +19,3 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - diff --git a/vendor/ralouphie/getallheaders/README.md b/vendor/ralouphie/getallheaders/README.md new file mode 100644 index 0000000000000000000000000000000000000000..9430d76bbc2ff17f6626b7da94c6588fc8bc4c12 --- /dev/null +++ b/vendor/ralouphie/getallheaders/README.md @@ -0,0 +1,27 @@ +getallheaders +============= + +PHP `getallheaders()` polyfill. Compatible with PHP >= 5.3. + +[](https://travis-ci.org/ralouphie/getallheaders) +[](https://coveralls.io/r/ralouphie/getallheaders?branch=master) +[](https://packagist.org/packages/ralouphie/getallheaders) +[](https://packagist.org/packages/ralouphie/getallheaders) +[](https://packagist.org/packages/ralouphie/getallheaders) + + +This is a simple polyfill for [`getallheaders()`](http://www.php.net/manual/en/function.getallheaders.php). + +## Install + +For PHP version **`>= 5.6`**: + +``` +composer require ralouphie/getallheaders +``` + +For PHP version **`< 5.6`**: + +``` +composer require ralouphie/getallheaders "^2" +``` diff --git a/vendor/ralouphie/getallheaders/composer.json b/vendor/ralouphie/getallheaders/composer.json new file mode 100644 index 0000000000000000000000000000000000000000..de8ce62e45dc6d37f9021969baed2830ac6537ae --- /dev/null +++ b/vendor/ralouphie/getallheaders/composer.json @@ -0,0 +1,26 @@ +{ + "name": "ralouphie/getallheaders", + "description": "A polyfill for getallheaders.", + "license": "MIT", + "authors": [ + { + "name": "Ralph Khattar", + "email": "ralph.khattar@gmail.com" + } + ], + "require": { + "php": ">=5.6" + }, + "require-dev": { + "phpunit/phpunit": "^5 || ^6.5", + "php-coveralls/php-coveralls": "^2.1" + }, + "autoload": { + "files": ["src/getallheaders.php"] + }, + "autoload-dev": { + "psr-4": { + "getallheaders\\Tests\\": "tests/" + } + } +} diff --git a/vendor/ralouphie/getallheaders/src/getallheaders.php b/vendor/ralouphie/getallheaders/src/getallheaders.php new file mode 100644 index 0000000000000000000000000000000000000000..c7285a5ba166616c89ea98d7ac3ce5cb05b382aa --- /dev/null +++ b/vendor/ralouphie/getallheaders/src/getallheaders.php @@ -0,0 +1,46 @@ +<?php + +if (!function_exists('getallheaders')) { + + /** + * Get all HTTP header key/values as an associative array for the current request. + * + * @return string[string] The HTTP header key/value pairs. + */ + function getallheaders() + { + $headers = array(); + + $copy_server = array( + 'CONTENT_TYPE' => 'Content-Type', + 'CONTENT_LENGTH' => 'Content-Length', + 'CONTENT_MD5' => 'Content-Md5', + ); + + foreach ($_SERVER as $key => $value) { + if (substr($key, 0, 5) === 'HTTP_') { + $key = substr($key, 5); + if (!isset($copy_server[$key]) || !isset($_SERVER[$key])) { + $key = str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', $key)))); + $headers[$key] = $value; + } + } elseif (isset($copy_server[$key])) { + $headers[$copy_server[$key]] = $value; + } + } + + if (!isset($headers['Authorization'])) { + if (isset($_SERVER['REDIRECT_HTTP_AUTHORIZATION'])) { + $headers['Authorization'] = $_SERVER['REDIRECT_HTTP_AUTHORIZATION']; + } elseif (isset($_SERVER['PHP_AUTH_USER'])) { + $basic_pass = isset($_SERVER['PHP_AUTH_PW']) ? $_SERVER['PHP_AUTH_PW'] : ''; + $headers['Authorization'] = 'Basic ' . base64_encode($_SERVER['PHP_AUTH_USER'] . ':' . $basic_pass); + } elseif (isset($_SERVER['PHP_AUTH_DIGEST'])) { + $headers['Authorization'] = $_SERVER['PHP_AUTH_DIGEST']; + } + } + + return $headers; + } + +} diff --git a/vendor/silex/silex/.travis.yml b/vendor/silex/silex/.travis.yml index 73463e5418c9055f98514c17f9466dee32b332db..e89b7bb95f4c692c9c5e48b4b76fb350d3c00cf0 100644 --- a/vendor/silex/silex/.travis.yml +++ b/vendor/silex/silex/.travis.yml @@ -14,25 +14,6 @@ cache: before_install: - phpenv config-rm xdebug.ini - - # Twig 1.x - - if [[ $TWIG_VERSION != 2.0 ]]; then sed -i 's/~1.8|~2.0/~1.8/g' composer.json; fi - - # Symfony 2.8 - - if [[ $SYMFONY_DEPS_VERSION = 2.8 ]]; then sed -i 's/~2\.8|^3\.0/2.8.*/g' composer.json; fi - # Symfony 3.3 - - | - if [[ $SYMFONY_DEPS_VERSION = 3.3 ]]; then - sed -i 's/~2\.8|^3\.0/3.3.*/g' composer.json; - composer require --no-update symfony/web-link:3.3.* - fi - # Symfony 3.4 - - | - if [[ $SYMFONY_DEPS_VERSION = 3.4 ]]; then - sed -i 's/~2\.8|^3\.0/3.4.*/g' composer.json; - composer require --no-update symfony/web-link:3.4.* - fi - - composer update --no-suggest install: @@ -42,16 +23,5 @@ script: ./vendor/bin/simple-phpunit matrix: include: - - php: 5.5 - - php: 5.6 - env: TWIG_VERSION=2.0 - - php: 5.6 - env: SYMFONY_DEPS_VERSION=2.8 - - php: 5.6 - env: SYMFONY_DEPS_VERSION=3.3 - - php: 5.6 - env: SYMFONY_DEPS_VERSION=3.4 - - php: 5.6 - - php: 7.0 - php: 7.1 - php: 7.2 diff --git a/vendor/silex/silex/README.rst b/vendor/silex/silex/README.rst index e7138a762fce08f428b64f207a063328e0ad4011..77e067dddbae7ee35914938a5d6e3c0022821023 100644 --- a/vendor/silex/silex/README.rst +++ b/vendor/silex/silex/README.rst @@ -3,8 +3,6 @@ Silex, a simple Web Framework **WARNING**: Silex is in maintenance mode only. Ends of life is set to June 2018. Read more on `Symfony's blog <http://symfony.com/blog/the-end-of-silex>`_. -But Silex can be saved! Any **help** to keep Silex alive is greatly appreciated. -See `#1593 <https://github.com/silexphp/Silex/issues/1593>`_. Silex is a PHP micro-framework to develop websites based on `Symfony components`_: @@ -23,7 +21,7 @@ components`_: $app->run(); -Silex works with PHP 5.5.9 or later. +Silex works with PHP 7.1.3 or later. Installation ------------ @@ -52,10 +50,12 @@ To run the test suite, you need `Composer`_ and `PHPUnit`_: composer install phpunit -Community ---------- +Support +------- + +If you have a configuration problem use the `silex tag`_ on StackOverflow to ask a question. -Check out #silex-php on irc.freenode.net. +If you think there is an actual problem in Silex, please `open an issue`_ if there isn't one already created. License ------- @@ -67,3 +67,5 @@ Silex is licensed under the MIT license. .. _PHPUnit: https://phpunit.de .. _silex.zip: http://silex.sensiolabs.org/download .. _documentation: http://silex.sensiolabs.org/documentation +.. _silex tag: https://stackoverflow.com/questions/tagged/silex +.. _open an issue: https://github.com/silexphp/Silex/issues/new diff --git a/vendor/silex/silex/composer.json b/vendor/silex/silex/composer.json index d7c52c6908a8ff8b7bab4363608de7af12d170d3..77d19b5ac988f23884fd55781d86850f70d7778c 100644 --- a/vendor/silex/silex/composer.json +++ b/vendor/silex/silex/composer.json @@ -15,43 +15,40 @@ } ], "require": { - "php": ">=5.5.9", - "pimple/pimple": "~3.0", - "symfony/event-dispatcher": "~2.8|^3.0", - "symfony/http-foundation": "~2.8|^3.0", - "symfony/http-kernel": "~2.8|^3.0", - "symfony/routing": "~2.8|^3.0" + "php": ">=7.1.3", + "pimple/pimple": "^3.0", + "symfony/event-dispatcher": "^4.0", + "symfony/http-foundation": "^4.0", + "symfony/http-kernel": "^4.0", + "symfony/routing": "^4.0" }, "require-dev": { - "symfony/asset": "~2.8|^3.0", - "symfony/expression-language": "~2.8|^3.0", - "symfony/security": "~2.8|^3.0", - "symfony/config": "~2.8|^3.0", - "symfony/form": "~2.8|^3.0", - "symfony/browser-kit": "~2.8|^3.0", - "symfony/css-selector": "~2.8|^3.0", - "symfony/debug": "~2.8|^3.0", - "symfony/dom-crawler": "~2.8|^3.0", - "symfony/finder": "~2.8|^3.0", - "symfony/intl": "~2.8|^3.0", - "symfony/monolog-bridge": "~2.8|^3.0", - "symfony/doctrine-bridge": "~2.8|^3.0", - "symfony/options-resolver": "~2.8|^3.0", + "symfony/asset": "^4.0", + "symfony/expression-language": "^4.0", + "symfony/security": "^4.0", + "symfony/config": "^4.0", + "symfony/form": "^4.0", + "symfony/browser-kit": "^4.0", + "symfony/css-selector": "^4.0", + "symfony/debug": "^4.0", + "symfony/dom-crawler": "^4.0", + "symfony/finder": "^4.0", + "symfony/intl": "^4.0", + "symfony/monolog-bridge": "^4.0", + "symfony/doctrine-bridge": "^4.0", + "symfony/options-resolver": "^4.0", "symfony/phpunit-bridge": "^3.2", - "symfony/process": "~2.8|^3.0", - "symfony/serializer": "~2.8|^3.0", - "symfony/translation": "~2.8|^3.0", - "symfony/twig-bridge": "~2.8|^3.0", - "symfony/validator": "~2.8|^3.0", - "symfony/var-dumper": "~2.8|^3.0", - "twig/twig": "~1.28|~2.0", - "doctrine/dbal": "~2.2", - "swiftmailer/swiftmailer": "~5", + "symfony/process": "^4.0", + "symfony/serializer": "^4.0", + "symfony/translation": "^4.0", + "symfony/twig-bridge": "^4.0", + "symfony/validator": "^4.0", + "symfony/var-dumper": "^4.0", + "twig/twig": "^2.0", + "doctrine/dbal": "^2.2", + "swiftmailer/swiftmailer": "^5", "monolog/monolog": "^1.4.1", - "symfony/web-link": "^3.3" - }, - "conflict": { - "phpunit/phpunit": "<4.8.35 || >= 5.0, <5.4.3" + "symfony/web-link": "^4.0" }, "replace": { "silex/api": "self.version", @@ -65,7 +62,7 @@ }, "extra": { "branch-alias": { - "dev-master": "2.2.x-dev" + "dev-master": "2.3.x-dev" } } } diff --git a/vendor/silex/silex/doc/changelog.rst b/vendor/silex/silex/doc/changelog.rst index 99bb079b57217a3b254e8418db490e206af135fa..c39b3c5c7e2824abbf53e65fd7429b41303d3523 100644 --- a/vendor/silex/silex/doc/changelog.rst +++ b/vendor/silex/silex/doc/changelog.rst @@ -1,6 +1,21 @@ Changelog ========= +2.3.0 (2018-04-20) +------------------ + + * added support for defining users provider as a service ID + * fixed error when HttpKernelRuntime is not available + * allow setting custom status code on exception response with Symfony 3.3+ + * made CSRF extension work with Validator translations domain + * fixed Security provider context usage + * dropped support for Twig < 2.0 + * dropped support for PHP < 7.1 + * dropped support for Symfony 2.x and 3.x + * added support for Symfony 4 + * added support PSR-3 log levels in MonologServiceProvider + * exposed AuthenticationUtils in SecurityServiceProvider + 2.2.3 (2018-02-25) ------------------ diff --git a/vendor/silex/silex/doc/cookbook/error_handler.rst b/vendor/silex/silex/doc/cookbook/error_handler.rst index 235c263a77ee1c735d537adf49f2c18917479609..d43ca18f46bd7144ac4f73e2cd47b6c743e5a27f 100644 --- a/vendor/silex/silex/doc/cookbook/error_handler.rst +++ b/vendor/silex/silex/doc/cookbook/error_handler.rst @@ -36,3 +36,15 @@ the ``$debug`` argument:: use Symfony\Component\Debug\ExceptionHandler; ExceptionHandler::register(false); + +.. note:: + + Important caveat when using Silex on a command-line interface: + The ``ExceptionHandler`` should not be enabled as it would convert an error + to HTML output and return a non-zero exit code:: + + use Symfony\Component\Debug\ExceptionHandler; + + if (!in_array(PHP_SAPI, ['cli', 'phpdbg'])) { + ExceptionHandler::register(); + } diff --git a/vendor/silex/silex/doc/providers/asset.rst b/vendor/silex/silex/doc/providers/asset.rst index bd5ec6525269c225c4658ee8fcd7b65fd6b778f3..17b49c8be0cc2c26e44e70a5269dc7bd06824196 100644 --- a/vendor/silex/silex/doc/providers/asset.rst +++ b/vendor/silex/silex/doc/providers/asset.rst @@ -10,14 +10,20 @@ Parameters * **assets.version**: Default version for assets. -* **assets.format_version** (optional): Default format for assets. +* **assets.version_format** (optional): Default format for assets. * **assets.base_path**: Default path to prepend to all assets without a package. +* **assets.base_urls**: (Alternative to ``assets.base_path``) List of base URLs + to choose from to prepend to assets without a package. + * **assets.named_packages** (optional): Named packages. Keys are the package names and values the configuration (supported keys are ``version``, ``version_format``, ``base_urls``, and ``base_path``). +* **assets.json_manifest_path** (optional): Absolute path to a `JSON version manifest + <https://symfony.com/blog/new-in-symfony-3-3-manifest-based-asset-versioning>`_. + Services -------- diff --git a/vendor/silex/silex/doc/providers/csrf.rst b/vendor/silex/silex/doc/providers/csrf.rst index a055c112ecf4c1f7236ccd5269d00d149c310b5c..057e79d52791aa3ead7d08c973f482f3013eb5a8 100644 --- a/vendor/silex/silex/doc/providers/csrf.rst +++ b/vendor/silex/silex/doc/providers/csrf.rst @@ -7,7 +7,8 @@ application with the Symfony Form component. Parameters ---------- -* none +* **csrf.session_namespace** (optional): The namespace under which the token + is stored in the session. Defaults to ``_csrf``. Services -------- diff --git a/vendor/silex/silex/doc/providers/form.rst b/vendor/silex/silex/doc/providers/form.rst index 6818b8582cebffe22bb77f6dd26c03f23627e60d..159408102bd5f9954aeac87b359fc380ddcf7635 100644 --- a/vendor/silex/silex/doc/providers/form.rst +++ b/vendor/silex/silex/doc/providers/form.rst @@ -157,7 +157,7 @@ You can register form types by extending ``form.types``:: $types[] = 'your.type.service'; return $types; - })); + }); You can register form extensions by extending ``form.extensions``:: @@ -213,4 +213,4 @@ Traits $app->namedForm($name, $data, $options, $type); For more information, consult the `Symfony Forms documentation -<http://symfony.com/doc/2.8/book/forms.html>`_. +<http://symfony.com/doc/current/forms.html>`_. diff --git a/vendor/silex/silex/doc/providers/monolog.rst b/vendor/silex/silex/doc/providers/monolog.rst index 645b710619893cdf88563e37d16e9d4895992b6d..6a73cfd4c528e454abc57cfdeab92504d248b82a 100644 --- a/vendor/silex/silex/doc/providers/monolog.rst +++ b/vendor/silex/silex/doc/providers/monolog.rst @@ -12,8 +12,8 @@ Parameters ---------- * **monolog.logfile**: File where logs are written to. -* **monolog.bubble**: (optional) Whether the messages that are handled can bubble up the stack or not. -* **monolog.permission**: (optional) File permissions default (null), nothing change. +* **monolog.bubble** (optional): Whether the messages that are handled can bubble up the stack or not. +* **monolog.permission** (optional): File permissions default (null), nothing change. * **monolog.level** (optional): Level of logging, defaults to ``DEBUG``. Must be one of ``Logger::DEBUG``, ``Logger::INFO``, @@ -25,6 +25,8 @@ Parameters level in string form, for example: ``"DEBUG"``, ``"INFO"``, ``"WARNING"``, ``"ERROR"``. + PSR-3 log levels from ``\Psr\Log\LogLevel::`` constants are also supported. + * **monolog.name** (optional): Name of the monolog channel, defaults to ``myapp``. diff --git a/vendor/silex/silex/doc/providers/routing.rst b/vendor/silex/silex/doc/providers/routing.rst index afa61c962b2208425856ab824cb00ee676ff8b25..4ff104107c195afa282c4bab7dae40d071e3b1f8 100644 --- a/vendor/silex/silex/doc/providers/routing.rst +++ b/vendor/silex/silex/doc/providers/routing.rst @@ -7,7 +7,8 @@ named routes. Parameters ---------- -None. +* **route_class**: (optional): The default route class used by the route + factory (defaults to ``Silex\Route``). Services -------- diff --git a/vendor/silex/silex/doc/providers/security.rst b/vendor/silex/silex/doc/providers/security.rst index 6a6f1516372dd1ceec448e0c7e6e86e3b18a1d71..ffeabc41a0a3a17787f4054b6193c8c1486c2cfb 100644 --- a/vendor/silex/silex/doc/providers/security.rst +++ b/vendor/silex/silex/doc/providers/security.rst @@ -12,6 +12,11 @@ Parameters * **security.encoder.bcrypt.cost** (optional): Defines BCrypt password encoder cost. Defaults to 13. +* **security.role_hierarchy**:(optional): Defines a map of roles including other roles. + +* **security.access_rules** (optional): Defines rules based on paths and roles. + See `Defining Access Rule <#defining-access-rules>`_. + Services -------- @@ -34,8 +39,11 @@ Services * **security.user_checker**: Checks user flags after authentication. -* **security.last_error**: Returns the last authentication errors when given a - Request object. +* **security.last_error**: Returns the last authentication error message when + given a Request object. + +* **security.authentication_utils**: Returns the AuthenticationUtils service + allowing you to get last authentication exception or last username. * **security.encoder_factory**: Defines the encoding strategies for user passwords (uses ``security.default_encoder``). @@ -90,7 +98,7 @@ Usage The Symfony Security component is powerful. To learn more about it, read the `Symfony Security documentation -<http://symfony.com/doc/2.8/book/security.html>`_. +<http://symfony.com/doc/current/security.html>`_. .. tip:: @@ -242,6 +250,10 @@ The ``error`` and ``last_username`` variables contain the last authentication error and the last username entered by the user in case of an authentication error. +If you want to have the last error message translated, you would need to use +the ``security.authentication_utils`` service and retrieve +the actual ``AuthenticationException`` instance. + Create the associated template: .. code-block:: jinja @@ -421,7 +433,7 @@ switch back to their primary account: <a href="?_switch_user=_exit"> exit</a> the switch. {% endif %} -Sharing security context between multiple firewalls +Sharing Security Context between multiple Firewalls ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ By default, all the firewalls have a different **security context**. In case you @@ -429,6 +441,8 @@ need to share the same security context between multiple firewalls you can set the ``context`` setting for each firewall you want the context to be shared with. +.. code-block:: php + $app['security.firewalls'] = array( 'login' => array( 'context' => 'admin_security', @@ -495,8 +509,8 @@ Defining a custom User Provider Using an array of users is simple and useful when securing an admin section of a personal website, but you can override this default mechanism with you own. -The ``users`` setting can be defined as a service that returns an instance of -`UserProviderInterface +The ``users`` setting can be defined as a service or a service id that returns +an instance of `UserProviderInterface <http://api.symfony.com/master/Symfony/Component/Security/Core/User/UserProviderInterface.html>`_:: 'users' => function () use ($app) { diff --git a/vendor/silex/silex/doc/providers/session.rst b/vendor/silex/silex/doc/providers/session.rst index 011b69febc8bc8731bfd6177b02fb79ca52f80de..9694501772cf13e8d4c93f9903e6bf1095f09b87 100644 --- a/vendor/silex/silex/doc/providers/session.rst +++ b/vendor/silex/silex/doc/providers/session.rst @@ -35,6 +35,12 @@ Parameters * **session.test**: Whether to simulate sessions or not (useful when writing functional tests). +* **session.attribute_bag** (optional): The attribute bag service to use in the session. + Instance of ``AttributeBagInterface``. + +* **session.flash_bag** (optional): The flash bag service to use in the session. + Instance of ``FlashBagInterface``. + Services -------- diff --git a/vendor/silex/silex/doc/providers/translation.rst b/vendor/silex/silex/doc/providers/translation.rst index 145fc18c6452586ab22c5d849f321819cad7f02d..04bc41cf8c7836eff57428726f73641f9213b7d9 100644 --- a/vendor/silex/silex/doc/providers/translation.rst +++ b/vendor/silex/silex/doc/providers/translation.rst @@ -16,6 +16,9 @@ Parameters * **locale_fallbacks** (optional): Fallback locales for the translator. It will be used when the current locale has no messages set. Defaults to ``en``. +* **translator.cache_dir** (optional): Defines the cache directory + if you want translations to be cached. + Services -------- diff --git a/vendor/silex/silex/doc/providers/validator.rst b/vendor/silex/silex/doc/providers/validator.rst index bd4e9985887aab0b31388ed185a26f5bd493be28..5c501bb75d2c141ca1bc8e68000c33b0e1b18bc5 100644 --- a/vendor/silex/silex/doc/providers/validator.rst +++ b/vendor/silex/silex/doc/providers/validator.rst @@ -8,9 +8,16 @@ standalone. Parameters ---------- -* **validator.validator_service_ids**: An array of service names representing +* **validator.validator_service_ids** (optional): An array of service names representing validators. +* **validator.translation_domain** (optional): The translation domain to use for translating validator messages. + (Defaults to ``validators``.) + +* **validator.object_initializers** (optional): An array of object initializers. + See `the relevant Validation documentation + <http://symfony.com/doc/current/reference/dic_tags.html#validator-initializer>`_. + Services -------- diff --git a/vendor/silex/silex/doc/testing.rst b/vendor/silex/silex/doc/testing.rst index 17f5f571c48174b920167358bec152ee985008db..06eb22593eb1804cb23a27dd523be347baabb429 100644 --- a/vendor/silex/silex/doc/testing.rst +++ b/vendor/silex/silex/doc/testing.rst @@ -26,10 +26,12 @@ PHPUnit `PHPUnit <https://github.com/sebastianbergmann/phpunit>`_ is the de-facto standard testing framework for PHP. It was built for writing unit tests, but it can be used for functional tests too. You write tests by creating a new class, -that extends the ``PHPUnit_Framework_TestCase``. Your test cases are methods +that extends the ``PHPUnit\Framework\TestCase``. Your test cases are methods prefixed with ``test``:: - class ContactFormTest extends \PHPUnit_Framework_TestCase + use PHPUnit\Framework\TestCase; + + class ContactFormTest extends TestCase { public function testInitialPage() { diff --git a/vendor/silex/silex/doc/usage.rst b/vendor/silex/silex/doc/usage.rst index 724254cefcce09542ba2d7a083dbc7509027c01f..7d857b8e10161b27fb1b1e6975f5441c9a523406 100644 --- a/vendor/silex/silex/doc/usage.rst +++ b/vendor/silex/silex/doc/usage.rst @@ -516,11 +516,32 @@ setting a more specific type hint for the Closure argument:: As Silex ensures that the Response status code is set to the most appropriate one depending on the exception, setting the status on the - response won't work. If you want to overwrite the status code, set the - ``X-Status-Code`` header:: + response alone won't work. + + If you want to overwrite the status code, which you should not without a + good reason, set the ``X-Status-Code`` header (on Symfony until version + 3.2):: return new Response('Error', 404 /* ignored */, array('X-Status-Code' => 200)); + As of Symfony 3.3, call + ``GetResponseForExceptionEvent::allowCustomResponseCode()`` first and then + then set the status code on the response as normal. The kernel will now use + your status code when sending the response to the client. The + ``GetResponseForExceptionEvent`` is passed to the error callback as a 4th + parameter:: + + use Symfony\Component\HttpFoundation\Response; + use Symfony\Component\HttpFoundation\Request; + use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent; + + $app->error(function (\Exception $e, Request $request, $code, GetResponseForExceptionEvent $event) { + $event->allowCustomResponseCode(); + $response = new Response('No Content', 204); + + return $response; + }); + If you want to use a separate error handler for logging, make sure you register it with a higher priority than response error handlers, because once a response is returned, the following handlers are ignored. diff --git a/vendor/silex/silex/src/Silex/Api/composer.json b/vendor/silex/silex/src/Silex/Api/composer.json index 7290988a36c9ff93cc8db5a7bbbb88916fd5657b..2c667e3b38aa8616338ff27a9b7ca64ddbd2d23f 100644 --- a/vendor/silex/silex/src/Silex/Api/composer.json +++ b/vendor/silex/silex/src/Silex/Api/composer.json @@ -28,7 +28,7 @@ }, "extra": { "branch-alias": { - "dev-master": "2.2.x-dev" + "dev-master": "2.3.x-dev" } } } diff --git a/vendor/silex/silex/src/Silex/Application.php b/vendor/silex/silex/src/Silex/Application.php index ee206d301ffa6b58677a35ed92b795badf6f33e8..62d947cb9b5411d58d2a8a0f511402aa0f83a510 100644 --- a/vendor/silex/silex/src/Silex/Application.php +++ b/vendor/silex/silex/src/Silex/Application.php @@ -41,7 +41,7 @@ use Silex\Provider\HttpKernelServiceProvider; */ class Application extends Container implements HttpKernelInterface, TerminableInterface { - const VERSION = '2.2.3'; + const VERSION = '2.3.0'; const EARLY_EVENT = 512; const LATE_EVENT = -512; diff --git a/vendor/silex/silex/src/Silex/ControllerResolver.php b/vendor/silex/silex/src/Silex/ControllerResolver.php deleted file mode 100644 index 0a95e15f2edcf7cd68b74744f2531123adb26503..0000000000000000000000000000000000000000 --- a/vendor/silex/silex/src/Silex/ControllerResolver.php +++ /dev/null @@ -1,54 +0,0 @@ -<?php - -/* - * This file is part of the Silex framework. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Silex; - -use Psr\Log\LoggerInterface; -use Symfony\Component\HttpKernel\Controller\ControllerResolver as BaseControllerResolver; -use Symfony\Component\HttpFoundation\Request; - -/** - * Adds Application as a valid argument for controllers. - * - * @author Fabien Potencier <fabien@symfony.com> - * - * @deprecated This class can be dropped once Symfony 3.0 is not supported anymore. - */ -class ControllerResolver extends BaseControllerResolver -{ - protected $app; - - /** - * Constructor. - * - * @param Application $app An Application instance - * @param LoggerInterface $logger A LoggerInterface instance - */ - public function __construct(Application $app, LoggerInterface $logger = null) - { - $this->app = $app; - - parent::__construct($logger); - } - - protected function doGetArguments(Request $request, $controller, array $parameters) - { - foreach ($parameters as $param) { - if ($param->getClass() && $param->getClass()->isInstance($this->app)) { - $request->attributes->set($param->getName(), $this->app); - - break; - } - } - - return parent::doGetArguments($request, $controller, $parameters); - } -} diff --git a/vendor/silex/silex/src/Silex/ExceptionListenerWrapper.php b/vendor/silex/silex/src/Silex/ExceptionListenerWrapper.php index e0d527b00c0ccf5eb3a6272413fa214addf1e6ce..d83170ebffb18ded4893a26dbbaaba7a34e29e1c 100644 --- a/vendor/silex/silex/src/Silex/ExceptionListenerWrapper.php +++ b/vendor/silex/silex/src/Silex/ExceptionListenerWrapper.php @@ -50,7 +50,7 @@ class ExceptionListenerWrapper $code = $exception instanceof HttpExceptionInterface ? $exception->getStatusCode() : 500; - $response = call_user_func($this->callback, $exception, $event->getRequest(), $code); + $response = call_user_func($this->callback, $exception, $event->getRequest(), $code, $event); $this->ensureResponse($response, $event); } diff --git a/vendor/silex/silex/src/Silex/Provider/AssetServiceProvider.php b/vendor/silex/silex/src/Silex/Provider/AssetServiceProvider.php index 062761c7a323ce82ffb99d42e14ea515a1d1d157..793a00e4ea960b8b4aaa6fb24d588fa1823ace3f 100644 --- a/vendor/silex/silex/src/Silex/Provider/AssetServiceProvider.php +++ b/vendor/silex/silex/src/Silex/Provider/AssetServiceProvider.php @@ -72,10 +72,6 @@ class AssetServiceProvider implements ServiceProviderInterface } if ($jsonManifestPath) { - if (!class_exists('Symfony\Component\Asset\VersionStrategy\JsonManifestVersionStrategy')) { - throw new \RuntimeException('You must require symfony/asset >= 3.3 to use JSON manifest version strategy.'); - } - return new JsonManifestVersionStrategy($jsonManifestPath); } diff --git a/vendor/silex/silex/src/Silex/Provider/FormServiceProvider.php b/vendor/silex/silex/src/Silex/Provider/FormServiceProvider.php index ccecb7fa19926be4b38bdd3f1205143859d00e2a..59d147cbd5d48db7d61827be19b55ed0624085fe 100644 --- a/vendor/silex/silex/src/Silex/Provider/FormServiceProvider.php +++ b/vendor/silex/silex/src/Silex/Provider/FormServiceProvider.php @@ -47,7 +47,9 @@ class FormServiceProvider implements ServiceProviderInterface $app['form.extension.csrf'] = function ($app) { if (isset($app['translator'])) { - return new CsrfExtension($app['csrf.token_manager'], $app['translator']); + $translationDomain = isset($app['validator.translation_domain']) ? $app['validator.translation_domain'] : null; + + return new CsrfExtension($app['csrf.token_manager'], $app['translator'], $translationDomain); } return new CsrfExtension($app['csrf.token_manager']); diff --git a/vendor/silex/silex/src/Silex/Provider/HttpKernelServiceProvider.php b/vendor/silex/silex/src/Silex/Provider/HttpKernelServiceProvider.php index 485c2bbd2086f31d230418367aff1b57ef454d89..cfc7cb5dbf1f77d1e582cac725d2fb60af943ce2 100644 --- a/vendor/silex/silex/src/Silex/Provider/HttpKernelServiceProvider.php +++ b/vendor/silex/silex/src/Silex/Provider/HttpKernelServiceProvider.php @@ -7,23 +7,17 @@ use Pimple\ServiceProviderInterface; use Silex\Api\EventListenerProviderInterface; use Silex\AppArgumentValueResolver; use Silex\CallbackResolver; -use Silex\ControllerResolver; use Silex\EventListener\ConverterListener; use Silex\EventListener\MiddlewareListener; use Silex\EventListener\StringToResponseListener; use Symfony\Component\EventDispatcher\EventDispatcher; use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\HttpKernel\Controller\ArgumentResolver; -use Symfony\Component\HttpKernel\Controller\ArgumentResolver\RequestAttributeValueResolver; -use Symfony\Component\HttpKernel\Controller\ArgumentResolver\RequestValueResolver; -use Symfony\Component\HttpKernel\Controller\ArgumentResolver\DefaultValueResolver; -use Symfony\Component\HttpKernel\Controller\ArgumentResolver\VariadicValueResolver; -use Symfony\Component\HttpKernel\Controller\ControllerResolver as SfControllerResolver; +use Symfony\Component\HttpKernel\Controller\ControllerResolver; use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadataFactory; use Symfony\Component\HttpKernel\EventListener\ResponseListener; use Symfony\Component\HttpKernel\HttpKernel; -use Symfony\Component\HttpKernel\Kernel; use Symfony\Component\WebLink\EventListener\AddLinkHeaderListener; use Symfony\Component\WebLink\HttpHeaderSerializer; @@ -35,36 +29,18 @@ class HttpKernelServiceProvider implements ServiceProviderInterface, EventListen public function register(Container $app) { $app['resolver'] = function ($app) { - if (Kernel::VERSION_ID >= 30100) { - return new SfControllerResolver($app['logger']); - } - - return new ControllerResolver($app, $app['logger']); + return new ControllerResolver($app['logger']); }; - if (Kernel::VERSION_ID >= 30100) { - $app['argument_metadata_factory'] = function ($app) { - return new ArgumentMetadataFactory(); - }; - $app['argument_value_resolvers'] = function ($app) { - if (Kernel::VERSION_ID < 30200) { - return [ - new AppArgumentValueResolver($app), - new RequestAttributeValueResolver(), - new RequestValueResolver(), - new DefaultValueResolver(), - new VariadicValueResolver(), - ]; - } - - return array_merge([new AppArgumentValueResolver($app)], ArgumentResolver::getDefaultArgumentValueResolvers()); - }; - } + $app['argument_metadata_factory'] = function ($app) { + return new ArgumentMetadataFactory(); + }; + $app['argument_value_resolvers'] = function ($app) { + return array_merge([new AppArgumentValueResolver($app)], ArgumentResolver::getDefaultArgumentValueResolvers()); + }; $app['argument_resolver'] = function ($app) { - if (Kernel::VERSION_ID >= 30100) { - return new ArgumentResolver($app['argument_metadata_factory'], $app['argument_value_resolvers']); - } + return new ArgumentResolver($app['argument_metadata_factory'], $app['argument_value_resolvers']); }; $app['kernel'] = function ($app) { diff --git a/vendor/silex/silex/src/Silex/Provider/MonologServiceProvider.php b/vendor/silex/silex/src/Silex/Provider/MonologServiceProvider.php index a94c3f5ea87fd7005f8763830b06af57731ece3b..91552a69f246855ea3d1fda83ad689ee6743fd8d 100644 --- a/vendor/silex/silex/src/Silex/Provider/MonologServiceProvider.php +++ b/vendor/silex/silex/src/Silex/Provider/MonologServiceProvider.php @@ -19,9 +19,10 @@ use Monolog\Handler; use Monolog\ErrorHandler; use Silex\Application; use Silex\Api\BootableProviderInterface; -use Symfony\Bridge\Monolog\Handler\DebugHandler; +use Silex\Api\EventListenerProviderInterface; use Symfony\Bridge\Monolog\Handler\FingersCrossed\NotFoundActivationStrategy; use Symfony\Bridge\Monolog\Processor\DebugProcessor; +use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Silex\EventListener\LogListener; /** @@ -29,7 +30,7 @@ use Silex\EventListener\LogListener; * * @author Fabien Potencier <fabien@symfony.com> */ -class MonologServiceProvider implements ServiceProviderInterface, BootableProviderInterface +class MonologServiceProvider implements ServiceProviderInterface, BootableProviderInterface, EventListenerProviderInterface { public function register(Container $app) { @@ -38,15 +39,11 @@ class MonologServiceProvider implements ServiceProviderInterface, BootableProvid }; if ($bridge = class_exists('Symfony\Bridge\Monolog\Logger')) { - $app['monolog.handler.debug'] = function () use ($app) { - $level = MonologServiceProvider::translateLevel($app['monolog.level']); - - return new DebugHandler($level); - }; - if (isset($app['request_stack'])) { $app['monolog.not_found_activation_strategy'] = function () use ($app) { - return new NotFoundActivationStrategy($app['request_stack'], ['^/'], $app['monolog.level']); + $level = MonologServiceProvider::translateLevel($app['monolog.level']); + + return new NotFoundActivationStrategy($app['request_stack'], ['^/'], $level); }; } } @@ -64,11 +61,7 @@ class MonologServiceProvider implements ServiceProviderInterface, BootableProvid $log->pushHandler($handler); if ($app['debug'] && $bridge) { - if (class_exists(DebugProcessor::class)) { - $log->pushProcessor(new DebugProcessor()); - } else { - $log->pushHandler($app['monolog.handler.debug']); - } + $log->pushProcessor(new DebugProcessor()); } return $log; @@ -121,9 +114,12 @@ class MonologServiceProvider implements ServiceProviderInterface, BootableProvid if ($app['monolog.use_error_handler']) { ErrorHandler::register($app['monolog']); } + } + public function subscribe(Container $app, EventDispatcherInterface $dispatcher) + { if (isset($app['monolog.listener'])) { - $app['dispatcher']->addSubscriber($app['monolog.listener']); + $dispatcher->addSubscriber($app['monolog.listener']); } } @@ -134,6 +130,12 @@ class MonologServiceProvider implements ServiceProviderInterface, BootableProvid return $name; } + $psrLevel = Logger::toMonologLevel($name); + + if (is_int($psrLevel)) { + return $psrLevel; + } + $levels = Logger::getLevels(); $upper = strtoupper($name); diff --git a/vendor/silex/silex/src/Silex/Provider/SecurityServiceProvider.php b/vendor/silex/silex/src/Silex/Provider/SecurityServiceProvider.php index 22df5f7b48b49dcd21bce4c61bf3a06819c98928..e06ee709a0d77a7743ccf015ee73d59cb1f5e5b2 100644 --- a/vendor/silex/silex/src/Silex/Provider/SecurityServiceProvider.php +++ b/vendor/silex/silex/src/Silex/Provider/SecurityServiceProvider.php @@ -31,6 +31,7 @@ use Symfony\Component\Security\Core\Authentication\Provider\DaoAuthenticationPro use Symfony\Component\Security\Core\Authentication\Provider\AnonymousAuthenticationProvider; use Symfony\Component\Security\Core\Authentication\AuthenticationProviderManager; use Symfony\Component\Security\Core\Authentication\AuthenticationTrustResolver; +use Symfony\Component\Security\Http\Authentication\AuthenticationUtils; use Symfony\Component\Security\Http\Authentication\DefaultAuthenticationSuccessHandler; use Symfony\Component\Security\Http\Authentication\DefaultAuthenticationFailureHandler; use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage; @@ -229,13 +230,19 @@ class SecurityServiceProvider implements ServiceProviderInterface, EventListener $protected = false === $security ? false : count($firewall); $listeners = ['security.channel_listener']; + if (is_string($users)) { + $users = function () use ($app, $users) { + return $app[$users]; + }; + } + if ($protected) { - if (!isset($app['security.context_listener.'.$name])) { + if (!isset($app['security.context_listener.'.$context])) { if (!isset($app['security.user_provider.'.$name])) { $app['security.user_provider.'.$name] = is_array($users) ? $app['security.user_provider.inmemory._proto']($users) : $users; } - $app['security.context_listener.'.$name] = $app['security.context_listener._proto']($name, [$app['security.user_provider.'.$name]]); + $app['security.context_listener.'.$context] = $app['security.context_listener._proto']($name, [$app['security.user_provider.'.$name]]); } if (false === $stateless) { @@ -665,6 +672,10 @@ class SecurityServiceProvider implements ServiceProviderInterface, EventListener return new AnonymousAuthenticationProvider($name); }; }); + + $app['security.authentication_utils'] = function ($app) { + return new AuthenticationUtils($app['request_stack']); + }; } public function subscribe(Container $app, EventDispatcherInterface $dispatcher) diff --git a/vendor/silex/silex/src/Silex/Provider/SessionServiceProvider.php b/vendor/silex/silex/src/Silex/Provider/SessionServiceProvider.php index d05af688f581a84cd3e04452e98d6f6b2be29a4e..e522eec93604444ed783f4ad2d00a6c3a85d8d68 100644 --- a/vendor/silex/silex/src/Silex/Provider/SessionServiceProvider.php +++ b/vendor/silex/silex/src/Silex/Provider/SessionServiceProvider.php @@ -69,7 +69,6 @@ class SessionServiceProvider implements ServiceProviderInterface, EventListenerP }; $app['session.storage.options'] = []; - $app['session.default_locale'] = 'en'; $app['session.storage.save_path'] = null; $app['session.attribute_bag'] = null; $app['session.flash_bag'] = null; @@ -80,7 +79,7 @@ class SessionServiceProvider implements ServiceProviderInterface, EventListenerP $dispatcher->addSubscriber($app['session.listener']); if ($app['session.test']) { - $app['dispatcher']->addSubscriber($app['session.listener.test']); + $dispatcher->addSubscriber($app['session.listener.test']); } } } diff --git a/vendor/silex/silex/src/Silex/Provider/TranslationServiceProvider.php b/vendor/silex/silex/src/Silex/Provider/TranslationServiceProvider.php index 9b8caff6a5a66b1d643eafe413a58c48e2081e77..6f70c5d6fa13b3e93b48c6363872d51674af5b07 100644 --- a/vendor/silex/silex/src/Silex/Provider/TranslationServiceProvider.php +++ b/vendor/silex/silex/src/Silex/Provider/TranslationServiceProvider.php @@ -13,10 +13,8 @@ namespace Silex\Provider; use Pimple\Container; use Pimple\ServiceProviderInterface; -use Symfony\Component\HttpKernel\Kernel; use Symfony\Component\Translation\Translator; use Symfony\Component\Translation\Formatter\MessageFormatter; -use Symfony\Component\Translation\MessageSelector; use Symfony\Component\Translation\Loader\ArrayLoader; use Symfony\Component\Translation\Loader\XliffFileLoader; use Symfony\Component\EventDispatcher\EventDispatcherInterface; @@ -79,10 +77,6 @@ class TranslationServiceProvider implements ServiceProviderInterface, EventListe } $app['translator.message_selector'] = function () { - if (Kernel::VERSION_ID < 30400) { - return new MessageSelector(); - } - return new MessageFormatter(); }; diff --git a/vendor/silex/silex/src/Silex/Provider/TwigServiceProvider.php b/vendor/silex/silex/src/Silex/Provider/TwigServiceProvider.php index 0f8004904140ac8ee3e3a8e9e0098851016a67a3..b46186a232e3f090460a0c7e08fa63ab7195627c 100644 --- a/vendor/silex/silex/src/Silex/Provider/TwigServiceProvider.php +++ b/vendor/silex/silex/src/Silex/Provider/TwigServiceProvider.php @@ -25,11 +25,8 @@ use Symfony\Bridge\Twig\Extension\HttpFoundationExtension; use Symfony\Bridge\Twig\Extension\HttpKernelExtension; use Symfony\Bridge\Twig\Extension\WebLinkExtension; use Symfony\Bridge\Twig\Form\TwigRendererEngine; -use Symfony\Bridge\Twig\Form\TwigRenderer; use Symfony\Bridge\Twig\Extension\HttpKernelRuntime; use Symfony\Component\Form\FormRenderer; -use Symfony\Component\HttpKernel\Kernel; -use Symfony\Component\WebLink\HttpHeaderSerializer; /** * Twig integration for Silex. @@ -54,14 +51,6 @@ class TwigServiceProvider implements ServiceProviderInterface $app['twig.number_format.thousands_separator'] = ','; $app['twig'] = function ($app) { - $app['twig.options'] = array_replace( - [ - 'charset' => $app['charset'], - 'debug' => $app['debug'], - 'strict_variables' => $app['debug'], - ], $app['twig.options'] - ); - $twig = $app['twig.environment_factory']($app); // registered for BC, but should not be used anymore // deprecated and should probably be removed in Silex 3.0 @@ -128,14 +117,10 @@ class TwigServiceProvider implements ServiceProviderInterface $app['twig.form.renderer'] = function ($app) { $csrfTokenManager = isset($app['csrf.token_manager']) ? $app['csrf.token_manager'] : null; - if (Kernel::VERSION_ID < 30400) { - return new TwigRenderer($app['twig.form.engine'], $csrfTokenManager); - } - return new FormRenderer($app['twig.form.engine'], $csrfTokenManager); }; - $twig->addExtension(new FormExtension(class_exists(HttpKernelRuntime::class) ? null : $app['twig.form.renderer'])); + $twig->addExtension(new FormExtension()); // add loader for Symfony built-in form templates $reflected = new \ReflectionClass('Symfony\Bridge\Twig\Extension\FormExtension'); @@ -147,13 +132,8 @@ class TwigServiceProvider implements ServiceProviderInterface $twig->addExtension(new DumpExtension($app['var_dumper.cloner'])); } - if (class_exists(HttpKernelRuntime::class)) { - $twig->addRuntimeLoader($app['twig.runtime_loader']); - } - - if (class_exists(HttpHeaderSerializer::class) && class_exists(WebLinkExtension::class)) { - $twig->addExtension(new WebLinkExtension($app['request_stack'])); - } + $twig->addRuntimeLoader($app['twig.runtime_loader']); + $twig->addExtension(new WebLinkExtension($app['request_stack'])); } return $twig; @@ -184,7 +164,11 @@ class TwigServiceProvider implements ServiceProviderInterface }; $app['twig.environment_factory'] = $app->protect(function ($app) { - return new \Twig_Environment($app['twig.loader'], $app['twig.options']); + return new \Twig_Environment($app['twig.loader'], array_replace([ + 'charset' => $app['charset'], + 'debug' => $app['debug'], + 'strict_variables' => $app['debug'], + ], $app['twig.options'])); }); $app['twig.runtime.httpkernel'] = function ($app) { @@ -192,17 +176,10 @@ class TwigServiceProvider implements ServiceProviderInterface }; $app['twig.runtimes'] = function ($app) { - $runtimes = [ + return [ HttpKernelRuntime::class => 'twig.runtime.httpkernel', + FormRenderer::class => 'twig.form.renderer', ]; - - if (Kernel::VERSION_ID < 30400) { - $runtimes[TwigRenderer::class] = 'twig.form.renderer'; - } else { - $runtimes[FormRenderer::class] = 'twig.form.renderer'; - } - - return $runtimes; }; $app['twig.runtime_loader'] = function ($app) { diff --git a/vendor/silex/silex/src/Silex/Provider/ValidatorServiceProvider.php b/vendor/silex/silex/src/Silex/Provider/ValidatorServiceProvider.php index 9aa7ebd52c3871af9f71fed1720ef201ded030f6..e073a3f7774af28d236cab48624a7d5cdee8cfa0 100644 --- a/vendor/silex/silex/src/Silex/Provider/ValidatorServiceProvider.php +++ b/vendor/silex/silex/src/Silex/Provider/ValidatorServiceProvider.php @@ -35,7 +35,7 @@ class ValidatorServiceProvider implements ServiceProviderInterface $app['validator.builder'] = function ($app) { $builder = Validation::createValidatorBuilder(); $builder->setConstraintValidatorFactory($app['validator.validator_factory']); - $builder->setTranslationDomain('validators'); + $builder->setTranslationDomain($app['validator.translation_domain']); $builder->addObjectInitializers($app['validator.object_initializers']); $builder->setMetadataFactory($app['validator.mapping.class_metadata_factory']); if (isset($app['translator'])) { @@ -58,5 +58,9 @@ class ValidatorServiceProvider implements ServiceProviderInterface }; $app['validator.validator_service_ids'] = []; + + $app['validator.translation_domain'] = function () { + return 'validators'; + }; } } diff --git a/vendor/silex/silex/src/Silex/Provider/composer.json b/vendor/silex/silex/src/Silex/Provider/composer.json index a1e9fbfe08df116f5299a8a8cee362d93fe2b8d4..416b85782503fa2f4ca4234e9c619f1a9cd40b5a 100644 --- a/vendor/silex/silex/src/Silex/Provider/composer.json +++ b/vendor/silex/silex/src/Silex/Provider/composer.json @@ -25,7 +25,7 @@ }, "extra": { "branch-alias": { - "dev-master": "2.2.x-dev" + "dev-master": "2.3.x-dev" } } } diff --git a/vendor/silex/silex/tests/Silex/Tests/Application/MonologTraitTest.php b/vendor/silex/silex/tests/Silex/Tests/Application/MonologTraitTest.php index 7487f43a54933d3caeafbf3a4233532aeb89cd87..e381c5f5116f8ad279e5e053e01229873d53593e 100644 --- a/vendor/silex/silex/tests/Silex/Tests/Application/MonologTraitTest.php +++ b/vendor/silex/silex/tests/Silex/Tests/Application/MonologTraitTest.php @@ -17,8 +17,6 @@ use Monolog\Handler\TestHandler; use Monolog\Logger; /** - * MonologTrait test cases. - * * @author Fabien Potencier <fabien@symfony.com> */ class MonologTraitTest extends TestCase diff --git a/vendor/silex/silex/tests/Silex/Tests/Application/SecurityTraitTest.php b/vendor/silex/silex/tests/Silex/Tests/Application/SecurityTraitTest.php index ce1ff5d20746f354e0ab815dfae3f16f3c14b927..8918a100cb9e5c8f8e840005455fbd094f06d3c3 100644 --- a/vendor/silex/silex/tests/Silex/Tests/Application/SecurityTraitTest.php +++ b/vendor/silex/silex/tests/Silex/Tests/Application/SecurityTraitTest.php @@ -17,8 +17,6 @@ use Symfony\Component\Security\Core\User\User; use Symfony\Component\HttpFoundation\Request; /** - * SecurityTrait test cases. - * * @author Fabien Potencier <fabien@symfony.com> */ class SecurityTraitTest extends TestCase diff --git a/vendor/silex/silex/tests/Silex/Tests/Application/SwiftmailerTraitTest.php b/vendor/silex/silex/tests/Silex/Tests/Application/SwiftmailerTraitTest.php index 34620b7190bcddcea59f8495537518fb97d7f4d9..fcff77e122098ab2bdf460c700af2d590557e381 100644 --- a/vendor/silex/silex/tests/Silex/Tests/Application/SwiftmailerTraitTest.php +++ b/vendor/silex/silex/tests/Silex/Tests/Application/SwiftmailerTraitTest.php @@ -15,8 +15,6 @@ use PHPUnit\Framework\TestCase; use Silex\Provider\SwiftmailerServiceProvider; /** - * SwiftmailerTrait test cases. - * * @author Fabien Potencier <fabien@symfony.com> */ class SwiftmailerTraitTest extends TestCase diff --git a/vendor/silex/silex/tests/Silex/Tests/Application/TranslationTraitTest.php b/vendor/silex/silex/tests/Silex/Tests/Application/TranslationTraitTest.php index 5c0546002b0988a3fd498909274d4227fa48bfbb..ed4b5fe3e6295f57280a9cdcda6b3f95451b4a0f 100644 --- a/vendor/silex/silex/tests/Silex/Tests/Application/TranslationTraitTest.php +++ b/vendor/silex/silex/tests/Silex/Tests/Application/TranslationTraitTest.php @@ -15,8 +15,6 @@ use PHPUnit\Framework\TestCase; use Silex\Provider\TranslationServiceProvider; /** - * TranslationTrait test cases. - * * @author Fabien Potencier <fabien@symfony.com> */ class TranslationTraitTest extends TestCase diff --git a/vendor/silex/silex/tests/Silex/Tests/Application/TwigTraitTest.php b/vendor/silex/silex/tests/Silex/Tests/Application/TwigTraitTest.php index 09ee8606de789b5e099d1fbee71b2633b308137c..753d92b794c4935d9d63d1c26a10b5da9764b486 100644 --- a/vendor/silex/silex/tests/Silex/Tests/Application/TwigTraitTest.php +++ b/vendor/silex/silex/tests/Silex/Tests/Application/TwigTraitTest.php @@ -17,8 +17,6 @@ use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\StreamedResponse; /** - * TwigTrait test cases. - * * @author Fabien Potencier <fabien@symfony.com> */ class TwigTraitTest extends TestCase diff --git a/vendor/silex/silex/tests/Silex/Tests/ApplicationTest.php b/vendor/silex/silex/tests/Silex/Tests/ApplicationTest.php index c46e4ff9b875b7d82be2f84bcf582bde1a9a160d..ee6c804a54ee26c200ad1fae13b3c7dcbfdc605a 100644 --- a/vendor/silex/silex/tests/Silex/Tests/ApplicationTest.php +++ b/vendor/silex/silex/tests/Silex/Tests/ApplicationTest.php @@ -25,7 +25,6 @@ use Symfony\Component\HttpFoundation\StreamedResponse; use Symfony\Component\HttpKernel\HttpKernelInterface; use Symfony\Component\EventDispatcher\Event; use Symfony\Component\Routing\RouteCollection; -use Symfony\Component\WebLink\HttpHeaderSerializer; /** * Application test cases. @@ -661,10 +660,6 @@ class ApplicationTest extends TestCase public function testWebLinkListener() { - if (!class_exists(HttpHeaderSerializer::class)) { - self::markTestSkipped('Symfony WebLink component is required.'); - } - $app = new Application(); $app->get('/', function () { diff --git a/vendor/silex/silex/tests/Silex/Tests/ControllerResolverTest.php b/vendor/silex/silex/tests/Silex/Tests/ControllerResolverTest.php deleted file mode 100644 index 14ccbbdf7c2ecc3cbd3f1040b633e68d029b214a..0000000000000000000000000000000000000000 --- a/vendor/silex/silex/tests/Silex/Tests/ControllerResolverTest.php +++ /dev/null @@ -1,44 +0,0 @@ -<?php - -/* - * This file is part of the Silex framework. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * This source file is subject to the MIT license that is bundled - * with this source code in the file LICENSE. - */ - -namespace Silex\Tests; - -use PHPUnit\Framework\TestCase; -use Silex\ControllerResolver; -use Silex\Application; -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpKernel\Kernel; - -/** - * ControllerResolver test cases. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class ControllerResolverTest extends TestCase -{ - /** - * @group legacy - */ - public function testGetArguments() - { - if (Kernel::VERSION_ID >= 30100) { - self::markTestSkipped('HttpKernel < 3.1.0 is required'); - } - - $app = new Application(); - $resolver = new ControllerResolver($app); - - $controller = function (Application $app) {}; - - $args = $resolver->getArguments(Request::create('/'), $controller); - $this->assertSame($app, $args[0]); - } -} diff --git a/vendor/silex/silex/tests/Silex/Tests/Provider/AssetServiceProviderTest.php b/vendor/silex/silex/tests/Silex/Tests/Provider/AssetServiceProviderTest.php index 7ddc421851d31169577dd20d0f21e353dd65f5b0..bdca9670b1e2c99490f19138a2565ec8d879e805 100644 --- a/vendor/silex/silex/tests/Silex/Tests/Provider/AssetServiceProviderTest.php +++ b/vendor/silex/silex/tests/Silex/Tests/Provider/AssetServiceProviderTest.php @@ -36,12 +36,6 @@ class AssetServiceProviderTest extends TestCase public function testJsonManifestVersionStrategy() { - if (!class_exists('Symfony\Component\Asset\VersionStrategy\JsonManifestVersionStrategy')) { - $this->markTestSkipped('JsonManifestVersionStrategy class is not available.'); - - return; - } - $app = new Application(); $app->register(new AssetServiceProvider(), [ 'assets.json_manifest_path' => __DIR__.'/../Fixtures/manifest.json', diff --git a/vendor/silex/silex/tests/Silex/Tests/Provider/FormServiceProviderTest.php b/vendor/silex/silex/tests/Silex/Tests/Provider/FormServiceProviderTest.php index 30fae97daa47ad840ebe29fc30324c2a0b7a25ea..dd4727133b508cc4e4fbd754a85248539b7292f3 100644 --- a/vendor/silex/silex/tests/Silex/Tests/Provider/FormServiceProviderTest.php +++ b/vendor/silex/silex/tests/Silex/Tests/Provider/FormServiceProviderTest.php @@ -23,7 +23,6 @@ use Symfony\Component\Form\AbstractTypeExtension; use Symfony\Component\Form\FormTypeGuesserChain; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\OptionsResolver\OptionsResolver; -use Symfony\Component\OptionsResolver\OptionsResolverInterface; use Symfony\Component\Translation\Exception\NotFoundResourceException; class FormServiceProviderTest extends TestCase @@ -313,52 +312,19 @@ class FormServiceProviderTest extends TestCase } } -if (!class_exists('Symfony\Component\Form\Deprecated\FormEvents')) { - class DummyFormType extends AbstractType - { - } -} else { - // FormTypeInterface::getName() is needed by the form component 2.8.x - class DummyFormType extends AbstractType - { - /** - * @return string The name of this type - */ - public function getName() - { - return 'dummy'; - } - } +class DummyFormType extends AbstractType +{ } -if (method_exists('Symfony\Component\Form\AbstractType', 'configureOptions')) { - class DummyFormTypeExtension extends AbstractTypeExtension +class DummyFormTypeExtension extends AbstractTypeExtension +{ + public function getExtendedType() { - public function getExtendedType() - { - return 'Symfony\Component\Form\Extension\Core\Type\FileType'; - } - - public function configureOptions(OptionsResolver $resolver) - { - $resolver->setDefined(['image_path']); - } + return 'Symfony\Component\Form\Extension\Core\Type\FileType'; } -} else { - class DummyFormTypeExtension extends AbstractTypeExtension - { - public function getExtendedType() - { - return 'Symfony\Component\Form\Extension\Core\Type\FileType'; - } - public function setDefaultOptions(OptionsResolverInterface $resolver) - { - if (!method_exists($resolver, 'setDefined')) { - $resolver->setOptional(['image_path']); - } else { - $resolver->setDefined(['image_path']); - } - } + public function configureOptions(OptionsResolver $resolver) + { + $resolver->setDefined(['image_path']); } } diff --git a/vendor/silex/silex/tests/Silex/Tests/Provider/MonologServiceProviderTest.php b/vendor/silex/silex/tests/Silex/Tests/Provider/MonologServiceProviderTest.php index eca21f0a568748201f52dafc5f9af53e3e3f2d08..408fb1c168453119f87fe8d8142ea5ffd83c2f21 100644 --- a/vendor/silex/silex/tests/Silex/Tests/Provider/MonologServiceProviderTest.php +++ b/vendor/silex/silex/tests/Silex/Tests/Provider/MonologServiceProviderTest.php @@ -11,16 +11,15 @@ namespace Silex\Tests\Provider; +use PHPUnit\Framework\TestCase; use Monolog\Formatter\JsonFormatter; use Monolog\Handler\TestHandler; use Monolog\Logger; -use PHPUnit\Framework\TestCase; use Silex\Application; use Silex\Provider\MonologServiceProvider; use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; -use Symfony\Component\HttpKernel\Kernel; /** * MonologProvider test cases. @@ -59,12 +58,8 @@ class MonologServiceProviderTest extends TestCase $this->assertTrue($app['monolog.handler']->hasDebug('< 200')); $records = $app['monolog.handler']->getRecords(); - if (Kernel::VERSION_ID < 30100) { - $this->assertContains('Matched route "GET_foo"', $records[0]['message']); - } else { - $this->assertContains('Matched route "{route}".', $records[0]['message']); - $this->assertSame('GET_foo', $records[0]['context']['route']); - } + $this->assertContains('Matched route "{route}".', $records[0]['message']); + $this->assertSame('GET_foo', $records[0]['context']['route']); } public function testManualLogging() diff --git a/vendor/silex/silex/tests/Silex/Tests/Provider/SecurityServiceProviderTest.php b/vendor/silex/silex/tests/Silex/Tests/Provider/SecurityServiceProviderTest.php index b52040c00891e4a80d4f33923a2ff1b909a40078..ccaa9aafd52675d1f2562fa54d5c1d6a56d1712e 100644 --- a/vendor/silex/silex/tests/Silex/Tests/Provider/SecurityServiceProviderTest.php +++ b/vendor/silex/silex/tests/Silex/Tests/Provider/SecurityServiceProviderTest.php @@ -17,6 +17,7 @@ use Silex\Provider\SecurityServiceProvider; use Silex\Provider\SessionServiceProvider; use Silex\Provider\ValidatorServiceProvider; use Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken; +use Symfony\Component\Security\Core\Exception\AuthenticationException; use Symfony\Component\HttpKernel\Client; use Symfony\Component\HttpFoundation\Request; @@ -181,6 +182,13 @@ class SecurityServiceProviderTest extends WebTestCase $client->request('post', '/login_check', ['_username' => 'unknown', '_password' => 'bar']); $this->assertEquals('Username "unknown" does not exist.', $app['security.last_error']($client->getRequest())); $client->getRequest()->getSession()->save(); + + $client->request('post', '/login_check', ['_username' => 'unknown', '_password' => 'bar']); + $app['request_stack']->push($client->getRequest()); + $authenticationException = $app['security.authentication_utils']->getLastAuthenticationError(); + $this->assertInstanceOf(AuthenticationException::class, $authenticationException); + $this->assertEquals('Username "unknown" does not exist.', $authenticationException->getMessage()); + $client->getRequest()->getSession()->save(); } public function testFakeRoutesAreSerializable() @@ -278,6 +286,36 @@ class SecurityServiceProviderTest extends WebTestCase $this->assertEquals('fabien', $app['user']->getUsername()); } + public function testUserAsServiceString() + { + $users = [ + 'fabien' => ['ROLE_ADMIN', '$2y$15$lzUNsTegNXvZW3qtfucV0erYBcEqWVeyOmjolB7R1uodsAVJ95vvu'], + ]; + + $app = new Application(); + $app->register(new SecurityServiceProvider(), [ + 'security.firewalls' => [ + 'default' => [ + 'http' => true, + 'users' => 'my_user_provider', + ], + ], + ]); + $app['my_user_provider'] = $app['security.user_provider.inmemory._proto']($users); + $app->get('/', function () { return 'foo'; }); + + $request = Request::create('/'); + $app->handle($request); + $this->assertNull($app['user']); + $this->assertSame($app['my_user_provider'], $app['security.user_provider.default']); + + $request->headers->set('PHP_AUTH_USER', 'fabien'); + $request->headers->set('PHP_AUTH_PW', 'foo'); + $app->handle($request); + $this->assertInstanceOf('Symfony\Component\Security\Core\User\UserInterface', $app['user']); + $this->assertEquals('fabien', $app['user']->getUsername()); + } + public function testUserWithNoToken() { $app = new Application(); diff --git a/vendor/silex/silex/tests/Silex/Tests/Provider/SecurityServiceProviderTest/TokenAuthenticator.php b/vendor/silex/silex/tests/Silex/Tests/Provider/SecurityServiceProviderTest/TokenAuthenticator.php index 3435fd12908d4fbca24cb4bd8967b6a67a4fe100..75bb54bd9b3738fefed8d7c855315c785fb20426 100644 --- a/vendor/silex/silex/tests/Silex/Tests/Provider/SecurityServiceProviderTest/TokenAuthenticator.php +++ b/vendor/silex/silex/tests/Silex/Tests/Provider/SecurityServiceProviderTest/TokenAuthenticator.php @@ -13,7 +13,6 @@ namespace Silex\Tests\Provider\SecurityServiceProviderTest; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\JsonResponse; -use Symfony\Component\HttpKernel\Kernel; use Symfony\Component\Security\Core\User\UserInterface; use Symfony\Component\Security\Core\User\UserProviderInterface; use Symfony\Component\Security\Guard\AbstractGuardAuthenticator; @@ -28,7 +27,7 @@ class TokenAuthenticator extends AbstractGuardAuthenticator public function getCredentials(Request $request) { if (!$token = $request->headers->get('X-AUTH-TOKEN')) { - return Kernel::VERSION_ID < 30400 ? null : false; + return false; } list($username, $secret) = explode(':', $token); diff --git a/vendor/silex/silex/tests/Silex/Tests/Provider/TwigServiceProviderTest.php b/vendor/silex/silex/tests/Silex/Tests/Provider/TwigServiceProviderTest.php index 58b2f28e1fbd1be23b4e77b909cdba7eddc7e55f..852dcebe4e57535431a56eb9c0d6c5a3a16eb5ca 100644 --- a/vendor/silex/silex/tests/Silex/Tests/Provider/TwigServiceProviderTest.php +++ b/vendor/silex/silex/tests/Silex/Tests/Provider/TwigServiceProviderTest.php @@ -18,10 +18,7 @@ use Silex\Provider\CsrfServiceProvider; use Silex\Provider\FormServiceProvider; use Silex\Provider\TwigServiceProvider; use Silex\Provider\AssetServiceProvider; -use Symfony\Bridge\Twig\Extension\WebLinkExtension; use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpKernel\Kernel; -use Symfony\Component\WebLink\HttpHeaderSerializer; /** * TwigProvider test cases. @@ -112,11 +109,7 @@ class TwigServiceProviderTest extends TestCase $this->assertInstanceOf('Twig_Environment', $app['twig']); $this->assertInstanceOf('Symfony\Bridge\Twig\Form\TwigRendererEngine', $app['twig.form.engine']); - if (Kernel::VERSION_ID < 30400) { - $this->assertInstanceOf('Symfony\Bridge\Twig\Form\TwigRenderer', $app['twig.form.renderer']); - } else { - $this->assertInstanceOf('Symfony\Component\Form\FormRenderer', $app['twig.form.renderer']); - } + $this->assertInstanceOf('Symfony\Component\Form\FormRenderer', $app['twig.form.renderer']); } public function testFormWithoutCsrf() @@ -152,10 +145,6 @@ class TwigServiceProviderTest extends TestCase public function testWebLinkIntegration() { - if (!class_exists(HttpHeaderSerializer::class) || !class_exists(WebLinkExtension::class)) { - $this->markTestSkipped('Twig WebLink extension not available.'); - } - $app = new Application(); $app['request_stack']->push($request = Request::create('/')); $app->register(new TwigServiceProvider(), [ diff --git a/vendor/silex/silex/tests/Silex/Tests/Provider/ValidatorServiceProviderTest.php b/vendor/silex/silex/tests/Silex/Tests/Provider/ValidatorServiceProviderTest.php index 14c7f09738d1d9d423d7918dc9fef6ecbc27fae2..832abb3c56a3f835134c2b72e2fcb739b3dfe996 100644 --- a/vendor/silex/silex/tests/Silex/Tests/Provider/ValidatorServiceProviderTest.php +++ b/vendor/silex/silex/tests/Silex/Tests/Provider/ValidatorServiceProviderTest.php @@ -20,7 +20,6 @@ use Symfony\Component\Translation\Exception\NotFoundResourceException; use Symfony\Component\Validator\Constraints as Assert; use Silex\Tests\Provider\ValidatorServiceProviderTest\Constraint\Custom; use Silex\Tests\Provider\ValidatorServiceProviderTest\Constraint\CustomValidator; -use Symfony\Component\Validator\ValidatorInterface as LegacyValidatorInterface; use Symfony\Component\Validator\Validator\ValidatorInterface; /** @@ -36,8 +35,6 @@ class ValidatorServiceProviderTest extends TestCase $app->register(new ValidatorServiceProvider()); $app->register(new FormServiceProvider()); - $this->assertInstanceOf('Symfony\Component\Validator\Validator\ValidatorInterface', $app['validator']); - return $app; } @@ -55,8 +52,6 @@ class ValidatorServiceProviderTest extends TestCase ], ]); - $this->assertInstanceOf('Symfony\Component\Validator\Validator\ValidatorInterface', $app['validator']); - return $app; } @@ -86,7 +81,7 @@ class ValidatorServiceProviderTest extends TestCase */ public function testValidatorServiceIsAValidator($app) { - $this->assertTrue($app['validator'] instanceof ValidatorInterface || $app['validator'] instanceof LegacyValidatorInterface); + $this->assertTrue($app['validator'] instanceof ValidatorInterface); } /** @@ -160,7 +155,7 @@ class ValidatorServiceProviderTest extends TestCase $app->register(new ValidatorServiceProvider()); $app->register(new TranslationServiceProvider()); - $app['translator'] = $app->extend('translator', function ($translator, $app) { + $app->extend('translator', function ($translator, $app) { $translator->addResource('array', ['This value should not be blank.' => 'Pas vide'], 'fr', 'validators'); return $translator; diff --git a/vendor/silex/silex/tests/Silex/Tests/ServiceControllerResolverTest.php b/vendor/silex/silex/tests/Silex/Tests/ServiceControllerResolverTest.php index e1404eea3e5c155d58ca827e7052414a04967fd3..f5e446954c0ffe534e5c2d1401be9aa72bcdeeed 100644 --- a/vendor/silex/silex/tests/Silex/Tests/ServiceControllerResolverTest.php +++ b/vendor/silex/silex/tests/Silex/Tests/ServiceControllerResolverTest.php @@ -15,7 +15,6 @@ use PHPUnit\Framework\TestCase; use Silex\ServiceControllerResolver; use Silex\Application; use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpKernel\Kernel; /** * Unit tests for ServiceControllerResolver, see ServiceControllerResolverRouterTest for some @@ -77,22 +76,4 @@ class ServiceControllerResolverTest extends Testcase $this->assertEquals(123, $this->resolver->getController($req)); } - - /** - * @group legacy - */ - public function testShouldDelegateGetArguments() - { - if (Kernel::VERSION_ID >= 40000) { - self::markTestSkipped('HttpKernel < 4.0 is required'); - } - - $req = Request::create('/'); - $this->mockResolver->expects($this->once()) - ->method('getArguments') - ->with($req) - ->will($this->returnValue(123)); - - $this->assertEquals(123, $this->resolver->getArguments($req, function () {})); - } } diff --git a/vendor/symfony/debug/BufferingLogger.php b/vendor/symfony/debug/BufferingLogger.php index a2ed75b9dc9f1f8833a7595abf1dd12506bbc159..e7db3a4ce4c6af5f4e79dbc04b4578afb73d292b 100644 --- a/vendor/symfony/debug/BufferingLogger.php +++ b/vendor/symfony/debug/BufferingLogger.php @@ -20,17 +20,17 @@ use Psr\Log\AbstractLogger; */ class BufferingLogger extends AbstractLogger { - private $logs = array(); + private $logs = []; - public function log($level, $message, array $context = array()) + public function log($level, $message, array $context = []) { - $this->logs[] = array($level, $message, $context); + $this->logs[] = [$level, $message, $context]; } public function cleanLogs() { $logs = $this->logs; - $this->logs = array(); + $this->logs = []; return $logs; } diff --git a/vendor/symfony/debug/CHANGELOG.md b/vendor/symfony/debug/CHANGELOG.md index 31c67eb60cce94e985828c572a9ac0bb80179971..367e834f01e7e5914976337e06afe134c1c2cac7 100644 --- a/vendor/symfony/debug/CHANGELOG.md +++ b/vendor/symfony/debug/CHANGELOG.md @@ -1,6 +1,20 @@ CHANGELOG ========= +4.3.0 +----- + +* made the `ErrorHandler` and `ExceptionHandler` classes final +* added `Exception\FlattenException::getAsString` and +`Exception\FlattenException::getTraceAsString` to increase compatibility to php +exception objects + +4.0.0 +----- + +* removed the symfony_debug extension +* removed `ContextErrorException` + 3.4.0 ----- diff --git a/vendor/symfony/debug/Debug.php b/vendor/symfony/debug/Debug.php index e3665ae5f40c893269e6e004c5cedc67205ea026..5d2d55cf9f02192d4ea56d36c8a3169be36d055a 100644 --- a/vendor/symfony/debug/Debug.php +++ b/vendor/symfony/debug/Debug.php @@ -25,9 +25,6 @@ class Debug * * This method registers an error handler and an exception handler. * - * If the Symfony ClassLoader component is available, a special - * class loader is also registered. - * * @param int $errorReportingLevel The level of error reporting you want * @param bool $displayErrors Whether to display errors (for development) or just log them (for production) */ @@ -45,10 +42,10 @@ class Debug error_reporting(E_ALL); } - if ('cli' !== PHP_SAPI) { + if (!\in_array(\PHP_SAPI, ['cli', 'phpdbg'], true)) { ini_set('display_errors', 0); ExceptionHandler::register(); - } elseif ($displayErrors && (!ini_get('log_errors') || ini_get('error_log'))) { + } elseif ($displayErrors && (!filter_var(ini_get('log_errors'), FILTER_VALIDATE_BOOLEAN) || ini_get('error_log'))) { // CLI - display errors only if they're not already logged to STDERR ini_set('display_errors', 1); } diff --git a/vendor/symfony/debug/DebugClassLoader.php b/vendor/symfony/debug/DebugClassLoader.php index 78bfb85388022f4b9dacd0a88dbbd0866a127a00..42e803b9db4edcb056def7da16fc87107c750fb7 100644 --- a/vendor/symfony/debug/DebugClassLoader.php +++ b/vendor/symfony/debug/DebugClassLoader.php @@ -11,6 +11,8 @@ namespace Symfony\Component\Debug; +use PHPUnit\Framework\MockObject\Matcher\StatelessInvocation; + /** * Autoloader checking if the class is really defined in the file found. * @@ -21,30 +23,32 @@ namespace Symfony\Component\Debug; * @author Fabien Potencier <fabien@symfony.com> * @author Christophe Coevoet <stof@notk.org> * @author Nicolas Grekas <p@tchwork.com> + * @author Guilhem Niot <guilhem.niot@gmail.com> */ class DebugClassLoader { private $classLoader; private $isFinder; - private $loaded = array(); + private $loaded = []; private static $caseCheck; - private static $checkedClasses = array(); - private static $final = array(); - private static $finalMethods = array(); - private static $deprecated = array(); - private static $internal = array(); - private static $internalMethods = array(); - private static $php7Reserved = array('int' => 1, 'float' => 1, 'bool' => 1, 'string' => 1, 'true' => 1, 'false' => 1, 'null' => 1); - private static $darwinCache = array('/' => array('/', array())); + private static $checkedClasses = []; + private static $final = []; + private static $finalMethods = []; + private static $deprecated = []; + private static $internal = []; + private static $internalMethods = []; + private static $annotatedParameters = []; + private static $darwinCache = ['/' => ['/', []]]; + private static $method = []; public function __construct(callable $classLoader) { $this->classLoader = $classLoader; - $this->isFinder = is_array($classLoader) && method_exists($classLoader[0], 'findFile'); + $this->isFinder = \is_array($classLoader) && method_exists($classLoader[0], 'findFile'); if (!isset(self::$caseCheck)) { - $file = file_exists(__FILE__) ? __FILE__ : rtrim(realpath('.'), DIRECTORY_SEPARATOR); - $i = strrpos($file, DIRECTORY_SEPARATOR); + $file = file_exists(__FILE__) ? __FILE__ : rtrim(realpath('.'), \DIRECTORY_SEPARATOR); + $i = strrpos($file, \DIRECTORY_SEPARATOR); $dir = substr($file, 0, 1 + $i); $file = substr($file, 1 + $i); $test = strtoupper($file) === $file ? strtolower($file) : strtoupper($file); @@ -53,7 +57,7 @@ class DebugClassLoader if (false === $test || false === $i) { // filesystem is case sensitive self::$caseCheck = 0; - } elseif (substr($test, -strlen($file)) === $file) { + } elseif (substr($test, -\strlen($file)) === $file) { // filesystem is case insensitive and realpath() normalizes the case of characters self::$caseCheck = 1; } elseif (false !== stripos(PHP_OS, 'darwin')) { @@ -85,7 +89,7 @@ class DebugClassLoader class_exists('Symfony\Component\Debug\ErrorHandler'); class_exists('Psr\Log\LogLevel'); - if (!is_array($functions = spl_autoload_functions())) { + if (!\is_array($functions = spl_autoload_functions())) { return; } @@ -94,8 +98,8 @@ class DebugClassLoader } foreach ($functions as $function) { - if (!is_array($function) || !$function[0] instanceof self) { - $function = array(new static($function), 'loadClass'); + if (!\is_array($function) || !$function[0] instanceof self) { + $function = [new static($function), 'loadClass']; } spl_autoload_register($function); @@ -107,7 +111,7 @@ class DebugClassLoader */ public static function disable() { - if (!is_array($functions = spl_autoload_functions())) { + if (!\is_array($functions = spl_autoload_functions())) { return; } @@ -116,7 +120,7 @@ class DebugClassLoader } foreach ($functions as $function) { - if (is_array($function) && $function[0] instanceof self) { + if (\is_array($function) && $function[0] instanceof self) { $function = $function[0]->getClassLoader(); } @@ -124,13 +128,19 @@ class DebugClassLoader } } + /** + * @return string|null + */ + public function findFile($class) + { + return $this->isFinder ? $this->classLoader[0]->findFile($class) ?: null : null; + } + /** * Loads the given class or interface. * * @param string $class The name of the class * - * @return bool|null True, if loaded - * * @throws \RuntimeException */ public function loadClass($class) @@ -140,17 +150,17 @@ class DebugClassLoader try { if ($this->isFinder && !isset($this->loaded[$class])) { $this->loaded[$class] = true; - if ($file = $this->classLoader[0]->findFile($class) ?: false) { - $wasCached = \function_exists('opcache_is_script_cached') && opcache_is_script_cached($file); - - require $file; - - if ($wasCached) { - return; - } + if (!$file = $this->classLoader[0]->findFile($class) ?: false) { + // no-op + } elseif (\function_exists('opcache_is_script_cached') && @opcache_is_script_cached($file)) { + include $file; + + return; + } elseif (false === include $file) { + return; } } else { - call_user_func($this->classLoader, $class); + ($this->classLoader)($class); $file = false; } } finally { @@ -162,7 +172,7 @@ class DebugClassLoader private function checkClass($class, $file = null) { - $exists = null === $file || \class_exists($class, false) || \interface_exists($class, false) || \trait_exists($class, false); + $exists = null === $file || class_exists($class, false) || interface_exists($class, false) || trait_exists($class, false); if (null !== $file && $class && '\\' === $class[0]) { $class = substr($class, 1); @@ -180,204 +190,318 @@ class DebugClassLoader } $name = $refl->getName(); - if ($name !== $class && 0 === \strcasecmp($name, $class)) { + if ($name !== $class && 0 === strcasecmp($name, $class)) { throw new \RuntimeException(sprintf('Case mismatch between loaded and declared class names: "%s" vs "%s".', $class, $name)); } - // Don't trigger deprecations for classes in the same vendor - if (2 > $len = 1 + (\strpos($name, '\\') ?: \strpos($name, '_'))) { - $len = 0; - $ns = ''; - } else { - $ns = \substr($name, 0, $len); + $deprecations = $this->checkAnnotations($refl, $name); + + foreach ($deprecations as $message) { + @trigger_error($message, E_USER_DEPRECATED); } + } - // Detect annotations on the class - if (false !== $doc = $refl->getDocComment()) { - foreach (array('final', 'deprecated', 'internal') as $annotation) { - if (false !== \strpos($doc, $annotation) && preg_match('#\n \* @'.$annotation.'(?:( .+?)\.?)?\r?\n \*(?: @|/$)#s', $doc, $notice)) { - self::${$annotation}[$name] = isset($notice[1]) ? preg_replace('#\s*\r?\n \* +#', ' ', $notice[1]) : ''; - } - } + if (!$file) { + return; + } + + if (!$exists) { + if (false !== strpos($class, '/')) { + throw new \RuntimeException(sprintf('Trying to autoload a class with an invalid name "%s". Be careful that the namespace separator is "\" in PHP, not "/".', $class)); } - $parentAndTraits = \class_uses($name, false); - if ($parent = \get_parent_class($class)) { - $parentAndTraits[] = $parent; + throw new \RuntimeException(sprintf('The autoloader expected class "%s" to be defined in file "%s". The file was found but the class was not in it, the class name or namespace probably has a typo.', $class, $file)); + } - if (!isset(self::$checkedClasses[$parent])) { - $this->checkClass($parent); - } + if (self::$caseCheck && $message = $this->checkCase($refl, $file, $class)) { + throw new \RuntimeException(sprintf('Case mismatch between class and real file names: "%s" vs "%s" in "%s".', $message[0], $message[1], $message[2])); + } + } + + public function checkAnnotations(\ReflectionClass $refl, $class) + { + $deprecations = []; + + // Don't trigger deprecations for classes in the same vendor + if (2 > $len = 1 + (strpos($class, '\\') ?: strpos($class, '_'))) { + $len = 0; + $ns = ''; + } else { + $ns = str_replace('_', '\\', substr($class, 0, $len)); + } - if (isset(self::$final[$parent])) { - @trigger_error(sprintf('The "%s" class is considered final%s. It may change without further notice as of its next major version. You should not extend it from "%s".', $parent, self::$final[$parent], $name), E_USER_DEPRECATED); + // Detect annotations on the class + if (false !== $doc = $refl->getDocComment()) { + foreach (['final', 'deprecated', 'internal'] as $annotation) { + if (false !== strpos($doc, $annotation) && preg_match('#\n\s+\* @'.$annotation.'(?:( .+?)\.?)?\r?\n\s+\*(?: @|/$|\r?\n)#s', $doc, $notice)) { + self::${$annotation}[$class] = isset($notice[1]) ? preg_replace('#\.?\r?\n( \*)? *(?= |\r?\n|$)#', '', $notice[1]) : ''; } } - // Detect if the parent is annotated - foreach ($parentAndTraits + $this->getOwnInterfaces($name, $parent) as $use) { - if (!isset(self::$checkedClasses[$use])) { - $this->checkClass($use); + if ($refl->isInterface() && false !== strpos($doc, 'method') && preg_match_all('#\n \* @method\s+(static\s+)?+(?:[\w\|&\[\]\\\]+\s+)?(\w+(?:\s*\([^\)]*\))?)+(.+?([[:punct:]]\s*)?)?(?=\r?\n \*(?: @|/$|\r?\n))#', $doc, $notice, PREG_SET_ORDER)) { + foreach ($notice as $method) { + $static = '' !== $method[1]; + $name = $method[2]; + $description = $method[3] ?? null; + if (false === strpos($name, '(')) { + $name .= '()'; + } + if (null !== $description) { + $description = trim($description); + if (!isset($method[4])) { + $description .= '.'; + } + } + self::$method[$class][] = [$class, $name, $static, $description]; } - if (isset(self::$deprecated[$use]) && \strncmp($ns, $use, $len)) { - $type = class_exists($name, false) ? 'class' : (interface_exists($name, false) ? 'interface' : 'trait'); - $verb = class_exists($use, false) || interface_exists($name, false) ? 'extends' : (interface_exists($use, false) ? 'implements' : 'uses'); + } + } - @trigger_error(sprintf('The "%s" %s %s "%s" that is deprecated%s.', $name, $type, $verb, $use, self::$deprecated[$use]), E_USER_DEPRECATED); - } - if (isset(self::$internal[$use]) && \strncmp($ns, $use, $len)) { - @trigger_error(sprintf('The "%s" %s is considered internal%s. It may change without further notice. You should not use it from "%s".', $use, class_exists($use, false) ? 'class' : (interface_exists($use, false) ? 'interface' : 'trait'), self::$internal[$use], $name), E_USER_DEPRECATED); - } + $parent = get_parent_class($class); + $parentAndOwnInterfaces = $this->getOwnInterfaces($class, $parent); + if ($parent) { + $parentAndOwnInterfaces[$parent] = $parent; + + if (!isset(self::$checkedClasses[$parent])) { + $this->checkClass($parent); + } + + if (isset(self::$final[$parent])) { + $deprecations[] = sprintf('The "%s" class is considered final%s. It may change without further notice as of its next major version. You should not extend it from "%s".', $parent, self::$final[$parent], $class); + } + } + + // Detect if the parent is annotated + foreach ($parentAndOwnInterfaces + class_uses($class, false) as $use) { + if (!isset(self::$checkedClasses[$use])) { + $this->checkClass($use); } + if (isset(self::$deprecated[$use]) && strncmp($ns, str_replace('_', '\\', $use), $len) && !isset(self::$deprecated[$class])) { + $type = class_exists($class, false) ? 'class' : (interface_exists($class, false) ? 'interface' : 'trait'); + $verb = class_exists($use, false) || interface_exists($class, false) ? 'extends' : (interface_exists($use, false) ? 'implements' : 'uses'); - // Inherit @final and @internal annotations for methods - self::$finalMethods[$name] = array(); - self::$internalMethods[$name] = array(); - foreach ($parentAndTraits as $use) { - foreach (array('finalMethods', 'internalMethods') as $property) { - if (isset(self::${$property}[$use])) { - self::${$property}[$name] = self::${$property}[$name] ? self::${$property}[$use] + self::${$property}[$name] : self::${$property}[$use]; + $deprecations[] = sprintf('The "%s" %s %s "%s" that is deprecated%s.', $class, $type, $verb, $use, self::$deprecated[$use]); + } + if (isset(self::$internal[$use]) && strncmp($ns, str_replace('_', '\\', $use), $len)) { + $deprecations[] = sprintf('The "%s" %s is considered internal%s. It may change without further notice. You should not use it from "%s".', $use, class_exists($use, false) ? 'class' : (interface_exists($use, false) ? 'interface' : 'trait'), self::$internal[$use], $class); + } + if (isset(self::$method[$use])) { + if ($refl->isAbstract()) { + if (isset(self::$method[$class])) { + self::$method[$class] = array_merge(self::$method[$class], self::$method[$use]); + } else { + self::$method[$class] = self::$method[$use]; + } + } elseif (!$refl->isInterface()) { + $hasCall = $refl->hasMethod('__call'); + $hasStaticCall = $refl->hasMethod('__callStatic'); + foreach (self::$method[$use] as $method) { + list($interface, $name, $static, $description) = $method; + if ($static ? $hasStaticCall : $hasCall) { + continue; + } + $realName = substr($name, 0, strpos($name, '(')); + if (!$refl->hasMethod($realName) || !($methodRefl = $refl->getMethod($realName))->isPublic() || ($static && !$methodRefl->isStatic()) || (!$static && $methodRefl->isStatic())) { + $deprecations[] = sprintf('Class "%s" should implement method "%s::%s"%s', $class, ($static ? 'static ' : '').$interface, $name, null == $description ? '.' : ': '.$description); + } } } } + } - $isClass = \class_exists($name, false); - foreach ($refl->getMethods(\ReflectionMethod::IS_PUBLIC | \ReflectionMethod::IS_PROTECTED) as $method) { - if ($method->class !== $name) { - continue; - } + if (trait_exists($class)) { + return $deprecations; + } - // Method from a trait - if ($method->getFilename() !== $refl->getFileName()) { - continue; + // Inherit @final, @internal and @param annotations for methods + self::$finalMethods[$class] = []; + self::$internalMethods[$class] = []; + self::$annotatedParameters[$class] = []; + foreach ($parentAndOwnInterfaces as $use) { + foreach (['finalMethods', 'internalMethods', 'annotatedParameters'] as $property) { + if (isset(self::${$property}[$use])) { + self::${$property}[$class] = self::${$property}[$class] ? self::${$property}[$use] + self::${$property}[$class] : self::${$property}[$use]; } + } + } - if ($isClass && $parent && isset(self::$finalMethods[$parent][$method->name])) { - list($declaringClass, $message) = self::$finalMethods[$parent][$method->name]; - @trigger_error(sprintf('The "%s::%s()" method is considered final%s. It may change without further notice as of its next major version. You should not extend it from "%s".', $declaringClass, $method->name, $message, $name), E_USER_DEPRECATED); - } + foreach ($refl->getMethods(\ReflectionMethod::IS_PUBLIC | \ReflectionMethod::IS_PROTECTED) as $method) { + if ($method->class !== $class) { + continue; + } - foreach ($parentAndTraits as $use) { - if (isset(self::$internalMethods[$use][$method->name])) { - list($declaringClass, $message) = self::$internalMethods[$use][$method->name]; - if (\strncmp($ns, $declaringClass, $len)) { - @trigger_error(sprintf('The "%s::%s()" method is considered internal%s. It may change without further notice. You should not extend it from "%s".', $declaringClass, $method->name, $message, $name), E_USER_DEPRECATED); - } - } + if ($parent && isset(self::$finalMethods[$parent][$method->name])) { + list($declaringClass, $message) = self::$finalMethods[$parent][$method->name]; + $deprecations[] = sprintf('The "%s::%s()" method is considered final%s. It may change without further notice as of its next major version. You should not extend it from "%s".', $declaringClass, $method->name, $message, $class); + } + + if (isset(self::$internalMethods[$class][$method->name])) { + list($declaringClass, $message) = self::$internalMethods[$class][$method->name]; + if (strncmp($ns, $declaringClass, $len)) { + $deprecations[] = sprintf('The "%s::%s()" method is considered internal%s. It may change without further notice. You should not extend it from "%s".', $declaringClass, $method->name, $message, $class); } + } + + // To read method annotations + $doc = $method->getDocComment(); - // Detect method annotations - if (false === $doc = $method->getDocComment()) { - continue; + if (isset(self::$annotatedParameters[$class][$method->name])) { + $definedParameters = []; + foreach ($method->getParameters() as $parameter) { + $definedParameters[$parameter->name] = true; } - foreach (array('final', 'internal') as $annotation) { - if (false !== \strpos($doc, $annotation) && preg_match('#\n\s+\* @'.$annotation.'(?:( .+?)\.?)?\r?\n\s+\*(?: @|/$)#s', $doc, $notice)) { - $message = isset($notice[1]) ? preg_replace('#\s*\r?\n \* +#', ' ', $notice[1]) : ''; - self::${$annotation.'Methods'}[$name][$method->name] = array($name, $message); + foreach (self::$annotatedParameters[$class][$method->name] as $parameterName => $deprecation) { + if (!isset($definedParameters[$parameterName]) && !($doc && preg_match("/\\n\\s+\\* @param +((?(?!callable *\().*?|callable *\(.*\).*?))(?<= )\\\${$parameterName}\\b/", $doc))) { + $deprecations[] = sprintf($deprecation, $class); } } } - if (isset(self::$php7Reserved[\strtolower($refl->getShortName())])) { - @trigger_error(sprintf('The "%s" class uses the reserved name "%s", it will break on PHP 7 and higher', $name, $refl->getShortName()), E_USER_DEPRECATED); + if (!$doc) { + continue; } - } - if ($file) { - if (!$exists) { - if (false !== strpos($class, '/')) { - throw new \RuntimeException(sprintf('Trying to autoload a class with an invalid name "%s". Be careful that the namespace separator is "\" in PHP, not "/".', $class)); + $finalOrInternal = false; + + foreach (['final', 'internal'] as $annotation) { + if (false !== strpos($doc, $annotation) && preg_match('#\n\s+\* @'.$annotation.'(?:( .+?)\.?)?\r?\n\s+\*(?: @|/$|\r?\n)#s', $doc, $notice)) { + $message = isset($notice[1]) ? preg_replace('#\.?\r?\n( \*)? *(?= |\r?\n|$)#', '', $notice[1]) : ''; + self::${$annotation.'Methods'}[$class][$method->name] = [$class, $message]; + $finalOrInternal = true; } + } - throw new \RuntimeException(sprintf('The autoloader expected class "%s" to be defined in file "%s". The file was found but the class was not in it, the class name or namespace probably has a typo.', $class, $file)); + if ($finalOrInternal || $method->isConstructor() || false === strpos($doc, '@param') || StatelessInvocation::class === $class) { + continue; + } + if (!preg_match_all('#\n\s+\* @param +((?(?!callable *\().*?|callable *\(.*\).*?))(?<= )\$([a-zA-Z0-9_\x7f-\xff]++)#', $doc, $matches, PREG_SET_ORDER)) { + continue; + } + if (!isset(self::$annotatedParameters[$class][$method->name])) { + $definedParameters = []; + foreach ($method->getParameters() as $parameter) { + $definedParameters[$parameter->name] = true; + } + } + foreach ($matches as list(, $parameterType, $parameterName)) { + if (!isset($definedParameters[$parameterName])) { + $parameterType = trim($parameterType); + self::$annotatedParameters[$class][$method->name][$parameterName] = sprintf('The "%%s::%s()" method will require a new "%s$%s" argument in the next major version of its parent class "%s", not defining it is deprecated.', $method->name, $parameterType ? $parameterType.' ' : '', $parameterName, $method->class); + } } - if (self::$caseCheck) { - $real = explode('\\', $class.strrchr($file, '.')); - $tail = explode(DIRECTORY_SEPARATOR, str_replace('/', DIRECTORY_SEPARATOR, $file)); + } - $i = count($tail) - 1; - $j = count($real) - 1; + return $deprecations; + } - while (isset($tail[$i], $real[$j]) && $tail[$i] === $real[$j]) { - --$i; - --$j; - } + /** + * @param string $file + * @param string $class + * + * @return array|null + */ + public function checkCase(\ReflectionClass $refl, $file, $class) + { + $real = explode('\\', $class.strrchr($file, '.')); + $tail = explode(\DIRECTORY_SEPARATOR, str_replace('/', \DIRECTORY_SEPARATOR, $file)); - array_splice($tail, 0, $i + 1); - } - if (self::$caseCheck && $tail) { - $tail = DIRECTORY_SEPARATOR.implode(DIRECTORY_SEPARATOR, $tail); - $tailLen = strlen($tail); - $real = $refl->getFileName(); + $i = \count($tail) - 1; + $j = \count($real) - 1; - if (2 === self::$caseCheck) { - // realpath() on MacOSX doesn't normalize the case of characters + while (isset($tail[$i], $real[$j]) && $tail[$i] === $real[$j]) { + --$i; + --$j; + } - $i = 1 + strrpos($real, '/'); - $file = substr($real, $i); - $real = substr($real, 0, $i); + array_splice($tail, 0, $i + 1); - if (isset(self::$darwinCache[$real])) { - $kDir = $real; - } else { - $kDir = strtolower($real); - - if (isset(self::$darwinCache[$kDir])) { - $real = self::$darwinCache[$kDir][0]; - } else { - $dir = getcwd(); - chdir($real); - $real = getcwd().'/'; - chdir($dir); - - $dir = $real; - $k = $kDir; - $i = strlen($dir) - 1; - while (!isset(self::$darwinCache[$k])) { - self::$darwinCache[$k] = array($dir, array()); - self::$darwinCache[$dir] = &self::$darwinCache[$k]; - - while ('/' !== $dir[--$i]) { - } - $k = substr($k, 0, ++$i); - $dir = substr($dir, 0, $i--); - } - } - } + if (!$tail) { + return null; + } - $dirFiles = self::$darwinCache[$kDir][1]; + $tail = \DIRECTORY_SEPARATOR.implode(\DIRECTORY_SEPARATOR, $tail); + $tailLen = \strlen($tail); + $real = $refl->getFileName(); - if (isset($dirFiles[$file])) { - $kFile = $file; - } else { - $kFile = strtolower($file); - - if (!isset($dirFiles[$kFile])) { - foreach (scandir($real, 2) as $f) { - if ('.' !== $f[0]) { - $dirFiles[$f] = $f; - if ($f === $file) { - $kFile = $k = $file; - } elseif ($f !== $k = strtolower($f)) { - $dirFiles[$k] = $f; - } - } - } - self::$darwinCache[$kDir][1] = $dirFiles; - } - } + if (2 === self::$caseCheck) { + $real = $this->darwinRealpath($real); + } + + if (0 === substr_compare($real, $tail, -$tailLen, $tailLen, true) + && 0 !== substr_compare($real, $tail, -$tailLen, $tailLen, false) + ) { + return [substr($tail, -$tailLen + 1), substr($real, -$tailLen + 1), substr($real, 0, -$tailLen + 1)]; + } + + return null; + } + + /** + * `realpath` on MacOSX doesn't normalize the case of characters. + */ + private function darwinRealpath($real) + { + $i = 1 + strrpos($real, '/'); + $file = substr($real, $i); + $real = substr($real, 0, $i); - $real .= $dirFiles[$kFile]; + if (isset(self::$darwinCache[$real])) { + $kDir = $real; + } else { + $kDir = strtolower($real); + + if (isset(self::$darwinCache[$kDir])) { + $real = self::$darwinCache[$kDir][0]; + } else { + $dir = getcwd(); + chdir($real); + $real = getcwd().'/'; + chdir($dir); + + $dir = $real; + $k = $kDir; + $i = \strlen($dir) - 1; + while (!isset(self::$darwinCache[$k])) { + self::$darwinCache[$k] = [$dir, []]; + self::$darwinCache[$dir] = &self::$darwinCache[$k]; + + while ('/' !== $dir[--$i]) { + } + $k = substr($k, 0, ++$i); + $dir = substr($dir, 0, $i--); } + } + } + + $dirFiles = self::$darwinCache[$kDir][1]; - if (0 === substr_compare($real, $tail, -$tailLen, $tailLen, true) - && 0 !== substr_compare($real, $tail, -$tailLen, $tailLen, false) - ) { - throw new \RuntimeException(sprintf('Case mismatch between class and real file names: "%s" vs "%s" in "%s".', substr($tail, -$tailLen + 1), substr($real, -$tailLen + 1), substr($real, 0, -$tailLen + 1))); + if (!isset($dirFiles[$file]) && ') : eval()\'d code' === substr($file, -17)) { + // Get the file name from "file_name.php(123) : eval()'d code" + $file = substr($file, 0, strrpos($file, '(', -17)); + } + + if (isset($dirFiles[$file])) { + return $real .= $dirFiles[$file]; + } + + $kFile = strtolower($file); + + if (!isset($dirFiles[$kFile])) { + foreach (scandir($real, 2) as $f) { + if ('.' !== $f[0]) { + $dirFiles[$f] = $f; + if ($f === $file) { + $kFile = $k = $file; + } elseif ($f !== $k = strtolower($f)) { + $dirFiles[$k] = $f; + } } } + self::$darwinCache[$kDir][1] = $dirFiles; } + + return $real .= $dirFiles[$kFile]; } /** diff --git a/vendor/symfony/debug/ErrorHandler.php b/vendor/symfony/debug/ErrorHandler.php index 90e5535d95666dea53cf9a835d7822332f3b2d8d..e866c91deadfa2b95c55ef253640e14333cd021b 100644 --- a/vendor/symfony/debug/ErrorHandler.php +++ b/vendor/symfony/debug/ErrorHandler.php @@ -11,17 +11,17 @@ namespace Symfony\Component\Debug; -use Psr\Log\LogLevel; use Psr\Log\LoggerInterface; -use Symfony\Component\Debug\Exception\ContextErrorException; +use Psr\Log\LogLevel; use Symfony\Component\Debug\Exception\FatalErrorException; use Symfony\Component\Debug\Exception\FatalThrowableError; +use Symfony\Component\Debug\Exception\FlattenException; use Symfony\Component\Debug\Exception\OutOfMemoryException; use Symfony\Component\Debug\Exception\SilencedErrorContext; -use Symfony\Component\Debug\FatalErrorHandler\UndefinedFunctionFatalErrorHandler; -use Symfony\Component\Debug\FatalErrorHandler\UndefinedMethodFatalErrorHandler; use Symfony\Component\Debug\FatalErrorHandler\ClassNotFoundFatalErrorHandler; use Symfony\Component\Debug\FatalErrorHandler\FatalErrorHandlerInterface; +use Symfony\Component\Debug\FatalErrorHandler\UndefinedFunctionFatalErrorHandler; +use Symfony\Component\Debug\FatalErrorHandler\UndefinedMethodFatalErrorHandler; /** * A generic ErrorHandler for the PHP engine. @@ -45,10 +45,12 @@ use Symfony\Component\Debug\FatalErrorHandler\FatalErrorHandlerInterface; * * @author Nicolas Grekas <p@tchwork.com> * @author Grégoire Pineau <lyrixx@lyrixx.info> + * + * @final since Symfony 4.3 */ class ErrorHandler { - private $levels = array( + private $levels = [ E_DEPRECATED => 'Deprecated', E_USER_DEPRECATED => 'User Deprecated', E_NOTICE => 'Notice', @@ -64,25 +66,25 @@ class ErrorHandler E_PARSE => 'Parse Error', E_ERROR => 'Error', E_CORE_ERROR => 'Core Error', - ); - - private $loggers = array( - E_DEPRECATED => array(null, LogLevel::INFO), - E_USER_DEPRECATED => array(null, LogLevel::INFO), - E_NOTICE => array(null, LogLevel::WARNING), - E_USER_NOTICE => array(null, LogLevel::WARNING), - E_STRICT => array(null, LogLevel::WARNING), - E_WARNING => array(null, LogLevel::WARNING), - E_USER_WARNING => array(null, LogLevel::WARNING), - E_COMPILE_WARNING => array(null, LogLevel::WARNING), - E_CORE_WARNING => array(null, LogLevel::WARNING), - E_USER_ERROR => array(null, LogLevel::CRITICAL), - E_RECOVERABLE_ERROR => array(null, LogLevel::CRITICAL), - E_COMPILE_ERROR => array(null, LogLevel::CRITICAL), - E_PARSE => array(null, LogLevel::CRITICAL), - E_ERROR => array(null, LogLevel::CRITICAL), - E_CORE_ERROR => array(null, LogLevel::CRITICAL), - ); + ]; + + private $loggers = [ + E_DEPRECATED => [null, LogLevel::INFO], + E_USER_DEPRECATED => [null, LogLevel::INFO], + E_NOTICE => [null, LogLevel::WARNING], + E_USER_NOTICE => [null, LogLevel::WARNING], + E_STRICT => [null, LogLevel::WARNING], + E_WARNING => [null, LogLevel::WARNING], + E_USER_WARNING => [null, LogLevel::WARNING], + E_COMPILE_WARNING => [null, LogLevel::WARNING], + E_CORE_WARNING => [null, LogLevel::WARNING], + E_USER_ERROR => [null, LogLevel::CRITICAL], + E_RECOVERABLE_ERROR => [null, LogLevel::CRITICAL], + E_COMPILE_ERROR => [null, LogLevel::CRITICAL], + E_PARSE => [null, LogLevel::CRITICAL], + E_ERROR => [null, LogLevel::CRITICAL], + E_CORE_ERROR => [null, LogLevel::CRITICAL], + ]; private $thrownErrors = 0x1FFF; // E_ALL - E_DEPRECATED - E_USER_DEPRECATED private $scopedErrors = 0x1FFF; // E_ALL - E_DEPRECATED - E_USER_DEPRECATED @@ -97,10 +99,8 @@ class ErrorHandler private $bootstrappingLogger; private static $reservedMemory; - private static $stackedErrors = array(); - private static $stackedErrorLevels = array(); private static $toStringException = null; - private static $silencedErrorCache = array(); + private static $silencedErrorCache = []; private static $silencedErrorCount = 0; private static $exitCode = 0; @@ -123,22 +123,33 @@ class ErrorHandler $handler = new static(); } - if (null === $prev = set_error_handler(array($handler, 'handleError'))) { + if (null === $prev = set_error_handler([$handler, 'handleError'])) { restore_error_handler(); // Specifying the error types earlier would expose us to https://bugs.php.net/63206 - set_error_handler(array($handler, 'handleError'), $handler->thrownErrors | $handler->loggedErrors); + set_error_handler([$handler, 'handleError'], $handler->thrownErrors | $handler->loggedErrors); $handler->isRoot = true; } - if ($handlerIsNew && is_array($prev) && $prev[0] instanceof self) { + if ($handlerIsNew && \is_array($prev) && $prev[0] instanceof self) { $handler = $prev[0]; $replace = false; } if (!$replace && $prev) { restore_error_handler(); + $handlerIsRegistered = \is_array($prev) && $handler === $prev[0]; + } else { + $handlerIsRegistered = true; } - if (is_array($prev = set_exception_handler(array($handler, 'handleException'))) && $prev[0] === $handler) { + if (\is_array($prev = set_exception_handler([$handler, 'handleException'])) && $prev[0] instanceof self) { restore_exception_handler(); + if (!$handlerIsRegistered) { + $handler = $prev[0]; + } elseif ($handler !== $prev[0] && $replace) { + set_exception_handler([$handler, 'handleException']); + $p = $prev[0]->setExceptionHandler(null); + $handler->setExceptionHandler($p); + $prev[0]->setExceptionHandler($p); + } } else { $handler->setExceptionHandler($prev); } @@ -167,12 +178,12 @@ class ErrorHandler */ public function setDefaultLogger(LoggerInterface $logger, $levels = E_ALL, $replace = false) { - $loggers = array(); + $loggers = []; - if (is_array($levels)) { + if (\is_array($levels)) { foreach ($levels as $type => $logLevel) { if (empty($this->loggers[$type][0]) || $replace || $this->loggers[$type][0] === $this->bootstrappingLogger) { - $loggers[$type] = array($logger, $logLevel); + $loggers[$type] = [$logger, $logLevel]; } } } else { @@ -203,15 +214,15 @@ class ErrorHandler { $prevLogged = $this->loggedErrors; $prev = $this->loggers; - $flush = array(); + $flush = []; foreach ($loggers as $type => $log) { if (!isset($prev[$type])) { throw new \InvalidArgumentException('Unknown error type: '.$type); } - if (!is_array($log)) { - $log = array($log); - } elseif (!array_key_exists(0, $log)) { + if (!\is_array($log)) { + $log = [$log]; + } elseif (!\array_key_exists(0, $log)) { throw new \InvalidArgumentException('No logger provided'); } if (null === $log[0]) { @@ -342,14 +353,14 @@ class ErrorHandler { if ($prev !== $this->thrownErrors | $this->loggedErrors) { $handler = set_error_handler('var_dump'); - $handler = is_array($handler) ? $handler[0] : null; + $handler = \is_array($handler) ? $handler[0] : null; restore_error_handler(); if ($handler === $this) { restore_error_handler(); if ($this->isRoot) { - set_error_handler(array($this, 'handleError'), $this->thrownErrors | $this->loggedErrors); + set_error_handler([$this, 'handleError'], $this->thrownErrors | $this->loggedErrors); } else { - set_error_handler(array($this, 'handleError')); + set_error_handler([$this, 'handleError']); } } } @@ -371,24 +382,28 @@ class ErrorHandler */ public function handleError($type, $message, $file, $line) { + if (\PHP_VERSION_ID >= 70300 && E_WARNING === $type && '"' === $message[0] && false !== strpos($message, '" targeting switch is equivalent to "break')) { + $type = E_DEPRECATED; + } + // Level is the current error reporting level to manage silent error. + $level = error_reporting(); + $silenced = 0 === ($level & $type); // Strong errors are not authorized to be silenced. - $level = error_reporting() | E_RECOVERABLE_ERROR | E_USER_ERROR | E_DEPRECATED | E_USER_DEPRECATED; + $level |= E_RECOVERABLE_ERROR | E_USER_ERROR | E_DEPRECATED | E_USER_DEPRECATED; $log = $this->loggedErrors & $type; $throw = $this->thrownErrors & $type & $level; $type &= $level | $this->screamedErrors; if (!$type || (!$log && !$throw)) { - return $type && $log; + return !$silenced && $type && $log; } $scope = $this->scopedErrors & $type; - if (4 < $numArgs = func_num_args()) { - $context = $scope ? (func_get_arg(4) ?: array()) : array(); - $backtrace = 5 < $numArgs ? func_get_arg(5) : null; // defined on HHVM + if (4 < $numArgs = \func_num_args()) { + $context = $scope ? (func_get_arg(4) ?: []) : []; } else { - $context = array(); - $backtrace = null; + $context = []; } if (isset($context['GLOBALS']) && $scope) { @@ -397,62 +412,53 @@ class ErrorHandler $context = $e; } - if (null !== $backtrace && $type & E_ERROR) { - // E_ERROR fatal errors are triggered on HHVM when - // hhvm.error_handling.call_user_handler_on_fatals=1 - // which is the way to get their backtrace. - $this->handleFatalError(compact('type', 'message', 'file', 'line', 'backtrace')); - - return true; + if (false !== strpos($message, "class@anonymous\0")) { + $logMessage = $this->levels[$type].': '.(new FlattenException())->setMessage($message)->getMessage(); + } else { + $logMessage = $this->levels[$type].': '.$message; } - $logMessage = $this->levels[$type].': '.$message; - if (null !== self::$toStringException) { $errorAsException = self::$toStringException; self::$toStringException = null; } elseif (!$throw && !($type & $level)) { if (!isset(self::$silencedErrorCache[$id = $file.':'.$line])) { - $lightTrace = $this->tracedErrors & $type ? $this->cleanTrace(debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 3), $type, $file, $line, false) : array(); - $errorAsException = new SilencedErrorContext($type, $file, $line, $lightTrace); + $lightTrace = $this->tracedErrors & $type ? $this->cleanTrace(debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 5), $type, $file, $line, false) : []; + $errorAsException = new SilencedErrorContext($type, $file, $line, isset($lightTrace[1]) ? [$lightTrace[0]] : $lightTrace); } elseif (isset(self::$silencedErrorCache[$id][$message])) { $lightTrace = null; $errorAsException = self::$silencedErrorCache[$id][$message]; ++$errorAsException->count; } else { - $lightTrace = array(); + $lightTrace = []; $errorAsException = null; } if (100 < ++self::$silencedErrorCount) { - self::$silencedErrorCache = $lightTrace = array(); + self::$silencedErrorCache = $lightTrace = []; self::$silencedErrorCount = 1; } if ($errorAsException) { self::$silencedErrorCache[$id][$message] = $errorAsException; } if (null === $lightTrace) { - return; + return true; } } else { - if ($scope) { - $errorAsException = new ContextErrorException($logMessage, 0, $type, $file, $line, $context); - } else { - $errorAsException = new \ErrorException($logMessage, 0, $type, $file, $line); - } + $errorAsException = new \ErrorException($logMessage, 0, $type, $file, $line); - // Clean the trace by removing function arguments and the first frames added by the error handler itself. if ($throw || $this->tracedErrors & $type) { - $backtrace = $backtrace ?: $errorAsException->getTrace(); + $backtrace = $errorAsException->getTrace(); $lightTrace = $this->cleanTrace($backtrace, $type, $file, $line, $throw); $this->traceReflector->setValue($errorAsException, $lightTrace); } else { - $this->traceReflector->setValue($errorAsException, array()); + $this->traceReflector->setValue($errorAsException, []); + $backtrace = []; } } if ($throw) { - if (E_USER_ERROR & $type) { + if (\PHP_VERSION_ID < 70400 && E_USER_ERROR & $type) { for ($i = 1; isset($backtrace[$i]); ++$i) { if (isset($backtrace[$i]['function'], $backtrace[$i]['type'], $backtrace[$i - 1]['function']) && '__toString' === $backtrace[$i]['function'] @@ -461,32 +467,25 @@ class ErrorHandler && ('trigger_error' === $backtrace[$i - 1]['function'] || 'user_error' === $backtrace[$i - 1]['function']) ) { // Here, we know trigger_error() has been called from __toString(). - // HHVM is fine with throwing from __toString() but PHP triggers a fatal error instead. + // PHP triggers a fatal error when throwing from __toString(). // A small convention allows working around the limitation: // given a caught $e exception in __toString(), quitting the method with // `return trigger_error($e, E_USER_ERROR);` allows this error handler // to make $e get through the __toString() barrier. foreach ($context as $e) { - if (($e instanceof \Exception || $e instanceof \Throwable) && $e->__toString() === $message) { - if (1 === $i) { - // On HHVM - $errorAsException = $e; - break; - } + if ($e instanceof \Throwable && $e->__toString() === $message) { self::$toStringException = $e; return true; } } - if (1 < $i) { - // On PHP (not on HHVM), display the original error message instead of the default one. - $this->handleException($errorAsException); + // Display the original error message instead of the default one. + $this->handleException($errorAsException); - // Stop the process by giving back the error to the native handler. - return false; - } + // Stop the process by giving back the error to the native handler. + return false; } } } @@ -496,24 +495,26 @@ class ErrorHandler if ($this->isRecursive) { $log = 0; - } elseif (self::$stackedErrorLevels) { - self::$stackedErrors[] = array( - $this->loggers[$type][0], - ($type & $level) ? $this->loggers[$type][1] : LogLevel::DEBUG, - $logMessage, - $errorAsException ? array('exception' => $errorAsException) : array(), - ); } else { + if (!\defined('HHVM_VERSION')) { + $currentErrorHandler = set_error_handler('var_dump'); + restore_error_handler(); + } + try { $this->isRecursive = true; $level = ($type & $level) ? $this->loggers[$type][1] : LogLevel::DEBUG; - $this->loggers[$type][0]->log($level, $logMessage, $errorAsException ? array('exception' => $errorAsException) : array()); + $this->loggers[$type][0]->log($level, $logMessage, $errorAsException ? ['exception' => $errorAsException] : []); } finally { $this->isRecursive = false; + + if (!\defined('HHVM_VERSION')) { + set_error_handler($currentErrorHandler); + } } } - return $type && $log; + return !$silenced && $type && $log; } /** @@ -536,27 +537,29 @@ class ErrorHandler $handlerException = null; if (($this->loggedErrors & $type) || $exception instanceof FatalThrowableError) { + if (false !== strpos($message = $exception->getMessage(), "class@anonymous\0")) { + $message = (new FlattenException())->setMessage($message)->getMessage(); + } if ($exception instanceof FatalErrorException) { if ($exception instanceof FatalThrowableError) { - $error = array( + $error = [ 'type' => $type, - 'message' => $message = $exception->getMessage(), + 'message' => $message, 'file' => $exception->getFile(), 'line' => $exception->getLine(), - ); + ]; } else { - $message = 'Fatal '.$exception->getMessage(); + $message = 'Fatal '.$message; } } elseif ($exception instanceof \ErrorException) { - $message = 'Uncaught '.$exception->getMessage(); + $message = 'Uncaught '.$message; } else { - $message = 'Uncaught Exception: '.$exception->getMessage(); + $message = 'Uncaught Exception: '.$message; } } if ($this->loggedErrors & $type) { try { - $this->loggers[$type][0]->log($this->loggers[$type][1], $message, array('exception' => $exception)); - } catch (\Exception $handlerException) { + $this->loggers[$type][0]->log($this->loggers[$type][1], $message, ['exception' => $exception]); } catch (\Throwable $handlerException) { } } @@ -568,15 +571,17 @@ class ErrorHandler } } } + $exceptionHandler = $this->exceptionHandler; + $this->exceptionHandler = null; try { - if (null !== $this->exceptionHandler) { - return \call_user_func($this->exceptionHandler, $exception); + if (null !== $exceptionHandler) { + $exceptionHandler($exception); + + return; } $handlerException = $handlerException ?: $exception; - } catch (\Exception $handlerException) { } catch (\Throwable $handlerException) { } - $this->exceptionHandler = null; if ($exception === $handlerException) { self::$reservedMemory = null; // Disable the fatal error handler throw $exception; // Give back $exception to the native handler @@ -598,11 +603,11 @@ class ErrorHandler } $handler = self::$reservedMemory = null; - $handlers = array(); + $handlers = []; $previousHandler = null; $sameHandlerLimit = 10; - while (!is_array($handler) || !$handler[0] instanceof self) { + while (!\is_array($handler) || !$handler[0] instanceof self) { $handler = set_exception_handler('var_dump'); restore_exception_handler(); @@ -629,22 +634,12 @@ class ErrorHandler $handler[0]->setExceptionHandler($h); } $handler = $handler[0]; - $handlers = array(); + $handlers = []; if ($exit = null === $error) { $error = error_get_last(); } - try { - while (self::$stackedErrorLevels) { - static::unstackErrors(); - } - } catch (\Exception $exception) { - // Handled below - } catch (\Throwable $exception) { - // Handled below - } - if ($error && $error['type'] &= E_PARSE | E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR) { // Let's not throw anymore but keep logging $handler->throwAt(0, true); @@ -655,10 +650,12 @@ class ErrorHandler } else { $exception = new FatalErrorException($handler->levels[$error['type']].': '.$error['message'], 0, $error['type'], $error['file'], $error['line'], 2, true, $trace); } + } else { + $exception = null; } try { - if (isset($exception)) { + if (null !== $exception) { self::$exitCode = 255; $handler->handleException($exception, $error); } @@ -672,55 +669,6 @@ class ErrorHandler } } - /** - * Configures the error handler for delayed handling. - * Ensures also that non-catchable fatal errors are never silenced. - * - * As shown by http://bugs.php.net/42098 and http://bugs.php.net/60724 - * PHP has a compile stage where it behaves unusually. To workaround it, - * we plug an error handler that only stacks errors for later. - * - * The most important feature of this is to prevent - * autoloading until unstackErrors() is called. - * - * @deprecated since version 3.4, to be removed in 4.0. - */ - public static function stackErrors() - { - @trigger_error('Support for stacking errors is deprecated since Symfony 3.4 and will be removed in 4.0.', E_USER_DEPRECATED); - - self::$stackedErrorLevels[] = error_reporting(error_reporting() | E_PARSE | E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR); - } - - /** - * Unstacks stacked errors and forwards to the logger. - * - * @deprecated since version 3.4, to be removed in 4.0. - */ - public static function unstackErrors() - { - @trigger_error('Support for unstacking errors is deprecated since Symfony 3.4 and will be removed in 4.0.', E_USER_DEPRECATED); - - $level = array_pop(self::$stackedErrorLevels); - - if (null !== $level) { - $errorReportingLevel = error_reporting($level); - if ($errorReportingLevel !== ($level | E_PARSE | E_ERROR | E_CORE_ERROR | E_COMPILE_ERROR)) { - // If the user changed the error level, do not overwrite it - error_reporting($errorReportingLevel); - } - } - - if (empty(self::$stackedErrorLevels)) { - $errors = self::$stackedErrors; - self::$stackedErrors = array(); - - foreach ($errors as $error) { - $error[0]->log($error[1], $error[2], $error[3]); - } - } - } - /** * Gets the fatal error handlers. * @@ -730,23 +678,33 @@ class ErrorHandler */ protected function getFatalErrorHandlers() { - return array( + return [ new UndefinedFunctionFatalErrorHandler(), new UndefinedMethodFatalErrorHandler(), new ClassNotFoundFatalErrorHandler(), - ); + ]; } + /** + * Cleans the trace by removing function arguments and the frames added by the error handler and DebugClassLoader. + */ private function cleanTrace($backtrace, $type, $file, $line, $throw) { $lightTrace = $backtrace; for ($i = 0; isset($backtrace[$i]); ++$i) { if (isset($backtrace[$i]['file'], $backtrace[$i]['line']) && $backtrace[$i]['line'] === $line && $backtrace[$i]['file'] === $file) { - $lightTrace = array_slice($lightTrace, 1 + $i); + $lightTrace = \array_slice($lightTrace, 1 + $i); break; } } + if (class_exists(DebugClassLoader::class, false)) { + for ($i = \count($lightTrace) - 2; 0 < $i; --$i) { + if (DebugClassLoader::class === ($lightTrace[$i]['class'] ?? null)) { + array_splice($lightTrace, --$i, 2); + } + } + } if (!($throw || $this->scopedErrors & $type)) { for ($i = 0; isset($lightTrace[$i]); ++$i) { unset($lightTrace[$i]['args'], $lightTrace[$i]['object']); diff --git a/vendor/symfony/debug/Exception/ClassNotFoundException.php b/vendor/symfony/debug/Exception/ClassNotFoundException.php index b91bf46631bbb482943988927889dd7fc6d7ab1d..fa98c4975d02a5f0a3719ee873560d0261c46495 100644 --- a/vendor/symfony/debug/Exception/ClassNotFoundException.php +++ b/vendor/symfony/debug/Exception/ClassNotFoundException.php @@ -18,7 +18,7 @@ namespace Symfony\Component\Debug\Exception; */ class ClassNotFoundException extends FatalErrorException { - public function __construct($message, \ErrorException $previous) + public function __construct(string $message, \ErrorException $previous) { parent::__construct( $message, @@ -26,6 +26,9 @@ class ClassNotFoundException extends FatalErrorException $previous->getSeverity(), $previous->getFile(), $previous->getLine(), + null, + true, + null, $previous->getPrevious() ); $this->setTrace($previous->getTrace()); diff --git a/vendor/symfony/debug/Exception/ContextErrorException.php b/vendor/symfony/debug/Exception/ContextErrorException.php deleted file mode 100644 index 554139da3bf1d2e163f6c47d93ddc37f6d7f6163..0000000000000000000000000000000000000000 --- a/vendor/symfony/debug/Exception/ContextErrorException.php +++ /dev/null @@ -1,40 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Debug\Exception; - -/** - * Error Exception with Variable Context. - * - * @author Christian Sciberras <uuf6429@gmail.com> - * - * @deprecated since version 3.3. Instead, \ErrorException will be used directly in 4.0. - */ -class ContextErrorException extends \ErrorException -{ - private $context = array(); - - public function __construct($message, $code, $severity, $filename, $lineno, $context = array()) - { - parent::__construct($message, $code, $severity, $filename, $lineno); - $this->context = $context; - } - - /** - * @return array Array of variables that existed when the exception occurred - */ - public function getContext() - { - @trigger_error(sprintf('The %s class is deprecated since Symfony 3.3 and will be removed in 4.0.', __CLASS__), E_USER_DEPRECATED); - - return $this->context; - } -} diff --git a/vendor/symfony/debug/Exception/FatalErrorException.php b/vendor/symfony/debug/Exception/FatalErrorException.php index f24a54e77a6aca14f4fda26f0e00cc78890894b2..93880fbc323cd14c7eb22a9cc4db21e6387127a6 100644 --- a/vendor/symfony/debug/Exception/FatalErrorException.php +++ b/vendor/symfony/debug/Exception/FatalErrorException.php @@ -18,9 +18,9 @@ namespace Symfony\Component\Debug\Exception; */ class FatalErrorException extends \ErrorException { - public function __construct($message, $code, $severity, $filename, $lineno, $traceOffset = null, $traceArgs = true, array $trace = null) + public function __construct(string $message, int $code, int $severity, string $filename, int $lineno, int $traceOffset = null, bool $traceArgs = true, array $trace = null, \Throwable $previous = null) { - parent::__construct($message, $code, $severity, $filename, $lineno); + parent::__construct($message, $code, $severity, $filename, $lineno, $previous); if (null !== $trace) { if (!$traceArgs) { @@ -31,7 +31,7 @@ class FatalErrorException extends \ErrorException $this->setTrace($trace); } elseif (null !== $traceOffset) { - if (function_exists('xdebug_get_function_stack')) { + if (\function_exists('xdebug_get_function_stack')) { $trace = xdebug_get_function_stack(); if (0 < $traceOffset) { array_splice($trace, -$traceOffset); @@ -60,13 +60,8 @@ class FatalErrorException extends \ErrorException unset($frame); $trace = array_reverse($trace); - } elseif (function_exists('symfony_debug_backtrace')) { - $trace = symfony_debug_backtrace(); - if (0 < $traceOffset) { - array_splice($trace, 0, $traceOffset); - } } else { - $trace = array(); + $trace = []; } $this->setTrace($trace); diff --git a/vendor/symfony/debug/Exception/FatalThrowableError.php b/vendor/symfony/debug/Exception/FatalThrowableError.php index 34f43b17b13b4fbbfe2abaf322c04848c563ba70..cdafb2a56842dd43d33842c79c2bd2de9c78d1f1 100644 --- a/vendor/symfony/debug/Exception/FatalThrowableError.php +++ b/vendor/symfony/debug/Exception/FatalThrowableError.php @@ -18,27 +18,34 @@ namespace Symfony\Component\Debug\Exception; */ class FatalThrowableError extends FatalErrorException { + private $originalClassName; + public function __construct(\Throwable $e) { + $this->originalClassName = \get_class($e); + if ($e instanceof \ParseError) { - $message = 'Parse error: '.$e->getMessage(); $severity = E_PARSE; } elseif ($e instanceof \TypeError) { - $message = 'Type error: '.$e->getMessage(); $severity = E_RECOVERABLE_ERROR; } else { - $message = $e->getMessage(); $severity = E_ERROR; } \ErrorException::__construct( - $message, + $e->getMessage(), $e->getCode(), $severity, $e->getFile(), - $e->getLine() + $e->getLine(), + $e->getPrevious() ); $this->setTrace($e->getTrace()); } + + public function getOriginalClassName(): string + { + return $this->originalClassName; + } } diff --git a/vendor/symfony/debug/Exception/FlattenException.php b/vendor/symfony/debug/Exception/FlattenException.php index 24679dcaab2424fdd75b9ceaf3addbe59f93aec0..2e97ac39bbd35926dfeda8f6c557ee8287ca7234 100644 --- a/vendor/symfony/debug/Exception/FlattenException.php +++ b/vendor/symfony/debug/Exception/FlattenException.php @@ -15,7 +15,7 @@ use Symfony\Component\HttpFoundation\Exception\RequestExceptionInterface; use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface; /** - * FlattenException wraps a PHP Exception to be able to serialize it. + * FlattenException wraps a PHP Error or Exception to be able to serialize it. * * Basically, this class removes all objects from the trace. * @@ -27,13 +27,19 @@ class FlattenException private $code; private $previous; private $trace; + private $traceAsString; private $class; private $statusCode; private $headers; private $file; private $line; - public static function create(\Exception $exception, $statusCode = null, array $headers = array()) + public static function create(\Exception $exception, $statusCode = null, array $headers = []) + { + return static::createFromThrowable($exception, $statusCode, $headers); + } + + public static function createFromThrowable(\Throwable $exception, ?int $statusCode = null, array $headers = []): self { $e = new static(); $e->setMessage($exception->getMessage()); @@ -52,17 +58,15 @@ class FlattenException $e->setStatusCode($statusCode); $e->setHeaders($headers); - $e->setTraceFromException($exception); - $e->setClass(get_class($exception)); + $e->setTraceFromThrowable($exception); + $e->setClass($exception instanceof FatalThrowableError ? $exception->getOriginalClassName() : \get_class($exception)); $e->setFile($exception->getFile()); $e->setLine($exception->getLine()); $previous = $exception->getPrevious(); - if ($previous instanceof \Exception) { - $e->setPrevious(static::create($previous)); - } elseif ($previous instanceof \Throwable) { - $e->setPrevious(static::create(new FatalThrowableError($previous))); + if ($previous instanceof \Throwable) { + $e->setPrevious(static::createFromThrowable($previous)); } return $e; @@ -70,13 +74,13 @@ class FlattenException public function toArray() { - $exceptions = array(); - foreach (array_merge(array($this), $this->getAllPrevious()) as $exception) { - $exceptions[] = array( + $exceptions = []; + foreach (array_merge([$this], $this->getAllPrevious()) as $exception) { + $exceptions[] = [ 'message' => $exception->getMessage(), 'class' => $exception->getClass(), 'trace' => $exception->getTrace(), - ); + ]; } return $exceptions; @@ -87,9 +91,14 @@ class FlattenException return $this->statusCode; } + /** + * @return $this + */ public function setStatusCode($code) { $this->statusCode = $code; + + return $this; } public function getHeaders() @@ -97,9 +106,14 @@ class FlattenException return $this->headers; } + /** + * @return $this + */ public function setHeaders(array $headers) { $this->headers = $headers; + + return $this; } public function getClass() @@ -107,9 +121,14 @@ class FlattenException return $this->class; } + /** + * @return $this + */ public function setClass($class) { - $this->class = $class; + $this->class = 'c' === $class[0] && 0 === strpos($class, "class@anonymous\0") ? get_parent_class($class).'@anonymous' : $class; + + return $this; } public function getFile() @@ -117,9 +136,14 @@ class FlattenException return $this->file; } + /** + * @return $this + */ public function setFile($file) { $this->file = $file; + + return $this; } public function getLine() @@ -127,9 +151,14 @@ class FlattenException return $this->line; } + /** + * @return $this + */ public function setLine($line) { $this->line = $line; + + return $this; } public function getMessage() @@ -137,9 +166,20 @@ class FlattenException return $this->message; } + /** + * @return $this + */ public function setMessage($message) { + if (false !== strpos($message, "class@anonymous\0")) { + $message = preg_replace_callback('/class@anonymous\x00.*?\.php0x?[0-9a-fA-F]++/', function ($m) { + return class_exists($m[0], false) ? get_parent_class($m[0]).'@anonymous' : $m[0]; + }, $message); + } + $this->message = $message; + + return $this; } public function getCode() @@ -147,9 +187,14 @@ class FlattenException return $this->code; } + /** + * @return $this + */ public function setCode($code) { $this->code = $code; + + return $this; } public function getPrevious() @@ -157,14 +202,19 @@ class FlattenException return $this->previous; } - public function setPrevious(FlattenException $previous) + /** + * @return $this + */ + public function setPrevious(self $previous) { $this->previous = $previous; + + return $this; } public function getAllPrevious() { - $exceptions = array(); + $exceptions = []; $e = $this; while ($e = $e->getPrevious()) { $exceptions[] = $e; @@ -178,15 +228,30 @@ class FlattenException return $this->trace; } + /** + * @deprecated since 4.1, use {@see setTraceFromThrowable()} instead. + */ public function setTraceFromException(\Exception $exception) { - $this->setTrace($exception->getTrace(), $exception->getFile(), $exception->getLine()); + @trigger_error(sprintf('The "%s()" method is deprecated since Symfony 4.1, use "setTraceFromThrowable()" instead.', __METHOD__), E_USER_DEPRECATED); + + $this->setTraceFromThrowable($exception); } + public function setTraceFromThrowable(\Throwable $throwable) + { + $this->traceAsString = $throwable->getTraceAsString(); + + return $this->setTrace($throwable->getTrace(), $throwable->getFile(), $throwable->getLine()); + } + + /** + * @return $this + */ public function setTrace($trace, $file, $line) { - $this->trace = array(); - $this->trace[] = array( + $this->trace = []; + $this->trace[] = [ 'namespace' => '', 'short_class' => '', 'class' => '', @@ -194,8 +259,8 @@ class FlattenException 'function' => '', 'file' => $file, 'line' => $line, - 'args' => array(), - ); + 'args' => [], + ]; foreach ($trace as $entry) { $class = ''; $namespace = ''; @@ -205,7 +270,7 @@ class FlattenException $namespace = implode('\\', $parts); } - $this->trace[] = array( + $this->trace[] = [ 'namespace' => $namespace, 'short_class' => $class, 'class' => isset($entry['class']) ? $entry['class'] : '', @@ -213,41 +278,43 @@ class FlattenException 'function' => isset($entry['function']) ? $entry['function'] : null, 'file' => isset($entry['file']) ? $entry['file'] : null, 'line' => isset($entry['line']) ? $entry['line'] : null, - 'args' => isset($entry['args']) ? $this->flattenArgs($entry['args']) : array(), - ); + 'args' => isset($entry['args']) ? $this->flattenArgs($entry['args']) : [], + ]; } + + return $this; } private function flattenArgs($args, $level = 0, &$count = 0) { - $result = array(); + $result = []; foreach ($args as $key => $value) { if (++$count > 1e4) { - return array('array', '*SKIPPED over 10000 entries*'); + return ['array', '*SKIPPED over 10000 entries*']; } if ($value instanceof \__PHP_Incomplete_Class) { // is_object() returns false on PHP<=7.1 - $result[$key] = array('incomplete-object', $this->getClassNameFromIncomplete($value)); - } elseif (is_object($value)) { - $result[$key] = array('object', get_class($value)); - } elseif (is_array($value)) { + $result[$key] = ['incomplete-object', $this->getClassNameFromIncomplete($value)]; + } elseif (\is_object($value)) { + $result[$key] = ['object', \get_class($value)]; + } elseif (\is_array($value)) { if ($level > 10) { - $result[$key] = array('array', '*DEEP NESTED ARRAY*'); + $result[$key] = ['array', '*DEEP NESTED ARRAY*']; } else { - $result[$key] = array('array', $this->flattenArgs($value, $level + 1, $count)); + $result[$key] = ['array', $this->flattenArgs($value, $level + 1, $count)]; } } elseif (null === $value) { - $result[$key] = array('null', null); - } elseif (is_bool($value)) { - $result[$key] = array('boolean', $value); - } elseif (is_int($value)) { - $result[$key] = array('integer', $value); - } elseif (is_float($value)) { - $result[$key] = array('float', $value); - } elseif (is_resource($value)) { - $result[$key] = array('resource', get_resource_type($value)); + $result[$key] = ['null', null]; + } elseif (\is_bool($value)) { + $result[$key] = ['boolean', $value]; + } elseif (\is_int($value)) { + $result[$key] = ['integer', $value]; + } elseif (\is_float($value)) { + $result[$key] = ['float', $value]; + } elseif (\is_resource($value)) { + $result[$key] = ['resource', get_resource_type($value)]; } else { - $result[$key] = array('string', (string) $value); + $result[$key] = ['string', (string) $value]; } } @@ -260,4 +327,33 @@ class FlattenException return $array['__PHP_Incomplete_Class_Name']; } + + public function getTraceAsString() + { + return $this->traceAsString; + } + + public function getAsString() + { + $message = ''; + $next = false; + + foreach (array_reverse(array_merge([$this], $this->getAllPrevious())) as $exception) { + if ($next) { + $message .= 'Next '; + } else { + $next = true; + } + $message .= $exception->getClass(); + + if ('' != $exception->getMessage()) { + $message .= ': '.$exception->getMessage(); + } + + $message .= ' in '.$exception->getFile().':'.$exception->getLine(). + "\nStack trace:\n".$exception->getTraceAsString()."\n\n"; + } + + return rtrim($message); + } } diff --git a/vendor/symfony/debug/Exception/SilencedErrorContext.php b/vendor/symfony/debug/Exception/SilencedErrorContext.php index 4be83491b9df73b5358f62b9fcf5e5015332a504..95bd7795f88b24fa2a3e3754cf1df56ac8d3de07 100644 --- a/vendor/symfony/debug/Exception/SilencedErrorContext.php +++ b/vendor/symfony/debug/Exception/SilencedErrorContext.php @@ -25,7 +25,7 @@ class SilencedErrorContext implements \JsonSerializable private $line; private $trace; - public function __construct($severity, $file, $line, array $trace = array(), $count = 1) + public function __construct(int $severity, string $file, int $line, array $trace = [], int $count = 1) { $this->severity = $severity; $this->file = $file; @@ -54,14 +54,14 @@ class SilencedErrorContext implements \JsonSerializable return $this->trace; } - public function JsonSerialize() + public function jsonSerialize() { - return array( + return [ 'severity' => $this->severity, 'file' => $this->file, 'line' => $this->line, 'trace' => $this->trace, 'count' => $this->count, - ); + ]; } } diff --git a/vendor/symfony/debug/Exception/UndefinedFunctionException.php b/vendor/symfony/debug/Exception/UndefinedFunctionException.php index a66ae2a3879c99778d464618c92c60dfb39b47bb..d936c8759e36c11bb819fd7c5a050d0d6a7db418 100644 --- a/vendor/symfony/debug/Exception/UndefinedFunctionException.php +++ b/vendor/symfony/debug/Exception/UndefinedFunctionException.php @@ -18,7 +18,7 @@ namespace Symfony\Component\Debug\Exception; */ class UndefinedFunctionException extends FatalErrorException { - public function __construct($message, \ErrorException $previous) + public function __construct(string $message, \ErrorException $previous) { parent::__construct( $message, @@ -26,6 +26,9 @@ class UndefinedFunctionException extends FatalErrorException $previous->getSeverity(), $previous->getFile(), $previous->getLine(), + null, + true, + null, $previous->getPrevious() ); $this->setTrace($previous->getTrace()); diff --git a/vendor/symfony/debug/Exception/UndefinedMethodException.php b/vendor/symfony/debug/Exception/UndefinedMethodException.php index 350dc3187f47541b28c5d46301690a4832566288..f627561fe16e21dab735c3e062dd69b9a7508162 100644 --- a/vendor/symfony/debug/Exception/UndefinedMethodException.php +++ b/vendor/symfony/debug/Exception/UndefinedMethodException.php @@ -18,7 +18,7 @@ namespace Symfony\Component\Debug\Exception; */ class UndefinedMethodException extends FatalErrorException { - public function __construct($message, \ErrorException $previous) + public function __construct(string $message, \ErrorException $previous) { parent::__construct( $message, @@ -26,6 +26,9 @@ class UndefinedMethodException extends FatalErrorException $previous->getSeverity(), $previous->getFile(), $previous->getLine(), + null, + true, + null, $previous->getPrevious() ); $this->setTrace($previous->getTrace()); diff --git a/vendor/symfony/debug/ExceptionHandler.php b/vendor/symfony/debug/ExceptionHandler.php index 97470cb6b4d01ae8e7f2bb1efe24a572407a5feb..743de65622d44916501d377e6466082ff69797c5 100644 --- a/vendor/symfony/debug/ExceptionHandler.php +++ b/vendor/symfony/debug/ExceptionHandler.php @@ -26,9 +26,21 @@ use Symfony\Component\HttpKernel\Debug\FileLinkFormatter; * * @author Fabien Potencier <fabien@symfony.com> * @author Nicolas Grekas <p@tchwork.com> + * + * @final since Symfony 4.3 */ class ExceptionHandler { + private const GHOST_ADDONS = [ + '02-14' => self::GHOST_HEART, + '02-29' => self::GHOST_PLUS, + '10-18' => self::GHOST_GIFT, + ]; + + private const GHOST_GIFT = 'M124.005 5.36c.396-.715 1.119-1.648-.124-1.873-.346-.177-.692-.492-1.038-.141-.769.303-1.435.728-.627 1.523.36.514.685 1.634 1.092 1.758.242-.417.47-.842.697-1.266zm-1.699 1.977c-.706-1.26-1.274-2.612-2.138-3.774-1.051-1.123-3.122-.622-3.593.825-.625 1.431.724 3.14 2.251 2.96 1.159.02 2.324.072 3.48-.011zm5.867.043c1.502-.202 2.365-2.092 1.51-3.347-.757-1.34-2.937-1.387-3.698-.025-.659 1.1-1.23 2.25-1.835 3.38 1.336.077 2.686.06 4.023-.008zm2.487 1.611c.512-.45 2.494-.981.993-1.409-.372-.105-.805-.59-1.14-.457-.726.902-1.842 1.432-3.007 1.376-.228.075-1.391-.114-1.077.1.822.47 1.623.979 2.474 1.395.595-.317 1.173-.667 1.757-1.005zm-11.696.255l1.314-.765c-1.338-.066-2.87.127-3.881-.95-.285-.319-.559-.684-.954-.282-.473.326-1.929.66-.808 1.058.976.576 1.945 1.167 2.946 1.701.476-.223.926-.503 1.383-.762zm6.416 2.846c.567-.456 1.942-.89 1.987-1.38-1.282-.737-2.527-1.56-3.87-2.183-.461-.175-.835.094-1.207.328-1.1.654-2.225 1.267-3.288 1.978 1.39.86 2.798 1.695 4.219 2.504.725-.407 1.44-.83 2.16-1.247zm5.692 1.423l1.765-1.114c-.005-1.244.015-2.488-.019-3.732a77.306 77.306 0 0 0-3.51 2.084c-.126 1.282-.062 2.586-.034 3.876.607-.358 1.2-.741 1.798-1.114zm-13.804-.784c.06-1.06.19-2.269-1.09-2.583-.807-.376-1.926-1.341-2.548-1.332-.02 1.195-.01 2.39-.011 3.585 1.192.744 2.364 1.524 3.582 2.226.119-.616.041-1.269.067-1.896zm8.541 4.105l2.117-1.336c-.003-1.284.05-2.57-.008-3.853-.776.223-1.662.91-2.48 1.337l-1.834 1.075c.012 1.37-.033 2.744.044 4.113.732-.427 1.443-.887 2.161-1.336zm-2.957-.72v-2.057c-1.416-.828-2.828-1.664-4.25-2.482-.078 1.311-.033 2.627-.045 3.94 1.416.887 2.817 1.798 4.25 2.655.057-.683.036-1.372.045-2.057zm8.255 2.755l1.731-1.153c-.024-1.218.06-2.453-.062-3.658-1.2.685-2.358 1.464-3.537 2.195.028 1.261-.058 2.536.072 3.786.609-.373 1.2-.777 1.796-1.17zm-13.851-.683l-.014-1.916c-1.193-.746-2.37-1.517-3.58-2.234-.076 1.224-.033 2.453-.044 3.679 1.203.796 2.392 1.614 3.61 2.385.048-.636.024-1.276.028-1.914zm8.584 4.199l2.102-1.396c-.002-1.298.024-2.596-.01-3.893-1.427.88-2.843 1.775-4.25 2.686-.158 1.253-.055 2.545-.056 3.811.437.266 1.553-.912 2.214-1.208zm-2.988-.556c-.085-.894.365-2.154-.773-2.5-1.146-.727-2.288-1.46-3.45-2.163-.17 1.228.008 2.508-.122 3.751a79.399 79.399 0 0 0 4.278 2.885c.117-.641.044-1.32.067-1.973zm-4.872-.236l-5.087-3.396c.002-3.493-.047-6.988.015-10.48.85-.524 1.753-.954 2.627-1.434-.564-1.616.25-3.58 1.887-4.184 1.372-.563 3.025-.055 3.9 1.13l1.906-.978 1.916.987c.915-1.086 2.483-1.706 3.842-1.097 1.631.573 2.52 2.532 1.936 4.145.88.497 1.837.886 2.644 1.492.036 3.473 0 6.946-.003 10.419-3.374 2.233-6.693 4.55-10.122 6.699-.997 0-1.858-1.083-2.783-1.522a735.316 735.316 0 0 1-2.678-1.781z'; + private const GHOST_HEART = 'M125.914 8.305c3.036-8.71 14.933 0 0 11.2-14.932-11.2-3.036-19.91 0-11.2z'; + private const GHOST_PLUS = 'M111.368 8.97h7.324V1.645h7.512v7.323h7.324v7.513h-7.324v7.323h-7.512v-7.323h-7.324z'; + private $debug; private $charset; private $handler; @@ -36,11 +48,11 @@ class ExceptionHandler private $caughtLength; private $fileLinkFormat; - public function __construct($debug = true, $charset = null, $fileLinkFormat = null) + public function __construct(bool $debug = true, string $charset = null, $fileLinkFormat = null) { $this->debug = $debug; $this->charset = $charset ?: ini_get('default_charset') ?: 'UTF-8'; - $this->fileLinkFormat = $fileLinkFormat ?: ini_get('xdebug.file_link_format') ?: get_cfg_var('xdebug.file_link_format'); + $this->fileLinkFormat = $fileLinkFormat; } /** @@ -56,10 +68,10 @@ class ExceptionHandler { $handler = new static($debug, $charset, $fileLinkFormat); - $prev = set_exception_handler(array($handler, 'handle')); - if (is_array($prev) && $prev[0] instanceof ErrorHandler) { + $prev = set_exception_handler([$handler, 'handle']); + if (\is_array($prev) && $prev[0] instanceof ErrorHandler) { restore_exception_handler(); - $prev[0]->setExceptionHandler(array($handler, 'handle')); + $prev[0]->setExceptionHandler([$handler, 'handle']); } return $handler; @@ -142,7 +154,7 @@ class ExceptionHandler $this->caughtBuffer = null; try { - call_user_func($this->handler, $exception); + ($this->handler)($exception); $this->caughtLength = $caughtLength; } catch (\Exception $e) { if (!$caughtLength) { @@ -205,51 +217,58 @@ class ExceptionHandler $title = 'Sorry, the page you are looking for could not be found.'; break; default: - $title = 'Whoops, looks like something went wrong.'; + $title = $this->debug ? $this->escapeHtml($exception->getMessage()) : 'Whoops, looks like something went wrong.'; + } + + if (!$this->debug) { + return <<<EOF + <div class="container"> + <h1>$title</h1> + </div> +EOF; } $content = ''; - if ($this->debug) { - try { - $count = count($exception->getAllPrevious()); - $total = $count + 1; - foreach ($exception->toArray() as $position => $e) { - $ind = $count - $position + 1; - $class = $this->formatClass($e['class']); - $message = nl2br($this->escapeHtml($e['message'])); - $content .= sprintf(<<<'EOF' - <div class="trace trace-as-html"> - <table class="trace-details"> - <thead class="trace-head"><tr><th> - <h3 class="trace-class"> - <span class="text-muted">(%d/%d)</span> - <span class="exception_title">%s</span> - </h3> - <p class="break-long-words trace-message">%s</p> - </th></tr></thead> - <tbody> + try { + $count = \count($exception->getAllPrevious()); + $total = $count + 1; + foreach ($exception->toArray() as $position => $e) { + $ind = $count - $position + 1; + $class = $this->formatClass($e['class']); + $message = nl2br($this->escapeHtml($e['message'])); + $content .= sprintf(<<<'EOF' + <div class="trace trace-as-html"> + <table class="trace-details"> + <thead class="trace-head"><tr><th> + <h3 class="trace-class"> + <span class="text-muted">(%d/%d)</span> + <span class="exception_title">%s</span> + </h3> + <p class="break-long-words trace-message">%s</p> + </th></tr></thead> + <tbody> EOF - , $ind, $total, $class, $message); - foreach ($e['trace'] as $trace) { - $content .= '<tr><td>'; - if ($trace['function']) { - $content .= sprintf('at <span class="trace-class">%s</span><span class="trace-type">%s</span><span class="trace-method">%s</span>(<span class="trace-arguments">%s</span>)', $this->formatClass($trace['class']), $trace['type'], $trace['function'], $this->formatArgs($trace['args'])); - } - if (isset($trace['file']) && isset($trace['line'])) { - $content .= $this->formatPath($trace['file'], $trace['line']); - } - $content .= "</td></tr>\n"; + , $ind, $total, $class, $message); + foreach ($e['trace'] as $trace) { + $content .= '<tr><td>'; + if ($trace['function']) { + $content .= sprintf('at <span class="trace-class">%s</span><span class="trace-type">%s</span><span class="trace-method">%s</span>(<span class="trace-arguments">%s</span>)', $this->formatClass($trace['class']), $trace['type'], $trace['function'], $this->formatArgs($trace['args'])); } - - $content .= "</tbody>\n</table>\n</div>\n"; - } - } catch (\Exception $e) { - // something nasty happened and we cannot throw an exception anymore - if ($this->debug) { - $title = sprintf('Exception thrown when handling an exception (%s: %s)', get_class($e), $this->escapeHtml($e->getMessage())); - } else { - $title = 'Whoops, looks like something went wrong.'; + if (isset($trace['file']) && isset($trace['line'])) { + $content .= $this->formatPath($trace['file'], $trace['line']); + } + $content .= "</td></tr>\n"; } + + $content .= "</tbody>\n</table>\n</div>\n"; + } + } catch (\Exception $e) { + // something nasty happened and we cannot throw an exception anymore + if ($this->debug) { + $e = FlattenException::create($e); + $title = sprintf('Exception thrown when handling an exception (%s: %s)', $e->getClass(), $this->escapeHtml($e->getMessage())); + } else { + $title = 'Whoops, looks like something went wrong.'; } } @@ -278,6 +297,14 @@ EOF; */ public function getStylesheet(FlattenException $exception) { + if (!$this->debug) { + return <<<'EOF' + body { background-color: #fff; color: #222; font: 16px/1.5 -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif; margin: 0; } + .container { margin: 30px; max-width: 600px; } + h1 { color: #dc3545; font-size: 24px; } +EOF; + } + return <<<'EOF' body { background-color: #F9F9F9; color: #222; font: 14px/1.4 Helvetica, Arial, sans-serif; margin: 0; padding-bottom: 45px; } @@ -355,13 +382,33 @@ EOF; private function formatPath($path, $line) { $file = $this->escapeHtml(preg_match('#[^/\\\\]*+$#', $path, $file) ? $file[0] : $path); - $fmt = $this->fileLinkFormat; + $fmt = $this->fileLinkFormat ?: ini_get('xdebug.file_link_format') ?: get_cfg_var('xdebug.file_link_format'); - if ($fmt && $link = is_string($fmt) ? strtr($fmt, array('%f' => $path, '%l' => $line)) : $fmt->format($path, $line)) { - return sprintf('<span class="block trace-file-path">in <a href="%s" title="Go to source">%s (line %d)</a></span>', $this->escapeHtml($link), $file, $line); + if (!$fmt) { + return sprintf('<span class="block trace-file-path">in <span title="%s%3$s"><strong>%s</strong>%s</span></span>', $this->escapeHtml($path), $file, 0 < $line ? ' line '.$line : ''); } - return sprintf('<span class="block trace-file-path">in <a title="%s line %3$d"><strong>%s</strong> (line %d)</a></span>', $this->escapeHtml($path), $file, $line); + if (\is_string($fmt)) { + $i = strpos($f = $fmt, '&', max(strrpos($f, '%f'), strrpos($f, '%l'))) ?: \strlen($f); + $fmt = [substr($f, 0, $i)] + preg_split('/&([^>]++)>/', substr($f, $i), -1, PREG_SPLIT_DELIM_CAPTURE); + + for ($i = 1; isset($fmt[$i]); ++$i) { + if (0 === strpos($path, $k = $fmt[$i++])) { + $path = substr_replace($path, $fmt[$i], 0, \strlen($k)); + break; + } + } + + $link = strtr($fmt[0], ['%f' => $path, '%l' => $line]); + } else { + try { + $link = $fmt->format($path, $line); + } catch (\Exception $e) { + return sprintf('<span class="block trace-file-path">in <span title="%s%3$s"><strong>%s</strong>%s</span></span>', $this->escapeHtml($path), $file, 0 < $line ? ' line '.$line : ''); + } + } + + return sprintf('<span class="block trace-file-path">in <a href="%s" title="Go to source"><strong>%s</string>%s</a></span>', $this->escapeHtml($link), $file, 0 < $line ? ' line '.$line : ''); } /** @@ -373,12 +420,12 @@ EOF; */ private function formatArgs(array $args) { - $result = array(); + $result = []; foreach ($args as $key => $item) { if ('object' === $item[0]) { $formattedValue = sprintf('<em>object</em>(%s)', $this->formatClass($item[1])); } elseif ('array' === $item[0]) { - $formattedValue = sprintf('<em>array</em>(%s)', is_array($item[1]) ? $this->formatArgs($item[1]) : $item[1]); + $formattedValue = sprintf('<em>array</em>(%s)', \is_array($item[1]) ? $this->formatArgs($item[1]) : $item[1]); } elseif ('null' === $item[0]) { $formattedValue = '<em>null</em>'; } elseif ('boolean' === $item[0]) { @@ -389,7 +436,7 @@ EOF; $formattedValue = str_replace("\n", '', $this->escapeHtml(var_export($item[1], true))); } - $result[] = is_int($key) ? $formattedValue : sprintf("'%s' => %s", $this->escapeHtml($key), $formattedValue); + $result[] = \is_int($key) ? $formattedValue : sprintf("'%s' => %s", $this->escapeHtml($key), $formattedValue); } return implode(', ', $result); @@ -405,6 +452,15 @@ EOF; private function getSymfonyGhostAsSvg() { - return '<svg viewBox="0 0 136 81" xmlns="http://www.w3.org/2000/svg" fill-rule="evenodd" clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.414"><path d="M92.358 20.403a23.168 23.168 0 0 1 9.003 1.881 23.67 23.67 0 0 1 5.197 3.079 24.257 24.257 0 0 1 3.457 3.296 24.771 24.771 0 0 1 5.042 9.396c.486 1.72.78 3.492.895 5.28l.008.142.028.158.015.246v13.875c.116.034.232.065.348.098.193.054.383.116.577.168.487.125.989.191 1.49.215.338.016.689.023 1.021-.059.021-.005.032-.029.048-.044l.095-.1c.243-.265.461-.552.663-.851.277-.408.523-.837.746-1.279l.042-.087c-.066-.012-.131-.026-.197-.04l-.099-.023a5.536 5.536 0 0 1-.694-.242 5.649 5.649 0 0 1-2.374-1.845 5.694 5.694 0 0 1-.824-1.594 6.514 6.514 0 0 1-.267-2.781c.045-.394.126-.779.233-1.159.079-.278.162-.562.307-.812.094-.163.129-.196.247-.341l.79-.882c.143-.143.174-.186.34-.303.249-.174.536-.289.834-.333.074-.011.15-.014.224-.02l1.188-.037c.173.004.217-.002.388.028s.211.05.375.105l.018.007c.059.026.119.05.176.079.151.076.179.104.313.2l.006-.021c.073-.187.084-.238.187-.41.077-.129.167-.249.27-.357.051-.054.108-.103.162-.154l1.124-.95c.14-.107.172-.14.327-.224.155-.085.199-.094.363-.154l.019-.006c.169-.043.211-.06.385-.077.174-.016.218-.007.392.003l1.446.158c.193.033.244.033.43.098.278.097.534.259.744.47.053.053.1.112.149.167l.923 1.158.149.213.028.054.017-.014.184-.125c.196-.104.196-.104.402-.184l1.386-.451c.064-.018.126-.038.19-.052.129-.028.259-.042.39-.043.16-.002.321.017.478.047.364.069.711.21 1.032.396.162.094.316.199.469.308.088.063.176.132.27.188l.021.011c.19.123.245.146.409.305.185.178.336.393.443.63.035.079.061.162.091.243l.439 1.428c.045.175.062.219.081.4.02.193.006.381-.015.573a7.79 7.79 0 0 1-.101.645c-.09.455-.212.901-.365 1.339-.128.366-.273.73-.445 1.077-.658 1.335-1.652 2.512-2.917 3.265a6.399 6.399 0 0 1-1.019.489 6.097 6.097 0 0 1-.631.203c-.226.058-.455.1-.686.134l-.096.012-.061.007c-.01.176-.022.352-.036.528-.034.39-.082.778-.153 1.163a14.258 14.258 0 0 1-.574 2.114c-.229.654-.484 1.306-.806 1.918a9.16 9.16 0 0 1-.386.656c-.219.348-.451.686-.697 1.013-.448.594-.946 1.148-1.521 1.614-.255.207-.52.397-.808.553-.9.489-1.919.648-2.921.735-.493.038-.986.059-1.478.099-.162.015-.324.033-.486.049-.145.011-.289.022-.434.03a15.768 15.768 0 0 1-2.778-.118c0 1.416.007 2.832-.001 4.248a9.737 9.737 0 0 1-.684 3.479 9.615 9.615 0 0 1-1.72 2.804 9.326 9.326 0 0 1-3.04 2.279 9.046 9.046 0 0 1-5.33.715 9.064 9.064 0 0 1-2.988-1.079 9.363 9.363 0 0 1-2.761-2.429 10.078 10.078 0 0 1-1.05 1.16 9.281 9.281 0 0 1-1.871 1.358 9.033 9.033 0 0 1-2.495.926 9.04 9.04 0 0 1-6.462-1.072 9.395 9.395 0 0 1-2.602-2.292l-.062-.08a10.896 10.896 0 0 1-.53.635 9.266 9.266 0 0 1-2.671 2.032 9.028 9.028 0 0 1-6.044.751 9.048 9.048 0 0 1-2.436-.934 9.343 9.343 0 0 1-2.286-1.803 9.572 9.572 0 0 1-1.783-2.757 9.705 9.705 0 0 1-.773-3.693V67.244c-.157.024-.314.047-.472.067-.487.06-.977.103-1.469.109-.313.004-.627-.009-.94-.028-.426-.025-.85-.065-1.273-.125-1.833-.264-3.65-.92-5.109-2.117a8.172 8.172 0 0 1-1.064-1.049 10.155 10.155 0 0 1-.878-1.236 15.277 15.277 0 0 1-.7-1.274 20.835 20.835 0 0 1-1.889-6.194l-.018-.142-.008-.061a6.47 6.47 0 0 1-.99-.297 6.135 6.135 0 0 1-.61-.285 6.587 6.587 0 0 1-.889-.562c-1.228-.924-2.124-2.259-2.668-3.711a9.947 9.947 0 0 1-.307-.99 10.288 10.288 0 0 1-.318-1.923c-.009-.147-.011-.293-.015-.44v-.037c.008-.175.004-.22.037-.393.033-.173.053-.213.11-.378l.561-1.417c.031-.068.06-.139.095-.206a2.028 2.028 0 0 1 .771-.803c.093-.054.194-.095.289-.145l.311-.179c.352-.194.714-.358 1.107-.44.213-.044.426-.061.643-.061l.034.001c.177.014.223.01.396.052.174.041.214.065.379.132l1.347.635c.073.04.15.076.221.121.142.091.272.2.388.325.154.166.176.222.297.414l.022.047.722-.762.168-.158c.165-.122.202-.161.385-.253.206-.102.429-.168.656-.193.076-.008.152-.008.228-.011l1.46.013c.177.011.223.007.397.046.175.038.215.061.381.126l.018.008c.154.08.196.094.338.196.142.102.169.137.294.259l.853.912.152-.067.191-.063.019-.005.196-.042c.177-.019.222-.031.401-.022.066.003.133.013.199.02l1.185.182c.073.016.147.027.219.047.288.08.558.227.784.428.151.135.177.181.303.339l.714 1.004c.097.152.127.187.201.352.077.172.123.352.164.536.029.134.056.269.08.404.063.361.102.725.112 1.091.021.78-.08 1.566-.321 2.307a5.906 5.906 0 0 1-.532 1.183 5.463 5.463 0 0 1-3.257 2.489l-.03.008c.195.584.433 1.155.712 1.701.215.422.453.833.735 1.211.026.035.026.034.053.068l.058.072c.056.024.113.042.171.06.319.09.653.121.982.14.488.027.978.013 1.461-.06.167-.028.333-.062.499-.089.134-.022.267-.042.401-.066l.28-.056c.154-.023.308-.049.462-.076l.115-.021V43.881c.011-.203.006-.203.042-.404a26.66 26.66 0 0 1 .226-2.241 24.737 24.737 0 0 1 5.72-12.577 24.204 24.204 0 0 1 3.457-3.296 23.653 23.653 0 0 1 4.937-2.966 23.215 23.215 0 0 1 5.604-1.681 23.703 23.703 0 0 1 3.958-.313zm-.287 2.042a21.169 21.169 0 0 0-8.012 1.622 21.636 21.636 0 0 0-4.799 2.766 22.233 22.233 0 0 0-3.205 2.985 22.705 22.705 0 0 0-4.897 9.196 23.383 23.383 0 0 0-.737 4.867h-.025v15.744c-.258.053-.258.052-.517.101-.28.051-.56.1-.841.144-.211.04-.421.079-.632.115l-.232.037-.411.078c-.116.02-.233.035-.348.057-.305.056-.609.11-.917.14a9.929 9.929 0 0 1-1.883-.017c-.514-.056-1.044-.155-1.51-.397a1.762 1.762 0 0 1-.33-.218 1.925 1.925 0 0 1-.234-.252 5.248 5.248 0 0 1-.174-.22 8.97 8.97 0 0 1-.582-.883 13.806 13.806 0 0 1-.941-1.971 14.348 14.348 0 0 1-.608-1.954 14.04 14.04 0 0 1-.169-.86l-.015-.11-.015-.109c.161-.007.16-.007.321-.016a12.793 12.793 0 0 0 1.413-.182 4.43 4.43 0 0 0 .28-.074 3.56 3.56 0 0 0 1.199-.616c.309-.244.576-.543.786-.88.163-.261.292-.544.387-.838.123-.378.192-.774.214-1.172a5.102 5.102 0 0 0-.024-.865 7.192 7.192 0 0 0-.145-.799l-.714-1.005-1.184-.182-.019.005-.946.758-.12 1.229a4.953 4.953 0 0 1 .111.455c.032.181.052.36.043.544a1.04 1.04 0 0 1-.056.303c-.11.301-.419.451-.696.548-.402.142-.813.25-1.229.339l.07-.648c.022-.191.047-.381.08-.57.036-.207.079-.413.152-.61.077-.211.182-.412.296-.605.044-.074.092-.146.135-.222.029-.048.031-.047.055-.098.016-.033.031-.064.045-.098l-.026-1.551-1.042-1.116-.018-.008-1.459-.014-1.022 1.079c-.049.128-.08.258-.111.393a5.274 5.274 0 0 0-.1.651 5.55 5.55 0 0 0-.031.466c-.009.687.104 1.37.294 2.028.11.382.262.753.402 1.123-.115-.029-.228-.06-.342-.092a9.526 9.526 0 0 1-1.176-.446c-.108-.05-.111-.048-.191-.097a1.921 1.921 0 0 1-.327-.249c-.416-.4-.589-.986-.671-1.55a5.643 5.643 0 0 1-.057-.549c-.007-.143-.006-.286-.007-.429-.001-.186.005-.372.011-.558l.001-.039-.567-1.446-1.347-.634c-.316-.008-.599.144-.867.299-.109.063-.218.126-.33.185a2.058 2.058 0 0 1-.125.061l-.042.019-.561 1.416c0 .209.014.416.036.624.04.377.106.75.196 1.118.076.309.164.616.275.913.415 1.109 1.093 2.146 2.043 2.838.234.171.485.317.746.442.183.088.371.161.565.22.263.079.532.13.803.17.296.045.594.075.892.095l.108.007c.004.151.01.302.017.453.011.177.023.353.038.529a18.13 18.13 0 0 0 .762 3.752c.239.76.522 1.505.857 2.225.23.494.483.977.767 1.44.288.469.608.915.989 1.308 1.001 1.028 2.324 1.648 3.687 1.976.643.155 1.298.243 1.955.287.311.021.622.036.933.033.418-.006.835-.041 1.25-.094.238-.03.477-.064.713-.11.117-.023.232-.053.348-.081.196-.048.392-.097.586-.151.147-.041.291-.094.436-.144.204-.069.408-.139.608-.217l.006-.003c0 2.207-.013 4.414.001 6.62a7.942 7.942 0 0 0 .13 1.32 7.545 7.545 0 0 0 2.383 4.243 7.23 7.23 0 0 0 2.258 1.372 7.094 7.094 0 0 0 7.012-1.164 7.504 7.504 0 0 0 2.035-2.613 7.727 7.727 0 0 0 .676-2.401l.009-.088.038-.765a8.16 8.16 0 0 0 .113 1.324c.121.694.338 1.37.643 2.001a7.49 7.49 0 0 0 1.692 2.275 7.266 7.266 0 0 0 2.24 1.399 7.11 7.11 0 0 0 4.615.19 7.212 7.212 0 0 0 2.351-1.218 7.501 7.501 0 0 0 2.128-2.64 7.763 7.763 0 0 0 .702-2.39l.01-.088.009-.088.038-.765a9.339 9.339 0 0 0 .021.575 7.626 7.626 0 0 0 .621 2.504 7.507 7.507 0 0 0 2.35 2.972 7.1 7.1 0 0 0 7.026.881 7.275 7.275 0 0 0 2.268-1.515 7.525 7.525 0 0 0 1.612-2.338 7.58 7.58 0 0 0 .572-2.033c.048-.347.069-.696.071-1.046v-6.721c.136.051.271.101.408.148a12.153 12.153 0 0 0 1.976.443c.264.035.529.055.794.071.33.02.66.031.991.027.245-.002.49-.012.735-.031.245-.018.49-.048.735-.068.407-.03.814-.051 1.221-.079a9.493 9.493 0 0 0 1.384-.188c.315-.073.626-.174.912-.329a3.53 3.53 0 0 0 .586-.418c.46-.386.85-.85 1.205-1.337a12.178 12.178 0 0 0 .801-1.246c.122-.232.229-.471.33-.712a15.873 15.873 0 0 0 .681-1.988c.136-.525.23-1.058.282-1.598.035-.41.052-.822.088-1.232.03-.317.078-.632.121-.947l.018-.145.016-.145c.144.009.287.016.431.021.459.009.924.007 1.378-.07a4.456 4.456 0 0 0 1.353-.482c.989-.55 1.752-1.466 2.258-2.488.116-.235.214-.48.304-.727a7.58 7.58 0 0 0 .377-1.43c.016-.109.027-.218.039-.328l.001-.009-.438-1.428a5.206 5.206 0 0 1-.16-.096c-.158-.105-.311-.219-.467-.326a3.829 3.829 0 0 0-.159-.1 1.356 1.356 0 0 0-.509-.18l-.01-.001-1.386.452-.681 1.323c-.016.212-.023.424-.043.636a5.66 5.66 0 0 1-.139.873c-.118.494-.316.999-.702 1.338a1.865 1.865 0 0 1-.496.301l-.272.087a9.57 9.57 0 0 1-.83.205 8.797 8.797 0 0 1-.582.091l.229-.462c.079-.163.158-.325.229-.492.051-.118.096-.239.139-.36.036-.103.076-.209.103-.315.019-.075.031-.153.041-.229.017-.132.031-.263.043-.395.035-.368.06-.737.094-1.104.02-.187.048-.372.067-.559.015-.167.015-.336.012-.505a4.76 4.76 0 0 0-.074-.826c-.012-.065-.03-.13-.045-.194l-.003-.009-.923-1.157-1.446-.159-.019.006-1.124.95-.154 1.489c.011.034.024.066.037.099.044.115.107.221.161.331.046.096.088.193.13.29l.031.076c.013.033.017.07.023.105.012.096.022.191.031.287.031.364.047.73.081 1.093.013.102.028.202.04.303.014.145.027.29.033.435.014.28.016.561.023.841a9.588 9.588 0 0 1-.862-.323c-.063-.027-.128-.062-.193-.084a1.325 1.325 0 0 0-.067-.013c-.081-.01-.162-.017-.243-.025-.245-.02-.49-.037-.734-.061-.066-.007-.132-.014-.198-.028l-.017-.005c-.03-.013-.029-.014-.067-.038a1.614 1.614 0 0 1-.161-.108.863.863 0 0 1-.22-.242c-.089-.155-.102-.34-.09-.517.02-.299.117-.591.228-.866l.004-.009-.018-1.197-.874-.84-.018-.007-1.188.036-.79.882c-.037.112-.074.224-.106.338a4.756 4.756 0 0 0-.171 1.906c.039.329.115.654.233.963a3.542 3.542 0 0 0 1.263 1.636c.313.222.659.393 1.019.517.237.082.487.111.734.145.479.06.959.106 1.438.166.121.017.241.037.362.058l.158.026a12.12 12.12 0 0 1-.923 2.565 13.221 13.221 0 0 1-.829 1.474 9.474 9.474 0 0 1-.984 1.286c-.08.087-.163.17-.248.252a1.655 1.655 0 0 1-.329.262 2.376 2.376 0 0 1-.722.247c-.457.089-.927.093-1.39.071-.391-.018-.781-.06-1.168-.123a7.817 7.817 0 0 1-.609-.124c-.226-.056-.448-.124-.671-.191-.065-.019-.131-.035-.197-.054a14.75 14.75 0 0 1-.543-.165 23.384 23.384 0 0 1-.453-.128c-.196-.059-.195-.059-.39-.12l-.276-.077V43.881h-.025a34.633 34.633 0 0 0-.031-.557 23.606 23.606 0 0 0-.4-2.994 22.743 22.743 0 0 0-1.492-4.708 22.567 22.567 0 0 0-4.593-6.748 21.865 21.865 0 0 0-6.882-4.706 21.175 21.175 0 0 0-8.115-1.722l-.411-.001zm9.15 33.69c.109.015.214.038.315.085a1.012 1.012 0 0 1 .574.771c.021.132.013.268.009.4a8.38 8.38 0 0 1-.026.476 8.767 8.767 0 0 1-1.564 4.282c-.306.437-.65.846-1.024 1.222a10.09 10.09 0 0 1-4.612 2.627c-1.32.343-2.704.427-4.055.254a10.422 10.422 0 0 1-2.67-.709 9.917 9.917 0 0 1-3.57-2.503 9.312 9.312 0 0 1-.775-.984 8.933 8.933 0 0 1-.731-1.288 8.648 8.648 0 0 1-.795-3.377c-.003-.104-.008-.211 0-.316a1.042 1.042 0 0 1 .254-.609.98.98 0 0 1 1.337-.125 1.023 1.023 0 0 1 .385.719c.007.151.006.303.014.454a6.547 6.547 0 0 0 .524 2.217c.257.595.599 1.15 1.006 1.648.325.398.691.759 1.087 1.081.312.253.642.482.987.684 2.592 1.522 5.945 1.538 8.553.047a7.982 7.982 0 0 0 1.069-.731 7.619 7.619 0 0 0 1.142-1.15 6.949 6.949 0 0 0 1.018-1.741 6.538 6.538 0 0 0 .467-2.425l.004-.084a1.012 1.012 0 0 1 .672-.876c.08-.028.158-.04.241-.05.082-.003.082-.003.164.001zm-70.51-12.426c-15.5.93-28.544-5.922-30.126-16.443C-1.156 15.689 11.64 4.024 29.14 1.235c17.501-2.79 33.123 4.345 34.864 15.922 1.575 10.475-8.749 21.021-23.691 25.001l.001.099a31.185 31.185 0 0 0 .042.833c.007.094.019.188.021.282.006.178.013.356.024.534.011.16.024.32.039.48.017.154.038.306.058.459.036.273.077.544.144.811a4.723 4.723 0 0 0 .449 1.128c.192.332.434.628.702.898l.047.05c.151.139.302.275.461.403.24.192.492.367.748.537.474.314.962.6 1.457.877l.041.023.588.735-.729.586c-.376.112-.755.216-1.135.309a11.193 11.193 0 0 1-2.562.355 8.575 8.575 0 0 1-2.995-.486 8.461 8.461 0 0 1-.96-.413 11.194 11.194 0 0 1-1.836-1.152 13.345 13.345 0 0 1-1.07-.934c-.23-.221-.454-.448-.672-.681-.121-.129-.246-.258-.36-.395a23.448 23.448 0 0 1-1.328-1.773c-.051-.076-.049-.077-.095-.155l-.277-.477-.072-.13c-.081-.177-.159-.357-.238-.535l-.003-.01-.092-.707zm52.409-7.804c3.557 0 6.444 3.201 6.444 7.145 0 3.944-2.887 7.146-6.444 7.146s-6.444-3.202-6.444-7.146 2.887-7.145 6.444-7.145zm18.062 0c3.557 0 6.444 3.201 6.444 7.145 0 3.944-2.887 7.146-6.444 7.146s-6.444-3.202-6.444-7.146 2.887-7.145 6.444-7.145zM83.12 42.029c1.915 0 3.47 1.601 3.47 3.573s-1.555 3.573-3.47 3.573c-1.915 0-3.47-1.601-3.47-3.573s1.555-3.573 3.47-3.573zm17.846 0c1.915 0 3.47 1.601 3.47 3.573s-1.555 3.573-3.47 3.573c-1.915 0-3.47-1.601-3.47-3.573s1.555-3.573 3.47-3.573zM17.019 28c-.368 1.65-1.848 5.008-5.178 5.799-2.572.611-4.153-.815-4.544-2.559-.424-1.891.722-3.532 2.121-4.575a3.473 3.473 0 0 1-1.446-2.099c-.421-1.875.867-3.637 3.184-4.187 1.917-.455 3.185.248 3.462 1.482.265 1.184-.534 2.275-1.828 2.582-.878.209-1.574-.042-1.718-.683a1.4 1.4 0 0 1 .044-.704s.287.227.894.083c.751-.179 1.086-.709.972-1.219-.14-.625-.892-.827-1.739-.626-1.054.25-2.06 1.096-1.713 2.642.232 1.036.871 1.56 1.483 1.813.245-.11.481-.183.688-.233.943-.224 1.48-.005 1.587.472.092.411-.144.935-1.166 1.178a3.255 3.255 0 0 1-1.548.004c-.837.771-1.58 1.883-1.27 3.264.276 1.234 1.267 2.125 2.944 1.726 2.598-.617 3.861-3.638 4.277-4.883-.353-.574-.615-1.153-.732-1.676-.107-.477.145-1.005.863-1.175.48-.114.702.127.846.769a2.77 2.77 0 0 1-.03.995c.209.331.443.622.735.951.616-1.983 1.369-3.877 1.737-3.964.591-.141 1.492.65 1.492.65-.815.644-1.689 2.376-2.333 4.158.804.658 1.627 1.103 2.139.982.43-.102.735-.577.95-1.151-.323-2.226.975-4.331 2.31-4.648.703-.167 1.257.204 1.39.796.114.51-.044 1.379-.854 1.745-.236-1.053-.672-1.348-.944-1.283-.495.117-.844 1.413-.538 2.778.232 1.037.712 1.529 1.351 1.377.756-.179 1.333-1.176 1.699-2.128-.265-2.095.877-4.166 2.221-4.486.671-.159 1.214.162 1.391.952.332 1.48-.986 2.885-2.173 3.444.265.734.673 1.053 1.281.909.96-.229 1.578-1.465 1.923-2.506-.125-1.267-.26-2.385-.406-3.035l-.055-.247s1.568-.286 1.778.652l.019.082c.238-.663.67-1.216 1.309-1.368.83-.197 1.526.504 1.755 1.524.497 2.22-.556 4.428-1.834 4.732-.368.087-.642.066-.883-.033.121 1.288.292 2.651.542 3.77.126.559.272 1.061.448 1.47-.464.11-1.797.392-1.978-.414-.16-.716-.342-3.206-.554-5.612-.504 1.107-1.311 2.192-2.441 2.46-1.008.24-1.685-.303-2.055-1.182-.491 1.082-1.281 2.148-2.381 2.409-.817.194-1.554-.117-1.988-1.013-.36.843-.875 1.555-1.54 1.713-.639.152-1.53-.295-2.4-1.024-.239.888-.384 1.668-.39 2.241 0 0-.701.028-.804-.433-.096-.427.065-1.436.341-2.61a10.315 10.315 0 0 1-.713-.848zm38.163-17.803c.068.157.185.527.266.889.424 1.892.37 4.451.739 6.42-.065.61-.387 3.077-1.352 3.307-.192.045-.333-.06-.422-.454-.14-.626-.091-1.607-.293-2.512-.258-1.152-.782-1.686-1.517-1.511-.767.182-1.287 1.016-1.643 2.054-.022-.099-.053-.386-.093-.567-.211-.938-1.779-.652-1.779-.652a6.2 6.2 0 0 1 .457 1.364c.07.31.119.618.155.921-.246.495-.637.996-1.225 1.135-.064.015-.128.031-.195.029a6.977 6.977 0 0 0-.126-.784c-.258-1.152-.871-2.011-1.526-1.855a.712.712 0 0 0-.423.291c-1.337.317-2.358 2.107-2.118 3.919-.214.889-.551 1.757-1.059 1.877-.415.099-.724-.452-1.03-1.817-.059-.263-.09-.706-.122-1.149.142-.64.177-1.237.081-1.665-.107-.477-.417-.733-.816-.638-.715.17-.909 1.75-.52 3.801-.238.92-.639 1.915-1.278 2.067-.464.11-.835-.27-1.012-1.059-.158-.708-.196-1.929-.236-3.08 1.201-.424 1.911-1.009 1.775-1.617-.114-.51-.739-.743-.739-.743s-.124.722-1.064 1.258c-.029-.582-.064-1.111-.137-1.44-.137-.609-.458-.914-1.688-.622.158.327.274.698.359 1.076.103.46.162.949.189 1.445-.611.128-.947.052-.947.052s-.1.457-.041.72c.078.345.432.348 1.026.224.02 1.364-.067 2.701.143 3.639.306 1.365 1.231 1.89 2.046 1.697.907-.216 1.539-1.275 1.914-2.36.407 1.245 1.031 1.955 1.951 1.736.731-.174 1.261-1.142 1.587-2.195.431.765 1.15 1.129 1.983.931 1.214-.289 1.742-1.54 1.835-2.775 0 0 .147-.018.243-.04.526-.125.949-.488 1.26-.915.04.788.053 1.518.194 2.146.111.493.339.612.595.552.495-.118 1.081-.881 1.081-.881a3.93 3.93 0 0 1-.383-1.035c-.284-1.267.317-3.541.988-3.7.208-.049.377.257.492.767.057.255.092.504.115.751l.098 1.469c.024.246.059.496.116.751.158.707.63 1.236 1.381 1.058 1.317-.313 2.07-2.634 2.178-3.956.228.157.536.175.909.086-.505-2.253.089-6.136-.298-7.864-.1-.444-1.001-.58-1.607-.583l-.467.037zM33.729 22.293c.415-.099.711.246.885 1.02.287 1.283-.222 2.616-.797 2.753-.191.045-.695-.025-.961-1.21-.025-.115-.051-.23-.061-.349.05-1.277.439-2.097.934-2.214zm-5.187.955c.271-.065.511.104.588.449.137.609-.338 1.345-1.275 1.966-.255-1.36.159-2.29.687-2.415zm18.032-.403c-.607.144-1.062-.458-1.239-1.248-.217-.97.001-2.097.644-2.457.001.155.038.32.075.484.147.658.554 1.497 1.268 1.83-.017.749-.253 1.273-.748 1.391zm9.877-1.654c.103.461.496.714 1.039.585.799-.19.973-.993.847-1.553-.125-.559-.461-.93-.988-.805-.543.13-1.108.836-.898 1.773zm-14.21-5.442c-.104-.461-.497-.714-1.056-.581-.783.186-.972.993-.847 1.552.126.56.461.93.908.824.56-.133 1.172-1.006.995-1.795z" fill="#fff" fill-opacity=".6"></path></svg>'; + return '<svg viewBox="0 0 136 81" xmlns="http://www.w3.org/2000/svg" fill-rule="evenodd" clip-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="1.4"><path d="M92.4 20.4a23.2 23.2 0 0 1 9 1.9 23.7 23.7 0 0 1 5.2 3 24.3 24.3 0 0 1 3.4 3.4 24.8 24.8 0 0 1 5 9.4c.5 1.7.8 3.4 1 5.2v14.5h.4l.5.2a7.4 7.4 0 0 0 2.5.2l.2-.2.6-.8.8-1.3-.2-.1a5.5 5.5 0 0 1-.8-.3 5.6 5.6 0 0 1-2.3-1.8 5.7 5.7 0 0 1-.9-1.6 6.5 6.5 0 0 1-.2-2.8 7.3 7.3 0 0 1 .5-2l.3-.3.8-.9.3-.3c.2-.2.5-.3.8-.3H120.7c.2 0 .3-.1.4 0h.4l.2.1.3.2.2-.4.3-.4.1-.1 1.2-1 .3-.2.4-.1.4-.1h.3l1.5.1.4.1.8.5.1.2 1 1.1v.2H129.4l.4-.2 1.4-.5h1.1c.3 0 .7.2 1 .4.2 0 .3.2.5.3l.2.2.5.3.4.6.1.3.4 1.4.1.4v.6a7.8 7.8 0 0 1-.1.6 9.9 9.9 0 0 1-.8 2.4 7.8 7.8 0 0 1-3 3.3 6.4 6.4 0 0 1-1 .5 6.1 6.1 0 0 1-.6.2l-.7.1h-.1a23.4 23.4 0 0 1-.2 1.7 14.3 14.3 0 0 1-.6 2.1l-.8 2a9.2 9.2 0 0 1-.4.6l-.7 1a9.1 9.1 0 0 1-2.3 2.2c-.9.5-2 .6-3 .7l-1.4.1h-.5l-.4.1a15.8 15.8 0 0 1-2.8-.1v4.2a9.7 9.7 0 0 1-.7 3.5 9.6 9.6 0 0 1-1.7 2.8 9.3 9.3 0 0 1-3 2.3 9 9 0 0 1-5.4.7 9 9 0 0 1-3-1 9.4 9.4 0 0 1-2.7-2.5 10 10 0 0 1-1 1.2 9.3 9.3 0 0 1-2 1.3 9 9 0 0 1-2.4 1 9 9 0 0 1-6.5-1.1A9.4 9.4 0 0 1 85 77V77a10.9 10.9 0 0 1-.6.6 9.3 9.3 0 0 1-2.7 2 9 9 0 0 1-6 .8 9 9 0 0 1-2.4-1 9.3 9.3 0 0 1-2.3-1.7 9.6 9.6 0 0 1-1.8-2.8 9.7 9.7 0 0 1-.8-3.7v-4a18.5 18.5 0 0 1-2.9.2l-1.2-.1c-1.9-.3-3.7-1-5.1-2.1A8.2 8.2 0 0 1 58 64a10.2 10.2 0 0 1-.9-1.2 15.3 15.3 0 0 1-.7-1.3 20.8 20.8 0 0 1-1.9-6.2v-.2a6.5 6.5 0 0 1-1-.3 6.1 6.1 0 0 1-.6-.3 6.6 6.6 0 0 1-.9-.5 8.2 8.2 0 0 1-2.7-3.8 10 10 0 0 1-.3-1 10.3 10.3 0 0 1-.3-1.9V47v-.4l.1-.4.6-1.4.1-.2a2 2 0 0 1 .8-.8l.3-.2.3-.2a3.2 3.2 0 0 1 1.8-.5h.4l.3.2 1.4.6.2.2.4.3.3.4.7-.7.2-.2.4-.2.6-.2h2.1l.4.2.4.2.3.2.8 1 .2-.1h.1v-.1H63l1.1.1h.3l.8.5.3.4.7 1 .2.3.1.5a11 11 0 0 1 .2 1.5c0 .8 0 1.6-.3 2.3a6 6 0 0 1-.5 1.2 5.5 5.5 0 0 1-3.3 2.5 12.3 12.3 0 0 0 1.4 3h.1l.2.1 1 .2h1.5l.5-.2H67.8l.5-.2h.1V44v-.4a26.7 26.7 0 0 1 .3-2.3 24.7 24.7 0 0 1 5.7-12.5 24.2 24.2 0 0 1 3.5-3.3 23.7 23.7 0 0 1 4.9-3 23.2 23.2 0 0 1 5.6-1.7 23.7 23.7 0 0 1 4-.3zm-.3 2a21.2 21.2 0 0 0-8 1.7 21.6 21.6 0 0 0-4.8 2.7 22.2 22.2 0 0 0-3.2 3 22.7 22.7 0 0 0-5 9.2 23.4 23.4 0 0 0-.7 4.9v15.7l-.5.1a34.3 34.3 0 0 1-1.5.3h-.2l-.4.1h-.4l-.9.2a10 10 0 0 1-1.9 0c-.5 0-1-.2-1.5-.4a1.8 1.8 0 0 1-.3-.2 2 2 0 0 1-.3-.3 5.2 5.2 0 0 1-.1-.2 9 9 0 0 1-.6-.9 13.8 13.8 0 0 1-1-2 14.3 14.3 0 0 1-.6-2 14 14 0 0 1-.1-.8v-.2h.3a12.8 12.8 0 0 0 1.4-.2 4.4 4.4 0 0 0 .3 0 3.6 3.6 0 0 0 1.1-.7 3.4 3.4 0 0 0 1.2-1.7l.2-1.2a5.1 5.1 0 0 0 0-.8 7.2 7.2 0 0 0-.1-.8l-.7-1-1.2-.2-1 .7-.1 1.3a5 5 0 0 1 .1.4v.6a1 1 0 0 1 0 .3c-.1.3-.4.4-.7.5l-1.2.4v-.7A9.9 9.9 0 0 1 60 49l.3-.6v-.2l.1-.1v-1.6l-1-1.2h-1.5l-1 1.1v.4a5.3 5.3 0 0 0-.2.6 5.5 5.5 0 0 0 0 .5c0 .7 0 1.4.3 2 0 .4.2.8.4 1.2L57 51a9.5 9.5 0 0 1-1.1-.5h-.2a2 2 0 0 1-.4-.3c-.4-.4-.5-1-.6-1.6a5.6 5.6 0 0 1 0-.5v-.5-.5l-.6-1.5-1.4-.6-.9.3s-.2 0-.3.2a2 2 0 0 1-.1 0l-.6 1.4v.7a8.5 8.5 0 0 0 .5 2c.4 1.1 1 2.1 2 2.8a4.7 4.7 0 0 0 2.1.9h1a22.8 22.8 0 0 0 .1 1 18.1 18.1 0 0 0 .8 3.8 18.2 18.2 0 0 0 1.6 3.7l1 1.3c1 1 2.3 1.6 3.7 2a11.7 11.7 0 0 0 4.8 0h.4l.5-.2.5-.1.6-.2v6.6a8 8 0 0 0 .1 1.3 7.5 7.5 0 0 0 2.4 4.3 7.2 7.2 0 0 0 2.3 1.3 7 7 0 0 0 7-1.1 7.5 7.5 0 0 0 2-2.6A7.7 7.7 0 0 0 85 72V71a8.2 8.2 0 0 0 .2 1.3c0 .7.3 1.4.6 2a7.5 7.5 0 0 0 1.7 2.3 7.3 7.3 0 0 0 2.2 1.4 7.1 7.1 0 0 0 4.6.2 7.2 7.2 0 0 0 2.4-1.2 7.5 7.5 0 0 0 2.1-2.7 7.8 7.8 0 0 0 .7-2.4V71a9.3 9.3 0 0 0 .1.6 7.6 7.6 0 0 0 .6 2.5 7.5 7.5 0 0 0 2.4 3 7.1 7.1 0 0 0 7 .8 7.3 7.3 0 0 0 2.3-1.5 7.5 7.5 0 0 0 1.6-2.3 7.6 7.6 0 0 0 .5-2l.1-1.1v-6.7l.4.1a12.2 12.2 0 0 0 2 .5 11.1 11.1 0 0 0 2.5 0h.8l1.2-.1a9.5 9.5 0 0 0 1.4-.2l.9-.3a3.5 3.5 0 0 0 .6-.4l1.2-1.4a12.2 12.2 0 0 0 .8-1.2c0-.3.2-.5.3-.7a15.9 15.9 0 0 0 .7-2l.3-1.6v-1.3l.2-.9V54.6a15.5 15.5 0 0 0 1.8 0 4.5 4.5 0 0 0 1.4-.5 5.7 5.7 0 0 0 2.5-3.2 7.6 7.6 0 0 0 .4-1.5v-.3l-.4-1.4a5.2 5.2 0 0 1-.2-.1l-.4-.4a3.8 3.8 0 0 0-.2 0 1.4 1.4 0 0 0-.5-.2l-1.4.4-.7 1.3v.7a5.7 5.7 0 0 1-.1.8l-.7 1.4a1.9 1.9 0 0 1-.5.3h-.3a9.6 9.6 0 0 1-.8.3 8.8 8.8 0 0 1-.6 0l.2-.4.2-.5.2-.3v-.4l.1-.2V50l.1-1 .1-.6v-.6a4.8 4.8 0 0 0 0-.8v-.2l-1-1.1-1.5-.2-1.1 1-.2 1.4v.1l.2.4.2.3v.4l.1 1.1v.3l.1.5v.8a9.6 9.6 0 0 1-.8-.3l-.2-.1h-.3l-.8-.1h-.2a1.6 1.6 0 0 1-.2-.2.9.9 0 0 1-.2-.2 1 1 0 0 1-.1-.5l.2-.9v-1.2l-.9-.8h-1.2l-.8.9v.3a4.8 4.8 0 0 0-.3 2l.3.9a3.5 3.5 0 0 0 1.2 1.6l1 .5.8.2 1.4.1h.4l.2.1a12.1 12.1 0 0 1-1 2.6 13.2 13.2 0 0 1-.8 1.5 9.5 9.5 0 0 1-1 1.2l-.2.3a1.7 1.7 0 0 1-.4.3 2.4 2.4 0 0 1-.7.2h-2.5a7.8 7.8 0 0 1-.6-.2l-.7-.2h-.2a14.8 14.8 0 0 1-.6-.2 23.4 23.4 0 0 1-.4-.1l-.4-.1-.3-.1V43.9a34.6 34.6 0 0 0 0-.6 23.6 23.6 0 0 0-.4-3 22.7 22.7 0 0 0-1.5-4.7 22.6 22.6 0 0 0-4.6-6.7 21.9 21.9 0 0 0-6.9-4.7 21.2 21.2 0 0 0-8.1-1.8H92zm9.1 33.7l.3.1a1 1 0 0 1 .6.8v.4a8.4 8.4 0 0 1 0 .5 8.8 8.8 0 0 1-1.6 4.2l-1 1.3A10 10 0 0 1 95 66c-1.3.3-2.7.4-4 .3a10.4 10.4 0 0 1-2.7-.8 10 10 0 0 1-3.6-2.5 9.3 9.3 0 0 1-.8-1 9 9 0 0 1-.7-1.2 8.6 8.6 0 0 1-.8-3.4V57a1 1 0 0 1 .3-.6 1 1 0 0 1 1.3-.2 1 1 0 0 1 .4.8v.4a6.5 6.5 0 0 0 .5 2.2 7 7 0 0 0 2.1 2.8l1 .6c2.6 1.6 6 1.6 8.5 0a8 8 0 0 0 1.1-.6 7.6 7.6 0 0 0 1.2-1.2 7 7 0 0 0 1-1.7 6.5 6.5 0 0 0 .4-2.5 1 1 0 0 1 .7-1h.4zM30.7 43.7c-15.5 1-28.5-6-30.1-16.4C-1.2 15.7 11.6 4 29 1.3 46.6-1.7 62.3 5.5 64 17.1c1.6 10.4-8.7 21-23.7 25a31.2 31.2 0 0 0 0 .9v.3a19 19 0 0 0 .1 1l.1.4.1.9a4.7 4.7 0 0 0 .5 1l.7 1a9.2 9.2 0 0 0 1.2 1l1.5.8.6.8-.7.6-1.1.3a11.2 11.2 0 0 1-2.6.4 8.6 8.6 0 0 1-3-.5 8.5 8.5 0 0 1-1-.4 11.2 11.2 0 0 1-1.8-1.2 13.3 13.3 0 0 1-1-1 18 18 0 0 1-.7-.6l-.4-.4a23.4 23.4 0 0 1-1.3-1.8l-.1-.1-.3-.5V45l-.3-.6v-.7zM83.1 36c3.6 0 6.5 3.2 6.5 7.1 0 4-3 7.2-6.5 7.2S76.7 47 76.7 43 79.6 36 83 36zm18 0c3.6 0 6.5 3.2 6.5 7.1 0 4-2.9 7.2-6.4 7.2S94.7 47 94.7 43s3-7.1 6.5-7.1zm-18 6.1c2 0 3.5 1.6 3.5 3.6S85 49.2 83 49.2s-3.4-1.6-3.4-3.6S81.2 42 83 42zm17.9 0c1.9 0 3.4 1.6 3.4 3.6s-1.5 3.6-3.4 3.6c-2 0-3.5-1.6-3.5-3.6S99.1 42 101 42zM17 28c-.3 1.6-1.8 5-5.2 5.8-2.5.6-4.1-.8-4.5-2.6-.4-1.9.7-3.5 2.1-4.5A3.5 3.5 0 0 1 8 24.6c-.4-2 .8-3.7 3.2-4.2 1.9-.5 3.1.2 3.4 1.5.3 1.1-.5 2.2-1.8 2.5-.9.3-1.6 0-1.7-.6a1.4 1.4 0 0 1 0-.7s.3.2 1 0c.7-.1 1-.7.9-1.2-.2-.6-1-.8-1.8-.6-1 .2-2 1-1.7 2.6.3 1 .9 1.6 1.5 1.8l.7-.2c1-.2 1.5 0 1.6.5 0 .4-.2 1-1.2 1.2a3.3 3.3 0 0 1-1.5 0c-.9.7-1.6 1.9-1.3 3.2.3 1.3 1.3 2.2 3 1.8 2.5-.7 3.8-3.7 4.2-5-.3-.5-.6-1-.7-1.6-.1-.5.1-1 .9-1.2.4 0 .7.2.8.8a2.8 2.8 0 0 1 0 1l.7 1c.6-2 1.4-4 1.7-4 .6-.2 1.5.6 1.5.6-.8.7-1.7 2.4-2.3 4.2.8.6 1.6 1 2.1 1 .5-.1.8-.6 1-1.2-.3-2.2 1-4.3 2.3-4.6.7-.2 1.3.2 1.4.8.1.5 0 1.3-.9 1.7-.2-1-.6-1.3-1-1.3-.4.1-.7 1.4-.4 2.8.2 1 .7 1.5 1.3 1.4.8-.2 1.3-1.2 1.7-2.1-.3-2.1.9-4.2 2.2-4.5.7-.2 1.2.1 1.4 1 .4 1.4-1 2.8-2.2 3.4.3.7.7 1 1.3.9 1-.3 1.6-1.5 2-2.5l-.5-3v-.3s1.6-.3 1.8.6v.1c.2-.6.7-1.2 1.3-1.4.8-.1 1.5.6 1.7 1.6.5 2.2-.5 4.4-1.8 4.7H33a31.9 31.9 0 0 0 1 5.2c-.4.1-1.8.4-2-.4l-.5-5.6c-.5 1-1.3 2.2-2.5 2.4-1 .3-1.6-.3-2-1.1-.5 1-1.3 2.1-2.4 2.4-.8.2-1.5-.1-2-1-.3.8-.9 1.5-1.5 1.7-.7.1-1.5-.3-2.4-1-.3.8-.4 1.6-.4 2.2 0 0-.7 0-.8-.4-.1-.5 0-1.5.3-2.7a10.3 10.3 0 0 1-.7-.8zm38.2-17.8l.2.9c.5 1.9.4 4.4.8 6.4 0 .6-.4 3-1.4 3.3-.2 0-.3 0-.4-.4-.1-.7 0-1.6-.3-2.6-.2-1.1-.8-1.6-1.5-1.5-.8.2-1.3 1-1.6 2l-.1-.5c-.2-1-1.8-.6-1.8-.6a6.2 6.2 0 0 1 .4 1.3l.2 1c-.2.5-.6 1-1.2 1l-.2.1a7 7 0 0 0-.1-.8c-.3-1.1-1-2-1.6-1.8a.7.7 0 0 0-.4.3c-1.3.3-2.4 2-2.1 3.9-.2.9-.6 1.7-1 1.9-.5 0-.8-.5-1.1-1.8l-.1-1.2a4 4 0 0 0 0-1.7c0-.4-.4-.7-.8-.6-.7.2-.9 1.7-.5 3.8-.2 1-.6 2-1.3 2-.4.2-.8-.2-1-1l-.2-3c1.2-.5 2-1 1.8-1.7-.1-.5-.8-.7-.8-.7s0 .7-1 1.2l-.2-1.4c-.1-.6-.4-1-1.7-.6l.4 1 .2 1.5h-1v.8c0 .3.4.3 1 .2 0 1.3 0 2.7.2 3.6.3 1.4 1.2 2 2 1.7 1-.2 1.6-1.3 2-2.3.3 1.2 1 2 1.9 1.7.7-.2 1.2-1.1 1.6-2.2.4.8 1.1 1.1 2 1 1.2-.4 1.7-1.6 1.8-2.8h.2c.6-.2 1-.6 1.3-1 0 .8 0 1.5.2 2.1.1.5.3.7.6.6.5-.1 1-.9 1-.9a4 4 0 0 1-.3-1c-.3-1.3.3-3.6 1-3.7.2 0 .3.2.5.7v.8l.2 1.5v.7c.2.7.7 1.3 1.5 1 1.3-.2 2-2.6 2.1-3.9.3.2.6.2 1 .1-.6-2.2 0-6.1-.3-7.9-.1-.4-1-.5-1.7-.5h-.4zm-21.5 12c.4 0 .7.3 1 1.1.2 1.3-.3 2.6-.9 2.8-.2 0-.7 0-1-1.2v-.4c0-1.3.4-2 1-2.2zm-5.2 1c.3 0 .6.2.6.5.2.6-.3 1.3-1.2 2-.3-1.4.1-2.3.6-2.5zm18-.4c-.5.2-1-.4-1.2-1.2-.2-1 0-2.1.7-2.5v.5c.2.7.6 1.5 1.3 1.9 0 .7-.2 1.2-.7 1.3zm10-1.6c0 .5.4.7 1 .6.8-.2 1-1 .8-1.6 0-.5-.4-1-1-.8-.5.1-1 .9-.8 1.8zm-14.3-5.5c0-.4-.5-.7-1-.5-.8.2-1 1-.9 1.5.2.6.5 1 1 .8.5 0 1.1-1 1-1.8z" fill="#fff" fill-opacity=".6"/>'.$this->addElementToGhost().'</svg>'; + } + + private function addElementToGhost() + { + if (!isset(self::GHOST_ADDONS[date('m-d')])) { + return ''; + } + + return '<path d="'.self::GHOST_ADDONS[date('m-d')].'" fill="#fff" fill-opacity="0.6"></path>'; } } diff --git a/vendor/symfony/debug/FatalErrorHandler/ClassNotFoundFatalErrorHandler.php b/vendor/symfony/debug/FatalErrorHandler/ClassNotFoundFatalErrorHandler.php index 32ba9a09c5777a78a6f98f1a77f67efeec9fd5bb..6ffb83635942c920e70e58c7adc09002a91e9e5e 100644 --- a/vendor/symfony/debug/FatalErrorHandler/ClassNotFoundFatalErrorHandler.php +++ b/vendor/symfony/debug/FatalErrorHandler/ClassNotFoundFatalErrorHandler.php @@ -11,11 +11,11 @@ namespace Symfony\Component\Debug\FatalErrorHandler; -use Symfony\Component\Debug\Exception\ClassNotFoundException; -use Symfony\Component\Debug\Exception\FatalErrorException; -use Symfony\Component\Debug\DebugClassLoader; use Composer\Autoload\ClassLoader as ComposerClassLoader; use Symfony\Component\ClassLoader\ClassLoader as SymfonyClassLoader; +use Symfony\Component\Debug\DebugClassLoader; +use Symfony\Component\Debug\Exception\ClassNotFoundException; +use Symfony\Component\Debug\Exception\FatalErrorException; /** * ErrorHandler for classes that do not exist. @@ -29,20 +29,20 @@ class ClassNotFoundFatalErrorHandler implements FatalErrorHandlerInterface */ public function handleError(array $error, FatalErrorException $exception) { - $messageLen = strlen($error['message']); + $messageLen = \strlen($error['message']); $notFoundSuffix = '\' not found'; - $notFoundSuffixLen = strlen($notFoundSuffix); + $notFoundSuffixLen = \strlen($notFoundSuffix); if ($notFoundSuffixLen > $messageLen) { - return; + return null; } if (0 !== substr_compare($error['message'], $notFoundSuffix, -$notFoundSuffixLen)) { - return; + return null; } - foreach (array('class', 'interface', 'trait') as $typeName) { + foreach (['class', 'interface', 'trait'] as $typeName) { $prefix = ucfirst($typeName).' \''; - $prefixLen = strlen($prefix); + $prefixLen = \strlen($prefix); if (0 !== strpos($error['message'], $prefix)) { continue; } @@ -71,6 +71,8 @@ class ClassNotFoundFatalErrorHandler implements FatalErrorHandlerInterface return new ClassNotFoundException($message, $exception); } + + return null; } /** @@ -83,24 +85,24 @@ class ClassNotFoundFatalErrorHandler implements FatalErrorHandlerInterface * * @return array An array of possible fully qualified class names */ - private function getClassCandidates($class) + private function getClassCandidates(string $class): array { - if (!is_array($functions = spl_autoload_functions())) { - return array(); + if (!\is_array($functions = spl_autoload_functions())) { + return []; } // find Symfony and Composer autoloaders - $classes = array(); + $classes = []; foreach ($functions as $function) { - if (!is_array($function)) { + if (!\is_array($function)) { continue; } // get class loaders wrapped by DebugClassLoader if ($function[0] instanceof DebugClassLoader) { $function = $function[0]->getClassLoader(); - if (!is_array($function)) { + if (!\is_array($function)) { continue; } } @@ -124,20 +126,13 @@ class ClassNotFoundFatalErrorHandler implements FatalErrorHandlerInterface return array_unique($classes); } - /** - * @param string $path - * @param string $class - * @param string $prefix - * - * @return array - */ - private function findClassInPath($path, $class, $prefix) + private function findClassInPath(string $path, string $class, string $prefix): array { - if (!$path = realpath($path.'/'.strtr($prefix, '\\_', '//')) ?: realpath($path.'/'.dirname(strtr($prefix, '\\_', '//'))) ?: realpath($path)) { - return array(); + if (!$path = realpath($path.'/'.strtr($prefix, '\\_', '//')) ?: realpath($path.'/'.\dirname(strtr($prefix, '\\_', '//'))) ?: realpath($path)) { + return []; } - $classes = array(); + $classes = []; $filename = $class.'.php'; foreach (new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($path, \RecursiveDirectoryIterator::SKIP_DOTS), \RecursiveIteratorIterator::LEAVES_ONLY) as $file) { if ($filename == $file->getFileName() && $class = $this->convertFileToClass($path, $file->getPathName(), $prefix)) { @@ -148,18 +143,11 @@ class ClassNotFoundFatalErrorHandler implements FatalErrorHandlerInterface return $classes; } - /** - * @param string $path - * @param string $file - * @param string $prefix - * - * @return string|null - */ - private function convertFileToClass($path, $file, $prefix) + private function convertFileToClass(string $path, string $file, string $prefix): ?string { - $candidates = array( + $candidates = [ // namespaced class - $namespacedClass = str_replace(array($path.DIRECTORY_SEPARATOR, '.php', '/'), array('', '', '\\'), $file), + $namespacedClass = str_replace([$path.\DIRECTORY_SEPARATOR, '.php', '/'], ['', '', '\\'], $file), // namespaced class (with target dir) $prefix.$namespacedClass, // namespaced class (with target dir and separator) @@ -170,7 +158,7 @@ class ClassNotFoundFatalErrorHandler implements FatalErrorHandlerInterface str_replace('\\', '_', $prefix.$namespacedClass), // PEAR class (with target dir and separator) str_replace('\\', '_', $prefix.'\\'.$namespacedClass), - ); + ]; if ($prefix) { $candidates = array_filter($candidates, function ($candidate) use ($prefix) { return 0 === strpos($candidate, $prefix); }); @@ -185,21 +173,22 @@ class ClassNotFoundFatalErrorHandler implements FatalErrorHandlerInterface } } - require_once $file; + try { + require_once $file; + } catch (\Throwable $e) { + return null; + } foreach ($candidates as $candidate) { if ($this->classExists($candidate)) { return $candidate; } } + + return null; } - /** - * @param string $class - * - * @return bool - */ - private function classExists($class) + private function classExists(string $class): bool { return class_exists($class, false) || interface_exists($class, false) || trait_exists($class, false); } diff --git a/vendor/symfony/debug/FatalErrorHandler/UndefinedFunctionFatalErrorHandler.php b/vendor/symfony/debug/FatalErrorHandler/UndefinedFunctionFatalErrorHandler.php index c6f391a79c686fe86a3538ec0b98ddb975b30816..77fc7aa26132996cf95385aafdd824e7c009bd01 100644 --- a/vendor/symfony/debug/FatalErrorHandler/UndefinedFunctionFatalErrorHandler.php +++ b/vendor/symfony/debug/FatalErrorHandler/UndefinedFunctionFatalErrorHandler.php @@ -11,8 +11,8 @@ namespace Symfony\Component\Debug\FatalErrorHandler; -use Symfony\Component\Debug\Exception\UndefinedFunctionException; use Symfony\Component\Debug\Exception\FatalErrorException; +use Symfony\Component\Debug\Exception\UndefinedFunctionException; /** * ErrorHandler for undefined functions. @@ -26,21 +26,21 @@ class UndefinedFunctionFatalErrorHandler implements FatalErrorHandlerInterface */ public function handleError(array $error, FatalErrorException $exception) { - $messageLen = strlen($error['message']); + $messageLen = \strlen($error['message']); $notFoundSuffix = '()'; - $notFoundSuffixLen = strlen($notFoundSuffix); + $notFoundSuffixLen = \strlen($notFoundSuffix); if ($notFoundSuffixLen > $messageLen) { - return; + return null; } if (0 !== substr_compare($error['message'], $notFoundSuffix, -$notFoundSuffixLen)) { - return; + return null; } $prefix = 'Call to undefined function '; - $prefixLen = strlen($prefix); + $prefixLen = \strlen($prefix); if (0 !== strpos($error['message'], $prefix)) { - return; + return null; } $fullyQualifiedFunctionName = substr($error['message'], $prefixLen, -$notFoundSuffixLen); @@ -53,7 +53,7 @@ class UndefinedFunctionFatalErrorHandler implements FatalErrorHandlerInterface $message = sprintf('Attempted to call function "%s" from the global namespace.', $functionName); } - $candidates = array(); + $candidates = []; foreach (get_defined_functions() as $type => $definedFunctionNames) { foreach ($definedFunctionNames as $definedFunctionName) { if (false !== $namespaceSeparatorIndex = strrpos($definedFunctionName, '\\')) { diff --git a/vendor/symfony/debug/FatalErrorHandler/UndefinedMethodFatalErrorHandler.php b/vendor/symfony/debug/FatalErrorHandler/UndefinedMethodFatalErrorHandler.php index 6fa62b6f24fbbf5fdc77da02f0d9e35b0fe440b8..ff2843b6811f2af90b159a1887983912f387f917 100644 --- a/vendor/symfony/debug/FatalErrorHandler/UndefinedMethodFatalErrorHandler.php +++ b/vendor/symfony/debug/FatalErrorHandler/UndefinedMethodFatalErrorHandler.php @@ -28,7 +28,7 @@ class UndefinedMethodFatalErrorHandler implements FatalErrorHandlerInterface { preg_match('/^Call to undefined method (.*)::(.*)\(\)$/', $error['message'], $matches); if (!$matches) { - return; + return null; } $className = $matches[1]; @@ -41,10 +41,10 @@ class UndefinedMethodFatalErrorHandler implements FatalErrorHandlerInterface return new UndefinedMethodException($message, $exception); } - $candidates = array(); + $candidates = []; foreach ($methods as $definedMethodName) { $lev = levenshtein($methodName, $definedMethodName); - if ($lev <= strlen($methodName) / 3 || false !== strpos($definedMethodName, $methodName)) { + if ($lev <= \strlen($methodName) / 3 || false !== strpos($definedMethodName, $methodName)) { $candidates[] = $definedMethodName; } } diff --git a/vendor/symfony/debug/LICENSE b/vendor/symfony/debug/LICENSE index 21d7fb9e2f29b50caca3a76f0647e94e2cc8ddc1..a677f43763ca467472898351b328aee41e2edd7c 100644 --- a/vendor/symfony/debug/LICENSE +++ b/vendor/symfony/debug/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-2018 Fabien Potencier +Copyright (c) 2004-2019 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/vendor/symfony/debug/Resources/ext/README.md b/vendor/symfony/debug/Resources/ext/README.md deleted file mode 100644 index 25dccf07664704efe155f18faea23e28d74b7aac..0000000000000000000000000000000000000000 --- a/vendor/symfony/debug/Resources/ext/README.md +++ /dev/null @@ -1,134 +0,0 @@ -Symfony Debug Extension for PHP 5 -================================= - -This extension publishes several functions to help building powerful debugging tools. -It is compatible with PHP 5.3, 5.4, 5.5 and 5.6; with ZTS and non-ZTS modes. -It is not required thus not provided for PHP 7. - -symfony_zval_info() -------------------- - -- exposes zval_hash/refcounts, allowing e.g. efficient exploration of arbitrary structures in PHP, -- does work with references, preventing memory copying. - -Its behavior is about the same as: - -```php -<?php - -function symfony_zval_info($key, $array, $options = 0) -{ - - // $options is currently not used, but could be in future version. - - if (!array_key_exists($key, $array)) { - return null; - } - - $info = array( - 'type' => gettype($array[$key]), - 'zval_hash' => /* hashed memory address of $array[$key] */, - 'zval_refcount' => /* internal zval refcount of $array[$key] */, - 'zval_isref' => /* is_ref status of $array[$key] */, - ); - - switch ($info['type']) { - case 'object': - $info += array( - 'object_class' => get_class($array[$key]), - 'object_refcount' => /* internal object refcount of $array[$key] */, - 'object_hash' => spl_object_hash($array[$key]), - 'object_handle' => /* internal object handle $array[$key] */, - ); - break; - - case 'resource': - $info += array( - 'resource_handle' => (int) $array[$key], - 'resource_type' => get_resource_type($array[$key]), - 'resource_refcount' => /* internal resource refcount of $array[$key] */, - ); - break; - - case 'array': - $info += array( - 'array_count' => count($array[$key]), - ); - break; - - case 'string': - $info += array( - 'strlen' => strlen($array[$key]), - ); - break; - } - - return $info; -} -``` - -symfony_debug_backtrace() -------------------------- - -This function works like debug_backtrace(), except that it can fetch the full backtrace in case of fatal errors: - -```php -function foo() { fatal(); } -function bar() { foo(); } - -function sd() { var_dump(symfony_debug_backtrace()); } - -register_shutdown_function('sd'); - -bar(); - -/* Will output -Fatal error: Call to undefined function fatal() in foo.php on line 42 -array(3) { - [0]=> - array(2) { - ["function"]=> - string(2) "sd" - ["args"]=> - array(0) { - } - } - [1]=> - array(4) { - ["file"]=> - string(7) "foo.php" - ["line"]=> - int(1) - ["function"]=> - string(3) "foo" - ["args"]=> - array(0) { - } - } - [2]=> - array(4) { - ["file"]=> - string(102) "foo.php" - ["line"]=> - int(2) - ["function"]=> - string(3) "bar" - ["args"]=> - array(0) { - } - } -} -*/ -``` - -Usage ------ - -To enable the extension from source, run: - -``` - phpize - ./configure - make - sudo make install -``` diff --git a/vendor/symfony/debug/Resources/ext/config.m4 b/vendor/symfony/debug/Resources/ext/config.m4 deleted file mode 100644 index 3c56047150569b5ad02799e03f7b7edfbee5d608..0000000000000000000000000000000000000000 --- a/vendor/symfony/debug/Resources/ext/config.m4 +++ /dev/null @@ -1,63 +0,0 @@ -dnl $Id$ -dnl config.m4 for extension symfony_debug - -dnl Comments in this file start with the string 'dnl'. -dnl Remove where necessary. This file will not work -dnl without editing. - -dnl If your extension references something external, use with: - -dnl PHP_ARG_WITH(symfony_debug, for symfony_debug support, -dnl Make sure that the comment is aligned: -dnl [ --with-symfony_debug Include symfony_debug support]) - -dnl Otherwise use enable: - -PHP_ARG_ENABLE(symfony_debug, whether to enable symfony_debug support, -dnl Make sure that the comment is aligned: -[ --enable-symfony_debug Enable symfony_debug support]) - -if test "$PHP_SYMFONY_DEBUG" != "no"; then - dnl Write more examples of tests here... - - dnl # --with-symfony_debug -> check with-path - dnl SEARCH_PATH="/usr/local /usr" # you might want to change this - dnl SEARCH_FOR="/include/symfony_debug.h" # you most likely want to change this - dnl if test -r $PHP_SYMFONY_DEBUG/$SEARCH_FOR; then # path given as parameter - dnl SYMFONY_DEBUG_DIR=$PHP_SYMFONY_DEBUG - dnl else # search default path list - dnl AC_MSG_CHECKING([for symfony_debug files in default path]) - dnl for i in $SEARCH_PATH ; do - dnl if test -r $i/$SEARCH_FOR; then - dnl SYMFONY_DEBUG_DIR=$i - dnl AC_MSG_RESULT(found in $i) - dnl fi - dnl done - dnl fi - dnl - dnl if test -z "$SYMFONY_DEBUG_DIR"; then - dnl AC_MSG_RESULT([not found]) - dnl AC_MSG_ERROR([Please reinstall the symfony_debug distribution]) - dnl fi - - dnl # --with-symfony_debug -> add include path - dnl PHP_ADD_INCLUDE($SYMFONY_DEBUG_DIR/include) - - dnl # --with-symfony_debug -> check for lib and symbol presence - dnl LIBNAME=symfony_debug # you may want to change this - dnl LIBSYMBOL=symfony_debug # you most likely want to change this - - dnl PHP_CHECK_LIBRARY($LIBNAME,$LIBSYMBOL, - dnl [ - dnl PHP_ADD_LIBRARY_WITH_PATH($LIBNAME, $SYMFONY_DEBUG_DIR/lib, SYMFONY_DEBUG_SHARED_LIBADD) - dnl AC_DEFINE(HAVE_SYMFONY_DEBUGLIB,1,[ ]) - dnl ],[ - dnl AC_MSG_ERROR([wrong symfony_debug lib version or lib not found]) - dnl ],[ - dnl -L$SYMFONY_DEBUG_DIR/lib -lm - dnl ]) - dnl - dnl PHP_SUBST(SYMFONY_DEBUG_SHARED_LIBADD) - - PHP_NEW_EXTENSION(symfony_debug, symfony_debug.c, $ext_shared) -fi diff --git a/vendor/symfony/debug/Resources/ext/config.w32 b/vendor/symfony/debug/Resources/ext/config.w32 deleted file mode 100644 index 487e6913891cf07b60f9779b0e3ffd18406c44ff..0000000000000000000000000000000000000000 --- a/vendor/symfony/debug/Resources/ext/config.w32 +++ /dev/null @@ -1,13 +0,0 @@ -// $Id$ -// vim:ft=javascript - -// If your extension references something external, use ARG_WITH -// ARG_WITH("symfony_debug", "for symfony_debug support", "no"); - -// Otherwise, use ARG_ENABLE -// ARG_ENABLE("symfony_debug", "enable symfony_debug support", "no"); - -if (PHP_SYMFONY_DEBUG != "no") { - EXTENSION("symfony_debug", "symfony_debug.c"); -} - diff --git a/vendor/symfony/debug/Resources/ext/php_symfony_debug.h b/vendor/symfony/debug/Resources/ext/php_symfony_debug.h deleted file mode 100644 index 26d0e8c0120300cda3204ed5cefd445a354e7cac..0000000000000000000000000000000000000000 --- a/vendor/symfony/debug/Resources/ext/php_symfony_debug.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -#ifndef PHP_SYMFONY_DEBUG_H -#define PHP_SYMFONY_DEBUG_H - -extern zend_module_entry symfony_debug_module_entry; -#define phpext_symfony_debug_ptr &symfony_debug_module_entry - -#define PHP_SYMFONY_DEBUG_VERSION "2.7" - -#ifdef PHP_WIN32 -# define PHP_SYMFONY_DEBUG_API __declspec(dllexport) -#elif defined(__GNUC__) && __GNUC__ >= 4 -# define PHP_SYMFONY_DEBUG_API __attribute__ ((visibility("default"))) -#else -# define PHP_SYMFONY_DEBUG_API -#endif - -#ifdef ZTS -#include "TSRM.h" -#endif - -ZEND_BEGIN_MODULE_GLOBALS(symfony_debug) - intptr_t req_rand_init; - void (*old_error_cb)(int type, const char *error_filename, const uint error_lineno, const char *format, va_list args); - zval *debug_bt; -ZEND_END_MODULE_GLOBALS(symfony_debug) - -PHP_MINIT_FUNCTION(symfony_debug); -PHP_MSHUTDOWN_FUNCTION(symfony_debug); -PHP_RINIT_FUNCTION(symfony_debug); -PHP_RSHUTDOWN_FUNCTION(symfony_debug); -PHP_MINFO_FUNCTION(symfony_debug); -PHP_GINIT_FUNCTION(symfony_debug); -PHP_GSHUTDOWN_FUNCTION(symfony_debug); - -PHP_FUNCTION(symfony_zval_info); -PHP_FUNCTION(symfony_debug_backtrace); - -static char *_symfony_debug_memory_address_hash(void * TSRMLS_DC); -static const char *_symfony_debug_zval_type(zval *); -static const char* _symfony_debug_get_resource_type(long TSRMLS_DC); -static int _symfony_debug_get_resource_refcount(long TSRMLS_DC); - -void symfony_debug_error_cb(int type, const char *error_filename, const uint error_lineno, const char *format, va_list args); - -#ifdef ZTS -#define SYMFONY_DEBUG_G(v) TSRMG(symfony_debug_globals_id, zend_symfony_debug_globals *, v) -#else -#define SYMFONY_DEBUG_G(v) (symfony_debug_globals.v) -#endif - -#endif /* PHP_SYMFONY_DEBUG_H */ diff --git a/vendor/symfony/debug/Resources/ext/symfony_debug.c b/vendor/symfony/debug/Resources/ext/symfony_debug.c deleted file mode 100644 index 0d7cb602320f93e440ad8f0043bd69f97b1a7863..0000000000000000000000000000000000000000 --- a/vendor/symfony/debug/Resources/ext/symfony_debug.c +++ /dev/null @@ -1,283 +0,0 @@ -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "php.h" -#ifdef ZTS -#include "TSRM.h" -#endif -#include "php_ini.h" -#include "ext/standard/info.h" -#include "php_symfony_debug.h" -#include "ext/standard/php_rand.h" -#include "ext/standard/php_lcg.h" -#include "ext/spl/php_spl.h" -#include "Zend/zend_gc.h" -#include "Zend/zend_builtin_functions.h" -#include "Zend/zend_extensions.h" /* for ZEND_EXTENSION_API_NO */ -#include "ext/standard/php_array.h" -#include "Zend/zend_interfaces.h" -#include "SAPI.h" - -#define IS_PHP_53 ZEND_EXTENSION_API_NO == 220090626 - -ZEND_DECLARE_MODULE_GLOBALS(symfony_debug) - -ZEND_BEGIN_ARG_INFO_EX(symfony_zval_arginfo, 0, 0, 2) - ZEND_ARG_INFO(0, key) - ZEND_ARG_ARRAY_INFO(0, array, 0) - ZEND_ARG_INFO(0, options) -ZEND_END_ARG_INFO() - -const zend_function_entry symfony_debug_functions[] = { - PHP_FE(symfony_zval_info, symfony_zval_arginfo) - PHP_FE(symfony_debug_backtrace, NULL) - PHP_FE_END -}; - -PHP_FUNCTION(symfony_debug_backtrace) -{ - if (zend_parse_parameters_none() == FAILURE) { - return; - } -#if IS_PHP_53 - zend_fetch_debug_backtrace(return_value, 1, 0 TSRMLS_CC); -#else - zend_fetch_debug_backtrace(return_value, 1, 0, 0 TSRMLS_CC); -#endif - - if (!SYMFONY_DEBUG_G(debug_bt)) { - return; - } - - php_array_merge(Z_ARRVAL_P(return_value), Z_ARRVAL_P(SYMFONY_DEBUG_G(debug_bt)), 0 TSRMLS_CC); -} - -PHP_FUNCTION(symfony_zval_info) -{ - zval *key = NULL, *arg = NULL; - zval **data = NULL; - HashTable *array = NULL; - long options = 0; - - if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "zh|l", &key, &array, &options) == FAILURE) { - return; - } - - switch (Z_TYPE_P(key)) { - case IS_STRING: - if (zend_symtable_find(array, Z_STRVAL_P(key), Z_STRLEN_P(key) + 1, (void **)&data) == FAILURE) { - return; - } - break; - case IS_LONG: - if (zend_hash_index_find(array, Z_LVAL_P(key), (void **)&data)) { - return; - } - break; - } - - arg = *data; - - array_init(return_value); - - add_assoc_string(return_value, "type", (char *)_symfony_debug_zval_type(arg), 1); - add_assoc_stringl(return_value, "zval_hash", _symfony_debug_memory_address_hash((void *)arg TSRMLS_CC), 16, 0); - add_assoc_long(return_value, "zval_refcount", Z_REFCOUNT_P(arg)); - add_assoc_bool(return_value, "zval_isref", (zend_bool)Z_ISREF_P(arg)); - - if (Z_TYPE_P(arg) == IS_OBJECT) { - char hash[33] = {0}; - - php_spl_object_hash(arg, (char *)hash TSRMLS_CC); - add_assoc_stringl(return_value, "object_class", (char *)Z_OBJCE_P(arg)->name, Z_OBJCE_P(arg)->name_length, 1); - add_assoc_long(return_value, "object_refcount", EG(objects_store).object_buckets[Z_OBJ_HANDLE_P(arg)].bucket.obj.refcount); - add_assoc_string(return_value, "object_hash", hash, 1); - add_assoc_long(return_value, "object_handle", Z_OBJ_HANDLE_P(arg)); - } else if (Z_TYPE_P(arg) == IS_ARRAY) { - add_assoc_long(return_value, "array_count", zend_hash_num_elements(Z_ARRVAL_P(arg))); - } else if(Z_TYPE_P(arg) == IS_RESOURCE) { - add_assoc_long(return_value, "resource_handle", Z_LVAL_P(arg)); - add_assoc_string(return_value, "resource_type", (char *)_symfony_debug_get_resource_type(Z_LVAL_P(arg) TSRMLS_CC), 1); - add_assoc_long(return_value, "resource_refcount", _symfony_debug_get_resource_refcount(Z_LVAL_P(arg) TSRMLS_CC)); - } else if (Z_TYPE_P(arg) == IS_STRING) { - add_assoc_long(return_value, "strlen", Z_STRLEN_P(arg)); - } -} - -void symfony_debug_error_cb(int type, const char *error_filename, const uint error_lineno, const char *format, va_list args) -{ - TSRMLS_FETCH(); - zval *retval; - - switch (type) { - case E_ERROR: - case E_PARSE: - case E_CORE_ERROR: - case E_CORE_WARNING: - case E_COMPILE_ERROR: - case E_COMPILE_WARNING: - ALLOC_INIT_ZVAL(retval); -#if IS_PHP_53 - zend_fetch_debug_backtrace(retval, 1, 0 TSRMLS_CC); -#else - zend_fetch_debug_backtrace(retval, 1, 0, 0 TSRMLS_CC); -#endif - SYMFONY_DEBUG_G(debug_bt) = retval; - } - - SYMFONY_DEBUG_G(old_error_cb)(type, error_filename, error_lineno, format, args); -} - -static const char* _symfony_debug_get_resource_type(long rsid TSRMLS_DC) -{ - const char *res_type; - res_type = zend_rsrc_list_get_rsrc_type(rsid TSRMLS_CC); - - if (!res_type) { - return "Unknown"; - } - - return res_type; -} - -static int _symfony_debug_get_resource_refcount(long rsid TSRMLS_DC) -{ - zend_rsrc_list_entry *le; - - if (zend_hash_index_find(&EG(regular_list), rsid, (void **) &le)==SUCCESS) { - return le->refcount; - } - - return 0; -} - -static char *_symfony_debug_memory_address_hash(void *address TSRMLS_DC) -{ - char *result = NULL; - intptr_t address_rand; - - if (!SYMFONY_DEBUG_G(req_rand_init)) { - if (!BG(mt_rand_is_seeded)) { - php_mt_srand(GENERATE_SEED() TSRMLS_CC); - } - SYMFONY_DEBUG_G(req_rand_init) = (intptr_t)php_mt_rand(TSRMLS_C); - } - - address_rand = (intptr_t)address ^ SYMFONY_DEBUG_G(req_rand_init); - - spprintf(&result, 17, "%016zx", address_rand); - - return result; -} - -static const char *_symfony_debug_zval_type(zval *zv) -{ - switch (Z_TYPE_P(zv)) { - case IS_NULL: - return "NULL"; - break; - - case IS_BOOL: - return "boolean"; - break; - - case IS_LONG: - return "integer"; - break; - - case IS_DOUBLE: - return "double"; - break; - - case IS_STRING: - return "string"; - break; - - case IS_ARRAY: - return "array"; - break; - - case IS_OBJECT: - return "object"; - - case IS_RESOURCE: - return "resource"; - - default: - return "unknown type"; - } -} - -zend_module_entry symfony_debug_module_entry = { - STANDARD_MODULE_HEADER, - "symfony_debug", - symfony_debug_functions, - PHP_MINIT(symfony_debug), - PHP_MSHUTDOWN(symfony_debug), - PHP_RINIT(symfony_debug), - PHP_RSHUTDOWN(symfony_debug), - PHP_MINFO(symfony_debug), - PHP_SYMFONY_DEBUG_VERSION, - PHP_MODULE_GLOBALS(symfony_debug), - PHP_GINIT(symfony_debug), - PHP_GSHUTDOWN(symfony_debug), - NULL, - STANDARD_MODULE_PROPERTIES_EX -}; - -#ifdef COMPILE_DL_SYMFONY_DEBUG -ZEND_GET_MODULE(symfony_debug) -#endif - -PHP_GINIT_FUNCTION(symfony_debug) -{ - memset(symfony_debug_globals, 0 , sizeof(*symfony_debug_globals)); -} - -PHP_GSHUTDOWN_FUNCTION(symfony_debug) -{ - -} - -PHP_MINIT_FUNCTION(symfony_debug) -{ - SYMFONY_DEBUG_G(old_error_cb) = zend_error_cb; - zend_error_cb = symfony_debug_error_cb; - - return SUCCESS; -} - -PHP_MSHUTDOWN_FUNCTION(symfony_debug) -{ - zend_error_cb = SYMFONY_DEBUG_G(old_error_cb); - - return SUCCESS; -} - -PHP_RINIT_FUNCTION(symfony_debug) -{ - return SUCCESS; -} - -PHP_RSHUTDOWN_FUNCTION(symfony_debug) -{ - return SUCCESS; -} - -PHP_MINFO_FUNCTION(symfony_debug) -{ - php_info_print_table_start(); - php_info_print_table_header(2, "Symfony Debug support", "enabled"); - php_info_print_table_header(2, "Symfony Debug version", PHP_SYMFONY_DEBUG_VERSION); - php_info_print_table_end(); -} diff --git a/vendor/symfony/debug/Resources/ext/tests/001.phpt b/vendor/symfony/debug/Resources/ext/tests/001.phpt deleted file mode 100644 index 4a87cd3180b03ab36b275fc0be9392adc86bed98..0000000000000000000000000000000000000000 --- a/vendor/symfony/debug/Resources/ext/tests/001.phpt +++ /dev/null @@ -1,155 +0,0 @@ ---TEST-- -Test symfony_zval_info API ---SKIPIF-- -<?php if (!extension_loaded('symfony_debug')) { - echo 'skip'; -} ?> ---FILE-- -<?php - -$int = 42; -$float = 42.42; -$str = 'foobar'; -$object = new StdClass(); -$array = array('foo', 'bar'); -$resource = tmpfile(); -$null = null; -$bool = true; - -$anotherint = 42; -$refcount2 = &$anotherint; - -$var = array( - 'int' => $int, - 'float' => $float, - 'str' => $str, - 'object' => $object, - 'array' => $array, - 'resource' => $resource, - 'null' => $null, - 'bool' => $bool, - 'refcount' => &$refcount2, -); - -var_dump(symfony_zval_info('int', $var)); -var_dump(symfony_zval_info('float', $var)); -var_dump(symfony_zval_info('str', $var)); -var_dump(symfony_zval_info('object', $var)); -var_dump(symfony_zval_info('array', $var)); -var_dump(symfony_zval_info('resource', $var)); -var_dump(symfony_zval_info('null', $var)); -var_dump(symfony_zval_info('bool', $var)); - -var_dump(symfony_zval_info('refcount', $var)); -var_dump(symfony_zval_info('not-exist', $var)); -?> ---EXPECTF-- -array(4) { - ["type"]=> - string(7) "integer" - ["zval_hash"]=> - string(16) "%s" - ["zval_refcount"]=> - int(2) - ["zval_isref"]=> - bool(false) -} -array(4) { - ["type"]=> - string(6) "double" - ["zval_hash"]=> - string(16) "%s" - ["zval_refcount"]=> - int(2) - ["zval_isref"]=> - bool(false) -} -array(5) { - ["type"]=> - string(6) "string" - ["zval_hash"]=> - string(16) "%s" - ["zval_refcount"]=> - int(2) - ["zval_isref"]=> - bool(false) - ["strlen"]=> - int(6) -} -array(8) { - ["type"]=> - string(6) "object" - ["zval_hash"]=> - string(16) "%s" - ["zval_refcount"]=> - int(2) - ["zval_isref"]=> - bool(false) - ["object_class"]=> - string(8) "stdClass" - ["object_refcount"]=> - int(1) - ["object_hash"]=> - string(32) "%s" - ["object_handle"]=> - int(%d) -} -array(5) { - ["type"]=> - string(5) "array" - ["zval_hash"]=> - string(16) "%s" - ["zval_refcount"]=> - int(2) - ["zval_isref"]=> - bool(false) - ["array_count"]=> - int(2) -} -array(7) { - ["type"]=> - string(8) "resource" - ["zval_hash"]=> - string(16) "%s" - ["zval_refcount"]=> - int(2) - ["zval_isref"]=> - bool(false) - ["resource_handle"]=> - int(%d) - ["resource_type"]=> - string(6) "stream" - ["resource_refcount"]=> - int(1) -} -array(4) { - ["type"]=> - string(4) "NULL" - ["zval_hash"]=> - string(16) "%s" - ["zval_refcount"]=> - int(2) - ["zval_isref"]=> - bool(false) -} -array(4) { - ["type"]=> - string(7) "boolean" - ["zval_hash"]=> - string(16) "%s" - ["zval_refcount"]=> - int(2) - ["zval_isref"]=> - bool(false) -} -array(4) { - ["type"]=> - string(7) "integer" - ["zval_hash"]=> - string(16) "%s" - ["zval_refcount"]=> - int(3) - ["zval_isref"]=> - bool(true) -} -NULL diff --git a/vendor/symfony/debug/Resources/ext/tests/002.phpt b/vendor/symfony/debug/Resources/ext/tests/002.phpt deleted file mode 100644 index afc7bb49024d960f0ffc65c531b3a6bbed9a60df..0000000000000000000000000000000000000000 --- a/vendor/symfony/debug/Resources/ext/tests/002.phpt +++ /dev/null @@ -1,65 +0,0 @@ ---TEST-- -Test symfony_debug_backtrace in case of fatal error ---SKIPIF-- -<?php if (!extension_loaded('symfony_debug')) { - echo 'skip'; -} ?> ---FILE-- -<?php - -function bar() -{ - foo(); -} - -function foo() -{ - notexist(); -} - -function bt() -{ - print_r(symfony_debug_backtrace()); -} - -register_shutdown_function('bt'); - -bar(); - -?> ---EXPECTF-- -Fatal error: Call to undefined function notexist() in %s on line %d -Array -( - [0] => Array - ( - [function] => bt - [args] => Array - ( - ) - - ) - - [1] => Array - ( - [file] => %s - [line] => %d - [function] => foo - [args] => Array - ( - ) - - ) - - [2] => Array - ( - [file] => %s - [line] => %d - [function] => bar - [args] => Array - ( - ) - - ) - -) diff --git a/vendor/symfony/debug/Resources/ext/tests/002_1.phpt b/vendor/symfony/debug/Resources/ext/tests/002_1.phpt deleted file mode 100644 index 86de3e177d08621f290d1dc21e95d9456f1b2b51..0000000000000000000000000000000000000000 --- a/vendor/symfony/debug/Resources/ext/tests/002_1.phpt +++ /dev/null @@ -1,48 +0,0 @@ ---TEST-- -Test symfony_debug_backtrace in case of non fatal error ---SKIPIF-- -<?php if (!extension_loaded('symfony_debug')) { - echo 'skip'; -} ?> ---FILE-- -<?php - -function bar() -{ - bt(); -} - -function bt() -{ - print_r(symfony_debug_backtrace()); -} - -bar(); - -?> ---EXPECTF-- -Array -( - [0] => Array - ( - [file] => %s - [line] => %d - [function] => bt - [args] => Array - ( - ) - - ) - - [1] => Array - ( - [file] => %s - [line] => %d - [function] => bar - [args] => Array - ( - ) - - ) - -) diff --git a/vendor/symfony/debug/Resources/ext/tests/003.phpt b/vendor/symfony/debug/Resources/ext/tests/003.phpt deleted file mode 100644 index ce3c4e0ab5647fd7c1617418538f7772d460f021..0000000000000000000000000000000000000000 --- a/vendor/symfony/debug/Resources/ext/tests/003.phpt +++ /dev/null @@ -1,87 +0,0 @@ ---TEST-- -Test ErrorHandler in case of fatal error ---SKIPIF-- -<?php if (!extension_loaded('symfony_debug')) { - echo 'skip'; -} ?> ---FILE-- -<?php - -namespace Psr\Log; - -class LogLevel -{ - const EMERGENCY = 'emergency'; - const ALERT = 'alert'; - const CRITICAL = 'critical'; - const ERROR = 'error'; - const WARNING = 'warning'; - const NOTICE = 'notice'; - const INFO = 'info'; - const DEBUG = 'debug'; -} - -namespace Symfony\Component\Debug; - -$dir = __DIR__.'/../../../'; -require $dir.'ErrorHandler.php'; -require $dir.'Exception/FatalErrorException.php'; -require $dir.'Exception/UndefinedFunctionException.php'; -require $dir.'FatalErrorHandler/FatalErrorHandlerInterface.php'; -require $dir.'FatalErrorHandler/ClassNotFoundFatalErrorHandler.php'; -require $dir.'FatalErrorHandler/UndefinedFunctionFatalErrorHandler.php'; -require $dir.'FatalErrorHandler/UndefinedMethodFatalErrorHandler.php'; - -function bar() -{ - foo(); -} - -function foo() -{ - notexist(); -} - -$handler = ErrorHandler::register(); -$handler->setExceptionHandler('print_r'); - -if (function_exists('xdebug_disable')) { - xdebug_disable(); -} - -bar(); -?> ---EXPECTF-- -Fatal error: Call to undefined function Symfony\Component\Debug\notexist() in %s on line %d -Symfony\Component\Debug\Exception\UndefinedFunctionException Object -( - [message:protected] => Attempted to call function "notexist" from namespace "Symfony\Component\Debug". - [string:Exception:private] => - [code:protected] => 0 - [file:protected] => %s - [line:protected] => %d - [trace:Exception:private] => Array - ( - [0] => Array - ( -%A [function] => Symfony\Component\Debug\foo -%A [args] => Array - ( - ) - - ) - - [1] => Array - ( -%A [function] => Symfony\Component\Debug\bar -%A [args] => Array - ( - ) - - ) -%A - ) - - [previous:Exception:private] => - [severity:protected] => 1 -) diff --git a/vendor/symfony/debug/Tests/DebugClassLoaderTest.php b/vendor/symfony/debug/Tests/DebugClassLoaderTest.php index 0219f5335086990e8203c83d0ee8a94907733348..30cf4a3326dbfcc144a709d420b184c4ceb4909f 100644 --- a/vendor/symfony/debug/Tests/DebugClassLoaderTest.php +++ b/vendor/symfony/debug/Tests/DebugClassLoaderTest.php @@ -13,7 +13,6 @@ namespace Symfony\Component\Debug\Tests; use PHPUnit\Framework\TestCase; use Symfony\Component\Debug\DebugClassLoader; -use Symfony\Component\Debug\ErrorHandler; class DebugClassLoaderTest extends TestCase { @@ -24,18 +23,18 @@ class DebugClassLoaderTest extends TestCase private $loader; - protected function setUp() + protected function setUp(): void { $this->errorReporting = error_reporting(E_ALL); $this->loader = new ClassLoader(); - spl_autoload_register(array($this->loader, 'loadClass'), true, true); + spl_autoload_register([$this->loader, 'loadClass'], true, true); DebugClassLoader::enable(); } - protected function tearDown() + protected function tearDown(): void { DebugClassLoader::disable(); - spl_autoload_unregister(array($this->loader, 'loadClass')); + spl_autoload_unregister([$this->loader, 'loadClass']); error_reporting($this->errorReporting); } @@ -45,7 +44,7 @@ class DebugClassLoaderTest extends TestCase $functions = spl_autoload_functions(); foreach ($functions as $function) { - if (is_array($function) && $function[0] instanceof DebugClassLoader) { + if (\is_array($function) && $function[0] instanceof DebugClassLoader) { $reflClass = new \ReflectionClass($function[0]); $reflProp = $reflClass->getProperty('classLoader'); $reflProp->setAccessible(true); @@ -59,12 +58,10 @@ class DebugClassLoaderTest extends TestCase $this->fail('DebugClassLoader did not register'); } - /** - * @expectedException \Exception - * @expectedExceptionMessage boo - */ public function testThrowingClass() { + $this->expectException('Exception'); + $this->expectExceptionMessage('boo'); try { class_exists(__NAMESPACE__.'\Fixtures\Throwing'); $this->fail('Exception expected'); @@ -76,84 +73,17 @@ class DebugClassLoaderTest extends TestCase class_exists(__NAMESPACE__.'\Fixtures\Throwing'); } - public function testUnsilencing() - { - if (\PHP_VERSION_ID >= 70000) { - $this->markTestSkipped('PHP7 throws exceptions, unsilencing is not required anymore.'); - } - if (defined('HHVM_VERSION')) { - $this->markTestSkipped('HHVM is not handled in this test case.'); - } - - ob_start(); - - $this->iniSet('log_errors', 0); - $this->iniSet('display_errors', 1); - - // See below: this will fail with parse error - // but this should not be @-silenced. - @class_exists(__NAMESPACE__.'\TestingUnsilencing', true); - - $output = ob_get_clean(); - - $this->assertStringMatchesFormat('%aParse error%a', $output); - } - - public function testStacking() - { - // the ContextErrorException must not be loaded to test the workaround - // for https://bugs.php.net/65322. - if (class_exists('Symfony\Component\Debug\Exception\ContextErrorException', false)) { - $this->markTestSkipped('The ContextErrorException class is already loaded.'); - } - if (defined('HHVM_VERSION')) { - $this->markTestSkipped('HHVM is not handled in this test case.'); - } - - ErrorHandler::register(); - - try { - // Trigger autoloading + E_STRICT at compile time - // which in turn triggers $errorHandler->handle() - // that again triggers autoloading for ContextErrorException. - // Error stacking works around the bug above and everything is fine. - - eval(' - namespace '.__NAMESPACE__.'; - class ChildTestingStacking extends TestingStacking { function foo($bar) {} } - '); - $this->fail('ContextErrorException expected'); - } catch (\ErrorException $exception) { - // if an exception is thrown, the test passed - $this->assertStringStartsWith(__FILE__, $exception->getFile()); - if (\PHP_VERSION_ID < 70000) { - $this->assertRegExp('/^Runtime Notice: Declaration/', $exception->getMessage()); - $this->assertEquals(E_STRICT, $exception->getSeverity()); - } else { - $this->assertRegExp('/^Warning: Declaration/', $exception->getMessage()); - $this->assertEquals(E_WARNING, $exception->getSeverity()); - } - } finally { - restore_error_handler(); - restore_exception_handler(); - } - } - - /** - * @expectedException \RuntimeException - * @expectedExceptionMessage Case mismatch between loaded and declared class names - */ public function testNameCaseMismatch() { + $this->expectException('RuntimeException'); + $this->expectExceptionMessage('Case mismatch between loaded and declared class names'); class_exists(__NAMESPACE__.'\TestingCaseMismatch', true); } - /** - * @expectedException \RuntimeException - * @expectedExceptionMessage Case mismatch between class and real file names - */ public function testFileCaseMismatch() { + $this->expectException('RuntimeException'); + $this->expectExceptionMessage('Case mismatch between class and real file names'); if (!file_exists(__DIR__.'/Fixtures/CaseMismatch.php')) { $this->markTestSkipped('Can only be run on case insensitive filesystems'); } @@ -161,12 +91,10 @@ class DebugClassLoaderTest extends TestCase class_exists(__NAMESPACE__.'\Fixtures\CaseMismatch', true); } - /** - * @expectedException \RuntimeException - * @expectedExceptionMessage Case mismatch between loaded and declared class names - */ public function testPsr4CaseMismatch() { + $this->expectException('RuntimeException'); + $this->expectExceptionMessage('Case mismatch between loaded and declared class names'); class_exists(__NAMESPACE__.'\Fixtures\Psr4CaseMismatch', true); } @@ -202,20 +130,20 @@ class DebugClassLoaderTest extends TestCase $lastError = error_get_last(); unset($lastError['file'], $lastError['line']); - $xError = array( + $xError = [ 'type' => E_USER_DEPRECATED, 'message' => 'The "Test\Symfony\Component\Debug\Tests\\'.$class.'" class '.$type.' "Symfony\Component\Debug\Tests\Fixtures\\'.$super.'" that is deprecated but this is a test deprecation notice.', - ); + ]; $this->assertSame($xError, $lastError); } public function provideDeprecatedSuper() { - return array( - array('DeprecatedInterfaceClass', 'DeprecatedInterface', 'implements'), - array('DeprecatedParentClass', 'DeprecatedClass', 'extends'), - ); + return [ + ['DeprecatedInterfaceClass', 'DeprecatedInterface', 'implements'], + ['DeprecatedParentClass', 'DeprecatedClass', 'extends'], + ]; } public function testInterfaceExtendsDeprecatedInterface() @@ -232,10 +160,10 @@ class DebugClassLoaderTest extends TestCase $lastError = error_get_last(); unset($lastError['file'], $lastError['line']); - $xError = array( + $xError = [ 'type' => E_USER_NOTICE, 'message' => '', - ); + ]; $this->assertSame($xError, $lastError); } @@ -254,47 +182,69 @@ class DebugClassLoaderTest extends TestCase $lastError = error_get_last(); unset($lastError['file'], $lastError['line']); - $xError = array( + $xError = [ 'type' => E_USER_NOTICE, 'message' => '', - ); + ]; $this->assertSame($xError, $lastError); } - public function testReservedForPhp7() + public function testExtendedFinalClass() { - if (\PHP_VERSION_ID >= 70000) { - $this->markTestSkipped('PHP7 already prevents using reserved names.'); - } + $deprecations = []; + set_error_handler(function ($type, $msg) use (&$deprecations) { $deprecations[] = $msg; }); + $e = error_reporting(E_USER_DEPRECATED); - set_error_handler(function () { return false; }); - $e = error_reporting(0); - trigger_error('', E_USER_NOTICE); + require __DIR__.'/Fixtures/FinalClasses.php'; - class_exists('Test\\'.__NAMESPACE__.'\\Float', true); + $i = 1; + while (class_exists($finalClass = __NAMESPACE__.'\\Fixtures\\FinalClass'.$i++, false)) { + spl_autoload_call($finalClass); + class_exists('Test\\'.__NAMESPACE__.'\\Extends'.substr($finalClass, strrpos($finalClass, '\\') + 1), true); + } error_reporting($e); restore_error_handler(); - $lastError = error_get_last(); - unset($lastError['file'], $lastError['line']); + $this->assertSame([ + 'The "Symfony\Component\Debug\Tests\Fixtures\FinalClass1" class is considered final since version 3.3. It may change without further notice as of its next major version. You should not extend it from "Test\Symfony\Component\Debug\Tests\ExtendsFinalClass1".', + 'The "Symfony\Component\Debug\Tests\Fixtures\FinalClass2" class is considered final. It may change without further notice as of its next major version. You should not extend it from "Test\Symfony\Component\Debug\Tests\ExtendsFinalClass2".', + 'The "Symfony\Component\Debug\Tests\Fixtures\FinalClass3" class is considered final comment with @@@ and ***. It may change without further notice as of its next major version. You should not extend it from "Test\Symfony\Component\Debug\Tests\ExtendsFinalClass3".', + 'The "Symfony\Component\Debug\Tests\Fixtures\FinalClass4" class is considered final. It may change without further notice as of its next major version. You should not extend it from "Test\Symfony\Component\Debug\Tests\ExtendsFinalClass4".', + 'The "Symfony\Component\Debug\Tests\Fixtures\FinalClass5" class is considered final multiline comment. It may change without further notice as of its next major version. You should not extend it from "Test\Symfony\Component\Debug\Tests\ExtendsFinalClass5".', + 'The "Symfony\Component\Debug\Tests\Fixtures\FinalClass6" class is considered final. It may change without further notice as of its next major version. You should not extend it from "Test\Symfony\Component\Debug\Tests\ExtendsFinalClass6".', + 'The "Symfony\Component\Debug\Tests\Fixtures\FinalClass7" class is considered final another multiline comment... It may change without further notice as of its next major version. You should not extend it from "Test\Symfony\Component\Debug\Tests\ExtendsFinalClass7".', + 'The "Symfony\Component\Debug\Tests\Fixtures\FinalClass8" class is considered final. It may change without further notice as of its next major version. You should not extend it from "Test\Symfony\Component\Debug\Tests\ExtendsFinalClass8".', + ], $deprecations); + } - $xError = array( - 'type' => E_USER_DEPRECATED, - 'message' => 'The "Test\Symfony\Component\Debug\Tests\Float" class uses the reserved name "Float", it will break on PHP 7 and higher', - ); + public function testExtendedFinalMethod() + { + $deprecations = []; + set_error_handler(function ($type, $msg) use (&$deprecations) { $deprecations[] = $msg; }); + $e = error_reporting(E_USER_DEPRECATED); - $this->assertSame($xError, $lastError); + class_exists(__NAMESPACE__.'\\Fixtures\\ExtendedFinalMethod', true); + + error_reporting($e); + restore_error_handler(); + + $xError = [ + 'The "Symfony\Component\Debug\Tests\Fixtures\FinalMethod::finalMethod()" method is considered final. It may change without further notice as of its next major version. You should not extend it from "Symfony\Component\Debug\Tests\Fixtures\ExtendedFinalMethod".', + 'The "Symfony\Component\Debug\Tests\Fixtures\FinalMethod::finalMethod2()" method is considered final. It may change without further notice as of its next major version. You should not extend it from "Symfony\Component\Debug\Tests\Fixtures\ExtendedFinalMethod".', + ]; + + $this->assertSame($xError, $deprecations); } - public function testExtendedFinalClass() + public function testExtendedDeprecatedMethodDoesntTriggerAnyNotice() { set_error_handler(function () { return false; }); $e = error_reporting(0); trigger_error('', E_USER_NOTICE); - class_exists('Test\\'.__NAMESPACE__.'\\ExtendsFinalClass', true); + class_exists('Test\\'.__NAMESPACE__.'\\ExtendsAnnotatedClass', true); error_reporting($e); restore_error_handler(); @@ -302,70 +252,108 @@ class DebugClassLoaderTest extends TestCase $lastError = error_get_last(); unset($lastError['file'], $lastError['line']); - $xError = array( - 'type' => E_USER_DEPRECATED, - 'message' => 'The "Symfony\Component\Debug\Tests\Fixtures\FinalClass" class is considered final since version 3.3. It may change without further notice as of its next major version. You should not extend it from "Test\Symfony\Component\Debug\Tests\ExtendsFinalClass".', - ); - - $this->assertSame($xError, $lastError); + $this->assertSame(['type' => E_USER_NOTICE, 'message' => ''], $lastError); } - public function testExtendedFinalMethod() + public function testInternalsUse() { - set_error_handler(function () { return false; }); - $e = error_reporting(0); - trigger_error('', E_USER_NOTICE); + $deprecations = []; + set_error_handler(function ($type, $msg) use (&$deprecations) { $deprecations[] = $msg; }); + $e = error_reporting(E_USER_DEPRECATED); - class_exists(__NAMESPACE__.'\\Fixtures\\ExtendedFinalMethod', true); + class_exists('Test\\'.__NAMESPACE__.'\\ExtendsInternals', true); error_reporting($e); restore_error_handler(); - $lastError = error_get_last(); - unset($lastError['file'], $lastError['line']); + $this->assertSame($deprecations, [ + 'The "Symfony\Component\Debug\Tests\Fixtures\InternalInterface" interface is considered internal. It may change without further notice. You should not use it from "Test\Symfony\Component\Debug\Tests\ExtendsInternalsParent".', + 'The "Symfony\Component\Debug\Tests\Fixtures\InternalClass" class is considered internal. It may change without further notice. You should not use it from "Test\Symfony\Component\Debug\Tests\ExtendsInternalsParent".', + 'The "Symfony\Component\Debug\Tests\Fixtures\InternalTrait" trait is considered internal. It may change without further notice. You should not use it from "Test\Symfony\Component\Debug\Tests\ExtendsInternals".', + 'The "Symfony\Component\Debug\Tests\Fixtures\InternalClass::internalMethod()" method is considered internal. It may change without further notice. You should not extend it from "Test\Symfony\Component\Debug\Tests\ExtendsInternals".', + ]); + } - $xError = array( - 'type' => E_USER_DEPRECATED, - 'message' => 'The "Symfony\Component\Debug\Tests\Fixtures\FinalMethod::finalMethod()" method is considered final since version 3.3. It may change without further notice as of its next major version. You should not extend it from "Symfony\Component\Debug\Tests\Fixtures\ExtendedFinalMethod".', - ); + public function testExtendedMethodDefinesNewParameters() + { + $deprecations = []; + set_error_handler(function ($type, $msg) use (&$deprecations) { $deprecations[] = $msg; }); + $e = error_reporting(E_USER_DEPRECATED); - $this->assertSame($xError, $lastError); + class_exists(__NAMESPACE__.'\\Fixtures\SubClassWithAnnotatedParameters', true); + + error_reporting($e); + restore_error_handler(); + + $this->assertSame([ + 'The "Symfony\Component\Debug\Tests\Fixtures\SubClassWithAnnotatedParameters::quzMethod()" method will require a new "Quz $quz" argument in the next major version of its parent class "Symfony\Component\Debug\Tests\Fixtures\ClassWithAnnotatedParameters", not defining it is deprecated.', + 'The "Symfony\Component\Debug\Tests\Fixtures\SubClassWithAnnotatedParameters::whereAmI()" method will require a new "bool $matrix" argument in the next major version of its parent class "Symfony\Component\Debug\Tests\Fixtures\InterfaceWithAnnotatedParameters", not defining it is deprecated.', + 'The "Symfony\Component\Debug\Tests\Fixtures\SubClassWithAnnotatedParameters::iAmHere()" method will require a new "$noType" argument in the next major version of its parent class "Symfony\Component\Debug\Tests\Fixtures\InterfaceWithAnnotatedParameters", not defining it is deprecated.', + 'The "Symfony\Component\Debug\Tests\Fixtures\SubClassWithAnnotatedParameters::iAmHere()" method will require a new "callable(\Throwable|null $reason, mixed $value) $callback" argument in the next major version of its parent class "Symfony\Component\Debug\Tests\Fixtures\InterfaceWithAnnotatedParameters", not defining it is deprecated.', + 'The "Symfony\Component\Debug\Tests\Fixtures\SubClassWithAnnotatedParameters::iAmHere()" method will require a new "string $param" argument in the next major version of its parent class "Symfony\Component\Debug\Tests\Fixtures\InterfaceWithAnnotatedParameters", not defining it is deprecated.', + 'The "Symfony\Component\Debug\Tests\Fixtures\SubClassWithAnnotatedParameters::iAmHere()" method will require a new "callable ($a, $b) $anotherOne" argument in the next major version of its parent class "Symfony\Component\Debug\Tests\Fixtures\InterfaceWithAnnotatedParameters", not defining it is deprecated.', + 'The "Symfony\Component\Debug\Tests\Fixtures\SubClassWithAnnotatedParameters::iAmHere()" method will require a new "Type$WithDollarIsStillAType $ccc" argument in the next major version of its parent class "Symfony\Component\Debug\Tests\Fixtures\InterfaceWithAnnotatedParameters", not defining it is deprecated.', + 'The "Symfony\Component\Debug\Tests\Fixtures\SubClassWithAnnotatedParameters::isSymfony()" method will require a new "true $yes" argument in the next major version of its parent class "Symfony\Component\Debug\Tests\Fixtures\ClassWithAnnotatedParameters", not defining it is deprecated.', + ], $deprecations); } - public function testExtendedDeprecatedMethodDoesntTriggerAnyNotice() + public function testUseTraitWithInternalMethod() { - set_error_handler(function () { return false; }); - $e = error_reporting(0); - trigger_error('', E_USER_NOTICE); + $deprecations = []; + set_error_handler(function ($type, $msg) use (&$deprecations) { $deprecations[] = $msg; }); + $e = error_reporting(E_USER_DEPRECATED); - class_exists('Test\\'.__NAMESPACE__.'\\ExtendsAnnotatedClass', true); + class_exists('Test\\'.__NAMESPACE__.'\\UseTraitWithInternalMethod', true); error_reporting($e); restore_error_handler(); - $lastError = error_get_last(); - unset($lastError['file'], $lastError['line']); + $this->assertSame([], $deprecations); + } + + public function testVirtualUse() + { + $deprecations = []; + set_error_handler(function ($type, $msg) use (&$deprecations) { $deprecations[] = $msg; }); + $e = error_reporting(E_USER_DEPRECATED); + + class_exists('Test\\'.__NAMESPACE__.'\\ExtendsVirtual', true); + + error_reporting($e); + restore_error_handler(); - $this->assertSame(array('type' => E_USER_NOTICE, 'message' => ''), $lastError); + $this->assertSame([ + 'Class "Test\Symfony\Component\Debug\Tests\ExtendsVirtualParent" should implement method "Symfony\Component\Debug\Tests\Fixtures\VirtualInterface::sameLineInterfaceMethodNoBraces()".', + 'Class "Test\Symfony\Component\Debug\Tests\ExtendsVirtualParent" should implement method "Symfony\Component\Debug\Tests\Fixtures\VirtualInterface::newLineInterfaceMethod()": Some description!', + 'Class "Test\Symfony\Component\Debug\Tests\ExtendsVirtualParent" should implement method "Symfony\Component\Debug\Tests\Fixtures\VirtualInterface::newLineInterfaceMethodNoBraces()": Description.', + 'Class "Test\Symfony\Component\Debug\Tests\ExtendsVirtualParent" should implement method "Symfony\Component\Debug\Tests\Fixtures\VirtualInterface::invalidInterfaceMethod()".', + 'Class "Test\Symfony\Component\Debug\Tests\ExtendsVirtualParent" should implement method "Symfony\Component\Debug\Tests\Fixtures\VirtualInterface::invalidInterfaceMethodNoBraces()".', + 'Class "Test\Symfony\Component\Debug\Tests\ExtendsVirtualParent" should implement method "Symfony\Component\Debug\Tests\Fixtures\VirtualInterface::complexInterfaceMethod($arg, ...$args)".', + 'Class "Test\Symfony\Component\Debug\Tests\ExtendsVirtualParent" should implement method "Symfony\Component\Debug\Tests\Fixtures\VirtualInterface::complexInterfaceMethodTyped($arg, int ...$args)": Description ...', + 'Class "Test\Symfony\Component\Debug\Tests\ExtendsVirtualParent" should implement method "static Symfony\Component\Debug\Tests\Fixtures\VirtualInterface::staticMethodNoBraces()".', + 'Class "Test\Symfony\Component\Debug\Tests\ExtendsVirtualParent" should implement method "static Symfony\Component\Debug\Tests\Fixtures\VirtualInterface::staticMethodTyped(int $arg)": Description.', + 'Class "Test\Symfony\Component\Debug\Tests\ExtendsVirtualParent" should implement method "static Symfony\Component\Debug\Tests\Fixtures\VirtualInterface::staticMethodTypedNoBraces()".', + 'Class "Test\Symfony\Component\Debug\Tests\ExtendsVirtual" should implement method "Symfony\Component\Debug\Tests\Fixtures\VirtualSubInterface::subInterfaceMethod()".', + ], $deprecations); } - public function testInternalsUse() + public function testVirtualUseWithMagicCall() { - $deprecations = array(); + $deprecations = []; set_error_handler(function ($type, $msg) use (&$deprecations) { $deprecations[] = $msg; }); $e = error_reporting(E_USER_DEPRECATED); - class_exists('Test\\'.__NAMESPACE__.'\\ExtendsInternals', true); + class_exists('Test\\'.__NAMESPACE__.'\\ExtendsVirtualMagicCall', true); error_reporting($e); restore_error_handler(); - $this->assertSame($deprecations, array( - 'The "Symfony\Component\Debug\Tests\Fixtures\InternalClass" class is considered internal since version 3.4. It may change without further notice. You should not use it from "Test\Symfony\Component\Debug\Tests\ExtendsInternalsParent".', - 'The "Symfony\Component\Debug\Tests\Fixtures\InternalInterface" interface is considered internal. It may change without further notice. You should not use it from "Test\Symfony\Component\Debug\Tests\ExtendsInternalsParent".', - 'The "Symfony\Component\Debug\Tests\Fixtures\InternalTrait" trait is considered internal. It may change without further notice. You should not use it from "Test\Symfony\Component\Debug\Tests\ExtendsInternals".', - 'The "Symfony\Component\Debug\Tests\Fixtures\InternalTrait2::internalMethod()" method is considered internal since version 3.4. It may change without further notice. You should not extend it from "Test\Symfony\Component\Debug\Tests\ExtendsInternals".', - )); + $this->assertSame([], $deprecations); + } + + public function testEvaluatedCode() + { + $this->assertTrue(class_exists(__NAMESPACE__.'\Fixtures\DefinitionInEvaluatedCode', true)); } } @@ -377,12 +365,12 @@ class ClassLoader public function getClassMap() { - return array(__NAMESPACE__.'\Fixtures\NotPSR0bis' => __DIR__.'/Fixtures/notPsr0Bis.php'); + return [__NAMESPACE__.'\Fixtures\NotPSR0bis' => __DIR__.'/Fixtures/notPsr0Bis.php']; } public function findFile($class) { - $fixtureDir = __DIR__.DIRECTORY_SEPARATOR.'Fixtures'.DIRECTORY_SEPARATOR; + $fixtureDir = __DIR__.\DIRECTORY_SEPARATOR.'Fixtures'.\DIRECTORY_SEPARATOR; if (__NAMESPACE__.'\TestingUnsilencing' === $class) { eval('-- parse error --'); @@ -391,7 +379,7 @@ class ClassLoader } elseif (__NAMESPACE__.'\TestingCaseMismatch' === $class) { eval('namespace '.__NAMESPACE__.'; class TestingCaseMisMatch {}'); } elseif (__NAMESPACE__.'\Fixtures\Psr4CaseMismatch' === $class) { - return $fixtureDir.'psr4'.DIRECTORY_SEPARATOR.'Psr4CaseMismatch.php'; + return $fixtureDir.'psr4'.\DIRECTORY_SEPARATOR.'Psr4CaseMismatch.php'; } elseif (__NAMESPACE__.'\Fixtures\NotPSR0' === $class) { return $fixtureDir.'reallyNotPsr0.php'; } elseif (__NAMESPACE__.'\Fixtures\NotPSR0bis' === $class) { @@ -406,8 +394,9 @@ class ClassLoader eval('namespace Test\\'.__NAMESPACE__.'; class NonDeprecatedInterfaceClass implements \\'.__NAMESPACE__.'\Fixtures\NonDeprecatedInterface {}'); } elseif ('Test\\'.__NAMESPACE__.'\Float' === $class) { eval('namespace Test\\'.__NAMESPACE__.'; class Float {}'); - } elseif ('Test\\'.__NAMESPACE__.'\ExtendsFinalClass' === $class) { - eval('namespace Test\\'.__NAMESPACE__.'; class ExtendsFinalClass extends \\'.__NAMESPACE__.'\Fixtures\FinalClass {}'); + } elseif (0 === strpos($class, 'Test\\'.__NAMESPACE__.'\ExtendsFinalClass')) { + $classShortName = substr($class, strrpos($class, '\\') + 1); + eval('namespace Test\\'.__NAMESPACE__.'; class '.$classShortName.' extends \\'.__NAMESPACE__.'\Fixtures\\'.substr($classShortName, 7).' {}'); } elseif ('Test\\'.__NAMESPACE__.'\ExtendsAnnotatedClass' === $class) { eval('namespace Test\\'.__NAMESPACE__.'; class ExtendsAnnotatedClass extends \\'.__NAMESPACE__.'\Fixtures\AnnotatedClass { public function deprecatedMethod() { } @@ -420,6 +409,36 @@ class ClassLoader }'); } elseif ('Test\\'.__NAMESPACE__.'\ExtendsInternalsParent' === $class) { eval('namespace Test\\'.__NAMESPACE__.'; class ExtendsInternalsParent extends \\'.__NAMESPACE__.'\Fixtures\InternalClass implements \\'.__NAMESPACE__.'\Fixtures\InternalInterface { }'); + } elseif ('Test\\'.__NAMESPACE__.'\UseTraitWithInternalMethod' === $class) { + eval('namespace Test\\'.__NAMESPACE__.'; class UseTraitWithInternalMethod { use \\'.__NAMESPACE__.'\Fixtures\TraitWithInternalMethod; }'); + } elseif ('Test\\'.__NAMESPACE__.'\ExtendsVirtual' === $class) { + eval('namespace Test\\'.__NAMESPACE__.'; class ExtendsVirtual extends ExtendsVirtualParent implements \\'.__NAMESPACE__.'\Fixtures\VirtualSubInterface { + public function ownClassMethod() { } + public function classMethod() { } + public function sameLineInterfaceMethodNoBraces() { } + }'); + } elseif ('Test\\'.__NAMESPACE__.'\ExtendsVirtualParent' === $class) { + eval('namespace Test\\'.__NAMESPACE__.'; class ExtendsVirtualParent extends ExtendsVirtualAbstract { + public function ownParentMethod() { } + public function traitMethod() { } + public function sameLineInterfaceMethod() { } + public function staticMethodNoBraces() { } // should be static + }'); + } elseif ('Test\\'.__NAMESPACE__.'\ExtendsVirtualAbstract' === $class) { + eval('namespace Test\\'.__NAMESPACE__.'; abstract class ExtendsVirtualAbstract extends ExtendsVirtualAbstractBase { + public static function staticMethod() { } + public function ownAbstractMethod() { } + public function interfaceMethod() { } + }'); + } elseif ('Test\\'.__NAMESPACE__.'\ExtendsVirtualAbstractBase' === $class) { + eval('namespace Test\\'.__NAMESPACE__.'; abstract class ExtendsVirtualAbstractBase extends \\'.__NAMESPACE__.'\Fixtures\VirtualClass implements \\'.__NAMESPACE__.'\Fixtures\VirtualInterface { + public function ownAbstractBaseMethod() { } + }'); + } elseif ('Test\\'.__NAMESPACE__.'\ExtendsVirtualMagicCall' === $class) { + eval('namespace Test\\'.__NAMESPACE__.'; class ExtendsVirtualMagicCall extends \\'.__NAMESPACE__.'\Fixtures\VirtualClassMagicCall implements \\'.__NAMESPACE__.'\Fixtures\VirtualInterface { + }'); } + + return null; } } diff --git a/vendor/symfony/debug/Tests/ErrorHandlerTest.php b/vendor/symfony/debug/Tests/ErrorHandlerTest.php index a57e83ee442b61a8c29a77c28756a9822c7c40ba..54e656b3f81033b5bddffa376ca4ea41481b847a 100644 --- a/vendor/symfony/debug/Tests/ErrorHandlerTest.php +++ b/vendor/symfony/debug/Tests/ErrorHandlerTest.php @@ -13,9 +13,12 @@ namespace Symfony\Component\Debug\Tests; use PHPUnit\Framework\TestCase; use Psr\Log\LogLevel; +use Psr\Log\NullLogger; use Symfony\Component\Debug\BufferingLogger; use Symfony\Component\Debug\ErrorHandler; use Symfony\Component\Debug\Exception\SilencedErrorContext; +use Symfony\Component\Debug\Tests\Fixtures\ErrorHandlerThatUsesThePreviousOne; +use Symfony\Component\Debug\Tests\Fixtures\LoggerThatSetAnErrorHandler; /** * ErrorHandlerTest. @@ -35,16 +38,16 @@ class ErrorHandlerTest extends TestCase $newHandler = new ErrorHandler(); - $this->assertSame($newHandler, ErrorHandler::register($newHandler, false)); + $this->assertSame($handler, ErrorHandler::register($newHandler, false)); $h = set_error_handler('var_dump'); restore_error_handler(); - $this->assertSame(array($handler, 'handleError'), $h); + $this->assertSame([$handler, 'handleError'], $h); try { $this->assertSame($newHandler, ErrorHandler::register($newHandler, true)); $h = set_error_handler('var_dump'); restore_error_handler(); - $this->assertSame(array($newHandler, 'handleError'), $h); + $this->assertSame([$newHandler, 'handleError'], $h); } catch (\Exception $e) { } @@ -65,6 +68,30 @@ class ErrorHandlerTest extends TestCase } } + public function testErrorGetLast() + { + $logger = $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock(); + $handler = ErrorHandler::register(); + $handler->setDefaultLogger($logger); + $handler->screamAt(E_ALL); + + try { + @trigger_error('Hello', E_USER_WARNING); + $expected = [ + 'type' => E_USER_WARNING, + 'message' => 'Hello', + 'file' => __FILE__, + 'line' => __LINE__ - 5, + ]; + $this->assertSame($expected, error_get_last()); + } catch (\Exception $e) { + restore_error_handler(); + restore_exception_handler(); + + throw $e; + } + } + public function testNotice() { ErrorHandler::register(); @@ -116,31 +143,30 @@ class ErrorHandlerTest extends TestCase public function testDefaultLogger() { try { - $handler = ErrorHandler::register(); - $logger = $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock(); + $handler = ErrorHandler::register(); $handler->setDefaultLogger($logger, E_NOTICE); - $handler->setDefaultLogger($logger, array(E_USER_NOTICE => LogLevel::CRITICAL)); - - $loggers = array( - E_DEPRECATED => array(null, LogLevel::INFO), - E_USER_DEPRECATED => array(null, LogLevel::INFO), - E_NOTICE => array($logger, LogLevel::WARNING), - E_USER_NOTICE => array($logger, LogLevel::CRITICAL), - E_STRICT => array(null, LogLevel::WARNING), - E_WARNING => array(null, LogLevel::WARNING), - E_USER_WARNING => array(null, LogLevel::WARNING), - E_COMPILE_WARNING => array(null, LogLevel::WARNING), - E_CORE_WARNING => array(null, LogLevel::WARNING), - E_USER_ERROR => array(null, LogLevel::CRITICAL), - E_RECOVERABLE_ERROR => array(null, LogLevel::CRITICAL), - E_COMPILE_ERROR => array(null, LogLevel::CRITICAL), - E_PARSE => array(null, LogLevel::CRITICAL), - E_ERROR => array(null, LogLevel::CRITICAL), - E_CORE_ERROR => array(null, LogLevel::CRITICAL), - ); - $this->assertSame($loggers, $handler->setLoggers(array())); + $handler->setDefaultLogger($logger, [E_USER_NOTICE => LogLevel::CRITICAL]); + + $loggers = [ + E_DEPRECATED => [null, LogLevel::INFO], + E_USER_DEPRECATED => [null, LogLevel::INFO], + E_NOTICE => [$logger, LogLevel::WARNING], + E_USER_NOTICE => [$logger, LogLevel::CRITICAL], + E_STRICT => [null, LogLevel::WARNING], + E_WARNING => [null, LogLevel::WARNING], + E_USER_WARNING => [null, LogLevel::WARNING], + E_COMPILE_WARNING => [null, LogLevel::WARNING], + E_CORE_WARNING => [null, LogLevel::WARNING], + E_USER_ERROR => [null, LogLevel::CRITICAL], + E_RECOVERABLE_ERROR => [null, LogLevel::CRITICAL], + E_COMPILE_ERROR => [null, LogLevel::CRITICAL], + E_PARSE => [null, LogLevel::CRITICAL], + E_ERROR => [null, LogLevel::CRITICAL], + E_CORE_ERROR => [null, LogLevel::CRITICAL], + ]; + $this->assertSame($loggers, $handler->setLoggers([])); } finally { restore_error_handler(); restore_exception_handler(); @@ -152,14 +178,14 @@ class ErrorHandlerTest extends TestCase try { $handler = ErrorHandler::register(); $handler->throwAt(0, true); - $this->assertFalse($handler->handleError(0, 'foo', 'foo.php', 12, array())); + $this->assertFalse($handler->handleError(0, 'foo', 'foo.php', 12, [])); restore_error_handler(); restore_exception_handler(); $handler = ErrorHandler::register(); $handler->throwAt(3, true); - $this->assertFalse($handler->handleError(4, 'foo', 'foo.php', 12, array())); + $this->assertFalse($handler->handleError(4, 'foo', 'foo.php', 12, [])); restore_error_handler(); restore_exception_handler(); @@ -167,7 +193,7 @@ class ErrorHandlerTest extends TestCase $handler = ErrorHandler::register(); $handler->throwAt(3, true); try { - $handler->handleError(4, 'foo', 'foo.php', 12, array()); + $handler->handleError(4, 'foo', 'foo.php', 12, []); } catch (\ErrorException $e) { $this->assertSame('Parse Error: foo', $e->getMessage()); $this->assertSame(4, $e->getSeverity()); @@ -180,14 +206,14 @@ class ErrorHandlerTest extends TestCase $handler = ErrorHandler::register(); $handler->throwAt(E_USER_DEPRECATED, true); - $this->assertFalse($handler->handleError(E_USER_DEPRECATED, 'foo', 'foo.php', 12, array())); + $this->assertFalse($handler->handleError(E_USER_DEPRECATED, 'foo', 'foo.php', 12, [])); restore_error_handler(); restore_exception_handler(); $handler = ErrorHandler::register(); $handler->throwAt(E_DEPRECATED, true); - $this->assertFalse($handler->handleError(E_DEPRECATED, 'foo', 'foo.php', 12, array())); + $this->assertFalse($handler->handleError(E_DEPRECATED, 'foo', 'foo.php', 12, [])); restore_error_handler(); restore_exception_handler(); @@ -207,12 +233,12 @@ class ErrorHandlerTest extends TestCase $logger ->expects($this->once()) ->method('log') - ->will($this->returnCallback($warnArgCheck)) + ->willReturnCallback($warnArgCheck) ; $handler = ErrorHandler::register(); $handler->setDefaultLogger($logger, E_USER_DEPRECATED); - $this->assertTrue($handler->handleError(E_USER_DEPRECATED, 'foo', 'foo.php', 12, array())); + $this->assertTrue($handler->handleError(E_USER_DEPRECATED, 'foo', 'foo.php', 12, [])); restore_error_handler(); restore_exception_handler(); @@ -235,7 +261,7 @@ class ErrorHandlerTest extends TestCase $logger ->expects($this->once()) ->method('log') - ->will($this->returnCallback($logArgCheck)) + ->willReturnCallback($logArgCheck) ; $handler = ErrorHandler::register(); @@ -257,6 +283,10 @@ class ErrorHandlerTest extends TestCase public function testHandleUserError() { + if (\PHP_VERSION_ID >= 70400) { + $this->markTestSkipped('PHP 7.4 allows __toString to throw exceptions'); + } + try { $handler = ErrorHandler::register(); $handler->throwAt(0, true); @@ -291,26 +321,24 @@ class ErrorHandlerTest extends TestCase $logger ->expects($this->once()) ->method('log') - ->will($this->returnCallback($logArgCheck)) + ->willReturnCallback($logArgCheck) ; $handler = new ErrorHandler(); $handler->setDefaultLogger($logger); - @$handler->handleError(E_USER_DEPRECATED, 'Foo deprecation', __FILE__, __LINE__, array()); + @$handler->handleError(E_USER_DEPRECATED, 'Foo deprecation', __FILE__, __LINE__, []); + + restore_error_handler(); } - /** - * @group no-hhvm - */ public function testHandleException() { try { + $logger = $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock(); $handler = ErrorHandler::register(); $exception = new \Exception('foo'); - $logger = $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock(); - $logArgCheck = function ($level, $message, $context) { $this->assertSame('Uncaught Exception: foo', $message); $this->assertArrayHasKey('exception', $context); @@ -320,7 +348,7 @@ class ErrorHandlerTest extends TestCase $logger ->expects($this->exactly(2)) ->method('log') - ->will($this->returnCallback($logArgCheck)) + ->willReturnCallback($logArgCheck) ; $handler->setDefaultLogger($logger, E_ERROR); @@ -343,64 +371,32 @@ class ErrorHandlerTest extends TestCase } } - /** - * @group legacy - */ - public function testErrorStacking() - { - try { - $handler = ErrorHandler::register(); - $handler->screamAt(E_USER_WARNING); - - $logger = $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock(); - - $logger - ->expects($this->exactly(2)) - ->method('log') - ->withConsecutive( - array($this->equalTo(LogLevel::WARNING), $this->equalTo('Dummy log')), - array($this->equalTo(LogLevel::DEBUG), $this->equalTo('User Warning: Silenced warning')) - ) - ; - - $handler->setDefaultLogger($logger, array(E_USER_WARNING => LogLevel::WARNING)); - - ErrorHandler::stackErrors(); - @trigger_error('Silenced warning', E_USER_WARNING); - $logger->log(LogLevel::WARNING, 'Dummy log'); - ErrorHandler::unstackErrors(); - } finally { - restore_error_handler(); - restore_exception_handler(); - } - } - public function testBootstrappingLogger() { $bootLogger = new BufferingLogger(); $handler = new ErrorHandler($bootLogger); - $loggers = array( - E_DEPRECATED => array($bootLogger, LogLevel::INFO), - E_USER_DEPRECATED => array($bootLogger, LogLevel::INFO), - E_NOTICE => array($bootLogger, LogLevel::WARNING), - E_USER_NOTICE => array($bootLogger, LogLevel::WARNING), - E_STRICT => array($bootLogger, LogLevel::WARNING), - E_WARNING => array($bootLogger, LogLevel::WARNING), - E_USER_WARNING => array($bootLogger, LogLevel::WARNING), - E_COMPILE_WARNING => array($bootLogger, LogLevel::WARNING), - E_CORE_WARNING => array($bootLogger, LogLevel::WARNING), - E_USER_ERROR => array($bootLogger, LogLevel::CRITICAL), - E_RECOVERABLE_ERROR => array($bootLogger, LogLevel::CRITICAL), - E_COMPILE_ERROR => array($bootLogger, LogLevel::CRITICAL), - E_PARSE => array($bootLogger, LogLevel::CRITICAL), - E_ERROR => array($bootLogger, LogLevel::CRITICAL), - E_CORE_ERROR => array($bootLogger, LogLevel::CRITICAL), - ); - - $this->assertSame($loggers, $handler->setLoggers(array())); - - $handler->handleError(E_DEPRECATED, 'Foo message', __FILE__, 123, array()); + $loggers = [ + E_DEPRECATED => [$bootLogger, LogLevel::INFO], + E_USER_DEPRECATED => [$bootLogger, LogLevel::INFO], + E_NOTICE => [$bootLogger, LogLevel::WARNING], + E_USER_NOTICE => [$bootLogger, LogLevel::WARNING], + E_STRICT => [$bootLogger, LogLevel::WARNING], + E_WARNING => [$bootLogger, LogLevel::WARNING], + E_USER_WARNING => [$bootLogger, LogLevel::WARNING], + E_COMPILE_WARNING => [$bootLogger, LogLevel::WARNING], + E_CORE_WARNING => [$bootLogger, LogLevel::WARNING], + E_USER_ERROR => [$bootLogger, LogLevel::CRITICAL], + E_RECOVERABLE_ERROR => [$bootLogger, LogLevel::CRITICAL], + E_COMPILE_ERROR => [$bootLogger, LogLevel::CRITICAL], + E_PARSE => [$bootLogger, LogLevel::CRITICAL], + E_ERROR => [$bootLogger, LogLevel::CRITICAL], + E_CORE_ERROR => [$bootLogger, LogLevel::CRITICAL], + ]; + + $this->assertSame($loggers, $handler->setLoggers([])); + + $handler->handleError(E_DEPRECATED, 'Foo message', __FILE__, 123, []); $logs = $bootLogger->cleanLogs(); @@ -416,19 +412,16 @@ class ErrorHandlerTest extends TestCase $this->assertSame(123, $exception->getLine()); $this->assertSame(E_DEPRECATED, $exception->getSeverity()); - $bootLogger->log(LogLevel::WARNING, 'Foo message', array('exception' => $exception)); + $bootLogger->log(LogLevel::WARNING, 'Foo message', ['exception' => $exception]); $mockLogger = $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock(); $mockLogger->expects($this->once()) ->method('log') - ->with(LogLevel::WARNING, 'Foo message', array('exception' => $exception)); + ->with(LogLevel::WARNING, 'Foo message', ['exception' => $exception]); - $handler->setLoggers(array(E_DEPRECATED => array($mockLogger, LogLevel::WARNING))); + $handler->setLoggers([E_DEPRECATED => [$mockLogger, LogLevel::WARNING]]); } - /** - * @group no-hhvm - */ public function testSettingLoggerWhenExceptionIsBuffered() { $bootLogger = new BufferingLogger(); @@ -439,7 +432,7 @@ class ErrorHandlerTest extends TestCase $mockLogger = $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock(); $mockLogger->expects($this->once()) ->method('log') - ->with(LogLevel::CRITICAL, 'Uncaught Exception: Foo message', array('exception' => $exception)); + ->with(LogLevel::CRITICAL, 'Uncaught Exception: Foo message', ['exception' => $exception]); $handler->setExceptionHandler(function () use ($handler, $mockLogger) { $handler->setDefaultLogger($mockLogger); @@ -448,22 +441,18 @@ class ErrorHandlerTest extends TestCase $handler->handleException($exception); } - /** - * @group no-hhvm - */ public function testHandleFatalError() { try { + $logger = $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock(); $handler = ErrorHandler::register(); - $error = array( + $error = [ 'type' => E_PARSE, 'message' => 'foo', 'file' => 'bar', 'line' => 123, - ); - - $logger = $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock(); + ]; $logArgCheck = function ($level, $message, $context) { $this->assertEquals('Fatal Parse Error: foo', $message); @@ -474,7 +463,7 @@ class ErrorHandlerTest extends TestCase $logger ->expects($this->once()) ->method('log') - ->will($this->returnCallback($logArgCheck)) + ->willReturnCallback($logArgCheck) ; $handler->setDefaultLogger($logger, E_PARSE); @@ -491,58 +480,83 @@ class ErrorHandlerTest extends TestCase } } - /** - * @requires PHP 7 - */ public function testHandleErrorException() { - $exception = new \Error("Class 'Foo' not found"); + $exception = new \Error("Class 'IReallyReallyDoNotExistAnywhereInTheRepositoryISwear' not found"); $handler = new ErrorHandler(); $handler->setExceptionHandler(function () use (&$args) { - $args = func_get_args(); + $args = \func_get_args(); }); $handler->handleException($exception); $this->assertInstanceOf('Symfony\Component\Debug\Exception\ClassNotFoundException', $args[0]); - $this->assertStringStartsWith("Attempted to load class \"Foo\" from the global namespace.\nDid you forget a \"use\" statement", $args[0]->getMessage()); + $this->assertStringStartsWith("Attempted to load class \"IReallyReallyDoNotExistAnywhereInTheRepositoryISwear\" from the global namespace.\nDid you forget a \"use\" statement", $args[0]->getMessage()); + } + + public function testCustomExceptionHandler() + { + $this->expectException('Exception'); + $handler = new ErrorHandler(); + $handler->setExceptionHandler(function ($e) use ($handler) { + $handler->handleException($e); + }); + + $handler->handleException(new \Exception()); } /** - * @group no-hhvm + * @dataProvider errorHandlerWhenLoggingProvider */ - public function testHandleFatalErrorOnHHVM() + public function testErrorHandlerWhenLogging($previousHandlerWasDefined, $loggerSetsAnotherHandler, $nextHandlerIsDefined) { try { + if ($previousHandlerWasDefined) { + set_error_handler('count'); + } + + $logger = $loggerSetsAnotherHandler ? new LoggerThatSetAnErrorHandler() : new NullLogger(); + $handler = ErrorHandler::register(); + $handler->setDefaultLogger($logger); - $logger = $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock(); - $logger - ->expects($this->once()) - ->method('log') - ->with( - $this->equalTo(LogLevel::CRITICAL), - $this->equalTo('Fatal Error: foo') - ) - ; + if ($nextHandlerIsDefined) { + $handler = ErrorHandlerThatUsesThePreviousOne::register(); + } - $handler->setDefaultLogger($logger, E_ERROR); + @trigger_error('foo', E_USER_DEPRECATED); + @trigger_error('bar', E_USER_DEPRECATED); - $error = array( - 'type' => E_ERROR + 0x1000000, // This error level is used by HHVM for fatal errors - 'message' => 'foo', - 'file' => 'bar', - 'line' => 123, - 'context' => array(123), - 'backtrace' => array(456), - ); + $this->assertSame([$handler, 'handleError'], set_error_handler('var_dump')); - call_user_func_array(array($handler, 'handleError'), $error); - $handler->handleFatalError($error); + if ($logger instanceof LoggerThatSetAnErrorHandler) { + $this->assertCount(2, $logger->cleanLogs()); + } + + restore_error_handler(); + + if ($previousHandlerWasDefined) { + restore_error_handler(); + } + + if ($nextHandlerIsDefined) { + restore_error_handler(); + } } finally { restore_error_handler(); restore_exception_handler(); } } + + public function errorHandlerWhenLoggingProvider() + { + foreach ([false, true] as $previousHandlerWasDefined) { + foreach ([false, true] as $loggerSetsAnotherHandler) { + foreach ([false, true] as $nextHandlerIsDefined) { + yield [$previousHandlerWasDefined, $loggerSetsAnotherHandler, $nextHandlerIsDefined]; + } + } + } + } } diff --git a/vendor/symfony/debug/Tests/Exception/FlattenExceptionTest.php b/vendor/symfony/debug/Tests/Exception/FlattenExceptionTest.php index 8fd1c79594d38c9492e361260943715495bbc79c..994a5efca15459a12ee4ba135bcc2363c0b38705 100644 --- a/vendor/symfony/debug/Tests/Exception/FlattenExceptionTest.php +++ b/vendor/symfony/debug/Tests/Exception/FlattenExceptionTest.php @@ -12,21 +12,22 @@ namespace Symfony\Component\Debug\Tests\Exception; use PHPUnit\Framework\TestCase; +use Symfony\Component\Debug\Exception\FatalThrowableError; use Symfony\Component\Debug\Exception\FlattenException; use Symfony\Component\HttpFoundation\Exception\SuspiciousOperationException; -use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; -use Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException; -use Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException; +use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException; use Symfony\Component\HttpKernel\Exception\BadRequestHttpException; -use Symfony\Component\HttpKernel\Exception\NotAcceptableHttpException; use Symfony\Component\HttpKernel\Exception\ConflictHttpException; -use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException; use Symfony\Component\HttpKernel\Exception\GoneHttpException; use Symfony\Component\HttpKernel\Exception\LengthRequiredHttpException; +use Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException; +use Symfony\Component\HttpKernel\Exception\NotAcceptableHttpException; +use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; use Symfony\Component\HttpKernel\Exception\PreconditionFailedHttpException; use Symfony\Component\HttpKernel\Exception\PreconditionRequiredHttpException; use Symfony\Component\HttpKernel\Exception\ServiceUnavailableHttpException; use Symfony\Component\HttpKernel\Exception\TooManyRequestsHttpException; +use Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException; use Symfony\Component\HttpKernel\Exception\UnsupportedMediaTypeHttpException; class FlattenExceptionTest extends TestCase @@ -39,6 +40,12 @@ class FlattenExceptionTest extends TestCase $flattened = FlattenException::create(new \RuntimeException()); $this->assertEquals('500', $flattened->getStatusCode()); + $flattened = FlattenException::createFromThrowable(new \DivisionByZeroError(), 403); + $this->assertEquals('403', $flattened->getStatusCode()); + + $flattened = FlattenException::createFromThrowable(new \DivisionByZeroError()); + $this->assertEquals('500', $flattened->getStatusCode()); + $flattened = FlattenException::create(new NotFoundHttpException()); $this->assertEquals('404', $flattened->getStatusCode()); @@ -54,7 +61,7 @@ class FlattenExceptionTest extends TestCase $flattened = FlattenException::create(new ConflictHttpException()); $this->assertEquals('409', $flattened->getStatusCode()); - $flattened = FlattenException::create(new MethodNotAllowedHttpException(array('POST'))); + $flattened = FlattenException::create(new MethodNotAllowedHttpException(['POST'])); $this->assertEquals('405', $flattened->getStatusCode()); $flattened = FlattenException::create(new AccessDeniedHttpException()); @@ -89,32 +96,32 @@ class FlattenExceptionTest extends TestCase public function testHeadersForHttpException() { - $flattened = FlattenException::create(new MethodNotAllowedHttpException(array('POST'))); - $this->assertEquals(array('Allow' => 'POST'), $flattened->getHeaders()); + $flattened = FlattenException::create(new MethodNotAllowedHttpException(['POST'])); + $this->assertEquals(['Allow' => 'POST'], $flattened->getHeaders()); $flattened = FlattenException::create(new UnauthorizedHttpException('Basic realm="My Realm"')); - $this->assertEquals(array('WWW-Authenticate' => 'Basic realm="My Realm"'), $flattened->getHeaders()); + $this->assertEquals(['WWW-Authenticate' => 'Basic realm="My Realm"'], $flattened->getHeaders()); $flattened = FlattenException::create(new ServiceUnavailableHttpException('Fri, 31 Dec 1999 23:59:59 GMT')); - $this->assertEquals(array('Retry-After' => 'Fri, 31 Dec 1999 23:59:59 GMT'), $flattened->getHeaders()); + $this->assertEquals(['Retry-After' => 'Fri, 31 Dec 1999 23:59:59 GMT'], $flattened->getHeaders()); $flattened = FlattenException::create(new ServiceUnavailableHttpException(120)); - $this->assertEquals(array('Retry-After' => 120), $flattened->getHeaders()); + $this->assertEquals(['Retry-After' => 120], $flattened->getHeaders()); $flattened = FlattenException::create(new TooManyRequestsHttpException('Fri, 31 Dec 1999 23:59:59 GMT')); - $this->assertEquals(array('Retry-After' => 'Fri, 31 Dec 1999 23:59:59 GMT'), $flattened->getHeaders()); + $this->assertEquals(['Retry-After' => 'Fri, 31 Dec 1999 23:59:59 GMT'], $flattened->getHeaders()); $flattened = FlattenException::create(new TooManyRequestsHttpException(120)); - $this->assertEquals(array('Retry-After' => 120), $flattened->getHeaders()); + $this->assertEquals(['Retry-After' => 120], $flattened->getHeaders()); } /** * @dataProvider flattenDataProvider */ - public function testFlattenHttpException(\Exception $exception, $statusCode) + public function testFlattenHttpException(\Throwable $exception) { - $flattened = FlattenException::create($exception); - $flattened2 = FlattenException::create($exception); + $flattened = FlattenException::createFromThrowable($exception); + $flattened2 = FlattenException::createFromThrowable($exception); $flattened->setPrevious($flattened2); @@ -123,78 +130,109 @@ class FlattenExceptionTest extends TestCase $this->assertInstanceOf($flattened->getClass(), $exception, 'The class is set to the class of the original exception'); } + public function testWrappedThrowable() + { + $exception = new FatalThrowableError(new \DivisionByZeroError('Ouch', 42)); + $flattened = FlattenException::create($exception); + + $this->assertSame('Ouch', $flattened->getMessage(), 'The message is copied from the original error.'); + $this->assertSame(42, $flattened->getCode(), 'The code is copied from the original error.'); + $this->assertSame('DivisionByZeroError', $flattened->getClass(), 'The class is set to the class of the original error'); + } + + public function testThrowable() + { + $error = new \DivisionByZeroError('Ouch', 42); + $flattened = FlattenException::createFromThrowable($error); + + $this->assertSame('Ouch', $flattened->getMessage(), 'The message is copied from the original error.'); + $this->assertSame(42, $flattened->getCode(), 'The code is copied from the original error.'); + $this->assertSame('DivisionByZeroError', $flattened->getClass(), 'The class is set to the class of the original error'); + } + /** * @dataProvider flattenDataProvider */ - public function testPrevious(\Exception $exception, $statusCode) + public function testPrevious(\Throwable $exception) { - $flattened = FlattenException::create($exception); - $flattened2 = FlattenException::create($exception); + $flattened = FlattenException::createFromThrowable($exception); + $flattened2 = FlattenException::createFromThrowable($exception); $flattened->setPrevious($flattened2); $this->assertSame($flattened2, $flattened->getPrevious()); - $this->assertSame(array($flattened2), $flattened->getAllPrevious()); + $this->assertSame([$flattened2], $flattened->getAllPrevious()); } - /** - * @requires PHP 7.0 - */ public function testPreviousError() { $exception = new \Exception('test', 123, new \ParseError('Oh noes!', 42)); $flattened = FlattenException::create($exception)->getPrevious(); - $this->assertEquals($flattened->getMessage(), 'Parse error: Oh noes!', 'The message is copied from the original exception.'); + $this->assertEquals($flattened->getMessage(), 'Oh noes!', 'The message is copied from the original exception.'); $this->assertEquals($flattened->getCode(), 42, 'The code is copied from the original exception.'); - $this->assertEquals($flattened->getClass(), 'Symfony\Component\Debug\Exception\FatalThrowableError', 'The class is set to the class of the original exception'); + $this->assertEquals($flattened->getClass(), 'ParseError', 'The class is set to the class of the original exception'); } /** * @dataProvider flattenDataProvider */ - public function testLine(\Exception $exception) + public function testLine(\Throwable $exception) { - $flattened = FlattenException::create($exception); + $flattened = FlattenException::createFromThrowable($exception); $this->assertSame($exception->getLine(), $flattened->getLine()); } /** * @dataProvider flattenDataProvider */ - public function testFile(\Exception $exception) + public function testFile(\Throwable $exception) { - $flattened = FlattenException::create($exception); + $flattened = FlattenException::createFromThrowable($exception); $this->assertSame($exception->getFile(), $flattened->getFile()); } /** * @dataProvider flattenDataProvider */ - public function testToArray(\Exception $exception, $statusCode) + public function testToArray(\Throwable $exception, string $expectedClass) { - $flattened = FlattenException::create($exception); - $flattened->setTrace(array(), 'foo.php', 123); + $flattened = FlattenException::createFromThrowable($exception); + $flattened->setTrace([], 'foo.php', 123); - $this->assertEquals(array( - array( + $this->assertEquals([ + [ 'message' => 'test', - 'class' => 'Exception', - 'trace' => array(array( + 'class' => $expectedClass, + 'trace' => [[ 'namespace' => '', 'short_class' => '', 'class' => '', 'type' => '', 'function' => '', 'file' => 'foo.php', 'line' => 123, - 'args' => array(), - )), - ), - ), $flattened->toArray()); + 'args' => [], + ]], + ], + ], $flattened->toArray()); } - public function flattenDataProvider() + public function testCreate() { - return array( - array(new \Exception('test', 123), 500), + $exception = new NotFoundHttpException( + 'test', + new \RuntimeException('previous', 123) ); + + $this->assertSame( + FlattenException::createFromThrowable($exception)->toArray(), + FlattenException::create($exception)->toArray() + ); + } + + public function flattenDataProvider() + { + return [ + [new \Exception('test', 123), 'Exception'], + [new \Error('test', 123), 'Error'], + ]; } public function testArguments() @@ -204,15 +242,15 @@ class FlattenExceptionTest extends TestCase $incomplete = unserialize('O:14:"BogusTestClass":0:{}'); - $exception = $this->createException(array( - (object) array('foo' => 1), + $exception = $this->createException([ + (object) ['foo' => 1], new NotFoundHttpException(), $incomplete, $dh, $fh, function () {}, - array(1, 2), - array('foo' => 123), + [1, 2], + ['foo' => 123], null, true, false, @@ -222,7 +260,7 @@ class FlattenExceptionTest extends TestCase '', INF, NAN, - )); + ]); $flattened = FlattenException::create($exception); $trace = $flattened->getTrace(); @@ -233,46 +271,46 @@ class FlattenExceptionTest extends TestCase fclose($fh); $i = 0; - $this->assertSame(array('object', 'stdClass'), $array[$i++]); - $this->assertSame(array('object', 'Symfony\Component\HttpKernel\Exception\NotFoundHttpException'), $array[$i++]); - $this->assertSame(array('incomplete-object', 'BogusTestClass'), $array[$i++]); - $this->assertSame(array('resource', defined('HHVM_VERSION') ? 'Directory' : 'stream'), $array[$i++]); - $this->assertSame(array('resource', 'stream'), $array[$i++]); + $this->assertSame(['object', 'stdClass'], $array[$i++]); + $this->assertSame(['object', 'Symfony\Component\HttpKernel\Exception\NotFoundHttpException'], $array[$i++]); + $this->assertSame(['incomplete-object', 'BogusTestClass'], $array[$i++]); + $this->assertSame(['resource', 'stream'], $array[$i++]); + $this->assertSame(['resource', 'stream'], $array[$i++]); $args = $array[$i++]; $this->assertSame($args[0], 'object'); $this->assertTrue('Closure' === $args[1] || is_subclass_of($args[1], '\Closure'), 'Expect object class name to be Closure or a subclass of Closure.'); - $this->assertSame(array('array', array(array('integer', 1), array('integer', 2))), $array[$i++]); - $this->assertSame(array('array', array('foo' => array('integer', 123))), $array[$i++]); - $this->assertSame(array('null', null), $array[$i++]); - $this->assertSame(array('boolean', true), $array[$i++]); - $this->assertSame(array('boolean', false), $array[$i++]); - $this->assertSame(array('integer', 0), $array[$i++]); - $this->assertSame(array('float', 0.0), $array[$i++]); - $this->assertSame(array('string', '0'), $array[$i++]); - $this->assertSame(array('string', ''), $array[$i++]); - $this->assertSame(array('float', INF), $array[$i++]); + $this->assertSame(['array', [['integer', 1], ['integer', 2]]], $array[$i++]); + $this->assertSame(['array', ['foo' => ['integer', 123]]], $array[$i++]); + $this->assertSame(['null', null], $array[$i++]); + $this->assertSame(['boolean', true], $array[$i++]); + $this->assertSame(['boolean', false], $array[$i++]); + $this->assertSame(['integer', 0], $array[$i++]); + $this->assertSame(['float', 0.0], $array[$i++]); + $this->assertSame(['string', '0'], $array[$i++]); + $this->assertSame(['string', ''], $array[$i++]); + $this->assertSame(['float', INF], $array[$i++]); // assertEquals() does not like NAN values. $this->assertEquals($array[$i][0], 'float'); - $this->assertTrue(is_nan($array[$i++][1])); + $this->assertNan($array[$i++][1]); } public function testRecursionInArguments() { $a = null; - $a = array('foo', array(2, &$a)); + $a = ['foo', [2, &$a]]; $exception = $this->createException($a); $flattened = FlattenException::create($exception); $trace = $flattened->getTrace(); - $this->assertContains('*DEEP NESTED ARRAY*', serialize($trace)); + $this->assertStringContainsString('*DEEP NESTED ARRAY*', serialize($trace)); } public function testTooBigArray() { - $a = array(); + $a = []; for ($i = 0; $i < 20; ++$i) { for ($j = 0; $j < 50; ++$j) { for ($k = 0; $k < 10; ++$k) { @@ -287,12 +325,60 @@ class FlattenExceptionTest extends TestCase $flattened = FlattenException::create($exception); $trace = $flattened->getTrace(); - $this->assertSame($trace[1]['args'][0], array('array', array('array', '*SKIPPED over 10000 entries*'))); + $this->assertSame($trace[1]['args'][0], ['array', ['array', '*SKIPPED over 10000 entries*']]); $serializeTrace = serialize($trace); - $this->assertContains('*SKIPPED over 10000 entries*', $serializeTrace); - $this->assertNotContains('*value1*', $serializeTrace); + $this->assertStringContainsString('*SKIPPED over 10000 entries*', $serializeTrace); + $this->assertStringNotContainsString('*value1*', $serializeTrace); + } + + public function testAnonymousClass() + { + $flattened = FlattenException::create(new class() extends \RuntimeException { + }); + + $this->assertSame('RuntimeException@anonymous', $flattened->getClass()); + + $flattened = FlattenException::create(new \Exception(sprintf('Class "%s" blah.', \get_class(new class() extends \RuntimeException { + })))); + + $this->assertSame('Class "RuntimeException@anonymous" blah.', $flattened->getMessage()); + } + + public function testToStringEmptyMessage() + { + $exception = new \RuntimeException(); + + $flattened = FlattenException::create($exception); + + $this->assertSame($exception->getTraceAsString(), $flattened->getTraceAsString()); + $this->assertSame($exception->__toString(), $flattened->getAsString()); + } + + public function testToString() + { + $test = function ($a, $b, $c, $d) { + return new \RuntimeException('This is a test message'); + }; + + $exception = $test('foo123', 1, null, 1.5); + + $flattened = FlattenException::create($exception); + + $this->assertSame($exception->getTraceAsString(), $flattened->getTraceAsString()); + $this->assertSame($exception->__toString(), $flattened->getAsString()); + } + + public function testToStringParent() + { + $exception = new \LogicException('This is message 1'); + $exception = new \RuntimeException('This is messsage 2', 500, $exception); + + $flattened = FlattenException::create($exception); + + $this->assertSame($exception->getTraceAsString(), $flattened->getTraceAsString()); + $this->assertSame($exception->__toString(), $flattened->getAsString()); } private function createException($foo) diff --git a/vendor/symfony/debug/Tests/ExceptionHandlerTest.php b/vendor/symfony/debug/Tests/ExceptionHandlerTest.php index 0285eff1346cbad9f95d5f1f84f364b01b1c1d09..ab6da5fb5ed5ac4fdb84933f1242fa9dfe7ca2a4 100644 --- a/vendor/symfony/debug/Tests/ExceptionHandlerTest.php +++ b/vendor/symfony/debug/Tests/ExceptionHandlerTest.php @@ -12,21 +12,21 @@ namespace Symfony\Component\Debug\Tests; use PHPUnit\Framework\TestCase; -use Symfony\Component\Debug\ExceptionHandler; use Symfony\Component\Debug\Exception\OutOfMemoryException; -use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; +use Symfony\Component\Debug\ExceptionHandler; use Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException; +use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; require_once __DIR__.'/HeaderMock.php'; class ExceptionHandlerTest extends TestCase { - protected function setUp() + protected function setUp(): void { testHeader(); } - protected function tearDown() + protected function tearDown(): void { testHeader(); } @@ -39,8 +39,8 @@ class ExceptionHandlerTest extends TestCase $handler->sendPhpResponse(new \RuntimeException('Foo')); $response = ob_get_clean(); - $this->assertContains('Whoops, looks like something went wrong.', $response); - $this->assertNotContains('<div class="trace trace-as-html">', $response); + $this->assertStringContainsString('Whoops, looks like something went wrong.', $response); + $this->assertStringNotContainsString('<div class="trace trace-as-html">', $response); $handler = new ExceptionHandler(true); @@ -48,8 +48,17 @@ class ExceptionHandlerTest extends TestCase $handler->sendPhpResponse(new \RuntimeException('Foo')); $response = ob_get_clean(); - $this->assertContains('Whoops, looks like something went wrong.', $response); - $this->assertContains('<div class="trace trace-as-html">', $response); + $this->assertStringContainsString('<h1 class="break-long-words exception-message">Foo</h1>', $response); + $this->assertStringContainsString('<div class="trace trace-as-html">', $response); + + // taken from https://www.owasp.org/index.php/Cross-site_Scripting_(XSS) + $htmlWithXss = '<body onload=alert(\'test1\')> <b onmouseover=alert(\'Wufff!\')>click me!</b> <img src="jAvascript:alert(\'test2\')"> <meta http-equiv="refresh" +content="0;url=data:text/html;base64,PHNjcmlwdD5hbGVydCgndGVzdDMnKTwvc2NyaXB0Pg">'; + ob_start(); + $handler->sendPhpResponse(new \RuntimeException($htmlWithXss)); + $response = ob_get_clean(); + + $this->assertStringContainsString(sprintf('<h1 class="break-long-words exception-message">%s</h1>', htmlspecialchars($htmlWithXss, ENT_COMPAT | ENT_SUBSTITUTE, 'UTF-8')), $response); } public function testStatusCode() @@ -60,12 +69,12 @@ class ExceptionHandlerTest extends TestCase $handler->sendPhpResponse(new NotFoundHttpException('Foo')); $response = ob_get_clean(); - $this->assertContains('Sorry, the page you are looking for could not be found.', $response); + $this->assertStringContainsString('Sorry, the page you are looking for could not be found.', $response); - $expectedHeaders = array( - array('HTTP/1.0 404', true, null), - array('Content-Type: text/html; charset=iso8859-1', true, null), - ); + $expectedHeaders = [ + ['HTTP/1.0 404', true, null], + ['Content-Type: text/html; charset=iso8859-1', true, null], + ]; $this->assertSame($expectedHeaders, testHeader()); } @@ -75,14 +84,14 @@ class ExceptionHandlerTest extends TestCase $handler = new ExceptionHandler(false, 'iso8859-1'); ob_start(); - $handler->sendPhpResponse(new MethodNotAllowedHttpException(array('POST'))); - $response = ob_get_clean(); + $handler->sendPhpResponse(new MethodNotAllowedHttpException(['POST'])); + ob_get_clean(); - $expectedHeaders = array( - array('HTTP/1.0 405', true, null), - array('Allow: POST', false, null), - array('Content-Type: text/html; charset=iso8859-1', true, null), - ); + $expectedHeaders = [ + ['HTTP/1.0 405', true, null], + ['Allow: POST', false, null], + ['Content-Type: text/html; charset=iso8859-1', true, null], + ]; $this->assertSame($expectedHeaders, testHeader()); } @@ -99,35 +108,65 @@ class ExceptionHandlerTest extends TestCase public function testHandle() { - $exception = new \Exception('foo'); + $handler = new ExceptionHandler(true); + ob_start(); - $handler = $this->getMockBuilder('Symfony\Component\Debug\ExceptionHandler')->setMethods(array('sendPhpResponse'))->getMock(); - $handler - ->expects($this->exactly(2)) - ->method('sendPhpResponse'); + $handler->handle(new \Exception('foo')); - $handler->handle($exception); + $this->assertThatTheExceptionWasOutput(ob_get_clean(), \Exception::class, 'Exception', 'foo'); + } - $handler->setHandler(function ($e) use ($exception) { - $this->assertSame($exception, $e); + public function testHandleWithACustomHandlerThatOutputsSomething() + { + $handler = new ExceptionHandler(true); + ob_start(); + $handler->setHandler(function () { + echo 'ccc'; }); - $handler->handle($exception); + $handler->handle(new \Exception()); + ob_end_flush(); // Necessary because of this PHP bug : https://bugs.php.net/76563 + $this->assertSame('ccc', ob_get_clean()); } - public function testHandleOutOfMemoryException() + public function testHandleWithACustomHandlerThatOutputsNothing() + { + $handler = new ExceptionHandler(true); + $handler->setHandler(function () {}); + + $handler->handle(new \Exception('ccc')); + + $this->assertThatTheExceptionWasOutput(ob_get_clean(), \Exception::class, 'Exception', 'ccc'); + } + + public function testHandleWithACustomHandlerThatFails() { - $exception = new OutOfMemoryException('foo', 0, E_ERROR, __FILE__, __LINE__); + $handler = new ExceptionHandler(true); + $handler->setHandler(function () { + throw new \RuntimeException(); + }); - $handler = $this->getMockBuilder('Symfony\Component\Debug\ExceptionHandler')->setMethods(array('sendPhpResponse'))->getMock(); - $handler - ->expects($this->once()) - ->method('sendPhpResponse'); + $handler->handle(new \Exception('ccc')); + + $this->assertThatTheExceptionWasOutput(ob_get_clean(), \Exception::class, 'Exception', 'ccc'); + } - $handler->setHandler(function ($e) { + public function testHandleOutOfMemoryException() + { + $handler = new ExceptionHandler(true); + ob_start(); + $handler->setHandler(function () { $this->fail('OutOfMemoryException should bypass the handler'); }); - $handler->handle($exception); + $handler->handle(new OutOfMemoryException('foo', 0, E_ERROR, __FILE__, __LINE__)); + + $this->assertThatTheExceptionWasOutput(ob_get_clean(), OutOfMemoryException::class, 'OutOfMemoryException', 'foo'); + } + + private function assertThatTheExceptionWasOutput($content, $expectedClass, $expectedTitle, $expectedMessage) + { + $this->assertStringContainsString(sprintf('<span class="exception_title"><abbr title="%s">%s</abbr></span>', $expectedClass, $expectedTitle), $content); + $this->assertStringContainsString(sprintf('<p class="break-long-words trace-message">%s</p>', $expectedMessage), $content); } } diff --git a/vendor/symfony/debug/Tests/FatalErrorHandler/ClassNotFoundFatalErrorHandlerTest.php b/vendor/symfony/debug/Tests/FatalErrorHandler/ClassNotFoundFatalErrorHandlerTest.php index 65c80fc1cf34a7833bc9f5f72b74b0f2692ec571..f3fd16e2ac1dad6471cdafe1e2952f4031f38513 100644 --- a/vendor/symfony/debug/Tests/FatalErrorHandler/ClassNotFoundFatalErrorHandlerTest.php +++ b/vendor/symfony/debug/Tests/FatalErrorHandler/ClassNotFoundFatalErrorHandlerTest.php @@ -11,18 +11,18 @@ namespace Symfony\Component\Debug\Tests\FatalErrorHandler; +use Composer\Autoload\ClassLoader as ComposerClassLoader; use PHPUnit\Framework\TestCase; +use Symfony\Component\Debug\DebugClassLoader; use Symfony\Component\Debug\Exception\FatalErrorException; use Symfony\Component\Debug\FatalErrorHandler\ClassNotFoundFatalErrorHandler; -use Symfony\Component\Debug\DebugClassLoader; -use Composer\Autoload\ClassLoader as ComposerClassLoader; class ClassNotFoundFatalErrorHandlerTest extends TestCase { - public static function setUpBeforeClass() + public static function setUpBeforeClass(): void { foreach (spl_autoload_functions() as $function) { - if (!is_array($function)) { + if (!\is_array($function)) { continue; } @@ -32,7 +32,7 @@ class ClassNotFoundFatalErrorHandlerTest extends TestCase } if ($function[0] instanceof ComposerClassLoader) { - $function[0]->add('Symfony_Component_Debug_Tests_Fixtures', dirname(dirname(dirname(dirname(dirname(__DIR__)))))); + $function[0]->add('Symfony_Component_Debug_Tests_Fixtures', \dirname(__DIR__, 5)); break; } } @@ -61,7 +61,7 @@ class ClassNotFoundFatalErrorHandlerTest extends TestCase } $this->assertInstanceOf('Symfony\Component\Debug\Exception\ClassNotFoundException', $exception); - $this->assertSame($translatedMessage, $exception->getMessage()); + $this->assertRegExp($translatedMessage, $exception->getMessage()); $this->assertSame($error['type'], $exception->getSeverity()); $this->assertSame($error['file'], $exception->getFile()); $this->assertSame($error['line'], $exception->getLine()); @@ -71,86 +71,90 @@ class ClassNotFoundFatalErrorHandlerTest extends TestCase { $autoloader = new ComposerClassLoader(); $autoloader->add('Symfony\Component\Debug\Exception\\', realpath(__DIR__.'/../../Exception')); + $autoloader->add('Symfony_Component_Debug_Tests_Fixtures', realpath(__DIR__.'/../../Tests/Fixtures')); - $debugClassLoader = new DebugClassLoader(array($autoloader, 'loadClass')); + $debugClassLoader = new DebugClassLoader([$autoloader, 'loadClass']); - return array( - array( - array( + return [ + [ + [ 'type' => 1, 'line' => 12, 'file' => 'foo.php', 'message' => 'Class \'WhizBangFactory\' not found', - ), - "Attempted to load class \"WhizBangFactory\" from the global namespace.\nDid you forget a \"use\" statement?", - ), - array( - array( + ], + "/^Attempted to load class \"WhizBangFactory\" from the global namespace.\nDid you forget a \"use\" statement\?$/", + ], + [ + [ 'type' => 1, 'line' => 12, 'file' => 'foo.php', 'message' => 'Class \'Foo\\Bar\\WhizBangFactory\' not found', - ), - "Attempted to load class \"WhizBangFactory\" from namespace \"Foo\\Bar\".\nDid you forget a \"use\" statement for another namespace?", - ), - array( - array( + ], + "/^Attempted to load class \"WhizBangFactory\" from namespace \"Foo\\\\Bar\".\nDid you forget a \"use\" statement for another namespace\?$/", + ], + [ + [ 'type' => 1, 'line' => 12, 'file' => 'foo.php', 'message' => 'Class \'UndefinedFunctionException\' not found', - ), - "Attempted to load class \"UndefinedFunctionException\" from the global namespace.\nDid you forget a \"use\" statement for \"Symfony\Component\Debug\Exception\UndefinedFunctionException\"?", - ), - array( - array( + ], + "/^Attempted to load class \"UndefinedFunctionException\" from the global namespace.\nDid you forget a \"use\" statement for .*\"Symfony\\\\Component\\\\Debug\\\\Exception\\\\UndefinedFunctionException\"\?$/", + [$debugClassLoader, 'loadClass'], + ], + [ + [ 'type' => 1, 'line' => 12, 'file' => 'foo.php', 'message' => 'Class \'PEARClass\' not found', - ), - "Attempted to load class \"PEARClass\" from the global namespace.\nDid you forget a \"use\" statement for \"Symfony_Component_Debug_Tests_Fixtures_PEARClass\"?", - ), - array( - array( + ], + "/^Attempted to load class \"PEARClass\" from the global namespace.\nDid you forget a \"use\" statement for \"Symfony_Component_Debug_Tests_Fixtures_PEARClass\"\?$/", + [$debugClassLoader, 'loadClass'], + ], + [ + [ 'type' => 1, 'line' => 12, 'file' => 'foo.php', 'message' => 'Class \'Foo\\Bar\\UndefinedFunctionException\' not found', - ), - "Attempted to load class \"UndefinedFunctionException\" from namespace \"Foo\Bar\".\nDid you forget a \"use\" statement for \"Symfony\Component\Debug\Exception\UndefinedFunctionException\"?", - ), - array( - array( + ], + "/^Attempted to load class \"UndefinedFunctionException\" from namespace \"Foo\\\\Bar\".\nDid you forget a \"use\" statement for .*\"Symfony\\\\Component\\\\Debug\\\\Exception\\\\UndefinedFunctionException\"\?$/", + [$debugClassLoader, 'loadClass'], + ], + [ + [ 'type' => 1, 'line' => 12, 'file' => 'foo.php', 'message' => 'Class \'Foo\\Bar\\UndefinedFunctionException\' not found', - ), - "Attempted to load class \"UndefinedFunctionException\" from namespace \"Foo\Bar\".\nDid you forget a \"use\" statement for \"Symfony\Component\Debug\Exception\UndefinedFunctionException\"?", - array($autoloader, 'loadClass'), - ), - array( - array( + ], + "/^Attempted to load class \"UndefinedFunctionException\" from namespace \"Foo\\\\Bar\".\nDid you forget a \"use\" statement for \"Symfony\\\\Component\\\\Debug\\\\Exception\\\\UndefinedFunctionException\"\?$/", + [$autoloader, 'loadClass'], + ], + [ + [ 'type' => 1, 'line' => 12, 'file' => 'foo.php', 'message' => 'Class \'Foo\\Bar\\UndefinedFunctionException\' not found', - ), - "Attempted to load class \"UndefinedFunctionException\" from namespace \"Foo\Bar\".\nDid you forget a \"use\" statement for \"Symfony\Component\Debug\Exception\UndefinedFunctionException\"?", - array($debugClassLoader, 'loadClass'), - ), - array( - array( + ], + "/^Attempted to load class \"UndefinedFunctionException\" from namespace \"Foo\\\\Bar\".\nDid you forget a \"use\" statement for \"Symfony\\\\Component\\\\Debug\\\\Exception\\\\UndefinedFunctionException\"\?/", + [$debugClassLoader, 'loadClass'], + ], + [ + [ 'type' => 1, 'line' => 12, 'file' => 'foo.php', 'message' => 'Class \'Foo\\Bar\\UndefinedFunctionException\' not found', - ), - "Attempted to load class \"UndefinedFunctionException\" from namespace \"Foo\\Bar\".\nDid you forget a \"use\" statement for another namespace?", + ], + "/^Attempted to load class \"UndefinedFunctionException\" from namespace \"Foo\\\\Bar\".\nDid you forget a \"use\" statement for another namespace\?$/", function ($className) { /* do nothing here */ }, - ), - ); + ], + ]; } public function testCannotRedeclareClass() @@ -161,12 +165,12 @@ class ClassNotFoundFatalErrorHandlerTest extends TestCase require_once __DIR__.'/../FIXTURES2/REQUIREDTWICE.PHP'; - $error = array( + $error = [ 'type' => 1, 'line' => 12, 'file' => 'foo.php', 'message' => 'Class \'Foo\\Bar\\RequiredTwice\' not found', - ); + ]; $handler = new ClassNotFoundFatalErrorHandler(); $exception = $handler->handleError($error, new FatalErrorException('', 0, $error['type'], $error['file'], $error['line'])); diff --git a/vendor/symfony/debug/Tests/FatalErrorHandler/UndefinedFunctionFatalErrorHandlerTest.php b/vendor/symfony/debug/Tests/FatalErrorHandler/UndefinedFunctionFatalErrorHandlerTest.php index 1dc2120045c2cd4a13a1c5b641453d99fe1e9420..de9994e447fed68dacb9c0f79030f658079e547a 100644 --- a/vendor/symfony/debug/Tests/FatalErrorHandler/UndefinedFunctionFatalErrorHandlerTest.php +++ b/vendor/symfony/debug/Tests/FatalErrorHandler/UndefinedFunctionFatalErrorHandlerTest.php @@ -26,7 +26,7 @@ class UndefinedFunctionFatalErrorHandlerTest extends TestCase $exception = $handler->handleError($error, new FatalErrorException('', 0, $error['type'], $error['file'], $error['line'])); $this->assertInstanceOf('Symfony\Component\Debug\Exception\UndefinedFunctionException', $exception); - // class names are case insensitive and PHP/HHVM do not return the same + // class names are case insensitive and PHP do not return the same $this->assertSame(strtolower($translatedMessage), strtolower($exception->getMessage())); $this->assertSame($error['type'], $exception->getSeverity()); $this->assertSame($error['file'], $exception->getFile()); @@ -35,44 +35,44 @@ class UndefinedFunctionFatalErrorHandlerTest extends TestCase public function provideUndefinedFunctionData() { - return array( - array( - array( + return [ + [ + [ 'type' => 1, 'line' => 12, 'file' => 'foo.php', 'message' => 'Call to undefined function test_namespaced_function()', - ), + ], "Attempted to call function \"test_namespaced_function\" from the global namespace.\nDid you mean to call \"\\symfony\\component\\debug\\tests\\fatalerrorhandler\\test_namespaced_function\"?", - ), - array( - array( + ], + [ + [ 'type' => 1, 'line' => 12, 'file' => 'foo.php', 'message' => 'Call to undefined function Foo\\Bar\\Baz\\test_namespaced_function()', - ), + ], "Attempted to call function \"test_namespaced_function\" from namespace \"Foo\\Bar\\Baz\".\nDid you mean to call \"\\symfony\\component\\debug\\tests\\fatalerrorhandler\\test_namespaced_function\"?", - ), - array( - array( + ], + [ + [ 'type' => 1, 'line' => 12, 'file' => 'foo.php', 'message' => 'Call to undefined function foo()', - ), + ], 'Attempted to call function "foo" from the global namespace.', - ), - array( - array( + ], + [ + [ 'type' => 1, 'line' => 12, 'file' => 'foo.php', 'message' => 'Call to undefined function Foo\\Bar\\Baz\\foo()', - ), + ], 'Attempted to call function "foo" from namespace "Foo\Bar\Baz".', - ), - ); + ], + ]; } } diff --git a/vendor/symfony/debug/Tests/FatalErrorHandler/UndefinedMethodFatalErrorHandlerTest.php b/vendor/symfony/debug/Tests/FatalErrorHandler/UndefinedMethodFatalErrorHandlerTest.php index 739e5b2b15b7ddddaf5376dfc32fc5b960202fbf..268a841351ec45990530a823f3e6de20c61af058 100644 --- a/vendor/symfony/debug/Tests/FatalErrorHandler/UndefinedMethodFatalErrorHandlerTest.php +++ b/vendor/symfony/debug/Tests/FatalErrorHandler/UndefinedMethodFatalErrorHandlerTest.php @@ -34,43 +34,43 @@ class UndefinedMethodFatalErrorHandlerTest extends TestCase public function provideUndefinedMethodData() { - return array( - array( - array( + return [ + [ + [ 'type' => 1, 'line' => 12, 'file' => 'foo.php', 'message' => 'Call to undefined method SplObjectStorage::what()', - ), + ], 'Attempted to call an undefined method named "what" of class "SplObjectStorage".', - ), - array( - array( + ], + [ + [ 'type' => 1, 'line' => 12, 'file' => 'foo.php', 'message' => 'Call to undefined method SplObjectStorage::walid()', - ), + ], "Attempted to call an undefined method named \"walid\" of class \"SplObjectStorage\".\nDid you mean to call \"valid\"?", - ), - array( - array( + ], + [ + [ 'type' => 1, 'line' => 12, 'file' => 'foo.php', 'message' => 'Call to undefined method SplObjectStorage::offsetFet()', - ), + ], "Attempted to call an undefined method named \"offsetFet\" of class \"SplObjectStorage\".\nDid you mean to call e.g. \"offsetGet\", \"offsetSet\" or \"offsetUnset\"?", - ), - array( - array( - 'type' => 1, - 'message' => 'Call to undefined method class@anonymous::test()', - 'file' => '/home/possum/work/symfony/test.php', - 'line' => 11, - ), + ], + [ + [ + 'type' => 1, + 'message' => 'Call to undefined method class@anonymous::test()', + 'file' => '/home/possum/work/symfony/test.php', + 'line' => 11, + ], 'Attempted to call an undefined method named "test" of class "class@anonymous".', - ), - ); + ], + ]; } } diff --git a/vendor/symfony/debug/Tests/Fixtures/AnnotatedClass.php b/vendor/symfony/debug/Tests/Fixtures/AnnotatedClass.php index dff9517d0a0466d3c0ce47d3f9e5bb7c1b2349c9..4eecb6d3f16683745a233a8c98cb6ea24552c1a7 100644 --- a/vendor/symfony/debug/Tests/Fixtures/AnnotatedClass.php +++ b/vendor/symfony/debug/Tests/Fixtures/AnnotatedClass.php @@ -5,7 +5,7 @@ namespace Symfony\Component\Debug\Tests\Fixtures; class AnnotatedClass { /** - * @deprecated since version 3.4. + * @deprecated */ public function deprecatedMethod() { diff --git a/vendor/symfony/debug/Tests/Fixtures/ClassWithAnnotatedParameters.php b/vendor/symfony/debug/Tests/Fixtures/ClassWithAnnotatedParameters.php new file mode 100644 index 0000000000000000000000000000000000000000..d6eec9aa690345bea3d68270875cc39379df15a2 --- /dev/null +++ b/vendor/symfony/debug/Tests/Fixtures/ClassWithAnnotatedParameters.php @@ -0,0 +1,34 @@ +<?php + +namespace Symfony\Component\Debug\Tests\Fixtures; + +class ClassWithAnnotatedParameters +{ + /** + * @param string $foo this is a foo parameter + */ + public function fooMethod(string $foo) + { + } + + /** + * @param string $bar parameter not implemented yet + */ + public function barMethod(/* string $bar = null */) + { + } + + /** + * @param Quz $quz parameter not implemented yet + */ + public function quzMethod(/* Quz $quz = null */) + { + } + + /** + * @param true $yes + */ + public function isSymfony() + { + } +} diff --git a/vendor/symfony/debug/Tests/Fixtures/DefinitionInEvaluatedCode.php b/vendor/symfony/debug/Tests/Fixtures/DefinitionInEvaluatedCode.php new file mode 100644 index 0000000000000000000000000000000000000000..ff6976e0fb1d702f85807e7595d4e500bb3a9dbf --- /dev/null +++ b/vendor/symfony/debug/Tests/Fixtures/DefinitionInEvaluatedCode.php @@ -0,0 +1,11 @@ +<?php + +namespace Symfony\Component\Debug\Tests\Fixtures; + +eval(' + namespace Symfony\Component\Debug\Tests\Fixtures; + + class DefinitionInEvaluatedCode + { + } +'); diff --git a/vendor/symfony/debug/Tests/Fixtures/ErrorHandlerThatUsesThePreviousOne.php b/vendor/symfony/debug/Tests/Fixtures/ErrorHandlerThatUsesThePreviousOne.php new file mode 100644 index 0000000000000000000000000000000000000000..d449c40cc76dbec78c4e921bab2565f733b2e9d8 --- /dev/null +++ b/vendor/symfony/debug/Tests/Fixtures/ErrorHandlerThatUsesThePreviousOne.php @@ -0,0 +1,22 @@ +<?php + +namespace Symfony\Component\Debug\Tests\Fixtures; + +class ErrorHandlerThatUsesThePreviousOne +{ + private static $previous; + + public static function register() + { + $handler = new static(); + + self::$previous = set_error_handler([$handler, 'handleError']); + + return $handler; + } + + public function handleError($type, $message, $file, $line, $context) + { + return \call_user_func(self::$previous, $type, $message, $file, $line, $context); + } +} diff --git a/vendor/symfony/debug/Tests/Fixtures/ExtendedFinalMethod.php b/vendor/symfony/debug/Tests/Fixtures/ExtendedFinalMethod.php index 2bd337e5a2db0058ca9c38a82d2a0f20ea0a81e6..050d19ff5e720d52a4c5cb16d78d92b1697e9305 100644 --- a/vendor/symfony/debug/Tests/Fixtures/ExtendedFinalMethod.php +++ b/vendor/symfony/debug/Tests/Fixtures/ExtendedFinalMethod.php @@ -4,6 +4,8 @@ namespace Symfony\Component\Debug\Tests\Fixtures; class ExtendedFinalMethod extends FinalMethod { + use FinalMethod2Trait; + /** * {@inheritdoc} */ diff --git a/vendor/symfony/debug/Tests/Fixtures/FinalClasses.php b/vendor/symfony/debug/Tests/Fixtures/FinalClasses.php new file mode 100644 index 0000000000000000000000000000000000000000..4c2b0aaf351f38603af944da971e0af2505e0b58 --- /dev/null +++ b/vendor/symfony/debug/Tests/Fixtures/FinalClasses.php @@ -0,0 +1,85 @@ +<?php + +namespace Symfony\Component\Debug\Tests\Fixtures; + +/** + * @final since version 3.3. + */ +class FinalClass1 +{ + // simple comment +} + +/** + * @final + */ +class FinalClass2 +{ + // no comment +} + +/** + * @final comment with @@@ and *** + * + * @author John Doe + */ +class FinalClass3 +{ + // with comment and a tag after +} + +/** + * @final + * + * @author John Doe + */ +class FinalClass4 +{ + // without comment and a tag after +} + +/** + * @author John Doe + * + * + * @final multiline + * comment + */ +class FinalClass5 +{ + // with comment and a tag before +} + +/** + * @author John Doe + * + * @final + */ +class FinalClass6 +{ + // without comment and a tag before +} + +/** + * @author John Doe + * + * @final another + * multiline comment... + * + * @return string + */ +class FinalClass7 +{ + // with comment and a tag before and after +} + +/** + * @author John Doe + * @final + * + * @return string + */ +class FinalClass8 +{ + // without comment and a tag before and after +} diff --git a/vendor/symfony/debug/Tests/Fixtures/FinalMethod.php b/vendor/symfony/debug/Tests/Fixtures/FinalMethod.php index 92ec421863f3f2795747b2fdc1783d155220f000..60a28b24c27fb55f82935589d89ea36d04fb1446 100644 --- a/vendor/symfony/debug/Tests/Fixtures/FinalMethod.php +++ b/vendor/symfony/debug/Tests/Fixtures/FinalMethod.php @@ -5,12 +5,21 @@ namespace Symfony\Component\Debug\Tests\Fixtures; class FinalMethod { /** - * @final since version 3.3. + * @final */ public function finalMethod() { } + /** + * @final + * + * @return int + */ + public function finalMethod2() + { + } + public function anotherMethod() { } diff --git a/vendor/symfony/debug/Tests/Fixtures/FinalMethod2Trait.php b/vendor/symfony/debug/Tests/Fixtures/FinalMethod2Trait.php new file mode 100644 index 0000000000000000000000000000000000000000..8547f3afed7abfa0c139ed845a4a7f3c54344e2a --- /dev/null +++ b/vendor/symfony/debug/Tests/Fixtures/FinalMethod2Trait.php @@ -0,0 +1,10 @@ +<?php + +namespace Symfony\Component\Debug\Tests\Fixtures; + +trait FinalMethod2Trait +{ + public function finalMethod2() + { + } +} diff --git a/vendor/symfony/debug/Tests/Fixtures/InterfaceWithAnnotatedParameters.php b/vendor/symfony/debug/Tests/Fixtures/InterfaceWithAnnotatedParameters.php new file mode 100644 index 0000000000000000000000000000000000000000..86593db1249e608a5844c9003b47df63a55859b3 --- /dev/null +++ b/vendor/symfony/debug/Tests/Fixtures/InterfaceWithAnnotatedParameters.php @@ -0,0 +1,27 @@ +<?php + +namespace Symfony\Component\Debug\Tests\Fixtures; + +/** + * Ensures a deprecation is triggered when a new parameter is not declared in child classes. + */ +interface InterfaceWithAnnotatedParameters +{ + /** + * @param bool $matrix + */ + public function whereAmI(); + + /** + * @param $noType + * @param callable(\Throwable|null $reason, mixed $value) $callback and a comment + * about this great param + * @param string $param (comment with $dollar) + * @param $defined + * @param callable ($a, $b) $anotherOne + * @param callable (mixed $a, $b) $definedCallable + * @param Type$WithDollarIsStillAType $ccc + * @param \JustAType + */ + public function iAmHere(); +} diff --git a/vendor/symfony/debug/Tests/Fixtures/InternalClass.php b/vendor/symfony/debug/Tests/Fixtures/InternalClass.php index 119842c26002750acb6ed654d9afa4d301c4513d..30efe79b333afef3e8711608a081895630a8eb1d 100644 --- a/vendor/symfony/debug/Tests/Fixtures/InternalClass.php +++ b/vendor/symfony/debug/Tests/Fixtures/InternalClass.php @@ -3,7 +3,7 @@ namespace Symfony\Component\Debug\Tests\Fixtures; /** - * @internal since version 3.4. + * @internal */ class InternalClass { diff --git a/vendor/symfony/debug/Tests/Fixtures/InternalTrait2.php b/vendor/symfony/debug/Tests/Fixtures/InternalTrait2.php index 05f18e83e4a9e81ac0e06c11af88ee4d57e86ebd..e4cbe12aec298517ae51200b3aa3b118829caa26 100644 --- a/vendor/symfony/debug/Tests/Fixtures/InternalTrait2.php +++ b/vendor/symfony/debug/Tests/Fixtures/InternalTrait2.php @@ -8,7 +8,7 @@ namespace Symfony\Component\Debug\Tests\Fixtures; trait InternalTrait2 { /** - * @internal since version 3.4 + * @internal */ public function internalMethod() { diff --git a/vendor/symfony/debug/Tests/Fixtures/LoggerThatSetAnErrorHandler.php b/vendor/symfony/debug/Tests/Fixtures/LoggerThatSetAnErrorHandler.php new file mode 100644 index 0000000000000000000000000000000000000000..dd8563627a1f44ef4139530a4ef06db1efb6dd73 --- /dev/null +++ b/vendor/symfony/debug/Tests/Fixtures/LoggerThatSetAnErrorHandler.php @@ -0,0 +1,15 @@ +<?php + +namespace Symfony\Component\Debug\Tests\Fixtures; + +use Symfony\Component\Debug\BufferingLogger; + +class LoggerThatSetAnErrorHandler extends BufferingLogger +{ + public function log($level, $message, array $context = []) + { + set_error_handler('is_string'); + parent::log($level, $message, $context); + restore_error_handler(); + } +} diff --git a/vendor/symfony/debug/Tests/Fixtures/SubClassWithAnnotatedParameters.php b/vendor/symfony/debug/Tests/Fixtures/SubClassWithAnnotatedParameters.php new file mode 100644 index 0000000000000000000000000000000000000000..5d05d798358ef025ae58e30086f39bc3b7696934 --- /dev/null +++ b/vendor/symfony/debug/Tests/Fixtures/SubClassWithAnnotatedParameters.php @@ -0,0 +1,32 @@ +<?php + +namespace Symfony\Component\Debug\Tests\Fixtures; + +class SubClassWithAnnotatedParameters extends ClassWithAnnotatedParameters implements InterfaceWithAnnotatedParameters +{ + use TraitWithAnnotatedParameters; + + public function fooMethod(string $foo) + { + } + + public function barMethod($bar = null) + { + } + + public function quzMethod() + { + } + + public function whereAmI() + { + } + + /** + * @param $defined + * @param Type\Does\Not\Matter $definedCallable + */ + public function iAmHere() + { + } +} diff --git a/vendor/symfony/debug/Tests/Fixtures/ToStringThrower.php b/vendor/symfony/debug/Tests/Fixtures/ToStringThrower.php index 40a5fb7f8c852a23c84782dabc02f7bf5d2abb2e..24ac8926d28fff1cca7e344014f9e7b874132829 100644 --- a/vendor/symfony/debug/Tests/Fixtures/ToStringThrower.php +++ b/vendor/symfony/debug/Tests/Fixtures/ToStringThrower.php @@ -18,7 +18,7 @@ class ToStringThrower } catch (\Exception $e) { // Using user_error() here is on purpose so we do not forget // that this alias also should work alongside with trigger_error(). - return user_error($e, E_USER_ERROR); + return trigger_error($e, E_USER_ERROR); } } } diff --git a/vendor/symfony/debug/Tests/Fixtures/TraitWithAnnotatedParameters.php b/vendor/symfony/debug/Tests/Fixtures/TraitWithAnnotatedParameters.php new file mode 100644 index 0000000000000000000000000000000000000000..5eb5fbf84bc93e20afcad7fbc7d2d1c3c6a82741 --- /dev/null +++ b/vendor/symfony/debug/Tests/Fixtures/TraitWithAnnotatedParameters.php @@ -0,0 +1,13 @@ +<?php + +namespace Symfony\Component\Debug\Tests\Fixtures; + +trait TraitWithAnnotatedParameters +{ + /** + * `@param` annotations in traits are not parsed. + */ + public function isSymfony() + { + } +} diff --git a/vendor/symfony/debug/Tests/Fixtures/TraitWithInternalMethod.php b/vendor/symfony/debug/Tests/Fixtures/TraitWithInternalMethod.php new file mode 100644 index 0000000000000000000000000000000000000000..4c3dae37ab52c6cf45998a164e5f61c89705c7d7 --- /dev/null +++ b/vendor/symfony/debug/Tests/Fixtures/TraitWithInternalMethod.php @@ -0,0 +1,13 @@ +<?php + +namespace Symfony\Component\Debug\Tests\Fixtures; + +trait TraitWithInternalMethod +{ + /** + * @internal + */ + public function foo() + { + } +} diff --git a/vendor/symfony/debug/Tests/Fixtures/VirtualClass.php b/vendor/symfony/debug/Tests/Fixtures/VirtualClass.php new file mode 100644 index 0000000000000000000000000000000000000000..25712519a5fb6059e254c447b13bf01e51cfa801 --- /dev/null +++ b/vendor/symfony/debug/Tests/Fixtures/VirtualClass.php @@ -0,0 +1,11 @@ +<?php + +namespace Symfony\Component\Debug\Tests\Fixtures; + +/** + * @method string classMethod() + */ +class VirtualClass +{ + use VirtualTrait; +} diff --git a/vendor/symfony/debug/Tests/Fixtures/VirtualClassMagicCall.php b/vendor/symfony/debug/Tests/Fixtures/VirtualClassMagicCall.php new file mode 100644 index 0000000000000000000000000000000000000000..de33e8afc557210c54cc60c2e663553583f60fdd --- /dev/null +++ b/vendor/symfony/debug/Tests/Fixtures/VirtualClassMagicCall.php @@ -0,0 +1,18 @@ +<?php + +namespace Symfony\Component\Debug\Tests\Fixtures; + +/** + * @method string magicMethod() + * @method static string staticMagicMethod() + */ +class VirtualClassMagicCall +{ + public static function __callStatic($name, $arguments) + { + } + + public function __call($name, $arguments) + { + } +} diff --git a/vendor/symfony/debug/Tests/Fixtures/VirtualInterface.php b/vendor/symfony/debug/Tests/Fixtures/VirtualInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..943014eefb18153ef34c0acd9a1a9e93dfb8a90d --- /dev/null +++ b/vendor/symfony/debug/Tests/Fixtures/VirtualInterface.php @@ -0,0 +1,34 @@ +<?php + +namespace Symfony\Component\Debug\Tests\Fixtures; + +/** + * @method string interfaceMethod() + * @method sameLineInterfaceMethod($arg) + * @method sameLineInterfaceMethodNoBraces + * + * Ignored + * @method + * @method + * + * Not ignored + * @method newLineInterfaceMethod() Some description! + * @method \stdClass newLineInterfaceMethodNoBraces Description + * + * Invalid + * @method unknownType invalidInterfaceMethod() + * @method unknownType|string invalidInterfaceMethodNoBraces + * + * Complex + * @method complexInterfaceMethod($arg, ...$args) + * @method string[]|int complexInterfaceMethodTyped($arg, int ...$args) Description ... + * + * Static + * @method static Foo&Bar staticMethod() + * @method static staticMethodNoBraces + * @method static \stdClass staticMethodTyped(int $arg) Description + * @method static \stdClass[] staticMethodTypedNoBraces + */ +interface VirtualInterface +{ +} diff --git a/vendor/symfony/debug/Tests/Fixtures/VirtualSubInterface.php b/vendor/symfony/debug/Tests/Fixtures/VirtualSubInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..dee19731dcd24c4311c246f2e7b5d897e018da2b --- /dev/null +++ b/vendor/symfony/debug/Tests/Fixtures/VirtualSubInterface.php @@ -0,0 +1,10 @@ +<?php + +namespace Symfony\Component\Debug\Tests\Fixtures; + +/** + * @method string subInterfaceMethod() + */ +interface VirtualSubInterface extends VirtualInterface +{ +} diff --git a/vendor/symfony/debug/Tests/Fixtures/FinalClass.php b/vendor/symfony/debug/Tests/Fixtures/VirtualTrait.php similarity index 57% rename from vendor/symfony/debug/Tests/Fixtures/FinalClass.php rename to vendor/symfony/debug/Tests/Fixtures/VirtualTrait.php index 2cf26b19e4fc8f17f28b3353195681d9e07cde85..f584a8aa8fdad197af54ab3c5845a5226e5e4b9a 100644 --- a/vendor/symfony/debug/Tests/Fixtures/FinalClass.php +++ b/vendor/symfony/debug/Tests/Fixtures/VirtualTrait.php @@ -3,8 +3,8 @@ namespace Symfony\Component\Debug\Tests\Fixtures; /** - * @final since version 3.3. + * @method string traitMethod() */ -class FinalClass +trait VirtualTrait { } diff --git a/vendor/symfony/debug/Tests/HeaderMock.php b/vendor/symfony/debug/Tests/HeaderMock.php index 65d0b588558b56f7795ca0f986be8cd3a099aa57..d7564db4854b8aefd0ada8454a3f2a142df3e292 100644 --- a/vendor/symfony/debug/Tests/HeaderMock.php +++ b/vendor/symfony/debug/Tests/HeaderMock.php @@ -25,14 +25,14 @@ namespace Symfony\Component\Debug\Tests; function testHeader() { - static $headers = array(); + static $headers = []; - if (!$h = func_get_args()) { + if (!$h = \func_get_args()) { $h = $headers; - $headers = array(); + $headers = []; return $h; } - $headers[] = func_get_args(); + $headers[] = \func_get_args(); } diff --git a/vendor/symfony/debug/Tests/phpt/debug_class_loader.phpt b/vendor/symfony/debug/Tests/phpt/debug_class_loader.phpt index b9d3d7288714e26994233b19cf9541f53d12dd02..53839c4899b0c3efff02d7778397c069da2f6510 100644 --- a/vendor/symfony/debug/Tests/phpt/debug_class_loader.phpt +++ b/vendor/symfony/debug/Tests/phpt/debug_class_loader.phpt @@ -9,7 +9,7 @@ use Symfony\Component\Debug\DebugClassLoader; $vendor = __DIR__; while (!file_exists($vendor.'/vendor')) { - $vendor = dirname($vendor); + $vendor = \dirname($vendor); } require $vendor.'/vendor/autoload.php'; @@ -23,4 +23,5 @@ class_exists(ExtendedFinalMethod::class); ?> --EXPECTF-- -The "Symfony\Component\Debug\Tests\Fixtures\FinalMethod::finalMethod()" method is considered final since version 3.3. It may change without further notice as of its next major version. You should not extend it from "Symfony\Component\Debug\Tests\Fixtures\ExtendedFinalMethod". +The "Symfony\Component\Debug\Tests\Fixtures\FinalMethod::finalMethod()" method is considered final. It may change without further notice as of its next major version. You should not extend it from "Symfony\Component\Debug\Tests\Fixtures\ExtendedFinalMethod". +The "Symfony\Component\Debug\Tests\Fixtures\FinalMethod::finalMethod2()" method is considered final. It may change without further notice as of its next major version. You should not extend it from "Symfony\Component\Debug\Tests\Fixtures\ExtendedFinalMethod". diff --git a/vendor/symfony/debug/Tests/phpt/decorate_exception_hander.phpt b/vendor/symfony/debug/Tests/phpt/decorate_exception_hander.phpt index 7ce7b9dc6f7dd27228713f81043a83add2435d8f..9cd44388c3166ecf379e826c47a32a54e4af636c 100644 --- a/vendor/symfony/debug/Tests/phpt/decorate_exception_hander.phpt +++ b/vendor/symfony/debug/Tests/phpt/decorate_exception_hander.phpt @@ -1,5 +1,7 @@ --TEST-- Test catching fatal errors when handlers are nested +--INI-- +display_errors=0 --FILE-- <?php @@ -7,7 +9,7 @@ namespace Symfony\Component\Debug; $vendor = __DIR__; while (!file_exists($vendor.'/vendor')) { - $vendor = dirname($vendor); + $vendor = \dirname($vendor); } require $vendor.'/vendor/autoload.php'; @@ -24,7 +26,6 @@ if (true) { ?> --EXPECTF-- -Fatal error: Class 'Symfony\Component\Debug\missing' not found in %s on line %d object(Symfony\Component\Debug\Exception\ClassNotFoundException)#%d (8) { ["message":protected]=> string(131) "Attempted to load class "missing" from namespace "Symfony\Component\Debug". @@ -38,8 +39,7 @@ Did you forget a "use" statement for another namespace?" ["line":protected]=> int(%d) ["trace":"Exception":private]=> - array(0) { - } + array(%d) {%A} ["previous":"Exception":private]=> NULL ["severity":protected]=> diff --git a/vendor/symfony/debug/Tests/phpt/exception_rethrown.phpt b/vendor/symfony/debug/Tests/phpt/exception_rethrown.phpt index 9df0a65cf79f9bafa5dac91965e3cf0d3b6e7a34..b743d93ad7c805871ff013b048c3946b84a42051 100644 --- a/vendor/symfony/debug/Tests/phpt/exception_rethrown.phpt +++ b/vendor/symfony/debug/Tests/phpt/exception_rethrown.phpt @@ -7,14 +7,14 @@ namespace Symfony\Component\Debug; $vendor = __DIR__; while (!file_exists($vendor.'/vendor')) { - $vendor = dirname($vendor); + $vendor = \dirname($vendor); } require $vendor.'/vendor/autoload.php'; if (true) { class TestLogger extends \Psr\Log\AbstractLogger { - public function log($level, $message, array $context = array()) + public function log($level, $message, array $context = []) { echo $message, "\n"; } diff --git a/vendor/symfony/debug/Tests/phpt/fatal_with_nested_handlers.phpt b/vendor/symfony/debug/Tests/phpt/fatal_with_nested_handlers.phpt index 5c5245c069e636076ac6db7291085c81660125b9..1736a3b5f2a739b4caa51c7e27ee13d7802d8452 100644 --- a/vendor/symfony/debug/Tests/phpt/fatal_with_nested_handlers.phpt +++ b/vendor/symfony/debug/Tests/phpt/fatal_with_nested_handlers.phpt @@ -7,7 +7,7 @@ namespace Symfony\Component\Debug; $vendor = __DIR__; while (!file_exists($vendor.'/vendor')) { - $vendor = dirname($vendor); + $vendor = \dirname($vendor); } require $vendor.'/vendor/autoload.php'; @@ -17,14 +17,14 @@ ini_set('display_errors', 0); $eHandler = set_error_handler('var_dump'); $xHandler = set_exception_handler('var_dump'); -var_dump(array( +var_dump([ $eHandler[0] === $xHandler[0] ? 'Error and exception handlers do match' : 'Error and exception handlers are different', -)); +]); $eHandler[0]->setExceptionHandler('print_r'); if (true) { - class Broken implements \Serializable + class Broken implements \JsonSerializable { } } @@ -37,6 +37,6 @@ array(1) { } object(Symfony\Component\Debug\Exception\FatalErrorException)#%d (%d) { ["message":protected]=> - string(199) "Error: Class Symfony\Component\Debug\Broken contains 2 abstract methods and must therefore be declared abstract or implement the remaining methods (Serializable::serialize, Serializable::unserialize)" + string(179) "Error: Class Symfony\Component\Debug\Broken contains 1 abstract method and must therefore be declared abstract or implement the remaining methods (JsonSerializable::jsonSerialize)" %a } diff --git a/vendor/symfony/debug/composer.json b/vendor/symfony/debug/composer.json index f98a5d07b5d6cd3952141261ed911cf62b6de231..7fd5ff9c93ab8825f606540ed9892765a7948af6 100644 --- a/vendor/symfony/debug/composer.json +++ b/vendor/symfony/debug/composer.json @@ -16,14 +16,14 @@ } ], "require": { - "php": "^5.5.9|>=7.0.8", + "php": "^7.1.3", "psr/log": "~1.0" }, "conflict": { - "symfony/http-kernel": ">=2.3,<2.3.24|~2.4.0|>=2.5,<2.5.9|>=2.6,<2.6.2" + "symfony/http-kernel": "<3.4" }, "require-dev": { - "symfony/http-kernel": "~2.8|~3.0|~4.0" + "symfony/http-kernel": "~3.4|~4.0" }, "autoload": { "psr-4": { "Symfony\\Component\\Debug\\": "" }, @@ -34,7 +34,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-master": "3.4-dev" + "dev-master": "4.3-dev" } } } diff --git a/vendor/symfony/debug/phpunit.xml.dist b/vendor/symfony/debug/phpunit.xml.dist index 12e58612bc5f585d43ce911f823a63c1339b2883..a51bbff93586161a8a8438e6765626d75ecfcb82 100644 --- a/vendor/symfony/debug/phpunit.xml.dist +++ b/vendor/symfony/debug/phpunit.xml.dist @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="UTF-8"?> <phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/4.1/phpunit.xsd" + xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/5.2/phpunit.xsd" backupGlobals="false" colors="true" bootstrap="vendor/autoload.php" diff --git a/vendor/symfony/event-dispatcher-contracts/.gitignore b/vendor/symfony/event-dispatcher-contracts/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..c49a5d8df5c6548379f00c77fe572a7217bce218 --- /dev/null +++ b/vendor/symfony/event-dispatcher-contracts/.gitignore @@ -0,0 +1,3 @@ +vendor/ +composer.lock +phpunit.xml diff --git a/vendor/symfony/event-dispatcher-contracts/Event.php b/vendor/symfony/event-dispatcher-contracts/Event.php new file mode 100644 index 0000000000000000000000000000000000000000..84f60f3ed0460ca1b1be1ba742b81c1a2a136e40 --- /dev/null +++ b/vendor/symfony/event-dispatcher-contracts/Event.php @@ -0,0 +1,96 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Contracts\EventDispatcher; + +use Psr\EventDispatcher\StoppableEventInterface; + +if (interface_exists(StoppableEventInterface::class)) { + /** + * Event is the base class for classes containing event data. + * + * This class contains no event data. It is used by events that do not pass + * state information to an event handler when an event is raised. + * + * You can call the method stopPropagation() to abort the execution of + * further listeners in your event listener. + * + * @author Guilherme Blanco <guilhermeblanco@hotmail.com> + * @author Jonathan Wage <jonwage@gmail.com> + * @author Roman Borschel <roman@code-factory.org> + * @author Bernhard Schussek <bschussek@gmail.com> + * @author Nicolas Grekas <p@tchwork.com> + */ + class Event implements StoppableEventInterface + { + private $propagationStopped = false; + + /** + * Returns whether further event listeners should be triggered. + */ + public function isPropagationStopped(): bool + { + return $this->propagationStopped; + } + + /** + * Stops the propagation of the event to further event listeners. + * + * If multiple event listeners are connected to the same event, no + * further event listener will be triggered once any trigger calls + * stopPropagation(). + */ + public function stopPropagation(): void + { + $this->propagationStopped = true; + } + } +} else { + /** + * Event is the base class for classes containing event data. + * + * This class contains no event data. It is used by events that do not pass + * state information to an event handler when an event is raised. + * + * You can call the method stopPropagation() to abort the execution of + * further listeners in your event listener. + * + * @author Guilherme Blanco <guilhermeblanco@hotmail.com> + * @author Jonathan Wage <jonwage@gmail.com> + * @author Roman Borschel <roman@code-factory.org> + * @author Bernhard Schussek <bschussek@gmail.com> + * @author Nicolas Grekas <p@tchwork.com> + */ + class Event + { + private $propagationStopped = false; + + /** + * Returns whether further event listeners should be triggered. + */ + public function isPropagationStopped(): bool + { + return $this->propagationStopped; + } + + /** + * Stops the propagation of the event to further event listeners. + * + * If multiple event listeners are connected to the same event, no + * further event listener will be triggered once any trigger calls + * stopPropagation(). + */ + public function stopPropagation(): void + { + $this->propagationStopped = true; + } + } +} diff --git a/vendor/symfony/event-dispatcher-contracts/EventDispatcherInterface.php b/vendor/symfony/event-dispatcher-contracts/EventDispatcherInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..2d470af92006c4915440e95a6c90fedeb05b3f00 --- /dev/null +++ b/vendor/symfony/event-dispatcher-contracts/EventDispatcherInterface.php @@ -0,0 +1,58 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Contracts\EventDispatcher; + +use Psr\EventDispatcher\EventDispatcherInterface as PsrEventDispatcherInterface; + +if (interface_exists(PsrEventDispatcherInterface::class)) { + /** + * Allows providing hooks on domain-specific lifecycles by dispatching events. + */ + interface EventDispatcherInterface extends PsrEventDispatcherInterface + { + /** + * Dispatches an event to all registered listeners. + * + * For BC with Symfony 4, the $eventName argument is not declared explicitly on the + * signature of the method. Implementations that are not bound by this BC constraint + * MUST declare it explicitly, as allowed by PHP. + * + * @param object $event The event to pass to the event handlers/listeners + * @param string|null $eventName The name of the event to dispatch. If not supplied, + * the class of $event should be used instead. + * + * @return object The passed $event MUST be returned + */ + public function dispatch($event/*, string $eventName = null*/); + } +} else { + /** + * Allows providing hooks on domain-specific lifecycles by dispatching events. + */ + interface EventDispatcherInterface + { + /** + * Dispatches an event to all registered listeners. + * + * For BC with Symfony 4, the $eventName argument is not declared explicitly on the + * signature of the method. Implementations that are not bound by this BC constraint + * MUST declare it explicitly, as allowed by PHP. + * + * @param object $event The event to pass to the event handlers/listeners + * @param string|null $eventName The name of the event to dispatch. If not supplied, + * the class of $event should be used instead. + * + * @return object The passed $event MUST be returned + */ + public function dispatch($event/*, string $eventName = null*/); + } +} diff --git a/vendor/symfony/polyfill-php70/LICENSE b/vendor/symfony/event-dispatcher-contracts/LICENSE similarity index 96% rename from vendor/symfony/polyfill-php70/LICENSE rename to vendor/symfony/event-dispatcher-contracts/LICENSE index 24fa32c2e9b27aef3eac523f0042b8ab9ba81944..3f853aaf35fe186d4016761eb6e8a403de3e6e0d 100644 --- a/vendor/symfony/polyfill-php70/LICENSE +++ b/vendor/symfony/event-dispatcher-contracts/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2015-2018 Fabien Potencier +Copyright (c) 2018-2019 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/vendor/symfony/event-dispatcher-contracts/README.md b/vendor/symfony/event-dispatcher-contracts/README.md new file mode 100644 index 0000000000000000000000000000000000000000..fb051c73fc74eae97b6f896f051955aa08f7ea38 --- /dev/null +++ b/vendor/symfony/event-dispatcher-contracts/README.md @@ -0,0 +1,9 @@ +Symfony EventDispatcher Contracts +================================= + +A set of abstractions extracted out of the Symfony components. + +Can be used to build on semantics that the Symfony components proved useful - and +that already have battle tested implementations. + +See https://github.com/symfony/contracts/blob/master/README.md for more information. diff --git a/vendor/symfony/event-dispatcher-contracts/composer.json b/vendor/symfony/event-dispatcher-contracts/composer.json new file mode 100644 index 0000000000000000000000000000000000000000..55802a491da69760a25da9ca69d36f1c33298ed7 --- /dev/null +++ b/vendor/symfony/event-dispatcher-contracts/composer.json @@ -0,0 +1,34 @@ +{ + "name": "symfony/event-dispatcher-contracts", + "type": "library", + "description": "Generic abstractions related to dispatching event", + "keywords": ["abstractions", "contracts", "decoupling", "interfaces", "interoperability", "standards"], + "homepage": "https://symfony.com", + "license": "MIT", + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "require": { + "php": "^7.1.3" + }, + "suggest": { + "psr/event-dispatcher": "", + "symfony/event-dispatcher-implementation": "" + }, + "autoload": { + "psr-4": { "Symfony\\Contracts\\EventDispatcher\\": "" } + }, + "minimum-stability": "dev", + "extra": { + "branch-alias": { + "dev-master": "1.1-dev" + } + } +} diff --git a/vendor/symfony/event-dispatcher/CHANGELOG.md b/vendor/symfony/event-dispatcher/CHANGELOG.md index c6aa5389ac724812183ba3defea3e9466c2fca78..7653cad1c0eb0ccd330253e6b6e24c237b57a534 100644 --- a/vendor/symfony/event-dispatcher/CHANGELOG.md +++ b/vendor/symfony/event-dispatcher/CHANGELOG.md @@ -1,6 +1,25 @@ CHANGELOG ========= +4.3.0 +----- + + * The signature of the `EventDispatcherInterface::dispatch()` method should be updated to `dispatch($event, string $eventName = null)`, not doing so is deprecated + * deprecated the `Event` class, use `Symfony\Contracts\EventDispatcher\Event` instead + +4.1.0 +----- + + * added support for invokable event listeners tagged with `kernel.event_listener` by default + * The `TraceableEventDispatcher::getOrphanedEvents()` method has been added. + * The `TraceableEventDispatcherInterface` has been deprecated. + +4.0.0 +----- + + * removed the `ContainerAwareEventDispatcher` class + * added the `reset()` method to the `TraceableEventDispatcherInterface` + 3.4.0 ----- diff --git a/vendor/symfony/event-dispatcher/ContainerAwareEventDispatcher.php b/vendor/symfony/event-dispatcher/ContainerAwareEventDispatcher.php deleted file mode 100644 index 81a1ff7caf7b2de6b82d5fbbf5bebd1a5bb9b7ea..0000000000000000000000000000000000000000 --- a/vendor/symfony/event-dispatcher/ContainerAwareEventDispatcher.php +++ /dev/null @@ -1,197 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\EventDispatcher; - -use Symfony\Component\DependencyInjection\ContainerInterface; - -/** - * Lazily loads listeners and subscribers from the dependency injection - * container. - * - * @author Fabien Potencier <fabien@symfony.com> - * @author Bernhard Schussek <bschussek@gmail.com> - * @author Jordan Alliot <jordan.alliot@gmail.com> - * - * @deprecated since 3.3, to be removed in 4.0. Use EventDispatcher with closure factories instead. - */ -class ContainerAwareEventDispatcher extends EventDispatcher -{ - private $container; - - /** - * The service IDs of the event listeners and subscribers. - */ - private $listenerIds = array(); - - /** - * The services registered as listeners. - */ - private $listeners = array(); - - public function __construct(ContainerInterface $container) - { - $this->container = $container; - - $class = get_class($this); - if ($this instanceof \PHPUnit_Framework_MockObject_MockObject || $this instanceof \Prophecy\Doubler\DoubleInterface) { - $class = get_parent_class($class); - } - if (__CLASS__ !== $class) { - @trigger_error(sprintf('The %s class is deprecated since Symfony 3.3 and will be removed in 4.0. Use EventDispatcher with closure factories instead.', __CLASS__), E_USER_DEPRECATED); - } - } - - /** - * Adds a service as event listener. - * - * @param string $eventName Event for which the listener is added - * @param array $callback The service ID of the listener service & the method - * name that has to be called - * @param int $priority The higher this value, the earlier an event listener - * will be triggered in the chain. - * Defaults to 0. - * - * @throws \InvalidArgumentException - */ - public function addListenerService($eventName, $callback, $priority = 0) - { - @trigger_error(sprintf('The %s class is deprecated since Symfony 3.3 and will be removed in 4.0. Use EventDispatcher with closure factories instead.', __CLASS__), E_USER_DEPRECATED); - - if (!is_array($callback) || 2 !== count($callback)) { - throw new \InvalidArgumentException('Expected an array("service", "method") argument'); - } - - $this->listenerIds[$eventName][] = array($callback[0], $callback[1], $priority); - } - - public function removeListener($eventName, $listener) - { - $this->lazyLoad($eventName); - - if (isset($this->listenerIds[$eventName])) { - foreach ($this->listenerIds[$eventName] as $i => list($serviceId, $method)) { - $key = $serviceId.'.'.$method; - if (isset($this->listeners[$eventName][$key]) && $listener === array($this->listeners[$eventName][$key], $method)) { - unset($this->listeners[$eventName][$key]); - if (empty($this->listeners[$eventName])) { - unset($this->listeners[$eventName]); - } - unset($this->listenerIds[$eventName][$i]); - if (empty($this->listenerIds[$eventName])) { - unset($this->listenerIds[$eventName]); - } - } - } - } - - parent::removeListener($eventName, $listener); - } - - /** - * {@inheritdoc} - */ - public function hasListeners($eventName = null) - { - if (null === $eventName) { - return $this->listenerIds || $this->listeners || parent::hasListeners(); - } - - if (isset($this->listenerIds[$eventName])) { - return true; - } - - return parent::hasListeners($eventName); - } - - /** - * {@inheritdoc} - */ - public function getListeners($eventName = null) - { - if (null === $eventName) { - foreach ($this->listenerIds as $serviceEventName => $args) { - $this->lazyLoad($serviceEventName); - } - } else { - $this->lazyLoad($eventName); - } - - return parent::getListeners($eventName); - } - - /** - * {@inheritdoc} - */ - public function getListenerPriority($eventName, $listener) - { - $this->lazyLoad($eventName); - - return parent::getListenerPriority($eventName, $listener); - } - - /** - * Adds a service as event subscriber. - * - * @param string $serviceId The service ID of the subscriber service - * @param string $class The service's class name (which must implement EventSubscriberInterface) - */ - public function addSubscriberService($serviceId, $class) - { - @trigger_error(sprintf('The %s class is deprecated since Symfony 3.3 and will be removed in 4.0. Use EventDispatcher with closure factories instead.', __CLASS__), E_USER_DEPRECATED); - - foreach ($class::getSubscribedEvents() as $eventName => $params) { - if (is_string($params)) { - $this->listenerIds[$eventName][] = array($serviceId, $params, 0); - } elseif (is_string($params[0])) { - $this->listenerIds[$eventName][] = array($serviceId, $params[0], isset($params[1]) ? $params[1] : 0); - } else { - foreach ($params as $listener) { - $this->listenerIds[$eventName][] = array($serviceId, $listener[0], isset($listener[1]) ? $listener[1] : 0); - } - } - } - } - - public function getContainer() - { - @trigger_error('The '.__METHOD__.'() method is deprecated since Symfony 3.3 as its class will be removed in 4.0. Inject the container or the services you need in your listeners/subscribers instead.', E_USER_DEPRECATED); - - return $this->container; - } - - /** - * Lazily loads listeners for this event from the dependency injection - * container. - * - * @param string $eventName The name of the event to dispatch. The name of - * the event is the name of the method that is - * invoked on listeners. - */ - protected function lazyLoad($eventName) - { - if (isset($this->listenerIds[$eventName])) { - foreach ($this->listenerIds[$eventName] as list($serviceId, $method, $priority)) { - $listener = $this->container->get($serviceId); - - $key = $serviceId.'.'.$method; - if (!isset($this->listeners[$eventName][$key])) { - $this->addListener($eventName, array($listener, $method), $priority); - } elseif ($this->listeners[$eventName][$key] !== $listener) { - parent::removeListener($eventName, array($this->listeners[$eventName][$key], $method)); - $this->addListener($eventName, array($listener, $method), $priority); - } - - $this->listeners[$eventName][$key] = $listener; - } - } - } -} diff --git a/vendor/symfony/event-dispatcher/Debug/TraceableEventDispatcher.php b/vendor/symfony/event-dispatcher/Debug/TraceableEventDispatcher.php index 9b5c689ad7137d302c362e7fc9dfaaf627ee19d2..513c6ade6d9a7ac761f6ffb98b922cc221b7d71d 100644 --- a/vendor/symfony/event-dispatcher/Debug/TraceableEventDispatcher.php +++ b/vendor/symfony/event-dispatcher/Debug/TraceableEventDispatcher.php @@ -11,11 +11,17 @@ namespace Symfony\Component\EventDispatcher\Debug; +use Psr\EventDispatcher\StoppableEventInterface; +use Psr\Log\LoggerInterface; +use Symfony\Component\EventDispatcher\Event; use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\EventDispatcher\EventSubscriberInterface; -use Symfony\Component\EventDispatcher\Event; +use Symfony\Component\EventDispatcher\LegacyEventDispatcherProxy; +use Symfony\Component\EventDispatcher\LegacyEventProxy; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\Stopwatch\Stopwatch; -use Psr\Log\LoggerInterface; +use Symfony\Contracts\EventDispatcher\Event as ContractsEvent; /** * Collects some data about event listeners. @@ -29,17 +35,21 @@ class TraceableEventDispatcher implements TraceableEventDispatcherInterface protected $logger; protected $stopwatch; - private $called; + private $callStack; private $dispatcher; private $wrappedListeners; + private $orphanedEvents; + private $requestStack; + private $currentRequestHash = ''; - public function __construct(EventDispatcherInterface $dispatcher, Stopwatch $stopwatch, LoggerInterface $logger = null) + public function __construct(EventDispatcherInterface $dispatcher, Stopwatch $stopwatch, LoggerInterface $logger = null, RequestStack $requestStack = null) { - $this->dispatcher = $dispatcher; + $this->dispatcher = LegacyEventDispatcherProxy::decorate($dispatcher); $this->stopwatch = $stopwatch; $this->logger = $logger; - $this->called = array(); - $this->wrappedListeners = array(); + $this->wrappedListeners = []; + $this->orphanedEvents = []; + $this->requestStack = $requestStack; } /** @@ -120,43 +130,75 @@ class TraceableEventDispatcher implements TraceableEventDispatcherInterface /** * {@inheritdoc} + * + * @param string|null $eventName */ - public function dispatch($eventName, Event $event = null) + public function dispatch($event/*, string $eventName = null*/) { - if (null === $event) { - $event = new Event(); - } - - if (null !== $this->logger && $event->isPropagationStopped()) { - $this->logger->debug(sprintf('The "%s" event is already stopped. No listeners have been called.', $eventName)); + if (null === $this->callStack) { + $this->callStack = new \SplObjectStorage(); } - $this->preProcess($eventName); - $this->preDispatch($eventName, $event); + $currentRequestHash = $this->currentRequestHash = $this->requestStack && ($request = $this->requestStack->getCurrentRequest()) ? spl_object_hash($request) : ''; + $eventName = 1 < \func_num_args() ? func_get_arg(1) : null; - $e = $this->stopwatch->start($eventName, 'section'); + if (\is_object($event)) { + $eventName = $eventName ?? \get_class($event); + } else { + @trigger_error(sprintf('Calling the "%s::dispatch()" method with the event name as first argument is deprecated since Symfony 4.3, pass it second and provide the event object first instead.', EventDispatcherInterface::class), E_USER_DEPRECATED); + $swap = $event; + $event = $eventName ?? new Event(); + $eventName = $swap; - $this->dispatcher->dispatch($eventName, $event); + if (!$event instanceof Event) { + throw new \TypeError(sprintf('Argument 1 passed to "%s::dispatch()" must be an instance of %s, %s given.', EventDispatcherInterface::class, Event::class, \is_object($event) ? \get_class($event) : \gettype($event))); + } + } - if ($e->isStarted()) { - $e->stop(); + if (null !== $this->logger && ($event instanceof Event || $event instanceof ContractsEvent || $event instanceof StoppableEventInterface) && $event->isPropagationStopped()) { + $this->logger->debug(sprintf('The "%s" event is already stopped. No listeners have been called.', $eventName)); } - $this->postDispatch($eventName, $event); - $this->postProcess($eventName); + $this->preProcess($eventName); + try { + $this->beforeDispatch($eventName, $event); + try { + $e = $this->stopwatch->start($eventName, 'section'); + try { + $this->dispatcher->dispatch($event, $eventName); + } finally { + if ($e->isStarted()) { + $e->stop(); + } + } + } finally { + $this->afterDispatch($eventName, $event); + } + } finally { + $this->currentRequestHash = $currentRequestHash; + $this->postProcess($eventName); + } return $event; } /** * {@inheritdoc} + * + * @param Request|null $request The request to get listeners for */ - public function getCalledListeners() + public function getCalledListeners(/* Request $request = null */) { - $called = array(); - foreach ($this->called as $eventName => $listeners) { - foreach ($listeners as $listener) { - $called[$eventName.'.'.$listener->getPretty()] = $listener->getInfo($eventName); + if (null === $this->callStack) { + return []; + } + + $hash = 1 <= \func_num_args() && null !== ($request = func_get_arg(0)) ? spl_object_hash($request) : null; + $called = []; + foreach ($this->callStack as $listener) { + list($eventName, $requestHash) = $this->callStack->getInfo(); + if (null === $hash || $hash === $requestHash) { + $called[] = $listener->getInfo($eventName); } } @@ -165,51 +207,73 @@ class TraceableEventDispatcher implements TraceableEventDispatcherInterface /** * {@inheritdoc} + * + * @param Request|null $request The request to get listeners for */ - public function getNotCalledListeners() + public function getNotCalledListeners(/* Request $request = null */) { try { $allListeners = $this->getListeners(); } catch (\Exception $e) { if (null !== $this->logger) { - $this->logger->info('An exception was thrown while getting the uncalled listeners.', array('exception' => $e)); + $this->logger->info('An exception was thrown while getting the uncalled listeners.', ['exception' => $e]); } // unable to retrieve the uncalled listeners - return array(); + return []; } - $notCalled = array(); - foreach ($allListeners as $eventName => $listeners) { - foreach ($listeners as $listener) { - $called = false; - if (isset($this->called[$eventName])) { - foreach ($this->called[$eventName] as $l) { - if ($l->getWrappedListener() === $listener) { - $called = true; - - break; - } - } + $hash = 1 <= \func_num_args() && null !== ($request = func_get_arg(0)) ? spl_object_hash($request) : null; + $calledListeners = []; + + if (null !== $this->callStack) { + foreach ($this->callStack as $calledListener) { + list(, $requestHash) = $this->callStack->getInfo(); + + if (null === $hash || $hash === $requestHash) { + $calledListeners[] = $calledListener->getWrappedListener(); } + } + } - if (!$called) { + $notCalled = []; + foreach ($allListeners as $eventName => $listeners) { + foreach ($listeners as $listener) { + if (!\in_array($listener, $calledListeners, true)) { if (!$listener instanceof WrappedListener) { $listener = new WrappedListener($listener, null, $this->stopwatch, $this); } - $notCalled[$eventName.'.'.$listener->getPretty()] = $listener->getInfo($eventName); + $notCalled[] = $listener->getInfo($eventName); } } } - uasort($notCalled, array($this, 'sortListenersByPriority')); + uasort($notCalled, [$this, 'sortNotCalledListeners']); return $notCalled; } + /** + * @param Request|null $request The request to get orphaned events for + */ + public function getOrphanedEvents(/* Request $request = null */): array + { + if (1 <= \func_num_args() && null !== $request = func_get_arg(0)) { + return $this->orphanedEvents[spl_object_hash($request)] ?? []; + } + + if (!$this->orphanedEvents) { + return []; + } + + return array_merge(...array_values($this->orphanedEvents)); + } + public function reset() { - $this->called = array(); + $this->callStack = null; + $this->orphanedEvents = []; + $this->currentRequestHash = ''; } /** @@ -222,24 +286,38 @@ class TraceableEventDispatcher implements TraceableEventDispatcherInterface */ public function __call($method, $arguments) { - return call_user_func_array(array($this->dispatcher, $method), $arguments); + return $this->dispatcher->{$method}(...$arguments); } /** * Called before dispatching the event. * - * @param string $eventName The event name - * @param Event $event The event + * @param object $event */ - protected function preDispatch($eventName, Event $event) + protected function beforeDispatch(string $eventName, $event) { + $this->preDispatch($eventName, $event instanceof Event ? $event : new LegacyEventProxy($event)); } /** * Called after dispatching the event. * - * @param string $eventName The event name - * @param Event $event The event + * @param object $event + */ + protected function afterDispatch(string $eventName, $event) + { + $this->postDispatch($eventName, $event instanceof Event ? $event : new LegacyEventProxy($event)); + } + + /** + * @deprecated since Symfony 4.3, will be removed in 5.0, use beforeDispatch instead + */ + protected function preDispatch($eventName, Event $event) + { + } + + /** + * @deprecated since Symfony 4.3, will be removed in 5.0, use afterDispatch instead */ protected function postDispatch($eventName, Event $event) { @@ -247,12 +325,19 @@ class TraceableEventDispatcher implements TraceableEventDispatcherInterface private function preProcess($eventName) { + if (!$this->dispatcher->hasListeners($eventName)) { + $this->orphanedEvents[$this->currentRequestHash][] = $eventName; + + return; + } + foreach ($this->dispatcher->getListeners($eventName) as $listener) { $priority = $this->getListenerPriority($eventName, $listener); - $wrappedListener = new WrappedListener($listener, null, $this->stopwatch, $this); + $wrappedListener = new WrappedListener($listener instanceof WrappedListener ? $listener->getWrappedListener() : $listener, null, $this->stopwatch, $this); $this->wrappedListeners[$eventName][] = $wrappedListener; $this->dispatcher->removeListener($eventName, $listener); $this->dispatcher->addListener($eventName, $wrappedListener, $priority); + $this->callStack->attach($wrappedListener, [$eventName, $this->currentRequestHash]); } } @@ -270,19 +355,15 @@ class TraceableEventDispatcher implements TraceableEventDispatcherInterface $this->dispatcher->addListener($eventName, $listener->getWrappedListener(), $priority); if (null !== $this->logger) { - $context = array('event' => $eventName, 'listener' => $listener->getPretty()); + $context = ['event' => $eventName, 'listener' => $listener->getPretty()]; } if ($listener->wasCalled()) { if (null !== $this->logger) { $this->logger->debug('Notified event "{event}" to listener "{listener}".', $context); } - - if (!isset($this->called[$eventName])) { - $this->called[$eventName] = new \SplObjectStorage(); - } - - $this->called[$eventName]->attach($listener); + } else { + $this->callStack->detach($listener); } if (null !== $this->logger && $skipped) { @@ -299,13 +380,17 @@ class TraceableEventDispatcher implements TraceableEventDispatcherInterface } } - private function sortListenersByPriority($a, $b) + private function sortNotCalledListeners(array $a, array $b) { - if (is_int($a['priority']) && !is_int($b['priority'])) { + if (0 !== $cmp = strcmp($a['event'], $b['event'])) { + return $cmp; + } + + if (\is_int($a['priority']) && !\is_int($b['priority'])) { return 1; } - if (!is_int($a['priority']) && is_int($b['priority'])) { + if (!\is_int($a['priority']) && \is_int($b['priority'])) { return -1; } diff --git a/vendor/symfony/event-dispatcher/Debug/TraceableEventDispatcherInterface.php b/vendor/symfony/event-dispatcher/Debug/TraceableEventDispatcherInterface.php index f0212753be5918bce203b5cc1ab4b159e7869d41..4fedb9a413a3bd1fdbcbb83c276e5e889195d6d6 100644 --- a/vendor/symfony/event-dispatcher/Debug/TraceableEventDispatcherInterface.php +++ b/vendor/symfony/event-dispatcher/Debug/TraceableEventDispatcherInterface.php @@ -12,25 +12,31 @@ namespace Symfony\Component\EventDispatcher\Debug; use Symfony\Component\EventDispatcher\EventDispatcherInterface; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Contracts\Service\ResetInterface; /** - * @author Fabien Potencier <fabien@symfony.com> + * @deprecated since Symfony 4.1 * - * @method reset() Resets the trace. + * @author Fabien Potencier <fabien@symfony.com> */ -interface TraceableEventDispatcherInterface extends EventDispatcherInterface +interface TraceableEventDispatcherInterface extends EventDispatcherInterface, ResetInterface { /** * Gets the called listeners. * + * @param Request|null $request The request to get listeners for + * * @return array An array of called listeners */ - public function getCalledListeners(); + public function getCalledListeners(/* Request $request = null */); /** * Gets the not called listeners. * + * @param Request|null $request The request to get listeners for + * * @return array An array of not called listeners */ - public function getNotCalledListeners(); + public function getNotCalledListeners(/* Request $request = null */); } diff --git a/vendor/symfony/event-dispatcher/Debug/WrappedListener.php b/vendor/symfony/event-dispatcher/Debug/WrappedListener.php index f7b0273e15aaa88e685d31bb76c340de15eba246..e047639081c78173175af0af1836d4af4f2c47d3 100644 --- a/vendor/symfony/event-dispatcher/Debug/WrappedListener.php +++ b/vendor/symfony/event-dispatcher/Debug/WrappedListener.php @@ -11,17 +11,23 @@ namespace Symfony\Component\EventDispatcher\Debug; -use Symfony\Component\Stopwatch\Stopwatch; +use Psr\EventDispatcher\StoppableEventInterface; use Symfony\Component\EventDispatcher\Event; use Symfony\Component\EventDispatcher\EventDispatcherInterface; +use Symfony\Component\EventDispatcher\LegacyEventProxy; +use Symfony\Component\Stopwatch\Stopwatch; use Symfony\Component\VarDumper\Caster\ClassStub; +use Symfony\Contracts\EventDispatcher\Event as ContractsEvent; /** * @author Fabien Potencier <fabien@symfony.com> + * + * @final since Symfony 4.3: the "Event" type-hint on __invoke() will be replaced by "object" in 5.0 */ class WrappedListener { private $listener; + private $optimizedListener; private $name; private $called; private $stoppedPropagation; @@ -29,26 +35,35 @@ class WrappedListener private $dispatcher; private $pretty; private $stub; + private $priority; private static $hasClassStub; - public function __construct($listener, $name, Stopwatch $stopwatch, EventDispatcherInterface $dispatcher = null) + public function __construct($listener, ?string $name, Stopwatch $stopwatch, EventDispatcherInterface $dispatcher = null) { $this->listener = $listener; - $this->name = $name; + $this->optimizedListener = $listener instanceof \Closure ? $listener : (\is_callable($listener) ? \Closure::fromCallable($listener) : null); $this->stopwatch = $stopwatch; $this->dispatcher = $dispatcher; $this->called = false; $this->stoppedPropagation = false; - if (is_array($listener)) { - $this->name = is_object($listener[0]) ? get_class($listener[0]) : $listener[0]; + if (\is_array($listener)) { + $this->name = \is_object($listener[0]) ? \get_class($listener[0]) : $listener[0]; $this->pretty = $this->name.'::'.$listener[1]; } elseif ($listener instanceof \Closure) { - $this->pretty = $this->name = 'closure'; - } elseif (is_string($listener)) { + $r = new \ReflectionFunction($listener); + if (false !== strpos($r->name, '{closure}')) { + $this->pretty = $this->name = 'closure'; + } elseif ($class = $r->getClosureScopeClass()) { + $this->name = $class->name; + $this->pretty = $this->name.'::'.$r->name; + } else { + $this->pretty = $this->name = $r->name; + } + } elseif (\is_string($listener)) { $this->pretty = $this->name = $listener; } else { - $this->name = get_class($listener); + $this->name = \get_class($listener); $this->pretty = $this->name.'::__invoke'; } @@ -87,27 +102,34 @@ class WrappedListener $this->stub = self::$hasClassStub ? new ClassStub($this->pretty.'()', $this->listener) : $this->pretty.'()'; } - return array( + return [ 'event' => $eventName, - 'priority' => null !== $this->dispatcher ? $this->dispatcher->getListenerPriority($eventName, $this->listener) : null, + 'priority' => null !== $this->priority ? $this->priority : (null !== $this->dispatcher ? $this->dispatcher->getListenerPriority($eventName, $this->listener) : null), 'pretty' => $this->pretty, 'stub' => $this->stub, - ); + ]; } public function __invoke(Event $event, $eventName, EventDispatcherInterface $dispatcher) { + if ($event instanceof LegacyEventProxy) { + $event = $event->getEvent(); + } + + $dispatcher = $this->dispatcher ?: $dispatcher; + $this->called = true; + $this->priority = $dispatcher->getListenerPriority($eventName, $this->listener); $e = $this->stopwatch->start($this->name, 'event_listener'); - call_user_func($this->listener, $event, $eventName, $this->dispatcher ?: $dispatcher); + ($this->optimizedListener ?? $this->listener)($event, $eventName, $dispatcher); if ($e->isStarted()) { $e->stop(); } - if ($event->isPropagationStopped()) { + if (($event instanceof Event || $event instanceof ContractsEvent || $event instanceof StoppableEventInterface) && $event->isPropagationStopped()) { $this->stoppedPropagation = true; } } diff --git a/vendor/symfony/event-dispatcher/DependencyInjection/RegisterListenersPass.php b/vendor/symfony/event-dispatcher/DependencyInjection/RegisterListenersPass.php index 9f9c09c52803554d3160b4480e2626d8b902220c..3e6493eb83f0aa1d51d9596c3e3b2f8e368d97f8 100644 --- a/vendor/symfony/event-dispatcher/DependencyInjection/RegisterListenersPass.php +++ b/vendor/symfony/event-dispatcher/DependencyInjection/RegisterListenersPass.php @@ -12,8 +12,8 @@ namespace Symfony\Component\EventDispatcher\DependencyInjection; use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument; -use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; +use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\EventDispatcher\EventDispatcher; @@ -27,20 +27,17 @@ class RegisterListenersPass implements CompilerPassInterface protected $dispatcherService; protected $listenerTag; protected $subscriberTag; + protected $eventAliasesParameter; - private $hotPathEvents = array(); + private $hotPathEvents = []; private $hotPathTagName; - /** - * @param string $dispatcherService Service name of the event dispatcher in processed container - * @param string $listenerTag Tag name used for listener - * @param string $subscriberTag Tag name used for subscribers - */ - public function __construct($dispatcherService = 'event_dispatcher', $listenerTag = 'kernel.event_listener', $subscriberTag = 'kernel.event_subscriber') + public function __construct(string $dispatcherService = 'event_dispatcher', string $listenerTag = 'kernel.event_listener', string $subscriberTag = 'kernel.event_subscriber', string $eventAliasesParameter = 'event_dispatcher.event_aliases') { $this->dispatcherService = $dispatcherService; $this->listenerTag = $listenerTag; $this->subscriberTag = $subscriberTag; + $this->eventAliasesParameter = $eventAliasesParameter; } public function setHotPathEvents(array $hotPathEvents, $tagName = 'container.hot_path') @@ -57,6 +54,12 @@ class RegisterListenersPass implements CompilerPassInterface return; } + if ($container->hasParameter($this->eventAliasesParameter)) { + $aliases = $container->getParameter($this->eventAliasesParameter); + $container->getParameterBag()->remove($this->eventAliasesParameter); + } else { + $aliases = []; + } $definition = $container->findDefinition($this->dispatcherService); foreach ($container->findTaggedServiceIds($this->listenerTag, true) as $id => $events) { @@ -66,16 +69,21 @@ class RegisterListenersPass implements CompilerPassInterface if (!isset($event['event'])) { throw new InvalidArgumentException(sprintf('Service "%s" must define the "event" attribute on "%s" tags.', $id, $this->listenerTag)); } + $event['event'] = $aliases[$event['event']] ?? $event['event']; if (!isset($event['method'])) { - $event['method'] = 'on'.preg_replace_callback(array( + $event['method'] = 'on'.preg_replace_callback([ '/(?<=\b)[a-z]/i', '/[^a-z0-9]/i', - ), function ($matches) { return strtoupper($matches[0]); }, $event['event']); + ], function ($matches) { return strtoupper($matches[0]); }, $event['event']); $event['method'] = preg_replace('/[^a-z0-9]/i', '', $event['method']); + + if (null !== ($class = $container->getDefinition($id)->getClass()) && ($r = $container->getReflectionClass($class, false)) && !$r->hasMethod($event['method']) && $r->hasMethod('__invoke')) { + $event['method'] = '__invoke'; + } } - $definition->addMethodCall('addListener', array($event['event'], array(new ServiceClosureArgument(new Reference($id)), $event['method']), $priority)); + $definition->addMethodCall('addListener', [$event['event'], [new ServiceClosureArgument(new Reference($id)), $event['method']], $priority]); if (isset($this->hotPathEvents[$event['event']])) { $container->getDefinition($id)->addTag($this->hotPathTagName); @@ -89,29 +97,29 @@ class RegisterListenersPass implements CompilerPassInterface $def = $container->getDefinition($id); // We must assume that the class value has been correctly filled, even if the service is created by a factory - $class = $container->getParameterBag()->resolveValue($def->getClass()); - $interface = 'Symfony\Component\EventDispatcher\EventSubscriberInterface'; - - if (!is_subclass_of($class, $interface)) { - if (!class_exists($class, false)) { - throw new InvalidArgumentException(sprintf('Class "%s" used for service "%s" cannot be found.', $class, $id)); - } + $class = $def->getClass(); - throw new InvalidArgumentException(sprintf('Service "%s" must implement interface "%s".', $id, $interface)); + if (!$r = $container->getReflectionClass($class)) { + throw new InvalidArgumentException(sprintf('Class "%s" used for service "%s" cannot be found.', $class, $id)); + } + if (!$r->isSubclassOf(EventSubscriberInterface::class)) { + throw new InvalidArgumentException(sprintf('Service "%s" must implement interface "%s".', $id, EventSubscriberInterface::class)); } - $container->addObjectResource($class); + $class = $r->name; + ExtractingEventDispatcher::$aliases = $aliases; ExtractingEventDispatcher::$subscriber = $class; $extractingDispatcher->addSubscriber($extractingDispatcher); foreach ($extractingDispatcher->listeners as $args) { - $args[1] = array(new ServiceClosureArgument(new Reference($id)), $args[1]); + $args[1] = [new ServiceClosureArgument(new Reference($id)), $args[1]]; $definition->addMethodCall('addListener', $args); if (isset($this->hotPathEvents[$args[0]])) { - $container->getDefinition($id)->addTag('container.hot_path'); + $container->getDefinition($id)->addTag($this->hotPathTagName); } } - $extractingDispatcher->listeners = array(); + $extractingDispatcher->listeners = []; + ExtractingEventDispatcher::$aliases = []; } } } @@ -121,19 +129,24 @@ class RegisterListenersPass implements CompilerPassInterface */ class ExtractingEventDispatcher extends EventDispatcher implements EventSubscriberInterface { - public $listeners = array(); + public $listeners = []; + public static $aliases = []; public static $subscriber; public function addListener($eventName, $listener, $priority = 0) { - $this->listeners[] = array($eventName, $listener[1], $priority); + $this->listeners[] = [$eventName, $listener[1], $priority]; } public static function getSubscribedEvents() { - $callback = array(self::$subscriber, 'getSubscribedEvents'); + $events = []; + + foreach ([self::$subscriber, 'getSubscribedEvents']() as $eventName => $params) { + $events[self::$aliases[$eventName] ?? $eventName] = $params; + } - return $callback(); + return $events; } } diff --git a/vendor/symfony/event-dispatcher/Event.php b/vendor/symfony/event-dispatcher/Event.php index 9c56b2f55b8a70c8986de919fd3a8311f9f05dd7..307c4be5de0c2ff126834043eb4324b5c6fc92f3 100644 --- a/vendor/symfony/event-dispatcher/Event.php +++ b/vendor/symfony/event-dispatcher/Event.php @@ -12,32 +12,16 @@ namespace Symfony\Component\EventDispatcher; /** - * Event is the base class for classes containing event data. - * - * This class contains no event data. It is used by events that do not pass - * state information to an event handler when an event is raised. - * - * You can call the method stopPropagation() to abort the execution of - * further listeners in your event listener. - * - * @author Guilherme Blanco <guilhermeblanco@hotmail.com> - * @author Jonathan Wage <jonwage@gmail.com> - * @author Roman Borschel <roman@code-factory.org> - * @author Bernhard Schussek <bschussek@gmail.com> + * @deprecated since Symfony 4.3, use "Symfony\Contracts\EventDispatcher\Event" instead */ class Event { - /** - * @var bool Whether no further event listeners should be triggered - */ private $propagationStopped = false; /** - * Returns whether further event listeners should be triggered. - * - * @see Event::stopPropagation() - * * @return bool Whether propagation was already stopped for this event + * + * @deprecated since Symfony 4.3, use "Symfony\Contracts\EventDispatcher\Event" instead */ public function isPropagationStopped() { @@ -45,11 +29,7 @@ class Event } /** - * Stops the propagation of the event to further event listeners. - * - * If multiple event listeners are connected to the same event, no - * further event listener will be triggered once any trigger calls - * stopPropagation(). + * @deprecated since Symfony 4.3, use "Symfony\Contracts\EventDispatcher\Event" instead */ public function stopPropagation() { diff --git a/vendor/symfony/event-dispatcher/EventDispatcher.php b/vendor/symfony/event-dispatcher/EventDispatcher.php index bc79a958da127ba019cc3a7f7defb0f887fbde5c..ebfd1ec6d5e7d6f585f03e7f5ce0a440c09877ec 100644 --- a/vendor/symfony/event-dispatcher/EventDispatcher.php +++ b/vendor/symfony/event-dispatcher/EventDispatcher.php @@ -11,6 +11,10 @@ namespace Symfony\Component\EventDispatcher; +use Psr\EventDispatcher\StoppableEventInterface; +use Symfony\Component\EventDispatcher\Debug\WrappedListener; +use Symfony\Contracts\EventDispatcher\Event as ContractsEvent; + /** * The EventDispatcherInterface is the central point of Symfony's event listener system. * @@ -28,20 +32,45 @@ namespace Symfony\Component\EventDispatcher; */ class EventDispatcher implements EventDispatcherInterface { - private $listeners = array(); - private $sorted = array(); + private $listeners = []; + private $sorted = []; + private $optimized; + + public function __construct() + { + if (__CLASS__ === \get_class($this)) { + $this->optimized = []; + } + } /** * {@inheritdoc} + * + * @param string|null $eventName */ - public function dispatch($eventName, Event $event = null) + public function dispatch($event/*, string $eventName = null*/) { - if (null === $event) { - $event = new Event(); + $eventName = 1 < \func_num_args() ? func_get_arg(1) : null; + + if (\is_object($event)) { + $eventName = $eventName ?? \get_class($event); + } elseif (\is_string($event) && (null === $eventName || $eventName instanceof Event)) { + @trigger_error(sprintf('Calling the "%s::dispatch()" method with the event name as the first argument is deprecated since Symfony 4.3, pass it as the second argument and provide the event object as the first argument instead.', EventDispatcherInterface::class), E_USER_DEPRECATED); + $swap = $event; + $event = $eventName ?? new Event(); + $eventName = $swap; + } else { + throw new \TypeError(sprintf('Argument 1 passed to "%s::dispatch()" must be an object, %s given.', EventDispatcherInterface::class, \is_object($event) ? \get_class($event) : \gettype($event))); } - if ($listeners = $this->getListeners($eventName)) { - $this->doDispatch($listeners, $eventName, $event); + if (null !== $this->optimized && null !== $eventName) { + $listeners = $this->optimized[$eventName] ?? (empty($this->listeners[$eventName]) ? [] : $this->optimizeListeners($eventName)); + } else { + $listeners = $this->getListeners($eventName); + } + + if ($listeners) { + $this->callListeners($listeners, $eventName, $event); } return $event; @@ -54,7 +83,7 @@ class EventDispatcher implements EventDispatcherInterface { if (null !== $eventName) { if (empty($this->listeners[$eventName])) { - return array(); + return []; } if (!isset($this->sorted[$eventName])) { @@ -79,24 +108,25 @@ class EventDispatcher implements EventDispatcherInterface public function getListenerPriority($eventName, $listener) { if (empty($this->listeners[$eventName])) { - return; + return null; } - if (is_array($listener) && isset($listener[0]) && $listener[0] instanceof \Closure) { + if (\is_array($listener) && isset($listener[0]) && $listener[0] instanceof \Closure) { $listener[0] = $listener[0](); } - foreach ($this->listeners[$eventName] as $priority => $listeners) { - foreach ($listeners as $k => $v) { - if ($v !== $listener && is_array($v) && isset($v[0]) && $v[0] instanceof \Closure) { + foreach ($this->listeners[$eventName] as $priority => &$listeners) { + foreach ($listeners as &$v) { + if ($v !== $listener && \is_array($v) && isset($v[0]) && $v[0] instanceof \Closure) { $v[0] = $v[0](); - $this->listeners[$eventName][$priority][$k] = $v; } if ($v === $listener) { return $priority; } } } + + return null; } /** @@ -123,7 +153,7 @@ class EventDispatcher implements EventDispatcherInterface public function addListener($eventName, $listener, $priority = 0) { $this->listeners[$eventName][$priority][] = $listener; - unset($this->sorted[$eventName]); + unset($this->sorted[$eventName], $this->optimized[$eventName]); } /** @@ -135,25 +165,21 @@ class EventDispatcher implements EventDispatcherInterface return; } - if (is_array($listener) && isset($listener[0]) && $listener[0] instanceof \Closure) { + if (\is_array($listener) && isset($listener[0]) && $listener[0] instanceof \Closure) { $listener[0] = $listener[0](); } - foreach ($this->listeners[$eventName] as $priority => $listeners) { - foreach ($listeners as $k => $v) { - if ($v !== $listener && is_array($v) && isset($v[0]) && $v[0] instanceof \Closure) { + foreach ($this->listeners[$eventName] as $priority => &$listeners) { + foreach ($listeners as $k => &$v) { + if ($v !== $listener && \is_array($v) && isset($v[0]) && $v[0] instanceof \Closure) { $v[0] = $v[0](); } if ($v === $listener) { - unset($listeners[$k], $this->sorted[$eventName]); - } else { - $listeners[$k] = $v; + unset($listeners[$k], $this->sorted[$eventName], $this->optimized[$eventName]); } } - if ($listeners) { - $this->listeners[$eventName][$priority] = $listeners; - } else { + if (!$listeners) { unset($this->listeners[$eventName][$priority]); } } @@ -165,13 +191,13 @@ class EventDispatcher implements EventDispatcherInterface public function addSubscriber(EventSubscriberInterface $subscriber) { foreach ($subscriber->getSubscribedEvents() as $eventName => $params) { - if (is_string($params)) { - $this->addListener($eventName, array($subscriber, $params)); - } elseif (is_string($params[0])) { - $this->addListener($eventName, array($subscriber, $params[0]), isset($params[1]) ? $params[1] : 0); + if (\is_string($params)) { + $this->addListener($eventName, [$subscriber, $params]); + } elseif (\is_string($params[0])) { + $this->addListener($eventName, [$subscriber, $params[0]], isset($params[1]) ? $params[1] : 0); } else { foreach ($params as $listener) { - $this->addListener($eventName, array($subscriber, $listener[0]), isset($listener[1]) ? $listener[1] : 0); + $this->addListener($eventName, [$subscriber, $listener[0]], isset($listener[1]) ? $listener[1] : 0); } } } @@ -183,12 +209,12 @@ class EventDispatcher implements EventDispatcherInterface public function removeSubscriber(EventSubscriberInterface $subscriber) { foreach ($subscriber->getSubscribedEvents() as $eventName => $params) { - if (is_array($params) && is_array($params[0])) { + if (\is_array($params) && \is_array($params[0])) { foreach ($params as $listener) { - $this->removeListener($eventName, array($subscriber, $listener[0])); + $this->removeListener($eventName, [$subscriber, $listener[0]]); } } else { - $this->removeListener($eventName, array($subscriber, is_string($params) ? $params : $params[0])); + $this->removeListener($eventName, [$subscriber, \is_string($params) ? $params : $params[0]]); } } } @@ -201,7 +227,29 @@ class EventDispatcher implements EventDispatcherInterface * * @param callable[] $listeners The event listeners * @param string $eventName The name of the event to dispatch - * @param Event $event The event object to pass to the event handlers/listeners + * @param object $event The event object to pass to the event handlers/listeners + */ + protected function callListeners(iterable $listeners, string $eventName, $event) + { + if ($event instanceof Event) { + $this->doDispatch($listeners, $eventName, $event); + + return; + } + + $stoppable = $event instanceof ContractsEvent || $event instanceof StoppableEventInterface; + + foreach ($listeners as $listener) { + if ($stoppable && $event->isPropagationStopped()) { + break; + } + // @deprecated: the ternary operator is part of a BC layer and should be removed in 5.0 + $listener($listener instanceof WrappedListener ? new LegacyEventProxy($event) : $event, $eventName, $this); + } + } + + /** + * @deprecated since Symfony 4.3, use callListeners() instead */ protected function doDispatch($listeners, $eventName, Event $event) { @@ -209,28 +257,52 @@ class EventDispatcher implements EventDispatcherInterface if ($event->isPropagationStopped()) { break; } - \call_user_func($listener, $event, $eventName, $this); + $listener($event, $eventName, $this); } } /** * Sorts the internal list of listeners for the given event by priority. - * - * @param string $eventName The name of the event */ - private function sortListeners($eventName) + private function sortListeners(string $eventName) { krsort($this->listeners[$eventName]); - $this->sorted[$eventName] = array(); + $this->sorted[$eventName] = []; - foreach ($this->listeners[$eventName] as $priority => $listeners) { + foreach ($this->listeners[$eventName] as &$listeners) { foreach ($listeners as $k => $listener) { if (\is_array($listener) && isset($listener[0]) && $listener[0] instanceof \Closure) { $listener[0] = $listener[0](); - $this->listeners[$eventName][$priority][$k] = $listener; } $this->sorted[$eventName][] = $listener; } } } + + /** + * Optimizes the internal list of listeners for the given event by priority. + */ + private function optimizeListeners(string $eventName): array + { + krsort($this->listeners[$eventName]); + $this->optimized[$eventName] = []; + + foreach ($this->listeners[$eventName] as &$listeners) { + foreach ($listeners as &$listener) { + $closure = &$this->optimized[$eventName][]; + if (\is_array($listener) && isset($listener[0]) && $listener[0] instanceof \Closure) { + $closure = static function (...$args) use (&$listener, &$closure) { + if ($listener[0] instanceof \Closure) { + $listener[0] = $listener[0](); + } + ($closure = \Closure::fromCallable($listener))(...$args); + }; + } else { + $closure = $listener instanceof \Closure || $listener instanceof WrappedListener ? $listener : \Closure::fromCallable($listener); + } + } + } + + return $this->optimized[$eventName]; + } } diff --git a/vendor/symfony/event-dispatcher/EventDispatcherInterface.php b/vendor/symfony/event-dispatcher/EventDispatcherInterface.php index d3d0cb8a452d26b42970284f130c29ef76f9e27c..ceaa62aeb0472101e83e561634f8a67bd4ca89ad 100644 --- a/vendor/symfony/event-dispatcher/EventDispatcherInterface.php +++ b/vendor/symfony/event-dispatcher/EventDispatcherInterface.php @@ -11,6 +11,8 @@ namespace Symfony\Component\EventDispatcher; +use Symfony\Contracts\EventDispatcher\EventDispatcherInterface as ContractsEventDispatcherInterface; + /** * The EventDispatcherInterface is the central point of Symfony's event listener system. * Listeners are registered on the manager and events are dispatched through the @@ -18,21 +20,8 @@ namespace Symfony\Component\EventDispatcher; * * @author Bernhard Schussek <bschussek@gmail.com> */ -interface EventDispatcherInterface +interface EventDispatcherInterface extends ContractsEventDispatcherInterface { - /** - * Dispatches an event to all registered listeners. - * - * @param string $eventName The name of the event to dispatch. The name of - * the event is the name of the method that is - * invoked on listeners. - * @param Event $event The event to pass to the event handlers/listeners - * If not supplied, an empty Event instance is created - * - * @return Event - */ - public function dispatch($eventName, Event $event = null); - /** * Adds an event listener that listens on the specified events. * @@ -46,7 +35,7 @@ interface EventDispatcherInterface /** * Adds an event subscriber. * - * The subscriber is asked for all the events he is + * The subscriber is asked for all the events it is * interested in and added as a listener for these events. */ public function addSubscriber(EventSubscriberInterface $subscriber); @@ -64,7 +53,7 @@ interface EventDispatcherInterface /** * Gets the listeners of a specific event or all listeners sorted by descending priority. * - * @param string $eventName The name of the event + * @param string|null $eventName The name of the event * * @return array The event listeners for the specified event, or all event listeners by event name */ @@ -85,7 +74,7 @@ interface EventDispatcherInterface /** * Checks whether an event has any registered listeners. * - * @param string $eventName The name of the event + * @param string|null $eventName The name of the event * * @return bool true if the specified event has any listeners, false otherwise */ diff --git a/vendor/symfony/event-dispatcher/EventSubscriberInterface.php b/vendor/symfony/event-dispatcher/EventSubscriberInterface.php index 8af778919bab71042d545f5f225fde02fa81845d..824f21599c2560611fb1ff88398d475c908e9be8 100644 --- a/vendor/symfony/event-dispatcher/EventSubscriberInterface.php +++ b/vendor/symfony/event-dispatcher/EventSubscriberInterface.php @@ -12,7 +12,7 @@ namespace Symfony\Component\EventDispatcher; /** - * An EventSubscriber knows himself what events he is interested in. + * An EventSubscriber knows itself what events it is interested in. * If an EventSubscriber is added to an EventDispatcherInterface, the manager invokes * {@link getSubscribedEvents} and registers the subscriber as a listener for all * returned events. @@ -36,9 +36,9 @@ interface EventSubscriberInterface * * For instance: * - * * array('eventName' => 'methodName') - * * array('eventName' => array('methodName', $priority)) - * * array('eventName' => array(array('methodName1', $priority), array('methodName2'))) + * * ['eventName' => 'methodName'] + * * ['eventName' => ['methodName', $priority]] + * * ['eventName' => [['methodName1', $priority], ['methodName2']]] * * @return array The event names to listen to */ diff --git a/vendor/symfony/event-dispatcher/GenericEvent.php b/vendor/symfony/event-dispatcher/GenericEvent.php index 95c99408de20f3ee779c1f44a009f56903adbace..f005e3a3db0762e55c1274b59b56d3cb0035e8c1 100644 --- a/vendor/symfony/event-dispatcher/GenericEvent.php +++ b/vendor/symfony/event-dispatcher/GenericEvent.php @@ -29,7 +29,7 @@ class GenericEvent extends Event implements \ArrayAccess, \IteratorAggregate * @param mixed $subject The subject of the event, usually an object or a callable * @param array $arguments Arguments to store in the event */ - public function __construct($subject = null, array $arguments = array()) + public function __construct($subject = null, array $arguments = []) { $this->subject = $subject; $this->arguments = $arguments; @@ -38,7 +38,7 @@ class GenericEvent extends Event implements \ArrayAccess, \IteratorAggregate /** * Getter for subject property. * - * @return mixed $subject The observer subject + * @return mixed The observer subject */ public function getSubject() { @@ -95,7 +95,7 @@ class GenericEvent extends Event implements \ArrayAccess, \IteratorAggregate * * @return $this */ - public function setArguments(array $args = array()) + public function setArguments(array $args = []) { $this->arguments = $args; @@ -111,7 +111,7 @@ class GenericEvent extends Event implements \ArrayAccess, \IteratorAggregate */ public function hasArgument($key) { - return array_key_exists($key, $this->arguments); + return \array_key_exists($key, $this->arguments); } /** diff --git a/vendor/symfony/event-dispatcher/ImmutableEventDispatcher.php b/vendor/symfony/event-dispatcher/ImmutableEventDispatcher.php index b3cf56c502dba3a7f80fea3241b766024348c3d7..75a7d7318187b41766e6bb4e56800d0a249c9ecf 100644 --- a/vendor/symfony/event-dispatcher/ImmutableEventDispatcher.php +++ b/vendor/symfony/event-dispatcher/ImmutableEventDispatcher.php @@ -22,15 +22,26 @@ class ImmutableEventDispatcher implements EventDispatcherInterface public function __construct(EventDispatcherInterface $dispatcher) { - $this->dispatcher = $dispatcher; + $this->dispatcher = LegacyEventDispatcherProxy::decorate($dispatcher); } /** * {@inheritdoc} + * + * @param string|null $eventName */ - public function dispatch($eventName, Event $event = null) + public function dispatch($event/*, string $eventName = null*/) { - return $this->dispatcher->dispatch($eventName, $event); + $eventName = 1 < \func_num_args() ? func_get_arg(1) : null; + + if (is_scalar($event)) { + // deprecated + $swap = $event; + $event = $eventName ?? new Event(); + $eventName = $swap; + } + + return $this->dispatcher->dispatch($event, $eventName); } /** diff --git a/vendor/symfony/event-dispatcher/LICENSE b/vendor/symfony/event-dispatcher/LICENSE index 21d7fb9e2f29b50caca3a76f0647e94e2cc8ddc1..a677f43763ca467472898351b328aee41e2edd7c 100644 --- a/vendor/symfony/event-dispatcher/LICENSE +++ b/vendor/symfony/event-dispatcher/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-2018 Fabien Potencier +Copyright (c) 2004-2019 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/vendor/symfony/event-dispatcher/LegacyEventDispatcherProxy.php b/vendor/symfony/event-dispatcher/LegacyEventDispatcherProxy.php new file mode 100644 index 0000000000000000000000000000000000000000..be0d381a29be69ef50a4a327af88c13538d3fbb2 --- /dev/null +++ b/vendor/symfony/event-dispatcher/LegacyEventDispatcherProxy.php @@ -0,0 +1,147 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\EventDispatcher; + +use Psr\EventDispatcher\StoppableEventInterface; +use Symfony\Contracts\EventDispatcher\Event as ContractsEvent; +use Symfony\Contracts\EventDispatcher\EventDispatcherInterface as ContractsEventDispatcherInterface; + +/** + * A helper class to provide BC/FC with the legacy signature of EventDispatcherInterface::dispatch(). + * + * This class should be deprecated in Symfony 5.1 + * + * @author Nicolas Grekas <p@tchwork.com> + */ +final class LegacyEventDispatcherProxy implements EventDispatcherInterface +{ + private $dispatcher; + + public static function decorate(?ContractsEventDispatcherInterface $dispatcher): ?ContractsEventDispatcherInterface + { + if (null === $dispatcher) { + return null; + } + $r = new \ReflectionMethod($dispatcher, 'dispatch'); + $param2 = $r->getParameters()[1] ?? null; + + if (!$param2 || !$param2->hasType() || $param2->getType()->isBuiltin()) { + return $dispatcher; + } + + @trigger_error(sprintf('The signature of the "%s::dispatch()" method should be updated to "dispatch($event, string $eventName = null)", not doing so is deprecated since Symfony 4.3.', $r->class), E_USER_DEPRECATED); + + $self = new self(); + $self->dispatcher = $dispatcher; + + return $self; + } + + /** + * {@inheritdoc} + * + * @param string|null $eventName + * + * @return object + */ + public function dispatch($event/*, string $eventName = null*/) + { + $eventName = 1 < \func_num_args() ? func_get_arg(1) : null; + + if (\is_object($event)) { + $eventName = $eventName ?? \get_class($event); + } elseif (\is_string($event) && (null === $eventName || $eventName instanceof Event)) { + @trigger_error(sprintf('Calling the "%s::dispatch()" method with the event name as the first argument is deprecated since Symfony 4.3, pass it as the second argument and provide the event object as the first argument instead.', ContractsEventDispatcherInterface::class), E_USER_DEPRECATED); + $swap = $event; + $event = $eventName ?? new Event(); + $eventName = $swap; + } else { + throw new \TypeError(sprintf('Argument 1 passed to "%s::dispatch()" must be an object, %s given.', ContractsEventDispatcherInterface::class, \is_object($event) ? \get_class($event) : \gettype($event))); + } + + $listeners = $this->getListeners($eventName); + $stoppable = $event instanceof Event || $event instanceof ContractsEvent || $event instanceof StoppableEventInterface; + + foreach ($listeners as $listener) { + if ($stoppable && $event->isPropagationStopped()) { + break; + } + $listener($event, $eventName, $this); + } + + return $event; + } + + /** + * {@inheritdoc} + */ + public function addListener($eventName, $listener, $priority = 0) + { + return $this->dispatcher->addListener($eventName, $listener, $priority); + } + + /** + * {@inheritdoc} + */ + public function addSubscriber(EventSubscriberInterface $subscriber) + { + return $this->dispatcher->addSubscriber($subscriber); + } + + /** + * {@inheritdoc} + */ + public function removeListener($eventName, $listener) + { + return $this->dispatcher->removeListener($eventName, $listener); + } + + /** + * {@inheritdoc} + */ + public function removeSubscriber(EventSubscriberInterface $subscriber) + { + return $this->dispatcher->removeSubscriber($subscriber); + } + + /** + * {@inheritdoc} + */ + public function getListeners($eventName = null) + { + return $this->dispatcher->getListeners($eventName); + } + + /** + * {@inheritdoc} + */ + public function getListenerPriority($eventName, $listener) + { + return $this->dispatcher->getListenerPriority($eventName, $listener); + } + + /** + * {@inheritdoc} + */ + public function hasListeners($eventName = null) + { + return $this->dispatcher->hasListeners($eventName); + } + + /** + * Proxies all method calls to the original event dispatcher. + */ + public function __call($method, $arguments) + { + return $this->dispatcher->{$method}(...$arguments); + } +} diff --git a/vendor/symfony/event-dispatcher/LegacyEventProxy.php b/vendor/symfony/event-dispatcher/LegacyEventProxy.php new file mode 100644 index 0000000000000000000000000000000000000000..cad8cfaedb724af76eb9dcfcff81afa50d5fe054 --- /dev/null +++ b/vendor/symfony/event-dispatcher/LegacyEventProxy.php @@ -0,0 +1,62 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\EventDispatcher; + +use Psr\EventDispatcher\StoppableEventInterface; +use Symfony\Contracts\EventDispatcher\Event as ContractsEvent; + +/** + * @internal to be removed in 5.0. + */ +final class LegacyEventProxy extends Event +{ + private $event; + + /** + * @param object $event + */ + public function __construct($event) + { + $this->event = $event; + } + + /** + * @return object $event + */ + public function getEvent() + { + return $this->event; + } + + public function isPropagationStopped() + { + if (!$this->event instanceof ContractsEvent && !$this->event instanceof StoppableEventInterface) { + return false; + } + + return $this->event->isPropagationStopped(); + } + + public function stopPropagation() + { + if (!$this->event instanceof ContractsEvent) { + return; + } + + $this->event->stopPropagation(); + } + + public function __call($name, $args) + { + return $this->event->{$name}(...$args); + } +} diff --git a/vendor/symfony/event-dispatcher/Tests/AbstractEventDispatcherTest.php b/vendor/symfony/event-dispatcher/Tests/AbstractEventDispatcherTest.php deleted file mode 100644 index 9443f21664ced19cc7424c53f092babfc358a6fa..0000000000000000000000000000000000000000 --- a/vendor/symfony/event-dispatcher/Tests/AbstractEventDispatcherTest.php +++ /dev/null @@ -1,442 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\EventDispatcher\Tests; - -use PHPUnit\Framework\TestCase; -use Symfony\Component\EventDispatcher\Event; -use Symfony\Component\EventDispatcher\EventDispatcher; -use Symfony\Component\EventDispatcher\EventSubscriberInterface; - -abstract class AbstractEventDispatcherTest extends TestCase -{ - /* Some pseudo events */ - const preFoo = 'pre.foo'; - const postFoo = 'post.foo'; - const preBar = 'pre.bar'; - const postBar = 'post.bar'; - - /** - * @var EventDispatcher - */ - private $dispatcher; - - private $listener; - - protected function setUp() - { - $this->dispatcher = $this->createEventDispatcher(); - $this->listener = new TestEventListener(); - } - - protected function tearDown() - { - $this->dispatcher = null; - $this->listener = null; - } - - abstract protected function createEventDispatcher(); - - public function testInitialState() - { - $this->assertEquals(array(), $this->dispatcher->getListeners()); - $this->assertFalse($this->dispatcher->hasListeners(self::preFoo)); - $this->assertFalse($this->dispatcher->hasListeners(self::postFoo)); - } - - public function testAddListener() - { - $this->dispatcher->addListener('pre.foo', array($this->listener, 'preFoo')); - $this->dispatcher->addListener('post.foo', array($this->listener, 'postFoo')); - $this->assertTrue($this->dispatcher->hasListeners()); - $this->assertTrue($this->dispatcher->hasListeners(self::preFoo)); - $this->assertTrue($this->dispatcher->hasListeners(self::postFoo)); - $this->assertCount(1, $this->dispatcher->getListeners(self::preFoo)); - $this->assertCount(1, $this->dispatcher->getListeners(self::postFoo)); - $this->assertCount(2, $this->dispatcher->getListeners()); - } - - public function testGetListenersSortsByPriority() - { - $listener1 = new TestEventListener(); - $listener2 = new TestEventListener(); - $listener3 = new TestEventListener(); - $listener1->name = '1'; - $listener2->name = '2'; - $listener3->name = '3'; - - $this->dispatcher->addListener('pre.foo', array($listener1, 'preFoo'), -10); - $this->dispatcher->addListener('pre.foo', array($listener2, 'preFoo'), 10); - $this->dispatcher->addListener('pre.foo', array($listener3, 'preFoo')); - - $expected = array( - array($listener2, 'preFoo'), - array($listener3, 'preFoo'), - array($listener1, 'preFoo'), - ); - - $this->assertSame($expected, $this->dispatcher->getListeners('pre.foo')); - } - - public function testGetAllListenersSortsByPriority() - { - $listener1 = new TestEventListener(); - $listener2 = new TestEventListener(); - $listener3 = new TestEventListener(); - $listener4 = new TestEventListener(); - $listener5 = new TestEventListener(); - $listener6 = new TestEventListener(); - - $this->dispatcher->addListener('pre.foo', $listener1, -10); - $this->dispatcher->addListener('pre.foo', $listener2); - $this->dispatcher->addListener('pre.foo', $listener3, 10); - $this->dispatcher->addListener('post.foo', $listener4, -10); - $this->dispatcher->addListener('post.foo', $listener5); - $this->dispatcher->addListener('post.foo', $listener6, 10); - - $expected = array( - 'pre.foo' => array($listener3, $listener2, $listener1), - 'post.foo' => array($listener6, $listener5, $listener4), - ); - - $this->assertSame($expected, $this->dispatcher->getListeners()); - } - - public function testGetListenerPriority() - { - $listener1 = new TestEventListener(); - $listener2 = new TestEventListener(); - - $this->dispatcher->addListener('pre.foo', $listener1, -10); - $this->dispatcher->addListener('pre.foo', $listener2); - - $this->assertSame(-10, $this->dispatcher->getListenerPriority('pre.foo', $listener1)); - $this->assertSame(0, $this->dispatcher->getListenerPriority('pre.foo', $listener2)); - $this->assertNull($this->dispatcher->getListenerPriority('pre.bar', $listener2)); - $this->assertNull($this->dispatcher->getListenerPriority('pre.foo', function () {})); - } - - public function testDispatch() - { - $this->dispatcher->addListener('pre.foo', array($this->listener, 'preFoo')); - $this->dispatcher->addListener('post.foo', array($this->listener, 'postFoo')); - $this->dispatcher->dispatch(self::preFoo); - $this->assertTrue($this->listener->preFooInvoked); - $this->assertFalse($this->listener->postFooInvoked); - $this->assertInstanceOf('Symfony\Component\EventDispatcher\Event', $this->dispatcher->dispatch('noevent')); - $this->assertInstanceOf('Symfony\Component\EventDispatcher\Event', $this->dispatcher->dispatch(self::preFoo)); - $event = new Event(); - $return = $this->dispatcher->dispatch(self::preFoo, $event); - $this->assertSame($event, $return); - } - - public function testDispatchForClosure() - { - $invoked = 0; - $listener = function () use (&$invoked) { - ++$invoked; - }; - $this->dispatcher->addListener('pre.foo', $listener); - $this->dispatcher->addListener('post.foo', $listener); - $this->dispatcher->dispatch(self::preFoo); - $this->assertEquals(1, $invoked); - } - - public function testStopEventPropagation() - { - $otherListener = new TestEventListener(); - - // postFoo() stops the propagation, so only one listener should - // be executed - // Manually set priority to enforce $this->listener to be called first - $this->dispatcher->addListener('post.foo', array($this->listener, 'postFoo'), 10); - $this->dispatcher->addListener('post.foo', array($otherListener, 'preFoo')); - $this->dispatcher->dispatch(self::postFoo); - $this->assertTrue($this->listener->postFooInvoked); - $this->assertFalse($otherListener->postFooInvoked); - } - - public function testDispatchByPriority() - { - $invoked = array(); - $listener1 = function () use (&$invoked) { - $invoked[] = '1'; - }; - $listener2 = function () use (&$invoked) { - $invoked[] = '2'; - }; - $listener3 = function () use (&$invoked) { - $invoked[] = '3'; - }; - $this->dispatcher->addListener('pre.foo', $listener1, -10); - $this->dispatcher->addListener('pre.foo', $listener2); - $this->dispatcher->addListener('pre.foo', $listener3, 10); - $this->dispatcher->dispatch(self::preFoo); - $this->assertEquals(array('3', '2', '1'), $invoked); - } - - public function testRemoveListener() - { - $this->dispatcher->addListener('pre.bar', $this->listener); - $this->assertTrue($this->dispatcher->hasListeners(self::preBar)); - $this->dispatcher->removeListener('pre.bar', $this->listener); - $this->assertFalse($this->dispatcher->hasListeners(self::preBar)); - $this->dispatcher->removeListener('notExists', $this->listener); - } - - public function testAddSubscriber() - { - $eventSubscriber = new TestEventSubscriber(); - $this->dispatcher->addSubscriber($eventSubscriber); - $this->assertTrue($this->dispatcher->hasListeners(self::preFoo)); - $this->assertTrue($this->dispatcher->hasListeners(self::postFoo)); - } - - public function testAddSubscriberWithPriorities() - { - $eventSubscriber = new TestEventSubscriber(); - $this->dispatcher->addSubscriber($eventSubscriber); - - $eventSubscriber = new TestEventSubscriberWithPriorities(); - $this->dispatcher->addSubscriber($eventSubscriber); - - $listeners = $this->dispatcher->getListeners('pre.foo'); - $this->assertTrue($this->dispatcher->hasListeners(self::preFoo)); - $this->assertCount(2, $listeners); - $this->assertInstanceOf('Symfony\Component\EventDispatcher\Tests\TestEventSubscriberWithPriorities', $listeners[0][0]); - } - - public function testAddSubscriberWithMultipleListeners() - { - $eventSubscriber = new TestEventSubscriberWithMultipleListeners(); - $this->dispatcher->addSubscriber($eventSubscriber); - - $listeners = $this->dispatcher->getListeners('pre.foo'); - $this->assertTrue($this->dispatcher->hasListeners(self::preFoo)); - $this->assertCount(2, $listeners); - $this->assertEquals('preFoo2', $listeners[0][1]); - } - - public function testRemoveSubscriber() - { - $eventSubscriber = new TestEventSubscriber(); - $this->dispatcher->addSubscriber($eventSubscriber); - $this->assertTrue($this->dispatcher->hasListeners(self::preFoo)); - $this->assertTrue($this->dispatcher->hasListeners(self::postFoo)); - $this->dispatcher->removeSubscriber($eventSubscriber); - $this->assertFalse($this->dispatcher->hasListeners(self::preFoo)); - $this->assertFalse($this->dispatcher->hasListeners(self::postFoo)); - } - - public function testRemoveSubscriberWithPriorities() - { - $eventSubscriber = new TestEventSubscriberWithPriorities(); - $this->dispatcher->addSubscriber($eventSubscriber); - $this->assertTrue($this->dispatcher->hasListeners(self::preFoo)); - $this->dispatcher->removeSubscriber($eventSubscriber); - $this->assertFalse($this->dispatcher->hasListeners(self::preFoo)); - } - - public function testRemoveSubscriberWithMultipleListeners() - { - $eventSubscriber = new TestEventSubscriberWithMultipleListeners(); - $this->dispatcher->addSubscriber($eventSubscriber); - $this->assertTrue($this->dispatcher->hasListeners(self::preFoo)); - $this->assertCount(2, $this->dispatcher->getListeners(self::preFoo)); - $this->dispatcher->removeSubscriber($eventSubscriber); - $this->assertFalse($this->dispatcher->hasListeners(self::preFoo)); - } - - public function testEventReceivesTheDispatcherInstanceAsArgument() - { - $listener = new TestWithDispatcher(); - $this->dispatcher->addListener('test', array($listener, 'foo')); - $this->assertNull($listener->name); - $this->assertNull($listener->dispatcher); - $this->dispatcher->dispatch('test'); - $this->assertEquals('test', $listener->name); - $this->assertSame($this->dispatcher, $listener->dispatcher); - } - - /** - * @see https://bugs.php.net/bug.php?id=62976 - * - * This bug affects: - * - The PHP 5.3 branch for versions < 5.3.18 - * - The PHP 5.4 branch for versions < 5.4.8 - * - The PHP 5.5 branch is not affected - */ - public function testWorkaroundForPhpBug62976() - { - $dispatcher = $this->createEventDispatcher(); - $dispatcher->addListener('bug.62976', new CallableClass()); - $dispatcher->removeListener('bug.62976', function () {}); - $this->assertTrue($dispatcher->hasListeners('bug.62976')); - } - - public function testHasListenersWhenAddedCallbackListenerIsRemoved() - { - $listener = function () {}; - $this->dispatcher->addListener('foo', $listener); - $this->dispatcher->removeListener('foo', $listener); - $this->assertFalse($this->dispatcher->hasListeners()); - } - - public function testGetListenersWhenAddedCallbackListenerIsRemoved() - { - $listener = function () {}; - $this->dispatcher->addListener('foo', $listener); - $this->dispatcher->removeListener('foo', $listener); - $this->assertSame(array(), $this->dispatcher->getListeners()); - } - - public function testHasListenersWithoutEventsReturnsFalseAfterHasListenersWithEventHasBeenCalled() - { - $this->assertFalse($this->dispatcher->hasListeners('foo')); - $this->assertFalse($this->dispatcher->hasListeners()); - } - - public function testHasListenersIsLazy() - { - $called = 0; - $listener = array(function () use (&$called) { ++$called; }, 'onFoo'); - $this->dispatcher->addListener('foo', $listener); - $this->assertTrue($this->dispatcher->hasListeners()); - $this->assertTrue($this->dispatcher->hasListeners('foo')); - $this->assertSame(0, $called); - } - - public function testDispatchLazyListener() - { - $called = 0; - $factory = function () use (&$called) { - ++$called; - - return new TestWithDispatcher(); - }; - $this->dispatcher->addListener('foo', array($factory, 'foo')); - $this->assertSame(0, $called); - $this->dispatcher->dispatch('foo', new Event()); - $this->dispatcher->dispatch('foo', new Event()); - $this->assertSame(1, $called); - } - - public function testRemoveFindsLazyListeners() - { - $test = new TestWithDispatcher(); - $factory = function () use ($test) { return $test; }; - - $this->dispatcher->addListener('foo', array($factory, 'foo')); - $this->assertTrue($this->dispatcher->hasListeners('foo')); - $this->dispatcher->removeListener('foo', array($test, 'foo')); - $this->assertFalse($this->dispatcher->hasListeners('foo')); - - $this->dispatcher->addListener('foo', array($test, 'foo')); - $this->assertTrue($this->dispatcher->hasListeners('foo')); - $this->dispatcher->removeListener('foo', array($factory, 'foo')); - $this->assertFalse($this->dispatcher->hasListeners('foo')); - } - - public function testPriorityFindsLazyListeners() - { - $test = new TestWithDispatcher(); - $factory = function () use ($test) { return $test; }; - - $this->dispatcher->addListener('foo', array($factory, 'foo'), 3); - $this->assertSame(3, $this->dispatcher->getListenerPriority('foo', array($test, 'foo'))); - $this->dispatcher->removeListener('foo', array($factory, 'foo')); - - $this->dispatcher->addListener('foo', array($test, 'foo'), 5); - $this->assertSame(5, $this->dispatcher->getListenerPriority('foo', array($factory, 'foo'))); - } - - public function testGetLazyListeners() - { - $test = new TestWithDispatcher(); - $factory = function () use ($test) { return $test; }; - - $this->dispatcher->addListener('foo', array($factory, 'foo'), 3); - $this->assertSame(array(array($test, 'foo')), $this->dispatcher->getListeners('foo')); - - $this->dispatcher->removeListener('foo', array($test, 'foo')); - $this->dispatcher->addListener('bar', array($factory, 'foo'), 3); - $this->assertSame(array('bar' => array(array($test, 'foo'))), $this->dispatcher->getListeners()); - } -} - -class CallableClass -{ - public function __invoke() - { - } -} - -class TestEventListener -{ - public $preFooInvoked = false; - public $postFooInvoked = false; - - /* Listener methods */ - - public function preFoo(Event $e) - { - $this->preFooInvoked = true; - } - - public function postFoo(Event $e) - { - $this->postFooInvoked = true; - - $e->stopPropagation(); - } -} - -class TestWithDispatcher -{ - public $name; - public $dispatcher; - - public function foo(Event $e, $name, $dispatcher) - { - $this->name = $name; - $this->dispatcher = $dispatcher; - } -} - -class TestEventSubscriber implements EventSubscriberInterface -{ - public static function getSubscribedEvents() - { - return array('pre.foo' => 'preFoo', 'post.foo' => 'postFoo'); - } -} - -class TestEventSubscriberWithPriorities implements EventSubscriberInterface -{ - public static function getSubscribedEvents() - { - return array( - 'pre.foo' => array('preFoo', 10), - 'post.foo' => array('postFoo'), - ); - } -} - -class TestEventSubscriberWithMultipleListeners implements EventSubscriberInterface -{ - public static function getSubscribedEvents() - { - return array('pre.foo' => array( - array('preFoo1'), - array('preFoo2', 10), - )); - } -} diff --git a/vendor/symfony/event-dispatcher/Tests/ChildEventDispatcherTest.php b/vendor/symfony/event-dispatcher/Tests/ChildEventDispatcherTest.php new file mode 100644 index 0000000000000000000000000000000000000000..442b88fbb39e1febf029d230f8eace7b991b042b --- /dev/null +++ b/vendor/symfony/event-dispatcher/Tests/ChildEventDispatcherTest.php @@ -0,0 +1,26 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\EventDispatcher\Tests; + +use Symfony\Component\EventDispatcher\EventDispatcher; + +class ChildEventDispatcherTest extends EventDispatcherTest +{ + protected function createEventDispatcher() + { + return new ChildEventDispatcher(); + } +} + +class ChildEventDispatcher extends EventDispatcher +{ +} diff --git a/vendor/symfony/event-dispatcher/Tests/ContainerAwareEventDispatcherTest.php b/vendor/symfony/event-dispatcher/Tests/ContainerAwareEventDispatcherTest.php deleted file mode 100644 index 9d5eecc547bd47c53515dd387d736a07add7079b..0000000000000000000000000000000000000000 --- a/vendor/symfony/event-dispatcher/Tests/ContainerAwareEventDispatcherTest.php +++ /dev/null @@ -1,210 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\EventDispatcher\Tests; - -use Symfony\Component\DependencyInjection\Container; -use Symfony\Component\EventDispatcher\ContainerAwareEventDispatcher; -use Symfony\Component\EventDispatcher\Event; -use Symfony\Component\EventDispatcher\EventSubscriberInterface; - -/** - * @group legacy - */ -class ContainerAwareEventDispatcherTest extends AbstractEventDispatcherTest -{ - protected function createEventDispatcher() - { - $container = new Container(); - - return new ContainerAwareEventDispatcher($container); - } - - public function testAddAListenerService() - { - $event = new Event(); - - $service = $this->getMockBuilder('Symfony\Component\EventDispatcher\Tests\Service')->getMock(); - - $service - ->expects($this->once()) - ->method('onEvent') - ->with($event) - ; - - $container = new Container(); - $container->set('service.listener', $service); - - $dispatcher = new ContainerAwareEventDispatcher($container); - $dispatcher->addListenerService('onEvent', array('service.listener', 'onEvent')); - - $dispatcher->dispatch('onEvent', $event); - } - - public function testAddASubscriberService() - { - $event = new Event(); - - $service = $this->getMockBuilder('Symfony\Component\EventDispatcher\Tests\SubscriberService')->getMock(); - - $service - ->expects($this->once()) - ->method('onEvent') - ->with($event) - ; - - $service - ->expects($this->once()) - ->method('onEventWithPriority') - ->with($event) - ; - - $service - ->expects($this->once()) - ->method('onEventNested') - ->with($event) - ; - - $container = new Container(); - $container->set('service.subscriber', $service); - - $dispatcher = new ContainerAwareEventDispatcher($container); - $dispatcher->addSubscriberService('service.subscriber', 'Symfony\Component\EventDispatcher\Tests\SubscriberService'); - - $dispatcher->dispatch('onEvent', $event); - $dispatcher->dispatch('onEventWithPriority', $event); - $dispatcher->dispatch('onEventNested', $event); - } - - public function testPreventDuplicateListenerService() - { - $event = new Event(); - - $service = $this->getMockBuilder('Symfony\Component\EventDispatcher\Tests\Service')->getMock(); - - $service - ->expects($this->once()) - ->method('onEvent') - ->with($event) - ; - - $container = new Container(); - $container->set('service.listener', $service); - - $dispatcher = new ContainerAwareEventDispatcher($container); - $dispatcher->addListenerService('onEvent', array('service.listener', 'onEvent'), 5); - $dispatcher->addListenerService('onEvent', array('service.listener', 'onEvent'), 10); - - $dispatcher->dispatch('onEvent', $event); - } - - public function testHasListenersOnLazyLoad() - { - $event = new Event(); - - $service = $this->getMockBuilder('Symfony\Component\EventDispatcher\Tests\Service')->getMock(); - - $container = new Container(); - $container->set('service.listener', $service); - - $dispatcher = new ContainerAwareEventDispatcher($container); - $dispatcher->addListenerService('onEvent', array('service.listener', 'onEvent')); - - $service - ->expects($this->once()) - ->method('onEvent') - ->with($event) - ; - - $this->assertTrue($dispatcher->hasListeners()); - - if ($dispatcher->hasListeners('onEvent')) { - $dispatcher->dispatch('onEvent'); - } - } - - public function testGetListenersOnLazyLoad() - { - $service = $this->getMockBuilder('Symfony\Component\EventDispatcher\Tests\Service')->getMock(); - - $container = new Container(); - $container->set('service.listener', $service); - - $dispatcher = new ContainerAwareEventDispatcher($container); - $dispatcher->addListenerService('onEvent', array('service.listener', 'onEvent')); - - $listeners = $dispatcher->getListeners(); - - $this->assertArrayHasKey('onEvent', $listeners); - - $this->assertCount(1, $dispatcher->getListeners('onEvent')); - } - - public function testRemoveAfterDispatch() - { - $service = $this->getMockBuilder('Symfony\Component\EventDispatcher\Tests\Service')->getMock(); - - $container = new Container(); - $container->set('service.listener', $service); - - $dispatcher = new ContainerAwareEventDispatcher($container); - $dispatcher->addListenerService('onEvent', array('service.listener', 'onEvent')); - - $dispatcher->dispatch('onEvent', new Event()); - $dispatcher->removeListener('onEvent', array($container->get('service.listener'), 'onEvent')); - $this->assertFalse($dispatcher->hasListeners('onEvent')); - } - - public function testRemoveBeforeDispatch() - { - $service = $this->getMockBuilder('Symfony\Component\EventDispatcher\Tests\Service')->getMock(); - - $container = new Container(); - $container->set('service.listener', $service); - - $dispatcher = new ContainerAwareEventDispatcher($container); - $dispatcher->addListenerService('onEvent', array('service.listener', 'onEvent')); - - $dispatcher->removeListener('onEvent', array($container->get('service.listener'), 'onEvent')); - $this->assertFalse($dispatcher->hasListeners('onEvent')); - } -} - -class Service -{ - public function onEvent(Event $e) - { - } -} - -class SubscriberService implements EventSubscriberInterface -{ - public static function getSubscribedEvents() - { - return array( - 'onEvent' => 'onEvent', - 'onEventWithPriority' => array('onEventWithPriority', 10), - 'onEventNested' => array(array('onEventNested')), - ); - } - - public function onEvent(Event $e) - { - } - - public function onEventWithPriority(Event $e) - { - } - - public function onEventNested(Event $e) - { - } -} diff --git a/vendor/symfony/event-dispatcher/Tests/Debug/TraceableEventDispatcherTest.php b/vendor/symfony/event-dispatcher/Tests/Debug/TraceableEventDispatcherTest.php index 53a3421afaf6acb15f15636c40deb2180951f67c..ea476eee04c8e3c27810b1fb808f9640592713f0 100644 --- a/vendor/symfony/event-dispatcher/Tests/Debug/TraceableEventDispatcherTest.php +++ b/vendor/symfony/event-dispatcher/Tests/Debug/TraceableEventDispatcherTest.php @@ -13,11 +13,12 @@ namespace Symfony\Component\EventDispatcher\Tests\Debug; use PHPUnit\Framework\TestCase; use Symfony\Component\EventDispatcher\Debug\TraceableEventDispatcher; +use Symfony\Component\EventDispatcher\Event; +use Symfony\Component\EventDispatcher\EventDispatcher; use Symfony\Component\EventDispatcher\EventDispatcherInterface; use Symfony\Component\EventDispatcher\EventSubscriberInterface; -use Symfony\Component\EventDispatcher\EventDispatcher; -use Symfony\Component\EventDispatcher\Event; use Symfony\Component\Stopwatch\Stopwatch; +use Symfony\Contracts\EventDispatcher\Event as ContractsEvent; class TraceableEventDispatcherTest extends TestCase { @@ -69,7 +70,7 @@ class TraceableEventDispatcherTest extends TestCase // Verify that priority is preserved when listener is removed and re-added // in preProcess() and postProcess(). - $tdispatcher->dispatch('foo', new Event()); + $tdispatcher->dispatch(new Event(), 'foo'); $listeners = $dispatcher->getListeners('foo'); $this->assertSame(123, $tdispatcher->getListenerPriority('foo', $listeners[0])); } @@ -84,7 +85,7 @@ class TraceableEventDispatcherTest extends TestCase }; $tdispatcher->addListener('bar', $listener, 5); - $tdispatcher->dispatch('bar'); + $tdispatcher->dispatch(new Event(), 'bar'); $this->assertSame(5, $priorityWhileDispatching); } @@ -98,7 +99,7 @@ class TraceableEventDispatcherTest extends TestCase $tdispatcher->addSubscriber($subscriber); $listeners = $dispatcher->getListeners('foo'); $this->assertCount(1, $listeners); - $this->assertSame(array($subscriber, 'call'), $listeners[0]); + $this->assertSame([$subscriber, 'call'], $listeners[0]); $tdispatcher->removeSubscriber($subscriber); $this->assertCount(0, $dispatcher->getListeners('foo')); @@ -110,18 +111,18 @@ class TraceableEventDispatcherTest extends TestCase $tdispatcher->addListener('foo', function () {}, 5); $listeners = $tdispatcher->getNotCalledListeners(); - $this->assertArrayHasKey('stub', $listeners['foo.closure']); - unset($listeners['foo.closure']['stub']); - $this->assertEquals(array(), $tdispatcher->getCalledListeners()); - $this->assertEquals(array('foo.closure' => array('event' => 'foo', 'pretty' => 'closure', 'priority' => 5)), $listeners); + $this->assertArrayHasKey('stub', $listeners[0]); + unset($listeners[0]['stub']); + $this->assertEquals([], $tdispatcher->getCalledListeners()); + $this->assertEquals([['event' => 'foo', 'pretty' => 'closure', 'priority' => 5]], $listeners); - $tdispatcher->dispatch('foo'); + $tdispatcher->dispatch(new Event(), 'foo'); $listeners = $tdispatcher->getCalledListeners(); - $this->assertArrayHasKey('stub', $listeners['foo.closure']); - unset($listeners['foo.closure']['stub']); - $this->assertEquals(array('foo.closure' => array('event' => 'foo', 'pretty' => 'closure', 'priority' => 5)), $listeners); - $this->assertEquals(array(), $tdispatcher->getNotCalledListeners()); + $this->assertArrayHasKey('stub', $listeners[0]); + unset($listeners[0]['stub']); + $this->assertEquals([['event' => 'foo', 'pretty' => 'closure', 'priority' => 5]], $listeners); + $this->assertEquals([], $tdispatcher->getNotCalledListeners()); } public function testClearCalledListeners() @@ -129,14 +130,39 @@ class TraceableEventDispatcherTest extends TestCase $tdispatcher = new TraceableEventDispatcher(new EventDispatcher(), new Stopwatch()); $tdispatcher->addListener('foo', function () {}, 5); - $tdispatcher->dispatch('foo'); + $tdispatcher->dispatch(new Event(), 'foo'); $tdispatcher->reset(); $listeners = $tdispatcher->getNotCalledListeners(); - $this->assertArrayHasKey('stub', $listeners['foo.closure']); - unset($listeners['foo.closure']['stub']); - $this->assertEquals(array(), $tdispatcher->getCalledListeners()); - $this->assertEquals(array('foo.closure' => array('event' => 'foo', 'pretty' => 'closure', 'priority' => 5)), $listeners); + $this->assertArrayHasKey('stub', $listeners[0]); + unset($listeners[0]['stub']); + $this->assertEquals([], $tdispatcher->getCalledListeners()); + $this->assertEquals([['event' => 'foo', 'pretty' => 'closure', 'priority' => 5]], $listeners); + } + + public function testDispatchContractsEvent() + { + $expectedEvent = new ContractsEvent(); + $tdispatcher = new TraceableEventDispatcher(new EventDispatcher(), new Stopwatch()); + $tdispatcher->addListener('foo', function ($event) use ($expectedEvent) { + $this->assertSame($event, $expectedEvent); + }, 5); + $tdispatcher->dispatch($expectedEvent, 'foo'); + + $listeners = $tdispatcher->getCalledListeners(); + $this->assertArrayHasKey('stub', $listeners[0]); + } + + public function testDispatchAfterReset() + { + $tdispatcher = new TraceableEventDispatcher(new EventDispatcher(), new Stopwatch()); + $tdispatcher->addListener('foo', function () {}, 5); + + $tdispatcher->reset(); + $tdispatcher->dispatch(new Event(), 'foo'); + + $listeners = $tdispatcher->getCalledListeners(); + $this->assertArrayHasKey('stub', $listeners[0]); } public function testGetCalledListenersNested() @@ -145,14 +171,39 @@ class TraceableEventDispatcherTest extends TestCase $dispatcher = new TraceableEventDispatcher(new EventDispatcher(), new Stopwatch()); $dispatcher->addListener('foo', function (Event $event, $eventName, $dispatcher) use (&$tdispatcher) { $tdispatcher = $dispatcher; - $dispatcher->dispatch('bar'); + $dispatcher->dispatch(new Event(), 'bar'); }); $dispatcher->addListener('bar', function (Event $event) {}); - $dispatcher->dispatch('foo'); + $dispatcher->dispatch(new Event(), 'foo'); $this->assertSame($dispatcher, $tdispatcher); $this->assertCount(2, $dispatcher->getCalledListeners()); } + public function testItReturnsNoOrphanedEventsWhenCreated() + { + $tdispatcher = new TraceableEventDispatcher(new EventDispatcher(), new Stopwatch()); + $events = $tdispatcher->getOrphanedEvents(); + $this->assertEmpty($events); + } + + public function testItReturnsOrphanedEventsAfterDispatch() + { + $tdispatcher = new TraceableEventDispatcher(new EventDispatcher(), new Stopwatch()); + $tdispatcher->dispatch(new Event(), 'foo'); + $events = $tdispatcher->getOrphanedEvents(); + $this->assertCount(1, $events); + $this->assertEquals(['foo'], $events); + } + + public function testItDoesNotReturnHandledEvents() + { + $tdispatcher = new TraceableEventDispatcher(new EventDispatcher(), new Stopwatch()); + $tdispatcher->addListener('foo', function () {}); + $tdispatcher->dispatch(new Event(), 'foo'); + $events = $tdispatcher->getOrphanedEvents(); + $this->assertEmpty($events); + } + public function testLogger() { $logger = $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock(); @@ -162,10 +213,10 @@ class TraceableEventDispatcherTest extends TestCase $tdispatcher->addListener('foo', $listener1 = function () {}); $tdispatcher->addListener('foo', $listener2 = function () {}); - $logger->expects($this->at(0))->method('debug')->with('Notified event "{event}" to listener "{listener}".', array('event' => 'foo', 'listener' => 'closure')); - $logger->expects($this->at(1))->method('debug')->with('Notified event "{event}" to listener "{listener}".', array('event' => 'foo', 'listener' => 'closure')); + $logger->expects($this->at(0))->method('debug')->with('Notified event "{event}" to listener "{listener}".', ['event' => 'foo', 'listener' => 'closure']); + $logger->expects($this->at(1))->method('debug')->with('Notified event "{event}" to listener "{listener}".', ['event' => 'foo', 'listener' => 'closure']); - $tdispatcher->dispatch('foo'); + $tdispatcher->dispatch(new Event(), 'foo'); } public function testLoggerWithStoppedEvent() @@ -177,25 +228,25 @@ class TraceableEventDispatcherTest extends TestCase $tdispatcher->addListener('foo', $listener1 = function (Event $event) { $event->stopPropagation(); }); $tdispatcher->addListener('foo', $listener2 = function () {}); - $logger->expects($this->at(0))->method('debug')->with('Notified event "{event}" to listener "{listener}".', array('event' => 'foo', 'listener' => 'closure')); - $logger->expects($this->at(1))->method('debug')->with('Listener "{listener}" stopped propagation of the event "{event}".', array('event' => 'foo', 'listener' => 'closure')); - $logger->expects($this->at(2))->method('debug')->with('Listener "{listener}" was not called for event "{event}".', array('event' => 'foo', 'listener' => 'closure')); + $logger->expects($this->at(0))->method('debug')->with('Notified event "{event}" to listener "{listener}".', ['event' => 'foo', 'listener' => 'closure']); + $logger->expects($this->at(1))->method('debug')->with('Listener "{listener}" stopped propagation of the event "{event}".', ['event' => 'foo', 'listener' => 'closure']); + $logger->expects($this->at(2))->method('debug')->with('Listener "{listener}" was not called for event "{event}".', ['event' => 'foo', 'listener' => 'closure']); - $tdispatcher->dispatch('foo'); + $tdispatcher->dispatch(new Event(), 'foo'); } public function testDispatchCallListeners() { - $called = array(); + $called = []; $dispatcher = new EventDispatcher(); $tdispatcher = new TraceableEventDispatcher($dispatcher, new Stopwatch()); $tdispatcher->addListener('foo', function () use (&$called) { $called[] = 'foo1'; }, 10); $tdispatcher->addListener('foo', function () use (&$called) { $called[] = 'foo2'; }, 20); - $tdispatcher->dispatch('foo'); + $tdispatcher->dispatch(new Event(), 'foo'); - $this->assertSame(array('foo2', 'foo1'), $called); + $this->assertSame(['foo2', 'foo1'], $called); } public function testDispatchNested() @@ -206,14 +257,14 @@ class TraceableEventDispatcherTest extends TestCase $dispatcher->addListener('foo', $listener1 = function () use ($dispatcher, &$loop) { ++$loop; if (2 == $loop) { - $dispatcher->dispatch('foo'); + $dispatcher->dispatch(new Event(), 'foo'); } }); $dispatcher->addListener('foo', function () use (&$dispatchedEvents) { ++$dispatchedEvents; }); - $dispatcher->dispatch('foo'); + $dispatcher->dispatch(new Event(), 'foo'); $this->assertSame(2, $dispatchedEvents); } @@ -223,14 +274,14 @@ class TraceableEventDispatcherTest extends TestCase $nestedCall = false; $dispatcher = new TraceableEventDispatcher(new EventDispatcher(), new Stopwatch()); $dispatcher->addListener('foo', function (Event $e) use ($dispatcher) { - $dispatcher->dispatch('bar', $e); + $dispatcher->dispatch(new Event(), 'bar', $e); }); $dispatcher->addListener('bar', function (Event $e) use (&$nestedCall) { $nestedCall = true; }); $this->assertFalse($nestedCall); - $dispatcher->dispatch('foo'); + $dispatcher->dispatch(new Event(), 'foo'); $this->assertTrue($nestedCall); } @@ -242,16 +293,27 @@ class TraceableEventDispatcherTest extends TestCase }; $eventDispatcher->addListener('foo', $listener1); $eventDispatcher->addListener('foo', function () {}); - $eventDispatcher->dispatch('foo'); + $eventDispatcher->dispatch(new Event(), 'foo'); $this->assertCount(1, $eventDispatcher->getListeners('foo'), 'expected listener1 to be removed'); } + + public function testClearOrphanedEvents() + { + $tdispatcher = new TraceableEventDispatcher(new EventDispatcher(), new Stopwatch()); + $tdispatcher->dispatch(new Event(), 'foo'); + $events = $tdispatcher->getOrphanedEvents(); + $this->assertCount(1, $events); + $tdispatcher->reset(); + $events = $tdispatcher->getOrphanedEvents(); + $this->assertCount(0, $events); + } } class EventSubscriber implements EventSubscriberInterface { public static function getSubscribedEvents() { - return array('foo' => 'call'); + return ['foo' => 'call']; } } diff --git a/vendor/symfony/event-dispatcher/Tests/Debug/WrappedListenerTest.php b/vendor/symfony/event-dispatcher/Tests/Debug/WrappedListenerTest.php new file mode 100644 index 0000000000000000000000000000000000000000..75e90120736ec88192cff59162473eb79ea428ce --- /dev/null +++ b/vendor/symfony/event-dispatcher/Tests/Debug/WrappedListenerTest.php @@ -0,0 +1,60 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\EventDispatcher\Tests\Debug; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\EventDispatcher\Debug\WrappedListener; +use Symfony\Component\EventDispatcher\EventDispatcherInterface; +use Symfony\Component\Stopwatch\Stopwatch; + +class WrappedListenerTest extends TestCase +{ + /** + * @dataProvider provideListenersToDescribe + */ + public function testListenerDescription($listener, $expected) + { + $wrappedListener = new WrappedListener($listener, null, $this->getMockBuilder(Stopwatch::class)->getMock(), $this->getMockBuilder(EventDispatcherInterface::class)->getMock()); + + $this->assertStringMatchesFormat($expected, $wrappedListener->getPretty()); + } + + public function provideListenersToDescribe() + { + return [ + [new FooListener(), 'Symfony\Component\EventDispatcher\Tests\Debug\FooListener::__invoke'], + [[new FooListener(), 'listen'], 'Symfony\Component\EventDispatcher\Tests\Debug\FooListener::listen'], + [['Symfony\Component\EventDispatcher\Tests\Debug\FooListener', 'listenStatic'], 'Symfony\Component\EventDispatcher\Tests\Debug\FooListener::listenStatic'], + [['Symfony\Component\EventDispatcher\Tests\Debug\FooListener', 'invalidMethod'], 'Symfony\Component\EventDispatcher\Tests\Debug\FooListener::invalidMethod'], + ['var_dump', 'var_dump'], + [function () {}, 'closure'], + [\Closure::fromCallable([new FooListener(), 'listen']), 'Symfony\Component\EventDispatcher\Tests\Debug\FooListener::listen'], + [\Closure::fromCallable(['Symfony\Component\EventDispatcher\Tests\Debug\FooListener', 'listenStatic']), 'Symfony\Component\EventDispatcher\Tests\Debug\FooListener::listenStatic'], + [\Closure::fromCallable(function () {}), 'closure'], + ]; + } +} + +class FooListener +{ + public function listen() + { + } + + public function __invoke() + { + } + + public static function listenStatic() + { + } +} diff --git a/vendor/symfony/event-dispatcher/Tests/DependencyInjection/RegisterListenersPassTest.php b/vendor/symfony/event-dispatcher/Tests/DependencyInjection/RegisterListenersPassTest.php index dbb1aa5c57b57a2f4d915444843c6359790e08c9..780f7087f44079fec549c4e793d76bc9ee5e0e7f 100644 --- a/vendor/symfony/event-dispatcher/Tests/DependencyInjection/RegisterListenersPassTest.php +++ b/vendor/symfony/event-dispatcher/Tests/DependencyInjection/RegisterListenersPassTest.php @@ -16,40 +16,21 @@ use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\EventDispatcher\DependencyInjection\RegisterListenersPass; +use Symfony\Component\EventDispatcher\EventSubscriberInterface; class RegisterListenersPassTest extends TestCase { /** * Tests that event subscribers not implementing EventSubscriberInterface * trigger an exception. - * - * @expectedException \InvalidArgumentException */ public function testEventSubscriberWithoutInterface() { - // one service, not implementing any interface - $services = array( - 'my_event_subscriber' => array(0 => array()), - ); - - $definition = $this->getMockBuilder('Symfony\Component\DependencyInjection\Definition')->getMock(); - $definition->expects($this->atLeastOnce()) - ->method('getClass') - ->will($this->returnValue('stdClass')); - - $builder = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerBuilder')->setMethods(array('hasDefinition', 'findTaggedServiceIds', 'getDefinition'))->getMock(); - $builder->expects($this->any()) - ->method('hasDefinition') - ->will($this->returnValue(true)); - - // We don't test kernel.event_listener here - $builder->expects($this->atLeastOnce()) - ->method('findTaggedServiceIds') - ->will($this->onConsecutiveCalls(array(), $services)); - - $builder->expects($this->atLeastOnce()) - ->method('getDefinition') - ->will($this->returnValue($definition)); + $this->expectException('InvalidArgumentException'); + $builder = new ContainerBuilder(); + $builder->register('event_dispatcher'); + $builder->register('my_event_subscriber', 'stdClass') + ->addTag('kernel.event_subscriber'); $registerListenersPass = new RegisterListenersPass(); $registerListenersPass->process($builder); @@ -57,59 +38,69 @@ class RegisterListenersPassTest extends TestCase public function testValidEventSubscriber() { - $services = array( - 'my_event_subscriber' => array(0 => array()), - ); + $builder = new ContainerBuilder(); + $eventDispatcherDefinition = $builder->register('event_dispatcher'); + $builder->register('my_event_subscriber', 'Symfony\Component\EventDispatcher\Tests\DependencyInjection\SubscriberService') + ->addTag('kernel.event_subscriber'); - $definition = $this->getMockBuilder('Symfony\Component\DependencyInjection\Definition')->getMock(); - $definition->expects($this->atLeastOnce()) - ->method('getClass') - ->will($this->returnValue('Symfony\Component\EventDispatcher\Tests\DependencyInjection\SubscriberService')); - - $builder = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerBuilder')->setMethods(array('hasDefinition', 'findTaggedServiceIds', 'getDefinition', 'findDefinition'))->getMock(); - $builder->expects($this->any()) - ->method('hasDefinition') - ->will($this->returnValue(true)); - - // We don't test kernel.event_listener here - $builder->expects($this->atLeastOnce()) - ->method('findTaggedServiceIds') - ->will($this->onConsecutiveCalls(array(), $services)); + $registerListenersPass = new RegisterListenersPass(); + $registerListenersPass->process($builder); - $builder->expects($this->atLeastOnce()) - ->method('getDefinition') - ->will($this->returnValue($definition)); + $expectedCalls = [ + [ + 'addListener', + [ + 'event', + [new ServiceClosureArgument(new Reference('my_event_subscriber')), 'onEvent'], + 0, + ], + ], + ]; + $this->assertEquals($expectedCalls, $eventDispatcherDefinition->getMethodCalls()); + } - $builder->expects($this->atLeastOnce()) - ->method('findDefinition') - ->will($this->returnValue($definition)); + public function testAliasedEventSubscriber(): void + { + $builder = new ContainerBuilder(); + $builder->setParameter('event_dispatcher.event_aliases', [AliasedEvent::class => 'aliased_event']); + $builder->register('event_dispatcher'); + $builder->register('my_event_subscriber', AliasedSubscriber::class) + ->addTag('kernel.event_subscriber'); $registerListenersPass = new RegisterListenersPass(); $registerListenersPass->process($builder); + + $expectedCalls = [ + [ + 'addListener', + [ + 'aliased_event', + [new ServiceClosureArgument(new Reference('my_event_subscriber')), 'onAliasedEvent'], + 0, + ], + ], + ]; + $this->assertEquals($expectedCalls, $builder->getDefinition('event_dispatcher')->getMethodCalls()); } - /** - * @expectedException \InvalidArgumentException - * @expectedExceptionMessage The service "foo" tagged "kernel.event_listener" must not be abstract. - */ public function testAbstractEventListener() { + $this->expectException('InvalidArgumentException'); + $this->expectExceptionMessage('The service "foo" tagged "kernel.event_listener" must not be abstract.'); $container = new ContainerBuilder(); - $container->register('foo', 'stdClass')->setAbstract(true)->addTag('kernel.event_listener', array()); + $container->register('foo', 'stdClass')->setAbstract(true)->addTag('kernel.event_listener', []); $container->register('event_dispatcher', 'stdClass'); $registerListenersPass = new RegisterListenersPass(); $registerListenersPass->process($container); } - /** - * @expectedException \InvalidArgumentException - * @expectedExceptionMessage The service "foo" tagged "kernel.event_subscriber" must not be abstract. - */ public function testAbstractEventSubscriber() { + $this->expectException('InvalidArgumentException'); + $this->expectExceptionMessage('The service "foo" tagged "kernel.event_subscriber" must not be abstract.'); $container = new ContainerBuilder(); - $container->register('foo', 'stdClass')->setAbstract(true)->addTag('kernel.event_subscriber', array()); + $container->register('foo', 'stdClass')->setAbstract(true)->addTag('kernel.event_subscriber', []); $container->register('event_dispatcher', 'stdClass'); $registerListenersPass = new RegisterListenersPass(); @@ -121,23 +112,23 @@ class RegisterListenersPassTest extends TestCase $container = new ContainerBuilder(); $container->setParameter('subscriber.class', 'Symfony\Component\EventDispatcher\Tests\DependencyInjection\SubscriberService'); - $container->register('foo', '%subscriber.class%')->addTag('kernel.event_subscriber', array()); + $container->register('foo', '%subscriber.class%')->addTag('kernel.event_subscriber', []); $container->register('event_dispatcher', 'stdClass'); $registerListenersPass = new RegisterListenersPass(); $registerListenersPass->process($container); $definition = $container->getDefinition('event_dispatcher'); - $expectedCalls = array( - array( + $expectedCalls = [ + [ 'addListener', - array( + [ 'event', - array(new ServiceClosureArgument(new Reference('foo')), 'onEvent'), + [new ServiceClosureArgument(new Reference('foo')), 'onEvent'], 0, - ), - ), - ); + ], + ], + ]; $this->assertEquals($expectedCalls, $definition->getMethodCalls()); } @@ -145,35 +136,123 @@ class RegisterListenersPassTest extends TestCase { $container = new ContainerBuilder(); - $container->register('foo', SubscriberService::class)->addTag('kernel.event_subscriber', array()); + $container->register('foo', SubscriberService::class)->addTag('kernel.event_subscriber', []); $container->register('event_dispatcher', 'stdClass'); - (new RegisterListenersPass())->setHotPathEvents(array('event'))->process($container); + (new RegisterListenersPass())->setHotPathEvents(['event'])->process($container); $this->assertTrue($container->getDefinition('foo')->hasTag('container.hot_path')); } - /** - * @expectedException \InvalidArgumentException - * @expectedExceptionMessage You have requested a non-existent parameter "subscriber.class" - */ public function testEventSubscriberUnresolvableClassName() { + $this->expectException('InvalidArgumentException'); + $this->expectExceptionMessage('You have requested a non-existent parameter "subscriber.class"'); $container = new ContainerBuilder(); - $container->register('foo', '%subscriber.class%')->addTag('kernel.event_subscriber', array()); + $container->register('foo', '%subscriber.class%')->addTag('kernel.event_subscriber', []); $container->register('event_dispatcher', 'stdClass'); $registerListenersPass = new RegisterListenersPass(); $registerListenersPass->process($container); } + + public function testInvokableEventListener() + { + $container = new ContainerBuilder(); + $container->register('foo', \stdClass::class)->addTag('kernel.event_listener', ['event' => 'foo.bar']); + $container->register('bar', InvokableListenerService::class)->addTag('kernel.event_listener', ['event' => 'foo.bar']); + $container->register('baz', InvokableListenerService::class)->addTag('kernel.event_listener', ['event' => 'event']); + $container->register('event_dispatcher', \stdClass::class); + + $registerListenersPass = new RegisterListenersPass(); + $registerListenersPass->process($container); + + $definition = $container->getDefinition('event_dispatcher'); + $expectedCalls = [ + [ + 'addListener', + [ + 'foo.bar', + [new ServiceClosureArgument(new Reference('foo')), 'onFooBar'], + 0, + ], + ], + [ + 'addListener', + [ + 'foo.bar', + [new ServiceClosureArgument(new Reference('bar')), '__invoke'], + 0, + ], + ], + [ + 'addListener', + [ + 'event', + [new ServiceClosureArgument(new Reference('baz')), 'onEvent'], + 0, + ], + ], + ]; + $this->assertEquals($expectedCalls, $definition->getMethodCalls()); + } + + public function testAliasedEventListener(): void + { + $container = new ContainerBuilder(); + $container->setParameter('event_dispatcher.event_aliases', [AliasedEvent::class => 'aliased_event']); + $container->register('foo', InvokableListenerService::class)->addTag('kernel.event_listener', ['event' => AliasedEvent::class, 'method' => 'onEvent']); + $container->register('event_dispatcher'); + + $registerListenersPass = new RegisterListenersPass(); + $registerListenersPass->process($container); + + $definition = $container->getDefinition('event_dispatcher'); + $expectedCalls = [ + [ + 'addListener', + [ + 'aliased_event', + [new ServiceClosureArgument(new Reference('foo')), 'onEvent'], + 0, + ], + ], + ]; + $this->assertEquals($expectedCalls, $definition->getMethodCalls()); + } } -class SubscriberService implements \Symfony\Component\EventDispatcher\EventSubscriberInterface +class SubscriberService implements EventSubscriberInterface { public static function getSubscribedEvents() { - return array( + return [ 'event' => 'onEvent', - ); + ]; } } + +class InvokableListenerService +{ + public function __invoke() + { + } + + public function onEvent() + { + } +} + +final class AliasedSubscriber implements EventSubscriberInterface +{ + public static function getSubscribedEvents(): array + { + return [ + AliasedEvent::class => 'onAliasedEvent', + ]; + } +} + +final class AliasedEvent +{ +} diff --git a/vendor/symfony/event-dispatcher/Tests/EventDispatcherTest.php b/vendor/symfony/event-dispatcher/Tests/EventDispatcherTest.php index 5faa5c8be876a017bac80f4f970e0da775a460a5..83d10a89be7445e5e7f3e3107a4f78d1c54a16f5 100644 --- a/vendor/symfony/event-dispatcher/Tests/EventDispatcherTest.php +++ b/vendor/symfony/event-dispatcher/Tests/EventDispatcherTest.php @@ -11,12 +11,501 @@ namespace Symfony\Component\EventDispatcher\Tests; +use PHPUnit\Framework\TestCase; +use Symfony\Component\EventDispatcher\Event; use Symfony\Component\EventDispatcher\EventDispatcher; +use Symfony\Component\EventDispatcher\EventSubscriberInterface; +use Symfony\Contracts\EventDispatcher\Event as ContractsEvent; -class EventDispatcherTest extends AbstractEventDispatcherTest +class EventDispatcherTest extends TestCase { + /* Some pseudo events */ + const preFoo = 'pre.foo'; + const postFoo = 'post.foo'; + const preBar = 'pre.bar'; + const postBar = 'post.bar'; + + /** + * @var EventDispatcher + */ + private $dispatcher; + + private $listener; + + protected function setUp(): void + { + $this->dispatcher = $this->createEventDispatcher(); + $this->listener = new TestEventListener(); + } + + protected function tearDown(): void + { + $this->dispatcher = null; + $this->listener = null; + } + protected function createEventDispatcher() { return new EventDispatcher(); } + + public function testInitialState() + { + $this->assertEquals([], $this->dispatcher->getListeners()); + $this->assertFalse($this->dispatcher->hasListeners(self::preFoo)); + $this->assertFalse($this->dispatcher->hasListeners(self::postFoo)); + } + + public function testAddListener() + { + $this->dispatcher->addListener('pre.foo', [$this->listener, 'preFoo']); + $this->dispatcher->addListener('post.foo', [$this->listener, 'postFoo']); + $this->assertTrue($this->dispatcher->hasListeners()); + $this->assertTrue($this->dispatcher->hasListeners(self::preFoo)); + $this->assertTrue($this->dispatcher->hasListeners(self::postFoo)); + $this->assertCount(1, $this->dispatcher->getListeners(self::preFoo)); + $this->assertCount(1, $this->dispatcher->getListeners(self::postFoo)); + $this->assertCount(2, $this->dispatcher->getListeners()); + } + + public function testGetListenersSortsByPriority() + { + $listener1 = new TestEventListener(); + $listener2 = new TestEventListener(); + $listener3 = new TestEventListener(); + $listener1->name = '1'; + $listener2->name = '2'; + $listener3->name = '3'; + + $this->dispatcher->addListener('pre.foo', [$listener1, 'preFoo'], -10); + $this->dispatcher->addListener('pre.foo', [$listener2, 'preFoo'], 10); + $this->dispatcher->addListener('pre.foo', [$listener3, 'preFoo']); + + $expected = [ + [$listener2, 'preFoo'], + [$listener3, 'preFoo'], + [$listener1, 'preFoo'], + ]; + + $this->assertSame($expected, $this->dispatcher->getListeners('pre.foo')); + } + + public function testGetAllListenersSortsByPriority() + { + $listener1 = new TestEventListener(); + $listener2 = new TestEventListener(); + $listener3 = new TestEventListener(); + $listener4 = new TestEventListener(); + $listener5 = new TestEventListener(); + $listener6 = new TestEventListener(); + + $this->dispatcher->addListener('pre.foo', $listener1, -10); + $this->dispatcher->addListener('pre.foo', $listener2); + $this->dispatcher->addListener('pre.foo', $listener3, 10); + $this->dispatcher->addListener('post.foo', $listener4, -10); + $this->dispatcher->addListener('post.foo', $listener5); + $this->dispatcher->addListener('post.foo', $listener6, 10); + + $expected = [ + 'pre.foo' => [$listener3, $listener2, $listener1], + 'post.foo' => [$listener6, $listener5, $listener4], + ]; + + $this->assertSame($expected, $this->dispatcher->getListeners()); + } + + public function testGetListenerPriority() + { + $listener1 = new TestEventListener(); + $listener2 = new TestEventListener(); + + $this->dispatcher->addListener('pre.foo', $listener1, -10); + $this->dispatcher->addListener('pre.foo', $listener2); + + $this->assertSame(-10, $this->dispatcher->getListenerPriority('pre.foo', $listener1)); + $this->assertSame(0, $this->dispatcher->getListenerPriority('pre.foo', $listener2)); + $this->assertNull($this->dispatcher->getListenerPriority('pre.bar', $listener2)); + $this->assertNull($this->dispatcher->getListenerPriority('pre.foo', function () {})); + } + + public function testDispatch() + { + $this->dispatcher->addListener('pre.foo', [$this->listener, 'preFoo']); + $this->dispatcher->addListener('post.foo', [$this->listener, 'postFoo']); + $this->dispatcher->dispatch(new Event(), self::preFoo); + $this->assertTrue($this->listener->preFooInvoked); + $this->assertFalse($this->listener->postFooInvoked); + $this->assertInstanceOf('Symfony\Component\EventDispatcher\Event', $this->dispatcher->dispatch(new Event(), 'noevent')); + $this->assertInstanceOf('Symfony\Component\EventDispatcher\Event', $this->dispatcher->dispatch(new Event(), self::preFoo)); + $event = new Event(); + $return = $this->dispatcher->dispatch($event, self::preFoo); + $this->assertSame($event, $return); + } + + public function testDispatchContractsEvent() + { + $this->dispatcher->addListener('pre.foo', [$this->listener, 'preFoo']); + $this->dispatcher->addListener('post.foo', [$this->listener, 'postFoo']); + $this->dispatcher->dispatch(new ContractsEvent(), self::preFoo); + $this->assertTrue($this->listener->preFooInvoked); + $this->assertFalse($this->listener->postFooInvoked); + $this->assertInstanceOf('Symfony\Component\EventDispatcher\Event', $this->dispatcher->dispatch(new Event(), 'noevent')); + $this->assertInstanceOf('Symfony\Component\EventDispatcher\Event', $this->dispatcher->dispatch(new Event(), self::preFoo)); + $event = new Event(); + $return = $this->dispatcher->dispatch($event, self::preFoo); + $this->assertSame($event, $return); + } + + public function testDispatchForClosure() + { + $invoked = 0; + $listener = function () use (&$invoked) { + ++$invoked; + }; + $this->dispatcher->addListener('pre.foo', $listener); + $this->dispatcher->addListener('post.foo', $listener); + $this->dispatcher->dispatch(new Event(), self::preFoo); + $this->assertEquals(1, $invoked); + } + + public function testStopEventPropagation() + { + $otherListener = new TestEventListener(); + + // postFoo() stops the propagation, so only one listener should + // be executed + // Manually set priority to enforce $this->listener to be called first + $this->dispatcher->addListener('post.foo', [$this->listener, 'postFoo'], 10); + $this->dispatcher->addListener('post.foo', [$otherListener, 'postFoo']); + $this->dispatcher->dispatch(new Event(), self::postFoo); + $this->assertTrue($this->listener->postFooInvoked); + $this->assertFalse($otherListener->postFooInvoked); + } + + public function testDispatchByPriority() + { + $invoked = []; + $listener1 = function () use (&$invoked) { + $invoked[] = '1'; + }; + $listener2 = function () use (&$invoked) { + $invoked[] = '2'; + }; + $listener3 = function () use (&$invoked) { + $invoked[] = '3'; + }; + $this->dispatcher->addListener('pre.foo', $listener1, -10); + $this->dispatcher->addListener('pre.foo', $listener2); + $this->dispatcher->addListener('pre.foo', $listener3, 10); + $this->dispatcher->dispatch(new Event(), self::preFoo); + $this->assertEquals(['3', '2', '1'], $invoked); + } + + public function testRemoveListener() + { + $this->dispatcher->addListener('pre.bar', $this->listener); + $this->assertTrue($this->dispatcher->hasListeners(self::preBar)); + $this->dispatcher->removeListener('pre.bar', $this->listener); + $this->assertFalse($this->dispatcher->hasListeners(self::preBar)); + $this->dispatcher->removeListener('notExists', $this->listener); + } + + public function testAddSubscriber() + { + $eventSubscriber = new TestEventSubscriber(); + $this->dispatcher->addSubscriber($eventSubscriber); + $this->assertTrue($this->dispatcher->hasListeners(self::preFoo)); + $this->assertTrue($this->dispatcher->hasListeners(self::postFoo)); + } + + public function testAddSubscriberWithPriorities() + { + $eventSubscriber = new TestEventSubscriber(); + $this->dispatcher->addSubscriber($eventSubscriber); + + $eventSubscriber = new TestEventSubscriberWithPriorities(); + $this->dispatcher->addSubscriber($eventSubscriber); + + $listeners = $this->dispatcher->getListeners('pre.foo'); + $this->assertTrue($this->dispatcher->hasListeners(self::preFoo)); + $this->assertCount(2, $listeners); + $this->assertInstanceOf('Symfony\Component\EventDispatcher\Tests\TestEventSubscriberWithPriorities', $listeners[0][0]); + } + + public function testAddSubscriberWithMultipleListeners() + { + $eventSubscriber = new TestEventSubscriberWithMultipleListeners(); + $this->dispatcher->addSubscriber($eventSubscriber); + + $listeners = $this->dispatcher->getListeners('pre.foo'); + $this->assertTrue($this->dispatcher->hasListeners(self::preFoo)); + $this->assertCount(2, $listeners); + $this->assertEquals('preFoo2', $listeners[0][1]); + } + + public function testRemoveSubscriber() + { + $eventSubscriber = new TestEventSubscriber(); + $this->dispatcher->addSubscriber($eventSubscriber); + $this->assertTrue($this->dispatcher->hasListeners(self::preFoo)); + $this->assertTrue($this->dispatcher->hasListeners(self::postFoo)); + $this->dispatcher->removeSubscriber($eventSubscriber); + $this->assertFalse($this->dispatcher->hasListeners(self::preFoo)); + $this->assertFalse($this->dispatcher->hasListeners(self::postFoo)); + } + + public function testRemoveSubscriberWithPriorities() + { + $eventSubscriber = new TestEventSubscriberWithPriorities(); + $this->dispatcher->addSubscriber($eventSubscriber); + $this->assertTrue($this->dispatcher->hasListeners(self::preFoo)); + $this->dispatcher->removeSubscriber($eventSubscriber); + $this->assertFalse($this->dispatcher->hasListeners(self::preFoo)); + } + + public function testRemoveSubscriberWithMultipleListeners() + { + $eventSubscriber = new TestEventSubscriberWithMultipleListeners(); + $this->dispatcher->addSubscriber($eventSubscriber); + $this->assertTrue($this->dispatcher->hasListeners(self::preFoo)); + $this->assertCount(2, $this->dispatcher->getListeners(self::preFoo)); + $this->dispatcher->removeSubscriber($eventSubscriber); + $this->assertFalse($this->dispatcher->hasListeners(self::preFoo)); + } + + public function testEventReceivesTheDispatcherInstanceAsArgument() + { + $listener = new TestWithDispatcher(); + $this->dispatcher->addListener('test', [$listener, 'foo']); + $this->assertNull($listener->name); + $this->assertNull($listener->dispatcher); + $this->dispatcher->dispatch(new Event(), 'test'); + $this->assertEquals('test', $listener->name); + $this->assertSame($this->dispatcher, $listener->dispatcher); + } + + /** + * @see https://bugs.php.net/62976 + * + * This bug affects: + * - The PHP 5.3 branch for versions < 5.3.18 + * - The PHP 5.4 branch for versions < 5.4.8 + * - The PHP 5.5 branch is not affected + */ + public function testWorkaroundForPhpBug62976() + { + $dispatcher = $this->createEventDispatcher(); + $dispatcher->addListener('bug.62976', new CallableClass()); + $dispatcher->removeListener('bug.62976', function () {}); + $this->assertTrue($dispatcher->hasListeners('bug.62976')); + } + + public function testHasListenersWhenAddedCallbackListenerIsRemoved() + { + $listener = function () {}; + $this->dispatcher->addListener('foo', $listener); + $this->dispatcher->removeListener('foo', $listener); + $this->assertFalse($this->dispatcher->hasListeners()); + } + + public function testGetListenersWhenAddedCallbackListenerIsRemoved() + { + $listener = function () {}; + $this->dispatcher->addListener('foo', $listener); + $this->dispatcher->removeListener('foo', $listener); + $this->assertSame([], $this->dispatcher->getListeners()); + } + + public function testHasListenersWithoutEventsReturnsFalseAfterHasListenersWithEventHasBeenCalled() + { + $this->assertFalse($this->dispatcher->hasListeners('foo')); + $this->assertFalse($this->dispatcher->hasListeners()); + } + + public function testHasListenersIsLazy() + { + $called = 0; + $listener = [function () use (&$called) { ++$called; }, 'onFoo']; + $this->dispatcher->addListener('foo', $listener); + $this->assertTrue($this->dispatcher->hasListeners()); + $this->assertTrue($this->dispatcher->hasListeners('foo')); + $this->assertSame(0, $called); + } + + public function testDispatchLazyListener() + { + $called = 0; + $factory = function () use (&$called) { + ++$called; + + return new TestWithDispatcher(); + }; + $this->dispatcher->addListener('foo', [$factory, 'foo']); + $this->assertSame(0, $called); + $this->dispatcher->dispatch(new Event(), 'foo'); + $this->dispatcher->dispatch(new Event(), 'foo'); + $this->assertSame(1, $called); + } + + public function testRemoveFindsLazyListeners() + { + $test = new TestWithDispatcher(); + $factory = function () use ($test) { return $test; }; + + $this->dispatcher->addListener('foo', [$factory, 'foo']); + $this->assertTrue($this->dispatcher->hasListeners('foo')); + $this->dispatcher->removeListener('foo', [$test, 'foo']); + $this->assertFalse($this->dispatcher->hasListeners('foo')); + + $this->dispatcher->addListener('foo', [$test, 'foo']); + $this->assertTrue($this->dispatcher->hasListeners('foo')); + $this->dispatcher->removeListener('foo', [$factory, 'foo']); + $this->assertFalse($this->dispatcher->hasListeners('foo')); + } + + public function testPriorityFindsLazyListeners() + { + $test = new TestWithDispatcher(); + $factory = function () use ($test) { return $test; }; + + $this->dispatcher->addListener('foo', [$factory, 'foo'], 3); + $this->assertSame(3, $this->dispatcher->getListenerPriority('foo', [$test, 'foo'])); + $this->dispatcher->removeListener('foo', [$factory, 'foo']); + + $this->dispatcher->addListener('foo', [$test, 'foo'], 5); + $this->assertSame(5, $this->dispatcher->getListenerPriority('foo', [$factory, 'foo'])); + } + + public function testGetLazyListeners() + { + $test = new TestWithDispatcher(); + $factory = function () use ($test) { return $test; }; + + $this->dispatcher->addListener('foo', [$factory, 'foo'], 3); + $this->assertSame([[$test, 'foo']], $this->dispatcher->getListeners('foo')); + + $this->dispatcher->removeListener('foo', [$test, 'foo']); + $this->dispatcher->addListener('bar', [$factory, 'foo'], 3); + $this->assertSame(['bar' => [[$test, 'foo']]], $this->dispatcher->getListeners()); + } + + public function testMutatingWhilePropagationIsStopped() + { + $testLoaded = false; + $test = new TestEventListener(); + $this->dispatcher->addListener('foo', [$test, 'postFoo']); + $this->dispatcher->addListener('foo', [function () use ($test, &$testLoaded) { + $testLoaded = true; + + return $test; + }, 'preFoo']); + + $this->dispatcher->dispatch(new Event(), 'foo'); + + $this->assertTrue($test->postFooInvoked); + $this->assertFalse($test->preFooInvoked); + + $this->assertsame(0, $this->dispatcher->getListenerPriority('foo', [$test, 'preFoo'])); + + $test->preFoo(new Event()); + $this->dispatcher->dispatch(new Event(), 'foo'); + + $this->assertTrue($testLoaded); + } + + /** + * @group legacy + * @expectedDeprecation Calling the "Symfony\Component\EventDispatcher\EventDispatcherInterface::dispatch()" method with the event name as the first argument is deprecated since Symfony 4.3, pass it as the second argument and provide the event object as the first argument instead. + */ + public function testLegacySignatureWithoutEvent() + { + $this->dispatcher->dispatch('foo'); + } + + /** + * @group legacy + * @expectedDeprecation Calling the "Symfony\Component\EventDispatcher\EventDispatcherInterface::dispatch()" method with the event name as the first argument is deprecated since Symfony 4.3, pass it as the second argument and provide the event object as the first argument instead. + */ + public function testLegacySignatureWithEvent() + { + $this->dispatcher->dispatch('foo', new Event()); + } + + public function testLegacySignatureWithNewEventObject() + { + $this->expectException('TypeError'); + $this->expectExceptionMessage('Argument 1 passed to "Symfony\Component\EventDispatcher\EventDispatcherInterface::dispatch()" must be an object, string given.'); + $this->dispatcher->dispatch('foo', new ContractsEvent()); + } +} + +class CallableClass +{ + public function __invoke() + { + } +} + +class TestEventListener +{ + public $preFooInvoked = false; + public $postFooInvoked = false; + + /* Listener methods */ + + public function preFoo($e) + { + $this->preFooInvoked = true; + } + + public function postFoo($e) + { + $this->postFooInvoked = true; + + if (!$this->preFooInvoked) { + $e->stopPropagation(); + } + } +} + +class TestWithDispatcher +{ + public $name; + public $dispatcher; + + public function foo($e, $name, $dispatcher) + { + $this->name = $name; + $this->dispatcher = $dispatcher; + } +} + +class TestEventSubscriber implements EventSubscriberInterface +{ + public static function getSubscribedEvents() + { + return ['pre.foo' => 'preFoo', 'post.foo' => 'postFoo']; + } +} + +class TestEventSubscriberWithPriorities implements EventSubscriberInterface +{ + public static function getSubscribedEvents() + { + return [ + 'pre.foo' => ['preFoo', 10], + 'post.foo' => ['postFoo'], + ]; + } +} + +class TestEventSubscriberWithMultipleListeners implements EventSubscriberInterface +{ + public static function getSubscribedEvents() + { + return ['pre.foo' => [ + ['preFoo1'], + ['preFoo2', 10], + ]]; + } } diff --git a/vendor/symfony/event-dispatcher/Tests/EventTest.php b/vendor/symfony/event-dispatcher/Tests/EventTest.php index 5be2ea09f9d2f8536108f7dda930844a2f83fb46..34ed3ba70ec4afd3ff4335e5d33667f52180fe99 100644 --- a/vendor/symfony/event-dispatcher/Tests/EventTest.php +++ b/vendor/symfony/event-dispatcher/Tests/EventTest.php @@ -15,7 +15,7 @@ use PHPUnit\Framework\TestCase; use Symfony\Component\EventDispatcher\Event; /** - * Test class for Event. + * @group legacy */ class EventTest extends TestCase { @@ -28,7 +28,7 @@ class EventTest extends TestCase * Sets up the fixture, for example, opens a network connection. * This method is called before a test is executed. */ - protected function setUp() + protected function setUp(): void { $this->event = new Event(); } @@ -37,7 +37,7 @@ class EventTest extends TestCase * Tears down the fixture, for example, closes a network connection. * This method is called after a test is executed. */ - protected function tearDown() + protected function tearDown(): void { $this->event = null; } diff --git a/vendor/symfony/event-dispatcher/Tests/GenericEventTest.php b/vendor/symfony/event-dispatcher/Tests/GenericEventTest.php index 9cf68c987f0da4821bb9dde0748ace073d13e2d7..484e1a5f3e11a0021a3d7dff2f5e845db467afd1 100644 --- a/vendor/symfony/event-dispatcher/Tests/GenericEventTest.php +++ b/vendor/symfony/event-dispatcher/Tests/GenericEventTest.php @@ -29,28 +29,24 @@ class GenericEventTest extends TestCase /** * Prepares the environment before running a test. */ - protected function setUp() + protected function setUp(): void { - parent::setUp(); - $this->subject = new \stdClass(); - $this->event = new GenericEvent($this->subject, array('name' => 'Event')); + $this->event = new GenericEvent($this->subject, ['name' => 'Event']); } /** * Cleans up the environment after running a test. */ - protected function tearDown() + protected function tearDown(): void { $this->subject = null; $this->event = null; - - parent::tearDown(); } public function testConstruct() { - $this->assertEquals($this->event, new GenericEvent($this->subject, array('name' => 'Event'))); + $this->assertEquals($this->event, new GenericEvent($this->subject, ['name' => 'Event'])); } /** @@ -59,20 +55,20 @@ class GenericEventTest extends TestCase public function testGetArguments() { // test getting all - $this->assertSame(array('name' => 'Event'), $this->event->getArguments()); + $this->assertSame(['name' => 'Event'], $this->event->getArguments()); } public function testSetArguments() { - $result = $this->event->setArguments(array('foo' => 'bar')); - $this->assertAttributeSame(array('foo' => 'bar'), 'arguments', $this->event); + $result = $this->event->setArguments(['foo' => 'bar']); + $this->assertSame(['foo' => 'bar'], $this->event->getArguments()); $this->assertSame($this->event, $result); } public function testSetArgument() { $result = $this->event->setArgument('foo2', 'bar2'); - $this->assertAttributeSame(array('name' => 'Event', 'foo2' => 'bar2'), 'arguments', $this->event); + $this->assertSame(['name' => 'Event', 'foo2' => 'bar2'], $this->event->getArguments()); $this->assertEquals($this->event, $result); } @@ -82,11 +78,9 @@ class GenericEventTest extends TestCase $this->assertEquals('Event', $this->event->getArgument('name')); } - /** - * @expectedException \InvalidArgumentException - */ public function testGetArgException() { + $this->expectException('\InvalidArgumentException'); $this->event->getArgument('nameNotExist'); } @@ -96,20 +90,20 @@ class GenericEventTest extends TestCase $this->assertEquals('Event', $this->event['name']); // test getting invalid arg - $this->{method_exists($this, $_ = 'expectException') ? $_ : 'setExpectedException'}('InvalidArgumentException'); + $this->expectException('InvalidArgumentException'); $this->assertFalse($this->event['nameNotExist']); } public function testOffsetSet() { $this->event['foo2'] = 'bar2'; - $this->assertAttributeSame(array('name' => 'Event', 'foo2' => 'bar2'), 'arguments', $this->event); + $this->assertSame(['name' => 'Event', 'foo2' => 'bar2'], $this->event->getArguments()); } public function testOffsetUnset() { unset($this->event['name']); - $this->assertAttributeSame(array(), 'arguments', $this->event); + $this->assertSame([], $this->event->getArguments()); } public function testOffsetIsset() @@ -131,10 +125,10 @@ class GenericEventTest extends TestCase public function testHasIterator() { - $data = array(); + $data = []; foreach ($this->event as $key => $value) { $data[$key] = $value; } - $this->assertEquals(array('name' => 'Event'), $data); + $this->assertEquals(['name' => 'Event'], $data); } } diff --git a/vendor/symfony/event-dispatcher/Tests/ImmutableEventDispatcherTest.php b/vendor/symfony/event-dispatcher/Tests/ImmutableEventDispatcherTest.php index 04f2861e331934d9442821c063a691ae4ec76fb7..edce6f199d30d63bcf12223d0b3f1b621f7795a3 100644 --- a/vendor/symfony/event-dispatcher/Tests/ImmutableEventDispatcherTest.php +++ b/vendor/symfony/event-dispatcher/Tests/ImmutableEventDispatcherTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\EventDispatcher\Tests; +use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Symfony\Component\EventDispatcher\Event; use Symfony\Component\EventDispatcher\ImmutableEventDispatcher; @@ -21,7 +22,7 @@ use Symfony\Component\EventDispatcher\ImmutableEventDispatcher; class ImmutableEventDispatcherTest extends TestCase { /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var MockObject */ private $innerDispatcher; @@ -30,7 +31,7 @@ class ImmutableEventDispatcherTest extends TestCase */ private $dispatcher; - protected function setUp() + protected function setUp(): void { $this->innerDispatcher = $this->getMockBuilder('Symfony\Component\EventDispatcher\EventDispatcherInterface')->getMock(); $this->dispatcher = new ImmutableEventDispatcher($this->innerDispatcher); @@ -39,13 +40,14 @@ class ImmutableEventDispatcherTest extends TestCase public function testDispatchDelegates() { $event = new Event(); + $resultEvent = new Event(); $this->innerDispatcher->expects($this->once()) ->method('dispatch') - ->with('event', $event) - ->will($this->returnValue('result')); + ->with($event, 'event') + ->willReturn($resultEvent); - $this->assertSame('result', $this->dispatcher->dispatch('event', $event)); + $this->assertSame($resultEvent, $this->dispatcher->dispatch('event', $event)); } public function testGetListenersDelegates() @@ -53,9 +55,9 @@ class ImmutableEventDispatcherTest extends TestCase $this->innerDispatcher->expects($this->once()) ->method('getListeners') ->with('event') - ->will($this->returnValue('result')); + ->willReturn(['result']); - $this->assertSame('result', $this->dispatcher->getListeners('event')); + $this->assertSame(['result'], $this->dispatcher->getListeners('event')); } public function testHasListenersDelegates() @@ -63,42 +65,34 @@ class ImmutableEventDispatcherTest extends TestCase $this->innerDispatcher->expects($this->once()) ->method('hasListeners') ->with('event') - ->will($this->returnValue('result')); + ->willReturn(true); - $this->assertSame('result', $this->dispatcher->hasListeners('event')); + $this->assertTrue($this->dispatcher->hasListeners('event')); } - /** - * @expectedException \BadMethodCallException - */ public function testAddListenerDisallowed() { + $this->expectException('\BadMethodCallException'); $this->dispatcher->addListener('event', function () { return 'foo'; }); } - /** - * @expectedException \BadMethodCallException - */ public function testAddSubscriberDisallowed() { + $this->expectException('\BadMethodCallException'); $subscriber = $this->getMockBuilder('Symfony\Component\EventDispatcher\EventSubscriberInterface')->getMock(); $this->dispatcher->addSubscriber($subscriber); } - /** - * @expectedException \BadMethodCallException - */ public function testRemoveListenerDisallowed() { + $this->expectException('\BadMethodCallException'); $this->dispatcher->removeListener('event', function () { return 'foo'; }); } - /** - * @expectedException \BadMethodCallException - */ public function testRemoveSubscriberDisallowed() { + $this->expectException('\BadMethodCallException'); $subscriber = $this->getMockBuilder('Symfony\Component\EventDispatcher\EventSubscriberInterface')->getMock(); $this->dispatcher->removeSubscriber($subscriber); diff --git a/vendor/symfony/event-dispatcher/Tests/LegacyEventDispatcherTest.php b/vendor/symfony/event-dispatcher/Tests/LegacyEventDispatcherTest.php new file mode 100644 index 0000000000000000000000000000000000000000..30bd0c33463bd85f9d3cdbd00e7cde157005e506 --- /dev/null +++ b/vendor/symfony/event-dispatcher/Tests/LegacyEventDispatcherTest.php @@ -0,0 +1,63 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\EventDispatcher\Tests; + +use Symfony\Component\EventDispatcher\Event; +use Symfony\Component\EventDispatcher\EventDispatcher; +use Symfony\Component\EventDispatcher\LegacyEventDispatcherProxy; +use Symfony\Contracts\EventDispatcher\Event as ContractsEvent; + +/** + * @group legacy + */ +class LegacyEventDispatcherTest extends EventDispatcherTest +{ + /** + * @group legacy + * @expectedDeprecation The signature of the "Symfony\Component\EventDispatcher\Tests\TestLegacyEventDispatcher::dispatch()" method should be updated to "dispatch($event, string $eventName = null)", not doing so is deprecated since Symfony 4.3. + * @expectedDeprecation Calling the "Symfony\Contracts\EventDispatcher\EventDispatcherInterface::dispatch()" method with the event name as the first argument is deprecated since Symfony 4.3, pass it as the second argument and provide the event object as the first argument instead. + */ + public function testLegacySignatureWithoutEvent() + { + $this->createEventDispatcher()->dispatch('foo'); + } + + /** + * @group legacy + * @expectedDeprecation The signature of the "Symfony\Component\EventDispatcher\Tests\TestLegacyEventDispatcher::dispatch()" method should be updated to "dispatch($event, string $eventName = null)", not doing so is deprecated since Symfony 4.3. + * @expectedDeprecation Calling the "Symfony\Contracts\EventDispatcher\EventDispatcherInterface::dispatch()" method with the event name as the first argument is deprecated since Symfony 4.3, pass it as the second argument and provide the event object as the first argument instead. + */ + public function testLegacySignatureWithEvent() + { + $this->createEventDispatcher()->dispatch('foo', new Event()); + } + + public function testLegacySignatureWithNewEventObject() + { + $this->expectException('TypeError'); + $this->expectExceptionMessage('Argument 1 passed to "Symfony\Contracts\EventDispatcher\EventDispatcherInterface::dispatch()" must be an object, string given.'); + $this->createEventDispatcher()->dispatch('foo', new ContractsEvent()); + } + + protected function createEventDispatcher() + { + return LegacyEventDispatcherProxy::decorate(new TestLegacyEventDispatcher()); + } +} + +class TestLegacyEventDispatcher extends EventDispatcher +{ + public function dispatch($eventName, Event $event = null) + { + return parent::dispatch($event, $eventName); + } +} diff --git a/vendor/symfony/event-dispatcher/composer.json b/vendor/symfony/event-dispatcher/composer.json index 75b881b917cd9a7d6b3831c1c5d0cb0ae7d32a77..8449c4785d93a59079e5601dc0201fa5bc6b4931 100644 --- a/vendor/symfony/event-dispatcher/composer.json +++ b/vendor/symfony/event-dispatcher/composer.json @@ -16,17 +16,24 @@ } ], "require": { - "php": "^5.5.9|>=7.0.8" + "php": "^7.1.3", + "symfony/event-dispatcher-contracts": "^1.1" }, "require-dev": { - "symfony/dependency-injection": "~3.3|~4.0", - "symfony/expression-language": "~2.8|~3.0|~4.0", - "symfony/config": "~2.8|~3.0|~4.0", - "symfony/stopwatch": "~2.8|~3.0|~4.0", + "symfony/dependency-injection": "~3.4|~4.0", + "symfony/expression-language": "~3.4|~4.0", + "symfony/config": "~3.4|~4.0", + "symfony/http-foundation": "^3.4|^4.0", + "symfony/service-contracts": "^1.1", + "symfony/stopwatch": "~3.4|~4.0", "psr/log": "~1.0" }, "conflict": { - "symfony/dependency-injection": "<3.3" + "symfony/dependency-injection": "<3.4" + }, + "provide": { + "psr/event-dispatcher-implementation": "1.0", + "symfony/event-dispatcher-implementation": "1.1" }, "suggest": { "symfony/dependency-injection": "", @@ -41,7 +48,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-master": "3.4-dev" + "dev-master": "4.3-dev" } } } diff --git a/vendor/symfony/event-dispatcher/phpunit.xml.dist b/vendor/symfony/event-dispatcher/phpunit.xml.dist index b3ad1bdf5a8e3344357ea623024e7fdfe18b3d8f..f2eb1692cdbbab8633d66aa8b109e017821ed3d8 100644 --- a/vendor/symfony/event-dispatcher/phpunit.xml.dist +++ b/vendor/symfony/event-dispatcher/phpunit.xml.dist @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="UTF-8"?> <phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/4.1/phpunit.xsd" + xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/5.2/phpunit.xsd" backupGlobals="false" colors="true" bootstrap="vendor/autoload.php" diff --git a/vendor/symfony/http-foundation/AcceptHeader.php b/vendor/symfony/http-foundation/AcceptHeader.php index d1740266b7a806d56372c3af4395d551f65d0a0f..3f5fbb8f3b5cd510825888f55a39a8f297839f0e 100644 --- a/vendor/symfony/http-foundation/AcceptHeader.php +++ b/vendor/symfony/http-foundation/AcceptHeader.php @@ -24,7 +24,7 @@ class AcceptHeader /** * @var AcceptHeaderItem[] */ - private $items = array(); + private $items = []; /** * @var bool @@ -52,12 +52,17 @@ class AcceptHeader { $index = 0; - return new self(array_map(function ($itemValue) use (&$index) { - $item = AcceptHeaderItem::fromString($itemValue); + $parts = HeaderUtils::split((string) $headerValue, ',;='); + + return new self(array_map(function ($subParts) use (&$index) { + $part = array_shift($subParts); + $attributes = HeaderUtils::combine($subParts); + + $item = new AcceptHeaderItem($part[0], $attributes); $item->setIndex($index++); return $item; - }, preg_split('/\s*(?:,*("[^"]+"),*|,*(\'[^\']+\'),*|,+)\s*/', $headerValue, 0, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE))); + }, $parts)); } /** @@ -91,7 +96,7 @@ class AcceptHeader */ public function get($value) { - return isset($this->items[$value]) ? $this->items[$value] : null; + return $this->items[$value] ?? $this->items[explode('/', $value)[0].'/*'] ?? $this->items['*/*'] ?? $this->items['*'] ?? null; } /** diff --git a/vendor/symfony/http-foundation/AcceptHeaderItem.php b/vendor/symfony/http-foundation/AcceptHeaderItem.php index c69dbbba3566366fc1f9d4e2f12271851793dcd2..954aac60145442c5b46c08951bb8fbea58a2a5ee 100644 --- a/vendor/symfony/http-foundation/AcceptHeaderItem.php +++ b/vendor/symfony/http-foundation/AcceptHeaderItem.php @@ -21,13 +21,9 @@ class AcceptHeaderItem private $value; private $quality = 1.0; private $index = 0; - private $attributes = array(); + private $attributes = []; - /** - * @param string $value - * @param array $attributes - */ - public function __construct($value, array $attributes = array()) + public function __construct(string $value, array $attributes = []) { $this->value = $value; foreach ($attributes as $name => $value) { @@ -44,38 +40,24 @@ class AcceptHeaderItem */ public static function fromString($itemValue) { - $bits = preg_split('/\s*(?:;*("[^"]+");*|;*(\'[^\']+\');*|;+)\s*/', $itemValue, 0, PREG_SPLIT_NO_EMPTY | PREG_SPLIT_DELIM_CAPTURE); - $value = array_shift($bits); - $attributes = array(); - - $lastNullAttribute = null; - foreach ($bits as $bit) { - if (($start = substr($bit, 0, 1)) === ($end = substr($bit, -1)) && ('"' === $start || '\'' === $start)) { - $attributes[$lastNullAttribute] = substr($bit, 1, -1); - } elseif ('=' === $end) { - $lastNullAttribute = $bit = substr($bit, 0, -1); - $attributes[$bit] = null; - } else { - $parts = explode('=', $bit); - $attributes[$parts[0]] = isset($parts[1]) && strlen($parts[1]) > 0 ? $parts[1] : ''; - } - } + $parts = HeaderUtils::split($itemValue, ';='); + + $part = array_shift($parts); + $attributes = HeaderUtils::combine($parts); - return new self(($start = substr($value, 0, 1)) === ($end = substr($value, -1)) && ('"' === $start || '\'' === $start) ? substr($value, 1, -1) : $value, $attributes); + return new self($part[0], $attributes); } /** - * Returns header value's string representation. + * Returns header value's string representation. * * @return string */ public function __toString() { $string = $this->value.($this->quality < 1 ? ';q='.$this->quality : ''); - if (count($this->attributes) > 0) { - $string .= ';'.implode(';', array_map(function ($name, $value) { - return sprintf(preg_match('/[,;=]/', $value) ? '%s="%s"' : '%s=%s', $name, $value); - }, array_keys($this->attributes), $this->attributes)); + if (\count($this->attributes) > 0) { + $string .= '; '.HeaderUtils::toString($this->attributes, ';'); } return $string; diff --git a/vendor/symfony/http-foundation/ApacheRequest.php b/vendor/symfony/http-foundation/ApacheRequest.php index 84803ebae28fdca5f79f93934317d50ae9109c3f..4e99186dcd503d9ae5d82e7d34c92a418ed439b3 100644 --- a/vendor/symfony/http-foundation/ApacheRequest.php +++ b/vendor/symfony/http-foundation/ApacheRequest.php @@ -35,7 +35,7 @@ class ApacheRequest extends Request if (false === strpos($this->server->get('REQUEST_URI'), $baseUrl)) { // assume mod_rewrite - return rtrim(dirname($baseUrl), '/\\'); + return rtrim(\dirname($baseUrl), '/\\'); } return $baseUrl; diff --git a/vendor/symfony/http-foundation/BinaryFileResponse.php b/vendor/symfony/http-foundation/BinaryFileResponse.php index 1010223042ef574dbb7b01ba009481de79b509f7..de3c159b08f4e9dc2f1df032f0b05ef40a88c4a5 100644 --- a/vendor/symfony/http-foundation/BinaryFileResponse.php +++ b/vendor/symfony/http-foundation/BinaryFileResponse.php @@ -11,8 +11,8 @@ namespace Symfony\Component\HttpFoundation; -use Symfony\Component\HttpFoundation\File\File; use Symfony\Component\HttpFoundation\File\Exception\FileException; +use Symfony\Component\HttpFoundation\File\File; /** * BinaryFileResponse represents an HTTP response delivering a file. @@ -31,8 +31,8 @@ class BinaryFileResponse extends Response * @var File */ protected $file; - protected $offset; - protected $maxlen; + protected $offset = 0; + protected $maxlen = -1; protected $deleteFileAfterSend = false; /** @@ -40,11 +40,11 @@ class BinaryFileResponse extends Response * @param int $status The response status code * @param array $headers An array of response headers * @param bool $public Files are public by default - * @param null|string $contentDisposition The type of Content-Disposition to set automatically with the filename + * @param string|null $contentDisposition The type of Content-Disposition to set automatically with the filename * @param bool $autoEtag Whether the ETag header should be automatically set * @param bool $autoLastModified Whether the Last-Modified header should be automatically set */ - public function __construct($file, $status = 200, $headers = array(), $public = true, $contentDisposition = null, $autoEtag = false, $autoLastModified = true) + public function __construct($file, int $status = 200, array $headers = [], bool $public = true, string $contentDisposition = null, bool $autoEtag = false, bool $autoLastModified = true) { parent::__construct(null, $status, $headers); @@ -60,13 +60,13 @@ class BinaryFileResponse extends Response * @param int $status The response status code * @param array $headers An array of response headers * @param bool $public Files are public by default - * @param null|string $contentDisposition The type of Content-Disposition to set automatically with the filename + * @param string|null $contentDisposition The type of Content-Disposition to set automatically with the filename * @param bool $autoEtag Whether the ETag header should be automatically set * @param bool $autoLastModified Whether the Last-Modified header should be automatically set * * @return static */ - public static function create($file = null, $status = 200, $headers = array(), $public = true, $contentDisposition = null, $autoEtag = false, $autoLastModified = true) + public static function create($file = null, $status = 200, $headers = [], $public = true, $contentDisposition = null, $autoEtag = false, $autoLastModified = true) { return new static($file, $status, $headers, $public, $contentDisposition, $autoEtag, $autoLastModified); } @@ -165,7 +165,7 @@ class BinaryFileResponse extends Response for ($i = 0, $filenameLength = mb_strlen($filename, $encoding); $i < $filenameLength; ++$i) { $char = mb_substr($filename, $i, 1, $encoding); - if ('%' === $char || ord($char) < 32 || ord($char) > 126) { + if ('%' === $char || \ord($char) < 32 || \ord($char) > 126) { $filenameFallback .= '_'; } else { $filenameFallback .= $char; @@ -218,28 +218,28 @@ class BinaryFileResponse extends Response if ('x-accel-redirect' === strtolower($type)) { // Do X-Accel-Mapping substitutions. // @link http://wiki.nginx.org/X-accel#X-Accel-Redirect - foreach (explode(',', $request->headers->get('X-Accel-Mapping', '')) as $mapping) { - $mapping = explode('=', $mapping, 2); - - if (2 === count($mapping)) { - $pathPrefix = trim($mapping[0]); - $location = trim($mapping[1]); - - if (substr($path, 0, strlen($pathPrefix)) === $pathPrefix) { - $path = $location.substr($path, strlen($pathPrefix)); - break; - } + $parts = HeaderUtils::split($request->headers->get('X-Accel-Mapping', ''), ',='); + foreach ($parts as $part) { + list($pathPrefix, $location) = $part; + if (substr($path, 0, \strlen($pathPrefix)) === $pathPrefix) { + $path = $location.substr($path, \strlen($pathPrefix)); + // Only set X-Accel-Redirect header if a valid URI can be produced + // as nginx does not serve arbitrary file paths. + $this->headers->set($type, $path); + $this->maxlen = 0; + break; } } + } else { + $this->headers->set($type, $path); + $this->maxlen = 0; } - $this->headers->set($type, $path); - $this->maxlen = 0; } elseif ($request->headers->has('Range')) { // Process the range headers. if (!$request->headers->has('If-Range') || $this->hasValidIfRangeHeader($request->headers->get('If-Range'))) { $range = $request->headers->get('Range'); - list($start, $end) = explode('-', substr($range, 6), 2) + array(0); + list($start, $end) = explode('-', substr($range, 6), 2) + [0]; $end = ('' === $end) ? $fileSize - 1 : (int) $end; @@ -305,7 +305,7 @@ class BinaryFileResponse extends Response fclose($out); fclose($file); - if ($this->deleteFileAfterSend) { + if ($this->deleteFileAfterSend && file_exists($this->file->getPathname())) { unlink($this->file->getPathname()); } @@ -322,12 +322,12 @@ class BinaryFileResponse extends Response if (null !== $content) { throw new \LogicException('The content cannot be set on a BinaryFileResponse instance.'); } + + return $this; } /** * {@inheritdoc} - * - * @return false */ public function getContent() { @@ -350,7 +350,7 @@ class BinaryFileResponse extends Response * * @return $this */ - public function deleteFileAfterSend($shouldDelete) + public function deleteFileAfterSend($shouldDelete = true) { $this->deleteFileAfterSend = $shouldDelete; diff --git a/vendor/symfony/http-foundation/CHANGELOG.md b/vendor/symfony/http-foundation/CHANGELOG.md index ee5b6cecf2e85e43883791f0adb62df64d874386..1ce01aea240bbbe36eae93cc318d3e980e5c93ab 100644 --- a/vendor/symfony/http-foundation/CHANGELOG.md +++ b/vendor/symfony/http-foundation/CHANGELOG.md @@ -1,6 +1,69 @@ CHANGELOG ========= +4.3.0 +----- + + * added PHPUnit constraints: `RequestAttributeValueSame`, `ResponseCookieValueSame`, `ResponseHasCookie`, + `ResponseHasHeader`, `ResponseHeaderSame`, `ResponseIsRedirected`, `ResponseIsSuccessful`, and `ResponseStatusCodeSame` + * deprecated `MimeTypeGuesserInterface` and `ExtensionGuesserInterface` in favor of `Symfony\Component\Mime\MimeTypesInterface`. + * deprecated `MimeType` and `MimeTypeExtensionGuesser` in favor of `Symfony\Component\Mime\MimeTypes`. + * deprecated `FileBinaryMimeTypeGuesser` in favor of `Symfony\Component\Mime\FileBinaryMimeTypeGuesser`. + * deprecated `FileinfoMimeTypeGuesser` in favor of `Symfony\Component\Mime\FileinfoMimeTypeGuesser`. + * added `UrlHelper` that allows to get an absolute URL and a relative path for a given path + +4.2.0 +----- + + * the default value of the "$secure" and "$samesite" arguments of Cookie's constructor + will respectively change from "false" to "null" and from "null" to "lax" in Symfony + 5.0, you should define their values explicitly or use "Cookie::create()" instead. + * added `matchPort()` in RequestMatcher + +4.1.3 +----- + + * [BC BREAK] Support for the IIS-only `X_ORIGINAL_URL` and `X_REWRITE_URL` + HTTP headers has been dropped for security reasons. + +4.1.0 +----- + + * Query string normalization uses `parse_str()` instead of custom parsing logic. + * Passing the file size to the constructor of the `UploadedFile` class is deprecated. + * The `getClientSize()` method of the `UploadedFile` class is deprecated. Use `getSize()` instead. + * added `RedisSessionHandler` to use Redis as a session storage + * The `get()` method of the `AcceptHeader` class now takes into account the + `*` and `*/*` default values (if they are present in the Accept HTTP header) + when looking for items. + * deprecated `Request::getSession()` when no session has been set. Use `Request::hasSession()` instead. + * added `CannotWriteFileException`, `ExtensionFileException`, `FormSizeFileException`, + `IniSizeFileException`, `NoFileException`, `NoTmpDirFileException`, `PartialFileException` to + handle failed `UploadedFile`. + * added `MigratingSessionHandler` for migrating between two session handlers without losing sessions + * added `HeaderUtils`. + +4.0.0 +----- + + * the `Request::setTrustedHeaderName()` and `Request::getTrustedHeaderName()` + methods have been removed + * the `Request::HEADER_CLIENT_IP` constant has been removed, use + `Request::HEADER_X_FORWARDED_FOR` instead + * the `Request::HEADER_CLIENT_HOST` constant has been removed, use + `Request::HEADER_X_FORWARDED_HOST` instead + * the `Request::HEADER_CLIENT_PROTO` constant has been removed, use + `Request::HEADER_X_FORWARDED_PROTO` instead + * the `Request::HEADER_CLIENT_PORT` constant has been removed, use + `Request::HEADER_X_FORWARDED_PORT` instead + * checking for cacheable HTTP methods using the `Request::isMethodSafe()` + method (by not passing `false` as its argument) is not supported anymore and + throws a `\BadMethodCallException` + * the `WriteCheckSessionHandler`, `NativeSessionHandler` and `NativeProxy` classes have been removed + * setting session save handlers that do not implement `\SessionHandlerInterface` in + `NativeSessionStorage::setSaveHandler()` is not supported anymore and throws a + `\TypeError` + 3.4.0 ----- @@ -15,7 +78,7 @@ CHANGELOG ----- * the `Request::setTrustedProxies()` method takes a new `$trustedHeaderSet` argument, - see http://symfony.com/doc/current/components/http_foundation/trusting_proxies.html for more info, + see https://symfony.com/doc/current/deployment/proxies.html for more info, * deprecated the `Request::setTrustedHeaderName()` and `Request::getTrustedHeaderName()` methods, * added `File\Stream`, to be passed to `BinaryFileResponse` when the size of the served file is unknown, disabling `Range` and `Content-Length` handling, switching to chunked encoding instead @@ -138,10 +201,10 @@ CHANGELOG * Added `FlashBag`. Flashes expire when retrieved by `get()` or `all()`. This implementation is ESI compatible. * Added `AutoExpireFlashBag` (default) to replicate Symfony 2.0.x auto expire - behaviour of messages auto expiring after one page page load. Messages must + behavior of messages auto expiring after one page page load. Messages must be retrieved by `get()` or `all()`. * Added `Symfony\Component\HttpFoundation\Attribute\AttributeBag` to replicate - attributes storage behaviour from 2.0.x (default). + attributes storage behavior from 2.0.x (default). * Added `Symfony\Component\HttpFoundation\Attribute\NamespacedAttributeBag` for namespace session attributes. * Flash API can stores messages in an array so there may be multiple messages diff --git a/vendor/symfony/http-foundation/Cookie.php b/vendor/symfony/http-foundation/Cookie.php index 4519a6adaeda59aee7b3c48eb7b2b213965fca82..1e22c745a03fb63734d7102b3cb15fb7306696ac 100644 --- a/vendor/symfony/http-foundation/Cookie.php +++ b/vendor/symfony/http-foundation/Cookie.php @@ -18,6 +18,10 @@ namespace Symfony\Component\HttpFoundation; */ class Cookie { + const SAMESITE_NONE = 'none'; + const SAMESITE_LAX = 'lax'; + const SAMESITE_STRICT = 'strict'; + protected $name; protected $value; protected $domain; @@ -25,11 +29,14 @@ class Cookie protected $path; protected $secure; protected $httpOnly; + private $raw; private $sameSite; + private $secureDefault = false; - const SAMESITE_LAX = 'lax'; - const SAMESITE_STRICT = 'strict'; + private static $reservedCharsList = "=,; \t\r\n\v\f"; + private static $reservedCharsFrom = ['=', ',', ';', ' ', "\t", "\r", "\n", "\v", "\f"]; + private static $reservedCharsTo = ['%3D', '%2C', '%3B', '%20', '%09', '%0D', '%0A', '%0B', '%0C']; /** * Creates cookie from raw header string. @@ -41,7 +48,7 @@ class Cookie */ public static function fromString($cookie, $decode = false) { - $data = array( + $data = [ 'expires' => 0, 'path' => '/', 'domain' => null, @@ -49,35 +56,26 @@ class Cookie 'httponly' => false, 'raw' => !$decode, 'samesite' => null, - ); - foreach (explode(';', $cookie) as $part) { - if (false === strpos($part, '=')) { - $key = trim($part); - $value = true; - } else { - list($key, $value) = explode('=', trim($part), 2); - $key = trim($key); - $value = trim($value); - } - if (!isset($data['name'])) { - $data['name'] = $decode ? urldecode($key) : $key; - $data['value'] = true === $value ? null : ($decode ? urldecode($value) : $value); - continue; - } - switch ($key = strtolower($key)) { - case 'name': - case 'value': - break; - case 'max-age': - $data['expires'] = time() + (int) $value; - break; - default: - $data[$key] = $value; - break; - } + ]; + + $parts = HeaderUtils::split($cookie, ';='); + $part = array_shift($parts); + + $name = $decode ? urldecode($part[0]) : $part[0]; + $value = isset($part[1]) ? ($decode ? urldecode($part[1]) : $part[1]) : null; + + $data = HeaderUtils::combine($parts) + $data; + + if (isset($data['max-age'])) { + $data['expires'] = time() + (int) $data['max-age']; } - return new static($data['name'], $data['value'], $data['expires'], $data['path'], $data['domain'], $data['secure'], $data['httponly'], $data['raw'], $data['samesite']); + return new static($name, $value, $data['expires'], $data['path'], $data['domain'], $data['secure'], $data['httponly'], $data['raw'], $data['samesite']); + } + + public static function create(string $name, string $value = null, $expire = 0, ?string $path = '/', string $domain = null, bool $secure = null, bool $httpOnly = true, bool $raw = false, ?string $sameSite = self::SAMESITE_LAX): self + { + return new self($name, $value, $expire, $path, $domain, $secure, $httpOnly, $raw, $sameSite); } /** @@ -86,17 +84,21 @@ class Cookie * @param int|string|\DateTimeInterface $expire The time the cookie expires * @param string $path The path on the server in which the cookie will be available on * @param string|null $domain The domain that the cookie is available to - * @param bool $secure Whether the cookie should only be transmitted over a secure HTTPS connection from the client + * @param bool|null $secure Whether the client should send back the cookie only over HTTPS or null to auto-enable this when the request is already using HTTPS * @param bool $httpOnly Whether the cookie will be made accessible only through the HTTP protocol * @param bool $raw Whether the cookie value should be sent with no url encoding * @param string|null $sameSite Whether the cookie will be available for cross-site requests * * @throws \InvalidArgumentException */ - public function __construct($name, $value = null, $expire = 0, $path = '/', $domain = null, $secure = false, $httpOnly = true, $raw = false, $sameSite = null) + public function __construct(string $name, string $value = null, $expire = 0, ?string $path = '/', string $domain = null, ?bool $secure = false, bool $httpOnly = true, bool $raw = false, string $sameSite = null) { + if (9 > \func_num_args()) { + @trigger_error(sprintf('The default value of the "$secure" and "$samesite" arguments of "%s"\'s constructor will respectively change from "false" to "null" and from "null" to "lax" in Symfony 5.0, you should define their values explicitly or use "Cookie::create()" instead.', __METHOD__), E_USER_DEPRECATED); + } + // from PHP source code - if (preg_match("/[=,; \t\r\n\013\014]/", $name)) { + if ($raw && false !== strpbrk($name, self::$reservedCharsList)) { throw new \InvalidArgumentException(sprintf('The cookie name "%s" contains invalid characters.', $name)); } @@ -120,15 +122,17 @@ class Cookie $this->domain = $domain; $this->expire = 0 < $expire ? (int) $expire : 0; $this->path = empty($path) ? '/' : $path; - $this->secure = (bool) $secure; - $this->httpOnly = (bool) $httpOnly; - $this->raw = (bool) $raw; + $this->secure = $secure; + $this->httpOnly = $httpOnly; + $this->raw = $raw; - if (null !== $sameSite) { + if ('' === $sameSite) { + $sameSite = null; + } elseif (null !== $sameSite) { $sameSite = strtolower($sameSite); } - if (!in_array($sameSite, array(self::SAMESITE_LAX, self::SAMESITE_STRICT, null), true)) { + if (!\in_array($sameSite, [self::SAMESITE_LAX, self::SAMESITE_STRICT, self::SAMESITE_NONE, null], true)) { throw new \InvalidArgumentException('The "sameSite" parameter value is not valid.'); } @@ -142,15 +146,21 @@ class Cookie */ public function __toString() { - $str = ($this->isRaw() ? $this->getName() : urlencode($this->getName())).'='; + if ($this->isRaw()) { + $str = $this->getName(); + } else { + $str = str_replace(self::$reservedCharsFrom, self::$reservedCharsTo, $this->getName()); + } + + $str .= '='; if ('' === (string) $this->getValue()) { - $str .= 'deleted; expires='.gmdate('D, d-M-Y H:i:s T', time() - 31536001).'; max-age=-31536001'; + $str .= 'deleted; expires='.gmdate('D, d-M-Y H:i:s T', time() - 31536001).'; Max-Age=0'; } else { $str .= $this->isRaw() ? $this->getValue() : rawurlencode($this->getValue()); if (0 !== $this->getExpiresTime()) { - $str .= '; expires='.gmdate('D, d-M-Y H:i:s T', $this->getExpiresTime()).'; max-age='.$this->getMaxAge(); + $str .= '; expires='.gmdate('D, d-M-Y H:i:s T', $this->getExpiresTime()).'; Max-Age='.$this->getMaxAge(); } } @@ -224,7 +234,9 @@ class Cookie */ public function getMaxAge() { - return 0 !== $this->expire ? $this->expire - time() : 0; + $maxAge = $this->expire - time(); + + return 0 >= $maxAge ? 0 : $maxAge; } /** @@ -244,7 +256,7 @@ class Cookie */ public function isSecure() { - return $this->secure; + return $this->secure ?? $this->secureDefault; } /** @@ -264,7 +276,7 @@ class Cookie */ public function isCleared() { - return $this->expire < time(); + return 0 !== $this->expire && $this->expire < time(); } /** @@ -286,4 +298,12 @@ class Cookie { return $this->sameSite; } + + /** + * @param bool $default The default value of the "secure" flag when it is set to null + */ + public function setSecureDefault(bool $default): void + { + $this->secureDefault = $default; + } } diff --git a/vendor/symfony/http-foundation/ExpressionRequestMatcher.php b/vendor/symfony/http-foundation/ExpressionRequestMatcher.php index e9c8441ce314b2f5a9eb88350b888fe83030636a..26bed7d3713ebe1102d7398c1e8fcfd435e78eba 100644 --- a/vendor/symfony/http-foundation/ExpressionRequestMatcher.php +++ b/vendor/symfony/http-foundation/ExpressionRequestMatcher.php @@ -35,13 +35,13 @@ class ExpressionRequestMatcher extends RequestMatcher throw new \LogicException('Unable to match the request as the expression language is not available.'); } - return $this->language->evaluate($this->expression, array( + return $this->language->evaluate($this->expression, [ 'request' => $request, 'method' => $request->getMethod(), 'path' => rawurldecode($request->getPathInfo()), 'host' => $request->getHost(), 'ip' => $request->getClientIp(), 'attributes' => $request->attributes->all(), - )) && parent::matches($request); + ]) && parent::matches($request); } } diff --git a/vendor/symfony/http-foundation/File/Exception/AccessDeniedException.php b/vendor/symfony/http-foundation/File/Exception/AccessDeniedException.php index 3b8e41d4a2cf99f40a99fed96a4fa660f8213885..c25c3629bb617b8072b2c8dda248069e72ef0f71 100644 --- a/vendor/symfony/http-foundation/File/Exception/AccessDeniedException.php +++ b/vendor/symfony/http-foundation/File/Exception/AccessDeniedException.php @@ -21,7 +21,7 @@ class AccessDeniedException extends FileException /** * @param string $path The path to the accessed file */ - public function __construct($path) + public function __construct(string $path) { parent::__construct(sprintf('The file %s could not be accessed', $path)); } diff --git a/vendor/symfony/http-foundation/File/Exception/CannotWriteFileException.php b/vendor/symfony/http-foundation/File/Exception/CannotWriteFileException.php new file mode 100644 index 0000000000000000000000000000000000000000..c49f53a6cfe9fffa41b5471f4ff69d7ef17f0808 --- /dev/null +++ b/vendor/symfony/http-foundation/File/Exception/CannotWriteFileException.php @@ -0,0 +1,21 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\File\Exception; + +/** + * Thrown when an UPLOAD_ERR_CANT_WRITE error occurred with UploadedFile. + * + * @author Florent Mata <florentmata@gmail.com> + */ +class CannotWriteFileException extends FileException +{ +} diff --git a/vendor/symfony/http-foundation/File/Exception/ExtensionFileException.php b/vendor/symfony/http-foundation/File/Exception/ExtensionFileException.php new file mode 100644 index 0000000000000000000000000000000000000000..ed83499c004a76259fcac3e5ae93cecb31a3c47a --- /dev/null +++ b/vendor/symfony/http-foundation/File/Exception/ExtensionFileException.php @@ -0,0 +1,21 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\File\Exception; + +/** + * Thrown when an UPLOAD_ERR_EXTENSION error occurred with UploadedFile. + * + * @author Florent Mata <florentmata@gmail.com> + */ +class ExtensionFileException extends FileException +{ +} diff --git a/vendor/symfony/http-foundation/File/Exception/FileNotFoundException.php b/vendor/symfony/http-foundation/File/Exception/FileNotFoundException.php index bfcc37ec66ea04583d11de82a10f3294d875f13f..0f1f3f951d806f76d2a5e78e9be94e76ecb70a4e 100644 --- a/vendor/symfony/http-foundation/File/Exception/FileNotFoundException.php +++ b/vendor/symfony/http-foundation/File/Exception/FileNotFoundException.php @@ -21,7 +21,7 @@ class FileNotFoundException extends FileException /** * @param string $path The path to the file that was not found */ - public function __construct($path) + public function __construct(string $path) { parent::__construct(sprintf('The file "%s" does not exist', $path)); } diff --git a/vendor/symfony/http-foundation/File/Exception/FormSizeFileException.php b/vendor/symfony/http-foundation/File/Exception/FormSizeFileException.php new file mode 100644 index 0000000000000000000000000000000000000000..8741be0884c364aa7b772e2f1d78bae6b8edbf46 --- /dev/null +++ b/vendor/symfony/http-foundation/File/Exception/FormSizeFileException.php @@ -0,0 +1,21 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\File\Exception; + +/** + * Thrown when an UPLOAD_ERR_FORM_SIZE error occurred with UploadedFile. + * + * @author Florent Mata <florentmata@gmail.com> + */ +class FormSizeFileException extends FileException +{ +} diff --git a/vendor/symfony/http-foundation/File/Exception/IniSizeFileException.php b/vendor/symfony/http-foundation/File/Exception/IniSizeFileException.php new file mode 100644 index 0000000000000000000000000000000000000000..c8fde6103ab279e13f52e189764d2dccd1f17144 --- /dev/null +++ b/vendor/symfony/http-foundation/File/Exception/IniSizeFileException.php @@ -0,0 +1,21 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\File\Exception; + +/** + * Thrown when an UPLOAD_ERR_INI_SIZE error occurred with UploadedFile. + * + * @author Florent Mata <florentmata@gmail.com> + */ +class IniSizeFileException extends FileException +{ +} diff --git a/vendor/symfony/debug/Tests/MockExceptionHandler.php b/vendor/symfony/http-foundation/File/Exception/NoFileException.php similarity index 51% rename from vendor/symfony/debug/Tests/MockExceptionHandler.php rename to vendor/symfony/http-foundation/File/Exception/NoFileException.php index 2d6ce564d23a4270603053716b781622bb8a008a..4b48cc7799d2a979bacfa2565826485bcca77306 100644 --- a/vendor/symfony/debug/Tests/MockExceptionHandler.php +++ b/vendor/symfony/http-foundation/File/Exception/NoFileException.php @@ -9,16 +9,13 @@ * file that was distributed with this source code. */ -namespace Symfony\Component\Debug\Tests; +namespace Symfony\Component\HttpFoundation\File\Exception; -use Symfony\Component\Debug\ExceptionHandler; - -class MockExceptionHandler extends ExceptionHandler +/** + * Thrown when an UPLOAD_ERR_NO_FILE error occurred with UploadedFile. + * + * @author Florent Mata <florentmata@gmail.com> + */ +class NoFileException extends FileException { - public $e; - - public function handle(\Exception $e) - { - $this->e = $e; - } } diff --git a/vendor/symfony/http-foundation/File/Exception/NoTmpDirFileException.php b/vendor/symfony/http-foundation/File/Exception/NoTmpDirFileException.php new file mode 100644 index 0000000000000000000000000000000000000000..bdead2d91c8a71b3f89eb06138eed87b869c7947 --- /dev/null +++ b/vendor/symfony/http-foundation/File/Exception/NoTmpDirFileException.php @@ -0,0 +1,21 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\File\Exception; + +/** + * Thrown when an UPLOAD_ERR_NO_TMP_DIR error occurred with UploadedFile. + * + * @author Florent Mata <florentmata@gmail.com> + */ +class NoTmpDirFileException extends FileException +{ +} diff --git a/vendor/symfony/http-foundation/File/Exception/PartialFileException.php b/vendor/symfony/http-foundation/File/Exception/PartialFileException.php new file mode 100644 index 0000000000000000000000000000000000000000..4641efb55a3aaac83049d96d10e415b5c3e51a58 --- /dev/null +++ b/vendor/symfony/http-foundation/File/Exception/PartialFileException.php @@ -0,0 +1,21 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\File\Exception; + +/** + * Thrown when an UPLOAD_ERR_PARTIAL error occurred with UploadedFile. + * + * @author Florent Mata <florentmata@gmail.com> + */ +class PartialFileException extends FileException +{ +} diff --git a/vendor/symfony/http-foundation/File/Exception/UnexpectedTypeException.php b/vendor/symfony/http-foundation/File/Exception/UnexpectedTypeException.php index 0444b8778218fb5e63d9ef8370f147c261921515..82b982b3789893a18e23fb9b7f7361b1971ff3fa 100644 --- a/vendor/symfony/http-foundation/File/Exception/UnexpectedTypeException.php +++ b/vendor/symfony/http-foundation/File/Exception/UnexpectedTypeException.php @@ -13,8 +13,8 @@ namespace Symfony\Component\HttpFoundation\File\Exception; class UnexpectedTypeException extends FileException { - public function __construct($value, $expectedType) + public function __construct($value, string $expectedType) { - parent::__construct(sprintf('Expected argument of type %s, %s given', $expectedType, is_object($value) ? get_class($value) : gettype($value))); + parent::__construct(sprintf('Expected argument of type %s, %s given', $expectedType, \is_object($value) ? \get_class($value) : \gettype($value))); } } diff --git a/vendor/symfony/http-foundation/File/File.php b/vendor/symfony/http-foundation/File/File.php index e2a67684fcda640de0cc7a71ea32562867501f49..396ff3450ed8c84210b8bbf13c972c015effdb79 100644 --- a/vendor/symfony/http-foundation/File/File.php +++ b/vendor/symfony/http-foundation/File/File.php @@ -13,8 +13,7 @@ namespace Symfony\Component\HttpFoundation\File; use Symfony\Component\HttpFoundation\File\Exception\FileException; use Symfony\Component\HttpFoundation\File\Exception\FileNotFoundException; -use Symfony\Component\HttpFoundation\File\MimeType\MimeTypeGuesser; -use Symfony\Component\HttpFoundation\File\MimeType\ExtensionGuesser; +use Symfony\Component\Mime\MimeTypes; /** * A file in the file system. @@ -31,7 +30,7 @@ class File extends \SplFileInfo * * @throws FileNotFoundException If the given path is not a file */ - public function __construct($path, $checkPath = true) + public function __construct(string $path, bool $checkPath = true) { if ($checkPath && !is_file($path)) { throw new FileNotFoundException($path); @@ -50,33 +49,28 @@ class File extends \SplFileInfo * * @return string|null The guessed extension or null if it cannot be guessed * - * @see ExtensionGuesser + * @see MimeTypes * @see getMimeType() */ public function guessExtension() { - $type = $this->getMimeType(); - $guesser = ExtensionGuesser::getInstance(); - - return $guesser->guess($type); + return MimeTypes::getDefault()->getExtensions($this->getMimeType())[0] ?? null; } /** * Returns the mime type of the file. * - * The mime type is guessed using a MimeTypeGuesser instance, which uses finfo(), - * mime_content_type() and the system binary "file" (in this order), depending on - * which of those are available. + * The mime type is guessed using a MimeTypeGuesserInterface instance, + * which uses finfo_file() then the "file" system binary, + * depending on which of those are available. * * @return string|null The guessed mime type (e.g. "application/pdf") * - * @see MimeTypeGuesser + * @see MimeTypes */ public function getMimeType() { - $guesser = MimeTypeGuesser::getInstance(); - - return $guesser->guess($this->getPathname()); + return MimeTypes::getDefault()->guessMimeType($this->getPathname()); } /** @@ -93,9 +87,11 @@ class File extends \SplFileInfo { $target = $this->getTargetFile($directory, $name); - if (!@rename($this->getPathname(), $target)) { - $error = error_get_last(); - throw new FileException(sprintf('Could not move the file "%s" to "%s" (%s)', $this->getPathname(), $target, strip_tags($error['message']))); + set_error_handler(function ($type, $msg) use (&$error) { $error = $msg; }); + $renamed = rename($this->getPathname(), $target); + restore_error_handler(); + if (!$renamed) { + throw new FileException(sprintf('Could not move the file "%s" to "%s" (%s)', $this->getPathname(), $target, strip_tags($error))); } @chmod($target, 0666 & ~umask()); @@ -113,7 +109,7 @@ class File extends \SplFileInfo throw new FileException(sprintf('Unable to write in the "%s" directory', $directory)); } - $target = rtrim($directory, '/\\').DIRECTORY_SEPARATOR.(null === $name ? $this->getBasename() : $this->getName($name)); + $target = rtrim($directory, '/\\').\DIRECTORY_SEPARATOR.(null === $name ? $this->getBasename() : $this->getName($name)); return new self($target, false); } diff --git a/vendor/symfony/http-foundation/File/MimeType/ExtensionGuesser.php b/vendor/symfony/http-foundation/File/MimeType/ExtensionGuesser.php index 263fb321c574515925cb98a8e102f58f026cb628..4ac2013305c0e7e4fa0f17df9922e9ea81665c46 100644 --- a/vendor/symfony/http-foundation/File/MimeType/ExtensionGuesser.php +++ b/vendor/symfony/http-foundation/File/MimeType/ExtensionGuesser.php @@ -11,6 +11,10 @@ namespace Symfony\Component\HttpFoundation\File\MimeType; +use Symfony\Component\Mime\MimeTypes; + +@trigger_error(sprintf('The "%s" class is deprecated since Symfony 4.3, use "%s" instead.', ExtensionGuesser::class, MimeTypes::class), E_USER_DEPRECATED); + /** * A singleton mime type to file extension guesser. * @@ -22,6 +26,8 @@ namespace Symfony\Component\HttpFoundation\File\MimeType; * $guesser->register(new MyCustomExtensionGuesser()); * * The last registered guesser is preferred over previously registered ones. + * + * @deprecated since Symfony 4.3, use {@link MimeTypes} instead */ class ExtensionGuesser implements ExtensionGuesserInterface { @@ -37,7 +43,7 @@ class ExtensionGuesser implements ExtensionGuesserInterface * * @var array */ - protected $guessers = array(); + protected $guessers = []; /** * Returns the singleton instance. @@ -90,5 +96,7 @@ class ExtensionGuesser implements ExtensionGuesserInterface return $extension; } } + + return null; } } diff --git a/vendor/symfony/http-foundation/File/MimeType/ExtensionGuesserInterface.php b/vendor/symfony/http-foundation/File/MimeType/ExtensionGuesserInterface.php index d19a0e5371349302b9aaac37ed9ae51562258b40..69fe6efb286c403a85e3a0ec199e4a40a64680d5 100644 --- a/vendor/symfony/http-foundation/File/MimeType/ExtensionGuesserInterface.php +++ b/vendor/symfony/http-foundation/File/MimeType/ExtensionGuesserInterface.php @@ -11,8 +11,12 @@ namespace Symfony\Component\HttpFoundation\File\MimeType; +use Symfony\Component\Mime\MimeTypesInterface; + /** * Guesses the file extension corresponding to a given mime type. + * + * @deprecated since Symfony 4.3, use {@link MimeTypesInterface} instead */ interface ExtensionGuesserInterface { diff --git a/vendor/symfony/http-foundation/File/MimeType/FileBinaryMimeTypeGuesser.php b/vendor/symfony/http-foundation/File/MimeType/FileBinaryMimeTypeGuesser.php index c2ac6768c30133db07434dc10d51610a862ff1f2..9633f0174ec69b20d0b2a76a39705397ce837bfd 100644 --- a/vendor/symfony/http-foundation/File/MimeType/FileBinaryMimeTypeGuesser.php +++ b/vendor/symfony/http-foundation/File/MimeType/FileBinaryMimeTypeGuesser.php @@ -11,13 +11,18 @@ namespace Symfony\Component\HttpFoundation\File\MimeType; -use Symfony\Component\HttpFoundation\File\Exception\FileNotFoundException; use Symfony\Component\HttpFoundation\File\Exception\AccessDeniedException; +use Symfony\Component\HttpFoundation\File\Exception\FileNotFoundException; +use Symfony\Component\Mime\FileBinaryMimeTypeGuesser as NewFileBinaryMimeTypeGuesser; + +@trigger_error(sprintf('The "%s" class is deprecated since Symfony 4.3, use "%s" instead.', FileBinaryMimeTypeGuesser::class, NewFileBinaryMimeTypeGuesser::class), E_USER_DEPRECATED); /** * Guesses the mime type with the binary "file" (only available on *nix). * * @author Bernhard Schussek <bschussek@gmail.com> + * + * @deprecated since Symfony 4.3, use {@link NewFileBinaryMimeTypeGuesser} instead */ class FileBinaryMimeTypeGuesser implements MimeTypeGuesserInterface { @@ -31,7 +36,7 @@ class FileBinaryMimeTypeGuesser implements MimeTypeGuesserInterface * * @param string $cmd The command to run to get the mime type of a file */ - public function __construct($cmd = 'file -b --mime %s 2>/dev/null') + public function __construct(string $cmd = 'file -b --mime %s 2>/dev/null') { $this->cmd = $cmd; } @@ -43,7 +48,21 @@ class FileBinaryMimeTypeGuesser implements MimeTypeGuesserInterface */ public static function isSupported() { - return '\\' !== DIRECTORY_SEPARATOR && function_exists('passthru') && function_exists('escapeshellarg'); + static $supported = null; + + if (null !== $supported) { + return $supported; + } + + if ('\\' === \DIRECTORY_SEPARATOR || !\function_exists('passthru') || !\function_exists('escapeshellarg')) { + return $supported = false; + } + + ob_start(); + passthru('command -v file', $exitStatus); + $binPath = trim(ob_get_clean()); + + return $supported = 0 === $exitStatus && '' !== $binPath; } /** @@ -60,7 +79,7 @@ class FileBinaryMimeTypeGuesser implements MimeTypeGuesserInterface } if (!self::isSupported()) { - return; + return null; } ob_start(); @@ -70,14 +89,14 @@ class FileBinaryMimeTypeGuesser implements MimeTypeGuesserInterface if ($return > 0) { ob_end_clean(); - return; + return null; } $type = trim(ob_get_clean()); if (!preg_match('#^([a-z0-9\-]+/[a-z0-9\-\.]+)#i', $type, $match)) { // it's not a type, but an error message - return; + return null; } return $match[1]; diff --git a/vendor/symfony/http-foundation/File/MimeType/FileinfoMimeTypeGuesser.php b/vendor/symfony/http-foundation/File/MimeType/FileinfoMimeTypeGuesser.php index 9b42835e4304418e4b9211307f9726cb5f6d221a..70a01d7aecd0dd43c38c09b41cd8a5d26b448900 100644 --- a/vendor/symfony/http-foundation/File/MimeType/FileinfoMimeTypeGuesser.php +++ b/vendor/symfony/http-foundation/File/MimeType/FileinfoMimeTypeGuesser.php @@ -11,13 +11,18 @@ namespace Symfony\Component\HttpFoundation\File\MimeType; -use Symfony\Component\HttpFoundation\File\Exception\FileNotFoundException; use Symfony\Component\HttpFoundation\File\Exception\AccessDeniedException; +use Symfony\Component\HttpFoundation\File\Exception\FileNotFoundException; +use Symfony\Component\Mime\FileinfoMimeTypeGuesser as NewFileinfoMimeTypeGuesser; + +@trigger_error(sprintf('The "%s" class is deprecated since Symfony 4.3, use "%s" instead.', FileinfoMimeTypeGuesser::class, NewFileinfoMimeTypeGuesser::class), E_USER_DEPRECATED); /** * Guesses the mime type using the PECL extension FileInfo. * * @author Bernhard Schussek <bschussek@gmail.com> + * + * @deprecated since Symfony 4.3, use {@link NewFileinfoMimeTypeGuesser} instead */ class FileinfoMimeTypeGuesser implements MimeTypeGuesserInterface { @@ -26,9 +31,9 @@ class FileinfoMimeTypeGuesser implements MimeTypeGuesserInterface /** * @param string $magicFile A magic file to use with the finfo instance * - * @see http://www.php.net/manual/en/function.finfo-open.php + * @see https://php.net/finfo-open */ - public function __construct($magicFile = null) + public function __construct(string $magicFile = null) { $this->magicFile = $magicFile; } @@ -40,7 +45,7 @@ class FileinfoMimeTypeGuesser implements MimeTypeGuesserInterface */ public static function isSupported() { - return function_exists('finfo_open'); + return \function_exists('finfo_open'); } /** @@ -57,11 +62,11 @@ class FileinfoMimeTypeGuesser implements MimeTypeGuesserInterface } if (!self::isSupported()) { - return; + return null; } if (!$finfo = new \finfo(FILEINFO_MIME_TYPE, $this->magicFile)) { - return; + return null; } return $finfo->file($path); diff --git a/vendor/symfony/http-foundation/File/MimeType/MimeTypeExtensionGuesser.php b/vendor/symfony/http-foundation/File/MimeType/MimeTypeExtensionGuesser.php index 896c135a53424b1b3cb59c9ef14a1d95e03d155f..651be070e122b792cfdf733b910b819833c7dec9 100644 --- a/vendor/symfony/http-foundation/File/MimeType/MimeTypeExtensionGuesser.php +++ b/vendor/symfony/http-foundation/File/MimeType/MimeTypeExtensionGuesser.php @@ -11,8 +11,14 @@ namespace Symfony\Component\HttpFoundation\File\MimeType; +use Symfony\Component\Mime\MimeTypes; + +@trigger_error(sprintf('The "%s" class is deprecated since Symfony 4.3, use "%s" instead.', MimeTypeExtensionGuesser::class, MimeTypes::class), E_USER_DEPRECATED); + /** * Provides a best-guess mapping of mime type to file extension. + * + * @deprecated since Symfony 4.3, use {@link MimeTypes} instead */ class MimeTypeExtensionGuesser implements ExtensionGuesserInterface { @@ -20,11 +26,11 @@ class MimeTypeExtensionGuesser implements ExtensionGuesserInterface * A map of mime types and their default extensions. * * This list has been placed under the public domain by the Apache HTTPD project. - * This list has been updated from upstream on 2013-04-23. + * This list has been updated from upstream on 2019-01-14. * - * @see http://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types + * @see https://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types */ - protected $defaultExtensions = array( + protected $defaultExtensions = [ 'application/andrew-inset' => 'ez', 'application/applixware' => 'aw', 'application/atom+xml' => 'atom', @@ -599,6 +605,7 @@ class MimeTypeExtensionGuesser implements ExtensionGuesserInterface 'application/x-xliff+xml' => 'xlf', 'application/x-xpinstall' => 'xpi', 'application/x-xz' => 'xz', + 'application/x-zip-compressed' => 'zip', 'application/x-zmachine' => 'z1', 'application/xaml+xml' => 'xaml', 'application/xcap-diff+xml' => 'xdf', @@ -617,7 +624,7 @@ class MimeTypeExtensionGuesser implements ExtensionGuesserInterface 'audio/adpcm' => 'adp', 'audio/basic' => 'au', 'audio/midi' => 'mid', - 'audio/mp4' => 'mp4a', + 'audio/mp4' => 'm4a', 'audio/mpeg' => 'mpga', 'audio/ogg' => 'oga', 'audio/s3m' => 's3m', @@ -638,6 +645,7 @@ class MimeTypeExtensionGuesser implements ExtensionGuesserInterface 'audio/x-aiff' => 'aif', 'audio/x-caf' => 'caf', 'audio/x-flac' => 'flac', + 'audio/x-hx-aac-adts' => 'aac', 'audio/x-matroska' => 'mka', 'audio/x-mpegurl' => 'm3u', 'audio/x-ms-wax' => 'wax', @@ -652,6 +660,11 @@ class MimeTypeExtensionGuesser implements ExtensionGuesserInterface 'chemical/x-cml' => 'cml', 'chemical/x-csml' => 'csml', 'chemical/x-xyz' => 'xyz', + 'font/collection' => 'ttc', + 'font/otf' => 'otf', + 'font/ttf' => 'ttf', + 'font/woff' => 'woff', + 'font/woff2' => 'woff2', 'image/bmp' => 'bmp', 'image/x-ms-bmp' => 'bmp', 'image/cgm' => 'cgm', @@ -668,8 +681,8 @@ class MimeTypeExtensionGuesser implements ExtensionGuesserInterface 'image/tiff' => 'tiff', 'image/vnd.adobe.photoshop' => 'psd', 'image/vnd.dece.graphic' => 'uvi', - 'image/vnd.dvb.subtitle' => 'sub', 'image/vnd.djvu' => 'djvu', + 'image/vnd.dvb.subtitle' => 'sub', 'image/vnd.dwg' => 'dwg', 'image/vnd.dxf' => 'dxf', 'image/vnd.fastbidsheet' => 'fbs', @@ -731,8 +744,8 @@ class MimeTypeExtensionGuesser implements ExtensionGuesserInterface 'text/vcard' => 'vcard', 'text/vnd.curl' => 'curl', 'text/vnd.curl.dcurl' => 'dcurl', - 'text/vnd.curl.scurl' => 'scurl', 'text/vnd.curl.mcurl' => 'mcurl', + 'text/vnd.curl.scurl' => 'scurl', 'text/vnd.dvb.subtitle' => 'sub', 'text/vnd.fly' => 'fly', 'text/vnd.fmi.flexstor' => 'flx', @@ -746,10 +759,10 @@ class MimeTypeExtensionGuesser implements ExtensionGuesserInterface 'text/x-asm' => 's', 'text/x-c' => 'c', 'text/x-fortran' => 'f', - 'text/x-pascal' => 'p', 'text/x-java-source' => 'java', - 'text/x-opml' => 'opml', 'text/x-nfo' => 'nfo', + 'text/x-opml' => 'opml', + 'text/x-pascal' => 'p', 'text/x-setext' => 'etx', 'text/x-sfv' => 'sfv', 'text/x-uuencode' => 'uu', @@ -795,13 +808,19 @@ class MimeTypeExtensionGuesser implements ExtensionGuesserInterface 'video/x-sgi-movie' => 'movie', 'video/x-smv' => 'smv', 'x-conference/x-cooltalk' => 'ice', - ); + ]; /** * {@inheritdoc} */ public function guess($mimeType) { - return isset($this->defaultExtensions[$mimeType]) ? $this->defaultExtensions[$mimeType] : null; + if (isset($this->defaultExtensions[$mimeType])) { + return $this->defaultExtensions[$mimeType]; + } + + $lcMimeType = strtolower($mimeType); + + return isset($this->defaultExtensions[$lcMimeType]) ? $this->defaultExtensions[$lcMimeType] : null; } } diff --git a/vendor/symfony/http-foundation/File/MimeType/MimeTypeGuesser.php b/vendor/symfony/http-foundation/File/MimeType/MimeTypeGuesser.php index e3ef45ef672cfbd48e4a7c76974bc31639235678..ece2109caee08fa74869833cf80c687f529dc78d 100644 --- a/vendor/symfony/http-foundation/File/MimeType/MimeTypeGuesser.php +++ b/vendor/symfony/http-foundation/File/MimeType/MimeTypeGuesser.php @@ -11,8 +11,11 @@ namespace Symfony\Component\HttpFoundation\File\MimeType; -use Symfony\Component\HttpFoundation\File\Exception\FileNotFoundException; use Symfony\Component\HttpFoundation\File\Exception\AccessDeniedException; +use Symfony\Component\HttpFoundation\File\Exception\FileNotFoundException; +use Symfony\Component\Mime\MimeTypes; + +@trigger_error(sprintf('The "%s" class is deprecated since Symfony 4.3, use "%s" instead.', MimeTypeGuesser::class, MimeTypes::class), E_USER_DEPRECATED); /** * A singleton mime type guesser. @@ -51,7 +54,7 @@ class MimeTypeGuesser implements MimeTypeGuesserInterface * * @var array */ - protected $guessers = array(); + protected $guessers = []; /** * Returns the singleton instance. @@ -80,13 +83,8 @@ class MimeTypeGuesser implements MimeTypeGuesserInterface */ private function __construct() { - if (FileBinaryMimeTypeGuesser::isSupported()) { - $this->register(new FileBinaryMimeTypeGuesser()); - } - - if (FileinfoMimeTypeGuesser::isSupported()) { - $this->register(new FileinfoMimeTypeGuesser()); - } + $this->register(new FileBinaryMimeTypeGuesser()); + $this->register(new FileinfoMimeTypeGuesser()); } /** @@ -125,18 +123,16 @@ class MimeTypeGuesser implements MimeTypeGuesserInterface throw new AccessDeniedException($path); } - if (!$this->guessers) { - $msg = 'Unable to guess the mime type as no guessers are available'; - if (!FileinfoMimeTypeGuesser::isSupported()) { - $msg .= ' (Did you enable the php_fileinfo extension?)'; - } - throw new \LogicException($msg); - } - foreach ($this->guessers as $guesser) { if (null !== $mimeType = $guesser->guess($path)) { return $mimeType; } } + + if (2 === \count($this->guessers) && !FileBinaryMimeTypeGuesser::isSupported() && !FileinfoMimeTypeGuesser::isSupported()) { + throw new \LogicException('Unable to guess the mime type as no guessers are available (Did you enable the php_fileinfo extension?)'); + } + + return null; } } diff --git a/vendor/symfony/http-foundation/File/MimeType/MimeTypeGuesserInterface.php b/vendor/symfony/http-foundation/File/MimeType/MimeTypeGuesserInterface.php index f8c3ad2289cc93fe77ddb2af14ff40e0535c4940..eab444890efe11954f8f887326d4abec26aa2424 100644 --- a/vendor/symfony/http-foundation/File/MimeType/MimeTypeGuesserInterface.php +++ b/vendor/symfony/http-foundation/File/MimeType/MimeTypeGuesserInterface.php @@ -11,13 +11,16 @@ namespace Symfony\Component\HttpFoundation\File\MimeType; -use Symfony\Component\HttpFoundation\File\Exception\FileNotFoundException; use Symfony\Component\HttpFoundation\File\Exception\AccessDeniedException; +use Symfony\Component\HttpFoundation\File\Exception\FileNotFoundException; +use Symfony\Component\Mime\MimeTypesInterface; /** * Guesses the mime type of a file. * * @author Bernhard Schussek <bschussek@gmail.com> + * + * @deprecated since Symfony 4.3, use {@link MimeTypesInterface} instead */ interface MimeTypeGuesserInterface { @@ -26,7 +29,7 @@ interface MimeTypeGuesserInterface * * @param string $path The path to the file * - * @return string The mime type or NULL, if none could be guessed + * @return string|null The mime type or NULL, if none could be guessed * * @throws FileNotFoundException If the file does not exist * @throws AccessDeniedException If the file could not be read diff --git a/vendor/symfony/http-foundation/File/UploadedFile.php b/vendor/symfony/http-foundation/File/UploadedFile.php index 082d8d534e17a361ff910d9d32d230fae75cb6eb..2367098a39ee33d4b5e8fbbb7f899d9cb2f0dbb9 100644 --- a/vendor/symfony/http-foundation/File/UploadedFile.php +++ b/vendor/symfony/http-foundation/File/UploadedFile.php @@ -11,9 +11,16 @@ namespace Symfony\Component\HttpFoundation\File; +use Symfony\Component\HttpFoundation\File\Exception\CannotWriteFileException; +use Symfony\Component\HttpFoundation\File\Exception\ExtensionFileException; use Symfony\Component\HttpFoundation\File\Exception\FileException; use Symfony\Component\HttpFoundation\File\Exception\FileNotFoundException; -use Symfony\Component\HttpFoundation\File\MimeType\ExtensionGuesser; +use Symfony\Component\HttpFoundation\File\Exception\FormSizeFileException; +use Symfony\Component\HttpFoundation\File\Exception\IniSizeFileException; +use Symfony\Component\HttpFoundation\File\Exception\NoFileException; +use Symfony\Component\HttpFoundation\File\Exception\NoTmpDirFileException; +use Symfony\Component\HttpFoundation\File\Exception\PartialFileException; +use Symfony\Component\Mime\MimeTypes; /** * A file uploaded through a form. @@ -27,7 +34,6 @@ class UploadedFile extends File private $test = false; private $originalName; private $mimeType; - private $size; private $error; /** @@ -47,7 +53,6 @@ class UploadedFile extends File * @param string $path The full temporary path to the file * @param string $originalName The original file name of the uploaded file * @param string|null $mimeType The type of the file as provided by PHP; null defaults to application/octet-stream - * @param int|null $size The file size provided by the uploader * @param int|null $error The error constant of the upload (one of PHP's UPLOAD_ERR_XXX constants); null defaults to UPLOAD_ERR_OK * @param bool $test Whether the test mode is active * Local files are used in test mode hence the code should not enforce HTTP uploads @@ -55,13 +60,19 @@ class UploadedFile extends File * @throws FileException If file_uploads is disabled * @throws FileNotFoundException If the file does not exist */ - public function __construct($path, $originalName, $mimeType = null, $size = null, $error = null, $test = false) + public function __construct(string $path, string $originalName, string $mimeType = null, int $error = null, $test = false) { $this->originalName = $this->getName($originalName); $this->mimeType = $mimeType ?: 'application/octet-stream'; - $this->size = $size; + + if (4 < \func_num_args() ? !\is_bool($test) : null !== $error && @filesize($path) === $error) { + @trigger_error(sprintf('Passing a size as 4th argument to the constructor of "%s" is deprecated since Symfony 4.1.', __CLASS__), E_USER_DEPRECATED); + $error = $test; + $test = 5 < \func_num_args() ? func_get_arg(5) : false; + } + $this->error = $error ?: UPLOAD_ERR_OK; - $this->test = (bool) $test; + $this->test = $test; parent::__construct($path, UPLOAD_ERR_OK === $this->error); } @@ -129,10 +140,7 @@ class UploadedFile extends File */ public function guessClientExtension() { - $type = $this->getClientMimeType(); - $guesser = ExtensionGuesser::getInstance(); - - return $guesser->guess($type); + return MimeTypes::getDefault()->getExtensions($this->getClientMimeType())[0] ?? null; } /** @@ -141,11 +149,15 @@ class UploadedFile extends File * It is extracted from the request from which the file has been uploaded. * Then it should not be considered as a safe value. * - * @return int|null The file size + * @deprecated since Symfony 4.1, use getSize() instead. + * + * @return int|null The file sizes */ public function getClientSize() { - return $this->size; + @trigger_error(sprintf('The "%s()" method is deprecated since Symfony 4.1. Use getSize() instead.', __METHOD__), E_USER_DEPRECATED); + + return $this->getSize(); } /** @@ -192,9 +204,11 @@ class UploadedFile extends File $target = $this->getTargetFile($directory, $name); - if (!@move_uploaded_file($this->getPathname(), $target)) { - $error = error_get_last(); - throw new FileException(sprintf('Could not move the file "%s" to "%s" (%s)', $this->getPathname(), $target, strip_tags($error['message']))); + set_error_handler(function ($type, $msg) use (&$error) { $error = $msg; }); + $moved = move_uploaded_file($this->getPathname(), $target); + restore_error_handler(); + if (!$moved) { + throw new FileException(sprintf('Could not move the file "%s" to "%s" (%s)', $this->getPathname(), $target, strip_tags($error))); } @chmod($target, 0666 & ~umask()); @@ -202,6 +216,23 @@ class UploadedFile extends File return $target; } + switch ($this->error) { + case UPLOAD_ERR_INI_SIZE: + throw new IniSizeFileException($this->getErrorMessage()); + case UPLOAD_ERR_FORM_SIZE: + throw new FormSizeFileException($this->getErrorMessage()); + case UPLOAD_ERR_PARTIAL: + throw new PartialFileException($this->getErrorMessage()); + case UPLOAD_ERR_NO_FILE: + throw new NoFileException($this->getErrorMessage()); + case UPLOAD_ERR_CANT_WRITE: + throw new CannotWriteFileException($this->getErrorMessage()); + case UPLOAD_ERR_NO_TMP_DIR: + throw new NoTmpDirFileException($this->getErrorMessage()); + case UPLOAD_ERR_EXTENSION: + throw new ExtensionFileException($this->getErrorMessage()); + } + throw new FileException($this->getErrorMessage()); } @@ -212,22 +243,35 @@ class UploadedFile extends File */ public static function getMaxFilesize() { - $iniMax = strtolower(ini_get('upload_max_filesize')); + $sizePostMax = self::parseFilesize(ini_get('post_max_size')); + $sizeUploadMax = self::parseFilesize(ini_get('upload_max_filesize')); - if ('' === $iniMax) { - return PHP_INT_MAX; + return min($sizePostMax ?: PHP_INT_MAX, $sizeUploadMax ?: PHP_INT_MAX); + } + + /** + * Returns the given size from an ini value in bytes. + * + * @return int The given size in bytes + */ + private static function parseFilesize($size) + { + if ('' === $size) { + return 0; } - $max = ltrim($iniMax, '+'); + $size = strtolower($size); + + $max = ltrim($size, '+'); if (0 === strpos($max, '0x')) { - $max = intval($max, 16); + $max = \intval($max, 16); } elseif (0 === strpos($max, '0')) { - $max = intval($max, 8); + $max = \intval($max, 8); } else { $max = (int) $max; } - switch (substr($iniMax, -1)) { + switch (substr($size, -1)) { case 't': $max *= 1024; // no break case 'g': $max *= 1024; @@ -247,7 +291,7 @@ class UploadedFile extends File */ public function getErrorMessage() { - static $errors = array( + static $errors = [ UPLOAD_ERR_INI_SIZE => 'The file "%s" exceeds your upload_max_filesize ini directive (limit is %d KiB).', UPLOAD_ERR_FORM_SIZE => 'The file "%s" exceeds the upload limit defined in your form.', UPLOAD_ERR_PARTIAL => 'The file "%s" was only partially uploaded.', @@ -255,7 +299,7 @@ class UploadedFile extends File UPLOAD_ERR_CANT_WRITE => 'The file "%s" could not be written on disk.', UPLOAD_ERR_NO_TMP_DIR => 'File could not be uploaded: missing temporary directory.', UPLOAD_ERR_EXTENSION => 'File upload was stopped by a PHP extension.', - ); + ]; $errorCode = $this->error; $maxFilesize = UPLOAD_ERR_INI_SIZE === $errorCode ? self::getMaxFilesize() / 1024 : 0; diff --git a/vendor/symfony/http-foundation/FileBag.php b/vendor/symfony/http-foundation/FileBag.php index 5edd0e6210c52551e2500591514e8e703fa74c66..f3248a5941e8af3e825f464f93dc96866abe4fa4 100644 --- a/vendor/symfony/http-foundation/FileBag.php +++ b/vendor/symfony/http-foundation/FileBag.php @@ -21,12 +21,12 @@ use Symfony\Component\HttpFoundation\File\UploadedFile; */ class FileBag extends ParameterBag { - private static $fileKeys = array('error', 'name', 'size', 'tmp_name', 'type'); + private static $fileKeys = ['error', 'name', 'size', 'tmp_name', 'type']; /** * @param array $parameters An array of HTTP files */ - public function __construct(array $parameters = array()) + public function __construct(array $parameters = []) { $this->replace($parameters); } @@ -34,9 +34,9 @@ class FileBag extends ParameterBag /** * {@inheritdoc} */ - public function replace(array $files = array()) + public function replace(array $files = []) { - $this->parameters = array(); + $this->parameters = []; $this->add($files); } @@ -45,7 +45,7 @@ class FileBag extends ParameterBag */ public function set($key, $value) { - if (!is_array($value) && !$value instanceof UploadedFile) { + if (!\is_array($value) && !$value instanceof UploadedFile) { throw new \InvalidArgumentException('An uploaded file must be an array or an instance of UploadedFile.'); } @@ -55,7 +55,7 @@ class FileBag extends ParameterBag /** * {@inheritdoc} */ - public function add(array $files = array()) + public function add(array $files = []) { foreach ($files as $key => $file) { $this->set($key, $file); @@ -75,8 +75,8 @@ class FileBag extends ParameterBag return $file; } - $file = $this->fixPhpFilesArray($file); - if (is_array($file)) { + if (\is_array($file)) { + $file = $this->fixPhpFilesArray($file); $keys = array_keys($file); sort($keys); @@ -84,10 +84,10 @@ class FileBag extends ParameterBag if (UPLOAD_ERR_NO_FILE == $file['error']) { $file = null; } else { - $file = new UploadedFile($file['tmp_name'], $file['name'], $file['type'], $file['size'], $file['error']); + $file = new UploadedFile($file['tmp_name'], $file['name'], $file['type'], $file['error'], false); } } else { - $file = array_map(array($this, 'convertFileInformation'), $file); + $file = array_map([$this, 'convertFileInformation'], $file); if (array_keys($keys) === $keys) { $file = array_filter($file); } @@ -109,18 +109,16 @@ class FileBag extends ParameterBag * It's safe to pass an already converted array, in which case this method * just returns the original array unmodified. * + * @param array $data + * * @return array */ protected function fixPhpFilesArray($data) { - if (!is_array($data)) { - return $data; - } - $keys = array_keys($data); sort($keys); - if (self::$fileKeys != $keys || !isset($data['name']) || !is_array($data['name'])) { + if (self::$fileKeys != $keys || !isset($data['name']) || !\is_array($data['name'])) { return $data; } @@ -130,13 +128,13 @@ class FileBag extends ParameterBag } foreach ($data['name'] as $key => $name) { - $files[$key] = $this->fixPhpFilesArray(array( + $files[$key] = $this->fixPhpFilesArray([ 'error' => $data['error'][$key], 'name' => $name, 'type' => $data['type'][$key], 'tmp_name' => $data['tmp_name'][$key], 'size' => $data['size'][$key], - )); + ]); } return $files; diff --git a/vendor/symfony/http-foundation/HeaderBag.php b/vendor/symfony/http-foundation/HeaderBag.php index 7aaa52ae56c11e86ac5f3e0e53e5257677927f11..7782f74244ab80e93b64deefaf374caecd1a6842 100644 --- a/vendor/symfony/http-foundation/HeaderBag.php +++ b/vendor/symfony/http-foundation/HeaderBag.php @@ -18,13 +18,13 @@ namespace Symfony\Component\HttpFoundation; */ class HeaderBag implements \IteratorAggregate, \Countable { - protected $headers = array(); - protected $cacheControl = array(); + protected $headers = []; + protected $cacheControl = []; /** * @param array $headers An array of HTTP headers */ - public function __construct(array $headers = array()) + public function __construct(array $headers = []) { foreach ($headers as $key => $values) { $this->set($key, $values); @@ -46,7 +46,7 @@ class HeaderBag implements \IteratorAggregate, \Countable $max = max(array_map('strlen', array_keys($headers))) + 1; $content = ''; foreach ($headers as $name => $values) { - $name = implode('-', array_map('ucfirst', explode('-', $name))); + $name = ucwords($name, '-'); foreach ($values as $value) { $content .= sprintf("%-{$max}s %s\r\n", $name.':', $value); } @@ -80,9 +80,9 @@ class HeaderBag implements \IteratorAggregate, \Countable * * @param array $headers An array of HTTP headers */ - public function replace(array $headers = array()) + public function replace(array $headers = []) { - $this->headers = array(); + $this->headers = []; $this->add($headers); } @@ -101,27 +101,35 @@ class HeaderBag implements \IteratorAggregate, \Countable /** * Returns a header value by name. * - * @param string $key The header name - * @param string|string[] $default The default value - * @param bool $first Whether to return the first value or all header values + * @param string $key The header name + * @param string|null $default The default value + * @param bool $first Whether to return the first value or all header values * - * @return string|string[] The first header value or default value if $first is true, an array of values otherwise + * @return string|string[]|null The first header value or default value if $first is true, an array of values otherwise */ public function get($key, $default = null, $first = true) { $key = str_replace('_', '-', strtolower($key)); $headers = $this->all(); - if (!array_key_exists($key, $headers)) { + if (!\array_key_exists($key, $headers)) { if (null === $default) { - return $first ? null : array(); + return $first ? null : []; } - return $first ? $default : array($default); + return $first ? $default : [$default]; } if ($first) { - return \count($headers[$key]) ? $headers[$key][0] : $default; + if (!$headers[$key]) { + return $default; + } + + if (null === $headers[$key][0]) { + return null; + } + + return (string) $headers[$key][0]; } return $headers[$key]; @@ -148,7 +156,7 @@ class HeaderBag implements \IteratorAggregate, \Countable } } else { if (true === $replace || !isset($this->headers[$key])) { - $this->headers[$key] = array($values); + $this->headers[$key] = [$values]; } else { $this->headers[$key][] = $values; } @@ -168,7 +176,7 @@ class HeaderBag implements \IteratorAggregate, \Countable */ public function has($key) { - return array_key_exists(str_replace('_', '-', strtolower($key)), $this->all()); + return \array_key_exists(str_replace('_', '-', strtolower($key)), $this->all()); } /** @@ -181,7 +189,7 @@ class HeaderBag implements \IteratorAggregate, \Countable */ public function contains($key, $value) { - return in_array($value, $this->get($key, null, false)); + return \in_array($value, $this->get($key, null, false)); } /** @@ -196,7 +204,7 @@ class HeaderBag implements \IteratorAggregate, \Countable unset($this->headers[$key]); if ('cache-control' === $key) { - $this->cacheControl = array(); + $this->cacheControl = []; } } @@ -206,7 +214,7 @@ class HeaderBag implements \IteratorAggregate, \Countable * @param string $key The parameter key * @param \DateTime $default The default value * - * @return null|\DateTime The parsed DateTime or the default value if the header does not exist + * @return \DateTime|null The parsed DateTime or the default value if the header does not exist * * @throws \RuntimeException When the HTTP header is not parseable */ @@ -245,7 +253,7 @@ class HeaderBag implements \IteratorAggregate, \Countable */ public function hasCacheControlDirective($key) { - return array_key_exists($key, $this->cacheControl); + return \array_key_exists($key, $this->cacheControl); } /** @@ -257,7 +265,7 @@ class HeaderBag implements \IteratorAggregate, \Countable */ public function getCacheControlDirective($key) { - return array_key_exists($key, $this->cacheControl) ? $this->cacheControl[$key] : null; + return \array_key_exists($key, $this->cacheControl) ? $this->cacheControl[$key] : null; } /** @@ -289,26 +297,14 @@ class HeaderBag implements \IteratorAggregate, \Countable */ public function count() { - return count($this->headers); + return \count($this->headers); } protected function getCacheControlHeader() { - $parts = array(); ksort($this->cacheControl); - foreach ($this->cacheControl as $key => $value) { - if (true === $value) { - $parts[] = $key; - } else { - if (preg_match('#[^a-zA-Z0-9._-]#', $value)) { - $value = '"'.$value.'"'; - } - $parts[] = "$key=$value"; - } - } - - return implode(', ', $parts); + return HeaderUtils::toString($this->cacheControl, ','); } /** @@ -320,12 +316,8 @@ class HeaderBag implements \IteratorAggregate, \Countable */ protected function parseCacheControl($header) { - $cacheControl = array(); - preg_match_all('#([a-zA-Z][a-zA-Z_-]*)\s*(?:=(?:"([^"]*)"|([^ \t",;]*)))?#', $header, $matches, PREG_SET_ORDER); - foreach ($matches as $match) { - $cacheControl[strtolower($match[1])] = isset($match[3]) ? $match[3] : (isset($match[2]) ? $match[2] : true); - } + $parts = HeaderUtils::split($header, ',='); - return $cacheControl; + return HeaderUtils::combine($parts); } } diff --git a/vendor/symfony/http-foundation/HeaderUtils.php b/vendor/symfony/http-foundation/HeaderUtils.php new file mode 100644 index 0000000000000000000000000000000000000000..5866e3b2b53e650796eaf68f417f1875895edd5b --- /dev/null +++ b/vendor/symfony/http-foundation/HeaderUtils.php @@ -0,0 +1,224 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation; + +/** + * HTTP header utility functions. + * + * @author Christian Schmidt <github@chsc.dk> + */ +class HeaderUtils +{ + public const DISPOSITION_ATTACHMENT = 'attachment'; + public const DISPOSITION_INLINE = 'inline'; + + /** + * This class should not be instantiated. + */ + private function __construct() + { + } + + /** + * Splits an HTTP header by one or more separators. + * + * Example: + * + * HeaderUtils::split("da, en-gb;q=0.8", ",;") + * // => ['da'], ['en-gb', 'q=0.8']] + * + * @param string $separators List of characters to split on, ordered by + * precedence, e.g. ",", ";=", or ",;=" + * + * @return array Nested array with as many levels as there are characters in + * $separators + */ + public static function split(string $header, string $separators): array + { + $quotedSeparators = preg_quote($separators, '/'); + + preg_match_all(' + / + (?!\s) + (?: + # quoted-string + "(?:[^"\\\\]|\\\\.)*(?:"|\\\\|$) + | + # token + [^"'.$quotedSeparators.']+ + )+ + (?<!\s) + | + # separator + \s* + (?<separator>['.$quotedSeparators.']) + \s* + /x', trim($header), $matches, PREG_SET_ORDER); + + return self::groupParts($matches, $separators); + } + + /** + * Combines an array of arrays into one associative array. + * + * Each of the nested arrays should have one or two elements. The first + * value will be used as the keys in the associative array, and the second + * will be used as the values, or true if the nested array only contains one + * element. Array keys are lowercased. + * + * Example: + * + * HeaderUtils::combine([["foo", "abc"], ["bar"]]) + * // => ["foo" => "abc", "bar" => true] + */ + public static function combine(array $parts): array + { + $assoc = []; + foreach ($parts as $part) { + $name = strtolower($part[0]); + $value = $part[1] ?? true; + $assoc[$name] = $value; + } + + return $assoc; + } + + /** + * Joins an associative array into a string for use in an HTTP header. + * + * The key and value of each entry are joined with "=", and all entries + * are joined with the specified separator and an additional space (for + * readability). Values are quoted if necessary. + * + * Example: + * + * HeaderUtils::toString(["foo" => "abc", "bar" => true, "baz" => "a b c"], ",") + * // => 'foo=abc, bar, baz="a b c"' + */ + public static function toString(array $assoc, string $separator): string + { + $parts = []; + foreach ($assoc as $name => $value) { + if (true === $value) { + $parts[] = $name; + } else { + $parts[] = $name.'='.self::quote($value); + } + } + + return implode($separator.' ', $parts); + } + + /** + * Encodes a string as a quoted string, if necessary. + * + * If a string contains characters not allowed by the "token" construct in + * the HTTP specification, it is backslash-escaped and enclosed in quotes + * to match the "quoted-string" construct. + */ + public static function quote(string $s): string + { + if (preg_match('/^[a-z0-9!#$%&\'*.^_`|~-]+$/i', $s)) { + return $s; + } + + return '"'.addcslashes($s, '"\\"').'"'; + } + + /** + * Decodes a quoted string. + * + * If passed an unquoted string that matches the "token" construct (as + * defined in the HTTP specification), it is passed through verbatimly. + */ + public static function unquote(string $s): string + { + return preg_replace('/\\\\(.)|"/', '$1', $s); + } + + /** + * Generates a HTTP Content-Disposition field-value. + * + * @param string $disposition One of "inline" or "attachment" + * @param string $filename A unicode string + * @param string $filenameFallback A string containing only ASCII characters that + * is semantically equivalent to $filename. If the filename is already ASCII, + * it can be omitted, or just copied from $filename + * + * @return string A string suitable for use as a Content-Disposition field-value + * + * @throws \InvalidArgumentException + * + * @see RFC 6266 + */ + public static function makeDisposition(string $disposition, string $filename, string $filenameFallback = ''): string + { + if (!\in_array($disposition, [self::DISPOSITION_ATTACHMENT, self::DISPOSITION_INLINE])) { + throw new \InvalidArgumentException(sprintf('The disposition must be either "%s" or "%s".', self::DISPOSITION_ATTACHMENT, self::DISPOSITION_INLINE)); + } + + if ('' === $filenameFallback) { + $filenameFallback = $filename; + } + + // filenameFallback is not ASCII. + if (!preg_match('/^[\x20-\x7e]*$/', $filenameFallback)) { + throw new \InvalidArgumentException('The filename fallback must only contain ASCII characters.'); + } + + // percent characters aren't safe in fallback. + if (false !== strpos($filenameFallback, '%')) { + throw new \InvalidArgumentException('The filename fallback cannot contain the "%" character.'); + } + + // path separators aren't allowed in either. + if (false !== strpos($filename, '/') || false !== strpos($filename, '\\') || false !== strpos($filenameFallback, '/') || false !== strpos($filenameFallback, '\\')) { + throw new \InvalidArgumentException('The filename and the fallback cannot contain the "/" and "\\" characters.'); + } + + $params = ['filename' => $filenameFallback]; + if ($filename !== $filenameFallback) { + $params['filename*'] = "utf-8''".rawurlencode($filename); + } + + return $disposition.'; '.self::toString($params, ';'); + } + + private static function groupParts(array $matches, string $separators): array + { + $separator = $separators[0]; + $partSeparators = substr($separators, 1); + + $i = 0; + $partMatches = []; + foreach ($matches as $match) { + if (isset($match['separator']) && $match['separator'] === $separator) { + ++$i; + } else { + $partMatches[$i][] = $match; + } + } + + $parts = []; + if ($partSeparators) { + foreach ($partMatches as $matches) { + $parts[] = self::groupParts($matches, $partSeparators); + } + } else { + foreach ($partMatches as $matches) { + $parts[] = self::unquote($matches[0][0]); + } + } + + return $parts; + } +} diff --git a/vendor/symfony/http-foundation/IpUtils.php b/vendor/symfony/http-foundation/IpUtils.php index 86d135b2d3afd8e0fb65470ae691439811be9a2d..67d13e57aafce553b40259116ddca89db429a996 100644 --- a/vendor/symfony/http-foundation/IpUtils.php +++ b/vendor/symfony/http-foundation/IpUtils.php @@ -18,7 +18,7 @@ namespace Symfony\Component\HttpFoundation; */ class IpUtils { - private static $checkedIps = array(); + private static $checkedIps = []; /** * This class should not be instantiated. @@ -37,8 +37,8 @@ class IpUtils */ public static function checkIp($requestIp, $ips) { - if (!is_array($ips)) { - $ips = array($ips); + if (!\is_array($ips)) { + $ips = [$ips]; } $method = substr_count($requestIp, ':') > 1 ? 'checkIp6' : 'checkIp4'; @@ -116,7 +116,7 @@ class IpUtils return self::$checkedIps[$cacheKey]; } - if (!((extension_loaded('sockets') && defined('AF_INET6')) || @inet_pton('::1'))) { + if (!((\extension_loaded('sockets') && \defined('AF_INET6')) || @inet_pton('::1'))) { throw new \RuntimeException('Unable to check Ipv6. Check that PHP was not compiled with option "disable-ipv6".'); } diff --git a/vendor/symfony/http-foundation/JsonResponse.php b/vendor/symfony/http-foundation/JsonResponse.php index 137ac33c46ed0c57734d3746e3a8a59bef86d804..11a0bebf883026be1b170ac73e049887aaac7aee 100644 --- a/vendor/symfony/http-foundation/JsonResponse.php +++ b/vendor/symfony/http-foundation/JsonResponse.php @@ -18,7 +18,7 @@ namespace Symfony\Component\HttpFoundation; * object. It is however recommended that you do return an object as it * protects yourself against XSSI and JSON-JavaScript Hijacking. * - * @see https://www.owasp.org/index.php/OWASP_AJAX_Security_Guidelines#Always_return_JSON_with_an_Object_on_the_outside + * @see https://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets/AJAX_Security_Cheat_Sheet.md#always-return-json-with-an-object-on-the-outside * * @author Igor Wiedler <igor@wiedler.ch> */ @@ -39,7 +39,7 @@ class JsonResponse extends Response * @param array $headers An array of response headers * @param bool $json If the data is already a JSON string */ - public function __construct($data = null, $status = 200, $headers = array(), $json = false) + public function __construct($data = null, int $status = 200, array $headers = [], bool $json = false) { parent::__construct('', $status, $headers); @@ -55,24 +55,35 @@ class JsonResponse extends Response * * Example: * - * return JsonResponse::create($data, 200) + * return JsonResponse::create(['key' => 'value']) * ->setSharedMaxAge(300); * - * @param mixed $data The json response data + * @param mixed $data The JSON response data * @param int $status The response status code * @param array $headers An array of response headers * * @return static */ - public static function create($data = null, $status = 200, $headers = array()) + public static function create($data = null, $status = 200, $headers = []) { return new static($data, $status, $headers); } /** - * Make easier the creation of JsonResponse from raw json. + * Factory method for chainability. + * + * Example: + * + * return JsonResponse::fromJsonString('{"key": "value"}') + * ->setSharedMaxAge(300); + * + * @param string|null $data The JSON response string + * @param int $status The response status code + * @param array $headers An array of response headers + * + * @return static */ - public static function fromJsonString($data = null, $status = 200, $headers = array()) + public static function fromJsonString($data = null, $status = 200, $headers = []) { return new static($data, $status, $headers, true); } @@ -89,19 +100,19 @@ class JsonResponse extends Response public function setCallback($callback = null) { if (null !== $callback) { - // partially taken from http://www.geekality.net/2011/08/03/valid-javascript-identifier/ + // partially taken from https://geekality.net/2011/08/03/valid-javascript-identifier/ // partially taken from https://github.com/willdurand/JsonpCallbackValidator // JsonpCallbackValidator is released under the MIT License. See https://github.com/willdurand/JsonpCallbackValidator/blob/v1.1.0/LICENSE for details. // (c) William Durand <william.durand1@gmail.com> $pattern = '/^[$_\p{L}][$_\p{L}\p{Mn}\p{Mc}\p{Nd}\p{Pc}\x{200C}\x{200D}]*(?:\[(?:"(?:\\\.|[^"\\\])*"|\'(?:\\\.|[^\'\\\])*\'|\d+)\])*?$/u'; - $reserved = array( + $reserved = [ 'break', 'do', 'instanceof', 'typeof', 'case', 'else', 'new', 'var', 'catch', 'finally', 'return', 'void', 'continue', 'for', 'switch', 'while', 'debugger', 'function', 'this', 'with', 'default', 'if', 'throw', 'delete', 'in', 'try', 'class', 'enum', 'extends', 'super', 'const', 'export', 'import', 'implements', 'let', 'private', 'public', 'yield', 'interface', 'package', 'protected', 'static', 'null', 'true', 'false', - ); + ]; $parts = explode('.', $callback); foreach ($parts as $part) { - if (!preg_match($pattern, $part) || in_array($part, $reserved, true)) { + if (!preg_match($pattern, $part) || \in_array($part, $reserved, true)) { throw new \InvalidArgumentException('The callback name is not valid.'); } } @@ -137,31 +148,19 @@ class JsonResponse extends Response * * @throws \InvalidArgumentException */ - public function setData($data = array()) + public function setData($data = []) { - if (defined('HHVM_VERSION')) { - // HHVM does not trigger any warnings and let exceptions - // thrown from a JsonSerializable object pass through. - // If only PHP did the same... + try { $data = json_encode($data, $this->encodingOptions); - } else { - if (!interface_exists('JsonSerializable', false)) { - set_error_handler(function () { return false; }); - try { - $data = @json_encode($data, $this->encodingOptions); - } finally { - restore_error_handler(); - } - } else { - try { - $data = json_encode($data, $this->encodingOptions); - } catch (\Exception $e) { - if ('Exception' === get_class($e) && 0 === strpos($e->getMessage(), 'Failed calling ')) { - throw $e->getPrevious() ?: $e; - } - throw $e; - } + } catch (\Exception $e) { + if ('Exception' === \get_class($e) && 0 === strpos($e->getMessage(), 'Failed calling ')) { + throw $e->getPrevious() ?: $e; } + throw $e; + } + + if (\PHP_VERSION_ID >= 70300 && (JSON_THROW_ON_ERROR & $this->encodingOptions)) { + return $this->setJson($data); } if (JSON_ERROR_NONE !== json_last_error()) { diff --git a/vendor/symfony/http-foundation/LICENSE b/vendor/symfony/http-foundation/LICENSE index 21d7fb9e2f29b50caca3a76f0647e94e2cc8ddc1..a677f43763ca467472898351b328aee41e2edd7c 100644 --- a/vendor/symfony/http-foundation/LICENSE +++ b/vendor/symfony/http-foundation/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-2018 Fabien Potencier +Copyright (c) 2004-2019 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/vendor/symfony/http-foundation/ParameterBag.php b/vendor/symfony/http-foundation/ParameterBag.php index 257ef8bceaa43cd7498a19e1c4c7923983b9915f..194ba2c6c57ef04077610d6a2e0947702c5ec168 100644 --- a/vendor/symfony/http-foundation/ParameterBag.php +++ b/vendor/symfony/http-foundation/ParameterBag.php @@ -26,7 +26,7 @@ class ParameterBag implements \IteratorAggregate, \Countable /** * @param array $parameters An array of parameters */ - public function __construct(array $parameters = array()) + public function __construct(array $parameters = []) { $this->parameters = $parameters; } @@ -56,7 +56,7 @@ class ParameterBag implements \IteratorAggregate, \Countable * * @param array $parameters An array of parameters */ - public function replace(array $parameters = array()) + public function replace(array $parameters = []) { $this->parameters = $parameters; } @@ -66,7 +66,7 @@ class ParameterBag implements \IteratorAggregate, \Countable * * @param array $parameters An array of parameters */ - public function add(array $parameters = array()) + public function add(array $parameters = []) { $this->parameters = array_replace($this->parameters, $parameters); } @@ -81,7 +81,7 @@ class ParameterBag implements \IteratorAggregate, \Countable */ public function get($key, $default = null) { - return array_key_exists($key, $this->parameters) ? $this->parameters[$key] : $default; + return \array_key_exists($key, $this->parameters) ? $this->parameters[$key] : $default; } /** @@ -104,7 +104,7 @@ class ParameterBag implements \IteratorAggregate, \Countable */ public function has($key) { - return array_key_exists($key, $this->parameters); + return \array_key_exists($key, $this->parameters); } /** @@ -154,7 +154,7 @@ class ParameterBag implements \IteratorAggregate, \Countable public function getDigits($key, $default = '') { // we need to remove - and + because they're allowed in the filter - return str_replace(array('-', '+'), '', $this->filter($key, $default, FILTER_SANITIZE_NUMBER_INT)); + return str_replace(['-', '+'], '', $this->filter($key, $default, FILTER_SANITIZE_NUMBER_INT)); } /** @@ -174,7 +174,7 @@ class ParameterBag implements \IteratorAggregate, \Countable * Returns the parameter value converted to boolean. * * @param string $key The parameter key - * @param mixed $default The default value if the parameter key does not exist + * @param bool $default The default value if the parameter key does not exist * * @return bool The filtered value */ @@ -191,21 +191,21 @@ class ParameterBag implements \IteratorAggregate, \Countable * @param int $filter FILTER_* constant * @param mixed $options Filter options * - * @see http://php.net/manual/en/function.filter-var.php + * @see https://php.net/filter-var * * @return mixed */ - public function filter($key, $default = null, $filter = FILTER_DEFAULT, $options = array()) + public function filter($key, $default = null, $filter = FILTER_DEFAULT, $options = []) { $value = $this->get($key, $default); // Always turn $options into an array - this allows filter_var option shortcuts. - if (!is_array($options) && $options) { - $options = array('flags' => $options); + if (!\is_array($options) && $options) { + $options = ['flags' => $options]; } // Add a convenience check for arrays. - if (is_array($value) && !isset($options['flags'])) { + if (\is_array($value) && !isset($options['flags'])) { $options['flags'] = FILTER_REQUIRE_ARRAY; } @@ -229,6 +229,6 @@ class ParameterBag implements \IteratorAggregate, \Countable */ public function count() { - return count($this->parameters); + return \count($this->parameters); } } diff --git a/vendor/symfony/http-foundation/RedirectResponse.php b/vendor/symfony/http-foundation/RedirectResponse.php index 01681dcdf787a1314c716bd6051b1cfc0f69c954..3abdf3eb4448f1d50218f7136eb43db5f37cbdec 100644 --- a/vendor/symfony/http-foundation/RedirectResponse.php +++ b/vendor/symfony/http-foundation/RedirectResponse.php @@ -30,9 +30,9 @@ class RedirectResponse extends Response * * @throws \InvalidArgumentException * - * @see http://tools.ietf.org/html/rfc2616#section-10.3 + * @see https://tools.ietf.org/html/rfc2616#section-10.3 */ - public function __construct($url, $status = 302, $headers = array()) + public function __construct(?string $url, int $status = 302, array $headers = []) { parent::__construct('', $status, $headers); @@ -42,7 +42,7 @@ class RedirectResponse extends Response throw new \InvalidArgumentException(sprintf('The HTTP status code is not a redirect ("%s" given).', $status)); } - if (301 == $status && !array_key_exists('cache-control', $headers)) { + if (301 == $status && !\array_key_exists('cache-control', array_change_key_case($headers, \CASE_LOWER))) { $this->headers->remove('cache-control'); } } @@ -56,7 +56,7 @@ class RedirectResponse extends Response * * @return static */ - public static function create($url = '', $status = 302, $headers = array()) + public static function create($url = '', $status = 302, $headers = []) { return new static($url, $status, $headers); } diff --git a/vendor/symfony/http-foundation/Request.php b/vendor/symfony/http-foundation/Request.php index be55069e47a6c031571ae24e5fba6cb52a1111f6..9af2c28256fab4fded3f8b89ca373d9a95a31df8 100644 --- a/vendor/symfony/http-foundation/Request.php +++ b/vendor/symfony/http-foundation/Request.php @@ -38,15 +38,6 @@ class Request const HEADER_X_FORWARDED_ALL = 0b11110; // All "X-Forwarded-*" headers const HEADER_X_FORWARDED_AWS_ELB = 0b11010; // AWS ELB doesn't send X-Forwarded-Host - /** @deprecated since version 3.3, to be removed in 4.0 */ - const HEADER_CLIENT_IP = self::HEADER_X_FORWARDED_FOR; - /** @deprecated since version 3.3, to be removed in 4.0 */ - const HEADER_CLIENT_HOST = self::HEADER_X_FORWARDED_HOST; - /** @deprecated since version 3.3, to be removed in 4.0 */ - const HEADER_CLIENT_PROTO = self::HEADER_X_FORWARDED_PROTO; - /** @deprecated since version 3.3, to be removed in 4.0 */ - const HEADER_CLIENT_PORT = self::HEADER_X_FORWARDED_PORT; - const METHOD_HEAD = 'HEAD'; const METHOD_GET = 'GET'; const METHOD_POST = 'POST'; @@ -61,90 +52,71 @@ class Request /** * @var string[] */ - protected static $trustedProxies = array(); + protected static $trustedProxies = []; /** * @var string[] */ - protected static $trustedHostPatterns = array(); + protected static $trustedHostPatterns = []; /** * @var string[] */ - protected static $trustedHosts = array(); - - /** - * Names for headers that can be trusted when - * using trusted proxies. - * - * The FORWARDED header is the standard as of rfc7239. - * - * The other headers are non-standard, but widely used - * by popular reverse proxies (like Apache mod_proxy or Amazon EC2). - * - * @deprecated since version 3.3, to be removed in 4.0 - */ - protected static $trustedHeaders = array( - self::HEADER_FORWARDED => 'FORWARDED', - self::HEADER_CLIENT_IP => 'X_FORWARDED_FOR', - self::HEADER_CLIENT_HOST => 'X_FORWARDED_HOST', - self::HEADER_CLIENT_PROTO => 'X_FORWARDED_PROTO', - self::HEADER_CLIENT_PORT => 'X_FORWARDED_PORT', - ); + protected static $trustedHosts = []; protected static $httpMethodParameterOverride = false; /** * Custom parameters. * - * @var \Symfony\Component\HttpFoundation\ParameterBag + * @var ParameterBag */ public $attributes; /** * Request body parameters ($_POST). * - * @var \Symfony\Component\HttpFoundation\ParameterBag + * @var ParameterBag */ public $request; /** * Query string parameters ($_GET). * - * @var \Symfony\Component\HttpFoundation\ParameterBag + * @var ParameterBag */ public $query; /** * Server and execution environment parameters ($_SERVER). * - * @var \Symfony\Component\HttpFoundation\ServerBag + * @var ServerBag */ public $server; /** * Uploaded files ($_FILES). * - * @var \Symfony\Component\HttpFoundation\FileBag + * @var FileBag */ public $files; /** * Cookies ($_COOKIE). * - * @var \Symfony\Component\HttpFoundation\ParameterBag + * @var ParameterBag */ public $cookies; /** * Headers (taken from the $_SERVER). * - * @var \Symfony\Component\HttpFoundation\HeaderBag + * @var HeaderBag */ public $headers; /** - * @var string|resource + * @var string|resource|false|null */ protected $content; @@ -199,7 +171,7 @@ class Request protected $format; /** - * @var \Symfony\Component\HttpFoundation\Session\SessionInterface + * @var SessionInterface */ protected $session; @@ -225,32 +197,40 @@ class Request private static $trustedHeaderSet = -1; - /** @deprecated since version 3.3, to be removed in 4.0 */ - private static $trustedHeaderNames = array( - self::HEADER_FORWARDED => 'FORWARDED', - self::HEADER_CLIENT_IP => 'X_FORWARDED_FOR', - self::HEADER_CLIENT_HOST => 'X_FORWARDED_HOST', - self::HEADER_CLIENT_PROTO => 'X_FORWARDED_PROTO', - self::HEADER_CLIENT_PORT => 'X_FORWARDED_PORT', - ); - - private static $forwardedParams = array( + private static $forwardedParams = [ self::HEADER_X_FORWARDED_FOR => 'for', self::HEADER_X_FORWARDED_HOST => 'host', self::HEADER_X_FORWARDED_PROTO => 'proto', self::HEADER_X_FORWARDED_PORT => 'host', - ); + ]; + + /** + * Names for headers that can be trusted when + * using trusted proxies. + * + * The FORWARDED header is the standard as of rfc7239. + * + * The other headers are non-standard, but widely used + * by popular reverse proxies (like Apache mod_proxy or Amazon EC2). + */ + private static $trustedHeaders = [ + self::HEADER_FORWARDED => 'FORWARDED', + self::HEADER_X_FORWARDED_FOR => 'X_FORWARDED_FOR', + self::HEADER_X_FORWARDED_HOST => 'X_FORWARDED_HOST', + self::HEADER_X_FORWARDED_PROTO => 'X_FORWARDED_PROTO', + self::HEADER_X_FORWARDED_PORT => 'X_FORWARDED_PORT', + ]; /** - * @param array $query The GET parameters - * @param array $request The POST parameters - * @param array $attributes The request attributes (parameters parsed from the PATH_INFO, ...) - * @param array $cookies The COOKIE parameters - * @param array $files The FILES parameters - * @param array $server The SERVER parameters - * @param string|resource $content The raw body data + * @param array $query The GET parameters + * @param array $request The POST parameters + * @param array $attributes The request attributes (parameters parsed from the PATH_INFO, ...) + * @param array $cookies The COOKIE parameters + * @param array $files The FILES parameters + * @param array $server The SERVER parameters + * @param string|resource|null $content The raw body data */ - public function __construct(array $query = array(), array $request = array(), array $attributes = array(), array $cookies = array(), array $files = array(), array $server = array(), $content = null) + public function __construct(array $query = [], array $request = [], array $attributes = [], array $cookies = [], array $files = [], array $server = [], $content = null) { $this->initialize($query, $request, $attributes, $cookies, $files, $server, $content); } @@ -260,15 +240,15 @@ class Request * * This method also re-initializes all properties. * - * @param array $query The GET parameters - * @param array $request The POST parameters - * @param array $attributes The request attributes (parameters parsed from the PATH_INFO, ...) - * @param array $cookies The COOKIE parameters - * @param array $files The FILES parameters - * @param array $server The SERVER parameters - * @param string|resource $content The raw body data + * @param array $query The GET parameters + * @param array $request The POST parameters + * @param array $attributes The request attributes (parameters parsed from the PATH_INFO, ...) + * @param array $cookies The COOKIE parameters + * @param array $files The FILES parameters + * @param array $server The SERVER parameters + * @param string|resource|null $content The raw body data */ - public function initialize(array $query = array(), array $request = array(), array $attributes = array(), array $cookies = array(), array $files = array(), array $server = array(), $content = null) + public function initialize(array $query = [], array $request = [], array $attributes = [], array $cookies = [], array $files = [], array $server = [], $content = null) { $this->request = new ParameterBag($request); $this->query = new ParameterBag($query); @@ -298,23 +278,10 @@ class Request */ public static function createFromGlobals() { - // With the php's bug #66606, the php's built-in web server - // stores the Content-Type and Content-Length header values in - // HTTP_CONTENT_TYPE and HTTP_CONTENT_LENGTH fields. - $server = $_SERVER; - if ('cli-server' === PHP_SAPI) { - if (array_key_exists('HTTP_CONTENT_LENGTH', $_SERVER)) { - $server['CONTENT_LENGTH'] = $_SERVER['HTTP_CONTENT_LENGTH']; - } - if (array_key_exists('HTTP_CONTENT_TYPE', $_SERVER)) { - $server['CONTENT_TYPE'] = $_SERVER['HTTP_CONTENT_TYPE']; - } - } - - $request = self::createRequestFromFactory($_GET, $_POST, array(), $_COOKIE, $_FILES, $server); + $request = self::createRequestFromFactory($_GET, $_POST, [], $_COOKIE, $_FILES, $_SERVER); if (0 === strpos($request->headers->get('CONTENT_TYPE'), 'application/x-www-form-urlencoded') - && in_array(strtoupper($request->server->get('REQUEST_METHOD', 'GET')), array('PUT', 'DELETE', 'PATCH')) + && \in_array(strtoupper($request->server->get('REQUEST_METHOD', 'GET')), ['PUT', 'DELETE', 'PATCH']) ) { parse_str($request->getContent(), $data); $request->request = new ParameterBag($data); @@ -329,23 +296,23 @@ class Request * The information contained in the URI always take precedence * over the other information (server and parameters). * - * @param string $uri The URI - * @param string $method The HTTP method - * @param array $parameters The query (GET) or request (POST) parameters - * @param array $cookies The request cookies ($_COOKIE) - * @param array $files The request files ($_FILES) - * @param array $server The server parameters ($_SERVER) - * @param string|resource $content The raw body data + * @param string $uri The URI + * @param string $method The HTTP method + * @param array $parameters The query (GET) or request (POST) parameters + * @param array $cookies The request cookies ($_COOKIE) + * @param array $files The request files ($_FILES) + * @param array $server The server parameters ($_SERVER) + * @param string|resource|null $content The raw body data * * @return static */ - public static function create($uri, $method = 'GET', $parameters = array(), $cookies = array(), $files = array(), $server = array(), $content = null) + public static function create($uri, $method = 'GET', $parameters = [], $cookies = [], $files = [], $server = [], $content = null) { - $server = array_replace(array( + $server = array_replace([ 'SERVER_NAME' => 'localhost', 'SERVER_PORT' => 80, 'HTTP_HOST' => 'localhost', - 'HTTP_USER_AGENT' => 'Symfony/3.X', + 'HTTP_USER_AGENT' => 'Symfony', 'HTTP_ACCEPT' => 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', 'HTTP_ACCEPT_LANGUAGE' => 'en-us,en;q=0.5', 'HTTP_ACCEPT_CHARSET' => 'ISO-8859-1,utf-8;q=0.7,*;q=0.7', @@ -354,7 +321,7 @@ class Request 'SCRIPT_FILENAME' => '', 'SERVER_PROTOCOL' => 'HTTP/1.1', 'REQUEST_TIME' => time(), - ), $server); + ], $server); $server['PATH_INFO'] = ''; $server['REQUEST_METHOD'] = strtoupper($method); @@ -377,7 +344,7 @@ class Request if (isset($components['port'])) { $server['SERVER_PORT'] = $components['port']; - $server['HTTP_HOST'] = $server['HTTP_HOST'].':'.$components['port']; + $server['HTTP_HOST'] .= ':'.$components['port']; } if (isset($components['user'])) { @@ -402,10 +369,10 @@ class Request // no break case 'PATCH': $request = $parameters; - $query = array(); + $query = []; break; default: - $request = array(); + $request = []; $query = $parameters; break; } @@ -428,7 +395,7 @@ class Request $server['REQUEST_URI'] = $components['path'].('' !== $queryString ? '?'.$queryString : ''); $server['QUERY_STRING'] = $queryString; - return self::createRequestFromFactory($query, $request, array(), $cookies, $files, $server, $content); + return self::createRequestFromFactory($query, $request, [], $cookies, $files, $server, $content); } /** @@ -528,11 +495,15 @@ class Request try { $content = $this->getContent(); } catch (\LogicException $e) { + if (\PHP_VERSION_ID >= 70400) { + throw $e; + } + return trigger_error($e, E_USER_ERROR); } $cookieHeader = ''; - $cookies = array(); + $cookies = []; foreach ($this->cookies as $k => $v) { $cookies[] = $k.'='.$v; @@ -557,7 +528,7 @@ class Request */ public function overrideGlobals() { - $this->server->set('QUERY_STRING', static::normalizeQueryString(http_build_query($this->query->all(), null, '&'))); + $this->server->set('QUERY_STRING', static::normalizeQueryString(http_build_query($this->query->all(), '', '&'))); $_GET = $this->query->all(); $_POST = $this->request->all(); @@ -566,22 +537,25 @@ class Request foreach ($this->headers->all() as $key => $value) { $key = strtoupper(str_replace('-', '_', $key)); - if (in_array($key, array('CONTENT_TYPE', 'CONTENT_LENGTH'))) { + if (\in_array($key, ['CONTENT_TYPE', 'CONTENT_LENGTH'])) { $_SERVER[$key] = implode(', ', $value); } else { $_SERVER['HTTP_'.$key] = implode(', ', $value); } } - $request = array('g' => $_GET, 'p' => $_POST, 'c' => $_COOKIE); + $request = ['g' => $_GET, 'p' => $_POST, 'c' => $_COOKIE]; $requestOrder = ini_get('request_order') ?: ini_get('variables_order'); $requestOrder = preg_replace('#[^cgp]#', '', strtolower($requestOrder)) ?: 'gp'; - $_REQUEST = array(); + $_REQUEST = [[]]; + foreach (str_split($requestOrder) as $order) { - $_REQUEST = array_merge($_REQUEST, $request[$order]); + $_REQUEST[] = $request[$order]; } + + $_REQUEST = array_merge(...$_REQUEST); } /** @@ -594,20 +568,9 @@ class Request * * @throws \InvalidArgumentException When $trustedHeaderSet is invalid */ - public static function setTrustedProxies(array $proxies/*, int $trustedHeaderSet*/) + public static function setTrustedProxies(array $proxies, int $trustedHeaderSet) { self::$trustedProxies = $proxies; - - if (2 > func_num_args()) { - @trigger_error(sprintf('The %s() method expects a bit field of Request::HEADER_* as second argument since Symfony 3.3. Defining it will be required in 4.0. ', __METHOD__), E_USER_DEPRECATED); - - return; - } - $trustedHeaderSet = (int) func_get_arg(1); - - foreach (self::$trustedHeaderNames as $header => $name) { - self::$trustedHeaders[$header] = $header & $trustedHeaderSet ? $name : null; - } self::$trustedHeaderSet = $trustedHeaderSet; } @@ -641,10 +604,10 @@ class Request public static function setTrustedHosts(array $hostPatterns) { self::$trustedHostPatterns = array_map(function ($hostPattern) { - return sprintf('#%s#i', $hostPattern); + return sprintf('{%s}i', $hostPattern); }, $hostPatterns); // we need to reset trusted hosts on trusted host patterns change - self::$trustedHosts = array(); + self::$trustedHosts = []; } /** @@ -657,78 +620,6 @@ class Request return self::$trustedHostPatterns; } - /** - * Sets the name for trusted headers. - * - * The following header keys are supported: - * - * * Request::HEADER_CLIENT_IP: defaults to X-Forwarded-For (see getClientIp()) - * * Request::HEADER_CLIENT_HOST: defaults to X-Forwarded-Host (see getHost()) - * * Request::HEADER_CLIENT_PORT: defaults to X-Forwarded-Port (see getPort()) - * * Request::HEADER_CLIENT_PROTO: defaults to X-Forwarded-Proto (see getScheme() and isSecure()) - * * Request::HEADER_FORWARDED: defaults to Forwarded (see RFC 7239) - * - * Setting an empty value allows to disable the trusted header for the given key. - * - * @param string $key The header key - * @param string $value The header name - * - * @throws \InvalidArgumentException - * - * @deprecated since version 3.3, to be removed in 4.0. Use the $trustedHeaderSet argument of the Request::setTrustedProxies() method instead. - */ - public static function setTrustedHeaderName($key, $value) - { - @trigger_error(sprintf('The "%s()" method is deprecated since Symfony 3.3 and will be removed in 4.0. Use the $trustedHeaderSet argument of the Request::setTrustedProxies() method instead.', __METHOD__), E_USER_DEPRECATED); - - if ('forwarded' === $key) { - $key = self::HEADER_FORWARDED; - } elseif ('client_ip' === $key) { - $key = self::HEADER_CLIENT_IP; - } elseif ('client_host' === $key) { - $key = self::HEADER_CLIENT_HOST; - } elseif ('client_proto' === $key) { - $key = self::HEADER_CLIENT_PROTO; - } elseif ('client_port' === $key) { - $key = self::HEADER_CLIENT_PORT; - } elseif (!array_key_exists($key, self::$trustedHeaders)) { - throw new \InvalidArgumentException(sprintf('Unable to set the trusted header name for key "%s".', $key)); - } - - self::$trustedHeaders[$key] = $value; - - if (null !== $value) { - self::$trustedHeaderNames[$key] = $value; - self::$trustedHeaderSet |= $key; - } else { - self::$trustedHeaderSet &= ~$key; - } - } - - /** - * Gets the trusted proxy header name. - * - * @param string $key The header key - * - * @return string The header name - * - * @throws \InvalidArgumentException - * - * @deprecated since version 3.3, to be removed in 4.0. Use the Request::getTrustedHeaderSet() method instead. - */ - public static function getTrustedHeaderName($key) - { - if (2 > func_num_args() || func_get_arg(1)) { - @trigger_error(sprintf('The "%s()" method is deprecated since Symfony 3.3 and will be removed in 4.0. Use the Request::getTrustedHeaderSet() method instead.', __METHOD__), E_USER_DEPRECATED); - } - - if (!array_key_exists($key, self::$trustedHeaders)) { - throw new \InvalidArgumentException(sprintf('Unable to get the trusted header name for key "%s".', $key)); - } - - return self::$trustedHeaders[$key]; - } - /** * Normalizes a query string. * @@ -745,31 +636,10 @@ class Request return ''; } - $parts = array(); - $order = array(); - - foreach (explode('&', $qs) as $param) { - if ('' === $param || '=' === $param[0]) { - // Ignore useless delimiters, e.g. "x=y&". - // Also ignore pairs with empty key, even if there was a value, e.g. "=value", as such nameless values cannot be retrieved anyway. - // PHP also does not include them when building _GET. - continue; - } - - $keyValuePair = explode('=', $param, 2); - - // GET parameters, that are submitted from a HTML form, encode spaces as "+" by default (as defined in enctype application/x-www-form-urlencoded). - // PHP also converts "+" to spaces when filling the global _GET or when using the function parse_str. This is why we use urldecode and then normalize to - // RFC 3986 with rawurlencode. - $parts[] = isset($keyValuePair[1]) ? - rawurlencode(urldecode($keyValuePair[0])).'='.rawurlencode(urldecode($keyValuePair[1])) : - rawurlencode(urldecode($keyValuePair[0])); - $order[] = urldecode($keyValuePair[0]); - } - - array_multisort($order, SORT_ASC, $parts); + parse_str($qs, $qs); + ksort($qs); - return implode('&', $parts); + return http_build_query($qs, '', '&', PHP_QUERY_RFC3986); } /** @@ -836,7 +706,17 @@ class Request */ public function getSession() { - return $this->session; + $session = $this->session; + if (!$session instanceof SessionInterface && null !== $session) { + $this->setSession($session = $session()); + } + + if (null === $session) { + @trigger_error(sprintf('Calling "%s()" when no session has been set is deprecated since Symfony 4.1 and will throw an exception in 5.0. Use "hasSession()" instead.', __METHOD__), E_USER_DEPRECATED); + // throw new \BadMethodCallException('Session has not been set'); + } + + return $session; } /** @@ -848,7 +728,7 @@ class Request public function hasPreviousSession() { // the check for $this->session avoids malicious users trying to fake a session cookie with proper name - return $this->hasSession() && $this->cookies->has($this->session->getName()); + return $this->hasSession() && $this->cookies->has($this->getSession()->getName()); } /** @@ -875,6 +755,14 @@ class Request $this->session = $session; } + /** + * @internal + */ + public function setSessionFactory(callable $factory) + { + $this->session = $factory; + } + /** * Returns the client IP addresses. * @@ -893,10 +781,10 @@ class Request $ip = $this->server->get('REMOTE_ADDR'); if (!$this->isFromTrustedProxy()) { - return array($ip); + return [$ip]; } - return $this->getTrustedValues(self::HEADER_CLIENT_IP, $ip) ?: array($ip); + return $this->getTrustedValues(self::HEADER_X_FORWARDED_FOR, $ip) ?: [$ip]; } /** @@ -915,7 +803,7 @@ class Request * @return string|null The client IP address * * @see getClientIps() - * @see http://en.wikipedia.org/wiki/X-Forwarded-For + * @see https://wikipedia.org/wiki/X-Forwarded-For */ public function getClientIp() { @@ -1015,17 +903,13 @@ class Request * * The "X-Forwarded-Port" header must contain the client port. * - * If your reverse proxy uses a different header name than "X-Forwarded-Port", - * configure it via via the $trustedHeaderSet argument of the - * Request::setTrustedProxies() method instead. - * * @return int|string can be a string if fetched from the server bag */ public function getPort() { - if ($this->isFromTrustedProxy() && $host = $this->getTrustedValues(self::HEADER_CLIENT_PORT)) { + if ($this->isFromTrustedProxy() && $host = $this->getTrustedValues(self::HEADER_X_FORWARDED_PORT)) { $host = $host[0]; - } elseif ($this->isFromTrustedProxy() && $host = $this->getTrustedValues(self::HEADER_CLIENT_HOST)) { + } elseif ($this->isFromTrustedProxy() && $host = $this->getTrustedValues(self::HEADER_X_FORWARDED_HOST)) { $host = $host[0]; } elseif (!$host = $this->headers->get('HOST')) { return $this->server->get('SERVER_PORT'); @@ -1037,8 +921,8 @@ class Request $pos = strrpos($host, ':'); } - if (false !== $pos) { - return (int) substr($host, $pos + 1); + if (false !== $pos && $port = substr($host, $pos + 1)) { + return (int) $port; } return 'https' === $this->getScheme() ? 443 : 80; @@ -1186,7 +1070,7 @@ class Request } $sourceDirs = explode('/', isset($basePath[0]) && '/' === $basePath[0] ? substr($basePath, 1) : $basePath); - $targetDirs = explode('/', isset($path[0]) && '/' === $path[0] ? substr($path, 1) : $path); + $targetDirs = explode('/', substr($path, 1)); array_pop($sourceDirs); $targetFile = array_pop($targetDirs); @@ -1199,12 +1083,12 @@ class Request } $targetDirs[] = $targetFile; - $path = str_repeat('../', count($sourceDirs)).implode('/', $targetDirs); + $path = str_repeat('../', \count($sourceDirs)).implode('/', $targetDirs); // A reference to the same base directory or an empty subdirectory must be prefixed with "./". // This also applies to a segment with a colon character (e.g., "file:colon") that cannot be used // as the first segment of a relative-path reference, as it would be mistaken for a scheme name - // (see http://tools.ietf.org/html/rfc3986#section-4.2). + // (see https://tools.ietf.org/html/rfc3986#section-4.2). return !isset($path[0]) || '/' === $path[0] || false !== ($colonPos = strpos($path, ':')) && ($colonPos < ($slashPos = strpos($path, '/')) || false === $slashPos) ? "./$path" : $path; @@ -1233,16 +1117,12 @@ class Request * * The "X-Forwarded-Proto" header must contain the protocol: "https" or "http". * - * If your reverse proxy uses a different header name than "X-Forwarded-Proto" - * ("SSL_HTTPS" for instance), configure it via the $trustedHeaderSet - * argument of the Request::setTrustedProxies() method instead. - * * @return bool */ public function isSecure() { - if ($this->isFromTrustedProxy() && $proto = $this->getTrustedValues(self::HEADER_CLIENT_PROTO)) { - return in_array(strtolower($proto[0]), array('https', 'on', 'ssl', '1'), true); + if ($this->isFromTrustedProxy() && $proto = $this->getTrustedValues(self::HEADER_X_FORWARDED_PROTO)) { + return \in_array(strtolower($proto[0]), ['https', 'on', 'ssl', '1'], true); } $https = $this->server->get('HTTPS'); @@ -1258,17 +1138,13 @@ class Request * * The "X-Forwarded-Host" header must contain the client host name. * - * If your reverse proxy uses a different header name than "X-Forwarded-Host", - * configure it via the $trustedHeaderSet argument of the - * Request::setTrustedProxies() method instead. - * * @return string * * @throws SuspiciousOperationException when the host name is invalid or not trusted */ public function getHost() { - if ($this->isFromTrustedProxy() && $host = $this->getTrustedValues(self::HEADER_CLIENT_HOST)) { + if ($this->isFromTrustedProxy() && $host = $this->getTrustedValues(self::HEADER_X_FORWARDED_HOST)) { $host = $host[0]; } elseif (!$host = $this->headers->get('HOST')) { if (!$host = $this->server->get('SERVER_NAME')) { @@ -1292,10 +1168,10 @@ class Request throw new SuspiciousOperationException(sprintf('Invalid Host "%s".', $host)); } - if (count(self::$trustedHostPatterns) > 0) { + if (\count(self::$trustedHostPatterns) > 0) { // to avoid host header injection attacks, you should provide a list of trusted host patterns - if (in_array($host, self::$trustedHosts)) { + if (\in_array($host, self::$trustedHosts)) { return $host; } @@ -1346,19 +1222,37 @@ class Request */ public function getMethod() { - if (null === $this->method) { - $this->method = strtoupper($this->server->get('REQUEST_METHOD', 'GET')); + if (null !== $this->method) { + return $this->method; + } - if ('POST' === $this->method) { - if ($method = $this->headers->get('X-HTTP-METHOD-OVERRIDE')) { - $this->method = strtoupper($method); - } elseif (self::$httpMethodParameterOverride) { - $this->method = strtoupper($this->request->get('_method', $this->query->get('_method', 'POST'))); - } - } + $this->method = strtoupper($this->server->get('REQUEST_METHOD', 'GET')); + + if ('POST' !== $this->method) { + return $this->method; + } + + $method = $this->headers->get('X-HTTP-METHOD-OVERRIDE'); + + if (!$method && self::$httpMethodParameterOverride) { + $method = $this->request->get('_method', $this->query->get('_method', 'POST')); } - return $this->method; + if (!\is_string($method)) { + return $this->method; + } + + $method = strtoupper($method); + + if (\in_array($method, ['GET', 'HEAD', 'POST', 'PUT', 'DELETE', 'CONNECT', 'OPTIONS', 'PATCH', 'PURGE', 'TRACE'], true)) { + return $this->method = $method; + } + + if (!preg_match('/^[A-Z]++$/D', $method)) { + throw new SuspiciousOperationException(sprintf('Invalid method override "%s".', $method)); + } + + return $this->method = $method; } /** @@ -1378,7 +1272,7 @@ class Request * * @param string $format The format * - * @return string The associated mime type (null if not found) + * @return string|null The associated mime type (null if not found) */ public function getMimeType($format) { @@ -1402,7 +1296,7 @@ class Request static::initializeFormats(); } - return isset(static::$formats[$format]) ? static::$formats[$format] : array(); + return isset(static::$formats[$format]) ? static::$formats[$format] : []; } /** @@ -1416,7 +1310,7 @@ class Request { $canonicalMimeType = null; if (false !== $pos = strpos($mimeType, ';')) { - $canonicalMimeType = substr($mimeType, 0, $pos); + $canonicalMimeType = trim(substr($mimeType, 0, $pos)); } if (null === static::$formats) { @@ -1424,13 +1318,15 @@ class Request } foreach (static::$formats as $format => $mimeTypes) { - if (in_array($mimeType, (array) $mimeTypes)) { + if (\in_array($mimeType, (array) $mimeTypes)) { return $format; } - if (null !== $canonicalMimeType && in_array($canonicalMimeType, (array) $mimeTypes)) { + if (null !== $canonicalMimeType && \in_array($canonicalMimeType, (array) $mimeTypes)) { return $format; } } + + return null; } /** @@ -1445,7 +1341,7 @@ class Request static::initializeFormats(); } - static::$formats[$format] = is_array($mimeTypes) ? $mimeTypes : array($mimeTypes); + static::$formats[$format] = \is_array($mimeTypes) ? $mimeTypes : [$mimeTypes]; } /** @@ -1457,9 +1353,9 @@ class Request * * _format request attribute * * $default * - * @param string $default The default format + * @param string|null $default The default format * - * @return string The request format + * @return string|null The request format */ public function getRequestFormat($default = 'html') { @@ -1557,15 +1453,12 @@ class Request */ public function isMethodSafe(/* $andCacheable = true */) { - if (!func_num_args() || func_get_arg(0)) { - // This deprecation should be turned into a BadMethodCallException in 4.0 (without adding the argument in the signature) - // then setting $andCacheable to false should be deprecated in 4.1 - @trigger_error('Checking only for cacheable HTTP methods with Symfony\Component\HttpFoundation\Request::isMethodSafe() is deprecated since Symfony 3.2 and will throw an exception in 4.0. Disable checking only for cacheable methods by calling the method with `false` as first argument or use the Request::isMethodCacheable() instead.', E_USER_DEPRECATED); - - return in_array($this->getMethod(), array('GET', 'HEAD')); + if (!\func_num_args() || func_get_arg(0)) { + // setting $andCacheable to false should be deprecated in 4.1 + throw new \BadMethodCallException('Checking only for cacheable HTTP methods with Symfony\Component\HttpFoundation\Request::isMethodSafe() is not supported.'); } - return in_array($this->getMethod(), array('GET', 'HEAD', 'OPTIONS', 'TRACE')); + return \in_array($this->getMethod(), ['GET', 'HEAD', 'OPTIONS', 'TRACE']); } /** @@ -1575,7 +1468,7 @@ class Request */ public function isMethodIdempotent() { - return in_array($this->getMethod(), array('HEAD', 'GET', 'PUT', 'DELETE', 'TRACE', 'OPTIONS', 'PURGE')); + return \in_array($this->getMethod(), ['HEAD', 'GET', 'PUT', 'DELETE', 'TRACE', 'OPTIONS', 'PURGE']); } /** @@ -1583,11 +1476,11 @@ class Request * * @see https://tools.ietf.org/html/rfc7231#section-4.2.3 * - * @return bool + * @return bool True for GET and HEAD, false otherwise */ public function isMethodCacheable() { - return in_array($this->getMethod(), array('GET', 'HEAD')); + return \in_array($this->getMethod(), ['GET', 'HEAD']); } /** @@ -1625,10 +1518,7 @@ class Request */ public function getContent($asResource = false) { - $currentContentIsResource = is_resource($this->content); - if (\PHP_VERSION_ID < 50600 && false === $this->content) { - throw new \LogicException('getContent() can only be called once when using the resource return type and PHP below 5.6.'); - } + $currentContentIsResource = \is_resource($this->content); if (true === $asResource) { if ($currentContentIsResource) { @@ -1638,7 +1528,7 @@ class Request } // Content passed in parameter (test) - if (is_string($this->content)) { + if (\is_string($this->content)) { $resource = fopen('php://temp', 'r+'); fwrite($resource, $this->content); rewind($resource); @@ -1701,12 +1591,12 @@ class Request return $locales[0]; } - $extendedPreferredLanguages = array(); + $extendedPreferredLanguages = []; foreach ($preferredLanguages as $language) { $extendedPreferredLanguages[] = $language; if (false !== $position = strpos($language, '_')) { $superLanguage = substr($language, 0, $position); - if (!in_array($superLanguage, $preferredLanguages)) { + if (!\in_array($superLanguage, $preferredLanguages)) { $extendedPreferredLanguages[] = $superLanguage; } } @@ -1729,7 +1619,7 @@ class Request } $languages = AcceptHeader::fromString($this->headers->get('Accept-Language'))->all(); - $this->languages = array(); + $this->languages = []; foreach ($languages as $lang => $acceptHeaderItem) { if (false !== strpos($lang, '-')) { $codes = explode('-', $lang); @@ -1737,11 +1627,11 @@ class Request // Language not listed in ISO 639 that are not variants // of any listed language, which can be registered with the // i-prefix, such as i-cherokee - if (count($codes) > 1) { + if (\count($codes) > 1) { $lang = $codes[1]; } } else { - for ($i = 0, $max = count($codes); $i < $max; ++$i) { + for ($i = 0, $max = \count($codes); $i < $max; ++$i) { if (0 === $i) { $lang = strtolower($codes[0]); } else { @@ -1805,7 +1695,7 @@ class Request * It works if your JavaScript library sets an X-Requested-With HTTP header. * It is known to work with common JavaScript frameworks: * - * @see http://en.wikipedia.org/wiki/List_of_Ajax_frameworks#JavaScript + * @see https://wikipedia.org/wiki/List_of_Ajax_frameworks#JavaScript * * @return bool true if the request is an XMLHttpRequest, false otherwise */ @@ -1817,37 +1707,40 @@ class Request /* * The following methods are derived from code of the Zend Framework (1.10dev - 2010-01-24) * - * Code subject to the new BSD license (http://framework.zend.com/license/new-bsd). + * Code subject to the new BSD license (https://framework.zend.com/license). * - * Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) + * Copyright (c) 2005-2010 Zend Technologies USA Inc. (https://www.zend.com/) */ protected function prepareRequestUri() { $requestUri = ''; - if ($this->headers->has('X_ORIGINAL_URL')) { - // IIS with Microsoft Rewrite Module - $requestUri = $this->headers->get('X_ORIGINAL_URL'); - $this->headers->remove('X_ORIGINAL_URL'); - $this->server->remove('HTTP_X_ORIGINAL_URL'); - $this->server->remove('UNENCODED_URL'); - $this->server->remove('IIS_WasUrlRewritten'); - } elseif ($this->headers->has('X_REWRITE_URL')) { - // IIS with ISAPI_Rewrite - $requestUri = $this->headers->get('X_REWRITE_URL'); - $this->headers->remove('X_REWRITE_URL'); - } elseif ('1' == $this->server->get('IIS_WasUrlRewritten') && '' != $this->server->get('UNENCODED_URL')) { + if ('1' == $this->server->get('IIS_WasUrlRewritten') && '' != $this->server->get('UNENCODED_URL')) { // IIS7 with URL Rewrite: make sure we get the unencoded URL (double slash problem) $requestUri = $this->server->get('UNENCODED_URL'); $this->server->remove('UNENCODED_URL'); $this->server->remove('IIS_WasUrlRewritten'); } elseif ($this->server->has('REQUEST_URI')) { $requestUri = $this->server->get('REQUEST_URI'); - // HTTP proxy reqs setup request URI with scheme and host [and port] + the URL path, only use URL path - $schemeAndHttpHost = $this->getSchemeAndHttpHost(); - if (0 === strpos($requestUri, $schemeAndHttpHost)) { - $requestUri = substr($requestUri, strlen($schemeAndHttpHost)); + + if ('' !== $requestUri && '/' === $requestUri[0]) { + // To only use path and query remove the fragment. + if (false !== $pos = strpos($requestUri, '#')) { + $requestUri = substr($requestUri, 0, $pos); + } + } else { + // HTTP proxy reqs setup request URI with scheme and host [and port] + the URL path, + // only use URL path. + $uriComponents = parse_url($requestUri); + + if (isset($uriComponents['path'])) { + $requestUri = $uriComponents['path']; + } + + if (isset($uriComponents['query'])) { + $requestUri .= '?'.$uriComponents['query']; + } } } elseif ($this->server->has('ORIG_PATH_INFO')) { // IIS 5.0, PHP as CGI @@ -1887,7 +1780,7 @@ class Request $segs = explode('/', trim($file, '/')); $segs = array_reverse($segs); $index = 0; - $last = count($segs); + $last = \count($segs); $baseUrl = ''; do { $seg = $segs[$index]; @@ -1907,9 +1800,9 @@ class Request return $prefix; } - if ($baseUrl && false !== $prefix = $this->getUrlencodedPrefix($requestUri, rtrim(dirname($baseUrl), '/'.DIRECTORY_SEPARATOR).'/')) { + if ($baseUrl && false !== $prefix = $this->getUrlencodedPrefix($requestUri, rtrim(\dirname($baseUrl), '/'.\DIRECTORY_SEPARATOR).'/')) { // directory portion of $baseUrl matches - return rtrim($prefix, '/'.DIRECTORY_SEPARATOR); + return rtrim($prefix, '/'.\DIRECTORY_SEPARATOR); } $truncatedRequestUri = $requestUri; @@ -1926,11 +1819,11 @@ class Request // If using mod_rewrite or ISAPI_Rewrite strip the script filename // out of baseUrl. $pos !== 0 makes sure it is not matching a value // from PATH_INFO or QUERY_STRING - if (strlen($requestUri) >= strlen($baseUrl) && (false !== $pos = strpos($requestUri, $baseUrl)) && 0 !== $pos) { - $baseUrl = substr($requestUri, 0, $pos + strlen($baseUrl)); + if (\strlen($requestUri) >= \strlen($baseUrl) && (false !== $pos = strpos($requestUri, $baseUrl)) && 0 !== $pos) { + $baseUrl = substr($requestUri, 0, $pos + \strlen($baseUrl)); } - return rtrim($baseUrl, '/'.DIRECTORY_SEPARATOR); + return rtrim($baseUrl, '/'.\DIRECTORY_SEPARATOR); } /** @@ -1947,12 +1840,12 @@ class Request $filename = basename($this->server->get('SCRIPT_FILENAME')); if (basename($baseUrl) === $filename) { - $basePath = dirname($baseUrl); + $basePath = \dirname($baseUrl); } else { $basePath = $baseUrl; } - if ('\\' === DIRECTORY_SEPARATOR) { + if ('\\' === \DIRECTORY_SEPARATOR) { $basePath = str_replace('\\', '/', $basePath); } @@ -1982,7 +1875,7 @@ class Request return $requestUri; } - $pathInfo = substr($requestUri, strlen($baseUrl)); + $pathInfo = substr($requestUri, \strlen($baseUrl)); if (false === $pathInfo || '' === $pathInfo) { // If substr() returns false then PATH_INFO is set to an empty string return '/'; @@ -1996,27 +1889,22 @@ class Request */ protected static function initializeFormats() { - static::$formats = array( - 'html' => array('text/html', 'application/xhtml+xml'), - 'txt' => array('text/plain'), - 'js' => array('application/javascript', 'application/x-javascript', 'text/javascript'), - 'css' => array('text/css'), - 'json' => array('application/json', 'application/x-json'), - 'jsonld' => array('application/ld+json'), - 'xml' => array('text/xml', 'application/xml', 'application/x-xml'), - 'rdf' => array('application/rdf+xml'), - 'atom' => array('application/atom+xml'), - 'rss' => array('application/rss+xml'), - 'form' => array('application/x-www-form-urlencoded'), - ); + static::$formats = [ + 'html' => ['text/html', 'application/xhtml+xml'], + 'txt' => ['text/plain'], + 'js' => ['application/javascript', 'application/x-javascript', 'text/javascript'], + 'css' => ['text/css'], + 'json' => ['application/json', 'application/x-json'], + 'jsonld' => ['application/ld+json'], + 'xml' => ['text/xml', 'application/xml', 'application/x-xml'], + 'rdf' => ['application/rdf+xml'], + 'atom' => ['application/atom+xml'], + 'rss' => ['application/rss+xml'], + 'form' => ['application/x-www-form-urlencoded'], + ]; } - /** - * Sets the default PHP locale. - * - * @param string $locale - */ - private function setPhpDefaultLocale($locale) + private function setPhpDefaultLocale(string $locale) { // if either the class Locale doesn't exist, or an exception is thrown when // setting the default locale, the intl module is not installed, and @@ -2029,22 +1917,19 @@ class Request } } - /* + /** * Returns the prefix as encoded in the string when the string starts with * the given prefix, false otherwise. * - * @param string $string The urlencoded string - * @param string $prefix The prefix not encoded - * * @return string|false The prefix as it is encoded in $string, or false */ - private function getUrlencodedPrefix($string, $prefix) + private function getUrlencodedPrefix(string $string, string $prefix) { if (0 !== strpos(rawurldecode($string), $prefix)) { return false; } - $len = strlen($prefix); + $len = \strlen($prefix); if (preg_match(sprintf('#^(%%[[:xdigit:]]{2}|.){%d}#', $len), $string, $match)) { return $match[0]; @@ -2053,10 +1938,10 @@ class Request return false; } - private static function createRequestFromFactory(array $query = array(), array $request = array(), array $attributes = array(), array $cookies = array(), array $files = array(), array $server = array(), $content = null) + private static function createRequestFromFactory(array $query = [], array $request = [], array $attributes = [], array $cookies = [], array $files = [], array $server = [], $content = null) { if (self::$requestFactory) { - $request = call_user_func(self::$requestFactory, $query, $request, $attributes, $cookies, $files, $server, $content); + $request = (self::$requestFactory)($query, $request, $attributes, $cookies, $files, $server, $content); if (!$request instanceof self) { throw new \LogicException('The Request factory must return an instance of Symfony\Component\HttpFoundation\Request.'); @@ -2083,18 +1968,32 @@ class Request private function getTrustedValues($type, $ip = null) { - $clientValues = array(); - $forwardedValues = array(); + $clientValues = []; + $forwardedValues = []; - if (self::$trustedHeaders[$type] && $this->headers->has(self::$trustedHeaders[$type])) { + if ((self::$trustedHeaderSet & $type) && $this->headers->has(self::$trustedHeaders[$type])) { foreach (explode(',', $this->headers->get(self::$trustedHeaders[$type])) as $v) { - $clientValues[] = (self::HEADER_CLIENT_PORT === $type ? '0.0.0.0:' : '').trim($v); + $clientValues[] = (self::HEADER_X_FORWARDED_PORT === $type ? '0.0.0.0:' : '').trim($v); } } - if (self::$trustedHeaders[self::HEADER_FORWARDED] && $this->headers->has(self::$trustedHeaders[self::HEADER_FORWARDED])) { - $forwardedValues = $this->headers->get(self::$trustedHeaders[self::HEADER_FORWARDED]); - $forwardedValues = preg_match_all(sprintf('{(?:%s)=(?:"?\[?)([a-zA-Z0-9\.:_\-/]*+)}', self::$forwardedParams[$type]), $forwardedValues, $matches) ? $matches[1] : array(); + if ((self::$trustedHeaderSet & self::HEADER_FORWARDED) && $this->headers->has(self::$trustedHeaders[self::HEADER_FORWARDED])) { + $forwarded = $this->headers->get(self::$trustedHeaders[self::HEADER_FORWARDED]); + $parts = HeaderUtils::split($forwarded, ',;='); + $forwardedValues = []; + $param = self::$forwardedParams[$type]; + foreach ($parts as $subParts) { + if (null === $v = HeaderUtils::combine($subParts)[$param] ?? null) { + continue; + } + if (self::HEADER_X_FORWARDED_PORT === $type) { + if (']' === substr($v, -1) || false === $v = strrchr($v, ':')) { + $v = $this->isSecure() ? ':443' : ':80'; + } + $v = '0.0.0.0'.$v; + } + $forwardedValues[] = $v; + } } if (null !== $ip) { @@ -2111,7 +2010,7 @@ class Request } if (!$this->isForwardedValid) { - return null !== $ip ? array('0.0.0.0', $ip) : array(); + return null !== $ip ? ['0.0.0.0', $ip] : []; } $this->isForwardedValid = false; @@ -2121,15 +2020,23 @@ class Request private function normalizeAndFilterClientIps(array $clientIps, $ip) { if (!$clientIps) { - return array(); + return []; } $clientIps[] = $ip; // Complete the IP chain with the IP the request actually came from $firstTrustedIp = null; foreach ($clientIps as $key => $clientIp) { - // Remove port (unfortunately, it does happen) - if (preg_match('{((?:\d+\.){3}\d+)\:\d+}', $clientIp, $match)) { - $clientIps[$key] = $clientIp = $match[1]; + if (strpos($clientIp, '.')) { + // Strip :port from IPv4 addresses. This is allowed in Forwarded + // and may occur in X-Forwarded-For. + $i = strpos($clientIp, ':'); + if ($i) { + $clientIps[$key] = $clientIp = substr($clientIp, 0, $i); + } + } elseif (0 === strpos($clientIp, '[')) { + // Strip brackets and :port from IPv6 addresses. + $i = strpos($clientIp, ']', 1); + $clientIps[$key] = $clientIp = substr($clientIp, 1, $i - 1); } if (!filter_var($clientIp, FILTER_VALIDATE_IP)) { @@ -2149,6 +2056,6 @@ class Request } // Now the IP chain contains only untrusted proxies and the client IP - return $clientIps ? array_reverse($clientIps) : array($firstTrustedIp); + return $clientIps ? array_reverse($clientIps) : [$firstTrustedIp]; } } diff --git a/vendor/symfony/http-foundation/RequestMatcher.php b/vendor/symfony/http-foundation/RequestMatcher.php index 076d077c7d0728a399dc8e822d35b83dcb85f931..9a4a2a13761e154d2c1abf2a83293e7cac1b07c9 100644 --- a/vendor/symfony/http-foundation/RequestMatcher.php +++ b/vendor/symfony/http-foundation/RequestMatcher.php @@ -28,41 +28,44 @@ class RequestMatcher implements RequestMatcherInterface */ private $host; + /** + * @var int|null + */ + private $port; + /** * @var string[] */ - private $methods = array(); + private $methods = []; /** * @var string[] */ - private $ips = array(); + private $ips = []; /** * @var array */ - private $attributes = array(); + private $attributes = []; /** * @var string[] */ - private $schemes = array(); + private $schemes = []; /** - * @param string|null $path - * @param string|null $host * @param string|string[]|null $methods * @param string|string[]|null $ips - * @param array $attributes * @param string|string[]|null $schemes */ - public function __construct($path = null, $host = null, $methods = null, $ips = null, array $attributes = array(), $schemes = null) + public function __construct(string $path = null, string $host = null, $methods = null, $ips = null, array $attributes = [], $schemes = null, int $port = null) { $this->matchPath($path); $this->matchHost($host); $this->matchMethod($methods); $this->matchIps($ips); $this->matchScheme($schemes); + $this->matchPort($port); foreach ($attributes as $k => $v) { $this->matchAttribute($k, $v); @@ -76,7 +79,7 @@ class RequestMatcher implements RequestMatcherInterface */ public function matchScheme($scheme) { - $this->schemes = null !== $scheme ? array_map('strtolower', (array) $scheme) : array(); + $this->schemes = null !== $scheme ? array_map('strtolower', (array) $scheme) : []; } /** @@ -89,6 +92,16 @@ class RequestMatcher implements RequestMatcherInterface $this->host = $regexp; } + /** + * Adds a check for the the URL port. + * + * @param int|null $port The port number to connect to + */ + public function matchPort(?int $port) + { + $this->port = $port; + } + /** * Adds a check for the URL path info. * @@ -116,7 +129,7 @@ class RequestMatcher implements RequestMatcherInterface */ public function matchIps($ips) { - $this->ips = null !== $ips ? (array) $ips : array(); + $this->ips = null !== $ips ? (array) $ips : []; } /** @@ -126,7 +139,7 @@ class RequestMatcher implements RequestMatcherInterface */ public function matchMethod($method) { - $this->methods = null !== $method ? array_map('strtoupper', (array) $method) : array(); + $this->methods = null !== $method ? array_map('strtoupper', (array) $method) : []; } /** @@ -145,11 +158,11 @@ class RequestMatcher implements RequestMatcherInterface */ public function matches(Request $request) { - if ($this->schemes && !in_array($request->getScheme(), $this->schemes, true)) { + if ($this->schemes && !\in_array($request->getScheme(), $this->schemes, true)) { return false; } - if ($this->methods && !in_array($request->getMethod(), $this->methods, true)) { + if ($this->methods && !\in_array($request->getMethod(), $this->methods, true)) { return false; } @@ -167,12 +180,16 @@ class RequestMatcher implements RequestMatcherInterface return false; } + if (null !== $this->port && 0 < $this->port && $request->getPort() !== $this->port) { + return false; + } + if (IpUtils::checkIp($request->getClientIp(), $this->ips)) { return true; } // Note to future implementors: add additional checks above the // foreach above or else your check might not be run! - return 0 === count($this->ips); + return 0 === \count($this->ips); } } diff --git a/vendor/symfony/http-foundation/RequestStack.php b/vendor/symfony/http-foundation/RequestStack.php index 3d9cfd0c641944728f0d21dcbbdbe89e5d0a3d85..244a77d631a8f6c8bb504d85f9bb4f7092be3f34 100644 --- a/vendor/symfony/http-foundation/RequestStack.php +++ b/vendor/symfony/http-foundation/RequestStack.php @@ -21,7 +21,7 @@ class RequestStack /** * @var Request[] */ - private $requests = array(); + private $requests = []; /** * Pushes a Request on the stack. @@ -47,7 +47,7 @@ class RequestStack public function pop() { if (!$this->requests) { - return; + return null; } return array_pop($this->requests); @@ -73,7 +73,7 @@ class RequestStack public function getMasterRequest() { if (!$this->requests) { - return; + return null; } return $this->requests[0]; @@ -92,10 +92,10 @@ class RequestStack */ public function getParentRequest() { - $pos = count($this->requests) - 2; + $pos = \count($this->requests) - 2; if (!isset($this->requests[$pos])) { - return; + return null; } return $this->requests[$pos]; diff --git a/vendor/symfony/http-foundation/Response.php b/vendor/symfony/http-foundation/Response.php index cf1325afe0627215e6aea8352c8f57e1690e05f0..1e616453c92db5a149c196d48aaaaf06ce352c62 100644 --- a/vendor/symfony/http-foundation/Response.php +++ b/vendor/symfony/http-foundation/Response.php @@ -21,6 +21,7 @@ class Response const HTTP_CONTINUE = 100; const HTTP_SWITCHING_PROTOCOLS = 101; const HTTP_PROCESSING = 102; // RFC2518 + const HTTP_EARLY_HINTS = 103; // RFC8297 const HTTP_OK = 200; const HTTP_CREATED = 201; const HTTP_ACCEPTED = 202; @@ -63,7 +64,12 @@ class Response const HTTP_UNPROCESSABLE_ENTITY = 422; // RFC4918 const HTTP_LOCKED = 423; // RFC4918 const HTTP_FAILED_DEPENDENCY = 424; // RFC4918 + + /** + * @deprecated + */ const HTTP_RESERVED_FOR_WEBDAV_ADVANCED_COLLECTIONS_EXPIRED_PROPOSAL = 425; // RFC2817 + const HTTP_TOO_EARLY = 425; // RFC-ietf-httpbis-replay-04 const HTTP_UPGRADE_REQUIRED = 426; // RFC2817 const HTTP_PRECONDITION_REQUIRED = 428; // RFC6585 const HTTP_TOO_MANY_REQUESTS = 429; // RFC6585 @@ -82,7 +88,7 @@ class Response const HTTP_NETWORK_AUTHENTICATION_REQUIRED = 511; // RFC6585 /** - * @var \Symfony\Component\HttpFoundation\ResponseHeaderBag + * @var ResponseHeaderBag */ public $headers; @@ -115,14 +121,14 @@ class Response * Status codes translation table. * * The list of codes is complete according to the - * {@link http://www.iana.org/assignments/http-status-codes/ Hypertext Transfer Protocol (HTTP) Status Code Registry} + * {@link https://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml Hypertext Transfer Protocol (HTTP) Status Code Registry} * (last updated 2016-03-01). * * Unless otherwise noted, the status code is defined in RFC2616. * * @var array */ - public static $statusTexts = array( + public static $statusTexts = [ 100 => 'Continue', 101 => 'Switching Protocols', 102 => 'Processing', // RFC2518 @@ -168,7 +174,7 @@ class Response 422 => 'Unprocessable Entity', // RFC4918 423 => 'Locked', // RFC4918 424 => 'Failed Dependency', // RFC4918 - 425 => 'Reserved for WebDAV advanced collections expired proposal', // RFC2817 + 425 => 'Too Early', // RFC-ietf-httpbis-replay-04 426 => 'Upgrade Required', // RFC2817 428 => 'Precondition Required', // RFC6585 429 => 'Too Many Requests', // RFC6585 @@ -185,16 +191,12 @@ class Response 508 => 'Loop Detected', // RFC5842 510 => 'Not Extended', // RFC2774 511 => 'Network Authentication Required', // RFC6585 - ); + ]; /** - * @param mixed $content The response content, see setContent() - * @param int $status The response status code - * @param array $headers An array of response headers - * * @throws \InvalidArgumentException When the HTTP status code is not valid */ - public function __construct($content = '', $status = 200, $headers = array()) + public function __construct($content = '', int $status = 200, array $headers = []) { $this->headers = new ResponseHeaderBag($headers); $this->setContent($content); @@ -216,7 +218,7 @@ class Response * * @return static */ - public static function create($content = '', $status = 200, $headers = array()) + public static function create($content = '', $status = 200, $headers = []) { return new static($content, $status, $headers); } @@ -304,13 +306,19 @@ class Response } // Check if we need to send extra expire info headers - if ('1.0' == $this->getProtocolVersion() && false !== strpos($this->headers->get('Cache-Control'), 'no-cache')) { - $this->headers->set('pragma', 'no-cache'); - $this->headers->set('expires', -1); + if ('1.0' == $this->getProtocolVersion() && false !== strpos($headers->get('Cache-Control'), 'no-cache')) { + $headers->set('pragma', 'no-cache'); + $headers->set('expires', -1); } $this->ensureIEOverSSLCompatibility($request); + if ($request->isSecure()) { + foreach ($headers->getCookies() as $cookie) { + $cookie->setSecureDefault(true); + } + } + return $this; } @@ -328,23 +336,20 @@ class Response // headers foreach ($this->headers->allPreserveCaseWithoutCookies() as $name => $values) { + $replace = 0 === strcasecmp($name, 'Content-Type'); foreach ($values as $value) { - header($name.': '.$value, false, $this->statusCode); + header($name.': '.$value, $replace, $this->statusCode); } } - // status - header(sprintf('HTTP/%s %s %s', $this->version, $this->statusCode, $this->statusText), true, $this->statusCode); - // cookies foreach ($this->headers->getCookies() as $cookie) { - if ($cookie->isRaw()) { - setrawcookie($cookie->getName(), $cookie->getValue(), $cookie->getExpiresTime(), $cookie->getPath(), $cookie->getDomain(), $cookie->isSecure(), $cookie->isHttpOnly()); - } else { - setcookie($cookie->getName(), $cookie->getValue(), $cookie->getExpiresTime(), $cookie->getPath(), $cookie->getDomain(), $cookie->isSecure(), $cookie->isHttpOnly()); - } + header('Set-Cookie: '.$cookie, false, $this->statusCode); } + // status + header(sprintf('HTTP/%s %s %s', $this->version, $this->statusCode, $this->statusText), true, $this->statusCode); + return $this; } @@ -370,9 +375,9 @@ class Response $this->sendHeaders(); $this->sendContent(); - if (function_exists('fastcgi_finish_request')) { + if (\function_exists('fastcgi_finish_request')) { fastcgi_finish_request(); - } elseif ('cli' !== PHP_SAPI) { + } elseif (!\in_array(\PHP_SAPI, ['cli', 'phpdbg'], true)) { static::closeOutputBuffers(0, true); } @@ -392,8 +397,8 @@ class Response */ public function setContent($content) { - if (null !== $content && !is_string($content) && !is_numeric($content) && !is_callable(array($content, '__toString'))) { - throw new \UnexpectedValueException(sprintf('The Response content must be a string or object implementing __toString(), "%s" given.', gettype($content))); + if (null !== $content && !\is_string($content) && !is_numeric($content) && !\is_callable([$content, '__toString'])) { + throw new \UnexpectedValueException(sprintf('The Response content must be a string or object implementing __toString(), "%s" given.', \gettype($content))); } $this->content = (string) $content; @@ -404,7 +409,7 @@ class Response /** * Gets the current response content. * - * @return string Content + * @return string|false */ public function getContent() { @@ -414,13 +419,11 @@ class Response /** * Sets the HTTP protocol version (1.0 or 1.1). * - * @param string $version The HTTP protocol version - * * @return $this * - * @final since version 3.2 + * @final */ - public function setProtocolVersion($version) + public function setProtocolVersion(string $version) { $this->version = $version; @@ -430,11 +433,9 @@ class Response /** * Gets the HTTP protocol version. * - * @return string The HTTP protocol version - * - * @final since version 3.2 + * @final */ - public function getProtocolVersion() + public function getProtocolVersion(): string { return $this->version; } @@ -445,18 +446,15 @@ class Response * If the status text is null it will be automatically populated for the known * status codes and left empty otherwise. * - * @param int $code HTTP status code - * @param mixed $text HTTP status text - * * @return $this * * @throws \InvalidArgumentException When the HTTP status code is not valid * - * @final since version 3.2 + * @final */ - public function setStatusCode($code, $text = null) + public function setStatusCode(int $code, $text = null) { - $this->statusCode = $code = (int) $code; + $this->statusCode = $code; if ($this->isInvalid()) { throw new \InvalidArgumentException(sprintf('The HTTP status code "%s" is not valid.', $code)); } @@ -481,11 +479,9 @@ class Response /** * Retrieves the status code for the current web response. * - * @return int Status code - * - * @final since version 3.2 + * @final */ - public function getStatusCode() + public function getStatusCode(): int { return $this->statusCode; } @@ -493,13 +489,11 @@ class Response /** * Sets the response charset. * - * @param string $charset Character set - * * @return $this * - * @final since version 3.2 + * @final */ - public function setCharset($charset) + public function setCharset(string $charset) { $this->charset = $charset; @@ -509,31 +503,33 @@ class Response /** * Retrieves the response charset. * - * @return string Character set - * - * @final since version 3.2 + * @final */ - public function getCharset() + public function getCharset(): ?string { return $this->charset; } /** - * Returns true if the response is worth caching under any circumstance. + * Returns true if the response may safely be kept in a shared (surrogate) cache. * * Responses marked "private" with an explicit Cache-Control directive are * considered uncacheable. * * Responses with neither a freshness lifetime (Expires, max-age) nor cache - * validator (Last-Modified, ETag) are considered uncacheable. + * validator (Last-Modified, ETag) are considered uncacheable because there is + * no way to tell when or how to remove them from the cache. * - * @return bool true if the response is worth caching, false otherwise + * Note that RFC 7231 and RFC 7234 possibly allow for a more permissive implementation, + * for example "status codes that are defined as cacheable by default [...] + * can be reused by a cache with heuristic expiration unless otherwise indicated" + * (https://tools.ietf.org/html/rfc7231#section-6.1) * - * @final since version 3.3 + * @final */ - public function isCacheable() + public function isCacheable(): bool { - if (!in_array($this->statusCode, array(200, 203, 300, 301, 302, 404, 410))) { + if (!\in_array($this->statusCode, [200, 203, 300, 301, 302, 404, 410])) { return false; } @@ -551,11 +547,9 @@ class Response * origin. A response is considered fresh when it includes a Cache-Control/max-age * indicator or Expires header and the calculated age is less than the freshness lifetime. * - * @return bool true if the response is fresh, false otherwise - * - * @final since version 3.3 + * @final */ - public function isFresh() + public function isFresh(): bool { return $this->getTtl() > 0; } @@ -564,11 +558,9 @@ class Response * Returns true if the response includes headers that can be used to validate * the response with the origin server using a conditional GET request. * - * @return bool true if the response is validateable, false otherwise - * - * @final since version 3.3 + * @final */ - public function isValidateable() + public function isValidateable(): bool { return $this->headers->has('Last-Modified') || $this->headers->has('ETag'); } @@ -580,7 +572,7 @@ class Response * * @return $this * - * @final since version 3.2 + * @final */ public function setPrivate() { @@ -597,7 +589,7 @@ class Response * * @return $this * - * @final since version 3.2 + * @final */ public function setPublic() { @@ -610,13 +602,11 @@ class Response /** * Marks the response as "immutable". * - * @param bool $immutable enables or disables the immutable directive - * * @return $this * * @final */ - public function setImmutable($immutable = true) + public function setImmutable(bool $immutable = true) { if ($immutable) { $this->headers->addCacheControlDirective('immutable'); @@ -630,11 +620,9 @@ class Response /** * Returns true if the response is marked as "immutable". * - * @return bool returns true if the response is marked as "immutable"; otherwise false - * * @final */ - public function isImmutable() + public function isImmutable(): bool { return $this->headers->hasCacheControlDirective('immutable'); } @@ -647,11 +635,9 @@ class Response * When present, the TTL of the response should not be overridden to be * greater than the value provided by the origin. * - * @return bool true if the response must be revalidated by a cache, false otherwise - * - * @final since version 3.3 + * @final */ - public function mustRevalidate() + public function mustRevalidate(): bool { return $this->headers->hasCacheControlDirective('must-revalidate') || $this->headers->hasCacheControlDirective('proxy-revalidate'); } @@ -659,13 +645,11 @@ class Response /** * Returns the Date header as a DateTime instance. * - * @return \DateTime A \DateTime instance - * * @throws \RuntimeException When the header is not parseable * - * @final since version 3.2 + * @final */ - public function getDate() + public function getDate(): ?\DateTimeInterface { return $this->headers->getDate('Date'); } @@ -675,30 +659,32 @@ class Response * * @return $this * - * @final since version 3.2 + * @final */ - public function setDate(\DateTime $date) + public function setDate(\DateTimeInterface $date) { - $date->setTimezone(new \DateTimeZone('UTC')); + if ($date instanceof \DateTime) { + $date = \DateTimeImmutable::createFromMutable($date); + } + + $date = $date->setTimezone(new \DateTimeZone('UTC')); $this->headers->set('Date', $date->format('D, d M Y H:i:s').' GMT'); return $this; } /** - * Returns the age of the response. + * Returns the age of the response in seconds. * - * @return int The age of the response in seconds - * - * @final since version 3.2 + * @final */ - public function getAge() + public function getAge(): int { if (null !== $age = $this->headers->get('Age')) { return (int) $age; } - return max(time() - $this->getDate()->format('U'), 0); + return max(time() - (int) $this->getDate()->format('U'), 0); } /** @@ -710,6 +696,7 @@ class Response { if ($this->isFresh()) { $this->headers->set('Age', $this->getMaxAge()); + $this->headers->remove('Expires'); } return $this; @@ -718,17 +705,15 @@ class Response /** * Returns the value of the Expires header as a DateTime instance. * - * @return \DateTime|null A DateTime instance or null if the header does not exist - * - * @final since version 3.2 + * @final */ - public function getExpires() + public function getExpires(): ?\DateTimeInterface { try { return $this->headers->getDate('Expires'); } catch (\RuntimeException $e) { // according to RFC 2616 invalid date formats (e.g. "0" and "-1") must be treated as in the past - return \DateTime::createFromFormat(DATE_RFC2822, 'Sat, 01 Jan 00 00:00:00 +0000'); + return \DateTime::createFromFormat('U', time() - 172800); } } @@ -737,22 +722,25 @@ class Response * * Passing null as value will remove the header. * - * @param \DateTime|null $date A \DateTime instance or null to remove the header - * * @return $this * - * @final since version 3.2 + * @final */ - public function setExpires(\DateTime $date = null) + public function setExpires(\DateTimeInterface $date = null) { if (null === $date) { $this->headers->remove('Expires'); - } else { - $date = clone $date; - $date->setTimezone(new \DateTimeZone('UTC')); - $this->headers->set('Expires', $date->format('D, d M Y H:i:s').' GMT'); + + return $this; + } + + if ($date instanceof \DateTime) { + $date = \DateTimeImmutable::createFromMutable($date); } + $date = $date->setTimezone(new \DateTimeZone('UTC')); + $this->headers->set('Expires', $date->format('D, d M Y H:i:s').' GMT'); + return $this; } @@ -763,11 +751,9 @@ class Response * First, it checks for a s-maxage directive, then a max-age directive, and then it falls * back on an expires header. It returns null when no maximum age can be established. * - * @return int|null Number of seconds - * - * @final since version 3.2 + * @final */ - public function getMaxAge() + public function getMaxAge(): ?int { if ($this->headers->hasCacheControlDirective('s-maxage')) { return (int) $this->headers->getCacheControlDirective('s-maxage'); @@ -778,8 +764,10 @@ class Response } if (null !== $this->getExpires()) { - return $this->getExpires()->format('U') - $this->getDate()->format('U'); + return (int) $this->getExpires()->format('U') - (int) $this->getDate()->format('U'); } + + return null; } /** @@ -787,13 +775,11 @@ class Response * * This methods sets the Cache-Control max-age directive. * - * @param int $value Number of seconds - * * @return $this * - * @final since version 3.2 + * @final */ - public function setMaxAge($value) + public function setMaxAge(int $value) { $this->headers->addCacheControlDirective('max-age', $value); @@ -805,13 +791,11 @@ class Response * * This methods sets the Cache-Control s-maxage directive. * - * @param int $value Number of seconds - * * @return $this * - * @final since version 3.2 + * @final */ - public function setSharedMaxAge($value) + public function setSharedMaxAge(int $value) { $this->setPublic(); $this->headers->addCacheControlDirective('s-maxage', $value); @@ -827,29 +811,25 @@ class Response * When the responses TTL is <= 0, the response may not be served from cache without first * revalidating with the origin. * - * @return int|null The TTL in seconds - * - * @final since version 3.2 + * @final */ - public function getTtl() + public function getTtl(): ?int { - if (null !== $maxAge = $this->getMaxAge()) { - return $maxAge - $this->getAge(); - } + $maxAge = $this->getMaxAge(); + + return null !== $maxAge ? $maxAge - $this->getAge() : null; } /** - * Sets the response's time-to-live for shared caches. + * Sets the response's time-to-live for shared caches in seconds. * * This method adjusts the Cache-Control/s-maxage directive. * - * @param int $seconds Number of seconds - * * @return $this * - * @final since version 3.2 + * @final */ - public function setTtl($seconds) + public function setTtl(int $seconds) { $this->setSharedMaxAge($this->getAge() + $seconds); @@ -857,17 +837,15 @@ class Response } /** - * Sets the response's time-to-live for private/client caches. + * Sets the response's time-to-live for private/client caches in seconds. * * This method adjusts the Cache-Control/max-age directive. * - * @param int $seconds Number of seconds - * * @return $this * - * @final since version 3.2 + * @final */ - public function setClientTtl($seconds) + public function setClientTtl(int $seconds) { $this->setMaxAge($this->getAge() + $seconds); @@ -877,13 +855,11 @@ class Response /** * Returns the Last-Modified HTTP header as a DateTime instance. * - * @return \DateTime|null A DateTime instance or null if the header does not exist - * * @throws \RuntimeException When the HTTP header is not parseable * - * @final since version 3.2 + * @final */ - public function getLastModified() + public function getLastModified(): ?\DateTimeInterface { return $this->headers->getDate('Last-Modified'); } @@ -893,33 +869,34 @@ class Response * * Passing null as value will remove the header. * - * @param \DateTime|null $date A \DateTime instance or null to remove the header - * * @return $this * - * @final since version 3.2 + * @final */ - public function setLastModified(\DateTime $date = null) + public function setLastModified(\DateTimeInterface $date = null) { if (null === $date) { $this->headers->remove('Last-Modified'); - } else { - $date = clone $date; - $date->setTimezone(new \DateTimeZone('UTC')); - $this->headers->set('Last-Modified', $date->format('D, d M Y H:i:s').' GMT'); + + return $this; } + if ($date instanceof \DateTime) { + $date = \DateTimeImmutable::createFromMutable($date); + } + + $date = $date->setTimezone(new \DateTimeZone('UTC')); + $this->headers->set('Last-Modified', $date->format('D, d M Y H:i:s').' GMT'); + return $this; } /** * Returns the literal value of the ETag HTTP header. * - * @return string|null The ETag HTTP header or null if it does not exist - * - * @final since version 3.2 + * @final */ - public function getEtag() + public function getEtag(): ?string { return $this->headers->get('ETag'); } @@ -932,9 +909,9 @@ class Response * * @return $this * - * @final since version 3.2 + * @final */ - public function setEtag($etag = null, $weak = false) + public function setEtag(string $etag = null, bool $weak = false) { if (null === $etag) { $this->headers->remove('Etag'); @@ -954,18 +931,16 @@ class Response * * Available options are: etag, last_modified, max_age, s_maxage, private, public and immutable. * - * @param array $options An array of cache options - * * @return $this * * @throws \InvalidArgumentException * - * @final since version 3.3 + * @final */ public function setCache(array $options) { - if ($diff = array_diff(array_keys($options), array('etag', 'last_modified', 'max_age', 's_maxage', 'private', 'public', 'immutable'))) { - throw new \InvalidArgumentException(sprintf('Response does not support the following options: "%s".', implode('", "', array_values($diff)))); + if ($diff = array_diff(array_keys($options), ['etag', 'last_modified', 'max_age', 's_maxage', 'private', 'public', 'immutable'])) { + throw new \InvalidArgumentException(sprintf('Response does not support the following options: "%s".', implode('", "', $diff))); } if (isset($options['etag'])) { @@ -1015,9 +990,9 @@ class Response * * @return $this * - * @see http://tools.ietf.org/html/rfc2616#section-10.3.5 + * @see https://tools.ietf.org/html/rfc2616#section-10.3.5 * - * @final since version 3.3 + * @final */ public function setNotModified() { @@ -1025,7 +1000,7 @@ class Response $this->setContent(null); // remove headers that MUST NOT be included with 304 Not Modified responses - foreach (array('Allow', 'Content-Encoding', 'Content-Language', 'Content-Length', 'Content-MD5', 'Content-Type', 'Last-Modified') as $header) { + foreach (['Allow', 'Content-Encoding', 'Content-Language', 'Content-Length', 'Content-MD5', 'Content-Type', 'Last-Modified'] as $header) { $this->headers->remove($header); } @@ -1035,11 +1010,9 @@ class Response /** * Returns true if the response includes a Vary header. * - * @return bool true if the response includes a Vary header, false otherwise - * - * @final since version 3.2 + * @final */ - public function hasVary() + public function hasVary(): bool { return null !== $this->headers->get('Vary'); } @@ -1047,17 +1020,15 @@ class Response /** * Returns an array of header names given in the Vary header. * - * @return array An array of Vary names - * - * @final since version 3.2 + * @final */ - public function getVary() + public function getVary(): array { if (!$vary = $this->headers->get('Vary', null, false)) { - return array(); + return []; } - $ret = array(); + $ret = []; foreach ($vary as $item) { $ret = array_merge($ret, preg_split('/[\s,]+/', $item)); } @@ -1073,9 +1044,9 @@ class Response * * @return $this * - * @final since version 3.2 + * @final */ - public function setVary($headers, $replace = true) + public function setVary($headers, bool $replace = true) { $this->headers->set('Vary', $headers, $replace); @@ -1091,9 +1062,9 @@ class Response * * @return bool true if the Response validators match the Request, false otherwise * - * @final since version 3.3 + * @final */ - public function isNotModified(Request $request) + public function isNotModified(Request $request): bool { if (!$request->isMethodCacheable()) { return false; @@ -1104,7 +1075,7 @@ class Response $modifiedSince = $request->headers->get('If-Modified-Since'); if ($etags = $request->getETags()) { - $notModified = in_array($this->getEtag(), $etags) || in_array('*', $etags); + $notModified = \in_array($this->getEtag(), $etags) || \in_array('*', $etags); } if ($modifiedSince && $lastModified) { @@ -1121,13 +1092,11 @@ class Response /** * Is response invalid? * - * @return bool + * @see https://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html * - * @see http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html - * - * @final since version 3.2 + * @final */ - public function isInvalid() + public function isInvalid(): bool { return $this->statusCode < 100 || $this->statusCode >= 600; } @@ -1135,11 +1104,9 @@ class Response /** * Is response informative? * - * @return bool - * - * @final since version 3.3 + * @final */ - public function isInformational() + public function isInformational(): bool { return $this->statusCode >= 100 && $this->statusCode < 200; } @@ -1147,11 +1114,9 @@ class Response /** * Is response successful? * - * @return bool - * - * @final since version 3.2 + * @final */ - public function isSuccessful() + public function isSuccessful(): bool { return $this->statusCode >= 200 && $this->statusCode < 300; } @@ -1159,11 +1124,9 @@ class Response /** * Is the response a redirect? * - * @return bool - * - * @final since version 3.2 + * @final */ - public function isRedirection() + public function isRedirection(): bool { return $this->statusCode >= 300 && $this->statusCode < 400; } @@ -1171,11 +1134,9 @@ class Response /** * Is there a client error? * - * @return bool - * - * @final since version 3.2 + * @final */ - public function isClientError() + public function isClientError(): bool { return $this->statusCode >= 400 && $this->statusCode < 500; } @@ -1183,11 +1144,9 @@ class Response /** * Was there a server side error? * - * @return bool - * - * @final since version 3.3 + * @final */ - public function isServerError() + public function isServerError(): bool { return $this->statusCode >= 500 && $this->statusCode < 600; } @@ -1195,11 +1154,9 @@ class Response /** * Is the response OK? * - * @return bool - * - * @final since version 3.2 + * @final */ - public function isOk() + public function isOk(): bool { return 200 === $this->statusCode; } @@ -1207,11 +1164,9 @@ class Response /** * Is the response forbidden? * - * @return bool - * - * @final since version 3.2 + * @final */ - public function isForbidden() + public function isForbidden(): bool { return 403 === $this->statusCode; } @@ -1219,11 +1174,9 @@ class Response /** * Is the response a not found error? * - * @return bool - * - * @final since version 3.2 + * @final */ - public function isNotFound() + public function isNotFound(): bool { return 404 === $this->statusCode; } @@ -1231,27 +1184,21 @@ class Response /** * Is the response a redirect of some form? * - * @param string $location - * - * @return bool - * - * @final since version 3.2 + * @final */ - public function isRedirect($location = null) + public function isRedirect(string $location = null): bool { - return in_array($this->statusCode, array(201, 301, 302, 303, 307, 308)) && (null === $location ?: $location == $this->headers->get('Location')); + return \in_array($this->statusCode, [201, 301, 302, 303, 307, 308]) && (null === $location ?: $location == $this->headers->get('Location')); } /** * Is the response empty? * - * @return bool - * - * @final since version 3.2 + * @final */ - public function isEmpty() + public function isEmpty(): bool { - return in_array($this->statusCode, array(204, 304)); + return \in_array($this->statusCode, [204, 304]); } /** @@ -1259,17 +1206,13 @@ class Response * * Resulting level can be greater than target level if a non-removable buffer has been encountered. * - * @param int $targetLevel The target output buffering level - * @param bool $flush Whether to flush or clean the buffers - * - * @final since version 3.3 + * @final */ - public static function closeOutputBuffers($targetLevel, $flush) + public static function closeOutputBuffers(int $targetLevel, bool $flush) { $status = ob_get_status(true); - $level = count($status); - // PHP_OUTPUT_HANDLER_* are not defined on HHVM 3.3 - $flags = defined('PHP_OUTPUT_HANDLER_REMOVABLE') ? PHP_OUTPUT_HANDLER_REMOVABLE | ($flush ? PHP_OUTPUT_HANDLER_FLUSHABLE : PHP_OUTPUT_HANDLER_CLEANABLE) : -1; + $level = \count($status); + $flags = PHP_OUTPUT_HANDLER_REMOVABLE | ($flush ? PHP_OUTPUT_HANDLER_FLUSHABLE : PHP_OUTPUT_HANDLER_CLEANABLE); while ($level-- > $targetLevel && ($s = $status[$level]) && (!isset($s['del']) ? !isset($s['flags']) || ($s['flags'] & $flags) === $flags : $s['del'])) { if ($flush) { @@ -1285,7 +1228,7 @@ class Response * * @see http://support.microsoft.com/kb/323308 * - * @final since version 3.3 + * @final */ protected function ensureIEOverSSLCompatibility(Request $request) { diff --git a/vendor/symfony/http-foundation/ResponseHeaderBag.php b/vendor/symfony/http-foundation/ResponseHeaderBag.php index 11a859326b047d2cd3ab6401a9fab116b16801a6..cf44d0eceba8e3dddb473de0687bbcedccee8e3d 100644 --- a/vendor/symfony/http-foundation/ResponseHeaderBag.php +++ b/vendor/symfony/http-foundation/ResponseHeaderBag.php @@ -24,11 +24,11 @@ class ResponseHeaderBag extends HeaderBag const DISPOSITION_ATTACHMENT = 'attachment'; const DISPOSITION_INLINE = 'inline'; - protected $computedCacheControl = array(); - protected $cookies = array(); - protected $headerNames = array(); + protected $computedCacheControl = []; + protected $cookies = []; + protected $headerNames = []; - public function __construct(array $headers = array()) + public function __construct(array $headers = []) { parent::__construct($headers); @@ -49,7 +49,7 @@ class ResponseHeaderBag extends HeaderBag */ public function allPreserveCase() { - $headers = array(); + $headers = []; foreach ($this->all() as $name => $value) { $headers[isset($this->headerNames[$name]) ? $this->headerNames[$name] : $name] = $value; } @@ -70,9 +70,9 @@ class ResponseHeaderBag extends HeaderBag /** * {@inheritdoc} */ - public function replace(array $headers = array()) + public function replace(array $headers = []) { - $this->headerNames = array(); + $this->headerNames = []; parent::replace($headers); @@ -107,7 +107,7 @@ class ResponseHeaderBag extends HeaderBag if ('set-cookie' === $uniqueKey) { if ($replace) { - $this->cookies = array(); + $this->cookies = []; } foreach ((array) $values as $cookie) { $this->setCookie(Cookie::fromString($cookie)); @@ -122,9 +122,8 @@ class ResponseHeaderBag extends HeaderBag parent::set($key, $values, $replace); // ensure the cache-control header has sensible defaults - if (\in_array($uniqueKey, array('cache-control', 'etag', 'last-modified', 'expires'), true)) { - $computed = $this->computeCacheControlValue(); - $this->headers['cache-control'] = array($computed); + if (\in_array($uniqueKey, ['cache-control', 'etag', 'last-modified', 'expires'], true) && '' !== $computed = $this->computeCacheControlValue()) { + $this->headers['cache-control'] = [$computed]; $this->headerNames['cache-control'] = 'Cache-Control'; $this->computedCacheControl = $this->parseCacheControl($computed); } @@ -139,7 +138,7 @@ class ResponseHeaderBag extends HeaderBag unset($this->headerNames[$uniqueKey]); if ('set-cookie' === $uniqueKey) { - $this->cookies = array(); + $this->cookies = []; return; } @@ -147,7 +146,7 @@ class ResponseHeaderBag extends HeaderBag parent::remove($key); if ('cache-control' === $uniqueKey) { - $this->computedCacheControl = array(); + $this->computedCacheControl = []; } if ('date' === $uniqueKey) { @@ -160,7 +159,7 @@ class ResponseHeaderBag extends HeaderBag */ public function hasCacheControlDirective($key) { - return array_key_exists($key, $this->computedCacheControl); + return \array_key_exists($key, $this->computedCacheControl); } /** @@ -168,7 +167,7 @@ class ResponseHeaderBag extends HeaderBag */ public function getCacheControlDirective($key) { - return array_key_exists($key, $this->computedCacheControl) ? $this->computedCacheControl[$key] : null; + return \array_key_exists($key, $this->computedCacheControl) ? $this->computedCacheControl[$key] : null; } public function setCookie(Cookie $cookie) @@ -210,21 +209,21 @@ class ResponseHeaderBag extends HeaderBag * * @param string $format * - * @return array + * @return Cookie[] * * @throws \InvalidArgumentException When the $format is invalid */ public function getCookies($format = self::COOKIES_FLAT) { - if (!in_array($format, array(self::COOKIES_FLAT, self::COOKIES_ARRAY))) { - throw new \InvalidArgumentException(sprintf('Format "%s" invalid (%s).', $format, implode(', ', array(self::COOKIES_FLAT, self::COOKIES_ARRAY)))); + if (!\in_array($format, [self::COOKIES_FLAT, self::COOKIES_ARRAY])) { + throw new \InvalidArgumentException(sprintf('Format "%s" invalid (%s).', $format, implode(', ', [self::COOKIES_FLAT, self::COOKIES_ARRAY]))); } if (self::COOKIES_ARRAY === $format) { return $this->cookies; } - $flattenedCookies = array(); + $flattenedCookies = []; foreach ($this->cookies as $path) { foreach ($path as $cookies) { foreach ($cookies as $cookie) { @@ -247,56 +246,15 @@ class ResponseHeaderBag extends HeaderBag */ public function clearCookie($name, $path = '/', $domain = null, $secure = false, $httpOnly = true) { - $this->setCookie(new Cookie($name, null, 1, $path, $domain, $secure, $httpOnly)); + $this->setCookie(new Cookie($name, null, 1, $path, $domain, $secure, $httpOnly, false, null)); } /** - * Generates a HTTP Content-Disposition field-value. - * - * @param string $disposition One of "inline" or "attachment" - * @param string $filename A unicode string - * @param string $filenameFallback A string containing only ASCII characters that - * is semantically equivalent to $filename. If the filename is already ASCII, - * it can be omitted, or just copied from $filename - * - * @return string A string suitable for use as a Content-Disposition field-value - * - * @throws \InvalidArgumentException - * - * @see RFC 6266 + * @see HeaderUtils::makeDisposition() */ public function makeDisposition($disposition, $filename, $filenameFallback = '') { - if (!in_array($disposition, array(self::DISPOSITION_ATTACHMENT, self::DISPOSITION_INLINE))) { - throw new \InvalidArgumentException(sprintf('The disposition must be either "%s" or "%s".', self::DISPOSITION_ATTACHMENT, self::DISPOSITION_INLINE)); - } - - if ('' == $filenameFallback) { - $filenameFallback = $filename; - } - - // filenameFallback is not ASCII. - if (!preg_match('/^[\x20-\x7e]*$/', $filenameFallback)) { - throw new \InvalidArgumentException('The filename fallback must only contain ASCII characters.'); - } - - // percent characters aren't safe in fallback. - if (false !== strpos($filenameFallback, '%')) { - throw new \InvalidArgumentException('The filename fallback cannot contain the "%" character.'); - } - - // path separators aren't allowed in either. - if (false !== strpos($filename, '/') || false !== strpos($filename, '\\') || false !== strpos($filenameFallback, '/') || false !== strpos($filenameFallback, '\\')) { - throw new \InvalidArgumentException('The filename and the fallback cannot contain the "/" and "\\" characters.'); - } - - $output = sprintf('%s; filename="%s"', $disposition, str_replace('"', '\\"', $filenameFallback)); - - if ($filename !== $filenameFallback) { - $output .= sprintf("; filename*=utf-8''%s", rawurlencode($filename)); - } - - return $output; + return HeaderUtils::makeDisposition((string) $disposition, (string) $filename, (string) $filenameFallback); } /** diff --git a/vendor/symfony/http-foundation/ServerBag.php b/vendor/symfony/http-foundation/ServerBag.php index 19d2022ef7ddb4ccb91651a34547bf20458830cb..4c82b1774873ff32a3a5274a920f17857e44aa06 100644 --- a/vendor/symfony/http-foundation/ServerBag.php +++ b/vendor/symfony/http-foundation/ServerBag.php @@ -27,8 +27,8 @@ class ServerBag extends ParameterBag */ public function getHeaders() { - $headers = array(); - $contentHeaders = array('CONTENT_LENGTH' => true, 'CONTENT_MD5' => true, 'CONTENT_TYPE' => true); + $headers = []; + $contentHeaders = ['CONTENT_LENGTH' => true, 'CONTENT_MD5' => true, 'CONTENT_TYPE' => true]; foreach ($this->parameters as $key => $value) { if (0 === strpos($key, 'HTTP_')) { $headers[substr($key, 5)] = $value; @@ -68,7 +68,7 @@ class ServerBag extends ParameterBag if (0 === stripos($authorizationHeader, 'basic ')) { // Decode AUTHORIZATION header into PHP_AUTH_USER and PHP_AUTH_PW when authorization header is basic $exploded = explode(':', base64_decode(substr($authorizationHeader, 6)), 2); - if (2 == count($exploded)) { + if (2 == \count($exploded)) { list($headers['PHP_AUTH_USER'], $headers['PHP_AUTH_PW']) = $exploded; } } elseif (empty($this->parameters['PHP_AUTH_DIGEST']) && (0 === stripos($authorizationHeader, 'digest '))) { @@ -79,7 +79,7 @@ class ServerBag extends ParameterBag /* * XXX: Since there is no PHP_AUTH_BEARER in PHP predefined variables, * I'll just set $headers['AUTHORIZATION'] here. - * http://php.net/manual/en/reserved.variables.server.php + * https://php.net/reserved.variables.server */ $headers['AUTHORIZATION'] = $authorizationHeader; } diff --git a/vendor/symfony/http-foundation/Session/Attribute/AttributeBag.php b/vendor/symfony/http-foundation/Session/Attribute/AttributeBag.php index ea1fda290fdfe94d2d16006ef3d31f56f5b60805..ee33698cf0842aa2fb21d538c0f6e6bf6bf6035f 100644 --- a/vendor/symfony/http-foundation/Session/Attribute/AttributeBag.php +++ b/vendor/symfony/http-foundation/Session/Attribute/AttributeBag.php @@ -19,12 +19,12 @@ class AttributeBag implements AttributeBagInterface, \IteratorAggregate, \Counta private $name = 'attributes'; private $storageKey; - protected $attributes = array(); + protected $attributes = []; /** * @param string $storageKey The key used to store attributes in the session */ - public function __construct($storageKey = '_sf2_attributes') + public function __construct(string $storageKey = '_sf2_attributes') { $this->storageKey = $storageKey; } @@ -63,7 +63,7 @@ class AttributeBag implements AttributeBagInterface, \IteratorAggregate, \Counta */ public function has($name) { - return array_key_exists($name, $this->attributes); + return \array_key_exists($name, $this->attributes); } /** @@ -71,7 +71,7 @@ class AttributeBag implements AttributeBagInterface, \IteratorAggregate, \Counta */ public function get($name, $default = null) { - return array_key_exists($name, $this->attributes) ? $this->attributes[$name] : $default; + return \array_key_exists($name, $this->attributes) ? $this->attributes[$name] : $default; } /** @@ -95,7 +95,7 @@ class AttributeBag implements AttributeBagInterface, \IteratorAggregate, \Counta */ public function replace(array $attributes) { - $this->attributes = array(); + $this->attributes = []; foreach ($attributes as $key => $value) { $this->set($key, $value); } @@ -107,7 +107,7 @@ class AttributeBag implements AttributeBagInterface, \IteratorAggregate, \Counta public function remove($name) { $retval = null; - if (array_key_exists($name, $this->attributes)) { + if (\array_key_exists($name, $this->attributes)) { $retval = $this->attributes[$name]; unset($this->attributes[$name]); } @@ -121,7 +121,7 @@ class AttributeBag implements AttributeBagInterface, \IteratorAggregate, \Counta public function clear() { $return = $this->attributes; - $this->attributes = array(); + $this->attributes = []; return $return; } @@ -143,6 +143,6 @@ class AttributeBag implements AttributeBagInterface, \IteratorAggregate, \Counta */ public function count() { - return count($this->attributes); + return \count($this->attributes); } } diff --git a/vendor/symfony/http-foundation/Session/Attribute/NamespacedAttributeBag.php b/vendor/symfony/http-foundation/Session/Attribute/NamespacedAttributeBag.php index abbf37ee7c33cf4be0a671ecf17c134a5bbdac55..2cf0743cf9d5e54845ae3e38e83cd4ba1ab0f32d 100644 --- a/vendor/symfony/http-foundation/Session/Attribute/NamespacedAttributeBag.php +++ b/vendor/symfony/http-foundation/Session/Attribute/NamespacedAttributeBag.php @@ -25,7 +25,7 @@ class NamespacedAttributeBag extends AttributeBag * @param string $storageKey Session storage key * @param string $namespaceCharacter Namespace character to use in keys */ - public function __construct($storageKey = '_sf2_attributes', $namespaceCharacter = '/') + public function __construct(string $storageKey = '_sf2_attributes', string $namespaceCharacter = '/') { $this->namespaceCharacter = $namespaceCharacter; parent::__construct($storageKey); @@ -44,7 +44,7 @@ class NamespacedAttributeBag extends AttributeBag return false; } - return array_key_exists($name, $attributes); + return \array_key_exists($name, $attributes); } /** @@ -60,7 +60,7 @@ class NamespacedAttributeBag extends AttributeBag return $default; } - return array_key_exists($name, $attributes) ? $attributes[$name] : $default; + return \array_key_exists($name, $attributes) ? $attributes[$name] : $default; } /** @@ -81,7 +81,7 @@ class NamespacedAttributeBag extends AttributeBag $retval = null; $attributes = &$this->resolveAttributePath($name); $name = $this->resolveKey($name); - if (null !== $attributes && array_key_exists($name, $attributes)) { + if (null !== $attributes && \array_key_exists($name, $attributes)) { $retval = $attributes[$name]; unset($attributes[$name]); } @@ -97,7 +97,7 @@ class NamespacedAttributeBag extends AttributeBag * @param string $name Key name * @param bool $writeContext Write context, default false * - * @return array + * @return array|null */ protected function &resolveAttributePath($name, $writeContext = false) { @@ -110,21 +110,27 @@ class NamespacedAttributeBag extends AttributeBag } $parts = explode($this->namespaceCharacter, $name); - if (count($parts) < 2) { + if (\count($parts) < 2) { if (!$writeContext) { return $array; } - $array[$parts[0]] = array(); + $array[$parts[0]] = []; return $array; } - unset($parts[count($parts) - 1]); + unset($parts[\count($parts) - 1]); foreach ($parts as $part) { - if (null !== $array && !array_key_exists($part, $array)) { - $array[$part] = $writeContext ? array() : null; + if (null !== $array && !\array_key_exists($part, $array)) { + if (!$writeContext) { + $null = null; + + return $null; + } + + $array[$part] = []; } $array = &$array[$part]; diff --git a/vendor/symfony/http-foundation/Session/Flash/AutoExpireFlashBag.php b/vendor/symfony/http-foundation/Session/Flash/AutoExpireFlashBag.php index 77521c24789c681def801d829b4315354b585b97..6502f3d50155f8280d9f488db9eaa6a4326b7efb 100644 --- a/vendor/symfony/http-foundation/Session/Flash/AutoExpireFlashBag.php +++ b/vendor/symfony/http-foundation/Session/Flash/AutoExpireFlashBag.php @@ -19,13 +19,13 @@ namespace Symfony\Component\HttpFoundation\Session\Flash; class AutoExpireFlashBag implements FlashBagInterface { private $name = 'flashes'; - private $flashes = array('display' => array(), 'new' => array()); + private $flashes = ['display' => [], 'new' => []]; private $storageKey; /** * @param string $storageKey The key used to store flashes in the session */ - public function __construct($storageKey = '_symfony_flashes') + public function __construct(string $storageKey = '_symfony_flashes') { $this->storageKey = $storageKey; } @@ -53,8 +53,8 @@ class AutoExpireFlashBag implements FlashBagInterface // The logic: messages from the last request will be stored in new, so we move them to previous // This request we will show what is in 'display'. What is placed into 'new' this time round will // be moved to display next time round. - $this->flashes['display'] = array_key_exists('new', $this->flashes) ? $this->flashes['new'] : array(); - $this->flashes['new'] = array(); + $this->flashes['display'] = \array_key_exists('new', $this->flashes) ? $this->flashes['new'] : []; + $this->flashes['new'] = []; } /** @@ -68,7 +68,7 @@ class AutoExpireFlashBag implements FlashBagInterface /** * {@inheritdoc} */ - public function peek($type, array $default = array()) + public function peek($type, array $default = []) { return $this->has($type) ? $this->flashes['display'][$type] : $default; } @@ -78,13 +78,13 @@ class AutoExpireFlashBag implements FlashBagInterface */ public function peekAll() { - return array_key_exists('display', $this->flashes) ? (array) $this->flashes['display'] : array(); + return \array_key_exists('display', $this->flashes) ? (array) $this->flashes['display'] : []; } /** * {@inheritdoc} */ - public function get($type, array $default = array()) + public function get($type, array $default = []) { $return = $default; @@ -106,7 +106,7 @@ class AutoExpireFlashBag implements FlashBagInterface public function all() { $return = $this->flashes['display']; - $this->flashes['display'] = array(); + $this->flashes['display'] = []; return $return; } @@ -132,7 +132,7 @@ class AutoExpireFlashBag implements FlashBagInterface */ public function has($type) { - return array_key_exists($type, $this->flashes['display']) && $this->flashes['display'][$type]; + return \array_key_exists($type, $this->flashes['display']) && $this->flashes['display'][$type]; } /** diff --git a/vendor/symfony/http-foundation/Session/Flash/FlashBag.php b/vendor/symfony/http-foundation/Session/Flash/FlashBag.php index 12fb740c5220c4c7b9908ff445a5283d0d5b6aae..c6b7ce354cec478124b9be7b6b10a9e3d87d72c9 100644 --- a/vendor/symfony/http-foundation/Session/Flash/FlashBag.php +++ b/vendor/symfony/http-foundation/Session/Flash/FlashBag.php @@ -19,13 +19,13 @@ namespace Symfony\Component\HttpFoundation\Session\Flash; class FlashBag implements FlashBagInterface { private $name = 'flashes'; - private $flashes = array(); + private $flashes = []; private $storageKey; /** * @param string $storageKey The key used to store flashes in the session */ - public function __construct($storageKey = '_symfony_flashes') + public function __construct(string $storageKey = '_symfony_flashes') { $this->storageKey = $storageKey; } @@ -62,7 +62,7 @@ class FlashBag implements FlashBagInterface /** * {@inheritdoc} */ - public function peek($type, array $default = array()) + public function peek($type, array $default = []) { return $this->has($type) ? $this->flashes[$type] : $default; } @@ -78,7 +78,7 @@ class FlashBag implements FlashBagInterface /** * {@inheritdoc} */ - public function get($type, array $default = array()) + public function get($type, array $default = []) { if (!$this->has($type)) { return $default; @@ -97,7 +97,7 @@ class FlashBag implements FlashBagInterface public function all() { $return = $this->peekAll(); - $this->flashes = array(); + $this->flashes = []; return $return; } @@ -123,7 +123,7 @@ class FlashBag implements FlashBagInterface */ public function has($type) { - return array_key_exists($type, $this->flashes) && $this->flashes[$type]; + return \array_key_exists($type, $this->flashes) && $this->flashes[$type]; } /** diff --git a/vendor/symfony/http-foundation/Session/Flash/FlashBagInterface.php b/vendor/symfony/http-foundation/Session/Flash/FlashBagInterface.php index 80e97f17cdff35d292b1c13109bc5018ad736203..99e8074214b622dfdd618f912b8c56031703cf0d 100644 --- a/vendor/symfony/http-foundation/Session/Flash/FlashBagInterface.php +++ b/vendor/symfony/http-foundation/Session/Flash/FlashBagInterface.php @@ -21,20 +21,20 @@ use Symfony\Component\HttpFoundation\Session\SessionBagInterface; interface FlashBagInterface extends SessionBagInterface { /** - * Adds a flash message for type. + * Adds a flash message for the given type. * * @param string $type - * @param string $message + * @param mixed $message */ public function add($type, $message); /** - * Registers a message for a given type. + * Registers one or more messages for a given type. * * @param string $type - * @param string|array $message + * @param string|array $messages */ - public function set($type, $message); + public function set($type, $messages); /** * Gets flash messages for a given type. @@ -44,7 +44,7 @@ interface FlashBagInterface extends SessionBagInterface * * @return array */ - public function peek($type, array $default = array()); + public function peek($type, array $default = []); /** * Gets all flash messages. @@ -61,7 +61,7 @@ interface FlashBagInterface extends SessionBagInterface * * @return array */ - public function get($type, array $default = array()); + public function get($type, array $default = []); /** * Gets and clears flashes from the stack. diff --git a/vendor/symfony/http-foundation/Session/Session.php b/vendor/symfony/http-foundation/Session/Session.php index a46cffbb8dbd6d03fa24b929f8c41c0a9b992f0f..db0b9aeb0b1186323cffb7a46ae04d9c887788ff 100644 --- a/vendor/symfony/http-foundation/Session/Session.php +++ b/vendor/symfony/http-foundation/Session/Session.php @@ -11,12 +11,12 @@ namespace Symfony\Component\HttpFoundation\Session; -use Symfony\Component\HttpFoundation\Session\Storage\SessionStorageInterface; use Symfony\Component\HttpFoundation\Session\Attribute\AttributeBag; use Symfony\Component\HttpFoundation\Session\Attribute\AttributeBagInterface; use Symfony\Component\HttpFoundation\Session\Flash\FlashBag; use Symfony\Component\HttpFoundation\Session\Flash\FlashBagInterface; use Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage; +use Symfony\Component\HttpFoundation\Session\Storage\SessionStorageInterface; /** * @author Fabien Potencier <fabien@symfony.com> @@ -28,8 +28,8 @@ class Session implements SessionInterface, \IteratorAggregate, \Countable private $flashName; private $attributeName; - private $data = array(); - private $hasBeenStarted; + private $data = []; + private $usageIndex = 0; /** * @param SessionStorageInterface $storage A SessionStorageInterface instance @@ -138,17 +138,17 @@ class Session implements SessionInterface, \IteratorAggregate, \Countable */ public function count() { - return count($this->getAttributeBag()->all()); + return \count($this->getAttributeBag()->all()); } /** - * @return bool + * @return int * * @internal */ - public function hasBeenStarted() + public function getUsageIndex() { - return $this->hasBeenStarted; + return $this->usageIndex; } /** @@ -158,6 +158,9 @@ class Session implements SessionInterface, \IteratorAggregate, \Countable */ public function isEmpty() { + if ($this->isStarted()) { + ++$this->usageIndex; + } foreach ($this->data as &$data) { if (!empty($data)) { return false; @@ -206,7 +209,9 @@ class Session implements SessionInterface, \IteratorAggregate, \Countable */ public function setId($id) { - $this->storage->setId($id); + if ($this->storage->getId() !== $id) { + $this->storage->setId($id); + } } /** @@ -230,6 +235,8 @@ class Session implements SessionInterface, \IteratorAggregate, \Countable */ public function getMetadataBag() { + ++$this->usageIndex; + return $this->storage->getMetadataBag(); } @@ -238,7 +245,7 @@ class Session implements SessionInterface, \IteratorAggregate, \Countable */ public function registerBag(SessionBagInterface $bag) { - $this->storage->registerBag(new SessionBagProxy($bag, $this->data, $this->hasBeenStarted)); + $this->storage->registerBag(new SessionBagProxy($bag, $this->data, $this->usageIndex)); } /** @@ -246,7 +253,9 @@ class Session implements SessionInterface, \IteratorAggregate, \Countable */ public function getBag($name) { - return $this->storage->getBag($name)->getBag(); + $bag = $this->storage->getBag($name); + + return method_exists($bag, 'getBag') ? $bag->getBag() : $bag; } /** diff --git a/vendor/symfony/http-foundation/Session/SessionBagProxy.php b/vendor/symfony/http-foundation/Session/SessionBagProxy.php index 307836d5f94616e22404631fea345f02a64fcb8c..3504bdfe7b4a6fe1c52c0bf8e628ec703857445a 100644 --- a/vendor/symfony/http-foundation/Session/SessionBagProxy.php +++ b/vendor/symfony/http-foundation/Session/SessionBagProxy.php @@ -20,13 +20,13 @@ final class SessionBagProxy implements SessionBagInterface { private $bag; private $data; - private $hasBeenStarted; + private $usageIndex; - public function __construct(SessionBagInterface $bag, array &$data, &$hasBeenStarted) + public function __construct(SessionBagInterface $bag, array &$data, &$usageIndex) { $this->bag = $bag; $this->data = &$data; - $this->hasBeenStarted = &$hasBeenStarted; + $this->usageIndex = &$usageIndex; } /** @@ -34,6 +34,8 @@ final class SessionBagProxy implements SessionBagInterface */ public function getBag() { + ++$this->usageIndex; + return $this->bag; } @@ -42,6 +44,11 @@ final class SessionBagProxy implements SessionBagInterface */ public function isEmpty() { + if (!isset($this->data[$this->bag->getStorageKey()])) { + return true; + } + ++$this->usageIndex; + return empty($this->data[$this->bag->getStorageKey()]); } @@ -58,7 +65,7 @@ final class SessionBagProxy implements SessionBagInterface */ public function initialize(array &$array) { - $this->hasBeenStarted = true; + ++$this->usageIndex; $this->data[$this->bag->getStorageKey()] = &$array; $this->bag->initialize($array); diff --git a/vendor/symfony/http-foundation/Session/SessionUtils.php b/vendor/symfony/http-foundation/Session/SessionUtils.php new file mode 100644 index 0000000000000000000000000000000000000000..b5bce4a884eff6afb2b1b180b2708e589d8f9b7d --- /dev/null +++ b/vendor/symfony/http-foundation/Session/SessionUtils.php @@ -0,0 +1,59 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\Session; + +/** + * Session utility functions. + * + * @author Nicolas Grekas <p@tchwork.com> + * @author Rémon van de Kamp <rpkamp@gmail.com> + * + * @internal + */ +final class SessionUtils +{ + /** + * Finds the session header amongst the headers that are to be sent, removes it, and returns + * it so the caller can process it further. + */ + public static function popSessionCookie(string $sessionName, string $sessionId): ?string + { + $sessionCookie = null; + $sessionCookiePrefix = sprintf(' %s=', urlencode($sessionName)); + $sessionCookieWithId = sprintf('%s%s;', $sessionCookiePrefix, urlencode($sessionId)); + $otherCookies = []; + foreach (headers_list() as $h) { + if (0 !== stripos($h, 'Set-Cookie:')) { + continue; + } + if (11 === strpos($h, $sessionCookiePrefix, 11)) { + $sessionCookie = $h; + + if (11 !== strpos($h, $sessionCookieWithId, 11)) { + $otherCookies[] = $h; + } + } else { + $otherCookies[] = $h; + } + } + if (null === $sessionCookie) { + return null; + } + + header_remove('Set-Cookie'); + foreach ($otherCookies as $h) { + header($h, false); + } + + return $sessionCookie; + } +} diff --git a/vendor/symfony/http-foundation/Session/Storage/Handler/AbstractSessionHandler.php b/vendor/symfony/http-foundation/Session/Storage/Handler/AbstractSessionHandler.php index 6ae1355816fdbb2d9fa45aaf7681b291b1b3ddd5..78340efbd2228f97221dc283f04903ae7af8c89e 100644 --- a/vendor/symfony/http-foundation/Session/Storage/Handler/AbstractSessionHandler.php +++ b/vendor/symfony/http-foundation/Session/Storage/Handler/AbstractSessionHandler.php @@ -11,6 +11,8 @@ namespace Symfony\Component\HttpFoundation\Session\Storage\Handler; +use Symfony\Component\HttpFoundation\Session\SessionUtils; + /** * This abstract session handler provides a generic implementation * of the PHP 7.0 SessionUpdateTimestampHandlerInterface, @@ -91,9 +93,6 @@ abstract class AbstractSessionHandler implements \SessionHandlerInterface, \Sess $data = $this->doRead($sessionId); $this->newSessionId = '' === $data ? $sessionId : null; - if (\PHP_VERSION_ID < 70000) { - $this->prefetchData = $data; - } return $data; } @@ -103,17 +102,9 @@ abstract class AbstractSessionHandler implements \SessionHandlerInterface, \Sess */ public function write($sessionId, $data) { - if (\PHP_VERSION_ID < 70000 && $this->prefetchData) { - $readData = $this->prefetchData; - $this->prefetchData = null; - - if ($readData === $data) { - return $this->updateTimestamp($sessionId, $data); - } - } if (null === $this->igbinaryEmptyData) { // see https://github.com/igbinary/igbinary/issues/146 - $this->igbinaryEmptyData = \function_exists('igbinary_serialize') ? igbinary_serialize(array()) : ''; + $this->igbinaryEmptyData = \function_exists('igbinary_serialize') ? igbinary_serialize([]) : ''; } if ('' === $data || $this->igbinaryEmptyData === $data) { return $this->destroy($sessionId); @@ -128,38 +119,27 @@ abstract class AbstractSessionHandler implements \SessionHandlerInterface, \Sess */ public function destroy($sessionId) { - if (\PHP_VERSION_ID < 70000) { - $this->prefetchData = null; - } - if (!headers_sent() && ini_get('session.use_cookies')) { + if (!headers_sent() && filter_var(ini_get('session.use_cookies'), FILTER_VALIDATE_BOOLEAN)) { if (!$this->sessionName) { - throw new \LogicException(sprintf('Session name cannot be empty, did you forget to call "parent::open()" in "%s"?.', get_class($this))); + throw new \LogicException(sprintf('Session name cannot be empty, did you forget to call "parent::open()" in "%s"?.', \get_class($this))); } - $sessionCookie = sprintf(' %s=', urlencode($this->sessionName)); - $sessionCookieWithId = sprintf('%s%s;', $sessionCookie, urlencode($sessionId)); - $sessionCookieFound = false; - $otherCookies = array(); - foreach (headers_list() as $h) { - if (0 !== stripos($h, 'Set-Cookie:')) { - continue; - } - if (11 === strpos($h, $sessionCookie, 11)) { - $sessionCookieFound = true; - - if (11 !== strpos($h, $sessionCookieWithId, 11)) { - $otherCookies[] = $h; - } + $cookie = SessionUtils::popSessionCookie($this->sessionName, $sessionId); + + /* + * We send an invalidation Set-Cookie header (zero lifetime) + * when either the session was started or a cookie with + * the session name was sent by the client (in which case + * we know it's invalid as a valid session cookie would've + * started the session). + */ + if (null === $cookie || isset($_COOKIE[$this->sessionName])) { + if (\PHP_VERSION_ID < 70300) { + setcookie($this->sessionName, '', 0, ini_get('session.cookie_path'), ini_get('session.cookie_domain'), filter_var(ini_get('session.cookie_secure'), FILTER_VALIDATE_BOOLEAN), filter_var(ini_get('session.cookie_httponly'), FILTER_VALIDATE_BOOLEAN)); } else { - $otherCookies[] = $h; - } - } - if ($sessionCookieFound) { - header_remove('Set-Cookie'); - foreach ($otherCookies as $h) { - header($h, false); + $params = session_get_cookie_params(); + unset($params['lifetime']); + setcookie($this->sessionName, '', $params); } - } else { - setcookie($this->sessionName, '', 0, ini_get('session.cookie_path'), ini_get('session.cookie_domain'), ini_get('session.cookie_secure'), ini_get('session.cookie_httponly')); } } diff --git a/vendor/symfony/http-foundation/Session/Storage/Handler/MemcacheSessionHandler.php b/vendor/symfony/http-foundation/Session/Storage/Handler/MemcacheSessionHandler.php deleted file mode 100644 index 90726beb04efe668a3017281e28323f457c246ea..0000000000000000000000000000000000000000 --- a/vendor/symfony/http-foundation/Session/Storage/Handler/MemcacheSessionHandler.php +++ /dev/null @@ -1,120 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session\Storage\Handler; - -@trigger_error(sprintf('The class %s is deprecated since Symfony 3.4 and will be removed in 4.0. Use Symfony\Component\HttpFoundation\Session\Storage\Handler\MemcachedSessionHandler instead.', MemcacheSessionHandler::class), E_USER_DEPRECATED); - -/** - * @author Drak <drak@zikula.org> - * - * @deprecated since version 3.4, to be removed in 4.0. Use Symfony\Component\HttpFoundation\Session\Storage\Handler\MemcachedSessionHandler instead. - */ -class MemcacheSessionHandler implements \SessionHandlerInterface -{ - private $memcache; - - /** - * @var int Time to live in seconds - */ - private $ttl; - - /** - * @var string Key prefix for shared environments - */ - private $prefix; - - /** - * Constructor. - * - * List of available options: - * * prefix: The prefix to use for the memcache keys in order to avoid collision - * * expiretime: The time to live in seconds - * - * @param \Memcache $memcache A \Memcache instance - * @param array $options An associative array of Memcache options - * - * @throws \InvalidArgumentException When unsupported options are passed - */ - public function __construct(\Memcache $memcache, array $options = array()) - { - if ($diff = array_diff(array_keys($options), array('prefix', 'expiretime'))) { - throw new \InvalidArgumentException(sprintf( - 'The following options are not supported "%s"', implode(', ', $diff) - )); - } - - $this->memcache = $memcache; - $this->ttl = isset($options['expiretime']) ? (int) $options['expiretime'] : 86400; - $this->prefix = isset($options['prefix']) ? $options['prefix'] : 'sf2s'; - } - - /** - * {@inheritdoc} - */ - public function open($savePath, $sessionName) - { - return true; - } - - /** - * {@inheritdoc} - */ - public function close() - { - return true; - } - - /** - * {@inheritdoc} - */ - public function read($sessionId) - { - return $this->memcache->get($this->prefix.$sessionId) ?: ''; - } - - /** - * {@inheritdoc} - */ - public function write($sessionId, $data) - { - return $this->memcache->set($this->prefix.$sessionId, $data, 0, time() + $this->ttl); - } - - /** - * {@inheritdoc} - */ - public function destroy($sessionId) - { - $this->memcache->delete($this->prefix.$sessionId); - - return true; - } - - /** - * {@inheritdoc} - */ - public function gc($maxlifetime) - { - // not required here because memcache will auto expire the records anyhow. - return true; - } - - /** - * Return a Memcache instance. - * - * @return \Memcache - */ - protected function getMemcache() - { - return $this->memcache; - } -} diff --git a/vendor/symfony/http-foundation/Session/Storage/Handler/MemcachedSessionHandler.php b/vendor/symfony/http-foundation/Session/Storage/Handler/MemcachedSessionHandler.php index 9f4ef7028edbe265f720a36231476a4d87d9006d..a399be5fd8ee7d62463dcf613a153bca764e93c3 100644 --- a/vendor/symfony/http-foundation/Session/Storage/Handler/MemcachedSessionHandler.php +++ b/vendor/symfony/http-foundation/Session/Storage/Handler/MemcachedSessionHandler.php @@ -15,7 +15,7 @@ namespace Symfony\Component\HttpFoundation\Session\Storage\Handler; * Memcached based session storage handler based on the Memcached class * provided by the PHP memcached extension. * - * @see http://php.net/memcached + * @see https://php.net/memcached * * @author Drak <drak@zikula.org> */ @@ -40,19 +40,14 @@ class MemcachedSessionHandler extends AbstractSessionHandler * * prefix: The prefix to use for the memcached keys in order to avoid collision * * expiretime: The time to live in seconds. * - * @param \Memcached $memcached A \Memcached instance - * @param array $options An associative array of Memcached options - * * @throws \InvalidArgumentException When unsupported options are passed */ - public function __construct(\Memcached $memcached, array $options = array()) + public function __construct(\Memcached $memcached, array $options = []) { $this->memcached = $memcached; - if ($diff = array_diff(array_keys($options), array('prefix', 'expiretime'))) { - throw new \InvalidArgumentException(sprintf( - 'The following options are not supported "%s"', implode(', ', $diff) - )); + if ($diff = array_diff(array_keys($options), ['prefix', 'expiretime'])) { + throw new \InvalidArgumentException(sprintf('The following options are not supported "%s"', implode(', ', $diff))); } $this->ttl = isset($options['expiretime']) ? (int) $options['expiretime'] : 86400; @@ -60,11 +55,11 @@ class MemcachedSessionHandler extends AbstractSessionHandler } /** - * {@inheritdoc} + * @return bool */ public function close() { - return true; + return $this->memcached->quit(); } /** @@ -76,11 +71,13 @@ class MemcachedSessionHandler extends AbstractSessionHandler } /** - * {@inheritdoc} + * @return bool */ public function updateTimestamp($sessionId, $data) { - return $this->memcached->touch($this->prefix.$sessionId, time() + $this->ttl); + $this->memcached->touch($this->prefix.$sessionId, time() + $this->ttl); + + return true; } /** @@ -102,7 +99,7 @@ class MemcachedSessionHandler extends AbstractSessionHandler } /** - * {@inheritdoc} + * @return bool */ public function gc($maxlifetime) { diff --git a/vendor/symfony/http-foundation/Session/Storage/Handler/MigratingSessionHandler.php b/vendor/symfony/http-foundation/Session/Storage/Handler/MigratingSessionHandler.php new file mode 100644 index 0000000000000000000000000000000000000000..253d8cb68509842b6b95ae48e7f0d02d393212b9 --- /dev/null +++ b/vendor/symfony/http-foundation/Session/Storage/Handler/MigratingSessionHandler.php @@ -0,0 +1,124 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\Session\Storage\Handler; + +/** + * Migrating session handler for migrating from one handler to another. It reads + * from the current handler and writes both the current and new ones. + * + * It ignores errors from the new handler. + * + * @author Ross Motley <ross.motley@amara.com> + * @author Oliver Radwell <oliver.radwell@amara.com> + */ +class MigratingSessionHandler implements \SessionHandlerInterface, \SessionUpdateTimestampHandlerInterface +{ + private $currentHandler; + private $writeOnlyHandler; + + public function __construct(\SessionHandlerInterface $currentHandler, \SessionHandlerInterface $writeOnlyHandler) + { + if (!$currentHandler instanceof \SessionUpdateTimestampHandlerInterface) { + $currentHandler = new StrictSessionHandler($currentHandler); + } + if (!$writeOnlyHandler instanceof \SessionUpdateTimestampHandlerInterface) { + $writeOnlyHandler = new StrictSessionHandler($writeOnlyHandler); + } + + $this->currentHandler = $currentHandler; + $this->writeOnlyHandler = $writeOnlyHandler; + } + + /** + * {@inheritdoc} + */ + public function close() + { + $result = $this->currentHandler->close(); + $this->writeOnlyHandler->close(); + + return $result; + } + + /** + * {@inheritdoc} + */ + public function destroy($sessionId) + { + $result = $this->currentHandler->destroy($sessionId); + $this->writeOnlyHandler->destroy($sessionId); + + return $result; + } + + /** + * @return bool + */ + public function gc($maxlifetime) + { + $result = $this->currentHandler->gc($maxlifetime); + $this->writeOnlyHandler->gc($maxlifetime); + + return $result; + } + + /** + * {@inheritdoc} + */ + public function open($savePath, $sessionName) + { + $result = $this->currentHandler->open($savePath, $sessionName); + $this->writeOnlyHandler->open($savePath, $sessionName); + + return $result; + } + + /** + * {@inheritdoc} + */ + public function read($sessionId) + { + // No reading from new handler until switch-over + return $this->currentHandler->read($sessionId); + } + + /** + * {@inheritdoc} + */ + public function write($sessionId, $sessionData) + { + $result = $this->currentHandler->write($sessionId, $sessionData); + $this->writeOnlyHandler->write($sessionId, $sessionData); + + return $result; + } + + /** + * {@inheritdoc} + */ + public function validateId($sessionId) + { + // No reading from new handler until switch-over + return $this->currentHandler->validateId($sessionId); + } + + /** + * {@inheritdoc} + */ + public function updateTimestamp($sessionId, $sessionData) + { + $result = $this->currentHandler->updateTimestamp($sessionId, $sessionData); + $this->writeOnlyHandler->updateTimestamp($sessionId, $sessionData); + + return $result; + } +} diff --git a/vendor/symfony/http-foundation/Session/Storage/Handler/MongoDbSessionHandler.php b/vendor/symfony/http-foundation/Session/Storage/Handler/MongoDbSessionHandler.php index 7d3fa218a269d62fef8b23cad74b672b63fe2e35..db85f06e3ed07fe0fbaaf9b7843d538196dbbd64 100644 --- a/vendor/symfony/http-foundation/Session/Storage/Handler/MongoDbSessionHandler.php +++ b/vendor/symfony/http-foundation/Session/Storage/Handler/MongoDbSessionHandler.php @@ -17,14 +17,14 @@ namespace Symfony\Component\HttpFoundation\Session\Storage\Handler; * @author Markus Bachmann <markus.bachmann@bachi.biz> * * @see https://packagist.org/packages/mongodb/mongodb - * @see http://php.net/manual/en/set.mongodb.php + * @see https://php.net/mongodb */ class MongoDbSessionHandler extends AbstractSessionHandler { private $mongo; /** - * @var \MongoCollection + * @var \MongoDB\Collection */ private $collection; @@ -56,7 +56,7 @@ class MongoDbSessionHandler extends AbstractSessionHandler * { "expireAfterSeconds": 0 } * ) * - * More details on: http://docs.mongodb.org/manual/tutorial/expire-data/ + * More details on: https://docs.mongodb.org/manual/tutorial/expire-data/ * * If you use such an index, you can drop `gc_probability` to 0 since * no garbage-collection is required. @@ -64,31 +64,22 @@ class MongoDbSessionHandler extends AbstractSessionHandler * @param \MongoDB\Client $mongo A MongoDB\Client instance * @param array $options An associative array of field options * - * @throws \InvalidArgumentException When MongoClient or Mongo instance not provided * @throws \InvalidArgumentException When "database" or "collection" not provided */ - public function __construct($mongo, array $options) + public function __construct(\MongoDB\Client $mongo, array $options) { - if ($mongo instanceof \MongoClient || $mongo instanceof \Mongo) { - @trigger_error(sprintf('Using %s with the legacy mongo extension is deprecated as of 3.4 and will be removed in 4.0. Use it with the mongodb/mongodb package and ext-mongodb instead.', __CLASS__), E_USER_DEPRECATED); - } - - if (!($mongo instanceof \MongoDB\Client || $mongo instanceof \MongoClient || $mongo instanceof \Mongo)) { - throw new \InvalidArgumentException('MongoClient or Mongo instance required'); - } - if (!isset($options['database']) || !isset($options['collection'])) { throw new \InvalidArgumentException('You must provide the "database" and "collection" option for MongoDBSessionHandler'); } $this->mongo = $mongo; - $this->options = array_merge(array( + $this->options = array_merge([ 'id_field' => '_id', 'data_field' => 'data', 'time_field' => 'time', 'expiry_field' => 'expires_at', - ), $options); + ], $options); } /** @@ -104,11 +95,9 @@ class MongoDbSessionHandler extends AbstractSessionHandler */ protected function doDestroy($sessionId) { - $methodName = $this->mongo instanceof \MongoDB\Client ? 'deleteOne' : 'remove'; - - $this->getCollection()->$methodName(array( + $this->getCollection()->deleteOne([ $this->options['id_field'] => $sessionId, - )); + ]); return true; } @@ -118,11 +107,9 @@ class MongoDbSessionHandler extends AbstractSessionHandler */ public function gc($maxlifetime) { - $methodName = $this->mongo instanceof \MongoDB\Client ? 'deleteMany' : 'remove'; - - $this->getCollection()->$methodName(array( - $this->options['expiry_field'] => array('$lt' => $this->createDateTime()), - )); + $this->getCollection()->deleteMany([ + $this->options['expiry_field'] => ['$lt' => new \MongoDB\BSON\UTCDateTime()], + ]); return true; } @@ -132,28 +119,18 @@ class MongoDbSessionHandler extends AbstractSessionHandler */ protected function doWrite($sessionId, $data) { - $expiry = $this->createDateTime(time() + (int) ini_get('session.gc_maxlifetime')); + $expiry = new \MongoDB\BSON\UTCDateTime((time() + (int) ini_get('session.gc_maxlifetime')) * 1000); - $fields = array( - $this->options['time_field'] => $this->createDateTime(), + $fields = [ + $this->options['time_field'] => new \MongoDB\BSON\UTCDateTime(), $this->options['expiry_field'] => $expiry, - ); + $this->options['data_field'] => new \MongoDB\BSON\Binary($data, \MongoDB\BSON\Binary::TYPE_OLD_BINARY), + ]; - $options = array('upsert' => true); - - if ($this->mongo instanceof \MongoDB\Client) { - $fields[$this->options['data_field']] = new \MongoDB\BSON\Binary($data, \MongoDB\BSON\Binary::TYPE_OLD_BINARY); - } else { - $fields[$this->options['data_field']] = new \MongoBinData($data, \MongoBinData::BYTE_ARRAY); - $options['multiple'] = false; - } - - $methodName = $this->mongo instanceof \MongoDB\Client ? 'updateOne' : 'update'; - - $this->getCollection()->$methodName( - array($this->options['id_field'] => $sessionId), - array('$set' => $fields), - $options + $this->getCollection()->updateOne( + [$this->options['id_field'] => $sessionId], + ['$set' => $fields], + ['upsert' => true] ); return true; @@ -164,23 +141,14 @@ class MongoDbSessionHandler extends AbstractSessionHandler */ public function updateTimestamp($sessionId, $data) { - $expiry = $this->createDateTime(time() + (int) ini_get('session.gc_maxlifetime')); - - if ($this->mongo instanceof \MongoDB\Client) { - $methodName = 'updateOne'; - $options = array(); - } else { - $methodName = 'update'; - $options = array('multiple' => false); - } + $expiry = new \MongoDB\BSON\UTCDateTime((time() + (int) ini_get('session.gc_maxlifetime')) * 1000); - $this->getCollection()->$methodName( - array($this->options['id_field'] => $sessionId), - array('$set' => array( - $this->options['time_field'] => $this->createDateTime(), + $this->getCollection()->updateOne( + [$this->options['id_field'] => $sessionId], + ['$set' => [ + $this->options['time_field'] => new \MongoDB\BSON\UTCDateTime(), $this->options['expiry_field'] => $expiry, - )), - $options + ]] ); return true; @@ -191,26 +159,20 @@ class MongoDbSessionHandler extends AbstractSessionHandler */ protected function doRead($sessionId) { - $dbData = $this->getCollection()->findOne(array( + $dbData = $this->getCollection()->findOne([ $this->options['id_field'] => $sessionId, - $this->options['expiry_field'] => array('$gte' => $this->createDateTime()), - )); + $this->options['expiry_field'] => ['$gte' => new \MongoDB\BSON\UTCDateTime()], + ]); if (null === $dbData) { return ''; } - if ($dbData[$this->options['data_field']] instanceof \MongoDB\BSON\Binary) { - return $dbData[$this->options['data_field']]->getData(); - } - - return $dbData[$this->options['data_field']]->bin; + return $dbData[$this->options['data_field']]->getData(); } /** - * Return a "MongoCollection" instance. - * - * @return \MongoCollection + * @return \MongoDB\Collection */ private function getCollection() { @@ -222,34 +184,10 @@ class MongoDbSessionHandler extends AbstractSessionHandler } /** - * Return a Mongo instance. - * - * @return \Mongo|\MongoClient|\MongoDB\Client + * @return \MongoDB\Client */ protected function getMongo() { return $this->mongo; } - - /** - * Create a date object using the class appropriate for the current mongo connection. - * - * Return an instance of a MongoDate or \MongoDB\BSON\UTCDateTime - * - * @param int $seconds An integer representing UTC seconds since Jan 1 1970. Defaults to now. - * - * @return \MongoDate|\MongoDB\BSON\UTCDateTime - */ - private function createDateTime($seconds = null) - { - if (null === $seconds) { - $seconds = time(); - } - - if ($this->mongo instanceof \MongoDB\Client) { - return new \MongoDB\BSON\UTCDateTime($seconds * 1000); - } - - return new \MongoDate($seconds); - } } diff --git a/vendor/symfony/http-foundation/Session/Storage/Handler/NativeFileSessionHandler.php b/vendor/symfony/http-foundation/Session/Storage/Handler/NativeFileSessionHandler.php index 4e9704bd5858f38066cf001ae91d88450992040f..bdfc9d819e8128ff404a88f67bdf824bb69260b6 100644 --- a/vendor/symfony/http-foundation/Session/Storage/Handler/NativeFileSessionHandler.php +++ b/vendor/symfony/http-foundation/Session/Storage/Handler/NativeFileSessionHandler.php @@ -16,19 +16,19 @@ namespace Symfony\Component\HttpFoundation\Session\Storage\Handler; * * @author Drak <drak@zikula.org> */ -class NativeFileSessionHandler extends NativeSessionHandler +class NativeFileSessionHandler extends \SessionHandler { /** * @param string $savePath Path of directory to save session files * Default null will leave setting as defined by PHP. * '/path', 'N;/path', or 'N;octal-mode;/path * - * @see http://php.net/session.configuration.php#ini.session.save-path for further details. + * @see https://php.net/session.configuration#ini.session.save-path for further details. * * @throws \InvalidArgumentException On invalid $savePath * @throws \RuntimeException When failing to create the save directory */ - public function __construct($savePath = null) + public function __construct(string $savePath = null) { if (null === $savePath) { $savePath = ini_get('session.save_path'); diff --git a/vendor/symfony/http-foundation/Session/Storage/Handler/NativeSessionHandler.php b/vendor/symfony/http-foundation/Session/Storage/Handler/NativeSessionHandler.php deleted file mode 100644 index 9be4528aeb436567ca1fd5d30c00ba8b8b0af8a7..0000000000000000000000000000000000000000 --- a/vendor/symfony/http-foundation/Session/Storage/Handler/NativeSessionHandler.php +++ /dev/null @@ -1,24 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session\Storage\Handler; - -/** - * @deprecated since version 3.4, to be removed in 4.0. Use \SessionHandler instead. - * @see http://php.net/sessionhandler - */ -class NativeSessionHandler extends \SessionHandler -{ - public function __construct() - { - @trigger_error('The '.__NAMESPACE__.'\NativeSessionHandler class is deprecated since Symfony 3.4 and will be removed in 4.0. Use the \SessionHandler class instead.', E_USER_DEPRECATED); - } -} diff --git a/vendor/symfony/http-foundation/Session/Storage/Handler/NullSessionHandler.php b/vendor/symfony/http-foundation/Session/Storage/Handler/NullSessionHandler.php index 8d193155b090f2d596ce937ec3d3040a86f75733..3ba9378ca7aed3d3bc4db94247c1a848338438b7 100644 --- a/vendor/symfony/http-foundation/Session/Storage/Handler/NullSessionHandler.php +++ b/vendor/symfony/http-foundation/Session/Storage/Handler/NullSessionHandler.php @@ -67,7 +67,7 @@ class NullSessionHandler extends AbstractSessionHandler } /** - * {@inheritdoc} + * @return bool */ public function gc($maxlifetime) { diff --git a/vendor/symfony/http-foundation/Session/Storage/Handler/PdoSessionHandler.php b/vendor/symfony/http-foundation/Session/Storage/Handler/PdoSessionHandler.php index 2e1692b6f0c99443a0cf397a718361c6596a2ee7..4f770c14ed2cc41b79d453749186feed9cee691c 100644 --- a/vendor/symfony/http-foundation/Session/Storage/Handler/PdoSessionHandler.php +++ b/vendor/symfony/http-foundation/Session/Storage/Handler/PdoSessionHandler.php @@ -32,7 +32,7 @@ namespace Symfony\Component\HttpFoundation\Session\Storage\Handler; * Saving it in a character column could corrupt the data. You can use createTable() * to initialize a correctly defined table. * - * @see http://php.net/sessionhandlerinterface + * @see https://php.net/sessionhandlerinterface * * @author Fabien Potencier <fabien@symfony.com> * @author Michael Williams <michael.williams@funsational.com> @@ -71,7 +71,7 @@ class PdoSessionHandler extends AbstractSessionHandler private $pdo; /** - * @var string|null|false DSN string or null for session.save_path or false when lazy connection disabled + * @var string|false|null DSN string or null for session.save_path or false when lazy connection disabled */ private $dsn = false; @@ -118,7 +118,7 @@ class PdoSessionHandler extends AbstractSessionHandler /** * @var array Connection options when lazy-connect */ - private $connectionOptions = array(); + private $connectionOptions = []; /** * @var int The strategy for locking, see constants @@ -130,7 +130,7 @@ class PdoSessionHandler extends AbstractSessionHandler * * @var \PDOStatement[] An array of statements to release advisory locks */ - private $unlockStatements = array(); + private $unlockStatements = []; /** * @var bool True when the current session exists but expired according to session.gc_maxlifetime @@ -161,15 +161,15 @@ class PdoSessionHandler extends AbstractSessionHandler * * db_time_col: The column where to store the timestamp [default: sess_time] * * db_username: The username when lazy-connect [default: ''] * * db_password: The password when lazy-connect [default: ''] - * * db_connection_options: An array of driver-specific connection options [default: array()] + * * db_connection_options: An array of driver-specific connection options [default: []] * * lock_mode: The strategy for locking, see constants [default: LOCK_TRANSACTIONAL] * - * @param \PDO|string|null $pdoOrDsn A \PDO instance or DSN string or null + * @param \PDO|string|null $pdoOrDsn A \PDO instance or DSN string or URL string or null * @param array $options An associative array of options * * @throws \InvalidArgumentException When PDO error mode is not PDO::ERRMODE_EXCEPTION */ - public function __construct($pdoOrDsn = null, array $options = array()) + public function __construct($pdoOrDsn = null, array $options = []) { if ($pdoOrDsn instanceof \PDO) { if (\PDO::ERRMODE_EXCEPTION !== $pdoOrDsn->getAttribute(\PDO::ATTR_ERRMODE)) { @@ -178,6 +178,8 @@ class PdoSessionHandler extends AbstractSessionHandler $this->pdo = $pdoOrDsn; $this->driver = $this->pdo->getAttribute(\PDO::ATTR_DRIVER_NAME); + } elseif (\is_string($pdoOrDsn) && false !== strpos($pdoOrDsn, '://')) { + $this->dsn = $this->buildDsnFromUrl($pdoOrDsn); } else { $this->dsn = $pdoOrDsn; } @@ -284,7 +286,7 @@ class PdoSessionHandler extends AbstractSessionHandler } /** - * {@inheritdoc} + * @return bool */ public function gc($maxlifetime) { @@ -431,6 +433,102 @@ class PdoSessionHandler extends AbstractSessionHandler $this->driver = $this->pdo->getAttribute(\PDO::ATTR_DRIVER_NAME); } + /** + * Builds a PDO DSN from a URL-like connection string. + * + * @param string $dsnOrUrl + * + * @return string + * + * @todo implement missing support for oci DSN (which look totally different from other PDO ones) + */ + private function buildDsnFromUrl($dsnOrUrl) + { + // (pdo_)?sqlite3?:///... => (pdo_)?sqlite3?://localhost/... or else the URL will be invalid + $url = preg_replace('#^((?:pdo_)?sqlite3?):///#', '$1://localhost/', $dsnOrUrl); + + $params = parse_url($url); + + if (false === $params) { + return $dsnOrUrl; // If the URL is not valid, let's assume it might be a DSN already. + } + + $params = array_map('rawurldecode', $params); + + // Override the default username and password. Values passed through options will still win over these in the constructor. + if (isset($params['user'])) { + $this->username = $params['user']; + } + + if (isset($params['pass'])) { + $this->password = $params['pass']; + } + + if (!isset($params['scheme'])) { + throw new \InvalidArgumentException('URLs without scheme are not supported to configure the PdoSessionHandler'); + } + + $driverAliasMap = [ + 'mssql' => 'sqlsrv', + 'mysql2' => 'mysql', // Amazon RDS, for some weird reason + 'postgres' => 'pgsql', + 'postgresql' => 'pgsql', + 'sqlite3' => 'sqlite', + ]; + + $driver = isset($driverAliasMap[$params['scheme']]) ? $driverAliasMap[$params['scheme']] : $params['scheme']; + + // Doctrine DBAL supports passing its internal pdo_* driver names directly too (allowing both dashes and underscores). This allows supporting the same here. + if (0 === strpos($driver, 'pdo_') || 0 === strpos($driver, 'pdo-')) { + $driver = substr($driver, 4); + } + + switch ($driver) { + case 'mysql': + case 'pgsql': + $dsn = $driver.':'; + + if (isset($params['host']) && '' !== $params['host']) { + $dsn .= 'host='.$params['host'].';'; + } + + if (isset($params['port']) && '' !== $params['port']) { + $dsn .= 'port='.$params['port'].';'; + } + + if (isset($params['path'])) { + $dbName = substr($params['path'], 1); // Remove the leading slash + $dsn .= 'dbname='.$dbName.';'; + } + + return $dsn; + + case 'sqlite': + return 'sqlite:'.substr($params['path'], 1); + + case 'sqlsrv': + $dsn = 'sqlsrv:server='; + + if (isset($params['host'])) { + $dsn .= $params['host']; + } + + if (isset($params['port']) && '' !== $params['port']) { + $dsn .= ','.$params['port']; + } + + if (isset($params['path'])) { + $dbName = substr($params['path'], 1); // Remove the leading slash + $dsn .= ';Database='.$dbName; + } + + return $dsn; + + default: + throw new \InvalidArgumentException(sprintf('The scheme "%s" is not supported by the PdoSessionHandler URL configuration. Pass a PDO DSN directly.', $params['scheme'])); + } + } + /** * Helper method to begin a transaction. * @@ -440,7 +538,7 @@ class PdoSessionHandler extends AbstractSessionHandler * PDO::rollback or PDO::inTransaction for SQLite. * * Also MySQLs default isolation, REPEATABLE READ, causes deadlock for different sessions - * due to http://www.mysqlperformanceblog.com/2013/12/12/one-more-innodb-gap-lock-to-avoid/ . + * due to https://percona.com/blog/2013/12/12/one-more-innodb-gap-lock-to-avoid/ . * So we change it to READ COMMITTED. */ private function beginTransaction() @@ -518,6 +616,7 @@ class PdoSessionHandler extends AbstractSessionHandler $selectSql = $this->getSelectSql(); $selectStmt = $this->pdo->prepare($selectSql); $selectStmt->bindParam(':id', $sessionId, \PDO::PARAM_STR); + $insertStmt = null; do { $selectStmt->execute(); @@ -530,10 +629,15 @@ class PdoSessionHandler extends AbstractSessionHandler return ''; } - return is_resource($sessionRows[0][0]) ? stream_get_contents($sessionRows[0][0]) : $sessionRows[0][0]; + return \is_resource($sessionRows[0][0]) ? stream_get_contents($sessionRows[0][0]) : $sessionRows[0][0]; } - if (!ini_get('session.use_strict_mode') && self::LOCK_TRANSACTIONAL === $this->lockMode && 'sqlite' !== $this->driver) { + if (null !== $insertStmt) { + $this->rollback(); + throw new \RuntimeException('Failed to read session: INSERT reported a duplicate id but next SELECT did not return any data.'); + } + + if (!filter_var(ini_get('session.use_strict_mode'), FILTER_VALIDATE_BOOLEAN) && self::LOCK_TRANSACTIONAL === $this->lockMode && 'sqlite' !== $this->driver) { // In strict mode, session fixation is not possible: new sessions always start with a unique // random id, so that concurrency is not possible and this code path can be skipped. // Exclusive-reading of non-existent rows does not block, so we need to do an insert to block @@ -564,8 +668,6 @@ class PdoSessionHandler extends AbstractSessionHandler /** * Executes an application-level lock on the database. * - * @param string $sessionId Session ID - * * @return \PDOStatement The statement that needs to be executed later to release the lock * * @throws \DomainException When an unsupported PDO driver is used @@ -574,18 +676,20 @@ class PdoSessionHandler extends AbstractSessionHandler * - for oci using DBMS_LOCK.REQUEST * - for sqlsrv using sp_getapplock with LockOwner = Session */ - private function doAdvisoryLock($sessionId) + private function doAdvisoryLock(string $sessionId) { switch ($this->driver) { case 'mysql': + // MySQL 5.7.5 and later enforces a maximum length on lock names of 64 characters. Previously, no limit was enforced. + $lockId = substr($sessionId, 0, 64); // should we handle the return value? 0 on timeout, null on error // we use a timeout of 50 seconds which is also the default for innodb_lock_wait_timeout $stmt = $this->pdo->prepare('SELECT GET_LOCK(:key, 50)'); - $stmt->bindValue(':key', $sessionId, \PDO::PARAM_STR); + $stmt->bindValue(':key', $lockId, \PDO::PARAM_STR); $stmt->execute(); $releaseStmt = $this->pdo->prepare('DO RELEASE_LOCK(:key)'); - $releaseStmt->bindValue(':key', $sessionId, \PDO::PARAM_STR); + $releaseStmt->bindValue(':key', $lockId, \PDO::PARAM_STR); return $releaseStmt; case 'pgsql': @@ -627,19 +731,15 @@ class PdoSessionHandler extends AbstractSessionHandler * Encodes the first 4 (when PHP_INT_SIZE == 4) or 8 characters of the string as an integer. * * Keep in mind, PHP integers are signed. - * - * @param string $string - * - * @return int */ - private function convertStringToInt($string) + private function convertStringToInt(string $string): int { if (4 === \PHP_INT_SIZE) { - return (ord($string[3]) << 24) + (ord($string[2]) << 16) + (ord($string[1]) << 8) + ord($string[0]); + return (\ord($string[3]) << 24) + (\ord($string[2]) << 16) + (\ord($string[1]) << 8) + \ord($string[0]); } - $int1 = (ord($string[7]) << 24) + (ord($string[6]) << 16) + (ord($string[5]) << 8) + ord($string[4]); - $int2 = (ord($string[3]) << 24) + (ord($string[2]) << 16) + (ord($string[1]) << 8) + ord($string[0]); + $int1 = (\ord($string[7]) << 24) + (\ord($string[6]) << 16) + (\ord($string[5]) << 8) + \ord($string[4]); + $int2 = (\ord($string[3]) << 24) + (\ord($string[2]) << 16) + (\ord($string[1]) << 8) + \ord($string[0]); return $int2 + ($int1 << 32); } @@ -647,11 +747,9 @@ class PdoSessionHandler extends AbstractSessionHandler /** * Return a locking or nonlocking SQL query to read session information. * - * @return string The SQL string - * * @throws \DomainException When an unsupported PDO driver is used */ - private function getSelectSql() + private function getSelectSql(): string { if (self::LOCK_TRANSACTIONAL === $this->lockMode) { $this->beginTransaction(); @@ -742,14 +840,8 @@ class PdoSessionHandler extends AbstractSessionHandler /** * Returns a merge/upsert (i.e. insert or update) statement when supported by the database for writing session data. - * - * @param string $sessionId Session ID - * @param string $data Encoded session data - * @param int $maxlifetime session.gc_maxlifetime - * - * @return \PDOStatement|null The merge statement or null when not supported */ - private function getMergeStatement($sessionId, $data, $maxlifetime) + private function getMergeStatement(string $sessionId, string $data, int $maxlifetime): ?\PDOStatement { switch (true) { case 'mysql' === $this->driver: @@ -758,7 +850,7 @@ class PdoSessionHandler extends AbstractSessionHandler break; case 'sqlsrv' === $this->driver && version_compare($this->pdo->getAttribute(\PDO::ATTR_SERVER_VERSION), '10', '>='): // MERGE is only available since SQL Server 2008 and must be terminated by semicolon - // It also requires HOLDLOCK according to http://weblogs.sqlteam.com/dang/archive/2009/01/31/UPSERT-Race-Condition-With-MERGE.aspx + // It also requires HOLDLOCK according to https://weblogs.sqlteam.com/dang/2009/01/31/upsert-race-condition-with-merge/ $mergeSql = "MERGE INTO $this->table WITH (HOLDLOCK) USING (SELECT 1 AS dummy) AS src ON ($this->idCol = ?) ". "WHEN NOT MATCHED THEN INSERT ($this->idCol, $this->dataCol, $this->lifetimeCol, $this->timeCol) VALUES (?, ?, ?, ?) ". "WHEN MATCHED THEN UPDATE SET $this->dataCol = ?, $this->lifetimeCol = ?, $this->timeCol = ?;"; @@ -771,7 +863,7 @@ class PdoSessionHandler extends AbstractSessionHandler "ON CONFLICT ($this->idCol) DO UPDATE SET ($this->dataCol, $this->lifetimeCol, $this->timeCol) = (EXCLUDED.$this->dataCol, EXCLUDED.$this->lifetimeCol, EXCLUDED.$this->timeCol)"; break; default: - // MERGE is not supported with LOBs: http://www.oracle.com/technetwork/articles/fuecks-lobs-095315.html + // MERGE is not supported with LOBs: https://oracle.com/technetwork/articles/fuecks-lobs-095315.html return null; } diff --git a/vendor/symfony/http-foundation/Session/Storage/Handler/RedisSessionHandler.php b/vendor/symfony/http-foundation/Session/Storage/Handler/RedisSessionHandler.php new file mode 100644 index 0000000000000000000000000000000000000000..46ca6796d8ebba99e1b1c054701f715ca5711cf9 --- /dev/null +++ b/vendor/symfony/http-foundation/Session/Storage/Handler/RedisSessionHandler.php @@ -0,0 +1,114 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\Session\Storage\Handler; + +use Predis\Response\ErrorInterface; +use Symfony\Component\Cache\Traits\RedisClusterProxy; +use Symfony\Component\Cache\Traits\RedisProxy; + +/** + * Redis based session storage handler based on the Redis class + * provided by the PHP redis extension. + * + * @author Dalibor Karlović <dalibor@flexolabs.io> + */ +class RedisSessionHandler extends AbstractSessionHandler +{ + private $redis; + + /** + * @var string Key prefix for shared environments + */ + private $prefix; + + /** + * List of available options: + * * prefix: The prefix to use for the keys in order to avoid collision on the Redis server. + * + * @param \Redis|\RedisArray|\RedisCluster|\Predis\ClientInterface|RedisProxy $redis + * @param array $options An associative array of options + * + * @throws \InvalidArgumentException When unsupported client or options are passed + */ + public function __construct($redis, array $options = []) + { + if ( + !$redis instanceof \Redis && + !$redis instanceof \RedisArray && + !$redis instanceof \RedisCluster && + !$redis instanceof \Predis\ClientInterface && + !$redis instanceof RedisProxy && + !$redis instanceof RedisClusterProxy + ) { + throw new \InvalidArgumentException(sprintf('%s() expects parameter 1 to be Redis, RedisArray, RedisCluster or Predis\ClientInterface, %s given', __METHOD__, \is_object($redis) ? \get_class($redis) : \gettype($redis))); + } + + if ($diff = array_diff(array_keys($options), ['prefix'])) { + throw new \InvalidArgumentException(sprintf('The following options are not supported "%s"', implode(', ', $diff))); + } + + $this->redis = $redis; + $this->prefix = $options['prefix'] ?? 'sf_s'; + } + + /** + * {@inheritdoc} + */ + protected function doRead($sessionId): string + { + return $this->redis->get($this->prefix.$sessionId) ?: ''; + } + + /** + * {@inheritdoc} + */ + protected function doWrite($sessionId, $data): bool + { + $result = $this->redis->setEx($this->prefix.$sessionId, (int) ini_get('session.gc_maxlifetime'), $data); + + return $result && !$result instanceof ErrorInterface; + } + + /** + * {@inheritdoc} + */ + protected function doDestroy($sessionId): bool + { + $this->redis->del($this->prefix.$sessionId); + + return true; + } + + /** + * {@inheritdoc} + */ + public function close(): bool + { + return true; + } + + /** + * {@inheritdoc} + */ + public function gc($maxlifetime): bool + { + return true; + } + + /** + * {@inheritdoc} + */ + public function updateTimestamp($sessionId, $data) + { + return (bool) $this->redis->expire($this->prefix.$sessionId, (int) ini_get('session.gc_maxlifetime')); + } +} diff --git a/vendor/symfony/http-foundation/Session/Storage/Handler/StrictSessionHandler.php b/vendor/symfony/http-foundation/Session/Storage/Handler/StrictSessionHandler.php index 228119297d85a0162aefe69be19859c9297bf96d..fab8e9a16d8d96a2e477cd52bcccc44e42e21d3d 100644 --- a/vendor/symfony/http-foundation/Session/Storage/Handler/StrictSessionHandler.php +++ b/vendor/symfony/http-foundation/Session/Storage/Handler/StrictSessionHandler.php @@ -24,7 +24,7 @@ class StrictSessionHandler extends AbstractSessionHandler public function __construct(\SessionHandlerInterface $handler) { if ($handler instanceof \SessionUpdateTimestampHandlerInterface) { - throw new \LogicException(sprintf('"%s" is already an instance of "SessionUpdateTimestampHandlerInterface", you cannot wrap it with "%s".', get_class($handler), self::class)); + throw new \LogicException(sprintf('"%s" is already an instance of "SessionUpdateTimestampHandlerInterface", you cannot wrap it with "%s".', \get_class($handler), self::class)); } $this->handler = $handler; @@ -94,7 +94,7 @@ class StrictSessionHandler extends AbstractSessionHandler } /** - * {@inheritdoc} + * @return bool */ public function gc($maxlifetime) { diff --git a/vendor/symfony/http-foundation/Session/Storage/Handler/WriteCheckSessionHandler.php b/vendor/symfony/http-foundation/Session/Storage/Handler/WriteCheckSessionHandler.php deleted file mode 100644 index 1541ec4e0aa495803454a00b16e74c09a1e55ed3..0000000000000000000000000000000000000000 --- a/vendor/symfony/http-foundation/Session/Storage/Handler/WriteCheckSessionHandler.php +++ /dev/null @@ -1,92 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session\Storage\Handler; - -@trigger_error(sprintf('The %s class is deprecated since Symfony 3.4 and will be removed in 4.0. Implement `SessionUpdateTimestampHandlerInterface` or extend `AbstractSessionHandler` instead.', WriteCheckSessionHandler::class), E_USER_DEPRECATED); - -/** - * Wraps another SessionHandlerInterface to only write the session when it has been modified. - * - * @author Adrien Brault <adrien.brault@gmail.com> - * - * @deprecated since version 3.4, to be removed in 4.0. Implement `SessionUpdateTimestampHandlerInterface` or extend `AbstractSessionHandler` instead. - */ -class WriteCheckSessionHandler implements \SessionHandlerInterface -{ - private $wrappedSessionHandler; - - /** - * @var array sessionId => session - */ - private $readSessions; - - public function __construct(\SessionHandlerInterface $wrappedSessionHandler) - { - $this->wrappedSessionHandler = $wrappedSessionHandler; - } - - /** - * {@inheritdoc} - */ - public function close() - { - return $this->wrappedSessionHandler->close(); - } - - /** - * {@inheritdoc} - */ - public function destroy($sessionId) - { - return $this->wrappedSessionHandler->destroy($sessionId); - } - - /** - * {@inheritdoc} - */ - public function gc($maxlifetime) - { - return $this->wrappedSessionHandler->gc($maxlifetime); - } - - /** - * {@inheritdoc} - */ - public function open($savePath, $sessionName) - { - return $this->wrappedSessionHandler->open($savePath, $sessionName); - } - - /** - * {@inheritdoc} - */ - public function read($sessionId) - { - $session = $this->wrappedSessionHandler->read($sessionId); - - $this->readSessions[$sessionId] = $session; - - return $session; - } - - /** - * {@inheritdoc} - */ - public function write($sessionId, $data) - { - if (isset($this->readSessions[$sessionId]) && $data === $this->readSessions[$sessionId]) { - return true; - } - - return $this->wrappedSessionHandler->write($sessionId, $data); - } -} diff --git a/vendor/symfony/http-foundation/Session/Storage/MetadataBag.php b/vendor/symfony/http-foundation/Session/Storage/MetadataBag.php index 6f59af486981ebb1b2cb9c2687cc3ef2d40250d4..2eff4109b43ab7ac77d2f116f5b457337fa7f906 100644 --- a/vendor/symfony/http-foundation/Session/Storage/MetadataBag.php +++ b/vendor/symfony/http-foundation/Session/Storage/MetadataBag.php @@ -39,7 +39,7 @@ class MetadataBag implements SessionBagInterface /** * @var array */ - protected $meta = array(self::CREATED => 0, self::UPDATED => 0, self::LIFETIME => 0); + protected $meta = [self::CREATED => 0, self::UPDATED => 0, self::LIFETIME => 0]; /** * Unix timestamp. @@ -57,7 +57,7 @@ class MetadataBag implements SessionBagInterface * @param string $storageKey The key used to store bag in the session * @param int $updateThreshold The time to wait between two UPDATED updates */ - public function __construct($storageKey = '_sf2_meta', $updateThreshold = 0) + public function __construct(string $storageKey = '_sf2_meta', int $updateThreshold = 0) { $this->storageKey = $storageKey; $this->updateThreshold = $updateThreshold; diff --git a/vendor/symfony/http-foundation/Session/Storage/MockArraySessionStorage.php b/vendor/symfony/http-foundation/Session/Storage/MockArraySessionStorage.php index 027f4efffce51b9958b3cda5133d162bfcad888e..37b6f145b87cc60d81f86ac25c389b898442915d 100644 --- a/vendor/symfony/http-foundation/Session/Storage/MockArraySessionStorage.php +++ b/vendor/symfony/http-foundation/Session/Storage/MockArraySessionStorage.php @@ -50,7 +50,7 @@ class MockArraySessionStorage implements SessionStorageInterface /** * @var array */ - protected $data = array(); + protected $data = []; /** * @var MetadataBag @@ -60,13 +60,9 @@ class MockArraySessionStorage implements SessionStorageInterface /** * @var array|SessionBagInterface[] */ - protected $bags = array(); + protected $bags = []; - /** - * @param string $name Session name - * @param MetadataBag $metaBag MetadataBag instance - */ - public function __construct($name = 'MOCKSESSID', MetadataBag $metaBag = null) + public function __construct(string $name = 'MOCKSESSID', MetadataBag $metaBag = null) { $this->name = $name; $this->setMetadataBag($metaBag); @@ -170,7 +166,7 @@ class MockArraySessionStorage implements SessionStorageInterface } // clear out the session - $this->data = array(); + $this->data = []; // reconnect the bags to the session $this->loadSession(); @@ -242,11 +238,11 @@ class MockArraySessionStorage implements SessionStorageInterface protected function loadSession() { - $bags = array_merge($this->bags, array($this->metadataBag)); + $bags = array_merge($this->bags, [$this->metadataBag]); foreach ($bags as $bag) { $key = $bag->getStorageKey(); - $this->data[$key] = isset($this->data[$key]) ? $this->data[$key] : array(); + $this->data[$key] = isset($this->data[$key]) ? $this->data[$key] : []; $bag->initialize($this->data[$key]); } diff --git a/vendor/symfony/http-foundation/Session/Storage/MockFileSessionStorage.php b/vendor/symfony/http-foundation/Session/Storage/MockFileSessionStorage.php index 14f427007ba82d97351a0e77ac4f89cacb710c8c..c0316c2c74e7c1f3753da2ae5acdb21ebfc7fd9d 100644 --- a/vendor/symfony/http-foundation/Session/Storage/MockFileSessionStorage.php +++ b/vendor/symfony/http-foundation/Session/Storage/MockFileSessionStorage.php @@ -31,7 +31,7 @@ class MockFileSessionStorage extends MockArraySessionStorage * @param string $name Session name * @param MetadataBag $metaBag MetadataBag instance */ - public function __construct($savePath = null, $name = 'MOCKSESSID', MetadataBag $metaBag = null) + public function __construct(string $savePath = null, string $name = 'MOCKSESSID', MetadataBag $metaBag = null) { if (null === $savePath) { $savePath = sys_get_temp_dir(); @@ -98,7 +98,7 @@ class MockFileSessionStorage extends MockArraySessionStorage unset($data[$key]); } } - if (array($key = $this->metadataBag->getStorageKey()) === array_keys($data)) { + if ([$key = $this->metadataBag->getStorageKey()] === array_keys($data)) { unset($data[$key]); } @@ -145,7 +145,7 @@ class MockFileSessionStorage extends MockArraySessionStorage private function read() { $filePath = $this->getFilePath(); - $this->data = is_readable($filePath) && is_file($filePath) ? unserialize(file_get_contents($filePath)) : array(); + $this->data = is_readable($filePath) && is_file($filePath) ? unserialize(file_get_contents($filePath)) : []; $this->loadSession(); } diff --git a/vendor/symfony/http-foundation/Session/Storage/NativeSessionStorage.php b/vendor/symfony/http-foundation/Session/Storage/NativeSessionStorage.php index 0dfad9acb353282c7d679bb82557824c3e08debe..202f3a5a6a166db1362ddf3043eedf46025fd841 100644 --- a/vendor/symfony/http-foundation/Session/Storage/NativeSessionStorage.php +++ b/vendor/symfony/http-foundation/Session/Storage/NativeSessionStorage.php @@ -12,6 +12,7 @@ namespace Symfony\Component\HttpFoundation\Session\Storage; use Symfony\Component\HttpFoundation\Session\SessionBagInterface; +use Symfony\Component\HttpFoundation\Session\SessionUtils; use Symfony\Component\HttpFoundation\Session\Storage\Handler\StrictSessionHandler; use Symfony\Component\HttpFoundation\Session\Storage\Proxy\AbstractProxy; use Symfony\Component\HttpFoundation\Session\Storage\Proxy\SessionHandlerProxy; @@ -26,7 +27,7 @@ class NativeSessionStorage implements SessionStorageInterface /** * @var SessionBagInterface[] */ - protected $bags = array(); + protected $bags = []; /** * @var bool @@ -48,13 +49,18 @@ class NativeSessionStorage implements SessionStorageInterface */ protected $metadataBag; + /** + * @var string|null + */ + private $emulateSameSite; + /** * Depending on how you want the storage driver to behave you probably * want to override this constructor entirely. * * List of options for $options array with their defaults. * - * @see http://php.net/session.configuration for options + * @see https://php.net/session.configuration for options * but we omit 'session.' from the beginning of the keys for convenience. * * ("auto_start", is not supported as it tells PHP to start a session before @@ -67,13 +73,10 @@ class NativeSessionStorage implements SessionStorageInterface * cookie_lifetime, "0" * cookie_path, "/" * cookie_secure, "" - * entropy_file, "" - * entropy_length, "0" + * cookie_samesite, null * gc_divisor, "100" * gc_maxlifetime, "1440" * gc_probability, "1" - * hash_bits_per_character, "4" - * hash_function, "0" * lazy_write, "1" * name, "PHPSESSID" * referer_check, "" @@ -98,14 +101,19 @@ class NativeSessionStorage implements SessionStorageInterface * @param \SessionHandlerInterface|null $handler * @param MetadataBag $metaBag MetadataBag */ - public function __construct(array $options = array(), $handler = null, MetadataBag $metaBag = null) + public function __construct(array $options = [], $handler = null, MetadataBag $metaBag = null) { - $options += array( + if (!\extension_loaded('session')) { + throw new \LogicException('PHP extension "session" is required.'); + } + + $options += [ 'cache_limiter' => '', 'cache_expire' => 0, 'use_cookies' => 1, 'lazy_write' => 1, - ); + 'use_strict_mode' => 1, + ]; session_register_shutdown(); @@ -137,7 +145,7 @@ class NativeSessionStorage implements SessionStorageInterface throw new \RuntimeException('Failed to start the session: already started by PHP.'); } - if (ini_get('session.use_cookies') && headers_sent($file, $line)) { + if (filter_var(ini_get('session.use_cookies'), FILTER_VALIDATE_BOOLEAN) && headers_sent($file, $line)) { throw new \RuntimeException(sprintf('Failed to start the session because headers have already been sent by "%s" at line %d.', $file, $line)); } @@ -146,6 +154,13 @@ class NativeSessionStorage implements SessionStorageInterface throw new \RuntimeException('Failed to start the session'); } + if (null !== $this->emulateSameSite) { + $originalCookie = SessionUtils::popSessionCookie(session_name(), session_id()); + if (null !== $originalCookie) { + header(sprintf('%s; SameSite=%s', $originalCookie, $this->emulateSameSite), false); + } + } + $this->loadSession(); return true; @@ -208,9 +223,16 @@ class NativeSessionStorage implements SessionStorageInterface $isRegenerated = session_regenerate_id($destroy); // The reference to $_SESSION in session bags is lost in PHP7 and we need to re-create it. - // @see https://bugs.php.net/bug.php?id=70013 + // @see https://bugs.php.net/70013 $this->loadSession(); + if (null !== $this->emulateSameSite) { + $originalCookie = SessionUtils::popSessionCookie(session_name(), session_id()); + if (null !== $originalCookie) { + header(sprintf('%s; SameSite=%s', $originalCookie, $this->emulateSameSite), false); + } + } + return $isRegenerated; } @@ -219,6 +241,7 @@ class NativeSessionStorage implements SessionStorageInterface */ public function save() { + // Store a copy so we can restore the bags in case the session was not left empty $session = $_SESSION; foreach ($this->bags as $bag) { @@ -226,32 +249,29 @@ class NativeSessionStorage implements SessionStorageInterface unset($_SESSION[$key]); } } - if (array($key = $this->metadataBag->getStorageKey()) === array_keys($_SESSION)) { + if ([$key = $this->metadataBag->getStorageKey()] === array_keys($_SESSION)) { unset($_SESSION[$key]); } - // Register custom error handler to catch a possible failure warning during session write - set_error_handler(function ($errno, $errstr, $errfile, $errline) { - throw new \ErrorException($errstr, $errno, E_WARNING, $errfile, $errline); - }, E_WARNING); + // Register error handler to add information about the current save handler + $previousHandler = set_error_handler(function ($type, $msg, $file, $line) use (&$previousHandler) { + if (E_WARNING === $type && 0 === strpos($msg, 'session_write_close():')) { + $handler = $this->saveHandler instanceof SessionHandlerProxy ? $this->saveHandler->getHandler() : $this->saveHandler; + $msg = sprintf('session_write_close(): Failed to write session data with "%s" handler', \get_class($handler)); + } + + return $previousHandler ? $previousHandler($type, $msg, $file, $line) : false; + }); try { - $e = null; session_write_close(); - } catch (\ErrorException $e) { } finally { restore_error_handler(); - $_SESSION = $session; - } - if (null !== $e) { - // The default PHP error message is not very helpful, as it does not give any information on the current save handler. - // Therefore, we catch this error and trigger a warning with a better error message - $handler = $this->getSaveHandler(); - if ($handler instanceof SessionHandlerProxy) { - $handler = $handler->getHandler(); - } - trigger_error(sprintf('session_write_close(): Failed to write session data with %s handler', get_class($handler)), E_USER_WARNING); + // Restore only if not empty + if ($_SESSION) { + $_SESSION = $session; + } } $this->closed = true; @@ -269,7 +289,7 @@ class NativeSessionStorage implements SessionStorageInterface } // clear out the session - $_SESSION = array(); + $_SESSION = []; // reconnect the bags to the session $this->loadSession(); @@ -338,9 +358,9 @@ class NativeSessionStorage implements SessionStorageInterface * For convenience we omit 'session.' from the beginning of the keys. * Explicitly ignores other ini keys. * - * @param array $options Session ini directives array(key => value) + * @param array $options Session ini directives [key => value] * - * @see http://php.net/session.configuration + * @see https://php.net/session.configuration */ public function setOptions(array $options) { @@ -348,22 +368,27 @@ class NativeSessionStorage implements SessionStorageInterface return; } - $validOptions = array_flip(array( - 'cache_limiter', 'cache_expire', 'cookie_domain', 'cookie_httponly', - 'cookie_lifetime', 'cookie_path', 'cookie_secure', - 'entropy_file', 'entropy_length', 'gc_divisor', - 'gc_maxlifetime', 'gc_probability', 'hash_bits_per_character', - 'hash_function', 'lazy_write', 'name', 'referer_check', + $validOptions = array_flip([ + 'cache_expire', 'cache_limiter', 'cookie_domain', 'cookie_httponly', + 'cookie_lifetime', 'cookie_path', 'cookie_secure', 'cookie_samesite', + 'gc_divisor', 'gc_maxlifetime', 'gc_probability', + 'lazy_write', 'name', 'referer_check', 'serialize_handler', 'use_strict_mode', 'use_cookies', 'use_only_cookies', 'use_trans_sid', 'upload_progress.enabled', 'upload_progress.cleanup', 'upload_progress.prefix', 'upload_progress.name', - 'upload_progress.freq', 'upload_progress.min-freq', 'url_rewriter.tags', + 'upload_progress.freq', 'upload_progress.min_freq', 'url_rewriter.tags', 'sid_length', 'sid_bits_per_character', 'trans_sid_hosts', 'trans_sid_tags', - )); + ]); foreach ($options as $key => $value) { if (isset($validOptions[$key])) { - ini_set('session.'.$key, $value); + if ('cookie_samesite' === $key && \PHP_VERSION_ID < 70300) { + // PHP < 7.3 does not support same_site cookies. We will emulate it in + // the start() method instead. + $this->emulateSameSite = $value; + continue; + } + ini_set('url_rewriter.tags' !== $key ? 'session.'.$key : $key, $value); } } } @@ -381,10 +406,10 @@ class NativeSessionStorage implements SessionStorageInterface * constructor, for a template see NativeFileSessionHandler or use handlers in * composer package drak/native-session * - * @see http://php.net/session-set-save-handler - * @see http://php.net/sessionhandlerinterface - * @see http://php.net/sessionhandler - * @see http://github.com/drak/NativeSession + * @see https://php.net/session-set-save-handler + * @see https://php.net/sessionhandlerinterface + * @see https://php.net/sessionhandler + * @see https://github.com/zikula/NativeSession * * @param \SessionHandlerInterface|null $saveHandler * @@ -411,8 +436,6 @@ class NativeSessionStorage implements SessionStorageInterface } if ($this->saveHandler instanceof SessionHandlerProxy) { - session_set_save_handler($this->saveHandler->getHandler(), false); - } elseif ($this->saveHandler instanceof \SessionHandlerInterface) { session_set_save_handler($this->saveHandler, false); } } @@ -431,11 +454,11 @@ class NativeSessionStorage implements SessionStorageInterface $session = &$_SESSION; } - $bags = array_merge($this->bags, array($this->metadataBag)); + $bags = array_merge($this->bags, [$this->metadataBag]); foreach ($bags as $bag) { $key = $bag->getStorageKey(); - $session[$key] = isset($session[$key]) ? $session[$key] : array(); + $session[$key] = isset($session[$key]) && \is_array($session[$key]) ? $session[$key] : []; $bag->initialize($session[$key]); } diff --git a/vendor/symfony/http-foundation/Session/Storage/PhpBridgeSessionStorage.php b/vendor/symfony/http-foundation/Session/Storage/PhpBridgeSessionStorage.php index 662ed5015adecdb293cc112e1d49239d1615097a..8969e609aaf95782deae4c56617650e4eb0b9a68 100644 --- a/vendor/symfony/http-foundation/Session/Storage/PhpBridgeSessionStorage.php +++ b/vendor/symfony/http-foundation/Session/Storage/PhpBridgeSessionStorage.php @@ -24,6 +24,10 @@ class PhpBridgeSessionStorage extends NativeSessionStorage */ public function __construct($handler = null, MetadataBag $metaBag = null) { + if (!\extension_loaded('session')) { + throw new \LogicException('PHP extension "session" is required.'); + } + $this->setMetadataBag($metaBag); $this->setSaveHandler($handler); } diff --git a/vendor/symfony/http-foundation/Session/Storage/Proxy/AbstractProxy.php b/vendor/symfony/http-foundation/Session/Storage/Proxy/AbstractProxy.php index 09c92483c7575f6b9bf7083c19a75c9ad6d9f58c..0303729e7b387b0b5b60dfa3a077cc54cf850836 100644 --- a/vendor/symfony/http-foundation/Session/Storage/Proxy/AbstractProxy.php +++ b/vendor/symfony/http-foundation/Session/Storage/Proxy/AbstractProxy.php @@ -31,7 +31,7 @@ abstract class AbstractProxy /** * Gets the session.save_handler name. * - * @return string + * @return string|null */ public function getSaveHandlerName() { diff --git a/vendor/symfony/http-foundation/Session/Storage/Proxy/NativeProxy.php b/vendor/symfony/http-foundation/Session/Storage/Proxy/NativeProxy.php deleted file mode 100644 index 082eed143eb4340bf611eb7bac81864fb49d2e57..0000000000000000000000000000000000000000 --- a/vendor/symfony/http-foundation/Session/Storage/Proxy/NativeProxy.php +++ /dev/null @@ -1,40 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Session\Storage\Proxy; - -@trigger_error('The '.__NAMESPACE__.'\NativeProxy class is deprecated since Symfony 3.4 and will be removed in 4.0. Use your session handler implementation directly.', E_USER_DEPRECATED); - -/** - * This proxy is built-in session handlers in PHP 5.3.x. - * - * @deprecated since version 3.4, to be removed in 4.0. Use your session handler implementation directly. - * - * @author Drak <drak@zikula.org> - */ -class NativeProxy extends AbstractProxy -{ - public function __construct() - { - // this makes an educated guess as to what the handler is since it should already be set. - $this->saveHandlerName = ini_get('session.save_handler'); - } - - /** - * Returns true if this handler wraps an internal PHP session save handler using \SessionHandler. - * - * @return bool False - */ - public function isWrapper() - { - return false; - } -} diff --git a/vendor/symfony/http-foundation/Session/Storage/Proxy/SessionHandlerProxy.php b/vendor/symfony/http-foundation/Session/Storage/Proxy/SessionHandlerProxy.php index 53c1209a1c07d1fdaeacd0932764175943bdd4b0..e40712d93f637144c482d7a3da9aa24a93eb9201 100644 --- a/vendor/symfony/http-foundation/Session/Storage/Proxy/SessionHandlerProxy.php +++ b/vendor/symfony/http-foundation/Session/Storage/Proxy/SessionHandlerProxy.php @@ -14,7 +14,7 @@ namespace Symfony\Component\HttpFoundation\Session\Storage\Proxy; /** * @author Drak <drak@zikula.org> */ -class SessionHandlerProxy extends AbstractProxy implements \SessionHandlerInterface +class SessionHandlerProxy extends AbstractProxy implements \SessionHandlerInterface, \SessionUpdateTimestampHandlerInterface { protected $handler; @@ -76,10 +76,26 @@ class SessionHandlerProxy extends AbstractProxy implements \SessionHandlerInterf } /** - * {@inheritdoc} + * @return bool */ public function gc($maxlifetime) { return (bool) $this->handler->gc($maxlifetime); } + + /** + * {@inheritdoc} + */ + public function validateId($sessionId) + { + return !$this->handler instanceof \SessionUpdateTimestampHandlerInterface || $this->handler->validateId($sessionId); + } + + /** + * {@inheritdoc} + */ + public function updateTimestamp($sessionId, $data) + { + return $this->handler instanceof \SessionUpdateTimestampHandlerInterface ? $this->handler->updateTimestamp($sessionId, $data) : $this->write($sessionId, $data); + } } diff --git a/vendor/symfony/http-foundation/Session/Storage/SessionStorageInterface.php b/vendor/symfony/http-foundation/Session/Storage/SessionStorageInterface.php index 66e8b33dd2bed4a6ed324025a591c81eaa39dbb2..eeb396a2f131c453fbd574023ac4b9639fddc1ff 100644 --- a/vendor/symfony/http-foundation/Session/Storage/SessionStorageInterface.php +++ b/vendor/symfony/http-foundation/Session/Storage/SessionStorageInterface.php @@ -77,7 +77,7 @@ interface SessionStorageInterface * only delete the session data from persistent storage. * * Care: When regenerating the session ID no locking is involved in PHP's - * session design. See https://bugs.php.net/bug.php?id=61470 for a discussion. + * session design. See https://bugs.php.net/61470 for a discussion. * So you must make sure the regenerated session is saved BEFORE sending the * headers with the new ID. Symfony's HttpKernel offers a listener for this. * See Symfony\Component\HttpKernel\EventListener\SaveSessionListener. diff --git a/vendor/symfony/http-foundation/StreamedResponse.php b/vendor/symfony/http-foundation/StreamedResponse.php index 92868d33e48144666e7a49e4ce00377079aa82f5..bfbcae9a53769e61e60521df14bcb84798ae629b 100644 --- a/vendor/symfony/http-foundation/StreamedResponse.php +++ b/vendor/symfony/http-foundation/StreamedResponse.php @@ -17,7 +17,7 @@ namespace Symfony\Component\HttpFoundation; * A StreamedResponse uses a callback for its content. * * The callback should use the standard PHP functions like echo - * to stream the response back to the client. The flush() method + * to stream the response back to the client. The flush() function * can also be used if needed. * * @see flush() @@ -35,7 +35,7 @@ class StreamedResponse extends Response * @param int $status The response status code * @param array $headers An array of response headers */ - public function __construct(callable $callback = null, $status = 200, $headers = array()) + public function __construct(callable $callback = null, int $status = 200, array $headers = []) { parent::__construct(null, $status, $headers); @@ -55,7 +55,7 @@ class StreamedResponse extends Response * * @return static */ - public static function create($callback = null, $status = 200, $headers = array()) + public static function create($callback = null, $status = 200, $headers = []) { return new static($callback, $status, $headers); } @@ -111,7 +111,7 @@ class StreamedResponse extends Response throw new \LogicException('The Response callback must not be null.'); } - call_user_func($this->callback); + ($this->callback)(); return $this; } @@ -129,13 +129,13 @@ class StreamedResponse extends Response throw new \LogicException('The content cannot be set on a StreamedResponse instance.'); } + $this->streamed = true; + return $this; } /** * {@inheritdoc} - * - * @return false */ public function getContent() { diff --git a/vendor/symfony/http-foundation/Test/Constraint/RequestAttributeValueSame.php b/vendor/symfony/http-foundation/Test/Constraint/RequestAttributeValueSame.php new file mode 100644 index 0000000000000000000000000000000000000000..2d105627860ef6970f607a21988eab2e433b1d3f --- /dev/null +++ b/vendor/symfony/http-foundation/Test/Constraint/RequestAttributeValueSame.php @@ -0,0 +1,54 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\Test\Constraint; + +use PHPUnit\Framework\Constraint\Constraint; + +final class RequestAttributeValueSame extends Constraint +{ + private $name; + private $value; + + public function __construct(string $name, string $value) + { + $this->name = $name; + $this->value = $value; + } + + /** + * {@inheritdoc} + */ + public function toString(): string + { + return sprintf('has attribute "%s" with value "%s"', $this->name, $this->value); + } + + /** + * @param Request $request + * + * {@inheritdoc} + */ + protected function matches($request): bool + { + return $this->value === $request->attributes->get($this->name); + } + + /** + * @param Request $request + * + * {@inheritdoc} + */ + protected function failureDescription($request): string + { + return 'the Request '.$this->toString(); + } +} diff --git a/vendor/symfony/http-foundation/Test/Constraint/ResponseCookieValueSame.php b/vendor/symfony/http-foundation/Test/Constraint/ResponseCookieValueSame.php new file mode 100644 index 0000000000000000000000000000000000000000..554e1a1602dd60ef281ca93702e1e84dcc963909 --- /dev/null +++ b/vendor/symfony/http-foundation/Test/Constraint/ResponseCookieValueSame.php @@ -0,0 +1,85 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\Test\Constraint; + +use PHPUnit\Framework\Constraint\Constraint; +use Symfony\Component\HttpFoundation\Cookie; +use Symfony\Component\HttpFoundation\Response; + +final class ResponseCookieValueSame extends Constraint +{ + private $name; + private $value; + private $path; + private $domain; + + public function __construct(string $name, string $value, string $path = '/', string $domain = null) + { + $this->name = $name; + $this->value = $value; + $this->path = $path; + $this->domain = $domain; + } + + /** + * {@inheritdoc} + */ + public function toString(): string + { + $str = sprintf('has cookie "%s"', $this->name); + if ('/' !== $this->path) { + $str .= sprintf(' with path "%s"', $this->path); + } + if ($this->domain) { + $str .= sprintf(' for domain "%s"', $this->domain); + } + $str .= sprintf(' with value "%s"', $this->value); + + return $str; + } + + /** + * @param Response $response + * + * {@inheritdoc} + */ + protected function matches($response): bool + { + $cookie = $this->getCookie($response); + if (!$cookie) { + return false; + } + + return $this->value === $cookie->getValue(); + } + + /** + * @param Response $response + * + * {@inheritdoc} + */ + protected function failureDescription($response): string + { + return 'the Response '.$this->toString(); + } + + protected function getCookie(Response $response): ?Cookie + { + $cookies = $response->headers->getCookies(); + + $filteredCookies = array_filter($cookies, function (Cookie $cookie) { + return $cookie->getName() === $this->name && $cookie->getPath() === $this->path && $cookie->getDomain() === $this->domain; + }); + + return reset($filteredCookies) ?: null; + } +} diff --git a/vendor/symfony/http-foundation/Test/Constraint/ResponseHasCookie.php b/vendor/symfony/http-foundation/Test/Constraint/ResponseHasCookie.php new file mode 100644 index 0000000000000000000000000000000000000000..bd792b0d876b2b7bdeb923b309cc41d28da5f638 --- /dev/null +++ b/vendor/symfony/http-foundation/Test/Constraint/ResponseHasCookie.php @@ -0,0 +1,77 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\Test\Constraint; + +use PHPUnit\Framework\Constraint\Constraint; +use Symfony\Component\HttpFoundation\Cookie; +use Symfony\Component\HttpFoundation\Response; + +final class ResponseHasCookie extends Constraint +{ + private $name; + private $path; + private $domain; + + public function __construct(string $name, string $path = '/', string $domain = null) + { + $this->name = $name; + $this->path = $path; + $this->domain = $domain; + } + + /** + * {@inheritdoc} + */ + public function toString(): string + { + $str = sprintf('has cookie "%s"', $this->name); + if ('/' !== $this->path) { + $str .= sprintf(' with path "%s"', $this->path); + } + if ($this->domain) { + $str .= sprintf(' for domain "%s"', $this->domain); + } + + return $str; + } + + /** + * @param Response $response + * + * {@inheritdoc} + */ + protected function matches($response): bool + { + return null !== $this->getCookie($response); + } + + /** + * @param Response $response + * + * {@inheritdoc} + */ + protected function failureDescription($response): string + { + return 'the Response '.$this->toString(); + } + + protected function getCookie(Response $response): ?Cookie + { + $cookies = $response->headers->getCookies(); + + $filteredCookies = array_filter($cookies, function (Cookie $cookie) { + return $cookie->getName() === $this->name && $cookie->getPath() === $this->path && $cookie->getDomain() === $this->domain; + }); + + return reset($filteredCookies) ?: null; + } +} diff --git a/vendor/symfony/http-foundation/Test/Constraint/ResponseHasHeader.php b/vendor/symfony/http-foundation/Test/Constraint/ResponseHasHeader.php new file mode 100644 index 0000000000000000000000000000000000000000..68ad8273fd56884a976e12da5ce6b13a7c8be90e --- /dev/null +++ b/vendor/symfony/http-foundation/Test/Constraint/ResponseHasHeader.php @@ -0,0 +1,53 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\Test\Constraint; + +use PHPUnit\Framework\Constraint\Constraint; +use Symfony\Component\HttpFoundation\Response; + +final class ResponseHasHeader extends Constraint +{ + private $headerName; + + public function __construct(string $headerName) + { + $this->headerName = $headerName; + } + + /** + * {@inheritdoc} + */ + public function toString(): string + { + return sprintf('has header "%s"', $this->headerName); + } + + /** + * @param Response $response + * + * {@inheritdoc} + */ + protected function matches($response): bool + { + return $response->headers->has($this->headerName); + } + + /** + * @param Response $response + * + * {@inheritdoc} + */ + protected function failureDescription($response): string + { + return 'the Response '.$this->toString(); + } +} diff --git a/vendor/symfony/http-foundation/Test/Constraint/ResponseHeaderSame.php b/vendor/symfony/http-foundation/Test/Constraint/ResponseHeaderSame.php new file mode 100644 index 0000000000000000000000000000000000000000..acdea71d154ec8f72acc8df98bdea6cb89a0f115 --- /dev/null +++ b/vendor/symfony/http-foundation/Test/Constraint/ResponseHeaderSame.php @@ -0,0 +1,55 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\Test\Constraint; + +use PHPUnit\Framework\Constraint\Constraint; +use Symfony\Component\HttpFoundation\Response; + +final class ResponseHeaderSame extends Constraint +{ + private $headerName; + private $expectedValue; + + public function __construct(string $headerName, string $expectedValue) + { + $this->headerName = $headerName; + $this->expectedValue = $expectedValue; + } + + /** + * {@inheritdoc} + */ + public function toString(): string + { + return sprintf('has header "%s" with value "%s"', $this->headerName, $this->expectedValue); + } + + /** + * @param Response $response + * + * {@inheritdoc} + */ + protected function matches($response): bool + { + return $this->expectedValue === $response->headers->get($this->headerName, null, true); + } + + /** + * @param Response $response + * + * {@inheritdoc} + */ + protected function failureDescription($response): string + { + return 'the Response '.$this->toString(); + } +} diff --git a/vendor/symfony/http-foundation/Test/Constraint/ResponseIsRedirected.php b/vendor/symfony/http-foundation/Test/Constraint/ResponseIsRedirected.php new file mode 100644 index 0000000000000000000000000000000000000000..8c4b883f0b076bba7ff5e9c2daaab4f0131d55bd --- /dev/null +++ b/vendor/symfony/http-foundation/Test/Constraint/ResponseIsRedirected.php @@ -0,0 +1,56 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\Test\Constraint; + +use PHPUnit\Framework\Constraint\Constraint; +use Symfony\Component\HttpFoundation\Response; + +final class ResponseIsRedirected extends Constraint +{ + /** + * {@inheritdoc} + */ + public function toString(): string + { + return 'is redirected'; + } + + /** + * @param Response $response + * + * {@inheritdoc} + */ + protected function matches($response): bool + { + return $response->isRedirect(); + } + + /** + * @param Response $response + * + * {@inheritdoc} + */ + protected function failureDescription($response): string + { + return 'the Response '.$this->toString(); + } + + /** + * @param Response $response + * + * {@inheritdoc} + */ + protected function additionalFailureDescription($response): string + { + return (string) $response; + } +} diff --git a/vendor/symfony/http-foundation/Test/Constraint/ResponseIsSuccessful.php b/vendor/symfony/http-foundation/Test/Constraint/ResponseIsSuccessful.php new file mode 100644 index 0000000000000000000000000000000000000000..9c665589072b71e3a1f0b82ab3d3687184fef17e --- /dev/null +++ b/vendor/symfony/http-foundation/Test/Constraint/ResponseIsSuccessful.php @@ -0,0 +1,56 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\Test\Constraint; + +use PHPUnit\Framework\Constraint\Constraint; +use Symfony\Component\HttpFoundation\Response; + +final class ResponseIsSuccessful extends Constraint +{ + /** + * {@inheritdoc} + */ + public function toString(): string + { + return 'is successful'; + } + + /** + * @param Response $response + * + * {@inheritdoc} + */ + protected function matches($response): bool + { + return $response->isSuccessful(); + } + + /** + * @param Response $response + * + * {@inheritdoc} + */ + protected function failureDescription($response): string + { + return 'the Response '.$this->toString(); + } + + /** + * @param Response $response + * + * {@inheritdoc} + */ + protected function additionalFailureDescription($response): string + { + return (string) $response; + } +} diff --git a/vendor/symfony/http-foundation/Test/Constraint/ResponseStatusCodeSame.php b/vendor/symfony/http-foundation/Test/Constraint/ResponseStatusCodeSame.php new file mode 100644 index 0000000000000000000000000000000000000000..72bb000b8592c7d7a32dfdfc27cc0cad912e7132 --- /dev/null +++ b/vendor/symfony/http-foundation/Test/Constraint/ResponseStatusCodeSame.php @@ -0,0 +1,63 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\Test\Constraint; + +use PHPUnit\Framework\Constraint\Constraint; +use Symfony\Component\HttpFoundation\Response; + +final class ResponseStatusCodeSame extends Constraint +{ + private $statusCode; + + public function __construct(int $statusCode) + { + $this->statusCode = $statusCode; + } + + /** + * {@inheritdoc} + */ + public function toString(): string + { + return 'status code is '.$this->statusCode; + } + + /** + * @param Response $response + * + * {@inheritdoc} + */ + protected function matches($response): bool + { + return $this->statusCode === $response->getStatusCode(); + } + + /** + * @param Response $response + * + * {@inheritdoc} + */ + protected function failureDescription($response): string + { + return 'the Response '.$this->toString(); + } + + /** + * @param Response $response + * + * {@inheritdoc} + */ + protected function additionalFailureDescription($response): string + { + return (string) $response; + } +} diff --git a/vendor/symfony/http-foundation/Tests/AcceptHeaderItemTest.php b/vendor/symfony/http-foundation/Tests/AcceptHeaderItemTest.php index cb43bb35168a795b90967623d6d8164bdfe491ff..516bd5551a0f34e816e0ef739e9ad271669b4924 100644 --- a/vendor/symfony/http-foundation/Tests/AcceptHeaderItemTest.php +++ b/vendor/symfony/http-foundation/Tests/AcceptHeaderItemTest.php @@ -28,24 +28,24 @@ class AcceptHeaderItemTest extends TestCase public function provideFromStringData() { - return array( - array( + return [ + [ 'text/html', - 'text/html', array(), - ), - array( + 'text/html', [], + ], + [ '"this;should,not=matter"', - 'this;should,not=matter', array(), - ), - array( + 'this;should,not=matter', [], + ], + [ "text/plain; charset=utf-8;param=\"this;should,not=matter\";\tfootnotes=true", - 'text/plain', array('charset' => 'utf-8', 'param' => 'this;should,not=matter', 'footnotes' => 'true'), - ), - array( + 'text/plain', ['charset' => 'utf-8', 'param' => 'this;should,not=matter', 'footnotes' => 'true'], + ], + [ '"this;should,not=matter";charset=utf-8', - 'this;should,not=matter', array('charset' => 'utf-8'), - ), - ); + 'this;should,not=matter', ['charset' => 'utf-8'], + ], + ]; } /** @@ -59,21 +59,21 @@ class AcceptHeaderItemTest extends TestCase public function provideToStringData() { - return array( - array( - 'text/html', array(), + return [ + [ + 'text/html', [], 'text/html', - ), - array( - 'text/plain', array('charset' => 'utf-8', 'param' => 'this;should,not=matter', 'footnotes' => 'true'), - 'text/plain;charset=utf-8;param="this;should,not=matter";footnotes=true', - ), - ); + ], + [ + 'text/plain', ['charset' => 'utf-8', 'param' => 'this;should,not=matter', 'footnotes' => 'true'], + 'text/plain; charset=utf-8; param="this;should,not=matter"; footnotes=true', + ], + ]; } public function testValue() { - $item = new AcceptHeaderItem('value', array()); + $item = new AcceptHeaderItem('value', []); $this->assertEquals('value', $item->getValue()); $item->setValue('new value'); @@ -85,7 +85,7 @@ class AcceptHeaderItemTest extends TestCase public function testQuality() { - $item = new AcceptHeaderItem('value', array()); + $item = new AcceptHeaderItem('value', []); $this->assertEquals(1.0, $item->getQuality()); $item->setQuality(0.5); @@ -98,14 +98,14 @@ class AcceptHeaderItemTest extends TestCase public function testAttribute() { - $item = new AcceptHeaderItem('value', array()); - $this->assertEquals(array(), $item->getAttributes()); + $item = new AcceptHeaderItem('value', []); + $this->assertEquals([], $item->getAttributes()); $this->assertFalse($item->hasAttribute('test')); $this->assertNull($item->getAttribute('test')); $this->assertEquals('default', $item->getAttribute('test', 'default')); $item->setAttribute('test', 'value'); - $this->assertEquals(array('test' => 'value'), $item->getAttributes()); + $this->assertEquals(['test' => 'value'], $item->getAttributes()); $this->assertTrue($item->hasAttribute('test')); $this->assertEquals('value', $item->getAttribute('test')); $this->assertEquals('value', $item->getAttribute('test', 'default')); diff --git a/vendor/symfony/http-foundation/Tests/AcceptHeaderTest.php b/vendor/symfony/http-foundation/Tests/AcceptHeaderTest.php index 9929eac28ef01feabe869324fbcbf1d492597060..1987e97fb8bc7296f0549d31487e9a5efeecb5bc 100644 --- a/vendor/symfony/http-foundation/Tests/AcceptHeaderTest.php +++ b/vendor/symfony/http-foundation/Tests/AcceptHeaderTest.php @@ -39,13 +39,13 @@ class AcceptHeaderTest extends TestCase public function provideFromStringData() { - return array( - array('', array()), - array('gzip', array(new AcceptHeaderItem('gzip'))), - array('gzip,deflate,sdch', array(new AcceptHeaderItem('gzip'), new AcceptHeaderItem('deflate'), new AcceptHeaderItem('sdch'))), - array("gzip, deflate\t,sdch", array(new AcceptHeaderItem('gzip'), new AcceptHeaderItem('deflate'), new AcceptHeaderItem('sdch'))), - array('"this;should,not=matter"', array(new AcceptHeaderItem('this;should,not=matter'))), - ); + return [ + ['', []], + ['gzip', [new AcceptHeaderItem('gzip')]], + ['gzip,deflate,sdch', [new AcceptHeaderItem('gzip'), new AcceptHeaderItem('deflate'), new AcceptHeaderItem('sdch')]], + ["gzip, deflate\t,sdch", [new AcceptHeaderItem('gzip'), new AcceptHeaderItem('deflate'), new AcceptHeaderItem('sdch')]], + ['"this;should,not=matter"', [new AcceptHeaderItem('this;should,not=matter')]], + ]; } /** @@ -59,12 +59,12 @@ class AcceptHeaderTest extends TestCase public function provideToStringData() { - return array( - array(array(), ''), - array(array(new AcceptHeaderItem('gzip')), 'gzip'), - array(array(new AcceptHeaderItem('gzip'), new AcceptHeaderItem('deflate'), new AcceptHeaderItem('sdch')), 'gzip,deflate,sdch'), - array(array(new AcceptHeaderItem('this;should,not=matter')), 'this;should,not=matter'), - ); + return [ + [[], ''], + [[new AcceptHeaderItem('gzip')], 'gzip'], + [[new AcceptHeaderItem('gzip'), new AcceptHeaderItem('deflate'), new AcceptHeaderItem('sdch')], 'gzip,deflate,sdch'], + [[new AcceptHeaderItem('this;should,not=matter')], 'this;should,not=matter'], + ]; } /** @@ -78,9 +78,9 @@ class AcceptHeaderTest extends TestCase public function provideFilterData() { - return array( - array('fr-FR,fr;q=0.8,en-US;q=0.6,en;q=0.4', '/fr.*/', array('fr-FR', 'fr')), - ); + return [ + ['fr-FR,fr;q=0.8,en-US;q=0.6,en;q=0.4', '/fr.*/', ['fr-FR', 'fr']], + ]; } /** @@ -94,10 +94,37 @@ class AcceptHeaderTest extends TestCase public function provideSortingData() { - return array( - 'quality has priority' => array('*;q=0.3,ISO-8859-1,utf-8;q=0.7', array('ISO-8859-1', 'utf-8', '*')), - 'order matters when q is equal' => array('*;q=0.3,ISO-8859-1;q=0.7,utf-8;q=0.7', array('ISO-8859-1', 'utf-8', '*')), - 'order matters when q is equal2' => array('*;q=0.3,utf-8;q=0.7,ISO-8859-1;q=0.7', array('utf-8', 'ISO-8859-1', '*')), - ); + return [ + 'quality has priority' => ['*;q=0.3,ISO-8859-1,utf-8;q=0.7', ['ISO-8859-1', 'utf-8', '*']], + 'order matters when q is equal' => ['*;q=0.3,ISO-8859-1;q=0.7,utf-8;q=0.7', ['ISO-8859-1', 'utf-8', '*']], + 'order matters when q is equal2' => ['*;q=0.3,utf-8;q=0.7,ISO-8859-1;q=0.7', ['utf-8', 'ISO-8859-1', '*']], + ]; + } + + /** + * @dataProvider provideDefaultValueData + */ + public function testDefaultValue($acceptHeader, $value, $expectedQuality) + { + $header = AcceptHeader::fromString($acceptHeader); + $this->assertSame($expectedQuality, $header->get($value)->getQuality()); + } + + public function provideDefaultValueData() + { + yield ['text/plain;q=0.5, text/html, text/x-dvi;q=0.8, *;q=0.3', 'text/xml', 0.3]; + yield ['text/plain;q=0.5, text/html, text/x-dvi;q=0.8, */*;q=0.3', 'text/xml', 0.3]; + yield ['text/plain;q=0.5, text/html, text/x-dvi;q=0.8, */*;q=0.3', 'text/html', 1.0]; + yield ['text/plain;q=0.5, text/html, text/x-dvi;q=0.8, */*;q=0.3', 'text/plain', 0.5]; + yield ['text/plain;q=0.5, text/html, text/x-dvi;q=0.8, */*;q=0.3', '*', 0.3]; + yield ['text/plain;q=0.5, text/html, text/x-dvi;q=0.8, */*', '*', 1.0]; + yield ['text/plain;q=0.5, text/html, text/x-dvi;q=0.8, */*', 'text/xml', 1.0]; + yield ['text/plain;q=0.5, text/html, text/x-dvi;q=0.8, */*', 'text/*', 1.0]; + yield ['text/plain;q=0.5, text/html, text/*;q=0.8, */*', 'text/*', 0.8]; + yield ['text/plain;q=0.5, text/html, text/*;q=0.8, */*', 'text/html', 1.0]; + yield ['text/plain;q=0.5, text/html, text/*;q=0.8, */*', 'text/x-dvi', 0.8]; + yield ['*;q=0.3, ISO-8859-1;q=0.7, utf-8;q=0.7', '*', 0.3]; + yield ['*;q=0.3, ISO-8859-1;q=0.7, utf-8;q=0.7', 'utf-8', 0.7]; + yield ['*;q=0.3, ISO-8859-1;q=0.7, utf-8;q=0.7', 'SHIFT_JIS', 0.3]; } } diff --git a/vendor/symfony/http-foundation/Tests/ApacheRequestTest.php b/vendor/symfony/http-foundation/Tests/ApacheRequestTest.php index 157ab90ec59a2b0d2faf9108b0f5f04ec0580c3a..6fa3b88917055cb1a93fb334dac74fadc54c408a 100644 --- a/vendor/symfony/http-foundation/Tests/ApacheRequestTest.php +++ b/vendor/symfony/http-foundation/Tests/ApacheRequestTest.php @@ -31,63 +31,63 @@ class ApacheRequestTest extends TestCase public function provideServerVars() { - return array( - array( - array( + return [ + [ + [ 'REQUEST_URI' => '/foo/app_dev.php/bar', 'SCRIPT_NAME' => '/foo/app_dev.php', 'PATH_INFO' => '/bar', - ), + ], '/foo/app_dev.php/bar', '/foo/app_dev.php', '/bar', - ), - array( - array( + ], + [ + [ 'REQUEST_URI' => '/foo/bar', 'SCRIPT_NAME' => '/foo/app_dev.php', - ), + ], '/foo/bar', '/foo', '/bar', - ), - array( - array( + ], + [ + [ 'REQUEST_URI' => '/app_dev.php/foo/bar', 'SCRIPT_NAME' => '/app_dev.php', 'PATH_INFO' => '/foo/bar', - ), + ], '/app_dev.php/foo/bar', '/app_dev.php', '/foo/bar', - ), - array( - array( + ], + [ + [ 'REQUEST_URI' => '/foo/bar', 'SCRIPT_NAME' => '/app_dev.php', - ), + ], '/foo/bar', '', '/foo/bar', - ), - array( - array( + ], + [ + [ 'REQUEST_URI' => '/app_dev.php', 'SCRIPT_NAME' => '/app_dev.php', - ), + ], '/app_dev.php', '/app_dev.php', '/', - ), - array( - array( + ], + [ + [ 'REQUEST_URI' => '/', 'SCRIPT_NAME' => '/app_dev.php', - ), + ], '/', '', '/', - ), - ); + ], + ]; } } diff --git a/vendor/symfony/http-foundation/Tests/BinaryFileResponseTest.php b/vendor/symfony/http-foundation/Tests/BinaryFileResponseTest.php index 1b9e58991cc6d5ba033d7c753ee9391c942fadc5..734f8e84545b494239b5efd8992c3e18a0c523ba 100644 --- a/vendor/symfony/http-foundation/Tests/BinaryFileResponseTest.php +++ b/vendor/symfony/http-foundation/Tests/BinaryFileResponseTest.php @@ -22,35 +22,33 @@ class BinaryFileResponseTest extends ResponseTestCase public function testConstruction() { $file = __DIR__.'/../README.md'; - $response = new BinaryFileResponse($file, 404, array('X-Header' => 'Foo'), true, null, true, true); + $response = new BinaryFileResponse($file, 404, ['X-Header' => 'Foo'], true, null, true, true); $this->assertEquals(404, $response->getStatusCode()); $this->assertEquals('Foo', $response->headers->get('X-Header')); $this->assertTrue($response->headers->has('ETag')); $this->assertTrue($response->headers->has('Last-Modified')); $this->assertFalse($response->headers->has('Content-Disposition')); - $response = BinaryFileResponse::create($file, 404, array(), true, ResponseHeaderBag::DISPOSITION_INLINE); + $response = BinaryFileResponse::create($file, 404, [], true, ResponseHeaderBag::DISPOSITION_INLINE); $this->assertEquals(404, $response->getStatusCode()); $this->assertFalse($response->headers->has('ETag')); - $this->assertEquals('inline; filename="README.md"', $response->headers->get('Content-Disposition')); + $this->assertEquals('inline; filename=README.md', $response->headers->get('Content-Disposition')); } public function testConstructWithNonAsciiFilename() { touch(sys_get_temp_dir().'/fööö.html'); - $response = new BinaryFileResponse(sys_get_temp_dir().'/fööö.html', 200, array(), true, 'attachment'); + $response = new BinaryFileResponse(sys_get_temp_dir().'/fööö.html', 200, [], true, 'attachment'); @unlink(sys_get_temp_dir().'/fööö.html'); $this->assertSame('fööö.html', $response->getFile()->getFilename()); } - /** - * @expectedException \LogicException - */ public function testSetContent() { + $this->expectException('LogicException'); $response = new BinaryFileResponse(__FILE__); $response->setContent('foo'); } @@ -66,7 +64,7 @@ class BinaryFileResponseTest extends ResponseTestCase $response = new BinaryFileResponse(__FILE__); $response->setContentDisposition(ResponseHeaderBag::DISPOSITION_ATTACHMENT, 'föö.html'); - $this->assertSame('attachment; filename="f__.html"; filename*=utf-8\'\'f%C3%B6%C3%B6.html', $response->headers->get('Content-Disposition')); + $this->assertSame('attachment; filename=f__.html; filename*=utf-8\'\'f%C3%B6%C3%B6.html', $response->headers->get('Content-Disposition')); } public function testSetContentDispositionGeneratesSafeFallbackFilenameForWronglyEncodedFilename() @@ -77,7 +75,7 @@ class BinaryFileResponseTest extends ResponseTestCase $response->setContentDisposition(ResponseHeaderBag::DISPOSITION_ATTACHMENT, $iso88591EncodedFilename); // the parameter filename* is invalid in this case (rawurldecode('f%F6%F6') does not provide a UTF-8 string but an ISO-8859-1 encoded one) - $this->assertSame('attachment; filename="f__.html"; filename*=utf-8\'\'f%F6%F6.html', $response->headers->get('Content-Disposition')); + $this->assertSame('attachment; filename=f__.html; filename*=utf-8\'\'f%F6%F6.html', $response->headers->get('Content-Disposition')); } /** @@ -85,7 +83,7 @@ class BinaryFileResponseTest extends ResponseTestCase */ public function testRequests($requestRange, $offset, $length, $responseRange) { - $response = BinaryFileResponse::create(__DIR__.'/File/Fixtures/test.gif', 200, array('Content-Type' => 'application/octet-stream'))->setAutoEtag(); + $response = BinaryFileResponse::create(__DIR__.'/File/Fixtures/test.gif', 200, ['Content-Type' => 'application/octet-stream'])->setAutoEtag(); // do a request to get the ETag $request = Request::create('/'); @@ -109,7 +107,7 @@ class BinaryFileResponseTest extends ResponseTestCase $this->assertEquals(206, $response->getStatusCode()); $this->assertEquals($responseRange, $response->headers->get('Content-Range')); - $this->assertSame($length, $response->headers->get('Content-Length')); + $this->assertSame((string) $length, $response->headers->get('Content-Length')); } /** @@ -117,7 +115,7 @@ class BinaryFileResponseTest extends ResponseTestCase */ public function testRequestsWithoutEtag($requestRange, $offset, $length, $responseRange) { - $response = BinaryFileResponse::create(__DIR__.'/File/Fixtures/test.gif', 200, array('Content-Type' => 'application/octet-stream')); + $response = BinaryFileResponse::create(__DIR__.'/File/Fixtures/test.gif', 200, ['Content-Type' => 'application/octet-stream']); // do a request to get the LastModified $request = Request::create('/'); @@ -145,19 +143,19 @@ class BinaryFileResponseTest extends ResponseTestCase public function provideRanges() { - return array( - array('bytes=1-4', 1, 4, 'bytes 1-4/35'), - array('bytes=-5', 30, 5, 'bytes 30-34/35'), - array('bytes=30-', 30, 5, 'bytes 30-34/35'), - array('bytes=30-30', 30, 1, 'bytes 30-30/35'), - array('bytes=30-34', 30, 5, 'bytes 30-34/35'), - ); + return [ + ['bytes=1-4', 1, 4, 'bytes 1-4/35'], + ['bytes=-5', 30, 5, 'bytes 30-34/35'], + ['bytes=30-', 30, 5, 'bytes 30-34/35'], + ['bytes=30-30', 30, 1, 'bytes 30-30/35'], + ['bytes=30-34', 30, 5, 'bytes 30-34/35'], + ]; } public function testRangeRequestsWithoutLastModifiedDate() { // prevent auto last modified - $response = BinaryFileResponse::create(__DIR__.'/File/Fixtures/test.gif', 200, array('Content-Type' => 'application/octet-stream'), true, null, false, false); + $response = BinaryFileResponse::create(__DIR__.'/File/Fixtures/test.gif', 200, ['Content-Type' => 'application/octet-stream'], true, null, false, false); // prepare a request for a range of the testing file $request = Request::create('/'); @@ -178,7 +176,7 @@ class BinaryFileResponseTest extends ResponseTestCase */ public function testFullFileRequests($requestRange) { - $response = BinaryFileResponse::create(__DIR__.'/File/Fixtures/test.gif', 200, array('Content-Type' => 'application/octet-stream'))->setAutoEtag(); + $response = BinaryFileResponse::create(__DIR__.'/File/Fixtures/test.gif', 200, ['Content-Type' => 'application/octet-stream'])->setAutoEtag(); // prepare a request for a range of the testing file $request = Request::create('/'); @@ -198,14 +196,27 @@ class BinaryFileResponseTest extends ResponseTestCase public function provideFullFileRanges() { - return array( - array('bytes=0-'), - array('bytes=0-34'), - array('bytes=-35'), + return [ + ['bytes=0-'], + ['bytes=0-34'], + ['bytes=-35'], // Syntactical invalid range-request should also return the full resource - array('bytes=20-10'), - array('bytes=50-40'), - ); + ['bytes=20-10'], + ['bytes=50-40'], + ]; + } + + public function testUnpreparedResponseSendsFullFile() + { + $response = BinaryFileResponse::create(__DIR__.'/File/Fixtures/test.gif', 200); + + $data = file_get_contents(__DIR__.'/File/Fixtures/test.gif'); + + $this->expectOutputString($data); + $response = clone $response; + $response->sendContent(); + + $this->assertEquals(200, $response->getStatusCode()); } /** @@ -213,7 +224,7 @@ class BinaryFileResponseTest extends ResponseTestCase */ public function testInvalidRequests($requestRange) { - $response = BinaryFileResponse::create(__DIR__.'/File/Fixtures/test.gif', 200, array('Content-Type' => 'application/octet-stream'))->setAutoEtag(); + $response = BinaryFileResponse::create(__DIR__.'/File/Fixtures/test.gif', 200, ['Content-Type' => 'application/octet-stream'])->setAutoEtag(); // prepare a request for a range of the testing file $request = Request::create('/'); @@ -229,10 +240,10 @@ class BinaryFileResponseTest extends ResponseTestCase public function provideInvalidRanges() { - return array( - array('bytes=-40'), - array('bytes=30-40'), - ); + return [ + ['bytes=-40'], + ['bytes=30-40'], + ]; } /** @@ -244,21 +255,21 @@ class BinaryFileResponseTest extends ResponseTestCase $request->headers->set('X-Sendfile-Type', 'X-Sendfile'); BinaryFileResponse::trustXSendfileTypeHeader(); - $response = BinaryFileResponse::create($file, 200, array('Content-Type' => 'application/octet-stream')); + $response = BinaryFileResponse::create($file, 200, ['Content-Type' => 'application/octet-stream']); $response->prepare($request); $this->expectOutputString(''); $response->sendContent(); - $this->assertContains('README.md', $response->headers->get('X-Sendfile')); + $this->assertStringContainsString('README.md', $response->headers->get('X-Sendfile')); } public function provideXSendfileFiles() { - return array( - array(__DIR__.'/../README.md'), - array('file://'.__DIR__.'/../README.md'), - ); + return [ + [__DIR__.'/../README.md'], + ['file://'.__DIR__.'/../README.md'], + ]; } /** @@ -273,7 +284,7 @@ class BinaryFileResponseTest extends ResponseTestCase $file = new FakeFile($realpath, __DIR__.'/File/Fixtures/test'); BinaryFileResponse::trustXSendfileTypeHeader(); - $response = new BinaryFileResponse($file, 200, array('Content-Type' => 'application/octet-stream')); + $response = new BinaryFileResponse($file, 200, ['Content-Type' => 'application/octet-stream']); $reflection = new \ReflectionObject($response); $property = $reflection->getProperty('file'); $property->setAccessible(true); @@ -292,7 +303,7 @@ class BinaryFileResponseTest extends ResponseTestCase $realPath = realpath($path); $this->assertFileExists($realPath); - $response = new BinaryFileResponse($realPath, 200, array('Content-Type' => 'application/octet-stream')); + $response = new BinaryFileResponse($realPath, 200, ['Content-Type' => 'application/octet-stream']); $response->deleteFileAfterSend(true); $response->prepare($request); @@ -304,7 +315,7 @@ class BinaryFileResponseTest extends ResponseTestCase public function testAcceptRangeOnUnsafeMethods() { $request = Request::create('/', 'POST'); - $response = BinaryFileResponse::create(__DIR__.'/File/Fixtures/test.gif', 200, array('Content-Type' => 'application/octet-stream')); + $response = BinaryFileResponse::create(__DIR__.'/File/Fixtures/test.gif', 200, ['Content-Type' => 'application/octet-stream']); $response->prepare($request); $this->assertEquals('none', $response->headers->get('Accept-Ranges')); @@ -313,7 +324,7 @@ class BinaryFileResponseTest extends ResponseTestCase public function testAcceptRangeNotOverriden() { $request = Request::create('/', 'POST'); - $response = BinaryFileResponse::create(__DIR__.'/File/Fixtures/test.gif', 200, array('Content-Type' => 'application/octet-stream')); + $response = BinaryFileResponse::create(__DIR__.'/File/Fixtures/test.gif', 200, ['Content-Type' => 'application/octet-stream']); $response->headers->set('Accept-Ranges', 'foo'); $response->prepare($request); @@ -322,16 +333,18 @@ class BinaryFileResponseTest extends ResponseTestCase public function getSampleXAccelMappings() { - return array( - array('/var/www/var/www/files/foo.txt', '/var/www/=/files/', '/files/var/www/files/foo.txt'), - array('/home/foo/bar.txt', '/var/www/=/files/,/home/foo/=/baz/', '/baz/bar.txt'), - ); + return [ + ['/var/www/var/www/files/foo.txt', '/var/www/=/files/', '/files/var/www/files/foo.txt'], + ['/home/Foo/bar.txt', '/var/www/=/files/,/home/Foo/=/baz/', '/baz/bar.txt'], + ['/home/Foo/bar.txt', '"/var/www/"="/files/", "/home/Foo/"="/baz/"', '/baz/bar.txt'], + ['/tmp/bar.txt', '"/var/www/"="/files/", "/home/Foo/"="/baz/"', null], + ]; } public function testStream() { $request = Request::create('/'); - $response = new BinaryFileResponse(new Stream(__DIR__.'/../README.md'), 200, array('Content-Type' => 'text/plain')); + $response = new BinaryFileResponse(new Stream(__DIR__.'/../README.md'), 200, ['Content-Type' => 'text/plain']); $response->prepare($request); $this->assertNull($response->headers->get('Content-Length')); @@ -339,10 +352,10 @@ class BinaryFileResponseTest extends ResponseTestCase protected function provideResponse() { - return new BinaryFileResponse(__DIR__.'/../README.md', 200, array('Content-Type' => 'application/octet-stream')); + return new BinaryFileResponse(__DIR__.'/../README.md', 200, ['Content-Type' => 'application/octet-stream']); } - public static function tearDownAfterClass() + public static function tearDownAfterClass(): void { $path = __DIR__.'/../Fixtures/to_delete'; if (file_exists($path)) { diff --git a/vendor/symfony/http-foundation/Tests/CookieTest.php b/vendor/symfony/http-foundation/Tests/CookieTest.php index 070b7dd4290e64271a440674efb7da53c86b9c5d..55287e082d996657e8960fa5280cbee17d77410e 100644 --- a/vendor/symfony/http-foundation/Tests/CookieTest.php +++ b/vendor/symfony/http-foundation/Tests/CookieTest.php @@ -24,41 +24,52 @@ use Symfony\Component\HttpFoundation\Cookie; */ class CookieTest extends TestCase { - public function invalidNames() + public function namesWithSpecialCharacters() { - return array( - array(''), - array(',MyName'), - array(';MyName'), - array(' MyName'), - array("\tMyName"), - array("\rMyName"), - array("\nMyName"), - array("\013MyName"), - array("\014MyName"), - ); + return [ + [',MyName'], + [';MyName'], + [' MyName'], + ["\tMyName"], + ["\rMyName"], + ["\nMyName"], + ["\013MyName"], + ["\014MyName"], + ]; } /** - * @dataProvider invalidNames - * @expectedException \InvalidArgumentException + * @dataProvider namesWithSpecialCharacters */ - public function testInstantiationThrowsExceptionIfCookieNameContainsInvalidCharacters($name) + public function testInstantiationThrowsExceptionIfRawCookieNameContainsSpecialCharacters($name) { - new Cookie($name); + $this->expectException('InvalidArgumentException'); + Cookie::create($name, null, 0, null, null, null, false, true); } /** - * @expectedException \InvalidArgumentException + * @dataProvider namesWithSpecialCharacters */ + public function testInstantiationSucceedNonRawCookieNameContainsSpecialCharacters($name) + { + $this->assertInstanceOf(Cookie::class, Cookie::create($name)); + } + + public function testInstantiationThrowsExceptionIfCookieNameIsEmpty() + { + $this->expectException('InvalidArgumentException'); + Cookie::create(''); + } + public function testInvalidExpiration() { - new Cookie('MyCookie', 'foo', 'bar'); + $this->expectException('InvalidArgumentException'); + Cookie::create('MyCookie', 'foo', 'bar'); } public function testNegativeExpirationIsNotPossible() { - $cookie = new Cookie('foo', 'bar', -100); + $cookie = Cookie::create('foo', 'bar', -100); $this->assertSame(0, $cookie->getExpiresTime()); } @@ -66,32 +77,32 @@ class CookieTest extends TestCase public function testGetValue() { $value = 'MyValue'; - $cookie = new Cookie('MyCookie', $value); + $cookie = Cookie::create('MyCookie', $value); $this->assertSame($value, $cookie->getValue(), '->getValue() returns the proper value'); } public function testGetPath() { - $cookie = new Cookie('foo', 'bar'); + $cookie = Cookie::create('foo', 'bar'); $this->assertSame('/', $cookie->getPath(), '->getPath() returns / as the default path'); } public function testGetExpiresTime() { - $cookie = new Cookie('foo', 'bar'); + $cookie = Cookie::create('foo', 'bar'); $this->assertEquals(0, $cookie->getExpiresTime(), '->getExpiresTime() returns the default expire date'); - $cookie = new Cookie('foo', 'bar', $expire = time() + 3600); + $cookie = Cookie::create('foo', 'bar', $expire = time() + 3600); $this->assertEquals($expire, $cookie->getExpiresTime(), '->getExpiresTime() returns the expire date'); } public function testGetExpiresTimeIsCastToInt() { - $cookie = new Cookie('foo', 'bar', 3600.9); + $cookie = Cookie::create('foo', 'bar', 3600.9); $this->assertSame(3600, $cookie->getExpiresTime(), '->getExpiresTime() returns the expire date as an integer'); } @@ -99,18 +110,15 @@ class CookieTest extends TestCase public function testConstructorWithDateTime() { $expire = new \DateTime(); - $cookie = new Cookie('foo', 'bar', $expire); + $cookie = Cookie::create('foo', 'bar', $expire); $this->assertEquals($expire->format('U'), $cookie->getExpiresTime(), '->getExpiresTime() returns the expire date'); } - /** - * @requires PHP 5.5 - */ public function testConstructorWithDateTimeImmutable() { $expire = new \DateTimeImmutable(); - $cookie = new Cookie('foo', 'bar', $expire); + $cookie = Cookie::create('foo', 'bar', $expire); $this->assertEquals($expire->format('U'), $cookie->getExpiresTime(), '->getExpiresTime() returns the expire date'); } @@ -118,92 +126,107 @@ class CookieTest extends TestCase public function testGetExpiresTimeWithStringValue() { $value = '+1 day'; - $cookie = new Cookie('foo', 'bar', $value); + $cookie = Cookie::create('foo', 'bar', $value); $expire = strtotime($value); - $this->assertEquals($expire, $cookie->getExpiresTime(), '->getExpiresTime() returns the expire date', 1); + $this->assertEqualsWithDelta($expire, $cookie->getExpiresTime(), 1, '->getExpiresTime() returns the expire date'); } public function testGetDomain() { - $cookie = new Cookie('foo', 'bar', 0, '/', '.myfoodomain.com'); + $cookie = Cookie::create('foo', 'bar', 0, '/', '.myfoodomain.com'); $this->assertEquals('.myfoodomain.com', $cookie->getDomain(), '->getDomain() returns the domain name on which the cookie is valid'); } public function testIsSecure() { - $cookie = new Cookie('foo', 'bar', 0, '/', '.myfoodomain.com', true); + $cookie = Cookie::create('foo', 'bar', 0, '/', '.myfoodomain.com', true); $this->assertTrue($cookie->isSecure(), '->isSecure() returns whether the cookie is transmitted over HTTPS'); } public function testIsHttpOnly() { - $cookie = new Cookie('foo', 'bar', 0, '/', '.myfoodomain.com', false, true); + $cookie = Cookie::create('foo', 'bar', 0, '/', '.myfoodomain.com', false, true); $this->assertTrue($cookie->isHttpOnly(), '->isHttpOnly() returns whether the cookie is only transmitted over HTTP'); } public function testCookieIsNotCleared() { - $cookie = new Cookie('foo', 'bar', time() + 3600 * 24); + $cookie = Cookie::create('foo', 'bar', time() + 3600 * 24); $this->assertFalse($cookie->isCleared(), '->isCleared() returns false if the cookie did not expire yet'); } public function testCookieIsCleared() { - $cookie = new Cookie('foo', 'bar', time() - 20); + $cookie = Cookie::create('foo', 'bar', time() - 20); $this->assertTrue($cookie->isCleared(), '->isCleared() returns true if the cookie has expired'); + + $cookie = Cookie::create('foo', 'bar'); + + $this->assertFalse($cookie->isCleared()); + + $cookie = Cookie::create('foo', 'bar'); + + $this->assertFalse($cookie->isCleared()); + + $cookie = Cookie::create('foo', 'bar', -1); + + $this->assertFalse($cookie->isCleared()); } public function testToString() { - $cookie = new Cookie('foo', 'bar', $expire = strtotime('Fri, 20-May-2011 15:25:52 GMT'), '/', '.myfoodomain.com', true); - $this->assertEquals('foo=bar; expires=Fri, 20-May-2011 15:25:52 GMT; max-age='.($expire - time()).'; path=/; domain=.myfoodomain.com; secure; httponly', (string) $cookie, '->__toString() returns string representation of the cookie'); + $cookie = Cookie::create('foo', 'bar', $expire = strtotime('Fri, 20-May-2011 15:25:52 GMT'), '/', '.myfoodomain.com', true, true, false, null); + $this->assertEquals('foo=bar; expires=Fri, 20-May-2011 15:25:52 GMT; Max-Age=0; path=/; domain=.myfoodomain.com; secure; httponly', (string) $cookie, '->__toString() returns string representation of the cookie'); - $cookie = new Cookie('foo', 'bar with white spaces', strtotime('Fri, 20-May-2011 15:25:52 GMT'), '/', '.myfoodomain.com', true); - $this->assertEquals('foo=bar%20with%20white%20spaces; expires=Fri, 20-May-2011 15:25:52 GMT; max-age='.($expire - time()).'; path=/; domain=.myfoodomain.com; secure; httponly', (string) $cookie, '->__toString() encodes the value of the cookie according to RFC 3986 (white space = %20)'); + $cookie = Cookie::create('foo', 'bar with white spaces', strtotime('Fri, 20-May-2011 15:25:52 GMT'), '/', '.myfoodomain.com', true, true, false, null); + $this->assertEquals('foo=bar%20with%20white%20spaces; expires=Fri, 20-May-2011 15:25:52 GMT; Max-Age=0; path=/; domain=.myfoodomain.com; secure; httponly', (string) $cookie, '->__toString() encodes the value of the cookie according to RFC 3986 (white space = %20)'); - $cookie = new Cookie('foo', null, 1, '/admin/', '.myfoodomain.com'); - $this->assertEquals('foo=deleted; expires='.gmdate('D, d-M-Y H:i:s T', $expire = time() - 31536001).'; max-age='.($expire - time()).'; path=/admin/; domain=.myfoodomain.com; httponly', (string) $cookie, '->__toString() returns string representation of a cleared cookie if value is NULL'); + $cookie = Cookie::create('foo', null, 1, '/admin/', '.myfoodomain.com', false, true, false, null); + $this->assertEquals('foo=deleted; expires='.gmdate('D, d-M-Y H:i:s T', $expire = time() - 31536001).'; Max-Age=0; path=/admin/; domain=.myfoodomain.com; httponly', (string) $cookie, '->__toString() returns string representation of a cleared cookie if value is NULL'); - $cookie = new Cookie('foo', 'bar', 0, '/', ''); - $this->assertEquals('foo=bar; path=/; httponly', (string) $cookie); + $cookie = Cookie::create('foo', 'bar'); + $this->assertEquals('foo=bar; path=/; httponly; samesite=lax', (string) $cookie); } public function testRawCookie() { - $cookie = new Cookie('foo', 'b a r', 0, '/', null, false, false); + $cookie = Cookie::create('foo', 'b a r', 0, '/', null, false, false, false, null); $this->assertFalse($cookie->isRaw()); $this->assertEquals('foo=b%20a%20r; path=/', (string) $cookie); - $cookie = new Cookie('foo', 'b+a+r', 0, '/', null, false, false, true); + $cookie = Cookie::create('foo', 'b+a+r', 0, '/', null, false, false, true, null); $this->assertTrue($cookie->isRaw()); $this->assertEquals('foo=b+a+r; path=/', (string) $cookie); } public function testGetMaxAge() { - $cookie = new Cookie('foo', 'bar'); + $cookie = Cookie::create('foo', 'bar'); $this->assertEquals(0, $cookie->getMaxAge()); - $cookie = new Cookie('foo', 'bar', $expire = time() + 100); + $cookie = Cookie::create('foo', 'bar', $expire = time() + 100); $this->assertEquals($expire - time(), $cookie->getMaxAge()); - $cookie = new Cookie('foo', 'bar', $expire = time() - 100); - $this->assertEquals($expire - time(), $cookie->getMaxAge()); + $cookie = Cookie::create('foo', 'bar', $expire = time() - 100); + $this->assertEquals(0, $cookie->getMaxAge()); } public function testFromString() { $cookie = Cookie::fromString('foo=bar; expires=Fri, 20-May-2011 15:25:52 GMT; path=/; domain=.myfoodomain.com; secure; httponly'); - $this->assertEquals(new Cookie('foo', 'bar', strtotime('Fri, 20-May-2011 15:25:52 GMT'), '/', '.myfoodomain.com', true, true, true), $cookie); + $this->assertEquals(Cookie::create('foo', 'bar', strtotime('Fri, 20-May-2011 15:25:52 GMT'), '/', '.myfoodomain.com', true, true, true, null), $cookie); $cookie = Cookie::fromString('foo=bar', true); - $this->assertEquals(new Cookie('foo', 'bar', 0, '/', null, false, false), $cookie); + $this->assertEquals(Cookie::create('foo', 'bar', 0, '/', null, false, false, false, null), $cookie); + + $cookie = Cookie::fromString('foo', true); + $this->assertEquals(Cookie::create('foo', null, 0, '/', null, false, false, false, null), $cookie); } public function testFromStringWithHttpOnly() @@ -215,9 +238,27 @@ class CookieTest extends TestCase $this->assertFalse($cookie->isHttpOnly()); } - public function testSameSiteAttributeIsCaseInsensitive() + public function testSameSiteAttribute() { $cookie = new Cookie('foo', 'bar', 0, '/', null, false, true, false, 'Lax'); $this->assertEquals('lax', $cookie->getSameSite()); + + $cookie = new Cookie('foo', 'bar', 0, '/', null, false, true, false, ''); + $this->assertNull($cookie->getSameSite()); + } + + public function testSetSecureDefault() + { + $cookie = Cookie::create('foo', 'bar'); + + $this->assertFalse($cookie->isSecure()); + + $cookie->setSecureDefault(true); + + $this->assertTrue($cookie->isSecure()); + + $cookie->setSecureDefault(false); + + $this->assertFalse($cookie->isSecure()); } } diff --git a/vendor/symfony/http-foundation/Tests/ExpressionRequestMatcherTest.php b/vendor/symfony/http-foundation/Tests/ExpressionRequestMatcherTest.php index 1152e46c0be7e5e9adef75a28f1ba4856e0672c8..8a389329e47ce7c92872689108f1c1d58a63ad36 100644 --- a/vendor/symfony/http-foundation/Tests/ExpressionRequestMatcherTest.php +++ b/vendor/symfony/http-foundation/Tests/ExpressionRequestMatcherTest.php @@ -18,11 +18,9 @@ use Symfony\Component\HttpFoundation\Request; class ExpressionRequestMatcherTest extends TestCase { - /** - * @expectedException \LogicException - */ public function testWhenNoExpressionIsSet() { + $this->expectException('LogicException'); $expressionRequestMatcher = new ExpressionRequestMatcher(); $expressionRequestMatcher->matches(new Request()); } @@ -55,15 +53,15 @@ class ExpressionRequestMatcherTest extends TestCase public function provideExpressions() { - return array( - array('request.getMethod() == method', true), - array('request.getPathInfo() == path', true), - array('request.getHost() == host', true), - array('request.getClientIp() == ip', true), - array('request.attributes.all() == attributes', true), - array('request.getMethod() == method && request.getPathInfo() == path && request.getHost() == host && request.getClientIp() == ip && request.attributes.all() == attributes', true), - array('request.getMethod() != method', false), - array('request.getMethod() != method && request.getPathInfo() == path && request.getHost() == host && request.getClientIp() == ip && request.attributes.all() == attributes', false), - ); + return [ + ['request.getMethod() == method', true], + ['request.getPathInfo() == path', true], + ['request.getHost() == host', true], + ['request.getClientIp() == ip', true], + ['request.attributes.all() == attributes', true], + ['request.getMethod() == method && request.getPathInfo() == path && request.getHost() == host && request.getClientIp() == ip && request.attributes.all() == attributes', true], + ['request.getMethod() != method', false], + ['request.getMethod() != method && request.getPathInfo() == path && request.getHost() == host && request.getClientIp() == ip && request.attributes.all() == attributes', false], + ]; } } diff --git a/vendor/symfony/http-foundation/Tests/File/FileTest.php b/vendor/symfony/http-foundation/Tests/File/FileTest.php index dbd9c44bd802cd53b92ec59189f36464b4ede843..2ef259ed1bd5e10f1b694faa5ee129883222acf5 100644 --- a/vendor/symfony/http-foundation/Tests/File/FileTest.php +++ b/vendor/symfony/http-foundation/Tests/File/FileTest.php @@ -13,8 +13,10 @@ namespace Symfony\Component\HttpFoundation\Tests\File; use PHPUnit\Framework\TestCase; use Symfony\Component\HttpFoundation\File\File; -use Symfony\Component\HttpFoundation\File\MimeType\MimeTypeGuesser; +/** + * @requires extension fileinfo + */ class FileTest extends TestCase { protected $file; @@ -22,49 +24,24 @@ class FileTest extends TestCase public function testGetMimeTypeUsesMimeTypeGuessers() { $file = new File(__DIR__.'/Fixtures/test.gif'); - $guesser = $this->createMockGuesser($file->getPathname(), 'image/gif'); - - MimeTypeGuesser::getInstance()->register($guesser); - $this->assertEquals('image/gif', $file->getMimeType()); } public function testGuessExtensionWithoutGuesser() { $file = new File(__DIR__.'/Fixtures/directory/.empty'); - $this->assertNull($file->guessExtension()); } public function testGuessExtensionIsBasedOnMimeType() { $file = new File(__DIR__.'/Fixtures/test'); - $guesser = $this->createMockGuesser($file->getPathname(), 'image/gif'); - - MimeTypeGuesser::getInstance()->register($guesser); - $this->assertEquals('gif', $file->guessExtension()); } - /** - * @requires extension fileinfo - */ - public function testGuessExtensionWithReset() - { - $file = new File(__DIR__.'/Fixtures/other-file.example'); - $guesser = $this->createMockGuesser($file->getPathname(), 'image/gif'); - MimeTypeGuesser::getInstance()->register($guesser); - - $this->assertEquals('gif', $file->guessExtension()); - - MimeTypeGuesser::reset(); - - $this->assertNull($file->guessExtension()); - } - public function testConstructWhenFileNotExists() { - $this->{method_exists($this, $_ = 'expectException') ? $_ : 'setExpectedException'}('Symfony\Component\HttpFoundation\File\Exception\FileNotFoundException'); + $this->expectException('Symfony\Component\HttpFoundation\File\Exception\FileNotFoundException'); new File(__DIR__.'/Fixtures/not_here'); } @@ -110,14 +87,14 @@ class FileTest extends TestCase public function getFilenameFixtures() { - return array( - array('original.gif', 'original.gif'), - array('..\\..\\original.gif', 'original.gif'), - array('../../original.gif', 'original.gif'), - array('файлfile.gif', 'файлfile.gif'), - array('..\\..\\файлfile.gif', 'файлfile.gif'), - array('../../файлfile.gif', 'файлfile.gif'), - ); + return [ + ['original.gif', 'original.gif'], + ['..\\..\\original.gif', 'original.gif'], + ['../../original.gif', 'original.gif'], + ['файлfile.gif', 'файлfile.gif'], + ['..\\..\\файлfile.gif', 'файлfile.gif'], + ['../../файлfile.gif', 'файлfile.gif'], + ]; } /** @@ -164,17 +141,4 @@ class FileTest extends TestCase @unlink($targetPath); @rmdir($targetDir); } - - protected function createMockGuesser($path, $mimeType) - { - $guesser = $this->getMockBuilder('Symfony\Component\HttpFoundation\File\MimeType\MimeTypeGuesserInterface')->getMock(); - $guesser - ->expects($this->once()) - ->method('guess') - ->with($this->equalTo($path)) - ->will($this->returnValue($mimeType)) - ; - - return $guesser; - } } diff --git a/vendor/symfony/http-foundation/Tests/File/Fixtures/case-sensitive-mime-type.xlsm b/vendor/symfony/http-foundation/Tests/File/Fixtures/case-sensitive-mime-type.xlsm new file mode 100644 index 0000000000000000000000000000000000000000..94d85e6132c553225a1628f056151bee22f5b352 Binary files /dev/null and b/vendor/symfony/http-foundation/Tests/File/Fixtures/case-sensitive-mime-type.xlsm differ diff --git a/vendor/symfony/http-foundation/Tests/File/MimeType/MimeTypeTest.php b/vendor/symfony/http-foundation/Tests/File/MimeType/MimeTypeTest.php index b3f1f026a558fafdf304286a9093d0463437e183..a43ce819fb1c0a44d13c7f45334fa1d8b9e256af 100644 --- a/vendor/symfony/http-foundation/Tests/File/MimeType/MimeTypeTest.php +++ b/vendor/symfony/http-foundation/Tests/File/MimeType/MimeTypeTest.php @@ -12,16 +12,15 @@ namespace Symfony\Component\HttpFoundation\Tests\File\MimeType; use PHPUnit\Framework\TestCase; -use Symfony\Component\HttpFoundation\File\MimeType\MimeTypeGuesser; use Symfony\Component\HttpFoundation\File\MimeType\FileBinaryMimeTypeGuesser; +use Symfony\Component\HttpFoundation\File\MimeType\MimeTypeGuesser; /** * @requires extension fileinfo + * @group legacy */ class MimeTypeTest extends TestCase { - protected $path; - public function testGuessImageWithoutExtension() { $this->assertEquals('image/gif', MimeTypeGuesser::getInstance()->guess(__DIR__.'/../Fixtures/test')); @@ -29,7 +28,7 @@ class MimeTypeTest extends TestCase public function testGuessImageWithDirectory() { - $this->{method_exists($this, $_ = 'expectException') ? $_ : 'setExpectedException'}('Symfony\Component\HttpFoundation\File\Exception\FileNotFoundException'); + $this->expectException('Symfony\Component\HttpFoundation\File\Exception\FileNotFoundException'); MimeTypeGuesser::getInstance()->guess(__DIR__.'/../Fixtures/directory'); } @@ -53,13 +52,13 @@ class MimeTypeTest extends TestCase public function testGuessWithIncorrectPath() { - $this->{method_exists($this, $_ = 'expectException') ? $_ : 'setExpectedException'}('Symfony\Component\HttpFoundation\File\Exception\FileNotFoundException'); + $this->expectException('Symfony\Component\HttpFoundation\File\Exception\FileNotFoundException'); MimeTypeGuesser::getInstance()->guess(__DIR__.'/../Fixtures/not_here'); } public function testGuessWithNonReadablePath() { - if ('\\' === DIRECTORY_SEPARATOR) { + if ('\\' === \DIRECTORY_SEPARATOR) { $this->markTestSkipped('Can not verify chmod operations on Windows'); } @@ -72,14 +71,14 @@ class MimeTypeTest extends TestCase @chmod($path, 0333); if ('0333' == substr(sprintf('%o', fileperms($path)), -4)) { - $this->{method_exists($this, $_ = 'expectException') ? $_ : 'setExpectedException'}('Symfony\Component\HttpFoundation\File\Exception\AccessDeniedException'); + $this->expectException('Symfony\Component\HttpFoundation\File\Exception\AccessDeniedException'); MimeTypeGuesser::getInstance()->guess($path); } else { $this->markTestSkipped('Can not verify chmod operations, change of file permissions failed'); } } - public static function tearDownAfterClass() + public static function tearDownAfterClass(): void { $path = __DIR__.'/../Fixtures/to_delete'; if (file_exists($path)) { diff --git a/vendor/symfony/http-foundation/Tests/File/UploadedFileTest.php b/vendor/symfony/http-foundation/Tests/File/UploadedFileTest.php index 36f122fe7922393b5212434d87e9ee3a9a27a82f..b31bfcb5bb1bebe69d6119b5e3a64051a25885cf 100644 --- a/vendor/symfony/http-foundation/Tests/File/UploadedFileTest.php +++ b/vendor/symfony/http-foundation/Tests/File/UploadedFileTest.php @@ -12,11 +12,19 @@ namespace Symfony\Component\HttpFoundation\Tests\File; use PHPUnit\Framework\TestCase; +use Symfony\Component\HttpFoundation\File\Exception\CannotWriteFileException; +use Symfony\Component\HttpFoundation\File\Exception\ExtensionFileException; +use Symfony\Component\HttpFoundation\File\Exception\FileException; +use Symfony\Component\HttpFoundation\File\Exception\FormSizeFileException; +use Symfony\Component\HttpFoundation\File\Exception\IniSizeFileException; +use Symfony\Component\HttpFoundation\File\Exception\NoFileException; +use Symfony\Component\HttpFoundation\File\Exception\NoTmpDirFileException; +use Symfony\Component\HttpFoundation\File\Exception\PartialFileException; use Symfony\Component\HttpFoundation\File\UploadedFile; class UploadedFileTest extends TestCase { - protected function setUp() + protected function setUp(): void { if (!ini_get('file_uploads')) { $this->markTestSkipped('file_uploads is disabled in php.ini'); @@ -25,7 +33,7 @@ class UploadedFileTest extends TestCase public function testConstructWhenFileNotExists() { - $this->{method_exists($this, $_ = 'expectException') ? $_ : 'setExpectedException'}('Symfony\Component\HttpFoundation\File\Exception\FileNotFoundException'); + $this->expectException('Symfony\Component\HttpFoundation\File\Exception\FileNotFoundException'); new UploadedFile( __DIR__.'/Fixtures/not_here', @@ -40,13 +48,12 @@ class UploadedFileTest extends TestCase __DIR__.'/Fixtures/test.gif', 'original.gif', null, - filesize(__DIR__.'/Fixtures/test.gif'), UPLOAD_ERR_OK ); $this->assertEquals('application/octet-stream', $file->getClientMimeType()); - if (extension_loaded('fileinfo')) { + if (\extension_loaded('fileinfo')) { $this->assertEquals('image/gif', $file->getMimeType()); } } @@ -57,7 +64,6 @@ class UploadedFileTest extends TestCase __DIR__.'/Fixtures/.unknownextension', 'original.gif', null, - filesize(__DIR__.'/Fixtures/.unknownextension'), UPLOAD_ERR_OK ); @@ -70,7 +76,6 @@ class UploadedFileTest extends TestCase __DIR__.'/Fixtures/test.gif', 'original.gif', 'image/gif', - filesize(__DIR__.'/Fixtures/test.gif'), null ); @@ -83,20 +88,30 @@ class UploadedFileTest extends TestCase __DIR__.'/Fixtures/test.gif', 'original.gif', 'image/jpeg', - filesize(__DIR__.'/Fixtures/test.gif'), null ); $this->assertEquals('jpeg', $file->guessClientExtension()); } + public function testCaseSensitiveMimeType() + { + $file = new UploadedFile( + __DIR__.'/Fixtures/case-sensitive-mime-type.xlsm', + 'test.xlsm', + 'application/vnd.ms-excel.sheet.macroEnabled.12', + null + ); + + $this->assertEquals('xlsm', $file->guessClientExtension()); + } + public function testErrorIsOkByDefault() { $file = new UploadedFile( __DIR__.'/Fixtures/test.gif', 'original.gif', 'image/gif', - filesize(__DIR__.'/Fixtures/test.gif'), null ); @@ -109,7 +124,6 @@ class UploadedFileTest extends TestCase __DIR__.'/Fixtures/test.gif', 'original.gif', 'image/gif', - filesize(__DIR__.'/Fixtures/test.gif'), null ); @@ -122,29 +136,73 @@ class UploadedFileTest extends TestCase __DIR__.'/Fixtures/test.gif', 'original.gif', 'image/gif', - filesize(__DIR__.'/Fixtures/test.gif'), null ); $this->assertEquals('gif', $file->getClientOriginalExtension()); } - /** - * @expectedException \Symfony\Component\HttpFoundation\File\Exception\FileException - */ public function testMoveLocalFileIsNotAllowed() { + $this->expectException('Symfony\Component\HttpFoundation\File\Exception\FileException'); $file = new UploadedFile( __DIR__.'/Fixtures/test.gif', 'original.gif', 'image/gif', - filesize(__DIR__.'/Fixtures/test.gif'), UPLOAD_ERR_OK ); $movedFile = $file->move(__DIR__.'/Fixtures/directory'); } + public function failedUploadedFile() + { + foreach ([UPLOAD_ERR_INI_SIZE, UPLOAD_ERR_FORM_SIZE, UPLOAD_ERR_PARTIAL, UPLOAD_ERR_NO_FILE, UPLOAD_ERR_CANT_WRITE, UPLOAD_ERR_NO_TMP_DIR, UPLOAD_ERR_EXTENSION, -1] as $error) { + yield [new UploadedFile( + __DIR__.'/Fixtures/test.gif', + 'original.gif', + 'image/gif', + $error + )]; + } + } + + /** + * @dataProvider failedUploadedFile + */ + public function testMoveFailed(UploadedFile $file) + { + switch ($file->getError()) { + case UPLOAD_ERR_INI_SIZE: + $exceptionClass = IniSizeFileException::class; + break; + case UPLOAD_ERR_FORM_SIZE: + $exceptionClass = FormSizeFileException::class; + break; + case UPLOAD_ERR_PARTIAL: + $exceptionClass = PartialFileException::class; + break; + case UPLOAD_ERR_NO_FILE: + $exceptionClass = NoFileException::class; + break; + case UPLOAD_ERR_CANT_WRITE: + $exceptionClass = CannotWriteFileException::class; + break; + case UPLOAD_ERR_NO_TMP_DIR: + $exceptionClass = NoTmpDirFileException::class; + break; + case UPLOAD_ERR_EXTENSION: + $exceptionClass = ExtensionFileException::class; + break; + default: + $exceptionClass = FileException::class; + } + + $this->expectException($exceptionClass); + + $file->move(__DIR__.'/Fixtures/directory'); + } + public function testMoveLocalFileIsAllowedInTestMode() { $path = __DIR__.'/Fixtures/test.copy.gif'; @@ -158,7 +216,6 @@ class UploadedFileTest extends TestCase $path, 'original.gif', 'image/gif', - filesize($path), UPLOAD_ERR_OK, true ); @@ -177,9 +234,7 @@ class UploadedFileTest extends TestCase $file = new UploadedFile( __DIR__.'/Fixtures/test.gif', '../../original.gif', - 'image/gif', - filesize(__DIR__.'/Fixtures/test.gif'), - null + 'image/gif' ); $this->assertEquals('original.gif', $file->getClientOriginalName()); @@ -190,9 +245,7 @@ class UploadedFileTest extends TestCase $file = new UploadedFile( __DIR__.'/Fixtures/test.gif', 'original.gif', - 'image/gif', - filesize(__DIR__.'/Fixtures/test.gif'), - null + 'image/gif' ); $this->assertEquals(filesize(__DIR__.'/Fixtures/test.gif'), $file->getSize()); @@ -206,12 +259,45 @@ class UploadedFileTest extends TestCase $this->assertEquals(filesize(__DIR__.'/Fixtures/test'), $file->getSize()); } - public function testGetExtension() + /** + * @group legacy + * @expectedDeprecation Passing a size as 4th argument to the constructor of "Symfony\Component\HttpFoundation\File\UploadedFile" is deprecated since Symfony 4.1. + */ + public function testConstructDeprecatedSize() { $file = new UploadedFile( __DIR__.'/Fixtures/test.gif', 'original.gif', - null + 'image/gif', + filesize(__DIR__.'/Fixtures/test.gif'), + UPLOAD_ERR_OK, + false + ); + + $this->assertEquals(filesize(__DIR__.'/Fixtures/test.gif'), $file->getSize()); + } + + /** + * @group legacy + * @expectedDeprecation Passing a size as 4th argument to the constructor of "Symfony\Component\HttpFoundation\File\UploadedFile" is deprecated since Symfony 4.1. + */ + public function testConstructDeprecatedSizeWhenPassingOnlyThe4Needed() + { + $file = new UploadedFile( + __DIR__.'/Fixtures/test.gif', + 'original.gif', + 'image/gif', + filesize(__DIR__.'/Fixtures/test.gif') + ); + + $this->assertEquals(filesize(__DIR__.'/Fixtures/test.gif'), $file->getSize()); + } + + public function testGetExtension() + { + $file = new UploadedFile( + __DIR__.'/Fixtures/test.gif', + 'original.gif' ); $this->assertEquals('gif', $file->getExtension()); @@ -223,7 +309,6 @@ class UploadedFileTest extends TestCase __DIR__.'/Fixtures/test.gif', 'original.gif', null, - filesize(__DIR__.'/Fixtures/test.gif'), UPLOAD_ERR_OK, true ); @@ -240,7 +325,6 @@ class UploadedFileTest extends TestCase __DIR__.'/Fixtures/test.gif', 'original.gif', null, - filesize(__DIR__.'/Fixtures/test.gif'), $error ); @@ -249,13 +333,13 @@ class UploadedFileTest extends TestCase public function uploadedFileErrorProvider() { - return array( - array(UPLOAD_ERR_INI_SIZE), - array(UPLOAD_ERR_FORM_SIZE), - array(UPLOAD_ERR_PARTIAL), - array(UPLOAD_ERR_NO_TMP_DIR), - array(UPLOAD_ERR_EXTENSION), - ); + return [ + [UPLOAD_ERR_INI_SIZE], + [UPLOAD_ERR_FORM_SIZE], + [UPLOAD_ERR_PARTIAL], + [UPLOAD_ERR_NO_TMP_DIR], + [UPLOAD_ERR_EXTENSION], + ]; } public function testIsInvalidIfNotHttpUpload() @@ -264,10 +348,23 @@ class UploadedFileTest extends TestCase __DIR__.'/Fixtures/test.gif', 'original.gif', null, - filesize(__DIR__.'/Fixtures/test.gif'), UPLOAD_ERR_OK ); $this->assertFalse($file->isValid()); } + + public function testGetMaxFilesize() + { + $size = UploadedFile::getMaxFilesize(); + + $this->assertIsInt($size); + $this->assertGreaterThan(0, $size); + + if (0 === (int) ini_get('post_max_size') && 0 === (int) ini_get('upload_max_filesize')) { + $this->assertSame(PHP_INT_MAX, $size); + } else { + $this->assertLessThan(PHP_INT_MAX, $size); + } + } } diff --git a/vendor/symfony/http-foundation/Tests/FileBagTest.php b/vendor/symfony/http-foundation/Tests/FileBagTest.php index b1bbba0d3f57cc0db98d69bb2f319a414f3df923..bde664194b8574841d478a8d120de4d14f8e3011 100644 --- a/vendor/symfony/http-foundation/Tests/FileBagTest.php +++ b/vendor/symfony/http-foundation/Tests/FileBagTest.php @@ -23,93 +23,91 @@ use Symfony\Component\HttpFoundation\FileBag; */ class FileBagTest extends TestCase { - /** - * @expectedException \InvalidArgumentException - */ public function testFileMustBeAnArrayOrUploadedFile() { - new FileBag(array('file' => 'foo')); + $this->expectException('InvalidArgumentException'); + new FileBag(['file' => 'foo']); } public function testShouldConvertsUploadedFiles() { $tmpFile = $this->createTempFile(); - $file = new UploadedFile($tmpFile, basename($tmpFile), 'text/plain', 100, 0); + $file = new UploadedFile($tmpFile, basename($tmpFile), 'text/plain'); - $bag = new FileBag(array('file' => array( + $bag = new FileBag(['file' => [ 'name' => basename($tmpFile), 'type' => 'text/plain', 'tmp_name' => $tmpFile, 'error' => 0, - 'size' => 100, - ))); + 'size' => null, + ]]); $this->assertEquals($file, $bag->get('file')); } public function testShouldSetEmptyUploadedFilesToNull() { - $bag = new FileBag(array('file' => array( + $bag = new FileBag(['file' => [ 'name' => '', 'type' => '', 'tmp_name' => '', 'error' => UPLOAD_ERR_NO_FILE, 'size' => 0, - ))); + ]]); $this->assertNull($bag->get('file')); } public function testShouldRemoveEmptyUploadedFilesForMultiUpload() { - $bag = new FileBag(array('files' => array( - 'name' => array(''), - 'type' => array(''), - 'tmp_name' => array(''), - 'error' => array(UPLOAD_ERR_NO_FILE), - 'size' => array(0), - ))); - - $this->assertSame(array(), $bag->get('files')); + $bag = new FileBag(['files' => [ + 'name' => [''], + 'type' => [''], + 'tmp_name' => [''], + 'error' => [UPLOAD_ERR_NO_FILE], + 'size' => [0], + ]]); + + $this->assertSame([], $bag->get('files')); } public function testShouldNotRemoveEmptyUploadedFilesForAssociativeArray() { - $bag = new FileBag(array('files' => array( - 'name' => array('file1' => ''), - 'type' => array('file1' => ''), - 'tmp_name' => array('file1' => ''), - 'error' => array('file1' => UPLOAD_ERR_NO_FILE), - 'size' => array('file1' => 0), - ))); - - $this->assertSame(array('file1' => null), $bag->get('files')); + $bag = new FileBag(['files' => [ + 'name' => ['file1' => ''], + 'type' => ['file1' => ''], + 'tmp_name' => ['file1' => ''], + 'error' => ['file1' => UPLOAD_ERR_NO_FILE], + 'size' => ['file1' => 0], + ]]); + + $this->assertSame(['file1' => null], $bag->get('files')); } public function testShouldConvertUploadedFilesWithPhpBug() { $tmpFile = $this->createTempFile(); - $file = new UploadedFile($tmpFile, basename($tmpFile), 'text/plain', 100, 0); + $file = new UploadedFile($tmpFile, basename($tmpFile), 'text/plain'); - $bag = new FileBag(array( - 'child' => array( - 'name' => array( + $bag = new FileBag([ + 'child' => [ + 'name' => [ 'file' => basename($tmpFile), - ), - 'type' => array( + ], + 'type' => [ 'file' => 'text/plain', - ), - 'tmp_name' => array( + ], + 'tmp_name' => [ 'file' => $tmpFile, - ), - 'error' => array( + ], + 'error' => [ 'file' => 0, - ), - 'size' => array( - 'file' => 100, - ), - ), - )); + ], + 'size' => [ + 'file' => null, + ], + ], + ]); $files = $bag->all(); $this->assertEquals($file, $files['child']['file']); @@ -118,27 +116,27 @@ class FileBagTest extends TestCase public function testShouldConvertNestedUploadedFilesWithPhpBug() { $tmpFile = $this->createTempFile(); - $file = new UploadedFile($tmpFile, basename($tmpFile), 'text/plain', 100, 0); - - $bag = new FileBag(array( - 'child' => array( - 'name' => array( - 'sub' => array('file' => basename($tmpFile)), - ), - 'type' => array( - 'sub' => array('file' => 'text/plain'), - ), - 'tmp_name' => array( - 'sub' => array('file' => $tmpFile), - ), - 'error' => array( - 'sub' => array('file' => 0), - ), - 'size' => array( - 'sub' => array('file' => 100), - ), - ), - )); + $file = new UploadedFile($tmpFile, basename($tmpFile), 'text/plain'); + + $bag = new FileBag([ + 'child' => [ + 'name' => [ + 'sub' => ['file' => basename($tmpFile)], + ], + 'type' => [ + 'sub' => ['file' => 'text/plain'], + ], + 'tmp_name' => [ + 'sub' => ['file' => $tmpFile], + ], + 'error' => [ + 'sub' => ['file' => 0], + ], + 'size' => [ + 'sub' => ['file' => null], + ], + ], + ]); $files = $bag->all(); $this->assertEquals($file, $files['child']['sub']['file']); @@ -147,8 +145,8 @@ class FileBagTest extends TestCase public function testShouldNotConvertNestedUploadedFiles() { $tmpFile = $this->createTempFile(); - $file = new UploadedFile($tmpFile, basename($tmpFile), 'text/plain', 100, 0); - $bag = new FileBag(array('image' => array('file' => $file))); + $file = new UploadedFile($tmpFile, basename($tmpFile), 'text/plain'); + $bag = new FileBag(['image' => ['file' => $file]]); $files = $bag->all(); $this->assertEquals($file, $files['image']['file']); @@ -156,15 +154,18 @@ class FileBagTest extends TestCase protected function createTempFile() { - return tempnam(sys_get_temp_dir().'/form_test', 'FormTest'); + $tempFile = tempnam(sys_get_temp_dir().'/form_test', 'FormTest'); + file_put_contents($tempFile, '1'); + + return $tempFile; } - protected function setUp() + protected function setUp(): void { mkdir(sys_get_temp_dir().'/form_test', 0777, true); } - protected function tearDown() + protected function tearDown(): void { foreach (glob(sys_get_temp_dir().'/form_test/*') as $file) { unlink($file); diff --git a/vendor/symfony/http-foundation/Tests/Fixtures/response-functional/common.inc b/vendor/symfony/http-foundation/Tests/Fixtures/response-functional/common.inc new file mode 100644 index 0000000000000000000000000000000000000000..0bdf9e4b75fddcb25356e09c32a5ca1e8ea19ed6 --- /dev/null +++ b/vendor/symfony/http-foundation/Tests/Fixtures/response-functional/common.inc @@ -0,0 +1,43 @@ +<?php + +use Symfony\Component\HttpFoundation\Response; + +$parent = __DIR__; +while (!@file_exists($parent.'/vendor/autoload.php')) { + if (!@file_exists($parent)) { + // open_basedir restriction in effect + break; + } + if ($parent === dirname($parent)) { + echo "vendor/autoload.php not found\n"; + exit(1); + } + + $parent = dirname($parent); +} + +require $parent.'/vendor/autoload.php'; + +error_reporting(-1); +ini_set('html_errors', 0); +ini_set('display_errors', 1); + +if (filter_var(ini_get('xdebug.default_enable'), FILTER_VALIDATE_BOOLEAN)) { + xdebug_disable(); +} + +header_remove('X-Powered-By'); +header('Content-Type: text/plain; charset=utf-8'); + +register_shutdown_function(function () { + echo "\n"; + session_write_close(); + print_r(headers_list()); + echo "shutdown\n"; +}); +ob_start(); + +$r = new Response(); +$r->headers->set('Date', 'Sat, 12 Nov 1955 20:04:00 GMT'); + +return $r; diff --git a/vendor/symfony/http-foundation/Tests/Fixtures/response-functional/cookie_max_age.expected b/vendor/symfony/http-foundation/Tests/Fixtures/response-functional/cookie_max_age.expected new file mode 100644 index 0000000000000000000000000000000000000000..bdb9d023f8f3d135e85c69dc186e139e1eb46a4c --- /dev/null +++ b/vendor/symfony/http-foundation/Tests/Fixtures/response-functional/cookie_max_age.expected @@ -0,0 +1,11 @@ + +Warning: Expiry date cannot have a year greater than 9999 in %scookie_max_age.php on line 10 + +Array +( + [0] => Content-Type: text/plain; charset=utf-8 + [1] => Cache-Control: no-cache, private + [2] => Date: Sat, 12 Nov 1955 20:04:00 GMT + [3] => Set-Cookie: foo=bar; expires=Sat, 01-Jan-10000 02:46:40 GMT; Max-Age=%d; path=/ +) +shutdown diff --git a/vendor/symfony/http-foundation/Tests/Fixtures/response-functional/cookie_max_age.php b/vendor/symfony/http-foundation/Tests/Fixtures/response-functional/cookie_max_age.php new file mode 100644 index 0000000000000000000000000000000000000000..e18ce525230f0164b2861e52bccc2385a5462593 --- /dev/null +++ b/vendor/symfony/http-foundation/Tests/Fixtures/response-functional/cookie_max_age.php @@ -0,0 +1,10 @@ +<?php + +use Symfony\Component\HttpFoundation\Cookie; + +$r = require __DIR__.'/common.inc'; + +$r->headers->setCookie(new Cookie('foo', 'bar', 253402310800, '', null, false, false, false, null)); +$r->sendHeaders(); + +setcookie('foo2', 'bar', 253402310800, '/'); diff --git a/vendor/symfony/http-foundation/Tests/Fixtures/response-functional/cookie_raw_urlencode.expected b/vendor/symfony/http-foundation/Tests/Fixtures/response-functional/cookie_raw_urlencode.expected new file mode 100644 index 0000000000000000000000000000000000000000..0c097972e78e2d68988b394ba9ca22fc00f1cccd --- /dev/null +++ b/vendor/symfony/http-foundation/Tests/Fixtures/response-functional/cookie_raw_urlencode.expected @@ -0,0 +1,10 @@ + +Array +( + [0] => Content-Type: text/plain; charset=utf-8 + [1] => Cache-Control: no-cache, private + [2] => Date: Sat, 12 Nov 1955 20:04:00 GMT + [3] => Set-Cookie: ?*():@&+$/%#[]=?*():@&+$/%#[]; path=/ + [4] => Set-Cookie: ?*():@&+$/%#[]=?*():@&+$/%#[]; path=/ +) +shutdown diff --git a/vendor/symfony/http-foundation/Tests/Fixtures/response-functional/cookie_raw_urlencode.php b/vendor/symfony/http-foundation/Tests/Fixtures/response-functional/cookie_raw_urlencode.php new file mode 100644 index 0000000000000000000000000000000000000000..00c022d9539477a3c0b30fdbeb50d1ecf7a57ca3 --- /dev/null +++ b/vendor/symfony/http-foundation/Tests/Fixtures/response-functional/cookie_raw_urlencode.php @@ -0,0 +1,12 @@ +<?php + +use Symfony\Component\HttpFoundation\Cookie; + +$r = require __DIR__.'/common.inc'; + +$str = '?*():@&+$/%#[]'; + +$r->headers->setCookie(new Cookie($str, $str, 0, '/', null, false, false, true, null)); +$r->sendHeaders(); + +setrawcookie($str, $str, 0, '/', null, false, false); diff --git a/vendor/symfony/http-foundation/Tests/Fixtures/response-functional/cookie_samesite_lax.expected b/vendor/symfony/http-foundation/Tests/Fixtures/response-functional/cookie_samesite_lax.expected new file mode 100644 index 0000000000000000000000000000000000000000..cbde2cbfe13f3c516f0295b50aa69823d971965d --- /dev/null +++ b/vendor/symfony/http-foundation/Tests/Fixtures/response-functional/cookie_samesite_lax.expected @@ -0,0 +1,9 @@ + +Array +( + [0] => Content-Type: text/plain; charset=utf-8 + [1] => Cache-Control: no-cache, private + [2] => Date: Sat, 12 Nov 1955 20:04:00 GMT + [3] => Set-Cookie: CookieSamesiteLaxTest=LaxValue; path=/; httponly; samesite=lax +) +shutdown diff --git a/vendor/symfony/http-foundation/Tests/Fixtures/response-functional/cookie_samesite_lax.php b/vendor/symfony/http-foundation/Tests/Fixtures/response-functional/cookie_samesite_lax.php new file mode 100644 index 0000000000000000000000000000000000000000..9a476f1d23fab043228d78075a8441aa6e0fd9e7 --- /dev/null +++ b/vendor/symfony/http-foundation/Tests/Fixtures/response-functional/cookie_samesite_lax.php @@ -0,0 +1,8 @@ +<?php + +use Symfony\Component\HttpFoundation\Cookie; + +$r = require __DIR__.'/common.inc'; + +$r->headers->setCookie(new Cookie('CookieSamesiteLaxTest', 'LaxValue', 0, '/', null, false, true, false, Cookie::SAMESITE_LAX)); +$r->sendHeaders(); diff --git a/vendor/symfony/http-foundation/Tests/Fixtures/response-functional/cookie_samesite_strict.expected b/vendor/symfony/http-foundation/Tests/Fixtures/response-functional/cookie_samesite_strict.expected new file mode 100644 index 0000000000000000000000000000000000000000..adc491fd2bc512d83b3a59da90e0b8affdb9afc3 --- /dev/null +++ b/vendor/symfony/http-foundation/Tests/Fixtures/response-functional/cookie_samesite_strict.expected @@ -0,0 +1,9 @@ + +Array +( + [0] => Content-Type: text/plain; charset=utf-8 + [1] => Cache-Control: no-cache, private + [2] => Date: Sat, 12 Nov 1955 20:04:00 GMT + [3] => Set-Cookie: CookieSamesiteStrictTest=StrictValue; path=/; httponly; samesite=strict +) +shutdown diff --git a/vendor/symfony/http-foundation/Tests/Fixtures/response-functional/cookie_samesite_strict.php b/vendor/symfony/http-foundation/Tests/Fixtures/response-functional/cookie_samesite_strict.php new file mode 100644 index 0000000000000000000000000000000000000000..3bcb41f8f059e7c2816ade1534c928fd6a0e287d --- /dev/null +++ b/vendor/symfony/http-foundation/Tests/Fixtures/response-functional/cookie_samesite_strict.php @@ -0,0 +1,8 @@ +<?php + +use Symfony\Component\HttpFoundation\Cookie; + +$r = require __DIR__.'/common.inc'; + +$r->headers->setCookie(new Cookie('CookieSamesiteStrictTest', 'StrictValue', 0, '/', null, false, true, false, Cookie::SAMESITE_STRICT)); +$r->sendHeaders(); diff --git a/vendor/symfony/http-foundation/Tests/Fixtures/response-functional/cookie_urlencode.expected b/vendor/symfony/http-foundation/Tests/Fixtures/response-functional/cookie_urlencode.expected new file mode 100644 index 0000000000000000000000000000000000000000..17a9efc669043b9c44d838ecb513b55e666d0452 --- /dev/null +++ b/vendor/symfony/http-foundation/Tests/Fixtures/response-functional/cookie_urlencode.expected @@ -0,0 +1,11 @@ + +Array +( + [0] => Content-Type: text/plain; charset=utf-8 + [1] => Cache-Control: no-cache, private + [2] => Date: Sat, 12 Nov 1955 20:04:00 GMT + [3] => Set-Cookie: %3D%2C%3B%20%09%0D%0A%0B%0C=%3D%2C%3B%20%09%0D%0A%0B%0C; path=/ + [4] => Set-Cookie: ?*():@&+$/%#[]=%3F%2A%28%29%3A%40%26%2B%24%2F%25%23%5B%5D; path=/ + [5] => Set-Cookie: ?*():@&+$/%#[]=%3F%2A%28%29%3A%40%26%2B%24%2F%25%23%5B%5D; path=/ +) +shutdown diff --git a/vendor/symfony/http-foundation/Tests/Fixtures/response-functional/cookie_urlencode.php b/vendor/symfony/http-foundation/Tests/Fixtures/response-functional/cookie_urlencode.php new file mode 100644 index 0000000000000000000000000000000000000000..9ffb0dfec82afc9d30fff32b34b25a71d7f8954b --- /dev/null +++ b/vendor/symfony/http-foundation/Tests/Fixtures/response-functional/cookie_urlencode.php @@ -0,0 +1,15 @@ +<?php + +use Symfony\Component\HttpFoundation\Cookie; + +$r = require __DIR__.'/common.inc'; + +$str1 = "=,; \t\r\n\v\f"; +$r->headers->setCookie(new Cookie($str1, $str1, 0, '', null, false, false, false, null)); + +$str2 = '?*():@&+$/%#[]'; + +$r->headers->setCookie(new Cookie($str2, $str2, 0, '', null, false, false, false, null)); +$r->sendHeaders(); + +setcookie($str2, $str2, 0, '/'); diff --git a/vendor/symfony/http-foundation/Tests/Fixtures/response-functional/invalid_cookie_name.expected b/vendor/symfony/http-foundation/Tests/Fixtures/response-functional/invalid_cookie_name.expected new file mode 100644 index 0000000000000000000000000000000000000000..2b560f0bd568960a175f77e836fcc0a3849748f5 --- /dev/null +++ b/vendor/symfony/http-foundation/Tests/Fixtures/response-functional/invalid_cookie_name.expected @@ -0,0 +1,6 @@ +The cookie name "Hello + world" contains invalid characters. +Array +( + [0] => Content-Type: text/plain; charset=utf-8 +) +shutdown diff --git a/vendor/symfony/http-foundation/Tests/Fixtures/response-functional/invalid_cookie_name.php b/vendor/symfony/http-foundation/Tests/Fixtures/response-functional/invalid_cookie_name.php new file mode 100644 index 0000000000000000000000000000000000000000..3acf86039d93d3d67348574032cf51cb3973192d --- /dev/null +++ b/vendor/symfony/http-foundation/Tests/Fixtures/response-functional/invalid_cookie_name.php @@ -0,0 +1,11 @@ +<?php + +use Symfony\Component\HttpFoundation\Cookie; + +$r = require __DIR__.'/common.inc'; + +try { + $r->headers->setCookie(new Cookie('Hello + world', 'hodor', 0, null, null, null, false, true)); +} catch (\InvalidArgumentException $e) { + echo $e->getMessage(); +} diff --git a/vendor/symfony/http-foundation/Tests/HeaderBagTest.php b/vendor/symfony/http-foundation/Tests/HeaderBagTest.php index 6d19ceb009f2316d13f730e145ccdf5d0d649241..dcc266f69c41af2990191028a16b4b00f2571ba3 100644 --- a/vendor/symfony/http-foundation/Tests/HeaderBagTest.php +++ b/vendor/symfony/http-foundation/Tests/HeaderBagTest.php @@ -18,7 +18,7 @@ class HeaderBagTest extends TestCase { public function testConstructor() { - $bag = new HeaderBag(array('foo' => 'bar')); + $bag = new HeaderBag(['foo' => 'bar']); $this->assertTrue($bag->has('foo')); } @@ -30,30 +30,35 @@ class HeaderBagTest extends TestCase public function testToStringNotNull() { - $bag = new HeaderBag(array('foo' => 'bar')); + $bag = new HeaderBag(['foo' => 'bar']); $this->assertEquals("Foo: bar\r\n", $bag->__toString()); } public function testKeys() { - $bag = new HeaderBag(array('foo' => 'bar')); + $bag = new HeaderBag(['foo' => 'bar']); $keys = $bag->keys(); $this->assertEquals('foo', $keys[0]); } public function testGetDate() { - $bag = new HeaderBag(array('foo' => 'Tue, 4 Sep 2012 20:00:00 +0200')); + $bag = new HeaderBag(['foo' => 'Tue, 4 Sep 2012 20:00:00 +0200']); $headerDate = $bag->getDate('foo'); $this->assertInstanceOf('DateTime', $headerDate); } - /** - * @expectedException \RuntimeException - */ + public function testGetDateNull() + { + $bag = new HeaderBag(['foo' => null]); + $headerDate = $bag->getDate('foo'); + $this->assertNull($headerDate); + } + public function testGetDateException() { - $bag = new HeaderBag(array('foo' => 'Tue')); + $this->expectException('RuntimeException'); + $bag = new HeaderBag(['foo' => 'Tue']); $headerDate = $bag->getDate('foo'); } @@ -67,50 +72,53 @@ class HeaderBagTest extends TestCase public function testAll() { - $bag = new HeaderBag(array('foo' => 'bar')); - $this->assertEquals(array('foo' => array('bar')), $bag->all(), '->all() gets all the input'); + $bag = new HeaderBag(['foo' => 'bar']); + $this->assertEquals(['foo' => ['bar']], $bag->all(), '->all() gets all the input'); - $bag = new HeaderBag(array('FOO' => 'BAR')); - $this->assertEquals(array('foo' => array('BAR')), $bag->all(), '->all() gets all the input key are lower case'); + $bag = new HeaderBag(['FOO' => 'BAR']); + $this->assertEquals(['foo' => ['BAR']], $bag->all(), '->all() gets all the input key are lower case'); } public function testReplace() { - $bag = new HeaderBag(array('foo' => 'bar')); + $bag = new HeaderBag(['foo' => 'bar']); - $bag->replace(array('NOPE' => 'BAR')); - $this->assertEquals(array('nope' => array('BAR')), $bag->all(), '->replace() replaces the input with the argument'); + $bag->replace(['NOPE' => 'BAR']); + $this->assertEquals(['nope' => ['BAR']], $bag->all(), '->replace() replaces the input with the argument'); $this->assertFalse($bag->has('foo'), '->replace() overrides previously set the input'); } public function testGet() { - $bag = new HeaderBag(array('foo' => 'bar', 'fuzz' => 'bizz')); + $bag = new HeaderBag(['foo' => 'bar', 'fuzz' => 'bizz']); $this->assertEquals('bar', $bag->get('foo'), '->get return current value'); $this->assertEquals('bar', $bag->get('FoO'), '->get key in case insensitive'); - $this->assertEquals(array('bar'), $bag->get('foo', 'nope', false), '->get return the value as array'); + $this->assertEquals(['bar'], $bag->get('foo', 'nope', false), '->get return the value as array'); // defaults $this->assertNull($bag->get('none'), '->get unknown values returns null'); $this->assertEquals('default', $bag->get('none', 'default'), '->get unknown values returns default'); - $this->assertEquals(array('default'), $bag->get('none', 'default', false), '->get unknown values returns default as array'); + $this->assertEquals(['default'], $bag->get('none', 'default', false), '->get unknown values returns default as array'); $bag->set('foo', 'bor', false); $this->assertEquals('bar', $bag->get('foo'), '->get return first value'); - $this->assertEquals(array('bar', 'bor'), $bag->get('foo', 'nope', false), '->get return all values as array'); + $this->assertEquals(['bar', 'bor'], $bag->get('foo', 'nope', false), '->get return all values as array'); + + $bag->set('baz', null); + $this->assertNull($bag->get('baz', 'nope'), '->get return null although different default value is given'); } public function testSetAssociativeArray() { $bag = new HeaderBag(); - $bag->set('foo', array('bad-assoc-index' => 'value')); + $bag->set('foo', ['bad-assoc-index' => 'value']); $this->assertSame('value', $bag->get('foo')); - $this->assertEquals(array('value'), $bag->get('foo', 'nope', false), 'assoc indices of multi-valued headers are ignored'); + $this->assertEquals(['value'], $bag->get('foo', 'nope', false), 'assoc indices of multi-valued headers are ignored'); } public function testContains() { - $bag = new HeaderBag(array('foo' => 'bar', 'fuzz' => 'bizz')); + $bag = new HeaderBag(['foo' => 'bar', 'fuzz' => 'bizz']); $this->assertTrue($bag->contains('foo', 'bar'), '->contains first value'); $this->assertTrue($bag->contains('fuzz', 'bizz'), '->contains second value'); $this->assertFalse($bag->contains('nope', 'nope'), '->contains unknown value'); @@ -143,7 +151,7 @@ class HeaderBagTest extends TestCase public function testCacheControlDirectiveParsing() { - $bag = new HeaderBag(array('cache-control' => 'public, max-age=10')); + $bag = new HeaderBag(['cache-control' => 'public, max-age=10']); $this->assertTrue($bag->hasCacheControlDirective('public')); $this->assertTrue($bag->getCacheControlDirective('public')); @@ -156,15 +164,15 @@ class HeaderBagTest extends TestCase public function testCacheControlDirectiveParsingQuotedZero() { - $bag = new HeaderBag(array('cache-control' => 'max-age="0"')); + $bag = new HeaderBag(['cache-control' => 'max-age="0"']); $this->assertTrue($bag->hasCacheControlDirective('max-age')); $this->assertEquals(0, $bag->getCacheControlDirective('max-age')); } public function testCacheControlDirectiveOverrideWithReplace() { - $bag = new HeaderBag(array('cache-control' => 'private, max-age=100')); - $bag->replace(array('cache-control' => 'public, max-age=10')); + $bag = new HeaderBag(['cache-control' => 'private, max-age=100']); + $bag->replace(['cache-control' => 'public, max-age=10']); $this->assertTrue($bag->hasCacheControlDirective('public')); $this->assertTrue($bag->getCacheControlDirective('public')); @@ -174,7 +182,7 @@ class HeaderBagTest extends TestCase public function testCacheControlClone() { - $headers = array('foo' => 'bar'); + $headers = ['foo' => 'bar']; $bag1 = new HeaderBag($headers); $bag2 = new HeaderBag($bag1->all()); @@ -183,23 +191,23 @@ class HeaderBagTest extends TestCase public function testGetIterator() { - $headers = array('foo' => 'bar', 'hello' => 'world', 'third' => 'charm'); + $headers = ['foo' => 'bar', 'hello' => 'world', 'third' => 'charm']; $headerBag = new HeaderBag($headers); $i = 0; foreach ($headerBag as $key => $val) { ++$i; - $this->assertEquals(array($headers[$key]), $val); + $this->assertEquals([$headers[$key]], $val); } - $this->assertEquals(count($headers), $i); + $this->assertEquals(\count($headers), $i); } public function testCount() { - $headers = array('foo' => 'bar', 'HELLO' => 'WORLD'); + $headers = ['foo' => 'bar', 'HELLO' => 'WORLD']; $headerBag = new HeaderBag($headers); - $this->assertCount(count($headers), $headerBag); + $this->assertCount(\count($headers), $headerBag); } } diff --git a/vendor/symfony/http-foundation/Tests/HeaderUtilsTest.php b/vendor/symfony/http-foundation/Tests/HeaderUtilsTest.php new file mode 100644 index 0000000000000000000000000000000000000000..d2b19ca84d1c64f1e27865ec6f7596d842227bcd --- /dev/null +++ b/vendor/symfony/http-foundation/Tests/HeaderUtilsTest.php @@ -0,0 +1,132 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\Tests; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\HttpFoundation\HeaderUtils; + +class HeaderUtilsTest extends TestCase +{ + public function testSplit() + { + $this->assertSame(['foo=123', 'bar'], HeaderUtils::split('foo=123,bar', ',')); + $this->assertSame(['foo=123', 'bar'], HeaderUtils::split('foo=123, bar', ',')); + $this->assertSame([['foo=123', 'bar']], HeaderUtils::split('foo=123; bar', ',;')); + $this->assertSame([['foo=123'], ['bar']], HeaderUtils::split('foo=123, bar', ',;')); + $this->assertSame(['foo', '123, bar'], HeaderUtils::split('foo=123, bar', '=')); + $this->assertSame(['foo', '123, bar'], HeaderUtils::split(' foo = 123, bar ', '=')); + $this->assertSame([['foo', '123'], ['bar']], HeaderUtils::split('foo=123, bar', ',=')); + $this->assertSame([[['foo', '123']], [['bar'], ['foo', '456']]], HeaderUtils::split('foo=123, bar; foo=456', ',;=')); + $this->assertSame([[['foo', 'a,b;c=d']]], HeaderUtils::split('foo="a,b;c=d"', ',;=')); + + $this->assertSame(['foo', 'bar'], HeaderUtils::split('foo,,,, bar', ',')); + $this->assertSame(['foo', 'bar'], HeaderUtils::split(',foo, bar,', ',')); + $this->assertSame(['foo', 'bar'], HeaderUtils::split(' , foo, bar, ', ',')); + $this->assertSame(['foo bar'], HeaderUtils::split('foo "bar"', ',')); + $this->assertSame(['foo bar'], HeaderUtils::split('"foo" bar', ',')); + $this->assertSame(['foo bar'], HeaderUtils::split('"foo" "bar"', ',')); + + // These are not a valid header values. We test that they parse anyway, + // and that both the valid and invalid parts are returned. + $this->assertSame([], HeaderUtils::split('', ',')); + $this->assertSame([], HeaderUtils::split(',,,', ',')); + $this->assertSame(['foo', 'bar', 'baz'], HeaderUtils::split('foo, "bar", "baz', ',')); + $this->assertSame(['foo', 'bar, baz'], HeaderUtils::split('foo, "bar, baz', ',')); + $this->assertSame(['foo', 'bar, baz\\'], HeaderUtils::split('foo, "bar, baz\\', ',')); + $this->assertSame(['foo', 'bar, baz\\'], HeaderUtils::split('foo, "bar, baz\\\\', ',')); + } + + public function testCombine() + { + $this->assertSame(['foo' => '123'], HeaderUtils::combine([['foo', '123']])); + $this->assertSame(['foo' => true], HeaderUtils::combine([['foo']])); + $this->assertSame(['foo' => true], HeaderUtils::combine([['Foo']])); + $this->assertSame(['foo' => '123', 'bar' => true], HeaderUtils::combine([['foo', '123'], ['bar']])); + } + + public function testToString() + { + $this->assertSame('foo', HeaderUtils::toString(['foo' => true], ',')); + $this->assertSame('foo; bar', HeaderUtils::toString(['foo' => true, 'bar' => true], ';')); + $this->assertSame('foo=123', HeaderUtils::toString(['foo' => '123'], ',')); + $this->assertSame('foo="1 2 3"', HeaderUtils::toString(['foo' => '1 2 3'], ',')); + $this->assertSame('foo="1 2 3", bar', HeaderUtils::toString(['foo' => '1 2 3', 'bar' => true], ',')); + } + + public function testQuote() + { + $this->assertSame('foo', HeaderUtils::quote('foo')); + $this->assertSame('az09!#$%&\'*.^_`|~-', HeaderUtils::quote('az09!#$%&\'*.^_`|~-')); + $this->assertSame('"foo bar"', HeaderUtils::quote('foo bar')); + $this->assertSame('"foo [bar]"', HeaderUtils::quote('foo [bar]')); + $this->assertSame('"foo \"bar\""', HeaderUtils::quote('foo "bar"')); + $this->assertSame('"foo \\\\ bar"', HeaderUtils::quote('foo \\ bar')); + } + + public function testUnquote() + { + $this->assertEquals('foo', HeaderUtils::unquote('foo')); + $this->assertEquals('az09!#$%&\'*.^_`|~-', HeaderUtils::unquote('az09!#$%&\'*.^_`|~-')); + $this->assertEquals('foo bar', HeaderUtils::unquote('"foo bar"')); + $this->assertEquals('foo [bar]', HeaderUtils::unquote('"foo [bar]"')); + $this->assertEquals('foo "bar"', HeaderUtils::unquote('"foo \"bar\""')); + $this->assertEquals('foo "bar"', HeaderUtils::unquote('"foo \"\b\a\r\""')); + $this->assertEquals('foo \\ bar', HeaderUtils::unquote('"foo \\\\ bar"')); + } + + public function testMakeDispositionInvalidDisposition() + { + $this->expectException('InvalidArgumentException'); + HeaderUtils::makeDisposition('invalid', 'foo.html'); + } + + /** + * @dataProvider provideMakeDisposition + */ + public function testMakeDisposition($disposition, $filename, $filenameFallback, $expected) + { + $this->assertEquals($expected, HeaderUtils::makeDisposition($disposition, $filename, $filenameFallback)); + } + + public function provideMakeDisposition() + { + return [ + ['attachment', 'foo.html', 'foo.html', 'attachment; filename=foo.html'], + ['attachment', 'foo.html', '', 'attachment; filename=foo.html'], + ['attachment', 'foo bar.html', '', 'attachment; filename="foo bar.html"'], + ['attachment', 'foo "bar".html', '', 'attachment; filename="foo \\"bar\\".html"'], + ['attachment', 'foo%20bar.html', 'foo bar.html', 'attachment; filename="foo bar.html"; filename*=utf-8\'\'foo%2520bar.html'], + ['attachment', 'föö.html', 'foo.html', 'attachment; filename=foo.html; filename*=utf-8\'\'f%C3%B6%C3%B6.html'], + ]; + } + + /** + * @dataProvider provideMakeDispositionFail + */ + public function testMakeDispositionFail($disposition, $filename) + { + $this->expectException('InvalidArgumentException'); + HeaderUtils::makeDisposition($disposition, $filename); + } + + public function provideMakeDispositionFail() + { + return [ + ['attachment', 'foo%20bar.html'], + ['attachment', 'foo/bar.html'], + ['attachment', '/foo.html'], + ['attachment', 'foo\bar.html'], + ['attachment', '\foo.html'], + ['attachment', 'föö.html'], + ]; + } +} diff --git a/vendor/symfony/http-foundation/Tests/IpUtilsTest.php b/vendor/symfony/http-foundation/Tests/IpUtilsTest.php index 7a93f9947262dbd03526002e1f702185c26c9426..d3b262e048526bdeda870a83a82f497f7a7245f0 100644 --- a/vendor/symfony/http-foundation/Tests/IpUtilsTest.php +++ b/vendor/symfony/http-foundation/Tests/IpUtilsTest.php @@ -26,20 +26,20 @@ class IpUtilsTest extends TestCase public function getIpv4Data() { - return array( - array(true, '192.168.1.1', '192.168.1.1'), - array(true, '192.168.1.1', '192.168.1.1/1'), - array(true, '192.168.1.1', '192.168.1.0/24'), - array(false, '192.168.1.1', '1.2.3.4/1'), - array(false, '192.168.1.1', '192.168.1.1/33'), // invalid subnet - array(true, '192.168.1.1', array('1.2.3.4/1', '192.168.1.0/24')), - array(true, '192.168.1.1', array('192.168.1.0/24', '1.2.3.4/1')), - array(false, '192.168.1.1', array('1.2.3.4/1', '4.3.2.1/1')), - array(true, '1.2.3.4', '0.0.0.0/0'), - array(true, '1.2.3.4', '192.168.1.0/0'), - array(false, '1.2.3.4', '256.256.256/0'), // invalid CIDR notation - array(false, 'an_invalid_ip', '192.168.1.0/24'), - ); + return [ + [true, '192.168.1.1', '192.168.1.1'], + [true, '192.168.1.1', '192.168.1.1/1'], + [true, '192.168.1.1', '192.168.1.0/24'], + [false, '192.168.1.1', '1.2.3.4/1'], + [false, '192.168.1.1', '192.168.1.1/33'], // invalid subnet + [true, '192.168.1.1', ['1.2.3.4/1', '192.168.1.0/24']], + [true, '192.168.1.1', ['192.168.1.0/24', '1.2.3.4/1']], + [false, '192.168.1.1', ['1.2.3.4/1', '4.3.2.1/1']], + [true, '1.2.3.4', '0.0.0.0/0'], + [true, '1.2.3.4', '192.168.1.0/0'], + [false, '1.2.3.4', '256.256.256/0'], // invalid CIDR notation + [false, 'an_invalid_ip', '192.168.1.0/24'], + ]; } /** @@ -47,7 +47,7 @@ class IpUtilsTest extends TestCase */ public function testIpv6($matches, $remoteAddr, $cidr) { - if (!defined('AF_INET6')) { + if (!\defined('AF_INET6')) { $this->markTestSkipped('Only works when PHP is compiled without the option "disable-ipv6".'); } @@ -56,29 +56,29 @@ class IpUtilsTest extends TestCase public function getIpv6Data() { - return array( - array(true, '2a01:198:603:0:396e:4789:8e99:890f', '2a01:198:603:0::/65'), - array(false, '2a00:198:603:0:396e:4789:8e99:890f', '2a01:198:603:0::/65'), - array(false, '2a01:198:603:0:396e:4789:8e99:890f', '::1'), - array(true, '0:0:0:0:0:0:0:1', '::1'), - array(false, '0:0:603:0:396e:4789:8e99:0001', '::1'), - array(true, '0:0:603:0:396e:4789:8e99:0001', '::/0'), - array(true, '0:0:603:0:396e:4789:8e99:0001', '2a01:198:603:0::/0'), - array(true, '2a01:198:603:0:396e:4789:8e99:890f', array('::1', '2a01:198:603:0::/65')), - array(true, '2a01:198:603:0:396e:4789:8e99:890f', array('2a01:198:603:0::/65', '::1')), - array(false, '2a01:198:603:0:396e:4789:8e99:890f', array('::1', '1a01:198:603:0::/65')), - array(false, '}__test|O:21:"JDatabaseDriverMysqli":3:{s:2', '::1'), - array(false, '2a01:198:603:0:396e:4789:8e99:890f', 'unknown'), - ); + return [ + [true, '2a01:198:603:0:396e:4789:8e99:890f', '2a01:198:603:0::/65'], + [false, '2a00:198:603:0:396e:4789:8e99:890f', '2a01:198:603:0::/65'], + [false, '2a01:198:603:0:396e:4789:8e99:890f', '::1'], + [true, '0:0:0:0:0:0:0:1', '::1'], + [false, '0:0:603:0:396e:4789:8e99:0001', '::1'], + [true, '0:0:603:0:396e:4789:8e99:0001', '::/0'], + [true, '0:0:603:0:396e:4789:8e99:0001', '2a01:198:603:0::/0'], + [true, '2a01:198:603:0:396e:4789:8e99:890f', ['::1', '2a01:198:603:0::/65']], + [true, '2a01:198:603:0:396e:4789:8e99:890f', ['2a01:198:603:0::/65', '::1']], + [false, '2a01:198:603:0:396e:4789:8e99:890f', ['::1', '1a01:198:603:0::/65']], + [false, '}__test|O:21:"JDatabaseDriverMysqli":3:{s:2', '::1'], + [false, '2a01:198:603:0:396e:4789:8e99:890f', 'unknown'], + ]; } /** - * @expectedException \RuntimeException * @requires extension sockets */ public function testAnIpv6WithOptionDisabledIpv6() { - if (defined('AF_INET6')) { + $this->expectException('RuntimeException'); + if (\defined('AF_INET6')) { $this->markTestSkipped('Only works when PHP is compiled with the option "disable-ipv6".'); } @@ -95,10 +95,10 @@ class IpUtilsTest extends TestCase public function invalidIpAddressData() { - return array( - 'invalid proxy wildcard' => array('192.168.20.13', '*'), - 'invalid proxy missing netmask' => array('192.168.20.13', '0.0.0.0'), - 'invalid request IP with invalid proxy wildcard' => array('0.0.0.0', '*'), - ); + return [ + 'invalid proxy wildcard' => ['192.168.20.13', '*'], + 'invalid proxy missing netmask' => ['192.168.20.13', '0.0.0.0'], + 'invalid request IP with invalid proxy wildcard' => ['0.0.0.0', '*'], + ]; } } diff --git a/vendor/symfony/http-foundation/Tests/JsonResponseTest.php b/vendor/symfony/http-foundation/Tests/JsonResponseTest.php index 201839f89c521f0f0dca61decd08f8cb206ece6f..aa8441799b2b6d6fcc26e75fe40c40b310ffd45b 100644 --- a/vendor/symfony/http-foundation/Tests/JsonResponseTest.php +++ b/vendor/symfony/http-foundation/Tests/JsonResponseTest.php @@ -24,13 +24,13 @@ class JsonResponseTest extends TestCase public function testConstructorWithArrayCreatesJsonArray() { - $response = new JsonResponse(array(0, 1, 2, 3)); + $response = new JsonResponse([0, 1, 2, 3]); $this->assertSame('[0,1,2,3]', $response->getContent()); } public function testConstructorWithAssocArrayCreatesJsonObject() { - $response = new JsonResponse(array('foo' => 'bar')); + $response = new JsonResponse(['foo' => 'bar']); $this->assertSame('{"foo":"bar"}', $response->getContent()); } @@ -43,7 +43,8 @@ class JsonResponseTest extends TestCase $this->assertSame('0', $response->getContent()); $response = new JsonResponse(0.1); - $this->assertSame('0.1', $response->getContent()); + $this->assertEquals(0.1, $response->getContent()); + $this->assertIsString($response->getContent()); $response = new JsonResponse(true); $this->assertSame('true', $response->getContent()); @@ -51,7 +52,7 @@ class JsonResponseTest extends TestCase public function testConstructorWithCustomStatus() { - $response = new JsonResponse(array(), 202); + $response = new JsonResponse([], 202); $this->assertSame(202, $response->getStatusCode()); } @@ -63,35 +64,35 @@ class JsonResponseTest extends TestCase public function testConstructorWithCustomHeaders() { - $response = new JsonResponse(array(), 200, array('ETag' => 'foo')); + $response = new JsonResponse([], 200, ['ETag' => 'foo']); $this->assertSame('application/json', $response->headers->get('Content-Type')); $this->assertSame('foo', $response->headers->get('ETag')); } public function testConstructorWithCustomContentType() { - $headers = array('Content-Type' => 'application/vnd.acme.blog-v1+json'); + $headers = ['Content-Type' => 'application/vnd.acme.blog-v1+json']; - $response = new JsonResponse(array(), 200, $headers); + $response = new JsonResponse([], 200, $headers); $this->assertSame('application/vnd.acme.blog-v1+json', $response->headers->get('Content-Type')); } public function testSetJson() { - $response = new JsonResponse('1', 200, array(), true); + $response = new JsonResponse('1', 200, [], true); $this->assertEquals('1', $response->getContent()); - $response = new JsonResponse('[1]', 200, array(), true); + $response = new JsonResponse('[1]', 200, [], true); $this->assertEquals('[1]', $response->getContent()); - $response = new JsonResponse(null, 200, array()); + $response = new JsonResponse(null, 200, []); $response->setJson('true'); $this->assertEquals('true', $response->getContent()); } public function testCreate() { - $response = JsonResponse::create(array('foo' => 'bar'), 204); + $response = JsonResponse::create(['foo' => 'bar'], 204); $this->assertInstanceOf('Symfony\Component\HttpFoundation\JsonResponse', $response); $this->assertEquals('{"foo":"bar"}', $response->getContent()); @@ -107,14 +108,14 @@ class JsonResponseTest extends TestCase public function testStaticCreateJsonArray() { - $response = JsonResponse::create(array(0, 1, 2, 3)); + $response = JsonResponse::create([0, 1, 2, 3]); $this->assertInstanceOf('Symfony\Component\HttpFoundation\JsonResponse', $response); $this->assertSame('[0,1,2,3]', $response->getContent()); } public function testStaticCreateJsonObject() { - $response = JsonResponse::create(array('foo' => 'bar')); + $response = JsonResponse::create(['foo' => 'bar']); $this->assertInstanceOf('Symfony\Component\HttpFoundation\JsonResponse', $response); $this->assertSame('{"foo":"bar"}', $response->getContent()); } @@ -131,7 +132,8 @@ class JsonResponseTest extends TestCase $response = JsonResponse::create(0.1); $this->assertInstanceOf('Symfony\Component\HttpFoundation\JsonResponse', $response); - $this->assertSame('0.1', $response->getContent()); + $this->assertEquals(0.1, $response->getContent()); + $this->assertIsString($response->getContent()); $response = JsonResponse::create(true); $this->assertInstanceOf('Symfony\Component\HttpFoundation\JsonResponse', $response); @@ -140,7 +142,7 @@ class JsonResponseTest extends TestCase public function testStaticCreateWithCustomStatus() { - $response = JsonResponse::create(array(), 202); + $response = JsonResponse::create([], 202); $this->assertSame(202, $response->getStatusCode()); } @@ -152,22 +154,22 @@ class JsonResponseTest extends TestCase public function testStaticCreateWithCustomHeaders() { - $response = JsonResponse::create(array(), 200, array('ETag' => 'foo')); + $response = JsonResponse::create([], 200, ['ETag' => 'foo']); $this->assertSame('application/json', $response->headers->get('Content-Type')); $this->assertSame('foo', $response->headers->get('ETag')); } public function testStaticCreateWithCustomContentType() { - $headers = array('Content-Type' => 'application/vnd.acme.blog-v1+json'); + $headers = ['Content-Type' => 'application/vnd.acme.blog-v1+json']; - $response = JsonResponse::create(array(), 200, $headers); + $response = JsonResponse::create([], 200, $headers); $this->assertSame('application/vnd.acme.blog-v1+json', $response->headers->get('Content-Type')); } public function testSetCallback() { - $response = JsonResponse::create(array('foo' => 'bar'))->setCallback('callback'); + $response = JsonResponse::create(['foo' => 'bar'])->setCallback('callback'); $this->assertEquals('/**/callback({"foo":"bar"});', $response->getContent()); $this->assertEquals('text/javascript', $response->headers->get('Content-Type')); @@ -190,7 +192,7 @@ class JsonResponseTest extends TestCase public function testSetEncodingOptions() { $response = new JsonResponse(); - $response->setData(array(array(1, 2, 3))); + $response->setData([[1, 2, 3]]); $this->assertEquals('[[1,2,3]]', $response->getContent()); @@ -205,29 +207,23 @@ class JsonResponseTest extends TestCase $this->assertSame('{"foo":"bar"}', $response->getContent()); } - /** - * @expectedException \InvalidArgumentException - */ public function testSetCallbackInvalidIdentifier() { + $this->expectException('InvalidArgumentException'); $response = new JsonResponse('foo'); $response->setCallback('+invalid'); } - /** - * @expectedException \InvalidArgumentException - */ public function testSetContent() { + $this->expectException('InvalidArgumentException'); JsonResponse::create("\xB1\x31"); } - /** - * @expectedException \Exception - * @expectedExceptionMessage This error is expected - */ public function testSetContentJsonSerializeError() { + $this->expectException('Exception'); + $this->expectExceptionMessage('This error is expected'); if (!interface_exists('JsonSerializable', false)) { $this->markTestSkipped('JsonSerializable is required.'); } @@ -239,7 +235,7 @@ class JsonResponseTest extends TestCase public function testSetComplexCallback() { - $response = JsonResponse::create(array('foo' => 'bar')); + $response = JsonResponse::create(['foo' => 'bar']); $response->setCallback('ಠ_ಠ["foo"].bar[0]'); $this->assertEquals('/**/ಠ_ಠ["foo"].bar[0]({"foo":"bar"});', $response->getContent()); diff --git a/vendor/symfony/http-foundation/Tests/ParameterBagTest.php b/vendor/symfony/http-foundation/Tests/ParameterBagTest.php index ab908d8d37de786e30d13f8cab1cefe8b671c345..d2a5c991cc7f68213da34208c9f8000d435d9c54 100644 --- a/vendor/symfony/http-foundation/Tests/ParameterBagTest.php +++ b/vendor/symfony/http-foundation/Tests/ParameterBagTest.php @@ -23,44 +23,44 @@ class ParameterBagTest extends TestCase public function testAll() { - $bag = new ParameterBag(array('foo' => 'bar')); - $this->assertEquals(array('foo' => 'bar'), $bag->all(), '->all() gets all the input'); + $bag = new ParameterBag(['foo' => 'bar']); + $this->assertEquals(['foo' => 'bar'], $bag->all(), '->all() gets all the input'); } public function testKeys() { - $bag = new ParameterBag(array('foo' => 'bar')); - $this->assertEquals(array('foo'), $bag->keys()); + $bag = new ParameterBag(['foo' => 'bar']); + $this->assertEquals(['foo'], $bag->keys()); } public function testAdd() { - $bag = new ParameterBag(array('foo' => 'bar')); - $bag->add(array('bar' => 'bas')); - $this->assertEquals(array('foo' => 'bar', 'bar' => 'bas'), $bag->all()); + $bag = new ParameterBag(['foo' => 'bar']); + $bag->add(['bar' => 'bas']); + $this->assertEquals(['foo' => 'bar', 'bar' => 'bas'], $bag->all()); } public function testRemove() { - $bag = new ParameterBag(array('foo' => 'bar')); - $bag->add(array('bar' => 'bas')); - $this->assertEquals(array('foo' => 'bar', 'bar' => 'bas'), $bag->all()); + $bag = new ParameterBag(['foo' => 'bar']); + $bag->add(['bar' => 'bas']); + $this->assertEquals(['foo' => 'bar', 'bar' => 'bas'], $bag->all()); $bag->remove('bar'); - $this->assertEquals(array('foo' => 'bar'), $bag->all()); + $this->assertEquals(['foo' => 'bar'], $bag->all()); } public function testReplace() { - $bag = new ParameterBag(array('foo' => 'bar')); + $bag = new ParameterBag(['foo' => 'bar']); - $bag->replace(array('FOO' => 'BAR')); - $this->assertEquals(array('FOO' => 'BAR'), $bag->all(), '->replace() replaces the input with the argument'); + $bag->replace(['FOO' => 'BAR']); + $this->assertEquals(['FOO' => 'BAR'], $bag->all(), '->replace() replaces the input with the argument'); $this->assertFalse($bag->has('foo'), '->replace() overrides previously set the input'); } public function testGet() { - $bag = new ParameterBag(array('foo' => 'bar', 'null' => null)); + $bag = new ParameterBag(['foo' => 'bar', 'null' => null]); $this->assertEquals('bar', $bag->get('foo'), '->get() gets the value of a parameter'); $this->assertEquals('default', $bag->get('unknown', 'default'), '->get() returns second argument as default if a parameter is not defined'); @@ -69,14 +69,14 @@ class ParameterBagTest extends TestCase public function testGetDoesNotUseDeepByDefault() { - $bag = new ParameterBag(array('foo' => array('bar' => 'moo'))); + $bag = new ParameterBag(['foo' => ['bar' => 'moo']]); $this->assertNull($bag->get('foo[bar]')); } public function testSet() { - $bag = new ParameterBag(array()); + $bag = new ParameterBag([]); $bag->set('foo', 'bar'); $this->assertEquals('bar', $bag->get('foo'), '->set() sets the value of parameter'); @@ -87,7 +87,7 @@ class ParameterBagTest extends TestCase public function testHas() { - $bag = new ParameterBag(array('foo' => 'bar')); + $bag = new ParameterBag(['foo' => 'bar']); $this->assertTrue($bag->has('foo'), '->has() returns true if a parameter is defined'); $this->assertFalse($bag->has('unknown'), '->has() return false if a parameter is not defined'); @@ -95,7 +95,7 @@ class ParameterBagTest extends TestCase public function testGetAlpha() { - $bag = new ParameterBag(array('word' => 'foo_BAR_012')); + $bag = new ParameterBag(['word' => 'foo_BAR_012']); $this->assertEquals('fooBAR', $bag->getAlpha('word'), '->getAlpha() gets only alphabetic characters'); $this->assertEquals('', $bag->getAlpha('unknown'), '->getAlpha() returns empty string if a parameter is not defined'); @@ -103,7 +103,7 @@ class ParameterBagTest extends TestCase public function testGetAlnum() { - $bag = new ParameterBag(array('word' => 'foo_BAR_012')); + $bag = new ParameterBag(['word' => 'foo_BAR_012']); $this->assertEquals('fooBAR012', $bag->getAlnum('word'), '->getAlnum() gets only alphanumeric characters'); $this->assertEquals('', $bag->getAlnum('unknown'), '->getAlnum() returns empty string if a parameter is not defined'); @@ -111,7 +111,7 @@ class ParameterBagTest extends TestCase public function testGetDigits() { - $bag = new ParameterBag(array('word' => 'foo_BAR_012')); + $bag = new ParameterBag(['word' => 'foo_BAR_012']); $this->assertEquals('012', $bag->getDigits('word'), '->getDigits() gets only digits as string'); $this->assertEquals('', $bag->getDigits('unknown'), '->getDigits() returns empty string if a parameter is not defined'); @@ -119,7 +119,7 @@ class ParameterBagTest extends TestCase public function testGetInt() { - $bag = new ParameterBag(array('digits' => '0123')); + $bag = new ParameterBag(['digits' => '0123']); $this->assertEquals(123, $bag->getInt('digits'), '->getInt() gets a value of parameter as integer'); $this->assertEquals(0, $bag->getInt('unknown'), '->getInt() returns zero if a parameter is not defined'); @@ -127,14 +127,14 @@ class ParameterBagTest extends TestCase public function testFilter() { - $bag = new ParameterBag(array( + $bag = new ParameterBag([ 'digits' => '0123ab', 'email' => 'example@example.com', 'url' => 'http://example.com/foo', 'dec' => '256', 'hex' => '0x100', - 'array' => array('bang'), - )); + 'array' => ['bang'], + ]); $this->assertEmpty($bag->filter('nokey'), '->filter() should return empty by default if no key is found'); @@ -142,27 +142,27 @@ class ParameterBagTest extends TestCase $this->assertEquals('example@example.com', $bag->filter('email', '', FILTER_VALIDATE_EMAIL), '->filter() gets a value of parameter as email'); - $this->assertEquals('http://example.com/foo', $bag->filter('url', '', FILTER_VALIDATE_URL, array('flags' => FILTER_FLAG_PATH_REQUIRED)), '->filter() gets a value of parameter as URL with a path'); + $this->assertEquals('http://example.com/foo', $bag->filter('url', '', FILTER_VALIDATE_URL, ['flags' => FILTER_FLAG_PATH_REQUIRED]), '->filter() gets a value of parameter as URL with a path'); // This test is repeated for code-coverage $this->assertEquals('http://example.com/foo', $bag->filter('url', '', FILTER_VALIDATE_URL, FILTER_FLAG_PATH_REQUIRED), '->filter() gets a value of parameter as URL with a path'); - $this->assertFalse($bag->filter('dec', '', FILTER_VALIDATE_INT, array( + $this->assertFalse($bag->filter('dec', '', FILTER_VALIDATE_INT, [ 'flags' => FILTER_FLAG_ALLOW_HEX, - 'options' => array('min_range' => 1, 'max_range' => 0xff), - )), '->filter() gets a value of parameter as integer between boundaries'); + 'options' => ['min_range' => 1, 'max_range' => 0xff], + ]), '->filter() gets a value of parameter as integer between boundaries'); - $this->assertFalse($bag->filter('hex', '', FILTER_VALIDATE_INT, array( + $this->assertFalse($bag->filter('hex', '', FILTER_VALIDATE_INT, [ 'flags' => FILTER_FLAG_ALLOW_HEX, - 'options' => array('min_range' => 1, 'max_range' => 0xff), - )), '->filter() gets a value of parameter as integer between boundaries'); + 'options' => ['min_range' => 1, 'max_range' => 0xff], + ]), '->filter() gets a value of parameter as integer between boundaries'); - $this->assertEquals(array('bang'), $bag->filter('array', ''), '->filter() gets a value of parameter as an array'); + $this->assertEquals(['bang'], $bag->filter('array', ''), '->filter() gets a value of parameter as an array'); } public function testGetIterator() { - $parameters = array('foo' => 'bar', 'hello' => 'world'); + $parameters = ['foo' => 'bar', 'hello' => 'world']; $bag = new ParameterBag($parameters); $i = 0; @@ -171,20 +171,20 @@ class ParameterBagTest extends TestCase $this->assertEquals($parameters[$key], $val); } - $this->assertEquals(count($parameters), $i); + $this->assertEquals(\count($parameters), $i); } public function testCount() { - $parameters = array('foo' => 'bar', 'hello' => 'world'); + $parameters = ['foo' => 'bar', 'hello' => 'world']; $bag = new ParameterBag($parameters); - $this->assertCount(count($parameters), $bag); + $this->assertCount(\count($parameters), $bag); } public function testGetBoolean() { - $parameters = array('string_true' => 'true', 'string_false' => 'false'); + $parameters = ['string_true' => 'true', 'string_false' => 'false']; $bag = new ParameterBag($parameters); $this->assertTrue($bag->getBoolean('string_true'), '->getBoolean() gets the string true as boolean true'); diff --git a/vendor/symfony/http-foundation/Tests/RedirectResponseTest.php b/vendor/symfony/http-foundation/Tests/RedirectResponseTest.php index d389e83dbe14a76a1c4c9955a20c11796f26c6da..92f4876da4ff1e0060e572d3c00f4b3d1af8ab30 100644 --- a/vendor/symfony/http-foundation/Tests/RedirectResponseTest.php +++ b/vendor/symfony/http-foundation/Tests/RedirectResponseTest.php @@ -22,23 +22,19 @@ class RedirectResponseTest extends TestCase $this->assertEquals(1, preg_match( '#<meta http-equiv="refresh" content="\d+;url=foo\.bar" />#', - preg_replace(array('/\s+/', '/\'/'), array(' ', '"'), $response->getContent()) + preg_replace(['/\s+/', '/\'/'], [' ', '"'], $response->getContent()) )); } - /** - * @expectedException \InvalidArgumentException - */ public function testRedirectResponseConstructorNullUrl() { + $this->expectException('InvalidArgumentException'); $response = new RedirectResponse(null); } - /** - * @expectedException \InvalidArgumentException - */ public function testRedirectResponseConstructorWrongStatusCode() { + $this->expectException('InvalidArgumentException'); $response = new RedirectResponse('foo.bar', 404); } @@ -65,11 +61,9 @@ class RedirectResponseTest extends TestCase $this->assertEquals('baz.beep', $response->getTargetUrl()); } - /** - * @expectedException \InvalidArgumentException - */ public function testSetTargetUrlNull() { + $this->expectException('InvalidArgumentException'); $response = new RedirectResponse('foo.bar'); $response->setTargetUrl(null); } @@ -87,7 +81,11 @@ class RedirectResponseTest extends TestCase $response = new RedirectResponse('foo.bar', 301); $this->assertFalse($response->headers->hasCacheControlDirective('no-cache')); - $response = new RedirectResponse('foo.bar', 301, array('cache-control' => 'max-age=86400')); + $response = new RedirectResponse('foo.bar', 301, ['cache-control' => 'max-age=86400']); + $this->assertFalse($response->headers->hasCacheControlDirective('no-cache')); + $this->assertTrue($response->headers->hasCacheControlDirective('max-age')); + + $response = new RedirectResponse('foo.bar', 301, ['Cache-Control' => 'max-age=86400']); $this->assertFalse($response->headers->hasCacheControlDirective('no-cache')); $this->assertTrue($response->headers->hasCacheControlDirective('max-age')); diff --git a/vendor/symfony/http-foundation/Tests/RequestMatcherTest.php b/vendor/symfony/http-foundation/Tests/RequestMatcherTest.php index b5d80048ff11e2bf9abddfcd8cee115301e15e55..57e9c3d30f2c9dfd6468e84eb39ae7c25c9284ca 100644 --- a/vendor/symfony/http-foundation/Tests/RequestMatcherTest.php +++ b/vendor/symfony/http-foundation/Tests/RequestMatcherTest.php @@ -12,8 +12,8 @@ namespace Symfony\Component\HttpFoundation\Tests; use PHPUnit\Framework\TestCase; -use Symfony\Component\HttpFoundation\RequestMatcher; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\RequestMatcher; class RequestMatcherTest extends TestCase { @@ -34,20 +34,20 @@ class RequestMatcherTest extends TestCase public function getMethodData() { - return array( - array('get', 'get', true), - array('get', array('get', 'post'), true), - array('get', 'post', false), - array('get', 'GET', true), - array('get', array('GET', 'POST'), true), - array('get', 'POST', false), - ); + return [ + ['get', 'get', true], + ['get', ['get', 'post'], true], + ['get', 'post', false], + ['get', 'GET', true], + ['get', ['GET', 'POST'], true], + ['get', 'POST', false], + ]; } public function testScheme() { $httpRequest = $request = $request = Request::create(''); - $httpsRequest = $request = $request = Request::create('', 'get', array(), array(), array(), array('HTTPS' => 'on')); + $httpsRequest = $request = $request = Request::create('', 'get', [], [], [], ['HTTPS' => 'on']); $matcher = new RequestMatcher(); $matcher->matchScheme('https'); @@ -69,7 +69,7 @@ class RequestMatcherTest extends TestCase public function testHost($pattern, $isMatch) { $matcher = new RequestMatcher(); - $request = Request::create('', 'get', array(), array(), array(), array('HTTP_HOST' => 'foo.example.com')); + $request = Request::create('', 'get', [], [], [], ['HTTP_HOST' => 'foo.example.com']); $matcher->matchHost($pattern); $this->assertSame($isMatch, $matcher->matches($request)); @@ -78,18 +78,33 @@ class RequestMatcherTest extends TestCase $this->assertSame($isMatch, $matcher->matches($request)); } + public function testPort() + { + $matcher = new RequestMatcher(); + $request = Request::create('', 'get', [], [], [], ['HTTP_HOST' => null, 'SERVER_PORT' => 8000]); + + $matcher->matchPort(8000); + $this->assertTrue($matcher->matches($request)); + + $matcher->matchPort(9000); + $this->assertFalse($matcher->matches($request)); + + $matcher = new RequestMatcher(null, null, null, null, [], null, 8000); + $this->assertTrue($matcher->matches($request)); + } + public function getHostData() { - return array( - array('.*\.example\.com', true), - array('\.example\.com$', true), - array('^.*\.example\.com$', true), - array('.*\.sensio\.com', false), - array('.*\.example\.COM', true), - array('\.example\.COM$', true), - array('^.*\.example\.COM$', true), - array('.*\.sensio\.COM', false), - ); + return [ + ['.*\.example\.com', true], + ['\.example\.com$', true], + ['^.*\.example\.com$', true], + ['.*\.sensio\.com', false], + ['.*\.example\.COM', true], + ['\.example\.COM$', true], + ['^.*\.example\.COM$', true], + ['.*\.sensio\.COM', false], + ]; } public function testPath() diff --git a/vendor/symfony/http-foundation/Tests/RequestTest.php b/vendor/symfony/http-foundation/Tests/RequestTest.php index 72add95359b5b130d6a873f16f948d8fd85a7c60..d56ef31476f59c0e6cf3132e63decd48af45b315 100644 --- a/vendor/symfony/http-foundation/Tests/RequestTest.php +++ b/vendor/symfony/http-foundation/Tests/RequestTest.php @@ -13,32 +13,32 @@ namespace Symfony\Component\HttpFoundation\Tests; use PHPUnit\Framework\TestCase; use Symfony\Component\HttpFoundation\Exception\SuspiciousOperationException; -use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage; -use Symfony\Component\HttpFoundation\Session\Session; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Session\Session; +use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage; class RequestTest extends TestCase { - protected function tearDown() + protected function tearDown(): void { - // reset - Request::setTrustedProxies(array(), -1); + Request::setTrustedProxies([], -1); + Request::setTrustedHosts([]); } public function testInitialize() { $request = new Request(); - $request->initialize(array('foo' => 'bar')); + $request->initialize(['foo' => 'bar']); $this->assertEquals('bar', $request->query->get('foo'), '->initialize() takes an array of query parameters as its first argument'); - $request->initialize(array(), array('foo' => 'bar')); + $request->initialize([], ['foo' => 'bar']); $this->assertEquals('bar', $request->request->get('foo'), '->initialize() takes an array of request parameters as its second argument'); - $request->initialize(array(), array(), array('foo' => 'bar')); + $request->initialize([], [], ['foo' => 'bar']); $this->assertEquals('bar', $request->attributes->get('foo'), '->initialize() takes an array of attributes as its third argument'); - $request->initialize(array(), array(), array(), array(), array(), array('HTTP_FOO' => 'bar')); + $request->initialize([], [], [], [], [], ['HTTP_FOO' => 'bar']); $this->assertEquals('bar', $request->headers->get('FOO'), '->initialize() takes an array of HTTP headers as its sixth argument'); } @@ -101,7 +101,7 @@ class RequestTest extends TestCase $this->assertEquals('test.com', $request->getHttpHost()); $this->assertFalse($request->isSecure()); - $request = Request::create('http://test.com/foo', 'GET', array('bar' => 'baz')); + $request = Request::create('http://test.com/foo', 'GET', ['bar' => 'baz']); $this->assertEquals('http://test.com/foo?bar=baz', $request->getUri()); $this->assertEquals('/foo', $request->getPathInfo()); $this->assertEquals('bar=baz', $request->getQueryString()); @@ -109,7 +109,7 @@ class RequestTest extends TestCase $this->assertEquals('test.com', $request->getHttpHost()); $this->assertFalse($request->isSecure()); - $request = Request::create('http://test.com/foo?bar=foo', 'GET', array('bar' => 'baz')); + $request = Request::create('http://test.com/foo?bar=foo', 'GET', ['bar' => 'baz']); $this->assertEquals('http://test.com/foo?bar=baz', $request->getUri()); $this->assertEquals('/foo', $request->getPathInfo()); $this->assertEquals('bar=baz', $request->getQueryString()); @@ -166,7 +166,7 @@ class RequestTest extends TestCase $this->assertTrue($request->isSecure()); $json = '{"jsonrpc":"2.0","method":"echo","id":7,"params":["Hello World"]}'; - $request = Request::create('http://example.com/jsonrpc', 'POST', array(), array(), array(), array(), $json); + $request = Request::create('http://example.com/jsonrpc', 'POST', [], [], [], [], $json); $this->assertEquals($json, $request->getContent()); $this->assertFalse($request->isSecure()); @@ -216,28 +216,126 @@ class RequestTest extends TestCase $request = Request::create('http://test.com/?foo'); $this->assertEquals('/?foo', $request->getRequestUri()); - $this->assertEquals(array('foo' => ''), $request->query->all()); + $this->assertEquals(['foo' => ''], $request->query->all()); // assume rewrite rule: (.*) --> app/app.php; app/ is a symlink to a symfony web/ directory - $request = Request::create('http://test.com/apparthotel-1234', 'GET', array(), array(), array(), - array( + $request = Request::create('http://test.com/apparthotel-1234', 'GET', [], [], [], + [ 'DOCUMENT_ROOT' => '/var/www/www.test.com', 'SCRIPT_FILENAME' => '/var/www/www.test.com/app/app.php', 'SCRIPT_NAME' => '/app/app.php', 'PHP_SELF' => '/app/app.php/apparthotel-1234', - )); + ]); $this->assertEquals('http://test.com/apparthotel-1234', $request->getUri()); $this->assertEquals('/apparthotel-1234', $request->getPathInfo()); $this->assertEquals('', $request->getQueryString()); $this->assertEquals(80, $request->getPort()); $this->assertEquals('test.com', $request->getHttpHost()); $this->assertFalse($request->isSecure()); + + // Fragment should not be included in the URI + $request = Request::create('http://test.com/foo#bar'); + $this->assertEquals('http://test.com/foo', $request->getUri()); + } + + public function testCreateWithRequestUri() + { + $request = Request::create('http://test.com:80/foo'); + $request->server->set('REQUEST_URI', 'http://test.com:80/foo'); + $this->assertEquals('http://test.com/foo', $request->getUri()); + $this->assertEquals('/foo', $request->getPathInfo()); + $this->assertEquals('test.com', $request->getHost()); + $this->assertEquals('test.com', $request->getHttpHost()); + $this->assertEquals(80, $request->getPort()); + $this->assertFalse($request->isSecure()); + + $request = Request::create('http://test.com:8080/foo'); + $request->server->set('REQUEST_URI', 'http://test.com:8080/foo'); + $this->assertEquals('http://test.com:8080/foo', $request->getUri()); + $this->assertEquals('/foo', $request->getPathInfo()); + $this->assertEquals('test.com', $request->getHost()); + $this->assertEquals('test.com:8080', $request->getHttpHost()); + $this->assertEquals(8080, $request->getPort()); + $this->assertFalse($request->isSecure()); + + $request = Request::create('http://test.com/foo?bar=foo', 'GET', ['bar' => 'baz']); + $request->server->set('REQUEST_URI', 'http://test.com/foo?bar=foo'); + $this->assertEquals('http://test.com/foo?bar=baz', $request->getUri()); + $this->assertEquals('/foo', $request->getPathInfo()); + $this->assertEquals('bar=baz', $request->getQueryString()); + $this->assertEquals('test.com', $request->getHost()); + $this->assertEquals('test.com', $request->getHttpHost()); + $this->assertEquals(80, $request->getPort()); + $this->assertFalse($request->isSecure()); + + $request = Request::create('https://test.com:443/foo'); + $request->server->set('REQUEST_URI', 'https://test.com:443/foo'); + $this->assertEquals('https://test.com/foo', $request->getUri()); + $this->assertEquals('/foo', $request->getPathInfo()); + $this->assertEquals('test.com', $request->getHost()); + $this->assertEquals('test.com', $request->getHttpHost()); + $this->assertEquals(443, $request->getPort()); + $this->assertTrue($request->isSecure()); + + // Fragment should not be included in the URI + $request = Request::create('http://test.com/foo#bar'); + $request->server->set('REQUEST_URI', 'http://test.com/foo#bar'); + $this->assertEquals('http://test.com/foo', $request->getUri()); + } + + /** + * @dataProvider getRequestUriData + */ + public function testGetRequestUri($serverRequestUri, $expected, $message) + { + $request = new Request(); + $request->server->add([ + 'REQUEST_URI' => $serverRequestUri, + + // For having http://test.com + 'SERVER_NAME' => 'test.com', + 'SERVER_PORT' => 80, + ]); + + $this->assertSame($expected, $request->getRequestUri(), $message); + $this->assertSame($expected, $request->server->get('REQUEST_URI'), 'Normalize the request URI.'); + } + + public function getRequestUriData() + { + $message = 'Do not modify the path.'; + yield ['/foo', '/foo', $message]; + yield ['//bar/foo', '//bar/foo', $message]; + yield ['///bar/foo', '///bar/foo', $message]; + + $message = 'Handle when the scheme, host are on REQUEST_URI.'; + yield ['http://test.com/foo?bar=baz', '/foo?bar=baz', $message]; + + $message = 'Handle when the scheme, host and port are on REQUEST_URI.'; + yield ['http://test.com:80/foo', '/foo', $message]; + yield ['https://test.com:8080/foo', '/foo', $message]; + yield ['https://test.com:443/foo', '/foo', $message]; + + $message = 'Fragment should not be included in the URI'; + yield ['http://test.com/foo#bar', '/foo', $message]; + yield ['/foo#bar', '/foo', $message]; + } + + public function testGetRequestUriWithoutRequiredHeader() + { + $expected = ''; + + $request = new Request(); + + $message = 'Fallback to empty URI when headers are missing.'; + $this->assertSame($expected, $request->getRequestUri(), $message); + $this->assertSame($expected, $request->server->get('REQUEST_URI'), 'Normalize the request URI.'); } public function testCreateCheckPrecedence() { // server is used by default - $request = Request::create('/', 'DELETE', array(), array(), array(), array( + $request = Request::create('/', 'DELETE', [], [], [], [ 'HTTP_HOST' => 'example.com', 'HTTPS' => 'on', 'SERVER_PORT' => 443, @@ -245,7 +343,7 @@ class RequestTest extends TestCase 'PHP_AUTH_PW' => 'pa$$', 'QUERY_STRING' => 'foo=bar', 'CONTENT_TYPE' => 'application/json', - )); + ]); $this->assertEquals('example.com', $request->getHost()); $this->assertEquals(443, $request->getPort()); $this->assertTrue($request->isSecure()); @@ -255,11 +353,11 @@ class RequestTest extends TestCase $this->assertEquals('application/json', $request->headers->get('CONTENT_TYPE')); // URI has precedence over server - $request = Request::create('http://thomas:pokemon@example.net:8080/?foo=bar', 'GET', array(), array(), array(), array( + $request = Request::create('http://thomas:pokemon@example.net:8080/?foo=bar', 'GET', [], [], [], [ 'HTTP_HOST' => 'example.com', 'HTTPS' => 'on', 'SERVER_PORT' => 443, - )); + ]); $this->assertEquals('example.net', $request->getHost()); $this->assertEquals(8080, $request->getPort()); $this->assertFalse($request->isSecure()); @@ -270,7 +368,7 @@ class RequestTest extends TestCase public function testDuplicate() { - $request = new Request(array('foo' => 'bar'), array('foo' => 'bar'), array('foo' => 'bar'), array(), array(), array('HTTP_FOO' => 'bar')); + $request = new Request(['foo' => 'bar'], ['foo' => 'bar'], ['foo' => 'bar'], [], [], ['HTTP_FOO' => 'bar']); $dup = $request->duplicate(); $this->assertEquals($request->query->all(), $dup->query->all(), '->duplicate() duplicates a request an copy the current query parameters'); @@ -278,17 +376,17 @@ class RequestTest extends TestCase $this->assertEquals($request->attributes->all(), $dup->attributes->all(), '->duplicate() duplicates a request an copy the current attributes'); $this->assertEquals($request->headers->all(), $dup->headers->all(), '->duplicate() duplicates a request an copy the current HTTP headers'); - $dup = $request->duplicate(array('foo' => 'foobar'), array('foo' => 'foobar'), array('foo' => 'foobar'), array(), array(), array('HTTP_FOO' => 'foobar')); + $dup = $request->duplicate(['foo' => 'foobar'], ['foo' => 'foobar'], ['foo' => 'foobar'], [], [], ['HTTP_FOO' => 'foobar']); - $this->assertEquals(array('foo' => 'foobar'), $dup->query->all(), '->duplicate() overrides the query parameters if provided'); - $this->assertEquals(array('foo' => 'foobar'), $dup->request->all(), '->duplicate() overrides the request parameters if provided'); - $this->assertEquals(array('foo' => 'foobar'), $dup->attributes->all(), '->duplicate() overrides the attributes if provided'); - $this->assertEquals(array('foo' => array('foobar')), $dup->headers->all(), '->duplicate() overrides the HTTP header if provided'); + $this->assertEquals(['foo' => 'foobar'], $dup->query->all(), '->duplicate() overrides the query parameters if provided'); + $this->assertEquals(['foo' => 'foobar'], $dup->request->all(), '->duplicate() overrides the request parameters if provided'); + $this->assertEquals(['foo' => 'foobar'], $dup->attributes->all(), '->duplicate() overrides the attributes if provided'); + $this->assertEquals(['foo' => ['foobar']], $dup->headers->all(), '->duplicate() overrides the HTTP header if provided'); } public function testDuplicateWithFormat() { - $request = new Request(array(), array(), array('_format' => 'json')); + $request = new Request([], [], ['_format' => 'json']); $dup = $request->duplicate(); $this->assertEquals('json', $dup->getRequestFormat()); @@ -323,7 +421,7 @@ class RequestTest extends TestCase public function getFormatToMimeTypeMapProviderWithAdditionalNullFormat() { return array_merge( - array(array(null, array(null, 'unexistent-mime-type'))), + [[null, [null, 'unexistent-mime-type']]], $this->getFormatToMimeTypeMapProvider() ); } @@ -332,6 +430,9 @@ class RequestTest extends TestCase { $request = new Request(); $this->assertEquals('json', $request->getFormat('application/json; charset=utf-8')); + $this->assertEquals('json', $request->getFormat('application/json;charset=utf-8')); + $this->assertEquals('json', $request->getFormat('application/json ; charset=utf-8')); + $this->assertEquals('json', $request->getFormat('application/json ;charset=utf-8')); } /** @@ -355,7 +456,7 @@ class RequestTest extends TestCase { $request = new Request(); $this->assertNull($request->getMimeType('foo')); - $this->assertEquals(array(), Request::getMimeTypes('foo')); + $this->assertEquals([], Request::getMimeTypes('foo')); } public function testGetFormatWithCustomMimeType() @@ -367,21 +468,21 @@ class RequestTest extends TestCase public function getFormatToMimeTypeMapProvider() { - return array( - array('txt', array('text/plain')), - array('js', array('application/javascript', 'application/x-javascript', 'text/javascript')), - array('css', array('text/css')), - array('json', array('application/json', 'application/x-json')), - array('jsonld', array('application/ld+json')), - array('xml', array('text/xml', 'application/xml', 'application/x-xml')), - array('rdf', array('application/rdf+xml')), - array('atom', array('application/atom+xml')), - ); + return [ + ['txt', ['text/plain']], + ['js', ['application/javascript', 'application/x-javascript', 'text/javascript']], + ['css', ['text/css']], + ['json', ['application/json', 'application/x-json']], + ['jsonld', ['application/ld+json']], + ['xml', ['text/xml', 'application/xml', 'application/x-xml']], + ['rdf', ['application/rdf+xml']], + ['atom', ['application/atom+xml']], + ]; } public function testGetUri() { - $server = array(); + $server = []; // Standard Request on non default PORT // http://host:8080/index.php/path/info?query=string @@ -400,7 +501,7 @@ class RequestTest extends TestCase $request = new Request(); - $request->initialize(array(), array(), array(), array(), array(), $server); + $request->initialize([], [], [], [], [], $server); $this->assertEquals('http://host:8080/index.php/path/info?query=string', $request->getUri(), '->getUri() with non default port'); @@ -409,7 +510,7 @@ class RequestTest extends TestCase $server['SERVER_NAME'] = 'servername'; $server['SERVER_PORT'] = '80'; - $request->initialize(array(), array(), array(), array(), array(), $server); + $request->initialize([], [], [], [], [], $server); $this->assertEquals('http://host/index.php/path/info?query=string', $request->getUri(), '->getUri() with default port'); @@ -418,7 +519,7 @@ class RequestTest extends TestCase $server['SERVER_NAME'] = 'servername'; $server['SERVER_PORT'] = '80'; - $request->initialize(array(), array(), array(), array(), array(), $server); + $request->initialize([], [], [], [], [], $server); $this->assertEquals('http://servername/index.php/path/info?query=string', $request->getUri(), '->getUri() with default port without HOST_HEADER'); @@ -426,7 +527,7 @@ class RequestTest extends TestCase // RewriteCond %{REQUEST_FILENAME} !-f // RewriteRule ^(.*)$ index.php [QSA,L] // http://host:8080/path/info?query=string - $server = array(); + $server = []; $server['HTTP_HOST'] = 'host:8080'; $server['SERVER_NAME'] = 'servername'; $server['SERVER_PORT'] = '8080'; @@ -440,7 +541,7 @@ class RequestTest extends TestCase $server['PHP_SELF'] = '/index.php'; $server['SCRIPT_FILENAME'] = '/some/where/index.php'; - $request->initialize(array(), array(), array(), array(), array(), $server); + $request->initialize([], [], [], [], [], $server); $this->assertEquals('http://host:8080/path/info?query=string', $request->getUri(), '->getUri() with rewrite'); // Use std port number @@ -449,7 +550,7 @@ class RequestTest extends TestCase $server['SERVER_NAME'] = 'servername'; $server['SERVER_PORT'] = '80'; - $request->initialize(array(), array(), array(), array(), array(), $server); + $request->initialize([], [], [], [], [], $server); $this->assertEquals('http://host/path/info?query=string', $request->getUri(), '->getUri() with rewrite and default port'); @@ -458,13 +559,13 @@ class RequestTest extends TestCase $server['SERVER_NAME'] = 'servername'; $server['SERVER_PORT'] = '80'; - $request->initialize(array(), array(), array(), array(), array(), $server); + $request->initialize([], [], [], [], [], $server); $this->assertEquals('http://servername/path/info?query=string', $request->getUri(), '->getUri() with rewrite, default port without HOST_HEADER'); // With encoded characters - $server = array( + $server = [ 'HTTP_HOST' => 'host:8080', 'SERVER_NAME' => 'servername', 'SERVER_PORT' => '8080', @@ -474,9 +575,9 @@ class RequestTest extends TestCase 'PATH_TRANSLATED' => 'redirect:/index.php/foo bar/in+fo', 'PHP_SELF' => '/ba se/index_dev.php/path/info', 'SCRIPT_FILENAME' => '/some/where/ba se/index_dev.php', - ); + ]; - $request->initialize(array(), array(), array(), array(), array(), $server); + $request->initialize([], [], [], [], [], $server); $this->assertEquals( 'http://host:8080/ba%20se/index_dev.php/foo%20bar/in+fo?query=string', @@ -486,11 +587,11 @@ class RequestTest extends TestCase // with user info $server['PHP_AUTH_USER'] = 'fabien'; - $request->initialize(array(), array(), array(), array(), array(), $server); + $request->initialize([], [], [], [], [], $server); $this->assertEquals('http://host:8080/ba%20se/index_dev.php/foo%20bar/in+fo?query=string', $request->getUri()); $server['PHP_AUTH_PW'] = 'symfony'; - $request->initialize(array(), array(), array(), array(), array(), $server); + $request->initialize([], [], [], [], [], $server); $this->assertEquals('http://host:8080/ba%20se/index_dev.php/foo%20bar/in+fo?query=string', $request->getUri()); } @@ -508,7 +609,7 @@ class RequestTest extends TestCase $request = Request::create('https://test.com:90/foo?bar=baz'); $this->assertEquals('https://test.com:90/some/path', $request->getUriForPath('/some/path')); - $server = array(); + $server = []; // Standard Request on non default PORT // http://host:8080/index.php/path/info?query=string @@ -527,7 +628,7 @@ class RequestTest extends TestCase $request = new Request(); - $request->initialize(array(), array(), array(), array(), array(), $server); + $request->initialize([], [], [], [], [], $server); $this->assertEquals('http://host:8080/index.php/some/path', $request->getUriForPath('/some/path'), '->getUriForPath() with non default port'); @@ -536,7 +637,7 @@ class RequestTest extends TestCase $server['SERVER_NAME'] = 'servername'; $server['SERVER_PORT'] = '80'; - $request->initialize(array(), array(), array(), array(), array(), $server); + $request->initialize([], [], [], [], [], $server); $this->assertEquals('http://host/index.php/some/path', $request->getUriForPath('/some/path'), '->getUriForPath() with default port'); @@ -545,7 +646,7 @@ class RequestTest extends TestCase $server['SERVER_NAME'] = 'servername'; $server['SERVER_PORT'] = '80'; - $request->initialize(array(), array(), array(), array(), array(), $server); + $request->initialize([], [], [], [], [], $server); $this->assertEquals('http://servername/index.php/some/path', $request->getUriForPath('/some/path'), '->getUriForPath() with default port without HOST_HEADER'); @@ -553,7 +654,7 @@ class RequestTest extends TestCase // RewriteCond %{REQUEST_FILENAME} !-f // RewriteRule ^(.*)$ index.php [QSA,L] // http://host:8080/path/info?query=string - $server = array(); + $server = []; $server['HTTP_HOST'] = 'host:8080'; $server['SERVER_NAME'] = 'servername'; $server['SERVER_PORT'] = '8080'; @@ -567,7 +668,7 @@ class RequestTest extends TestCase $server['PHP_SELF'] = '/index.php'; $server['SCRIPT_FILENAME'] = '/some/where/index.php'; - $request->initialize(array(), array(), array(), array(), array(), $server); + $request->initialize([], [], [], [], [], $server); $this->assertEquals('http://host:8080/some/path', $request->getUriForPath('/some/path'), '->getUri() with rewrite'); // Use std port number @@ -576,7 +677,7 @@ class RequestTest extends TestCase $server['SERVER_NAME'] = 'servername'; $server['SERVER_PORT'] = '80'; - $request->initialize(array(), array(), array(), array(), array(), $server); + $request->initialize([], [], [], [], [], $server); $this->assertEquals('http://host/some/path', $request->getUriForPath('/some/path'), '->getUriForPath() with rewrite and default port'); @@ -585,7 +686,7 @@ class RequestTest extends TestCase $server['SERVER_NAME'] = 'servername'; $server['SERVER_PORT'] = '80'; - $request->initialize(array(), array(), array(), array(), array(), $server); + $request->initialize([], [], [], [], [], $server); $this->assertEquals('http://servername/some/path', $request->getUriForPath('/some/path'), '->getUriForPath() with rewrite, default port without HOST_HEADER'); $this->assertEquals('servername', $request->getHttpHost()); @@ -593,11 +694,11 @@ class RequestTest extends TestCase // with user info $server['PHP_AUTH_USER'] = 'fabien'; - $request->initialize(array(), array(), array(), array(), array(), $server); + $request->initialize([], [], [], [], [], $server); $this->assertEquals('http://servername/some/path', $request->getUriForPath('/some/path')); $server['PHP_AUTH_PW'] = 'symfony'; - $request->initialize(array(), array(), array(), array(), array(), $server); + $request->initialize([], [], [], [], [], $server); $this->assertEquals('http://servername/some/path', $request->getUriForPath('/some/path')); } @@ -611,30 +712,30 @@ class RequestTest extends TestCase public function getRelativeUriForPathData() { - return array( - array('me.png', '/foo', '/me.png'), - array('../me.png', '/foo/bar', '/me.png'), - array('me.png', '/foo/bar', '/foo/me.png'), - array('../baz/me.png', '/foo/bar/b', '/foo/baz/me.png'), - array('../../fooz/baz/me.png', '/foo/bar/b', '/fooz/baz/me.png'), - array('baz/me.png', '/foo/bar/b', 'baz/me.png'), - ); + return [ + ['me.png', '/foo', '/me.png'], + ['../me.png', '/foo/bar', '/me.png'], + ['me.png', '/foo/bar', '/foo/me.png'], + ['../baz/me.png', '/foo/bar/b', '/foo/baz/me.png'], + ['../../fooz/baz/me.png', '/foo/bar/b', '/fooz/baz/me.png'], + ['baz/me.png', '/foo/bar/b', 'baz/me.png'], + ]; } public function testGetUserInfo() { $request = new Request(); - $server = array('PHP_AUTH_USER' => 'fabien'); - $request->initialize(array(), array(), array(), array(), array(), $server); + $server = ['PHP_AUTH_USER' => 'fabien']; + $request->initialize([], [], [], [], [], $server); $this->assertEquals('fabien', $request->getUserInfo()); $server['PHP_AUTH_USER'] = '0'; - $request->initialize(array(), array(), array(), array(), array(), $server); + $request->initialize([], [], [], [], [], $server); $this->assertEquals('0', $request->getUserInfo()); $server['PHP_AUTH_PW'] = '0'; - $request->initialize(array(), array(), array(), array(), array(), $server); + $request->initialize([], [], [], [], [], $server); $this->assertEquals('0:0', $request->getUserInfo()); } @@ -642,22 +743,22 @@ class RequestTest extends TestCase { $request = new Request(); - $server = array(); + $server = []; $server['SERVER_NAME'] = 'servername'; $server['SERVER_PORT'] = '90'; - $request->initialize(array(), array(), array(), array(), array(), $server); + $request->initialize([], [], [], [], [], $server); $this->assertEquals('http://servername:90', $request->getSchemeAndHttpHost()); $server['PHP_AUTH_USER'] = 'fabien'; - $request->initialize(array(), array(), array(), array(), array(), $server); + $request->initialize([], [], [], [], [], $server); $this->assertEquals('http://servername:90', $request->getSchemeAndHttpHost()); $server['PHP_AUTH_USER'] = '0'; - $request->initialize(array(), array(), array(), array(), array(), $server); + $request->initialize([], [], [], [], [], $server); $this->assertEquals('http://servername:90', $request->getSchemeAndHttpHost()); $server['PHP_AUTH_PW'] = '0'; - $request->initialize(array(), array(), array(), array(), array(), $server); + $request->initialize([], [], [], [], [], $server); $this->assertEquals('http://servername:90', $request->getSchemeAndHttpHost()); } @@ -674,29 +775,35 @@ class RequestTest extends TestCase public function getQueryStringNormalizationData() { - return array( - array('foo', 'foo', 'works with valueless parameters'), - array('foo=', 'foo=', 'includes a dangling equal sign'), - array('bar=&foo=bar', 'bar=&foo=bar', '->works with empty parameters'), - array('foo=bar&bar=', 'bar=&foo=bar', 'sorts keys alphabetically'), + return [ + ['foo', 'foo=', 'works with valueless parameters'], + ['foo=', 'foo=', 'includes a dangling equal sign'], + ['bar=&foo=bar', 'bar=&foo=bar', '->works with empty parameters'], + ['foo=bar&bar=', 'bar=&foo=bar', 'sorts keys alphabetically'], // GET parameters, that are submitted from a HTML form, encode spaces as "+" by default (as defined in enctype application/x-www-form-urlencoded). // PHP also converts "+" to spaces when filling the global _GET or when using the function parse_str. - array('him=John%20Doe&her=Jane+Doe', 'her=Jane%20Doe&him=John%20Doe', 'normalizes spaces in both encodings "%20" and "+"'), + ['baz=Foo%20Baz&bar=Foo+Bar', 'bar=Foo%20Bar&baz=Foo%20Baz', 'normalizes spaces in both encodings "%20" and "+"'], - array('foo[]=1&foo[]=2', 'foo%5B%5D=1&foo%5B%5D=2', 'allows array notation'), - array('foo=1&foo=2', 'foo=1&foo=2', 'allows repeated parameters'), - array('pa%3Dram=foo%26bar%3Dbaz&test=test', 'pa%3Dram=foo%26bar%3Dbaz&test=test', 'works with encoded delimiters'), - array('0', '0', 'allows "0"'), - array('Jane Doe&John%20Doe', 'Jane%20Doe&John%20Doe', 'normalizes encoding in keys'), - array('her=Jane Doe&him=John%20Doe', 'her=Jane%20Doe&him=John%20Doe', 'normalizes encoding in values'), - array('foo=bar&&&test&&', 'foo=bar&test', 'removes unneeded delimiters'), - array('formula=e=m*c^2', 'formula=e%3Dm%2Ac%5E2', 'correctly treats only the first "=" as delimiter and the next as value'), + ['foo[]=1&foo[]=2', 'foo%5B0%5D=1&foo%5B1%5D=2', 'allows array notation'], + ['foo=1&foo=2', 'foo=2', 'merges repeated parameters'], + ['pa%3Dram=foo%26bar%3Dbaz&test=test', 'pa%3Dram=foo%26bar%3Dbaz&test=test', 'works with encoded delimiters'], + ['0', '0=', 'allows "0"'], + ['Foo Bar&Foo%20Baz', 'Foo_Bar=&Foo_Baz=', 'normalizes encoding in keys'], + ['bar=Foo Bar&baz=Foo%20Baz', 'bar=Foo%20Bar&baz=Foo%20Baz', 'normalizes encoding in values'], + ['foo=bar&&&test&&', 'foo=bar&test=', 'removes unneeded delimiters'], + ['formula=e=m*c^2', 'formula=e%3Dm%2Ac%5E2', 'correctly treats only the first "=" as delimiter and the next as value'], // Ignore pairs with empty key, even if there was a value, e.g. "=value", as such nameless values cannot be retrieved anyway. // PHP also does not include them when building _GET. - array('foo=bar&=a=b&=x=y', 'foo=bar', 'removes params with empty key'), - ); + ['foo=bar&=a=b&=x=y', 'foo=bar', 'removes params with empty key'], + + // Don't reorder nested query string keys + ['foo[]=Z&foo[]=A', 'foo%5B0%5D=Z&foo%5B1%5D=A', 'keeps order of values'], + ['foo[Z]=B&foo[A]=B', 'foo%5BZ%5D=B&foo%5BA%5D=B', 'keeps order of keys'], + + ['utf8=✓', 'utf8=%E2%9C%93', 'encodes UTF-8'], + ]; } public function testGetQueryStringReturnsNull() @@ -713,85 +820,83 @@ class RequestTest extends TestCase { $request = new Request(); - $request->initialize(array('foo' => 'bar')); + $request->initialize(['foo' => 'bar']); $this->assertEquals('', $request->getHost(), '->getHost() return empty string if not initialized'); - $request->initialize(array(), array(), array(), array(), array(), array('HTTP_HOST' => 'www.example.com')); + $request->initialize([], [], [], [], [], ['HTTP_HOST' => 'www.example.com']); $this->assertEquals('www.example.com', $request->getHost(), '->getHost() from Host Header'); // Host header with port number - $request->initialize(array(), array(), array(), array(), array(), array('HTTP_HOST' => 'www.example.com:8080')); + $request->initialize([], [], [], [], [], ['HTTP_HOST' => 'www.example.com:8080']); $this->assertEquals('www.example.com', $request->getHost(), '->getHost() from Host Header with port number'); // Server values - $request->initialize(array(), array(), array(), array(), array(), array('SERVER_NAME' => 'www.example.com')); + $request->initialize([], [], [], [], [], ['SERVER_NAME' => 'www.example.com']); $this->assertEquals('www.example.com', $request->getHost(), '->getHost() from server name'); - $request->initialize(array(), array(), array(), array(), array(), array('SERVER_NAME' => 'www.example.com', 'HTTP_HOST' => 'www.host.com')); + $request->initialize([], [], [], [], [], ['SERVER_NAME' => 'www.example.com', 'HTTP_HOST' => 'www.host.com']); $this->assertEquals('www.host.com', $request->getHost(), '->getHost() value from Host header has priority over SERVER_NAME '); } public function testGetPort() { - $request = Request::create('http://example.com', 'GET', array(), array(), array(), array( + $request = Request::create('http://example.com', 'GET', [], [], [], [ 'HTTP_X_FORWARDED_PROTO' => 'https', 'HTTP_X_FORWARDED_PORT' => '443', - )); + ]); $port = $request->getPort(); $this->assertEquals(80, $port, 'Without trusted proxies FORWARDED_PROTO and FORWARDED_PORT are ignored.'); - Request::setTrustedProxies(array('1.1.1.1'), Request::HEADER_X_FORWARDED_ALL); - $request = Request::create('http://example.com', 'GET', array(), array(), array(), array( + Request::setTrustedProxies(['1.1.1.1'], Request::HEADER_X_FORWARDED_ALL); + $request = Request::create('http://example.com', 'GET', [], [], [], [ 'HTTP_X_FORWARDED_PROTO' => 'https', 'HTTP_X_FORWARDED_PORT' => '8443', - )); + ]); $this->assertEquals(80, $request->getPort(), 'With PROTO and PORT on untrusted connection server value takes precedence.'); $request->server->set('REMOTE_ADDR', '1.1.1.1'); $this->assertEquals(8443, $request->getPort(), 'With PROTO and PORT set PORT takes precedence.'); - $request = Request::create('http://example.com', 'GET', array(), array(), array(), array( + $request = Request::create('http://example.com', 'GET', [], [], [], [ 'HTTP_X_FORWARDED_PROTO' => 'https', - )); + ]); $this->assertEquals(80, $request->getPort(), 'With only PROTO set getPort() ignores trusted headers on untrusted connection.'); $request->server->set('REMOTE_ADDR', '1.1.1.1'); $this->assertEquals(443, $request->getPort(), 'With only PROTO set getPort() defaults to 443.'); - $request = Request::create('http://example.com', 'GET', array(), array(), array(), array( + $request = Request::create('http://example.com', 'GET', [], [], [], [ 'HTTP_X_FORWARDED_PROTO' => 'http', - )); + ]); $this->assertEquals(80, $request->getPort(), 'If X_FORWARDED_PROTO is set to HTTP getPort() ignores trusted headers on untrusted connection.'); $request->server->set('REMOTE_ADDR', '1.1.1.1'); $this->assertEquals(80, $request->getPort(), 'If X_FORWARDED_PROTO is set to HTTP getPort() returns port of the original request.'); - $request = Request::create('http://example.com', 'GET', array(), array(), array(), array( + $request = Request::create('http://example.com', 'GET', [], [], [], [ 'HTTP_X_FORWARDED_PROTO' => 'On', - )); + ]); $this->assertEquals(80, $request->getPort(), 'With only PROTO set and value is On, getPort() ignores trusted headers on untrusted connection.'); $request->server->set('REMOTE_ADDR', '1.1.1.1'); $this->assertEquals(443, $request->getPort(), 'With only PROTO set and value is On, getPort() defaults to 443.'); - $request = Request::create('http://example.com', 'GET', array(), array(), array(), array( + $request = Request::create('http://example.com', 'GET', [], [], [], [ 'HTTP_X_FORWARDED_PROTO' => '1', - )); + ]); $this->assertEquals(80, $request->getPort(), 'With only PROTO set and value is 1, getPort() ignores trusted headers on untrusted connection.'); $request->server->set('REMOTE_ADDR', '1.1.1.1'); $this->assertEquals(443, $request->getPort(), 'With only PROTO set and value is 1, getPort() defaults to 443.'); - $request = Request::create('http://example.com', 'GET', array(), array(), array(), array( + $request = Request::create('http://example.com', 'GET', [], [], [], [ 'HTTP_X_FORWARDED_PROTO' => 'something-else', - )); + ]); $port = $request->getPort(); $this->assertEquals(80, $port, 'With only PROTO set and value is not recognized, getPort() defaults to 80.'); } - /** - * @expectedException \RuntimeException - */ public function testGetHostWithFakeHttpHostValue() { + $this->expectException('RuntimeException'); $request = new Request(); - $request->initialize(array(), array(), array(), array(), array(), array('HTTP_HOST' => 'www.host.com?query=string')); + $request->initialize([], [], [], [], [], ['HTTP_HOST' => 'www.host.com?query=string']); $request->getHost(); } @@ -848,6 +953,11 @@ class RequestTest extends TestCase $request->setMethod('POST'); $request->headers->set('X-HTTP-METHOD-OVERRIDE', 'delete'); $this->assertEquals('DELETE', $request->getMethod(), '->getMethod() returns the method from X-HTTP-Method-Override if defined and POST'); + + $request = new Request(); + $request->setMethod('POST'); + $request->query->set('_method', ['delete', 'patch']); + $this->assertSame('POST', $request->getMethod(), '->getMethod() returns the request method if invalid type is defined in query'); } /** @@ -883,88 +993,88 @@ class RequestTest extends TestCase public function getClientIpsForwardedProvider() { // $expected $remoteAddr $httpForwarded $trustedProxies - return array( - array(array('127.0.0.1'), '127.0.0.1', 'for="_gazonk"', null), - array(array('127.0.0.1'), '127.0.0.1', 'for="_gazonk"', array('127.0.0.1')), - array(array('88.88.88.88'), '127.0.0.1', 'for="88.88.88.88:80"', array('127.0.0.1')), - array(array('192.0.2.60'), '::1', 'for=192.0.2.60;proto=http;by=203.0.113.43', array('::1')), - array(array('2620:0:1cfe:face:b00c::3', '192.0.2.43'), '::1', 'for=192.0.2.43, for=2620:0:1cfe:face:b00c::3', array('::1')), - array(array('2001:db8:cafe::17'), '::1', 'for="[2001:db8:cafe::17]:4711', array('::1')), - ); + return [ + [['127.0.0.1'], '127.0.0.1', 'for="_gazonk"', null], + [['127.0.0.1'], '127.0.0.1', 'for="_gazonk"', ['127.0.0.1']], + [['88.88.88.88'], '127.0.0.1', 'for="88.88.88.88:80"', ['127.0.0.1']], + [['192.0.2.60'], '::1', 'for=192.0.2.60;proto=http;by=203.0.113.43', ['::1']], + [['2620:0:1cfe:face:b00c::3', '192.0.2.43'], '::1', 'for=192.0.2.43, for="[2620:0:1cfe:face:b00c::3]"', ['::1']], + [['2001:db8:cafe::17'], '::1', 'for="[2001:db8:cafe::17]:4711', ['::1']], + ]; } public function getClientIpsProvider() { - // $expected $remoteAddr $httpForwardedFor $trustedProxies - return array( + // $expected $remoteAddr $httpForwardedFor $trustedProxies + return [ // simple IPv4 - array(array('88.88.88.88'), '88.88.88.88', null, null), + [['88.88.88.88'], '88.88.88.88', null, null], // trust the IPv4 remote addr - array(array('88.88.88.88'), '88.88.88.88', null, array('88.88.88.88')), + [['88.88.88.88'], '88.88.88.88', null, ['88.88.88.88']], // simple IPv6 - array(array('::1'), '::1', null, null), + [['::1'], '::1', null, null], // trust the IPv6 remote addr - array(array('::1'), '::1', null, array('::1')), + [['::1'], '::1', null, ['::1']], // forwarded for with remote IPv4 addr not trusted - array(array('127.0.0.1'), '127.0.0.1', '88.88.88.88', null), - // forwarded for with remote IPv4 addr trusted - array(array('88.88.88.88'), '127.0.0.1', '88.88.88.88', array('127.0.0.1')), + [['127.0.0.1'], '127.0.0.1', '88.88.88.88', null], + // forwarded for with remote IPv4 addr trusted + comma + [['88.88.88.88'], '127.0.0.1', '88.88.88.88,', ['127.0.0.1']], // forwarded for with remote IPv4 and all FF addrs trusted - array(array('88.88.88.88'), '127.0.0.1', '88.88.88.88', array('127.0.0.1', '88.88.88.88')), + [['88.88.88.88'], '127.0.0.1', '88.88.88.88', ['127.0.0.1', '88.88.88.88']], // forwarded for with remote IPv4 range trusted - array(array('88.88.88.88'), '123.45.67.89', '88.88.88.88', array('123.45.67.0/24')), + [['88.88.88.88'], '123.45.67.89', '88.88.88.88', ['123.45.67.0/24']], // forwarded for with remote IPv6 addr not trusted - array(array('1620:0:1cfe:face:b00c::3'), '1620:0:1cfe:face:b00c::3', '2620:0:1cfe:face:b00c::3', null), + [['1620:0:1cfe:face:b00c::3'], '1620:0:1cfe:face:b00c::3', '2620:0:1cfe:face:b00c::3', null], // forwarded for with remote IPv6 addr trusted - array(array('2620:0:1cfe:face:b00c::3'), '1620:0:1cfe:face:b00c::3', '2620:0:1cfe:face:b00c::3', array('1620:0:1cfe:face:b00c::3')), + [['2620:0:1cfe:face:b00c::3'], '1620:0:1cfe:face:b00c::3', '2620:0:1cfe:face:b00c::3', ['1620:0:1cfe:face:b00c::3']], // forwarded for with remote IPv6 range trusted - array(array('88.88.88.88'), '2a01:198:603:0:396e:4789:8e99:890f', '88.88.88.88', array('2a01:198:603:0::/65')), + [['88.88.88.88'], '2a01:198:603:0:396e:4789:8e99:890f', '88.88.88.88', ['2a01:198:603:0::/65']], // multiple forwarded for with remote IPv4 addr trusted - array(array('88.88.88.88', '87.65.43.21', '127.0.0.1'), '123.45.67.89', '127.0.0.1, 87.65.43.21, 88.88.88.88', array('123.45.67.89')), + [['88.88.88.88', '87.65.43.21', '127.0.0.1'], '123.45.67.89', '127.0.0.1, 87.65.43.21, 88.88.88.88', ['123.45.67.89']], // multiple forwarded for with remote IPv4 addr and some reverse proxies trusted - array(array('87.65.43.21', '127.0.0.1'), '123.45.67.89', '127.0.0.1, 87.65.43.21, 88.88.88.88', array('123.45.67.89', '88.88.88.88')), + [['87.65.43.21', '127.0.0.1'], '123.45.67.89', '127.0.0.1, 87.65.43.21, 88.88.88.88', ['123.45.67.89', '88.88.88.88']], // multiple forwarded for with remote IPv4 addr and some reverse proxies trusted but in the middle - array(array('88.88.88.88', '127.0.0.1'), '123.45.67.89', '127.0.0.1, 87.65.43.21, 88.88.88.88', array('123.45.67.89', '87.65.43.21')), + [['88.88.88.88', '127.0.0.1'], '123.45.67.89', '127.0.0.1, 87.65.43.21, 88.88.88.88', ['123.45.67.89', '87.65.43.21']], // multiple forwarded for with remote IPv4 addr and all reverse proxies trusted - array(array('127.0.0.1'), '123.45.67.89', '127.0.0.1, 87.65.43.21, 88.88.88.88', array('123.45.67.89', '87.65.43.21', '88.88.88.88', '127.0.0.1')), + [['127.0.0.1'], '123.45.67.89', '127.0.0.1, 87.65.43.21, 88.88.88.88', ['123.45.67.89', '87.65.43.21', '88.88.88.88', '127.0.0.1']], // multiple forwarded for with remote IPv6 addr trusted - array(array('2620:0:1cfe:face:b00c::3', '3620:0:1cfe:face:b00c::3'), '1620:0:1cfe:face:b00c::3', '3620:0:1cfe:face:b00c::3,2620:0:1cfe:face:b00c::3', array('1620:0:1cfe:face:b00c::3')), + [['2620:0:1cfe:face:b00c::3', '3620:0:1cfe:face:b00c::3'], '1620:0:1cfe:face:b00c::3', '3620:0:1cfe:face:b00c::3,2620:0:1cfe:face:b00c::3', ['1620:0:1cfe:face:b00c::3']], // multiple forwarded for with remote IPv6 addr and some reverse proxies trusted - array(array('3620:0:1cfe:face:b00c::3'), '1620:0:1cfe:face:b00c::3', '3620:0:1cfe:face:b00c::3,2620:0:1cfe:face:b00c::3', array('1620:0:1cfe:face:b00c::3', '2620:0:1cfe:face:b00c::3')), + [['3620:0:1cfe:face:b00c::3'], '1620:0:1cfe:face:b00c::3', '3620:0:1cfe:face:b00c::3,2620:0:1cfe:face:b00c::3', ['1620:0:1cfe:face:b00c::3', '2620:0:1cfe:face:b00c::3']], // multiple forwarded for with remote IPv4 addr and some reverse proxies trusted but in the middle - array(array('2620:0:1cfe:face:b00c::3', '4620:0:1cfe:face:b00c::3'), '1620:0:1cfe:face:b00c::3', '4620:0:1cfe:face:b00c::3,3620:0:1cfe:face:b00c::3,2620:0:1cfe:face:b00c::3', array('1620:0:1cfe:face:b00c::3', '3620:0:1cfe:face:b00c::3')), + [['2620:0:1cfe:face:b00c::3', '4620:0:1cfe:face:b00c::3'], '1620:0:1cfe:face:b00c::3', '4620:0:1cfe:face:b00c::3,3620:0:1cfe:face:b00c::3,2620:0:1cfe:face:b00c::3', ['1620:0:1cfe:face:b00c::3', '3620:0:1cfe:face:b00c::3']], // client IP with port - array(array('88.88.88.88'), '127.0.0.1', '88.88.88.88:12345, 127.0.0.1', array('127.0.0.1')), + [['88.88.88.88'], '127.0.0.1', '88.88.88.88:12345, 127.0.0.1', ['127.0.0.1']], // invalid forwarded IP is ignored - array(array('88.88.88.88'), '127.0.0.1', 'unknown,88.88.88.88', array('127.0.0.1')), - array(array('88.88.88.88'), '127.0.0.1', '}__test|O:21:"JDatabaseDriverMysqli":3:{s:2,88.88.88.88', array('127.0.0.1')), - ); + [['88.88.88.88'], '127.0.0.1', 'unknown,88.88.88.88', ['127.0.0.1']], + [['88.88.88.88'], '127.0.0.1', '}__test|O:21:"JDatabaseDriverMysqli":3:{s:2,88.88.88.88', ['127.0.0.1']], + ]; } /** - * @expectedException \Symfony\Component\HttpFoundation\Exception\ConflictingHeadersException * @dataProvider getClientIpsWithConflictingHeadersProvider */ public function testGetClientIpsWithConflictingHeaders($httpForwarded, $httpXForwardedFor) { + $this->expectException('Symfony\Component\HttpFoundation\Exception\ConflictingHeadersException'); $request = new Request(); - $server = array( + $server = [ 'REMOTE_ADDR' => '88.88.88.88', 'HTTP_FORWARDED' => $httpForwarded, 'HTTP_X_FORWARDED_FOR' => $httpXForwardedFor, - ); + ]; - Request::setTrustedProxies(array('88.88.88.88'), Request::HEADER_X_FORWARDED_ALL | Request::HEADER_FORWARDED); + Request::setTrustedProxies(['88.88.88.88'], Request::HEADER_X_FORWARDED_ALL | Request::HEADER_FORWARDED); - $request->initialize(array(), array(), array(), array(), array(), $server); + $request->initialize([], [], [], [], [], $server); $request->getClientIps(); } @@ -976,15 +1086,15 @@ class RequestTest extends TestCase { $request = new Request(); - $server = array( + $server = [ 'REMOTE_ADDR' => '88.88.88.88', 'HTTP_FORWARDED' => $httpForwarded, 'HTTP_X_FORWARDED_FOR' => $httpXForwardedFor, - ); + ]; - Request::setTrustedProxies(array('88.88.88.88'), Request::HEADER_X_FORWARDED_FOR); + Request::setTrustedProxies(['88.88.88.88'], Request::HEADER_X_FORWARDED_FOR); - $request->initialize(array(), array(), array(), array(), array(), $server); + $request->initialize([], [], [], [], [], $server); $this->assertSame(array_reverse(explode(',', $httpXForwardedFor)), $request->getClientIps()); } @@ -992,13 +1102,13 @@ class RequestTest extends TestCase public function getClientIpsWithConflictingHeadersProvider() { // $httpForwarded $httpXForwardedFor - return array( - array('for=87.65.43.21', '192.0.2.60'), - array('for=87.65.43.21, for=192.0.2.60', '192.0.2.60'), - array('for=192.0.2.60', '192.0.2.60,87.65.43.21'), - array('for="::face", for=192.0.2.60', '192.0.2.60,192.0.2.43'), - array('for=87.65.43.21, for=192.0.2.60', '192.0.2.60,87.65.43.21'), - ); + return [ + ['for=87.65.43.21', '192.0.2.60'], + ['for=87.65.43.21, for=192.0.2.60', '192.0.2.60'], + ['for=192.0.2.60', '192.0.2.60,87.65.43.21'], + ['for="::face", for=192.0.2.60', '192.0.2.60,192.0.2.43'], + ['for=87.65.43.21, for=192.0.2.60', '192.0.2.60,87.65.43.21'], + ]; } /** @@ -1008,15 +1118,15 @@ class RequestTest extends TestCase { $request = new Request(); - $server = array( + $server = [ 'REMOTE_ADDR' => '88.88.88.88', 'HTTP_FORWARDED' => $httpForwarded, 'HTTP_X_FORWARDED_FOR' => $httpXForwardedFor, - ); + ]; - Request::setTrustedProxies(array('88.88.88.88'), Request::HEADER_X_FORWARDED_ALL); + Request::setTrustedProxies(['88.88.88.88'], -1); - $request->initialize(array(), array(), array(), array(), array(), $server); + $request->initialize([], [], [], [], [], $server); $clientIps = $request->getClientIps(); @@ -1026,14 +1136,14 @@ class RequestTest extends TestCase public function getClientIpsWithAgreeingHeadersProvider() { // $httpForwarded $httpXForwardedFor - return array( - array('for="192.0.2.60"', '192.0.2.60', array('192.0.2.60')), - array('for=192.0.2.60, for=87.65.43.21', '192.0.2.60,87.65.43.21', array('87.65.43.21', '192.0.2.60')), - array('for="[::face]", for=192.0.2.60', '::face,192.0.2.60', array('192.0.2.60', '::face')), - array('for="192.0.2.60:80"', '192.0.2.60', array('192.0.2.60')), - array('for=192.0.2.60;proto=http;by=203.0.113.43', '192.0.2.60', array('192.0.2.60')), - array('for="[2001:db8:cafe::17]:4711"', '2001:db8:cafe::17', array('2001:db8:cafe::17')), - ); + return [ + ['for="192.0.2.60"', '192.0.2.60', ['192.0.2.60']], + ['for=192.0.2.60, for=87.65.43.21', '192.0.2.60,87.65.43.21', ['87.65.43.21', '192.0.2.60']], + ['for="[::face]", for=192.0.2.60', '::face,192.0.2.60', ['192.0.2.60', '::face']], + ['for="192.0.2.60:80"', '192.0.2.60', ['192.0.2.60']], + ['for=192.0.2.60;proto=http;by=203.0.113.43', '192.0.2.60', ['192.0.2.60']], + ['for="[2001:db8:cafe::17]:4711"', '2001:db8:cafe::17', ['2001:db8:cafe::17']], + ]; } public function testGetContentWorksTwiceInDefaultMode() @@ -1047,17 +1157,17 @@ class RequestTest extends TestCase { $req = new Request(); $retval = $req->getContent(true); - $this->assertInternalType('resource', $retval); + $this->assertIsResource($retval); $this->assertEquals('', fread($retval, 1)); $this->assertTrue(feof($retval)); } public function testGetContentReturnsResourceWhenContentSetInConstructor() { - $req = new Request(array(), array(), array(), array(), array(), array(), 'MyContent'); + $req = new Request([], [], [], [], [], [], 'MyContent'); $resource = $req->getContent(true); - $this->assertInternalType('resource', $resource); + $this->assertIsResource($resource); $this->assertEquals('MyContent', stream_get_contents($resource)); } @@ -1067,37 +1177,21 @@ class RequestTest extends TestCase fwrite($resource, 'My other content'); rewind($resource); - $req = new Request(array(), array(), array(), array(), array(), array(), $resource); + $req = new Request([], [], [], [], [], [], $resource); $this->assertEquals('My other content', stream_get_contents($req->getContent(true))); $this->assertEquals('My other content', $req->getContent()); } - /** - * @expectedException \LogicException - * @dataProvider getContentCantBeCalledTwiceWithResourcesProvider - */ - public function testGetContentCantBeCalledTwiceWithResources($first, $second) - { - if (\PHP_VERSION_ID >= 50600) { - $this->markTestSkipped('PHP >= 5.6 allows to open php://input several times.'); - } - - $req = new Request(); - $req->getContent($first); - $req->getContent($second); - } - public function getContentCantBeCalledTwiceWithResourcesProvider() { - return array( - 'Resource then fetch' => array(true, false), - 'Resource then resource' => array(true, true), - ); + return [ + 'Resource then fetch' => [true, false], + 'Resource then resource' => [true, true], + ]; } /** * @dataProvider getContentCanBeCalledTwiceWithResourcesProvider - * @requires PHP 5.6 */ public function testGetContentCanBeCalledTwiceWithResources($first, $second) { @@ -1118,24 +1212,24 @@ class RequestTest extends TestCase public function getContentCanBeCalledTwiceWithResourcesProvider() { - return array( - 'Fetch then fetch' => array(false, false), - 'Fetch then resource' => array(false, true), - 'Resource then fetch' => array(true, false), - 'Resource then resource' => array(true, true), - ); + return [ + 'Fetch then fetch' => [false, false], + 'Fetch then resource' => [false, true], + 'Resource then fetch' => [true, false], + 'Resource then resource' => [true, true], + ]; } public function provideOverloadedMethods() { - return array( - array('PUT'), - array('DELETE'), - array('PATCH'), - array('put'), - array('delete'), - array('patch'), - ); + return [ + ['PUT'], + ['DELETE'], + ['PATCH'], + ['put'], + ['delete'], + ['patch'], + ]; } /** @@ -1148,14 +1242,14 @@ class RequestTest extends TestCase $_GET['foo1'] = 'bar1'; $_POST['foo2'] = 'bar2'; $_COOKIE['foo3'] = 'bar3'; - $_FILES['foo4'] = array('bar4'); + $_FILES['foo4'] = ['bar4']; $_SERVER['foo5'] = 'bar5'; $request = Request::createFromGlobals(); $this->assertEquals('bar1', $request->query->get('foo1'), '::fromGlobals() uses values from $_GET'); $this->assertEquals('bar2', $request->request->get('foo2'), '::fromGlobals() uses values from $_POST'); $this->assertEquals('bar3', $request->cookies->get('foo3'), '::fromGlobals() uses values from $_COOKIE'); - $this->assertEquals(array('bar4'), $request->files->get('foo4'), '::fromGlobals() uses values from $_FILES'); + $this->assertEquals(['bar4'], $request->files->get('foo4'), '::fromGlobals() uses values from $_FILES'); $this->assertEquals('bar5', $request->server->get('foo5'), '::fromGlobals() uses values from $_SERVER'); unset($_GET['foo1'], $_POST['foo2'], $_COOKIE['foo3'], $_FILES['foo4'], $_SERVER['foo5']); @@ -1185,25 +1279,25 @@ class RequestTest extends TestCase public function testOverrideGlobals() { $request = new Request(); - $request->initialize(array('foo' => 'bar')); + $request->initialize(['foo' => 'bar']); // as the Request::overrideGlobals really work, it erase $_SERVER, so we must backup it $server = $_SERVER; $request->overrideGlobals(); - $this->assertEquals(array('foo' => 'bar'), $_GET); + $this->assertEquals(['foo' => 'bar'], $_GET); - $request->initialize(array(), array('foo' => 'bar')); + $request->initialize([], ['foo' => 'bar']); $request->overrideGlobals(); - $this->assertEquals(array('foo' => 'bar'), $_POST); + $this->assertEquals(['foo' => 'bar'], $_POST); $this->assertArrayNotHasKey('HTTP_X_FORWARDED_PROTO', $_SERVER); $request->headers->set('X_FORWARDED_PROTO', 'https'); - Request::setTrustedProxies(array('1.1.1.1'), Request::HEADER_X_FORWARDED_ALL); + Request::setTrustedProxies(['1.1.1.1'], Request::HEADER_X_FORWARDED_ALL); $this->assertFalse($request->isSecure()); $request->server->set('REMOTE_ADDR', '1.1.1.1'); $this->assertTrue($request->isSecure()); @@ -1220,12 +1314,12 @@ class RequestTest extends TestCase $this->assertArrayHasKey('CONTENT_TYPE', $_SERVER); $this->assertArrayHasKey('CONTENT_LENGTH', $_SERVER); - $request->initialize(array('foo' => 'bar', 'baz' => 'foo')); + $request->initialize(['foo' => 'bar', 'baz' => 'foo']); $request->query->remove('baz'); $request->overrideGlobals(); - $this->assertEquals(array('foo' => 'bar'), $_GET); + $this->assertEquals(['foo' => 'bar'], $_GET); $this->assertEquals('foo=bar', $_SERVER['QUERY_STRING']); $this->assertEquals('foo=bar', $request->server->get('QUERY_STRING')); @@ -1238,23 +1332,23 @@ class RequestTest extends TestCase $request = new Request(); $this->assertEquals('', $request->getScriptName()); - $server = array(); + $server = []; $server['SCRIPT_NAME'] = '/index.php'; - $request->initialize(array(), array(), array(), array(), array(), $server); + $request->initialize([], [], [], [], [], $server); $this->assertEquals('/index.php', $request->getScriptName()); - $server = array(); + $server = []; $server['ORIG_SCRIPT_NAME'] = '/frontend.php'; - $request->initialize(array(), array(), array(), array(), array(), $server); + $request->initialize([], [], [], [], [], $server); $this->assertEquals('/frontend.php', $request->getScriptName()); - $server = array(); + $server = []; $server['SCRIPT_NAME'] = '/index.php'; $server['ORIG_SCRIPT_NAME'] = '/frontend.php'; - $request->initialize(array(), array(), array(), array(), array(), $server); + $request->initialize([], [], [], [], [], $server); $this->assertEquals('/index.php', $request->getScriptName()); } @@ -1264,29 +1358,29 @@ class RequestTest extends TestCase $request = new Request(); $this->assertEquals('', $request->getBasePath()); - $server = array(); + $server = []; $server['SCRIPT_FILENAME'] = '/some/where/index.php'; - $request->initialize(array(), array(), array(), array(), array(), $server); + $request->initialize([], [], [], [], [], $server); $this->assertEquals('', $request->getBasePath()); - $server = array(); + $server = []; $server['SCRIPT_FILENAME'] = '/some/where/index.php'; $server['SCRIPT_NAME'] = '/index.php'; - $request->initialize(array(), array(), array(), array(), array(), $server); + $request->initialize([], [], [], [], [], $server); $this->assertEquals('', $request->getBasePath()); - $server = array(); + $server = []; $server['SCRIPT_FILENAME'] = '/some/where/index.php'; $server['PHP_SELF'] = '/index.php'; - $request->initialize(array(), array(), array(), array(), array(), $server); + $request->initialize([], [], [], [], [], $server); $this->assertEquals('', $request->getBasePath()); - $server = array(); + $server = []; $server['SCRIPT_FILENAME'] = '/some/where/index.php'; $server['ORIG_SCRIPT_NAME'] = '/index.php'; - $request->initialize(array(), array(), array(), array(), array(), $server); + $request->initialize([], [], [], [], [], $server); $this->assertEquals('', $request->getBasePath()); } @@ -1296,21 +1390,21 @@ class RequestTest extends TestCase $request = new Request(); $this->assertEquals('/', $request->getPathInfo()); - $server = array(); + $server = []; $server['REQUEST_URI'] = '/path/info'; - $request->initialize(array(), array(), array(), array(), array(), $server); + $request->initialize([], [], [], [], [], $server); $this->assertEquals('/path/info', $request->getPathInfo()); - $server = array(); + $server = []; $server['REQUEST_URI'] = '/path%20test/info'; - $request->initialize(array(), array(), array(), array(), array(), $server); + $request->initialize([], [], [], [], [], $server); $this->assertEquals('/path%20test/info', $request->getPathInfo()); - $server = array(); + $server = []; $server['REQUEST_URI'] = '?a=b'; - $request->initialize(array(), array(), array(), array(), array(), $server); + $request->initialize([], [], [], [], [], $server); $this->assertEquals('/', $request->getPathInfo()); } @@ -1338,27 +1432,27 @@ class RequestTest extends TestCase { $request = new Request(); $this->assertNull($request->getPreferredLanguage()); - $this->assertNull($request->getPreferredLanguage(array())); - $this->assertEquals('fr', $request->getPreferredLanguage(array('fr'))); - $this->assertEquals('fr', $request->getPreferredLanguage(array('fr', 'en'))); - $this->assertEquals('en', $request->getPreferredLanguage(array('en', 'fr'))); - $this->assertEquals('fr-ch', $request->getPreferredLanguage(array('fr-ch', 'fr-fr'))); + $this->assertNull($request->getPreferredLanguage([])); + $this->assertEquals('fr', $request->getPreferredLanguage(['fr'])); + $this->assertEquals('fr', $request->getPreferredLanguage(['fr', 'en'])); + $this->assertEquals('en', $request->getPreferredLanguage(['en', 'fr'])); + $this->assertEquals('fr-ch', $request->getPreferredLanguage(['fr-ch', 'fr-fr'])); $request = new Request(); $request->headers->set('Accept-language', 'zh, en-us; q=0.8, en; q=0.6'); - $this->assertEquals('en', $request->getPreferredLanguage(array('en', 'en-us'))); + $this->assertEquals('en', $request->getPreferredLanguage(['en', 'en-us'])); $request = new Request(); $request->headers->set('Accept-language', 'zh, en-us; q=0.8, en; q=0.6'); - $this->assertEquals('en', $request->getPreferredLanguage(array('fr', 'en'))); + $this->assertEquals('en', $request->getPreferredLanguage(['fr', 'en'])); $request = new Request(); $request->headers->set('Accept-language', 'zh, en-us; q=0.8'); - $this->assertEquals('en', $request->getPreferredLanguage(array('fr', 'en'))); + $this->assertEquals('en', $request->getPreferredLanguage(['fr', 'en'])); $request = new Request(); $request->headers->set('Accept-language', 'zh, en-us; q=0.8, fr-fr; q=0.6, fr; q=0.5'); - $this->assertEquals('en', $request->getPreferredLanguage(array('fr', 'en'))); + $this->assertEquals('en', $request->getPreferredLanguage(['fr', 'en'])); } public function testIsXmlHttpRequest() @@ -1396,72 +1490,71 @@ class RequestTest extends TestCase public function testGetCharsets() { $request = new Request(); - $this->assertEquals(array(), $request->getCharsets()); + $this->assertEquals([], $request->getCharsets()); $request->headers->set('Accept-Charset', 'ISO-8859-1, US-ASCII, UTF-8; q=0.8, ISO-10646-UCS-2; q=0.6'); - $this->assertEquals(array(), $request->getCharsets()); // testing caching + $this->assertEquals([], $request->getCharsets()); // testing caching $request = new Request(); $request->headers->set('Accept-Charset', 'ISO-8859-1, US-ASCII, UTF-8; q=0.8, ISO-10646-UCS-2; q=0.6'); - $this->assertEquals(array('ISO-8859-1', 'US-ASCII', 'UTF-8', 'ISO-10646-UCS-2'), $request->getCharsets()); + $this->assertEquals(['ISO-8859-1', 'US-ASCII', 'UTF-8', 'ISO-10646-UCS-2'], $request->getCharsets()); $request = new Request(); $request->headers->set('Accept-Charset', 'ISO-8859-1,utf-8;q=0.7,*;q=0.7'); - $this->assertEquals(array('ISO-8859-1', 'utf-8', '*'), $request->getCharsets()); + $this->assertEquals(['ISO-8859-1', 'utf-8', '*'], $request->getCharsets()); } public function testGetEncodings() { $request = new Request(); - $this->assertEquals(array(), $request->getEncodings()); + $this->assertEquals([], $request->getEncodings()); $request->headers->set('Accept-Encoding', 'gzip,deflate,sdch'); - $this->assertEquals(array(), $request->getEncodings()); // testing caching + $this->assertEquals([], $request->getEncodings()); // testing caching $request = new Request(); $request->headers->set('Accept-Encoding', 'gzip,deflate,sdch'); - $this->assertEquals(array('gzip', 'deflate', 'sdch'), $request->getEncodings()); + $this->assertEquals(['gzip', 'deflate', 'sdch'], $request->getEncodings()); $request = new Request(); $request->headers->set('Accept-Encoding', 'gzip;q=0.4,deflate;q=0.9,compress;q=0.7'); - $this->assertEquals(array('deflate', 'compress', 'gzip'), $request->getEncodings()); + $this->assertEquals(['deflate', 'compress', 'gzip'], $request->getEncodings()); } public function testGetAcceptableContentTypes() { $request = new Request(); - $this->assertEquals(array(), $request->getAcceptableContentTypes()); + $this->assertEquals([], $request->getAcceptableContentTypes()); $request->headers->set('Accept', 'application/vnd.wap.wmlscriptc, text/vnd.wap.wml, application/vnd.wap.xhtml+xml, application/xhtml+xml, text/html, multipart/mixed, */*'); - $this->assertEquals(array(), $request->getAcceptableContentTypes()); // testing caching + $this->assertEquals([], $request->getAcceptableContentTypes()); // testing caching $request = new Request(); $request->headers->set('Accept', 'application/vnd.wap.wmlscriptc, text/vnd.wap.wml, application/vnd.wap.xhtml+xml, application/xhtml+xml, text/html, multipart/mixed, */*'); - $this->assertEquals(array('application/vnd.wap.wmlscriptc', 'text/vnd.wap.wml', 'application/vnd.wap.xhtml+xml', 'application/xhtml+xml', 'text/html', 'multipart/mixed', '*/*'), $request->getAcceptableContentTypes()); + $this->assertEquals(['application/vnd.wap.wmlscriptc', 'text/vnd.wap.wml', 'application/vnd.wap.xhtml+xml', 'application/xhtml+xml', 'text/html', 'multipart/mixed', '*/*'], $request->getAcceptableContentTypes()); } public function testGetLanguages() { $request = new Request(); - $this->assertEquals(array(), $request->getLanguages()); + $this->assertEquals([], $request->getLanguages()); $request = new Request(); $request->headers->set('Accept-language', 'zh, en-us; q=0.8, en; q=0.6'); - $this->assertEquals(array('zh', 'en_US', 'en'), $request->getLanguages()); - $this->assertEquals(array('zh', 'en_US', 'en'), $request->getLanguages()); + $this->assertEquals(['zh', 'en_US', 'en'], $request->getLanguages()); $request = new Request(); $request->headers->set('Accept-language', 'zh, en-us; q=0.6, en; q=0.8'); - $this->assertEquals(array('zh', 'en', 'en_US'), $request->getLanguages()); // Test out of order qvalues + $this->assertEquals(['zh', 'en', 'en_US'], $request->getLanguages()); // Test out of order qvalues $request = new Request(); $request->headers->set('Accept-language', 'zh, en, en-us'); - $this->assertEquals(array('zh', 'en', 'en_US'), $request->getLanguages()); // Test equal weighting without qvalues + $this->assertEquals(['zh', 'en', 'en_US'], $request->getLanguages()); // Test equal weighting without qvalues $request = new Request(); $request->headers->set('Accept-language', 'zh; q=0.6, en, en-us; q=0.6'); - $this->assertEquals(array('en', 'zh', 'en_US'), $request->getLanguages()); // Test equal weighting with qvalues + $this->assertEquals(['en', 'zh', 'en_US'], $request->getLanguages()); // Test equal weighting with qvalues $request = new Request(); $request->headers->set('Accept-language', 'zh, i-cherokee; q=0.6'); - $this->assertEquals(array('zh', 'cherokee'), $request->getLanguages()); + $this->assertEquals(['zh', 'cherokee'], $request->getLanguages()); } public function testGetRequestFormat() @@ -1481,7 +1574,7 @@ class RequestTest extends TestCase $this->assertNull($request->setRequestFormat('foo')); $this->assertEquals('foo', $request->getRequestFormat(null)); - $request = new Request(array('_format' => 'foo')); + $request = new Request(['_format' => 'foo']); $this->assertEquals('html', $request->getRequestFormat()); } @@ -1507,6 +1600,15 @@ class RequestTest extends TestCase $this->assertObjectHasAttribute('attributeName', $session); } + /** + * @group legacy + * @expectedDeprecation Calling "Symfony\Component\HttpFoundation\Request::getSession()" when no session has been set is deprecated since Symfony 4.1 and will throw an exception in 5.0. Use "hasSession()" instead. + */ + public function testGetSessionNullable() + { + (new Request())->getSession(); + } + public function testHasPreviousSession() { $request = new Request(); @@ -1527,14 +1629,14 @@ class RequestTest extends TestCase $asString = (string) $request; - $this->assertContains('Accept-Language: zh, en-us; q=0.8, en; q=0.6', $asString); - $this->assertContains('Cookie: Foo=Bar', $asString); + $this->assertStringContainsString('Accept-Language: zh, en-us; q=0.8, en; q=0.6', $asString); + $this->assertStringContainsString('Cookie: Foo=Bar', $asString); $request->cookies->set('Another', 'Cookie'); $asString = (string) $request; - $this->assertContains('Cookie: Foo=Bar; Another=Cookie', $asString); + $this->assertStringContainsString('Cookie: Foo=Bar; Another=Cookie', $asString); } public function testIsMethod() @@ -1558,7 +1660,7 @@ class RequestTest extends TestCase */ public function testGetBaseUrl($uri, $server, $expectedBaseUrl, $expectedPathInfo) { - $request = Request::create($uri, 'GET', array(), array(), array(), $server); + $request = Request::create($uri, 'GET', [], [], [], $server); $this->assertSame($expectedBaseUrl, $request->getBaseUrl(), 'baseUrl'); $this->assertSame($expectedPathInfo, $request->getPathInfo(), 'pathInfo'); @@ -1566,78 +1668,78 @@ class RequestTest extends TestCase public function getBaseUrlData() { - return array( - array( + return [ + [ '/fruit/strawberry/1234index.php/blah', - array( + [ 'SCRIPT_FILENAME' => 'E:/Sites/cc-new/public_html/fruit/index.php', 'SCRIPT_NAME' => '/fruit/index.php', 'PHP_SELF' => '/fruit/index.php', - ), + ], '/fruit', '/strawberry/1234index.php/blah', - ), - array( + ], + [ '/fruit/strawberry/1234index.php/blah', - array( + [ 'SCRIPT_FILENAME' => 'E:/Sites/cc-new/public_html/index.php', 'SCRIPT_NAME' => '/index.php', 'PHP_SELF' => '/index.php', - ), + ], '', '/fruit/strawberry/1234index.php/blah', - ), - array( + ], + [ '/foo%20bar/', - array( + [ 'SCRIPT_FILENAME' => '/home/John Doe/public_html/foo bar/app.php', 'SCRIPT_NAME' => '/foo bar/app.php', 'PHP_SELF' => '/foo bar/app.php', - ), + ], '/foo%20bar', '/', - ), - array( + ], + [ '/foo%20bar/home', - array( + [ 'SCRIPT_FILENAME' => '/home/John Doe/public_html/foo bar/app.php', 'SCRIPT_NAME' => '/foo bar/app.php', 'PHP_SELF' => '/foo bar/app.php', - ), + ], '/foo%20bar', '/home', - ), - array( + ], + [ '/foo%20bar/app.php/home', - array( + [ 'SCRIPT_FILENAME' => '/home/John Doe/public_html/foo bar/app.php', 'SCRIPT_NAME' => '/foo bar/app.php', 'PHP_SELF' => '/foo bar/app.php', - ), + ], '/foo%20bar/app.php', '/home', - ), - array( + ], + [ '/foo%20bar/app.php/home%3Dbaz', - array( + [ 'SCRIPT_FILENAME' => '/home/John Doe/public_html/foo bar/app.php', 'SCRIPT_NAME' => '/foo bar/app.php', 'PHP_SELF' => '/foo bar/app.php', - ), + ], '/foo%20bar/app.php', '/home%3Dbaz', - ), - array( + ], + [ '/foo/bar+baz', - array( + [ 'SCRIPT_FILENAME' => '/home/John Doe/public_html/foo/app.php', 'SCRIPT_NAME' => '/foo/app.php', 'PHP_SELF' => '/foo/app.php', - ), + ], '/foo', '/bar+baz', - ), - ); + ], + ]; } /** @@ -1655,16 +1757,16 @@ class RequestTest extends TestCase public function urlencodedStringPrefixData() { - return array( - array('foo', 'foo', 'foo'), - array('fo%6f', 'foo', 'fo%6f'), - array('foo/bar', 'foo', 'foo'), - array('fo%6f/bar', 'foo', 'fo%6f'), - array('f%6f%6f/bar', 'foo', 'f%6f%6f'), - array('%66%6F%6F/bar', 'foo', '%66%6F%6F'), - array('fo+o/bar', 'fo+o', 'fo+o'), - array('fo%2Bo/bar', 'fo+o', 'fo%2Bo'), - ); + return [ + ['foo', 'foo', 'foo'], + ['fo%6f', 'foo', 'fo%6f'], + ['foo/bar', 'foo', 'foo'], + ['fo%6f/bar', 'foo', 'fo%6f'], + ['f%6f%6f/bar', 'foo', 'f%6f%6f'], + ['%66%6F%6F/bar', 'foo', '%66%6F%6F'], + ['fo+o/bar', 'fo+o', 'fo+o'], + ['fo%2Bo/bar', 'fo+o', 'fo%2Bo'], + ]; } private function disableHttpMethodParameterOverride() @@ -1679,7 +1781,7 @@ class RequestTest extends TestCase { $request = new Request(); - $server = array('REMOTE_ADDR' => $remoteAddr); + $server = ['REMOTE_ADDR' => $remoteAddr]; if (null !== $httpForwardedFor) { $server['HTTP_X_FORWARDED_FOR'] = $httpForwardedFor; } @@ -1688,7 +1790,7 @@ class RequestTest extends TestCase Request::setTrustedProxies($trustedProxies, Request::HEADER_X_FORWARDED_ALL); } - $request->initialize(array(), array(), array(), array(), array(), $server); + $request->initialize([], [], [], [], [], $server); return $request; } @@ -1697,7 +1799,7 @@ class RequestTest extends TestCase { $request = new Request(); - $server = array('REMOTE_ADDR' => $remoteAddr); + $server = ['REMOTE_ADDR' => $remoteAddr]; if (null !== $httpForwarded) { $server['HTTP_FORWARDED'] = $httpForwarded; @@ -1707,7 +1809,7 @@ class RequestTest extends TestCase Request::setTrustedProxies($trustedProxies, Request::HEADER_FORWARDED); } - $request->initialize(array(), array(), array(), array(), array(), $server); + $request->initialize([], [], [], [], [], $server); return $request; } @@ -1728,35 +1830,35 @@ class RequestTest extends TestCase $this->assertFalse($request->isSecure()); // disabling proxy trusting - Request::setTrustedProxies(array(), Request::HEADER_X_FORWARDED_ALL); + Request::setTrustedProxies([], Request::HEADER_X_FORWARDED_ALL); $this->assertEquals('3.3.3.3', $request->getClientIp()); $this->assertEquals('example.com', $request->getHost()); $this->assertEquals(80, $request->getPort()); $this->assertFalse($request->isSecure()); // request is forwarded by a non-trusted proxy - Request::setTrustedProxies(array('2.2.2.2'), Request::HEADER_X_FORWARDED_ALL); + Request::setTrustedProxies(['2.2.2.2'], Request::HEADER_X_FORWARDED_ALL); $this->assertEquals('3.3.3.3', $request->getClientIp()); $this->assertEquals('example.com', $request->getHost()); $this->assertEquals(80, $request->getPort()); $this->assertFalse($request->isSecure()); // trusted proxy via setTrustedProxies() - Request::setTrustedProxies(array('3.3.3.3', '2.2.2.2'), Request::HEADER_X_FORWARDED_ALL); + Request::setTrustedProxies(['3.3.3.3', '2.2.2.2'], Request::HEADER_X_FORWARDED_ALL); $this->assertEquals('1.1.1.1', $request->getClientIp()); $this->assertEquals('foo.example.com', $request->getHost()); $this->assertEquals(443, $request->getPort()); $this->assertTrue($request->isSecure()); // trusted proxy via setTrustedProxies() - Request::setTrustedProxies(array('3.3.3.4', '2.2.2.2'), Request::HEADER_X_FORWARDED_ALL); + Request::setTrustedProxies(['3.3.3.4', '2.2.2.2'], Request::HEADER_X_FORWARDED_ALL); $this->assertEquals('3.3.3.3', $request->getClientIp()); $this->assertEquals('example.com', $request->getHost()); $this->assertEquals(80, $request->getPort()); $this->assertFalse($request->isSecure()); // check various X_FORWARDED_PROTO header values - Request::setTrustedProxies(array('3.3.3.3', '2.2.2.2'), Request::HEADER_X_FORWARDED_ALL); + Request::setTrustedProxies(['3.3.3.3', '2.2.2.2'], Request::HEADER_X_FORWARDED_ALL); $request->headers->set('X_FORWARDED_PROTO', 'ssl'); $this->assertTrue($request->isSecure()); @@ -1764,53 +1866,6 @@ class RequestTest extends TestCase $this->assertTrue($request->isSecure()); } - /** - * @group legacy - * @expectedDeprecation The "Symfony\Component\HttpFoundation\Request::setTrustedHeaderName()" method is deprecated since Symfony 3.3 and will be removed in 4.0. Use the $trustedHeaderSet argument of the Request::setTrustedProxies() method instead. - */ - public function testLegacyTrustedProxies() - { - $request = Request::create('http://example.com/'); - $request->server->set('REMOTE_ADDR', '3.3.3.3'); - $request->headers->set('X_FORWARDED_FOR', '1.1.1.1, 2.2.2.2'); - $request->headers->set('X_FORWARDED_HOST', 'foo.example.com, real.example.com:8080'); - $request->headers->set('X_FORWARDED_PROTO', 'https'); - $request->headers->set('X_FORWARDED_PORT', 443); - $request->headers->set('X_MY_FOR', '3.3.3.3, 4.4.4.4'); - $request->headers->set('X_MY_HOST', 'my.example.com'); - $request->headers->set('X_MY_PROTO', 'http'); - $request->headers->set('X_MY_PORT', 81); - - Request::setTrustedProxies(array('3.3.3.3', '2.2.2.2'), Request::HEADER_X_FORWARDED_ALL); - - // custom header names - Request::setTrustedHeaderName(Request::HEADER_CLIENT_IP, 'X_MY_FOR'); - Request::setTrustedHeaderName(Request::HEADER_CLIENT_HOST, 'X_MY_HOST'); - Request::setTrustedHeaderName(Request::HEADER_CLIENT_PORT, 'X_MY_PORT'); - Request::setTrustedHeaderName(Request::HEADER_CLIENT_PROTO, 'X_MY_PROTO'); - $this->assertEquals('4.4.4.4', $request->getClientIp()); - $this->assertEquals('my.example.com', $request->getHost()); - $this->assertEquals(81, $request->getPort()); - $this->assertFalse($request->isSecure()); - - // disabling via empty header names - Request::setTrustedHeaderName(Request::HEADER_CLIENT_IP, null); - Request::setTrustedHeaderName(Request::HEADER_CLIENT_HOST, null); - Request::setTrustedHeaderName(Request::HEADER_CLIENT_PORT, null); - Request::setTrustedHeaderName(Request::HEADER_CLIENT_PROTO, null); - $this->assertEquals('3.3.3.3', $request->getClientIp()); - $this->assertEquals('example.com', $request->getHost()); - $this->assertEquals(80, $request->getPort()); - $this->assertFalse($request->isSecure()); - - //reset - Request::setTrustedHeaderName(Request::HEADER_FORWARDED, 'FORWARDED'); - Request::setTrustedHeaderName(Request::HEADER_CLIENT_IP, 'X_FORWARDED_FOR'); - Request::setTrustedHeaderName(Request::HEADER_CLIENT_HOST, 'X_FORWARDED_HOST'); - Request::setTrustedHeaderName(Request::HEADER_CLIENT_PORT, 'X_FORWARDED_PORT'); - Request::setTrustedHeaderName(Request::HEADER_CLIENT_PROTO, 'X_FORWARDED_PROTO'); - } - public function testTrustedProxiesForwarded() { $request = Request::create('http://example.com/'); @@ -1824,35 +1879,35 @@ class RequestTest extends TestCase $this->assertFalse($request->isSecure()); // disabling proxy trusting - Request::setTrustedProxies(array(), Request::HEADER_FORWARDED); + Request::setTrustedProxies([], Request::HEADER_FORWARDED); $this->assertEquals('3.3.3.3', $request->getClientIp()); $this->assertEquals('example.com', $request->getHost()); $this->assertEquals(80, $request->getPort()); $this->assertFalse($request->isSecure()); // request is forwarded by a non-trusted proxy - Request::setTrustedProxies(array('2.2.2.2'), Request::HEADER_FORWARDED); + Request::setTrustedProxies(['2.2.2.2'], Request::HEADER_FORWARDED); $this->assertEquals('3.3.3.3', $request->getClientIp()); $this->assertEquals('example.com', $request->getHost()); $this->assertEquals(80, $request->getPort()); $this->assertFalse($request->isSecure()); // trusted proxy via setTrustedProxies() - Request::setTrustedProxies(array('3.3.3.3', '2.2.2.2'), Request::HEADER_FORWARDED); + Request::setTrustedProxies(['3.3.3.3', '2.2.2.2'], Request::HEADER_FORWARDED); $this->assertEquals('1.1.1.1', $request->getClientIp()); $this->assertEquals('foo.example.com', $request->getHost()); $this->assertEquals(8080, $request->getPort()); $this->assertTrue($request->isSecure()); // trusted proxy via setTrustedProxies() - Request::setTrustedProxies(array('3.3.3.4', '2.2.2.2'), Request::HEADER_FORWARDED); + Request::setTrustedProxies(['3.3.3.4', '2.2.2.2'], Request::HEADER_FORWARDED); $this->assertEquals('3.3.3.3', $request->getClientIp()); $this->assertEquals('example.com', $request->getHost()); $this->assertEquals(80, $request->getPort()); $this->assertFalse($request->isSecure()); // check various X_FORWARDED_PROTO header values - Request::setTrustedProxies(array('3.3.3.3', '2.2.2.2'), Request::HEADER_FORWARDED); + Request::setTrustedProxies(['3.3.3.3', '2.2.2.2'], Request::HEADER_FORWARDED); $request->headers->set('FORWARDED', 'proto=ssl'); $this->assertTrue($request->isSecure()); @@ -1860,26 +1915,6 @@ class RequestTest extends TestCase $this->assertTrue($request->isSecure()); } - /** - * @group legacy - * @expectedException \InvalidArgumentException - */ - public function testSetTrustedProxiesInvalidHeaderName() - { - Request::create('http://example.com/'); - Request::setTrustedHeaderName('bogus name', 'X_MY_FOR'); - } - - /** - * @group legacy - * @expectedException \InvalidArgumentException - */ - public function testGetTrustedProxiesInvalidHeaderName() - { - Request::create('http://example.com/'); - Request::getTrustedHeaderName('bogus name'); - } - /** * @dataProvider iisRequestUriProvider */ @@ -1892,81 +1927,37 @@ class RequestTest extends TestCase $this->assertEquals($expectedRequestUri, $request->getRequestUri(), '->getRequestUri() is correct'); $subRequestUri = '/bar/foo'; - $subRequest = Request::create($subRequestUri, 'get', array(), array(), array(), $request->server->all()); + $subRequest = Request::create($subRequestUri, 'get', [], [], [], $request->server->all()); $this->assertEquals($subRequestUri, $subRequest->getRequestUri(), '->getRequestUri() is correct in sub request'); } public function iisRequestUriProvider() { - return array( - array( - array( - 'X_ORIGINAL_URL' => '/foo/bar', - ), - array(), - '/foo/bar', - ), - array( - array( - 'X_REWRITE_URL' => '/foo/bar', - ), - array(), - '/foo/bar', - ), - array( - array(), - array( + return [ + [ + [], + [ 'IIS_WasUrlRewritten' => '1', 'UNENCODED_URL' => '/foo/bar', - ), - '/foo/bar', - ), - array( - array( - 'X_ORIGINAL_URL' => '/foo/bar', - ), - array( - 'HTTP_X_ORIGINAL_URL' => '/foo/bar', - ), + ], '/foo/bar', - ), - array( - array( - 'X_ORIGINAL_URL' => '/foo/bar', - ), - array( - 'IIS_WasUrlRewritten' => '1', - 'UNENCODED_URL' => '/foo/bar', - ), - '/foo/bar', - ), - array( - array( - 'X_ORIGINAL_URL' => '/foo/bar', - ), - array( - 'HTTP_X_ORIGINAL_URL' => '/foo/bar', - 'IIS_WasUrlRewritten' => '1', - 'UNENCODED_URL' => '/foo/bar', - ), - '/foo/bar', - ), - array( - array(), - array( + ], + [ + [], + [ 'ORIG_PATH_INFO' => '/foo/bar', - ), + ], '/foo/bar', - ), - array( - array(), - array( + ], + [ + [], + [ 'ORIG_PATH_INFO' => '/foo/bar', 'QUERY_STRING' => 'foo=bar', - ), + ], '/foo/bar?foo=bar', - ), - ); + ], + ]; } public function testTrustedHosts() @@ -1979,7 +1970,7 @@ class RequestTest extends TestCase $this->assertEquals('evil.com', $request->getHost()); // add a trusted domain and all its subdomains - Request::setTrustedHosts(array('^([a-z]{9}\.)?trusted\.com$')); + Request::setTrustedHosts(['^([a-z]{9}\.)?trusted\.com$']); // untrusted host $request->headers->set('host', 'evil.com'); @@ -2007,14 +1998,20 @@ class RequestTest extends TestCase $request->headers->set('host', 'subdomain.trusted.com'); $this->assertEquals('subdomain.trusted.com', $request->getHost()); + } + + public function testSetTrustedHostsDoesNotBreakOnSpecialCharacters() + { + Request::setTrustedHosts(['localhost(\.local){0,1}#,example.com', 'localhost']); - // reset request for following tests - Request::setTrustedHosts(array()); + $request = Request::create('/'); + $request->headers->set('host', 'localhost'); + $this->assertSame('localhost', $request->getHost()); } public function testFactory() { - Request::setFactory(function (array $query = array(), array $request = array(), array $attributes = array(), array $cookies = array(), array $files = array(), array $server = array(), $content = null) { + Request::setFactory(function (array $query = [], array $request = [], array $attributes = [], array $cookies = [], array $files = [], array $server = [], $content = null) { return new NewRequest(); }); @@ -2050,12 +2047,8 @@ class RequestTest extends TestCase $this->assertSame($expectedPort, $request->getPort()); } } else { - if (method_exists($this, 'expectException')) { - $this->expectException(SuspiciousOperationException::class); - $this->expectExceptionMessage('Invalid Host'); - } else { - $this->setExpectedException(SuspiciousOperationException::class, 'Invalid Host'); - } + $this->expectException(SuspiciousOperationException::class); + $this->expectExceptionMessage('Invalid Host'); $request->getHost(); } @@ -2063,23 +2056,23 @@ class RequestTest extends TestCase public function getHostValidities() { - return array( - array('.a', false), - array('a..', false), - array('a.', true), - array("\xE9", false), - array('[::1]', true), - array('[::1]:80', true, '[::1]', 80), - array(str_repeat('.', 101), false), - ); + return [ + ['.a', false], + ['a..', false], + ['a.', true], + ["\xE9", false], + ['[::1]', true], + ['[::1]:80', true, '[::1]', 80], + [str_repeat('.', 101), false], + ]; } public function getLongHostNames() { - return array( - array('a'.str_repeat('.a', 40000)), - array(str_repeat(':', 101)), - ); + return [ + ['a'.str_repeat('.a', 40000)], + [str_repeat(':', 101)], + ]; } /** @@ -2094,18 +2087,18 @@ class RequestTest extends TestCase public function methodIdempotentProvider() { - return array( - array('HEAD', true), - array('GET', true), - array('POST', false), - array('PUT', true), - array('PATCH', false), - array('DELETE', true), - array('PURGE', true), - array('OPTIONS', true), - array('TRACE', true), - array('CONNECT', false), - ); + return [ + ['HEAD', true], + ['GET', true], + ['POST', false], + ['PUT', true], + ['PATCH', false], + ['DELETE', true], + ['PURGE', true], + ['OPTIONS', true], + ['TRACE', true], + ['CONNECT', false], + ]; } /** @@ -2120,110 +2113,52 @@ class RequestTest extends TestCase public function methodSafeProvider() { - return array( - array('HEAD', true), - array('GET', true), - array('POST', false), - array('PUT', false), - array('PATCH', false), - array('DELETE', false), - array('PURGE', false), - array('OPTIONS', true), - array('TRACE', true), - array('CONNECT', false), - ); + return [ + ['HEAD', true], + ['GET', true], + ['POST', false], + ['PUT', false], + ['PATCH', false], + ['DELETE', false], + ['PURGE', false], + ['OPTIONS', true], + ['TRACE', true], + ['CONNECT', false], + ]; } - /** - * @group legacy - * @expectedDeprecation Checking only for cacheable HTTP methods with Symfony\Component\HttpFoundation\Request::isMethodSafe() is deprecated since Symfony 3.2 and will throw an exception in 4.0. Disable checking only for cacheable methods by calling the method with `false` as first argument or use the Request::isMethodCacheable() instead. - */ public function testMethodSafeChecksCacheable() { + $this->expectException('BadMethodCallException'); $request = new Request(); $request->setMethod('OPTIONS'); - $this->assertFalse($request->isMethodSafe()); + $request->isMethodSafe(); } /** * @dataProvider methodCacheableProvider */ - public function testMethodCacheable($method, $chacheable) + public function testMethodCacheable($method, $cacheable) { $request = new Request(); $request->setMethod($method); - $this->assertEquals($chacheable, $request->isMethodCacheable()); + $this->assertEquals($cacheable, $request->isMethodCacheable()); } public function methodCacheableProvider() { - return array( - array('HEAD', true), - array('GET', true), - array('POST', false), - array('PUT', false), - array('PATCH', false), - array('DELETE', false), - array('PURGE', false), - array('OPTIONS', false), - array('TRACE', false), - array('CONNECT', false), - ); - } - - /** - * @group legacy - */ - public function testGetTrustedHeaderName() - { - Request::setTrustedProxies(array('8.8.8.8'), Request::HEADER_X_FORWARDED_ALL); - - $this->assertNull(Request::getTrustedHeaderName(Request::HEADER_FORWARDED)); - $this->assertSame('X_FORWARDED_FOR', Request::getTrustedHeaderName(Request::HEADER_CLIENT_IP)); - $this->assertSame('X_FORWARDED_HOST', Request::getTrustedHeaderName(Request::HEADER_CLIENT_HOST)); - $this->assertSame('X_FORWARDED_PORT', Request::getTrustedHeaderName(Request::HEADER_CLIENT_PORT)); - $this->assertSame('X_FORWARDED_PROTO', Request::getTrustedHeaderName(Request::HEADER_CLIENT_PROTO)); - - Request::setTrustedProxies(array('8.8.8.8'), Request::HEADER_FORWARDED); - - $this->assertSame('FORWARDED', Request::getTrustedHeaderName(Request::HEADER_FORWARDED)); - $this->assertNull(Request::getTrustedHeaderName(Request::HEADER_CLIENT_IP)); - $this->assertNull(Request::getTrustedHeaderName(Request::HEADER_CLIENT_HOST)); - $this->assertNull(Request::getTrustedHeaderName(Request::HEADER_CLIENT_PORT)); - $this->assertNull(Request::getTrustedHeaderName(Request::HEADER_CLIENT_PROTO)); - - Request::setTrustedHeaderName(Request::HEADER_FORWARDED, 'A'); - Request::setTrustedHeaderName(Request::HEADER_CLIENT_IP, 'B'); - Request::setTrustedHeaderName(Request::HEADER_CLIENT_HOST, 'C'); - Request::setTrustedHeaderName(Request::HEADER_CLIENT_PORT, 'D'); - Request::setTrustedHeaderName(Request::HEADER_CLIENT_PROTO, 'E'); - - Request::setTrustedProxies(array('8.8.8.8'), Request::HEADER_FORWARDED); - - $this->assertSame('A', Request::getTrustedHeaderName(Request::HEADER_FORWARDED)); - $this->assertNull(Request::getTrustedHeaderName(Request::HEADER_CLIENT_IP)); - $this->assertNull(Request::getTrustedHeaderName(Request::HEADER_CLIENT_HOST)); - $this->assertNull(Request::getTrustedHeaderName(Request::HEADER_CLIENT_PORT)); - $this->assertNull(Request::getTrustedHeaderName(Request::HEADER_CLIENT_PROTO)); - - Request::setTrustedProxies(array('8.8.8.8'), Request::HEADER_X_FORWARDED_ALL); - - $this->assertNull(Request::getTrustedHeaderName(Request::HEADER_FORWARDED)); - $this->assertSame('B', Request::getTrustedHeaderName(Request::HEADER_CLIENT_IP)); - $this->assertSame('C', Request::getTrustedHeaderName(Request::HEADER_CLIENT_HOST)); - $this->assertSame('D', Request::getTrustedHeaderName(Request::HEADER_CLIENT_PORT)); - $this->assertSame('E', Request::getTrustedHeaderName(Request::HEADER_CLIENT_PROTO)); - - Request::setTrustedProxies(array('8.8.8.8'), Request::HEADER_FORWARDED); - - $this->assertSame('A', Request::getTrustedHeaderName(Request::HEADER_FORWARDED)); - - //reset - Request::setTrustedHeaderName(Request::HEADER_FORWARDED, 'FORWARDED'); - Request::setTrustedHeaderName(Request::HEADER_CLIENT_IP, 'X_FORWARDED_FOR'); - Request::setTrustedHeaderName(Request::HEADER_CLIENT_HOST, 'X_FORWARDED_HOST'); - Request::setTrustedHeaderName(Request::HEADER_CLIENT_PORT, 'X_FORWARDED_PORT'); - Request::setTrustedHeaderName(Request::HEADER_CLIENT_PROTO, 'X_FORWARDED_PROTO'); + return [ + ['HEAD', true], + ['GET', true], + ['POST', false], + ['PUT', false], + ['PATCH', false], + ['DELETE', false], + ['PURGE', false], + ['OPTIONS', false], + ['TRACE', false], + ['CONNECT', false], + ]; } /** @@ -2232,7 +2167,7 @@ class RequestTest extends TestCase public function testProtocolVersion($serverProtocol, $trustedProxy, $via, $expected) { if ($trustedProxy) { - Request::setTrustedProxies(array('1.1.1.1'), -1); + Request::setTrustedProxies(['1.1.1.1'], -1); } $request = new Request(); @@ -2245,41 +2180,41 @@ class RequestTest extends TestCase public function protocolVersionProvider() { - return array( - 'untrusted without via' => array('HTTP/2.0', false, '', 'HTTP/2.0'), - 'untrusted with via' => array('HTTP/2.0', false, '1.0 fred, 1.1 nowhere.com (Apache/1.1)', 'HTTP/2.0'), - 'trusted without via' => array('HTTP/2.0', true, '', 'HTTP/2.0'), - 'trusted with via' => array('HTTP/2.0', true, '1.0 fred, 1.1 nowhere.com (Apache/1.1)', 'HTTP/1.0'), - 'trusted with via and protocol name' => array('HTTP/2.0', true, 'HTTP/1.0 fred, HTTP/1.1 nowhere.com (Apache/1.1)', 'HTTP/1.0'), - 'trusted with broken via' => array('HTTP/2.0', true, 'HTTP/1^0 foo', 'HTTP/2.0'), - 'trusted with partially-broken via' => array('HTTP/2.0', true, '1.0 fred, foo', 'HTTP/1.0'), - ); + return [ + 'untrusted without via' => ['HTTP/2.0', false, '', 'HTTP/2.0'], + 'untrusted with via' => ['HTTP/2.0', false, '1.0 fred, 1.1 nowhere.com (Apache/1.1)', 'HTTP/2.0'], + 'trusted without via' => ['HTTP/2.0', true, '', 'HTTP/2.0'], + 'trusted with via' => ['HTTP/2.0', true, '1.0 fred, 1.1 nowhere.com (Apache/1.1)', 'HTTP/1.0'], + 'trusted with via and protocol name' => ['HTTP/2.0', true, 'HTTP/1.0 fred, HTTP/1.1 nowhere.com (Apache/1.1)', 'HTTP/1.0'], + 'trusted with broken via' => ['HTTP/2.0', true, 'HTTP/1^0 foo', 'HTTP/2.0'], + 'trusted with partially-broken via' => ['HTTP/2.0', true, '1.0 fred, foo', 'HTTP/1.0'], + ]; } public function nonstandardRequestsData() { - return array( - array('', '', '/', 'http://host:8080/', ''), - array('/', '', '/', 'http://host:8080/', ''), + return [ + ['', '', '/', 'http://host:8080/', ''], + ['/', '', '/', 'http://host:8080/', ''], - array('hello/app.php/x', '', '/x', 'http://host:8080/hello/app.php/x', '/hello', '/hello/app.php'), - array('/hello/app.php/x', '', '/x', 'http://host:8080/hello/app.php/x', '/hello', '/hello/app.php'), + ['hello/app.php/x', '', '/x', 'http://host:8080/hello/app.php/x', '/hello', '/hello/app.php'], + ['/hello/app.php/x', '', '/x', 'http://host:8080/hello/app.php/x', '/hello', '/hello/app.php'], - array('', 'a=b', '/', 'http://host:8080/?a=b'), - array('?a=b', 'a=b', '/', 'http://host:8080/?a=b'), - array('/?a=b', 'a=b', '/', 'http://host:8080/?a=b'), + ['', 'a=b', '/', 'http://host:8080/?a=b'], + ['?a=b', 'a=b', '/', 'http://host:8080/?a=b'], + ['/?a=b', 'a=b', '/', 'http://host:8080/?a=b'], - array('x', 'a=b', '/x', 'http://host:8080/x?a=b'), - array('x?a=b', 'a=b', '/x', 'http://host:8080/x?a=b'), - array('/x?a=b', 'a=b', '/x', 'http://host:8080/x?a=b'), + ['x', 'a=b', '/x', 'http://host:8080/x?a=b'], + ['x?a=b', 'a=b', '/x', 'http://host:8080/x?a=b'], + ['/x?a=b', 'a=b', '/x', 'http://host:8080/x?a=b'], - array('hello/x', '', '/x', 'http://host:8080/hello/x', '/hello'), - array('/hello/x', '', '/x', 'http://host:8080/hello/x', '/hello'), + ['hello/x', '', '/x', 'http://host:8080/hello/x', '/hello'], + ['/hello/x', '', '/x', 'http://host:8080/hello/x', '/hello'], - array('hello/app.php/x', 'a=b', '/x', 'http://host:8080/hello/app.php/x?a=b', '/hello', '/hello/app.php'), - array('hello/app.php/x?a=b', 'a=b', '/x', 'http://host:8080/hello/app.php/x?a=b', '/hello', '/hello/app.php'), - array('/hello/app.php/x?a=b', 'a=b', '/x', 'http://host:8080/hello/app.php/x?a=b', '/hello', '/hello/app.php'), - ); + ['hello/app.php/x', 'a=b', '/x', 'http://host:8080/hello/app.php/x?a=b', '/hello', '/hello/app.php'], + ['hello/app.php/x?a=b', 'a=b', '/x', 'http://host:8080/hello/app.php/x?a=b', '/hello', '/hello/app.php'], + ['/hello/app.php/x?a=b', 'a=b', '/x', 'http://host:8080/hello/app.php/x?a=b', '/hello', '/hello/app.php'], + ]; } /** @@ -2291,16 +2226,16 @@ class RequestTest extends TestCase $expectedBaseUrl = $expectedBasePath; } - $server = array( + $server = [ 'HTTP_HOST' => 'host:8080', 'SERVER_PORT' => '8080', 'QUERY_STRING' => $queryString, 'PHP_SELF' => '/hello/app.php', 'SCRIPT_FILENAME' => '/some/path/app.php', 'REQUEST_URI' => $requestUri, - ); + ]; - $request = new Request(array(), array(), array(), array(), array(), $server); + $request = new Request([], [], [], [], [], $server); $this->assertEquals($expectedPathInfo, $request->getPathInfo()); $this->assertEquals($expectedUri, $request->getUri()); @@ -2310,13 +2245,74 @@ class RequestTest extends TestCase $this->assertEquals($expectedBaseUrl, $request->getBaseUrl()); $this->assertEquals($expectedBasePath, $request->getBasePath()); } + + public function testTrustedHost() + { + Request::setTrustedProxies(['1.1.1.1'], -1); + + $request = Request::create('/'); + $request->server->set('REMOTE_ADDR', '1.1.1.1'); + $request->headers->set('Forwarded', 'host=localhost:8080'); + $request->headers->set('X-Forwarded-Host', 'localhost:8080'); + + $this->assertSame('localhost:8080', $request->getHttpHost()); + $this->assertSame(8080, $request->getPort()); + + $request = Request::create('/'); + $request->server->set('REMOTE_ADDR', '1.1.1.1'); + $request->headers->set('Forwarded', 'host="[::1]:443"'); + $request->headers->set('X-Forwarded-Host', '[::1]:443'); + $request->headers->set('X-Forwarded-Port', 443); + + $this->assertSame('[::1]:443', $request->getHttpHost()); + $this->assertSame(443, $request->getPort()); + } + + public function testTrustedPort() + { + Request::setTrustedProxies(['1.1.1.1'], -1); + + $request = Request::create('/'); + $request->server->set('REMOTE_ADDR', '1.1.1.1'); + $request->headers->set('Forwarded', 'host=localhost:8080'); + $request->headers->set('X-Forwarded-Port', 8080); + + $this->assertSame(8080, $request->getPort()); + + $request = Request::create('/'); + $request->server->set('REMOTE_ADDR', '1.1.1.1'); + $request->headers->set('Forwarded', 'host=localhost'); + $request->headers->set('X-Forwarded-Port', 80); + + $this->assertSame(80, $request->getPort()); + + $request = Request::create('/'); + $request->server->set('REMOTE_ADDR', '1.1.1.1'); + $request->headers->set('Forwarded', 'host="[::1]"'); + $request->headers->set('X-Forwarded-Proto', 'https'); + $request->headers->set('X-Forwarded-Port', 443); + + $this->assertSame(443, $request->getPort()); + } + + public function testTrustedPortDoesNotDefaultToZero() + { + Request::setTrustedProxies(['1.1.1.1'], Request::HEADER_X_FORWARDED_ALL); + + $request = Request::create('/'); + $request->server->set('REMOTE_ADDR', '1.1.1.1'); + $request->headers->set('X-Forwarded-Host', 'test.example.com'); + $request->headers->set('X-Forwarded-Port', ''); + + $this->assertSame(80, $request->getPort()); + } } class RequestContentProxy extends Request { public function getContent($asResource = false) { - return http_build_query(array('_method' => 'PUT', 'content' => 'mycontent')); + return http_build_query(['_method' => 'PUT', 'content' => 'mycontent'], '', '&'); } } diff --git a/vendor/symfony/http-foundation/Tests/ResponseFunctionalTest.php b/vendor/symfony/http-foundation/Tests/ResponseFunctionalTest.php new file mode 100644 index 0000000000000000000000000000000000000000..21a66bbf861e08fb3bd5407a95b353098c162b58 --- /dev/null +++ b/vendor/symfony/http-foundation/Tests/ResponseFunctionalTest.php @@ -0,0 +1,58 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\Tests; + +use PHPUnit\Framework\TestCase; + +/** + * @requires PHP 7.0 + */ +class ResponseFunctionalTest extends TestCase +{ + private static $server; + + public static function setUpBeforeClass(): void + { + $spec = [ + 1 => ['file', '/dev/null', 'w'], + 2 => ['file', '/dev/null', 'w'], + ]; + if (!self::$server = @proc_open('exec php -S localhost:8054', $spec, $pipes, __DIR__.'/Fixtures/response-functional')) { + self::markTestSkipped('PHP server unable to start.'); + } + sleep(1); + } + + public static function tearDownAfterClass(): void + { + if (self::$server) { + proc_terminate(self::$server); + proc_close(self::$server); + } + } + + /** + * @dataProvider provideCookie + */ + public function testCookie($fixture) + { + $result = file_get_contents(sprintf('http://localhost:8054/%s.php', $fixture)); + $this->assertStringMatchesFormatFile(__DIR__.sprintf('/Fixtures/response-functional/%s.expected', $fixture), $result); + } + + public function provideCookie() + { + foreach (glob(__DIR__.'/Fixtures/response-functional/*.php') as $file) { + yield [pathinfo($file, PATHINFO_FILENAME)]; + } + } +} diff --git a/vendor/symfony/http-foundation/Tests/ResponseHeaderBagTest.php b/vendor/symfony/http-foundation/Tests/ResponseHeaderBagTest.php index ce8553590dcdbabfc301992649d66c7608cdef88..dc4f7105f4d8e4afaafeab93d1052e7783acd15e 100644 --- a/vendor/symfony/http-foundation/Tests/ResponseHeaderBagTest.php +++ b/vendor/symfony/http-foundation/Tests/ResponseHeaderBagTest.php @@ -12,8 +12,8 @@ namespace Symfony\Component\HttpFoundation\Tests; use PHPUnit\Framework\TestCase; -use Symfony\Component\HttpFoundation\ResponseHeaderBag; use Symfony\Component\HttpFoundation\Cookie; +use Symfony\Component\HttpFoundation\ResponseHeaderBag; /** * @group time-sensitive @@ -22,7 +22,7 @@ class ResponseHeaderBagTest extends TestCase { public function testAllPreserveCase() { - $headers = array( + $headers = [ 'fOo' => 'BAR', 'ETag' => 'xyzzy', 'Content-MD5' => 'Q2hlY2sgSW50ZWdyaXR5IQ==', @@ -30,7 +30,7 @@ class ResponseHeaderBagTest extends TestCase 'WWW-Authenticate' => 'Basic realm="WallyWorld"', 'X-UA-Compatible' => 'IE=edge,chrome=1', 'X-XSS-Protection' => '1; mode=block', - ); + ]; $bag = new ResponseHeaderBag($headers); $allPreservedCase = $bag->allPreserveCase(); @@ -42,45 +42,45 @@ class ResponseHeaderBagTest extends TestCase public function testCacheControlHeader() { - $bag = new ResponseHeaderBag(array()); + $bag = new ResponseHeaderBag([]); $this->assertEquals('no-cache, private', $bag->get('Cache-Control')); $this->assertTrue($bag->hasCacheControlDirective('no-cache')); - $bag = new ResponseHeaderBag(array('Cache-Control' => 'public')); + $bag = new ResponseHeaderBag(['Cache-Control' => 'public']); $this->assertEquals('public', $bag->get('Cache-Control')); $this->assertTrue($bag->hasCacheControlDirective('public')); - $bag = new ResponseHeaderBag(array('ETag' => 'abcde')); + $bag = new ResponseHeaderBag(['ETag' => 'abcde']); $this->assertEquals('private, must-revalidate', $bag->get('Cache-Control')); $this->assertTrue($bag->hasCacheControlDirective('private')); $this->assertTrue($bag->hasCacheControlDirective('must-revalidate')); $this->assertFalse($bag->hasCacheControlDirective('max-age')); - $bag = new ResponseHeaderBag(array('Expires' => 'Wed, 16 Feb 2011 14:17:43 GMT')); + $bag = new ResponseHeaderBag(['Expires' => 'Wed, 16 Feb 2011 14:17:43 GMT']); $this->assertEquals('private, must-revalidate', $bag->get('Cache-Control')); - $bag = new ResponseHeaderBag(array( + $bag = new ResponseHeaderBag([ 'Expires' => 'Wed, 16 Feb 2011 14:17:43 GMT', 'Cache-Control' => 'max-age=3600', - )); + ]); $this->assertEquals('max-age=3600, private', $bag->get('Cache-Control')); - $bag = new ResponseHeaderBag(array('Last-Modified' => 'abcde')); + $bag = new ResponseHeaderBag(['Last-Modified' => 'abcde']); $this->assertEquals('private, must-revalidate', $bag->get('Cache-Control')); - $bag = new ResponseHeaderBag(array('Etag' => 'abcde', 'Last-Modified' => 'abcde')); + $bag = new ResponseHeaderBag(['Etag' => 'abcde', 'Last-Modified' => 'abcde']); $this->assertEquals('private, must-revalidate', $bag->get('Cache-Control')); - $bag = new ResponseHeaderBag(array('cache-control' => 'max-age=100')); + $bag = new ResponseHeaderBag(['cache-control' => 'max-age=100']); $this->assertEquals('max-age=100, private', $bag->get('Cache-Control')); - $bag = new ResponseHeaderBag(array('cache-control' => 's-maxage=100')); + $bag = new ResponseHeaderBag(['cache-control' => 's-maxage=100']); $this->assertEquals('s-maxage=100', $bag->get('Cache-Control')); - $bag = new ResponseHeaderBag(array('cache-control' => 'private, max-age=100')); + $bag = new ResponseHeaderBag(['cache-control' => 'private, max-age=100']); $this->assertEquals('max-age=100, private', $bag->get('Cache-Control')); - $bag = new ResponseHeaderBag(array('cache-control' => 'public, max-age=100')); + $bag = new ResponseHeaderBag(['cache-control' => 'public, max-age=100']); $this->assertEquals('max-age=100, public', $bag->get('Cache-Control')); $bag = new ResponseHeaderBag(); @@ -88,7 +88,7 @@ class ResponseHeaderBagTest extends TestCase $this->assertEquals('private, must-revalidate', $bag->get('Cache-Control')); $bag = new ResponseHeaderBag(); - $bag->set('Cache-Control', array('public', 'must-revalidate')); + $bag->set('Cache-Control', ['public', 'must-revalidate']); $this->assertCount(1, $bag->get('Cache-Control', null, false)); $this->assertEquals('must-revalidate, public', $bag->get('Cache-Control')); @@ -101,7 +101,7 @@ class ResponseHeaderBagTest extends TestCase public function testCacheControlClone() { - $headers = array('foo' => 'bar'); + $headers = ['foo' => 'bar']; $bag1 = new ResponseHeaderBag($headers); $bag2 = new ResponseHeaderBag($bag1->allPreserveCase()); $this->assertEquals($bag1->allPreserveCase(), $bag2->allPreserveCase()); @@ -109,44 +109,44 @@ class ResponseHeaderBagTest extends TestCase public function testToStringIncludesCookieHeaders() { - $bag = new ResponseHeaderBag(array()); - $bag->setCookie(new Cookie('foo', 'bar')); + $bag = new ResponseHeaderBag([]); + $bag->setCookie(Cookie::create('foo', 'bar')); - $this->assertSetCookieHeader('foo=bar; path=/; httponly', $bag); + $this->assertSetCookieHeader('foo=bar; path=/; httponly; samesite=lax', $bag); $bag->clearCookie('foo'); - $this->assertSetCookieHeader('foo=deleted; expires='.gmdate('D, d-M-Y H:i:s T', time() - 31536001).'; max-age=-31536001; path=/; httponly', $bag); + $this->assertSetCookieHeader('foo=deleted; expires='.gmdate('D, d-M-Y H:i:s T', time() - 31536001).'; Max-Age=0; path=/; httponly', $bag); } public function testClearCookieSecureNotHttpOnly() { - $bag = new ResponseHeaderBag(array()); + $bag = new ResponseHeaderBag([]); $bag->clearCookie('foo', '/', null, true, false); - $this->assertSetCookieHeader('foo=deleted; expires='.gmdate('D, d-M-Y H:i:s T', time() - 31536001).'; max-age=-31536001; path=/; secure', $bag); + $this->assertSetCookieHeader('foo=deleted; expires='.gmdate('D, d-M-Y H:i:s T', time() - 31536001).'; Max-Age=0; path=/; secure', $bag); } public function testReplace() { - $bag = new ResponseHeaderBag(array()); + $bag = new ResponseHeaderBag([]); $this->assertEquals('no-cache, private', $bag->get('Cache-Control')); $this->assertTrue($bag->hasCacheControlDirective('no-cache')); - $bag->replace(array('Cache-Control' => 'public')); + $bag->replace(['Cache-Control' => 'public']); $this->assertEquals('public', $bag->get('Cache-Control')); $this->assertTrue($bag->hasCacheControlDirective('public')); } public function testReplaceWithRemove() { - $bag = new ResponseHeaderBag(array()); + $bag = new ResponseHeaderBag([]); $this->assertEquals('no-cache, private', $bag->get('Cache-Control')); $this->assertTrue($bag->hasCacheControlDirective('no-cache')); $bag->remove('Cache-Control'); - $bag->replace(array()); + $bag->replace([]); $this->assertEquals('no-cache, private', $bag->get('Cache-Control')); $this->assertTrue($bag->hasCacheControlDirective('no-cache')); } @@ -154,24 +154,24 @@ class ResponseHeaderBagTest extends TestCase public function testCookiesWithSameNames() { $bag = new ResponseHeaderBag(); - $bag->setCookie(new Cookie('foo', 'bar', 0, '/path/foo', 'foo.bar')); - $bag->setCookie(new Cookie('foo', 'bar', 0, '/path/bar', 'foo.bar')); - $bag->setCookie(new Cookie('foo', 'bar', 0, '/path/bar', 'bar.foo')); - $bag->setCookie(new Cookie('foo', 'bar')); + $bag->setCookie(Cookie::create('foo', 'bar', 0, '/path/foo', 'foo.bar')); + $bag->setCookie(Cookie::create('foo', 'bar', 0, '/path/bar', 'foo.bar')); + $bag->setCookie(Cookie::create('foo', 'bar', 0, '/path/bar', 'bar.foo')); + $bag->setCookie(Cookie::create('foo', 'bar')); $this->assertCount(4, $bag->getCookies()); - $this->assertEquals('foo=bar; path=/path/foo; domain=foo.bar; httponly', $bag->get('set-cookie')); - $this->assertEquals(array( - 'foo=bar; path=/path/foo; domain=foo.bar; httponly', - 'foo=bar; path=/path/bar; domain=foo.bar; httponly', - 'foo=bar; path=/path/bar; domain=bar.foo; httponly', - 'foo=bar; path=/; httponly', - ), $bag->get('set-cookie', null, false)); - - $this->assertSetCookieHeader('foo=bar; path=/path/foo; domain=foo.bar; httponly', $bag); - $this->assertSetCookieHeader('foo=bar; path=/path/bar; domain=foo.bar; httponly', $bag); - $this->assertSetCookieHeader('foo=bar; path=/path/bar; domain=bar.foo; httponly', $bag); - $this->assertSetCookieHeader('foo=bar; path=/; httponly', $bag); + $this->assertEquals('foo=bar; path=/path/foo; domain=foo.bar; httponly; samesite=lax', $bag->get('set-cookie')); + $this->assertEquals([ + 'foo=bar; path=/path/foo; domain=foo.bar; httponly; samesite=lax', + 'foo=bar; path=/path/bar; domain=foo.bar; httponly; samesite=lax', + 'foo=bar; path=/path/bar; domain=bar.foo; httponly; samesite=lax', + 'foo=bar; path=/; httponly; samesite=lax', + ], $bag->get('set-cookie', null, false)); + + $this->assertSetCookieHeader('foo=bar; path=/path/foo; domain=foo.bar; httponly; samesite=lax', $bag); + $this->assertSetCookieHeader('foo=bar; path=/path/bar; domain=foo.bar; httponly; samesite=lax', $bag); + $this->assertSetCookieHeader('foo=bar; path=/path/bar; domain=bar.foo; httponly; samesite=lax', $bag); + $this->assertSetCookieHeader('foo=bar; path=/; httponly; samesite=lax', $bag); $cookies = $bag->getCookies(ResponseHeaderBag::COOKIES_ARRAY); @@ -186,8 +186,8 @@ class ResponseHeaderBagTest extends TestCase $bag = new ResponseHeaderBag(); $this->assertFalse($bag->has('set-cookie')); - $bag->setCookie(new Cookie('foo', 'bar', 0, '/path/foo', 'foo.bar')); - $bag->setCookie(new Cookie('bar', 'foo', 0, '/path/bar', 'foo.bar')); + $bag->setCookie(Cookie::create('foo', 'bar', 0, '/path/foo', 'foo.bar')); + $bag->setCookie(Cookie::create('bar', 'foo', 0, '/path/bar', 'foo.bar')); $this->assertTrue($bag->has('set-cookie')); $cookies = $bag->getCookies(ResponseHeaderBag::COOKIES_ARRAY); @@ -209,8 +209,8 @@ class ResponseHeaderBagTest extends TestCase public function testRemoveCookieWithNullRemove() { $bag = new ResponseHeaderBag(); - $bag->setCookie(new Cookie('foo', 'bar', 0)); - $bag->setCookie(new Cookie('bar', 'foo', 0)); + $bag->setCookie(Cookie::create('foo', 'bar')); + $bag->setCookie(Cookie::create('bar', 'foo')); $cookies = $bag->getCookies(ResponseHeaderBag::COOKIES_ARRAY); $this->assertArrayHasKey('/', $cookies['']); @@ -228,48 +228,26 @@ class ResponseHeaderBagTest extends TestCase { $bag = new ResponseHeaderBag(); $bag->set('set-cookie', 'foo=bar'); - $this->assertEquals(array(new Cookie('foo', 'bar', 0, '/', null, false, false, true)), $bag->getCookies()); + $this->assertEquals([Cookie::create('foo', 'bar', 0, '/', null, false, false, true, null)], $bag->getCookies()); $bag->set('set-cookie', 'foo2=bar2', false); - $this->assertEquals(array( - new Cookie('foo', 'bar', 0, '/', null, false, false, true), - new Cookie('foo2', 'bar2', 0, '/', null, false, false, true), - ), $bag->getCookies()); + $this->assertEquals([ + Cookie::create('foo', 'bar', 0, '/', null, false, false, true, null), + Cookie::create('foo2', 'bar2', 0, '/', null, false, false, true, null), + ], $bag->getCookies()); $bag->remove('set-cookie'); - $this->assertEquals(array(), $bag->getCookies()); + $this->assertEquals([], $bag->getCookies()); } - /** - * @expectedException \InvalidArgumentException - */ public function testGetCookiesWithInvalidArgument() { + $this->expectException('InvalidArgumentException'); $bag = new ResponseHeaderBag(); $bag->getCookies('invalid_argument'); } - /** - * @expectedException \InvalidArgumentException - */ - public function testMakeDispositionInvalidDisposition() - { - $headers = new ResponseHeaderBag(); - - $headers->makeDisposition('invalid', 'foo.html'); - } - - /** - * @dataProvider provideMakeDisposition - */ - public function testMakeDisposition($disposition, $filename, $filenameFallback, $expected) - { - $headers = new ResponseHeaderBag(); - - $this->assertEquals($expected, $headers->makeDisposition($disposition, $filename, $filenameFallback)); - } - public function testToStringDoesntMessUpHeaders() { $headers = new ResponseHeaderBag(); @@ -280,43 +258,8 @@ class ResponseHeaderBagTest extends TestCase (string) $headers; $allHeaders = $headers->allPreserveCase(); - $this->assertEquals(array('http://www.symfony.com'), $allHeaders['Location']); - $this->assertEquals(array('text/html'), $allHeaders['Content-type']); - } - - public function provideMakeDisposition() - { - return array( - array('attachment', 'foo.html', 'foo.html', 'attachment; filename="foo.html"'), - array('attachment', 'foo.html', '', 'attachment; filename="foo.html"'), - array('attachment', 'foo bar.html', '', 'attachment; filename="foo bar.html"'), - array('attachment', 'foo "bar".html', '', 'attachment; filename="foo \\"bar\\".html"'), - array('attachment', 'foo%20bar.html', 'foo bar.html', 'attachment; filename="foo bar.html"; filename*=utf-8\'\'foo%2520bar.html'), - array('attachment', 'föö.html', 'foo.html', 'attachment; filename="foo.html"; filename*=utf-8\'\'f%C3%B6%C3%B6.html'), - ); - } - - /** - * @dataProvider provideMakeDispositionFail - * @expectedException \InvalidArgumentException - */ - public function testMakeDispositionFail($disposition, $filename) - { - $headers = new ResponseHeaderBag(); - - $headers->makeDisposition($disposition, $filename); - } - - public function provideMakeDispositionFail() - { - return array( - array('attachment', 'foo%20bar.html'), - array('attachment', 'foo/bar.html'), - array('attachment', '/foo.html'), - array('attachment', 'foo\bar.html'), - array('attachment', '\foo.html'), - array('attachment', 'föö.html'), - ); + $this->assertEquals(['http://www.symfony.com'], $allHeaders['Location']); + $this->assertEquals(['text/html'], $allHeaders['Content-type']); } public function testDateHeaderAddedOnCreation() @@ -332,7 +275,7 @@ class ResponseHeaderBagTest extends TestCase public function testDateHeaderCanBeSetOnCreation() { $someDate = 'Thu, 23 Mar 2017 09:15:12 GMT'; - $bag = new ResponseHeaderBag(array('Date' => $someDate)); + $bag = new ResponseHeaderBag(['Date' => $someDate]); $this->assertEquals($someDate, $bag->get('Date')); } @@ -340,7 +283,7 @@ class ResponseHeaderBagTest extends TestCase public function testDateHeaderWillBeRecreatedWhenRemoved() { $someDate = 'Thu, 23 Mar 2017 09:15:12 GMT'; - $bag = new ResponseHeaderBag(array('Date' => $someDate)); + $bag = new ResponseHeaderBag(['Date' => $someDate]); $bag->remove('Date'); // a (new) Date header is still present @@ -351,7 +294,7 @@ class ResponseHeaderBagTest extends TestCase public function testDateHeaderWillBeRecreatedWhenHeadersAreReplaced() { $bag = new ResponseHeaderBag(); - $bag->replace(array()); + $bag->replace([]); $this->assertTrue($bag->has('Date')); } diff --git a/vendor/symfony/http-foundation/Tests/ResponseTest.php b/vendor/symfony/http-foundation/Tests/ResponseTest.php index 350d972a945887a3f1f959a323ce6dae69b30785..ad1f806d7379b73ce923414c7552ae5eb285444b 100644 --- a/vendor/symfony/http-foundation/Tests/ResponseTest.php +++ b/vendor/symfony/http-foundation/Tests/ResponseTest.php @@ -11,6 +11,7 @@ namespace Symfony\Component\HttpFoundation\Tests; +use Symfony\Component\HttpFoundation\Cookie; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; @@ -21,7 +22,7 @@ class ResponseTest extends ResponseTestCase { public function testCreate() { - $response = Response::create('foo', 301, array('Foo' => 'bar')); + $response = Response::create('foo', 301, ['Foo' => 'bar']); $this->assertInstanceOf('Symfony\Component\HttpFoundation\Response', $response); $this->assertEquals(301, $response->getStatusCode()); @@ -126,7 +127,7 @@ class ResponseTest extends ResponseTestCase public function testSetNotModified() { - $response = new Response(); + $response = new Response('foo'); $modified = $response->setNotModified(); $this->assertObjectHasAttribute('headers', $modified); $this->assertObjectHasAttribute('content', $modified); @@ -135,6 +136,11 @@ class ResponseTest extends ResponseTestCase $this->assertObjectHasAttribute('statusText', $modified); $this->assertObjectHasAttribute('charset', $modified); $this->assertEquals(304, $modified->getStatusCode()); + + ob_start(); + $modified->sendContent(); + $string = ob_get_clean(); + $this->assertEmpty($string); } public function testIsSuccessful() @@ -248,10 +254,10 @@ class ResponseTest extends ResponseTestCase public function testIsValidateable() { - $response = new Response('', 200, array('Last-Modified' => $this->createDateTimeOneHourAgo()->format(DATE_RFC2822))); + $response = new Response('', 200, ['Last-Modified' => $this->createDateTimeOneHourAgo()->format(DATE_RFC2822)]); $this->assertTrue($response->isValidateable(), '->isValidateable() returns true if Last-Modified is present'); - $response = new Response('', 200, array('ETag' => '"12345"')); + $response = new Response('', 200, ['ETag' => '"12345"']); $this->assertTrue($response->isValidateable(), '->isValidateable() returns true if ETag is present'); $response = new Response(); @@ -261,7 +267,7 @@ class ResponseTest extends ResponseTestCase public function testGetDate() { $oneHourAgo = $this->createDateTimeOneHourAgo(); - $response = new Response('', 200, array('Date' => $oneHourAgo->format(DATE_RFC2822))); + $response = new Response('', 200, ['Date' => $oneHourAgo->format(DATE_RFC2822)]); $date = $response->getDate(); $this->assertEquals($oneHourAgo->getTimestamp(), $date->getTimestamp(), '->getDate() returns the Date header if present'); @@ -269,7 +275,7 @@ class ResponseTest extends ResponseTestCase $date = $response->getDate(); $this->assertEquals(time(), $date->getTimestamp(), '->getDate() returns the current Date if no Date header present'); - $response = new Response('', 200, array('Date' => $this->createDateTimeOneHourAgo()->format(DATE_RFC2822))); + $response = new Response('', 200, ['Date' => $this->createDateTimeOneHourAgo()->format(DATE_RFC2822)]); $now = $this->createDateTimeNow(); $response->headers->set('Date', $now->format(DATE_RFC2822)); $date = $response->getDate(); @@ -300,7 +306,7 @@ class ResponseTest extends ResponseTestCase $response = new Response(); $response->headers->set('Cache-Control', 'must-revalidate'); $response->headers->set('Expires', -1); - $this->assertEquals('Sat, 01 Jan 00 00:00:00 +0000', $response->getExpires()->format(DATE_RFC822)); + $this->assertLessThanOrEqual(time() - 2 * 86400, $response->getExpires()->format('U')); $response = new Response(); $this->assertNull($response->getMaxAge(), '->getMaxAge() returns null if no freshness information available'); @@ -357,6 +363,17 @@ class ResponseTest extends ResponseTestCase $response->headers->set('Expires', -1); $response->expire(); $this->assertNull($response->headers->get('Age'), '->expire() does not set the Age when the response is expired'); + + $response = new Response(); + $response->headers->set('Expires', date(DATE_RFC2822, time() + 600)); + $response->expire(); + $this->assertNull($response->headers->get('Expires'), '->expire() removes the Expires header when the response is fresh'); + } + + public function testNullExpireHeader() + { + $response = new Response(null, 200, ['Expires' => null]); + $this->assertNull($response->getExpires()); } public function testGetTtl() @@ -404,21 +421,21 @@ class ResponseTest extends ResponseTestCase public function testGetVary() { $response = new Response(); - $this->assertEquals(array(), $response->getVary(), '->getVary() returns an empty array if no Vary header is present'); + $this->assertEquals([], $response->getVary(), '->getVary() returns an empty array if no Vary header is present'); $response = new Response(); $response->headers->set('Vary', 'Accept-Language'); - $this->assertEquals(array('Accept-Language'), $response->getVary(), '->getVary() parses a single header name value'); + $this->assertEquals(['Accept-Language'], $response->getVary(), '->getVary() parses a single header name value'); $response = new Response(); $response->headers->set('Vary', 'Accept-Language User-Agent X-Foo'); - $this->assertEquals(array('Accept-Language', 'User-Agent', 'X-Foo'), $response->getVary(), '->getVary() parses multiple header name values separated by spaces'); + $this->assertEquals(['Accept-Language', 'User-Agent', 'X-Foo'], $response->getVary(), '->getVary() parses multiple header name values separated by spaces'); $response = new Response(); $response->headers->set('Vary', 'Accept-Language,User-Agent, X-Foo'); - $this->assertEquals(array('Accept-Language', 'User-Agent', 'X-Foo'), $response->getVary(), '->getVary() parses multiple header name values separated by commas'); + $this->assertEquals(['Accept-Language', 'User-Agent', 'X-Foo'], $response->getVary(), '->getVary() parses multiple header name values separated by commas'); - $vary = array('Accept-Language', 'User-Agent', 'X-foo'); + $vary = ['Accept-Language', 'User-Agent', 'X-foo']; $response = new Response(); $response->headers->set('Vary', $vary); @@ -433,18 +450,18 @@ class ResponseTest extends ResponseTestCase { $response = new Response(); $response->setVary('Accept-Language'); - $this->assertEquals(array('Accept-Language'), $response->getVary()); + $this->assertEquals(['Accept-Language'], $response->getVary()); $response->setVary('Accept-Language, User-Agent'); - $this->assertEquals(array('Accept-Language', 'User-Agent'), $response->getVary(), '->setVary() replace the vary header by default'); + $this->assertEquals(['Accept-Language', 'User-Agent'], $response->getVary(), '->setVary() replace the vary header by default'); $response->setVary('X-Foo', false); - $this->assertEquals(array('Accept-Language', 'User-Agent', 'X-Foo'), $response->getVary(), '->setVary() doesn\'t wipe out earlier Vary headers if replace is set to false'); + $this->assertEquals(['Accept-Language', 'User-Agent', 'X-Foo'], $response->getVary(), '->setVary() doesn\'t wipe out earlier Vary headers if replace is set to false'); } public function testDefaultContentType() { - $headerMock = $this->getMockBuilder('Symfony\Component\HttpFoundation\ResponseHeaderBag')->setMethods(array('set'))->getMock(); + $headerMock = $this->getMockBuilder('Symfony\Component\HttpFoundation\ResponseHeaderBag')->setMethods(['set'])->getMock(); $headerMock->expects($this->at(0)) ->method('set') ->with('Content-Type', 'text/html'); @@ -522,7 +539,6 @@ class ResponseTest extends ResponseTestCase $response->prepare($request); $this->assertEquals('', $response->getContent()); $this->assertFalse($response->headers->has('Content-Type')); - $this->assertFalse($response->headers->has('Content-Type')); $response->setContent('content'); $response->setStatusCode(304); @@ -563,58 +579,76 @@ class ResponseTest extends ResponseTestCase $this->assertFalse($response->headers->has('expires')); } + public function testPrepareSetsCookiesSecure() + { + $cookie = Cookie::create('foo', 'bar'); + + $response = new Response('foo'); + $response->headers->setCookie($cookie); + + $request = Request::create('/', 'GET'); + $response->prepare($request); + + $this->assertFalse($cookie->isSecure()); + + $request = Request::create('https://localhost/', 'GET'); + $response->prepare($request); + + $this->assertTrue($cookie->isSecure()); + } + public function testSetCache() { $response = new Response(); - //array('etag', 'last_modified', 'max_age', 's_maxage', 'private', 'public') + // ['etag', 'last_modified', 'max_age', 's_maxage', 'private', 'public'] try { - $response->setCache(array('wrong option' => 'value')); + $response->setCache(['wrong option' => 'value']); $this->fail('->setCache() throws an InvalidArgumentException if an option is not supported'); } catch (\Exception $e) { $this->assertInstanceOf('InvalidArgumentException', $e, '->setCache() throws an InvalidArgumentException if an option is not supported'); - $this->assertContains('"wrong option"', $e->getMessage()); + $this->assertStringContainsString('"wrong option"', $e->getMessage()); } - $options = array('etag' => '"whatever"'); + $options = ['etag' => '"whatever"']; $response->setCache($options); $this->assertEquals($response->getEtag(), '"whatever"'); $now = $this->createDateTimeNow(); - $options = array('last_modified' => $now); + $options = ['last_modified' => $now]; $response->setCache($options); $this->assertEquals($response->getLastModified()->getTimestamp(), $now->getTimestamp()); - $options = array('max_age' => 100); + $options = ['max_age' => 100]; $response->setCache($options); $this->assertEquals($response->getMaxAge(), 100); - $options = array('s_maxage' => 200); + $options = ['s_maxage' => 200]; $response->setCache($options); $this->assertEquals($response->getMaxAge(), 200); $this->assertTrue($response->headers->hasCacheControlDirective('public')); $this->assertFalse($response->headers->hasCacheControlDirective('private')); - $response->setCache(array('public' => true)); + $response->setCache(['public' => true]); $this->assertTrue($response->headers->hasCacheControlDirective('public')); $this->assertFalse($response->headers->hasCacheControlDirective('private')); - $response->setCache(array('public' => false)); + $response->setCache(['public' => false]); $this->assertFalse($response->headers->hasCacheControlDirective('public')); $this->assertTrue($response->headers->hasCacheControlDirective('private')); - $response->setCache(array('private' => true)); + $response->setCache(['private' => true]); $this->assertFalse($response->headers->hasCacheControlDirective('public')); $this->assertTrue($response->headers->hasCacheControlDirective('private')); - $response->setCache(array('private' => false)); + $response->setCache(['private' => false]); $this->assertTrue($response->headers->hasCacheControlDirective('public')); $this->assertFalse($response->headers->hasCacheControlDirective('private')); - $response->setCache(array('immutable' => true)); + $response->setCache(['immutable' => true]); $this->assertTrue($response->headers->hasCacheControlDirective('immutable')); - $response->setCache(array('immutable' => false)); + $response->setCache(['immutable' => false]); $this->assertFalse($response->headers->hasCacheControlDirective('immutable')); } @@ -625,7 +659,7 @@ class ResponseTest extends ResponseTestCase ob_start(); $response->sendContent(); $string = ob_get_clean(); - $this->assertContains('test response rendering', $string); + $this->assertStringContainsString('test response rendering', $string); } public function testSetPublic() @@ -653,6 +687,22 @@ class ResponseTest extends ResponseTestCase $this->assertTrue($response->isImmutable()); } + public function testSetDate() + { + $response = new Response(); + $response->setDate(\DateTime::createFromFormat(\DateTime::ATOM, '2013-01-26T09:21:56+0100', new \DateTimeZone('Europe/Berlin'))); + + $this->assertEquals('2013-01-26T08:21:56+00:00', $response->getDate()->format(\DateTime::ATOM)); + } + + public function testSetDateWithImmutable() + { + $response = new Response(); + $response->setDate(\DateTimeImmutable::createFromFormat(\DateTime::ATOM, '2013-01-26T09:21:56+0100', new \DateTimeZone('Europe/Berlin'))); + + $this->assertEquals('2013-01-26T08:21:56+00:00', $response->getDate()->format(\DateTime::ATOM)); + } + public function testSetExpires() { $response = new Response(); @@ -666,6 +716,16 @@ class ResponseTest extends ResponseTestCase $this->assertEquals($response->getExpires()->getTimestamp(), $now->getTimestamp()); } + public function testSetExpiresWithImmutable() + { + $response = new Response(); + + $now = $this->createDateTimeImmutableNow(); + $response->setExpires($now); + + $this->assertEquals($response->getExpires()->getTimestamp(), $now->getTimestamp()); + } + public function testSetLastModified() { $response = new Response(); @@ -676,6 +736,16 @@ class ResponseTest extends ResponseTestCase $this->assertNull($response->getLastModified()); } + public function testSetLastModifiedWithImmutable() + { + $response = new Response(); + $response->setLastModified($this->createDateTimeImmutableNow()); + $this->assertNotNull($response->getLastModified()); + + $response->setLastModified(null); + $this->assertNull($response->getLastModified()); + } + public function testIsInvalid() { $response = new Response(); @@ -715,14 +785,14 @@ class ResponseTest extends ResponseTestCase public function getStatusCodeFixtures() { - return array( - array('200', null, 'OK'), - array('200', false, ''), - array('200', 'foo', 'foo'), - array('199', null, 'unknown status'), - array('199', false, ''), - array('199', 'foo', 'foo'), - ); + return [ + ['200', null, 'OK'], + ['200', false, ''], + ['200', 'foo', 'foo'], + ['199', null, 'unknown status'], + ['199', false, ''], + ['199', 'foo', 'foo'], + ]; } public function testIsInformational() @@ -736,7 +806,7 @@ class ResponseTest extends ResponseTestCase public function testIsRedirectRedirection() { - foreach (array(301, 302, 303, 307) as $code) { + foreach ([301, 302, 303, 307] as $code) { $response = new Response('', $code); $this->assertTrue($response->isRedirection()); $this->assertTrue($response->isRedirect()); @@ -754,7 +824,7 @@ class ResponseTest extends ResponseTestCase $this->assertFalse($response->isRedirection()); $this->assertFalse($response->isRedirect()); - $response = new Response('', 301, array('Location' => '/good-uri')); + $response = new Response('', 301, ['Location' => '/good-uri']); $this->assertFalse($response->isRedirect('/bad-uri')); $this->assertTrue($response->isRedirect('/good-uri')); } @@ -770,7 +840,7 @@ class ResponseTest extends ResponseTestCase public function testIsEmpty() { - foreach (array(204, 304) as $code) { + foreach ([204, 304] as $code) { $response = new Response('', $code); $this->assertTrue($response->isEmpty()); } @@ -819,7 +889,7 @@ class ResponseTest extends ResponseTestCase public function testSetEtag() { - $response = new Response('', 200, array('ETag' => '"12345"')); + $response = new Response('', 200, ['ETag' => '"12345"']); $response->setEtag(); $this->assertNull($response->headers->get('Etag'), '->setEtag() removes Etags when call with null'); @@ -836,11 +906,11 @@ class ResponseTest extends ResponseTestCase } /** - * @expectedException \UnexpectedValueException * @dataProvider invalidContentProvider */ public function testSetContentInvalid($content) { + $this->expectException('UnexpectedValueException'); $response = new Response(); $response->setContent($content); } @@ -849,7 +919,7 @@ class ResponseTest extends ResponseTestCase { $response = new Response(); - $setters = array( + $setters = [ 'setProtocolVersion' => '1.0', 'setCharset' => 'UTF-8', 'setPublic' => null, @@ -860,7 +930,7 @@ class ResponseTest extends ResponseTestCase 'setSharedMaxAge' => 1, 'setTtl' => 1, 'setClientTtl' => 1, - ); + ]; foreach ($setters as $setter => $arg) { $this->assertEquals($response, $response->{$setter}($arg)); @@ -879,20 +949,20 @@ class ResponseTest extends ResponseTestCase public function validContentProvider() { - return array( - 'obj' => array(new StringableObject()), - 'string' => array('Foo'), - 'int' => array(2), - ); + return [ + 'obj' => [new StringableObject()], + 'string' => ['Foo'], + 'int' => [2], + ]; } public function invalidContentProvider() { - return array( - 'obj' => array(new \stdClass()), - 'array' => array(array()), - 'bool' => array(true, '1'), - ); + return [ + 'obj' => [new \stdClass()], + 'array' => [[]], + 'bool' => [true, '1'], + ]; } protected function createDateTimeOneHourAgo() @@ -912,39 +982,47 @@ class ResponseTest extends ResponseTestCase return $date->setTimestamp(time()); } + protected function createDateTimeImmutableNow() + { + $date = new \DateTimeImmutable(); + + return $date->setTimestamp(time()); + } + protected function provideResponse() { return new Response(); } /** - * @see http://github.com/zendframework/zend-diactoros for the canonical source repository + * @see http://github.com/zendframework/zend-diactoros for the canonical source repository * - * @author Fábio Pacheco + * @author Fábio Pacheco * @copyright Copyright (c) 2015-2016 Zend Technologies USA Inc. (http://www.zend.com) - * @license https://github.com/zendframework/zend-diactoros/blob/master/LICENSE.md New BSD License + * @license https://github.com/zendframework/zend-diactoros/blob/master/LICENSE.md New BSD License */ public function ianaCodesReasonPhrasesProvider() { - if (!in_array('https', stream_get_wrappers(), true)) { + if (!\in_array('https', stream_get_wrappers(), true)) { $this->markTestSkipped('The "https" wrapper is not available'); } $ianaHttpStatusCodes = new \DOMDocument(); - libxml_set_streams_context(stream_context_create(array( - 'http' => array( + $context = stream_context_create([ + 'http' => [ 'method' => 'GET', 'timeout' => 30, - ), - ))); + 'user_agent' => __METHOD__, + ], + ]); - $ianaHttpStatusCodes->load('https://www.iana.org/assignments/http-status-codes/http-status-codes.xml'); + $ianaHttpStatusCodes->loadXML(file_get_contents('https://www.iana.org/assignments/http-status-codes/http-status-codes.xml', false, $context)); if (!$ianaHttpStatusCodes->relaxNGValidate(__DIR__.'/schema/http-status-codes.rng')) { self::fail('Invalid IANA\'s HTTP status code list.'); } - $ianaCodesReasonPhrases = array(); + $ianaCodesReasonPhrases = []; $xpath = new \DOMXPath($ianaHttpStatusCodes); $xpath->registerNamespace('ns', 'http://www.iana.org/assignments'); @@ -954,16 +1032,16 @@ class ResponseTest extends ResponseTestCase $value = $xpath->query('.//ns:value', $record)->item(0)->nodeValue; $description = $xpath->query('.//ns:description', $record)->item(0)->nodeValue; - if (in_array($description, array('Unassigned', '(Unused)'), true)) { + if (\in_array($description, ['Unassigned', '(Unused)'], true)) { continue; } if (preg_match('/^([0-9]+)\s*\-\s*([0-9]+)$/', $value, $matches)) { for ($value = $matches[1]; $value <= $matches[2]; ++$value) { - $ianaCodesReasonPhrases[] = array($value, $description); + $ianaCodesReasonPhrases[] = [$value, $description]; } } else { - $ianaCodesReasonPhrases[] = array($value, $description); + $ianaCodesReasonPhrases[] = [$value, $description]; } } @@ -990,14 +1068,3 @@ class StringableObject class DefaultResponse extends Response { } - -class ExtendedResponse extends Response -{ - public function setLastModified(\DateTime $date = null) - { - } - - public function getDate() - { - } -} diff --git a/vendor/symfony/http-foundation/Tests/ServerBagTest.php b/vendor/symfony/http-foundation/Tests/ServerBagTest.php index f8becec5a982df0ffc049c1f409e334b7e260cc2..0663b118e675e9996646e1417be0dd69254a1932 100644 --- a/vendor/symfony/http-foundation/Tests/ServerBagTest.php +++ b/vendor/symfony/http-foundation/Tests/ServerBagTest.php @@ -23,7 +23,7 @@ class ServerBagTest extends TestCase { public function testShouldExtractHeadersFromServerArray() { - $server = array( + $server = [ 'SOME_SERVER_VARIABLE' => 'value', 'SOME_SERVER_VARIABLE2' => 'value', 'ROOT' => 'value', @@ -32,45 +32,45 @@ class ServerBagTest extends TestCase 'HTTP_ETAG' => 'asdf', 'PHP_AUTH_USER' => 'foo', 'PHP_AUTH_PW' => 'bar', - ); + ]; $bag = new ServerBag($server); - $this->assertEquals(array( + $this->assertEquals([ 'CONTENT_TYPE' => 'text/html', 'CONTENT_LENGTH' => '0', 'ETAG' => 'asdf', 'AUTHORIZATION' => 'Basic '.base64_encode('foo:bar'), 'PHP_AUTH_USER' => 'foo', 'PHP_AUTH_PW' => 'bar', - ), $bag->getHeaders()); + ], $bag->getHeaders()); } public function testHttpPasswordIsOptional() { - $bag = new ServerBag(array('PHP_AUTH_USER' => 'foo')); + $bag = new ServerBag(['PHP_AUTH_USER' => 'foo']); - $this->assertEquals(array( + $this->assertEquals([ 'AUTHORIZATION' => 'Basic '.base64_encode('foo:'), 'PHP_AUTH_USER' => 'foo', 'PHP_AUTH_PW' => '', - ), $bag->getHeaders()); + ], $bag->getHeaders()); } public function testHttpBasicAuthWithPhpCgi() { - $bag = new ServerBag(array('HTTP_AUTHORIZATION' => 'Basic '.base64_encode('foo:bar'))); + $bag = new ServerBag(['HTTP_AUTHORIZATION' => 'Basic '.base64_encode('foo:bar')]); - $this->assertEquals(array( + $this->assertEquals([ 'AUTHORIZATION' => 'Basic '.base64_encode('foo:bar'), 'PHP_AUTH_USER' => 'foo', 'PHP_AUTH_PW' => 'bar', - ), $bag->getHeaders()); + ], $bag->getHeaders()); } public function testHttpBasicAuthWithPhpCgiBogus() { - $bag = new ServerBag(array('HTTP_AUTHORIZATION' => 'Basic_'.base64_encode('foo:bar'))); + $bag = new ServerBag(['HTTP_AUTHORIZATION' => 'Basic_'.base64_encode('foo:bar')]); // Username and passwords should not be set as the header is bogus $headers = $bag->getHeaders(); @@ -80,41 +80,41 @@ class ServerBagTest extends TestCase public function testHttpBasicAuthWithPhpCgiRedirect() { - $bag = new ServerBag(array('REDIRECT_HTTP_AUTHORIZATION' => 'Basic '.base64_encode('username:pass:word'))); + $bag = new ServerBag(['REDIRECT_HTTP_AUTHORIZATION' => 'Basic '.base64_encode('username:pass:word')]); - $this->assertEquals(array( + $this->assertEquals([ 'AUTHORIZATION' => 'Basic '.base64_encode('username:pass:word'), 'PHP_AUTH_USER' => 'username', 'PHP_AUTH_PW' => 'pass:word', - ), $bag->getHeaders()); + ], $bag->getHeaders()); } public function testHttpBasicAuthWithPhpCgiEmptyPassword() { - $bag = new ServerBag(array('HTTP_AUTHORIZATION' => 'Basic '.base64_encode('foo:'))); + $bag = new ServerBag(['HTTP_AUTHORIZATION' => 'Basic '.base64_encode('foo:')]); - $this->assertEquals(array( + $this->assertEquals([ 'AUTHORIZATION' => 'Basic '.base64_encode('foo:'), 'PHP_AUTH_USER' => 'foo', 'PHP_AUTH_PW' => '', - ), $bag->getHeaders()); + ], $bag->getHeaders()); } public function testHttpDigestAuthWithPhpCgi() { $digest = 'Digest username="foo", realm="acme", nonce="'.md5('secret').'", uri="/protected, qop="auth"'; - $bag = new ServerBag(array('HTTP_AUTHORIZATION' => $digest)); + $bag = new ServerBag(['HTTP_AUTHORIZATION' => $digest]); - $this->assertEquals(array( + $this->assertEquals([ 'AUTHORIZATION' => $digest, 'PHP_AUTH_DIGEST' => $digest, - ), $bag->getHeaders()); + ], $bag->getHeaders()); } public function testHttpDigestAuthWithPhpCgiBogus() { $digest = 'Digest_username="foo", realm="acme", nonce="'.md5('secret').'", uri="/protected, qop="auth"'; - $bag = new ServerBag(array('HTTP_AUTHORIZATION' => $digest)); + $bag = new ServerBag(['HTTP_AUTHORIZATION' => $digest]); // Username and passwords should not be set as the header is bogus $headers = $bag->getHeaders(); @@ -125,32 +125,32 @@ class ServerBagTest extends TestCase public function testHttpDigestAuthWithPhpCgiRedirect() { $digest = 'Digest username="foo", realm="acme", nonce="'.md5('secret').'", uri="/protected, qop="auth"'; - $bag = new ServerBag(array('REDIRECT_HTTP_AUTHORIZATION' => $digest)); + $bag = new ServerBag(['REDIRECT_HTTP_AUTHORIZATION' => $digest]); - $this->assertEquals(array( + $this->assertEquals([ 'AUTHORIZATION' => $digest, 'PHP_AUTH_DIGEST' => $digest, - ), $bag->getHeaders()); + ], $bag->getHeaders()); } public function testOAuthBearerAuth() { $headerContent = 'Bearer L-yLEOr9zhmUYRkzN1jwwxwQ-PBNiKDc8dgfB4hTfvo'; - $bag = new ServerBag(array('HTTP_AUTHORIZATION' => $headerContent)); + $bag = new ServerBag(['HTTP_AUTHORIZATION' => $headerContent]); - $this->assertEquals(array( + $this->assertEquals([ 'AUTHORIZATION' => $headerContent, - ), $bag->getHeaders()); + ], $bag->getHeaders()); } public function testOAuthBearerAuthWithRedirect() { $headerContent = 'Bearer L-yLEOr9zhmUYRkzN1jwwxwQ-PBNiKDc8dgfB4hTfvo'; - $bag = new ServerBag(array('REDIRECT_HTTP_AUTHORIZATION' => $headerContent)); + $bag = new ServerBag(['REDIRECT_HTTP_AUTHORIZATION' => $headerContent]); - $this->assertEquals(array( + $this->assertEquals([ 'AUTHORIZATION' => $headerContent, - ), $bag->getHeaders()); + ], $bag->getHeaders()); } /** @@ -159,12 +159,12 @@ class ServerBagTest extends TestCase public function testItDoesNotOverwriteTheAuthorizationHeaderIfItIsAlreadySet() { $headerContent = 'Bearer L-yLEOr9zhmUYRkzN1jwwxwQ-PBNiKDc8dgfB4hTfvo'; - $bag = new ServerBag(array('PHP_AUTH_USER' => 'foo', 'HTTP_AUTHORIZATION' => $headerContent)); + $bag = new ServerBag(['PHP_AUTH_USER' => 'foo', 'HTTP_AUTHORIZATION' => $headerContent]); - $this->assertEquals(array( + $this->assertEquals([ 'AUTHORIZATION' => $headerContent, 'PHP_AUTH_USER' => 'foo', 'PHP_AUTH_PW' => '', - ), $bag->getHeaders()); + ], $bag->getHeaders()); } } diff --git a/vendor/symfony/http-foundation/Tests/Session/Attribute/AttributeBagTest.php b/vendor/symfony/http-foundation/Tests/Session/Attribute/AttributeBagTest.php index 724a0b9844700d79dae4c6842e58b304c07ac3be..6313967afa405d80844ee6997982ef90d60361e3 100644 --- a/vendor/symfony/http-foundation/Tests/Session/Attribute/AttributeBagTest.php +++ b/vendor/symfony/http-foundation/Tests/Session/Attribute/AttributeBagTest.php @@ -21,38 +21,38 @@ use Symfony\Component\HttpFoundation\Session\Attribute\AttributeBag; */ class AttributeBagTest extends TestCase { - private $array = array(); + private $array = []; /** * @var AttributeBag */ private $bag; - protected function setUp() + protected function setUp(): void { - $this->array = array( + $this->array = [ 'hello' => 'world', 'always' => 'be happy', 'user.login' => 'drak', - 'csrf.token' => array( + 'csrf.token' => [ 'a' => '1234', 'b' => '4321', - ), - 'category' => array( - 'fishing' => array( + ], + 'category' => [ + 'fishing' => [ 'first' => 'cod', 'second' => 'sole', - ), - ), - ); - $this->bag = new AttributeBag('_sf2'); + ], + ], + ]; + $this->bag = new AttributeBag('_sf'); $this->bag->initialize($this->array); } - protected function tearDown() + protected function tearDown(): void { $this->bag = null; - $this->array = array(); + $this->array = []; } public function testInitialize() @@ -60,14 +60,14 @@ class AttributeBagTest extends TestCase $bag = new AttributeBag(); $bag->initialize($this->array); $this->assertEquals($this->array, $bag->all()); - $array = array('should' => 'change'); + $array = ['should' => 'change']; $bag->initialize($array); $this->assertEquals($array, $bag->all()); } public function testGetStorageKey() { - $this->assertEquals('_sf2', $this->bag->getStorageKey()); + $this->assertEquals('_sf', $this->bag->getStorageKey()); $attributeBag = new AttributeBag('test'); $this->assertEquals('test', $attributeBag->getStorageKey()); } @@ -122,7 +122,7 @@ class AttributeBagTest extends TestCase public function testReplace() { - $array = array(); + $array = []; $array['name'] = 'jack'; $array['foo.bar'] = 'beep'; $this->bag->replace($array); @@ -150,22 +150,22 @@ class AttributeBagTest extends TestCase public function testClear() { $this->bag->clear(); - $this->assertEquals(array(), $this->bag->all()); + $this->assertEquals([], $this->bag->all()); } public function attributesProvider() { - return array( - array('hello', 'world', true), - array('always', 'be happy', true), - array('user.login', 'drak', true), - array('csrf.token', array('a' => '1234', 'b' => '4321'), true), - array('category', array('fishing' => array('first' => 'cod', 'second' => 'sole')), true), - array('user2.login', null, false), - array('never', null, false), - array('bye', null, false), - array('bye/for/now', null, false), - ); + return [ + ['hello', 'world', true], + ['always', 'be happy', true], + ['user.login', 'drak', true], + ['csrf.token', ['a' => '1234', 'b' => '4321'], true], + ['category', ['fishing' => ['first' => 'cod', 'second' => 'sole']], true], + ['user2.login', null, false], + ['never', null, false], + ['bye', null, false], + ['bye/for/now', null, false], + ]; } public function testGetIterator() @@ -176,11 +176,11 @@ class AttributeBagTest extends TestCase ++$i; } - $this->assertEquals(count($this->array), $i); + $this->assertEquals(\count($this->array), $i); } public function testCount() { - $this->assertCount(count($this->array), $this->bag); + $this->assertCount(\count($this->array), $this->bag); } } diff --git a/vendor/symfony/http-foundation/Tests/Session/Attribute/NamespacedAttributeBagTest.php b/vendor/symfony/http-foundation/Tests/Session/Attribute/NamespacedAttributeBagTest.php index f074ce1b26261e4adc4220d0980a7553396759ac..3a3251d05b799ee47d3d63beb2fff9fbccb20854 100644 --- a/vendor/symfony/http-foundation/Tests/Session/Attribute/NamespacedAttributeBagTest.php +++ b/vendor/symfony/http-foundation/Tests/Session/Attribute/NamespacedAttributeBagTest.php @@ -21,38 +21,38 @@ use Symfony\Component\HttpFoundation\Session\Attribute\NamespacedAttributeBag; */ class NamespacedAttributeBagTest extends TestCase { - private $array = array(); + private $array = []; /** * @var NamespacedAttributeBag */ private $bag; - protected function setUp() + protected function setUp(): void { - $this->array = array( + $this->array = [ 'hello' => 'world', 'always' => 'be happy', 'user.login' => 'drak', - 'csrf.token' => array( + 'csrf.token' => [ 'a' => '1234', 'b' => '4321', - ), - 'category' => array( - 'fishing' => array( + ], + 'category' => [ + 'fishing' => [ 'first' => 'cod', 'second' => 'sole', - ), - ), - ); + ], + ], + ]; $this->bag = new NamespacedAttributeBag('_sf2', '/'); $this->bag->initialize($this->array); } - protected function tearDown() + protected function tearDown(): void { $this->bag = null; - $this->array = array(); + $this->array = []; } public function testInitialize() @@ -60,7 +60,7 @@ class NamespacedAttributeBagTest extends TestCase $bag = new NamespacedAttributeBag(); $bag->initialize($this->array); $this->assertEquals($this->array, $this->bag->all()); - $array = array('should' => 'not stick'); + $array = ['should' => 'not stick']; $bag->initialize($array); // should have remained the same @@ -82,6 +82,17 @@ class NamespacedAttributeBagTest extends TestCase $this->assertEquals($exists, $this->bag->has($key)); } + /** + * @dataProvider attributesProvider + */ + public function testHasNoSideEffect($key, $value, $expected) + { + $expected = json_encode($this->bag->all()); + $this->bag->has($key); + + $this->assertEquals($expected, json_encode($this->bag->all())); + } + /** * @dataProvider attributesProvider */ @@ -96,6 +107,17 @@ class NamespacedAttributeBagTest extends TestCase $this->assertEquals('default', $this->bag->get('user2.login', 'default')); } + /** + * @dataProvider attributesProvider + */ + public function testGetNoSideEffect($key, $value, $expected) + { + $expected = json_encode($this->bag->all()); + $this->bag->get($key); + + $this->assertEquals($expected, json_encode($this->bag->all())); + } + /** * @dataProvider attributesProvider */ @@ -117,7 +139,7 @@ class NamespacedAttributeBagTest extends TestCase public function testReplace() { - $array = array(); + $array = []; $array['name'] = 'jack'; $array['foo.bar'] = 'beep'; $this->bag->replace($array); @@ -155,28 +177,28 @@ class NamespacedAttributeBagTest extends TestCase public function testClear() { $this->bag->clear(); - $this->assertEquals(array(), $this->bag->all()); + $this->assertEquals([], $this->bag->all()); } public function attributesProvider() { - return array( - array('hello', 'world', true), - array('always', 'be happy', true), - array('user.login', 'drak', true), - array('csrf.token', array('a' => '1234', 'b' => '4321'), true), - array('csrf.token/a', '1234', true), - array('csrf.token/b', '4321', true), - array('category', array('fishing' => array('first' => 'cod', 'second' => 'sole')), true), - array('category/fishing', array('first' => 'cod', 'second' => 'sole'), true), - array('category/fishing/missing/first', null, false), - array('category/fishing/first', 'cod', true), - array('category/fishing/second', 'sole', true), - array('category/fishing/missing/second', null, false), - array('user2.login', null, false), - array('never', null, false), - array('bye', null, false), - array('bye/for/now', null, false), - ); + return [ + ['hello', 'world', true], + ['always', 'be happy', true], + ['user.login', 'drak', true], + ['csrf.token', ['a' => '1234', 'b' => '4321'], true], + ['csrf.token/a', '1234', true], + ['csrf.token/b', '4321', true], + ['category', ['fishing' => ['first' => 'cod', 'second' => 'sole']], true], + ['category/fishing', ['first' => 'cod', 'second' => 'sole'], true], + ['category/fishing/missing/first', null, false], + ['category/fishing/first', 'cod', true], + ['category/fishing/second', 'sole', true], + ['category/fishing/missing/second', null, false], + ['user2.login', null, false], + ['never', null, false], + ['bye', null, false], + ['bye/for/now', null, false], + ]; } } diff --git a/vendor/symfony/http-foundation/Tests/Session/Flash/AutoExpireFlashBagTest.php b/vendor/symfony/http-foundation/Tests/Session/Flash/AutoExpireFlashBagTest.php index fa8626ab923b7b365a3ee4df035a29bfc962c829..ba2687199d7b5187035fbc2fd9ab58fd165501c3 100644 --- a/vendor/symfony/http-foundation/Tests/Session/Flash/AutoExpireFlashBagTest.php +++ b/vendor/symfony/http-foundation/Tests/Session/Flash/AutoExpireFlashBagTest.php @@ -26,17 +26,17 @@ class AutoExpireFlashBagTest extends TestCase */ private $bag; - protected $array = array(); + protected $array = []; - protected function setUp() + protected function setUp(): void { parent::setUp(); $this->bag = new FlashBag(); - $this->array = array('new' => array('notice' => array('A previous flash message'))); + $this->array = ['new' => ['notice' => ['A previous flash message']]]; $this->bag->initialize($this->array); } - protected function tearDown() + protected function tearDown(): void { $this->bag = null; parent::tearDown(); @@ -45,16 +45,16 @@ class AutoExpireFlashBagTest extends TestCase public function testInitialize() { $bag = new FlashBag(); - $array = array('new' => array('notice' => array('A previous flash message'))); + $array = ['new' => ['notice' => ['A previous flash message']]]; $bag->initialize($array); - $this->assertEquals(array('A previous flash message'), $bag->peek('notice')); - $array = array('new' => array( - 'notice' => array('Something else'), - 'error' => array('a'), - )); + $this->assertEquals(['A previous flash message'], $bag->peek('notice')); + $array = ['new' => [ + 'notice' => ['Something else'], + 'error' => ['a'], + ]]; $bag->initialize($array); - $this->assertEquals(array('Something else'), $bag->peek('notice')); - $this->assertEquals(array('a'), $bag->peek('error')); + $this->assertEquals(['Something else'], $bag->peek('notice')); + $this->assertEquals(['a'], $bag->peek('error')); } public function testGetStorageKey() @@ -73,16 +73,16 @@ class AutoExpireFlashBagTest extends TestCase public function testPeek() { - $this->assertEquals(array(), $this->bag->peek('non_existing')); - $this->assertEquals(array('default'), $this->bag->peek('non_existing', array('default'))); - $this->assertEquals(array('A previous flash message'), $this->bag->peek('notice')); - $this->assertEquals(array('A previous flash message'), $this->bag->peek('notice')); + $this->assertEquals([], $this->bag->peek('non_existing')); + $this->assertEquals(['default'], $this->bag->peek('non_existing', ['default'])); + $this->assertEquals(['A previous flash message'], $this->bag->peek('notice')); + $this->assertEquals(['A previous flash message'], $this->bag->peek('notice')); } public function testSet() { $this->bag->set('notice', 'Foo'); - $this->assertEquals(array('A previous flash message'), $this->bag->peek('notice')); + $this->assertEquals(['A previous flash message'], $this->bag->peek('notice')); } public function testHas() @@ -93,43 +93,43 @@ class AutoExpireFlashBagTest extends TestCase public function testKeys() { - $this->assertEquals(array('notice'), $this->bag->keys()); + $this->assertEquals(['notice'], $this->bag->keys()); } public function testPeekAll() { - $array = array( - 'new' => array( + $array = [ + 'new' => [ 'notice' => 'Foo', 'error' => 'Bar', - ), - ); + ], + ]; $this->bag->initialize($array); - $this->assertEquals(array( + $this->assertEquals([ 'notice' => 'Foo', 'error' => 'Bar', - ), $this->bag->peekAll() + ], $this->bag->peekAll() ); - $this->assertEquals(array( + $this->assertEquals([ 'notice' => 'Foo', 'error' => 'Bar', - ), $this->bag->peekAll() + ], $this->bag->peekAll() ); } public function testGet() { - $this->assertEquals(array(), $this->bag->get('non_existing')); - $this->assertEquals(array('default'), $this->bag->get('non_existing', array('default'))); - $this->assertEquals(array('A previous flash message'), $this->bag->get('notice')); - $this->assertEquals(array(), $this->bag->get('notice')); + $this->assertEquals([], $this->bag->get('non_existing')); + $this->assertEquals(['default'], $this->bag->get('non_existing', ['default'])); + $this->assertEquals(['A previous flash message'], $this->bag->get('notice')); + $this->assertEquals([], $this->bag->get('notice')); } public function testSetAll() { - $this->bag->setAll(array('a' => 'first', 'b' => 'second')); + $this->bag->setAll(['a' => 'first', 'b' => 'second']); $this->assertFalse($this->bag->has('a')); $this->assertFalse($this->bag->has('b')); } @@ -138,17 +138,17 @@ class AutoExpireFlashBagTest extends TestCase { $this->bag->set('notice', 'Foo'); $this->bag->set('error', 'Bar'); - $this->assertEquals(array( - 'notice' => array('A previous flash message'), - ), $this->bag->all() + $this->assertEquals([ + 'notice' => ['A previous flash message'], + ], $this->bag->all() ); - $this->assertEquals(array(), $this->bag->all()); + $this->assertEquals([], $this->bag->all()); } public function testClear() { - $this->assertEquals(array('notice' => array('A previous flash message')), $this->bag->clear()); + $this->assertEquals(['notice' => ['A previous flash message']], $this->bag->clear()); } public function testDoNotRemoveTheNewFlashesWhenDisplayingTheExistingOnes() @@ -156,6 +156,6 @@ class AutoExpireFlashBagTest extends TestCase $this->bag->add('success', 'Something'); $this->bag->all(); - $this->assertEquals(array('new' => array('success' => array('Something')), 'display' => array()), $this->array); + $this->assertEquals(['new' => ['success' => ['Something']], 'display' => []], $this->array); } } diff --git a/vendor/symfony/http-foundation/Tests/Session/Flash/FlashBagTest.php b/vendor/symfony/http-foundation/Tests/Session/Flash/FlashBagTest.php index c4e75b1b18b4085e485b6345702b71fb37be21b4..24dbbfe98f05fc9cb2778f057abc7e1a88eede95 100644 --- a/vendor/symfony/http-foundation/Tests/Session/Flash/FlashBagTest.php +++ b/vendor/symfony/http-foundation/Tests/Session/Flash/FlashBagTest.php @@ -26,17 +26,17 @@ class FlashBagTest extends TestCase */ private $bag; - protected $array = array(); + protected $array = []; - protected function setUp() + protected function setUp(): void { parent::setUp(); $this->bag = new FlashBag(); - $this->array = array('notice' => array('A previous flash message')); + $this->array = ['notice' => ['A previous flash message']]; $this->bag->initialize($this->array); } - protected function tearDown() + protected function tearDown(): void { $this->bag = null; parent::tearDown(); @@ -47,7 +47,7 @@ class FlashBagTest extends TestCase $bag = new FlashBag(); $bag->initialize($this->array); $this->assertEquals($this->array, $bag->peekAll()); - $array = array('should' => array('change')); + $array = ['should' => ['change']]; $bag->initialize($array); $this->assertEquals($array, $bag->peekAll()); } @@ -68,37 +68,49 @@ class FlashBagTest extends TestCase public function testPeek() { - $this->assertEquals(array(), $this->bag->peek('non_existing')); - $this->assertEquals(array('default'), $this->bag->peek('not_existing', array('default'))); - $this->assertEquals(array('A previous flash message'), $this->bag->peek('notice')); - $this->assertEquals(array('A previous flash message'), $this->bag->peek('notice')); + $this->assertEquals([], $this->bag->peek('non_existing')); + $this->assertEquals(['default'], $this->bag->peek('not_existing', ['default'])); + $this->assertEquals(['A previous flash message'], $this->bag->peek('notice')); + $this->assertEquals(['A previous flash message'], $this->bag->peek('notice')); + } + + public function testAdd() + { + $tab = ['bar' => 'baz']; + $this->bag->add('string_message', 'lorem'); + $this->bag->add('object_message', new \stdClass()); + $this->bag->add('array_message', $tab); + + $this->assertEquals(['lorem'], $this->bag->get('string_message')); + $this->assertEquals([new \stdClass()], $this->bag->get('object_message')); + $this->assertEquals([$tab], $this->bag->get('array_message')); } public function testGet() { - $this->assertEquals(array(), $this->bag->get('non_existing')); - $this->assertEquals(array('default'), $this->bag->get('not_existing', array('default'))); - $this->assertEquals(array('A previous flash message'), $this->bag->get('notice')); - $this->assertEquals(array(), $this->bag->get('notice')); + $this->assertEquals([], $this->bag->get('non_existing')); + $this->assertEquals(['default'], $this->bag->get('not_existing', ['default'])); + $this->assertEquals(['A previous flash message'], $this->bag->get('notice')); + $this->assertEquals([], $this->bag->get('notice')); } public function testAll() { $this->bag->set('notice', 'Foo'); $this->bag->set('error', 'Bar'); - $this->assertEquals(array( - 'notice' => array('Foo'), - 'error' => array('Bar'), ), $this->bag->all() + $this->assertEquals([ + 'notice' => ['Foo'], + 'error' => ['Bar'], ], $this->bag->all() ); - $this->assertEquals(array(), $this->bag->all()); + $this->assertEquals([], $this->bag->all()); } public function testSet() { $this->bag->set('notice', 'Foo'); $this->bag->set('notice', 'Bar'); - $this->assertEquals(array('Bar'), $this->bag->peek('notice')); + $this->assertEquals(['Bar'], $this->bag->peek('notice')); } public function testHas() @@ -109,24 +121,37 @@ class FlashBagTest extends TestCase public function testKeys() { - $this->assertEquals(array('notice'), $this->bag->keys()); + $this->assertEquals(['notice'], $this->bag->keys()); + } + + public function testSetAll() + { + $this->bag->add('one_flash', 'Foo'); + $this->bag->add('another_flash', 'Bar'); + $this->assertTrue($this->bag->has('one_flash')); + $this->assertTrue($this->bag->has('another_flash')); + $this->bag->setAll(['unique_flash' => 'FooBar']); + $this->assertFalse($this->bag->has('one_flash')); + $this->assertFalse($this->bag->has('another_flash')); + $this->assertSame(['unique_flash' => 'FooBar'], $this->bag->all()); + $this->assertSame([], $this->bag->all()); } public function testPeekAll() { $this->bag->set('notice', 'Foo'); $this->bag->set('error', 'Bar'); - $this->assertEquals(array( - 'notice' => array('Foo'), - 'error' => array('Bar'), - ), $this->bag->peekAll() + $this->assertEquals([ + 'notice' => ['Foo'], + 'error' => ['Bar'], + ], $this->bag->peekAll() ); $this->assertTrue($this->bag->has('notice')); $this->assertTrue($this->bag->has('error')); - $this->assertEquals(array( - 'notice' => array('Foo'), - 'error' => array('Bar'), - ), $this->bag->peekAll() + $this->assertEquals([ + 'notice' => ['Foo'], + 'error' => ['Bar'], + ], $this->bag->peekAll() ); } } diff --git a/vendor/symfony/http-foundation/Tests/Session/SessionTest.php b/vendor/symfony/http-foundation/Tests/Session/SessionTest.php index 41720e4b6fc4edf4bc01a3d31ae0f918714cb1e0..e216bfc8c2eef71b5aeb6774b1f31ead735a096f 100644 --- a/vendor/symfony/http-foundation/Tests/Session/SessionTest.php +++ b/vendor/symfony/http-foundation/Tests/Session/SessionTest.php @@ -12,9 +12,10 @@ namespace Symfony\Component\HttpFoundation\Tests\Session; use PHPUnit\Framework\TestCase; -use Symfony\Component\HttpFoundation\Session\Session; -use Symfony\Component\HttpFoundation\Session\Flash\FlashBag; use Symfony\Component\HttpFoundation\Session\Attribute\AttributeBag; +use Symfony\Component\HttpFoundation\Session\Flash\FlashBag; +use Symfony\Component\HttpFoundation\Session\Session; +use Symfony\Component\HttpFoundation\Session\SessionBagProxy; use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage; /** @@ -36,13 +37,13 @@ class SessionTest extends TestCase */ protected $session; - protected function setUp() + protected function setUp(): void { $this->storage = new MockArraySessionStorage(); $this->session = new Session($this->storage, new AttributeBag(), new FlashBag()); } - protected function tearDown() + protected function tearDown(): void { $this->storage = null; $this->session = null; @@ -70,6 +71,27 @@ class SessionTest extends TestCase $this->assertEquals('0123456789abcdef', $this->session->getId()); } + public function testSetIdAfterStart() + { + $this->session->start(); + $id = $this->session->getId(); + + $e = null; + try { + $this->session->setId($id); + } catch (\Exception $e) { + } + + $this->assertNull($e); + + try { + $this->session->setId('different'); + } catch (\Exception $e) { + } + + $this->assertInstanceOf('\LogicException', $e); + } + public function testSetName() { $this->assertEquals('MOCKSESSID', $this->session->getName()); @@ -106,10 +128,10 @@ class SessionTest extends TestCase public function testReplace() { - $this->session->replace(array('happiness' => 'be good', 'symfony' => 'awesome')); - $this->assertEquals(array('happiness' => 'be good', 'symfony' => 'awesome'), $this->session->all()); - $this->session->replace(array()); - $this->assertEquals(array(), $this->session->all()); + $this->session->replace(['happiness' => 'be good', 'symfony' => 'awesome']); + $this->assertEquals(['happiness' => 'be good', 'symfony' => 'awesome'], $this->session->all()); + $this->session->replace([]); + $this->assertEquals([], $this->session->all()); } /** @@ -129,16 +151,16 @@ class SessionTest extends TestCase $this->session->set('hi', 'fabien'); $this->session->set($key, $value); $this->session->clear(); - $this->assertEquals(array(), $this->session->all()); + $this->assertEquals([], $this->session->all()); } public function setProvider() { - return array( - array('foo', 'bar', array('foo' => 'bar')), - array('foo.bar', 'too much beer', array('foo.bar' => 'too much beer')), - array('great', 'symfony is great', array('great' => 'symfony is great')), - ); + return [ + ['foo', 'bar', ['foo' => 'bar']], + ['foo.bar', 'too much beer', ['foo.bar' => 'too much beer']], + ['great', 'symfony is great', ['great' => 'symfony is great']], + ]; } /** @@ -149,14 +171,14 @@ class SessionTest extends TestCase $this->session->set('hi.world', 'have a nice day'); $this->session->set($key, $value); $this->session->remove($key); - $this->assertEquals(array('hi.world' => 'have a nice day'), $this->session->all()); + $this->assertEquals(['hi.world' => 'have a nice day'], $this->session->all()); } public function testInvalidate() { $this->session->set('invalidate', 123); $this->session->invalidate(); - $this->assertEquals(array(), $this->session->all()); + $this->assertEquals([], $this->session->all()); } public function testMigrate() @@ -195,7 +217,7 @@ class SessionTest extends TestCase public function testGetIterator() { - $attributes = array('hello' => 'world', 'symfony' => 'rocks'); + $attributes = ['hello' => 'world', 'symfony' => 'rocks']; foreach ($attributes as $key => $val) { $this->session->set($key, $val); } @@ -206,7 +228,7 @@ class SessionTest extends TestCase ++$i; } - $this->assertEquals(count($attributes), $i); + $this->assertEquals(\count($attributes), $i); } public function testGetCount() @@ -239,4 +261,28 @@ class SessionTest extends TestCase $flash->get('hello'); $this->assertTrue($this->session->isEmpty()); } + + public function testGetBagWithBagImplementingGetBag() + { + $bag = new AttributeBag(); + $bag->setName('foo'); + + $storage = new MockArraySessionStorage(); + $storage->registerBag($bag); + + $this->assertSame($bag, (new Session($storage))->getBag('foo')); + } + + public function testGetBagWithBagNotImplementingGetBag() + { + $data = []; + + $bag = new AttributeBag(); + $bag->setName('foo'); + + $storage = new MockArraySessionStorage(); + $storage->registerBag(new SessionBagProxy($bag, $data, $usageIndex)); + + $this->assertSame($bag, (new Session($storage))->getBag('foo')); + } } diff --git a/vendor/symfony/http-foundation/Tests/Session/Storage/Handler/AbstractRedisSessionHandlerTestCase.php b/vendor/symfony/http-foundation/Tests/Session/Storage/Handler/AbstractRedisSessionHandlerTestCase.php new file mode 100644 index 0000000000000000000000000000000000000000..6a15a06873e25a3b7109d05b805dff00e98bf52b --- /dev/null +++ b/vendor/symfony/http-foundation/Tests/Session/Storage/Handler/AbstractRedisSessionHandlerTestCase.php @@ -0,0 +1,145 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\Tests\Session\Storage\Handler; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\HttpFoundation\Session\Storage\Handler\RedisSessionHandler; + +/** + * @requires extension redis + * @group time-sensitive + */ +abstract class AbstractRedisSessionHandlerTestCase extends TestCase +{ + protected const PREFIX = 'prefix_'; + + /** + * @var RedisSessionHandler + */ + protected $storage; + + /** + * @var \Redis|\RedisArray|\RedisCluster|\Predis\Client + */ + protected $redisClient; + + /** + * @return \Redis|\RedisArray|\RedisCluster|\Predis\Client + */ + abstract protected function createRedisClient(string $host); + + protected function setUp(): void + { + parent::setUp(); + + if (!\extension_loaded('redis')) { + self::markTestSkipped('Extension redis required.'); + } + + $host = getenv('REDIS_HOST') ?: 'localhost'; + + $this->redisClient = $this->createRedisClient($host); + $this->storage = new RedisSessionHandler( + $this->redisClient, + ['prefix' => self::PREFIX] + ); + } + + protected function tearDown(): void + { + $this->redisClient = null; + $this->storage = null; + + parent::tearDown(); + } + + public function testOpenSession() + { + $this->assertTrue($this->storage->open('', '')); + } + + public function testCloseSession() + { + $this->assertTrue($this->storage->close()); + } + + public function testReadSession() + { + $this->redisClient->set(self::PREFIX.'id1', null); + $this->redisClient->set(self::PREFIX.'id2', 'abc123'); + + $this->assertEquals('', $this->storage->read('id1')); + $this->assertEquals('abc123', $this->storage->read('id2')); + } + + public function testWriteSession() + { + $this->assertTrue($this->storage->write('id', 'data')); + + $this->assertTrue((bool) $this->redisClient->exists(self::PREFIX.'id')); + $this->assertEquals('data', $this->redisClient->get(self::PREFIX.'id')); + } + + public function testUseSessionGcMaxLifetimeAsTimeToLive() + { + $this->storage->write('id', 'data'); + $ttl = $this->redisClient->ttl(self::PREFIX.'id'); + + $this->assertLessThanOrEqual(ini_get('session.gc_maxlifetime'), $ttl); + $this->assertGreaterThanOrEqual(0, $ttl); + } + + public function testDestroySession() + { + $this->redisClient->set(self::PREFIX.'id', 'foo'); + + $this->assertTrue((bool) $this->redisClient->exists(self::PREFIX.'id')); + $this->assertTrue($this->storage->destroy('id')); + $this->assertFalse((bool) $this->redisClient->exists(self::PREFIX.'id')); + } + + public function testGcSession() + { + $this->assertTrue($this->storage->gc(123)); + } + + public function testUpdateTimestamp() + { + $lowTtl = 10; + + $this->redisClient->setex(self::PREFIX.'id', $lowTtl, 'foo'); + $this->storage->updateTimestamp('id', []); + + $this->assertGreaterThan($lowTtl, $this->redisClient->ttl(self::PREFIX.'id')); + } + + /** + * @dataProvider getOptionFixtures + */ + public function testSupportedParam(array $options, bool $supported) + { + try { + new RedisSessionHandler($this->redisClient, $options); + $this->assertTrue($supported); + } catch (\InvalidArgumentException $e) { + $this->assertFalse($supported); + } + } + + public function getOptionFixtures(): array + { + return [ + [['prefix' => 'session'], true], + [['prefix' => 'sfs', 'foo' => 'bar'], false], + ]; + } +} diff --git a/vendor/symfony/http-foundation/Tests/Session/Storage/Handler/AbstractSessionHandlerTest.php b/vendor/symfony/http-foundation/Tests/Session/Storage/Handler/AbstractSessionHandlerTest.php index 3ac081e3884c1f0cfa37ea8fa4e15766e818316f..b25b68bbb3703c8c8a1d4ea26e97f3f3c7ee1225 100644 --- a/vendor/symfony/http-foundation/Tests/Session/Storage/Handler/AbstractSessionHandlerTest.php +++ b/vendor/symfony/http-foundation/Tests/Session/Storage/Handler/AbstractSessionHandlerTest.php @@ -13,26 +13,23 @@ namespace Symfony\Component\HttpFoundation\Tests\Session\Storage\Handler; use PHPUnit\Framework\TestCase; -/** - * @requires PHP 7.0 - */ class AbstractSessionHandlerTest extends TestCase { private static $server; - public static function setUpBeforeClass() + public static function setUpBeforeClass(): void { - $spec = array( - 1 => array('file', '/dev/null', 'w'), - 2 => array('file', '/dev/null', 'w'), - ); + $spec = [ + 1 => ['file', '/dev/null', 'w'], + 2 => ['file', '/dev/null', 'w'], + ]; if (!self::$server = @proc_open('exec php -S localhost:8053', $spec, $pipes, __DIR__.'/Fixtures')) { self::markTestSkipped('PHP server unable to start.'); } sleep(1); } - public static function tearDownAfterClass() + public static function tearDownAfterClass(): void { if (self::$server) { proc_terminate(self::$server); @@ -45,7 +42,7 @@ class AbstractSessionHandlerTest extends TestCase */ public function testSession($fixture) { - $context = array('http' => array('header' => "Cookie: sid=123abc\r\n")); + $context = ['http' => ['header' => "Cookie: sid=123abc\r\n"]]; $context = stream_context_create($context); $result = file_get_contents(sprintf('http://localhost:8053/%s.php', $fixture), false, $context); @@ -55,7 +52,7 @@ class AbstractSessionHandlerTest extends TestCase public function provideSession() { foreach (glob(__DIR__.'/Fixtures/*.php') as $file) { - yield array(pathinfo($file, PATHINFO_FILENAME)); + yield [pathinfo($file, PATHINFO_FILENAME)]; } } } diff --git a/vendor/symfony/http-foundation/Tests/Session/Storage/Handler/Fixtures/common.inc b/vendor/symfony/http-foundation/Tests/Session/Storage/Handler/Fixtures/common.inc index 7a064c7f3f06121d0eb554508edf4ff5740af35f..a887f607e899a4a1450e5a819267fd5e3b196ff2 100644 --- a/vendor/symfony/http-foundation/Tests/Session/Storage/Handler/Fixtures/common.inc +++ b/vendor/symfony/http-foundation/Tests/Session/Storage/Handler/Fixtures/common.inc @@ -60,14 +60,14 @@ class TestSessionHandler extends AbstractSessionHandler $this->data = $data; } - public function open($path, $name) + public function open($path, $name): bool { echo __FUNCTION__, "\n"; return parent::open($path, $name); } - public function validateId($sessionId) + public function validateId($sessionId): bool { echo __FUNCTION__, "\n"; @@ -77,7 +77,7 @@ class TestSessionHandler extends AbstractSessionHandler /** * {@inheritdoc} */ - public function read($sessionId) + public function read($sessionId): string { echo __FUNCTION__, "\n"; @@ -87,7 +87,7 @@ class TestSessionHandler extends AbstractSessionHandler /** * {@inheritdoc} */ - public function updateTimestamp($sessionId, $data) + public function updateTimestamp($sessionId, $data): bool { echo __FUNCTION__, "\n"; @@ -97,7 +97,7 @@ class TestSessionHandler extends AbstractSessionHandler /** * {@inheritdoc} */ - public function write($sessionId, $data) + public function write($sessionId, $data): bool { echo __FUNCTION__, "\n"; @@ -107,42 +107,42 @@ class TestSessionHandler extends AbstractSessionHandler /** * {@inheritdoc} */ - public function destroy($sessionId) + public function destroy($sessionId): bool { echo __FUNCTION__, "\n"; return parent::destroy($sessionId); } - public function close() + public function close(): bool { echo __FUNCTION__, "\n"; return true; } - public function gc($maxLifetime) + public function gc($maxLifetime): bool { echo __FUNCTION__, "\n"; return true; } - protected function doRead($sessionId) + protected function doRead($sessionId): string { echo __FUNCTION__.': ', $this->data, "\n"; return $this->data; } - protected function doWrite($sessionId, $data) + protected function doWrite($sessionId, $data): bool { echo __FUNCTION__.': ', $data, "\n"; return true; } - protected function doDestroy($sessionId) + protected function doDestroy($sessionId): bool { echo __FUNCTION__, "\n"; diff --git a/vendor/symfony/http-foundation/Tests/Session/Storage/Handler/Fixtures/storage.expected b/vendor/symfony/http-foundation/Tests/Session/Storage/Handler/Fixtures/storage.expected index 4533a10a1f7cf99dd7af1b7fc22a2fe0fa1c746a..05a5d5d0b090f2e2897ce3198885ac2e5902de9c 100644 --- a/vendor/symfony/http-foundation/Tests/Session/Storage/Handler/Fixtures/storage.expected +++ b/vendor/symfony/http-foundation/Tests/Session/Storage/Handler/Fixtures/storage.expected @@ -11,10 +11,11 @@ $_SESSION is not empty write destroy close -$_SESSION is not empty +$_SESSION is empty Array ( [0] => Content-Type: text/plain; charset=utf-8 [1] => Cache-Control: max-age=0, private, must-revalidate + [2] => Set-Cookie: sid=deleted; expires=Thu, 01-Jan-1970 00:00:01 GMT; Max-Age=0; path=/; secure; HttpOnly ) shutdown diff --git a/vendor/symfony/http-foundation/Tests/Session/Storage/Handler/Fixtures/with_cookie_and_session.expected b/vendor/symfony/http-foundation/Tests/Session/Storage/Handler/Fixtures/with_cookie_and_session.expected index 5de2d9e3904ed4d37b75edf4811aa3863662cbfe..63078228df139b9130357054d9c2c0d90b79427d 100644 --- a/vendor/symfony/http-foundation/Tests/Session/Storage/Handler/Fixtures/with_cookie_and_session.expected +++ b/vendor/symfony/http-foundation/Tests/Session/Storage/Handler/Fixtures/with_cookie_and_session.expected @@ -20,5 +20,6 @@ Array [0] => Content-Type: text/plain; charset=utf-8 [1] => Cache-Control: max-age=10800, private, must-revalidate [2] => Set-Cookie: abc=def + [3] => Set-Cookie: sid=deleted; expires=Thu, 01-Jan-1970 00:00:01 GMT; Max-Age=0; path=/; secure; HttpOnly ) shutdown diff --git a/vendor/symfony/http-foundation/Tests/Session/Storage/Handler/Fixtures/with_samesite.expected b/vendor/symfony/http-foundation/Tests/Session/Storage/Handler/Fixtures/with_samesite.expected new file mode 100644 index 0000000000000000000000000000000000000000..d20fb88ec052f3979ed38c9b08b2e0fa71b34280 --- /dev/null +++ b/vendor/symfony/http-foundation/Tests/Session/Storage/Handler/Fixtures/with_samesite.expected @@ -0,0 +1,16 @@ +open +validateId +read +doRead: +read + +write +doWrite: foo|s:3:"bar"; +close +Array +( + [0] => Content-Type: text/plain; charset=utf-8 + [1] => Cache-Control: max-age=0, private, must-revalidate + [2] => Set-Cookie: sid=random_session_id; path=/; secure; HttpOnly; SameSite=lax +) +shutdown diff --git a/vendor/symfony/http-foundation/Tests/Session/Storage/Handler/Fixtures/with_samesite.php b/vendor/symfony/http-foundation/Tests/Session/Storage/Handler/Fixtures/with_samesite.php new file mode 100644 index 0000000000000000000000000000000000000000..fc2c4182895acb965d1c92140fed1a4532aeb17e --- /dev/null +++ b/vendor/symfony/http-foundation/Tests/Session/Storage/Handler/Fixtures/with_samesite.php @@ -0,0 +1,13 @@ +<?php + +require __DIR__.'/common.inc'; + +use Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage; + +$storage = new NativeSessionStorage(['cookie_samesite' => 'lax']); +$storage->setSaveHandler(new TestSessionHandler()); +$storage->start(); + +$_SESSION = ['foo' => 'bar']; + +ob_start(function ($buffer) { return str_replace(session_id(), 'random_session_id', $buffer); }); diff --git a/vendor/symfony/http-foundation/Tests/Session/Storage/Handler/Fixtures/with_samesite_and_migration.expected b/vendor/symfony/http-foundation/Tests/Session/Storage/Handler/Fixtures/with_samesite_and_migration.expected new file mode 100644 index 0000000000000000000000000000000000000000..8b5fc08bd375b9764be6c51eb29413a6a9dc01b6 --- /dev/null +++ b/vendor/symfony/http-foundation/Tests/Session/Storage/Handler/Fixtures/with_samesite_and_migration.expected @@ -0,0 +1,23 @@ +open +validateId +read +doRead: +read +destroy +close +open +validateId +read +doRead: +read + +write +doWrite: foo|s:3:"bar"; +close +Array +( + [0] => Content-Type: text/plain; charset=utf-8 + [1] => Cache-Control: max-age=0, private, must-revalidate + [2] => Set-Cookie: sid=random_session_id; path=/; secure; HttpOnly; SameSite=lax +) +shutdown diff --git a/vendor/symfony/http-foundation/Tests/Session/Storage/Handler/Fixtures/with_samesite_and_migration.php b/vendor/symfony/http-foundation/Tests/Session/Storage/Handler/Fixtures/with_samesite_and_migration.php new file mode 100644 index 0000000000000000000000000000000000000000..a28b6fedfc375e0443f9ccce0aa4484d0e367521 --- /dev/null +++ b/vendor/symfony/http-foundation/Tests/Session/Storage/Handler/Fixtures/with_samesite_and_migration.php @@ -0,0 +1,15 @@ +<?php + +require __DIR__.'/common.inc'; + +use Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage; + +$storage = new NativeSessionStorage(['cookie_samesite' => 'lax']); +$storage->setSaveHandler(new TestSessionHandler()); +$storage->start(); + +$_SESSION = ['foo' => 'bar']; + +$storage->regenerate(true); + +ob_start(function ($buffer) { return preg_replace('~_sf2_meta.*$~m', '', str_replace(session_id(), 'random_session_id', $buffer)); }); diff --git a/vendor/symfony/http-foundation/Tests/Session/Storage/Handler/MemcacheSessionHandlerTest.php b/vendor/symfony/http-foundation/Tests/Session/Storage/Handler/MemcacheSessionHandlerTest.php deleted file mode 100644 index dda43c805ba7d1869f597568a79801d97d824b64..0000000000000000000000000000000000000000 --- a/vendor/symfony/http-foundation/Tests/Session/Storage/Handler/MemcacheSessionHandlerTest.php +++ /dev/null @@ -1,135 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Tests\Session\Storage\Handler; - -use PHPUnit\Framework\TestCase; -use Symfony\Component\HttpFoundation\Session\Storage\Handler\MemcacheSessionHandler; - -/** - * @requires extension memcache - * @group time-sensitive - * @group legacy - */ -class MemcacheSessionHandlerTest extends TestCase -{ - const PREFIX = 'prefix_'; - const TTL = 1000; - - /** - * @var MemcacheSessionHandler - */ - protected $storage; - - protected $memcache; - - protected function setUp() - { - if (defined('HHVM_VERSION')) { - $this->markTestSkipped('PHPUnit_MockObject cannot mock the Memcache class on HHVM. See https://github.com/sebastianbergmann/phpunit-mock-objects/pull/289'); - } - - parent::setUp(); - $this->memcache = $this->getMockBuilder('Memcache')->getMock(); - $this->storage = new MemcacheSessionHandler( - $this->memcache, - array('prefix' => self::PREFIX, 'expiretime' => self::TTL) - ); - } - - protected function tearDown() - { - $this->memcache = null; - $this->storage = null; - parent::tearDown(); - } - - public function testOpenSession() - { - $this->assertTrue($this->storage->open('', '')); - } - - public function testCloseSession() - { - $this->assertTrue($this->storage->close()); - } - - public function testReadSession() - { - $this->memcache - ->expects($this->once()) - ->method('get') - ->with(self::PREFIX.'id') - ; - - $this->assertEquals('', $this->storage->read('id')); - } - - public function testWriteSession() - { - $this->memcache - ->expects($this->once()) - ->method('set') - ->with(self::PREFIX.'id', 'data', 0, $this->equalTo(time() + self::TTL, 2)) - ->will($this->returnValue(true)) - ; - - $this->assertTrue($this->storage->write('id', 'data')); - } - - public function testDestroySession() - { - $this->memcache - ->expects($this->once()) - ->method('delete') - ->with(self::PREFIX.'id') - ->will($this->returnValue(true)) - ; - - $this->assertTrue($this->storage->destroy('id')); - } - - public function testGcSession() - { - $this->assertTrue($this->storage->gc(123)); - } - - /** - * @dataProvider getOptionFixtures - */ - public function testSupportedOptions($options, $supported) - { - try { - new MemcacheSessionHandler($this->memcache, $options); - $this->assertTrue($supported); - } catch (\InvalidArgumentException $e) { - $this->assertFalse($supported); - } - } - - public function getOptionFixtures() - { - return array( - array(array('prefix' => 'session'), true), - array(array('expiretime' => 100), true), - array(array('prefix' => 'session', 'expiretime' => 200), true), - array(array('expiretime' => 100, 'foo' => 'bar'), false), - ); - } - - public function testGetConnection() - { - $method = new \ReflectionMethod($this->storage, 'getMemcache'); - $method->setAccessible(true); - - $this->assertInstanceOf('\Memcache', $method->invoke($this->storage)); - } -} diff --git a/vendor/symfony/http-foundation/Tests/Session/Storage/Handler/MemcachedSessionHandlerTest.php b/vendor/symfony/http-foundation/Tests/Session/Storage/Handler/MemcachedSessionHandlerTest.php index 2e7be359efcfff04427367f21d8d216a660b7882..e9c17703a7173a915e89d4dbc6040673e6be613a 100644 --- a/vendor/symfony/http-foundation/Tests/Session/Storage/Handler/MemcachedSessionHandlerTest.php +++ b/vendor/symfony/http-foundation/Tests/Session/Storage/Handler/MemcachedSessionHandlerTest.php @@ -30,12 +30,8 @@ class MemcachedSessionHandlerTest extends TestCase protected $memcached; - protected function setUp() + protected function setUp(): void { - if (defined('HHVM_VERSION')) { - $this->markTestSkipped('PHPUnit_MockObject cannot mock the Memcached class on HHVM. See https://github.com/sebastianbergmann/phpunit-mock-objects/pull/289'); - } - parent::setUp(); if (version_compare(phpversion('memcached'), '2.2.0', '>=') && version_compare(phpversion('memcached'), '3.0.0b1', '<')) { @@ -45,11 +41,11 @@ class MemcachedSessionHandlerTest extends TestCase $this->memcached = $this->getMockBuilder('Memcached')->getMock(); $this->storage = new MemcachedSessionHandler( $this->memcached, - array('prefix' => self::PREFIX, 'expiretime' => self::TTL) + ['prefix' => self::PREFIX, 'expiretime' => self::TTL] ); } - protected function tearDown() + protected function tearDown(): void { $this->memcached = null; $this->storage = null; @@ -63,6 +59,12 @@ class MemcachedSessionHandlerTest extends TestCase public function testCloseSession() { + $this->memcached + ->expects($this->once()) + ->method('quit') + ->willReturn(true) + ; + $this->assertTrue($this->storage->close()); } @@ -83,7 +85,7 @@ class MemcachedSessionHandlerTest extends TestCase ->expects($this->once()) ->method('set') ->with(self::PREFIX.'id', 'data', $this->equalTo(time() + self::TTL, 2)) - ->will($this->returnValue(true)) + ->willReturn(true) ; $this->assertTrue($this->storage->write('id', 'data')); @@ -95,7 +97,7 @@ class MemcachedSessionHandlerTest extends TestCase ->expects($this->once()) ->method('delete') ->with(self::PREFIX.'id') - ->will($this->returnValue(true)) + ->willReturn(true) ; $this->assertTrue($this->storage->destroy('id')); @@ -121,12 +123,12 @@ class MemcachedSessionHandlerTest extends TestCase public function getOptionFixtures() { - return array( - array(array('prefix' => 'session'), true), - array(array('expiretime' => 100), true), - array(array('prefix' => 'session', 'expiretime' => 200), true), - array(array('expiretime' => 100, 'foo' => 'bar'), false), - ); + return [ + [['prefix' => 'session'], true], + [['expiretime' => 100], true], + [['prefix' => 'session', 'expiretime' => 200], true], + [['expiretime' => 100, 'foo' => 'bar'], false], + ]; } public function testGetConnection() diff --git a/vendor/symfony/http-foundation/Tests/Session/Storage/Handler/MigratingSessionHandlerTest.php b/vendor/symfony/http-foundation/Tests/Session/Storage/Handler/MigratingSessionHandlerTest.php new file mode 100644 index 0000000000000000000000000000000000000000..01615e6b1f2eb718895c4dd5eb99ab1049712ade --- /dev/null +++ b/vendor/symfony/http-foundation/Tests/Session/Storage/Handler/MigratingSessionHandlerTest.php @@ -0,0 +1,186 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\Tests\Session\Storage\Handler; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\HttpFoundation\Session\Storage\Handler\MigratingSessionHandler; + +class MigratingSessionHandlerTest extends TestCase +{ + private $dualHandler; + private $currentHandler; + private $writeOnlyHandler; + + protected function setUp(): void + { + $this->currentHandler = $this->createMock(\SessionHandlerInterface::class); + $this->writeOnlyHandler = $this->createMock(\SessionHandlerInterface::class); + + $this->dualHandler = new MigratingSessionHandler($this->currentHandler, $this->writeOnlyHandler); + } + + public function testInstanceOf() + { + $this->assertInstanceOf(\SessionHandlerInterface::class, $this->dualHandler); + $this->assertInstanceOf(\SessionUpdateTimestampHandlerInterface::class, $this->dualHandler); + } + + public function testClose() + { + $this->currentHandler->expects($this->once()) + ->method('close') + ->willReturn(true); + + $this->writeOnlyHandler->expects($this->once()) + ->method('close') + ->willReturn(false); + + $result = $this->dualHandler->close(); + + $this->assertTrue($result); + } + + public function testDestroy() + { + $sessionId = 'xyz'; + + $this->currentHandler->expects($this->once()) + ->method('destroy') + ->with($sessionId) + ->willReturn(true); + + $this->writeOnlyHandler->expects($this->once()) + ->method('destroy') + ->with($sessionId) + ->willReturn(false); + + $result = $this->dualHandler->destroy($sessionId); + + $this->assertTrue($result); + } + + public function testGc() + { + $maxlifetime = 357; + + $this->currentHandler->expects($this->once()) + ->method('gc') + ->with($maxlifetime) + ->willReturn(true); + + $this->writeOnlyHandler->expects($this->once()) + ->method('gc') + ->with($maxlifetime) + ->willReturn(false); + + $result = $this->dualHandler->gc($maxlifetime); + $this->assertTrue($result); + } + + public function testOpen() + { + $savePath = '/path/to/save/location'; + $sessionName = 'xyz'; + + $this->currentHandler->expects($this->once()) + ->method('open') + ->with($savePath, $sessionName) + ->willReturn(true); + + $this->writeOnlyHandler->expects($this->once()) + ->method('open') + ->with($savePath, $sessionName) + ->willReturn(false); + + $result = $this->dualHandler->open($savePath, $sessionName); + + $this->assertTrue($result); + } + + public function testRead() + { + $sessionId = 'xyz'; + $readValue = 'something'; + + $this->currentHandler->expects($this->once()) + ->method('read') + ->with($sessionId) + ->willReturn($readValue); + + $this->writeOnlyHandler->expects($this->never()) + ->method('read') + ->with($this->any()); + + $result = $this->dualHandler->read($sessionId); + + $this->assertSame($readValue, $result); + } + + public function testWrite() + { + $sessionId = 'xyz'; + $data = 'my-serialized-data'; + + $this->currentHandler->expects($this->once()) + ->method('write') + ->with($sessionId, $data) + ->willReturn(true); + + $this->writeOnlyHandler->expects($this->once()) + ->method('write') + ->with($sessionId, $data) + ->willReturn(false); + + $result = $this->dualHandler->write($sessionId, $data); + + $this->assertTrue($result); + } + + public function testValidateId() + { + $sessionId = 'xyz'; + $readValue = 'something'; + + $this->currentHandler->expects($this->once()) + ->method('read') + ->with($sessionId) + ->willReturn($readValue); + + $this->writeOnlyHandler->expects($this->never()) + ->method('read') + ->with($this->any()); + + $result = $this->dualHandler->validateId($sessionId); + + $this->assertTrue($result); + } + + public function testUpdateTimestamp() + { + $sessionId = 'xyz'; + $data = 'my-serialized-data'; + + $this->currentHandler->expects($this->once()) + ->method('write') + ->with($sessionId, $data) + ->willReturn(true); + + $this->writeOnlyHandler->expects($this->once()) + ->method('write') + ->with($sessionId, $data) + ->willReturn(false); + + $result = $this->dualHandler->updateTimestamp($sessionId, $data); + + $this->assertTrue($result); + } +} diff --git a/vendor/symfony/http-foundation/Tests/Session/Storage/Handler/MongoDbSessionHandlerTest.php b/vendor/symfony/http-foundation/Tests/Session/Storage/Handler/MongoDbSessionHandlerTest.php index da051096c8730c1866b1dd198f251bcd39530de4..f956fa2760f77f036cb788fe239ae29c599692de 100644 --- a/vendor/symfony/http-foundation/Tests/Session/Storage/Handler/MongoDbSessionHandlerTest.php +++ b/vendor/symfony/http-foundation/Tests/Session/Storage/Handler/MongoDbSessionHandlerTest.php @@ -11,71 +11,52 @@ namespace Symfony\Component\HttpFoundation\Tests\Session\Storage\Handler; +use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; use Symfony\Component\HttpFoundation\Session\Storage\Handler\MongoDbSessionHandler; /** * @author Markus Bachmann <markus.bachmann@bachi.biz> * @group time-sensitive - * @group legacy + * @requires extension mongodb */ class MongoDbSessionHandlerTest extends TestCase { /** - * @var \PHPUnit_Framework_MockObject_MockObject + * @var MockObject */ private $mongo; private $storage; public $options; - protected function setUp() + protected function setUp(): void { parent::setUp(); - if (extension_loaded('mongodb')) { - if (!class_exists('MongoDB\Client')) { - $this->markTestSkipped('The mongodb/mongodb package is required.'); - } - } elseif (!extension_loaded('mongo')) { - $this->markTestSkipped('The Mongo or MongoDB extension is required.'); + if (!class_exists(\MongoDB\Client::class)) { + $this->markTestSkipped('The mongodb/mongodb package is required.'); } - if (phpversion('mongodb')) { - $mongoClass = 'MongoDB\Client'; - } else { - $mongoClass = version_compare(phpversion('mongo'), '1.3.0', '<') ? 'Mongo' : 'MongoClient'; - } - - $this->mongo = $this->getMockBuilder($mongoClass) + $this->mongo = $this->getMockBuilder(\MongoDB\Client::class) ->disableOriginalConstructor() ->getMock(); - $this->options = array( + $this->options = [ 'id_field' => '_id', 'data_field' => 'data', 'time_field' => 'time', 'expiry_field' => 'expires_at', - 'database' => 'sf2-test', + 'database' => 'sf-test', 'collection' => 'session-test', - ); + ]; $this->storage = new MongoDbSessionHandler($this->mongo, $this->options); } - /** - * @expectedException \InvalidArgumentException - */ - public function testConstructorShouldThrowExceptionForInvalidMongo() - { - new MongoDbSessionHandler(new \stdClass(), $this->options); - } - - /** - * @expectedException \InvalidArgumentException - */ public function testConstructorShouldThrowExceptionForMissingOptions() { - new MongoDbSessionHandler($this->mongo, array()); + $this->expectException('InvalidArgumentException'); + new MongoDbSessionHandler($this->mongo, []); } public function testOpenMethodAlwaysReturnTrue() @@ -95,7 +76,7 @@ class MongoDbSessionHandlerTest extends TestCase $this->mongo->expects($this->once()) ->method('selectCollection') ->with($this->options['database'], $this->options['collection']) - ->will($this->returnValue($collection)); + ->willReturn($collection); // defining the timeout before the actual method call // allows to test for "greater than" values in the $criteria @@ -103,35 +84,22 @@ class MongoDbSessionHandlerTest extends TestCase $collection->expects($this->once()) ->method('findOne') - ->will($this->returnCallback(function ($criteria) use ($testTimeout) { + ->willReturnCallback(function ($criteria) use ($testTimeout) { $this->assertArrayHasKey($this->options['id_field'], $criteria); $this->assertEquals($criteria[$this->options['id_field']], 'foo'); $this->assertArrayHasKey($this->options['expiry_field'], $criteria); $this->assertArrayHasKey('$gte', $criteria[$this->options['expiry_field']]); - if (phpversion('mongodb')) { - $this->assertInstanceOf('MongoDB\BSON\UTCDateTime', $criteria[$this->options['expiry_field']]['$gte']); - $this->assertGreaterThanOrEqual(round((string) $criteria[$this->options['expiry_field']]['$gte'] / 1000), $testTimeout); - } else { - $this->assertInstanceOf('MongoDate', $criteria[$this->options['expiry_field']]['$gte']); - $this->assertGreaterThanOrEqual($criteria[$this->options['expiry_field']]['$gte']->sec, $testTimeout); - } + $this->assertInstanceOf(\MongoDB\BSON\UTCDateTime::class, $criteria[$this->options['expiry_field']]['$gte']); + $this->assertGreaterThanOrEqual(round((string) $criteria[$this->options['expiry_field']]['$gte'] / 1000), $testTimeout); - $fields = array( + return [ $this->options['id_field'] => 'foo', - ); - - if (phpversion('mongodb')) { - $fields[$this->options['data_field']] = new \MongoDB\BSON\Binary('bar', \MongoDB\BSON\Binary::TYPE_OLD_BINARY); - $fields[$this->options['id_field']] = new \MongoDB\BSON\UTCDateTime(time() * 1000); - } else { - $fields[$this->options['data_field']] = new \MongoBinData('bar', \MongoBinData::BYTE_ARRAY); - $fields[$this->options['id_field']] = new \MongoDate(); - } - - return $fields; - })); + $this->options['expiry_field'] => new \MongoDB\BSON\UTCDateTime(), + $this->options['data_field'] => new \MongoDB\BSON\Binary('bar', \MongoDB\BSON\Binary::TYPE_OLD_BINARY), + ]; + }); $this->assertEquals('bar', $this->storage->read('foo')); } @@ -143,91 +111,24 @@ class MongoDbSessionHandlerTest extends TestCase $this->mongo->expects($this->once()) ->method('selectCollection') ->with($this->options['database'], $this->options['collection']) - ->will($this->returnValue($collection)); - - $data = array(); - - $methodName = phpversion('mongodb') ? 'updateOne' : 'update'; - - $collection->expects($this->once()) - ->method($methodName) - ->will($this->returnCallback(function ($criteria, $updateData, $options) use (&$data) { - $this->assertEquals(array($this->options['id_field'] => 'foo'), $criteria); - - if (phpversion('mongodb')) { - $this->assertEquals(array('upsert' => true), $options); - } else { - $this->assertEquals(array('upsert' => true, 'multiple' => false), $options); - } - - $data = $updateData['$set']; - })); - - $expectedExpiry = time() + (int) ini_get('session.gc_maxlifetime'); - $this->assertTrue($this->storage->write('foo', 'bar')); - - if (phpversion('mongodb')) { - $this->assertEquals('bar', $data[$this->options['data_field']]->getData()); - $this->assertInstanceOf('MongoDB\BSON\UTCDateTime', $data[$this->options['time_field']]); - $this->assertInstanceOf('MongoDB\BSON\UTCDateTime', $data[$this->options['expiry_field']]); - $this->assertGreaterThanOrEqual($expectedExpiry, round((string) $data[$this->options['expiry_field']] / 1000)); - } else { - $this->assertEquals('bar', $data[$this->options['data_field']]->bin); - $this->assertInstanceOf('MongoDate', $data[$this->options['time_field']]); - $this->assertInstanceOf('MongoDate', $data[$this->options['expiry_field']]); - $this->assertGreaterThanOrEqual($expectedExpiry, $data[$this->options['expiry_field']]->sec); - } - } - - public function testWriteWhenUsingExpiresField() - { - $this->options = array( - 'id_field' => '_id', - 'data_field' => 'data', - 'time_field' => 'time', - 'database' => 'sf2-test', - 'collection' => 'session-test', - 'expiry_field' => 'expiresAt', - ); - - $this->storage = new MongoDbSessionHandler($this->mongo, $this->options); - - $collection = $this->createMongoCollectionMock(); - - $this->mongo->expects($this->once()) - ->method('selectCollection') - ->with($this->options['database'], $this->options['collection']) - ->will($this->returnValue($collection)); - - $data = array(); - - $methodName = phpversion('mongodb') ? 'updateOne' : 'update'; + ->willReturn($collection); $collection->expects($this->once()) - ->method($methodName) - ->will($this->returnCallback(function ($criteria, $updateData, $options) use (&$data) { - $this->assertEquals(array($this->options['id_field'] => 'foo'), $criteria); - - if (phpversion('mongodb')) { - $this->assertEquals(array('upsert' => true), $options); - } else { - $this->assertEquals(array('upsert' => true, 'multiple' => false), $options); - } + ->method('updateOne') + ->willReturnCallback(function ($criteria, $updateData, $options) { + $this->assertEquals([$this->options['id_field'] => 'foo'], $criteria); + $this->assertEquals(['upsert' => true], $options); $data = $updateData['$set']; - })); + $expectedExpiry = time() + (int) ini_get('session.gc_maxlifetime'); + $this->assertInstanceOf(\MongoDB\BSON\Binary::class, $data[$this->options['data_field']]); + $this->assertEquals('bar', $data[$this->options['data_field']]->getData()); + $this->assertInstanceOf(\MongoDB\BSON\UTCDateTime::class, $data[$this->options['time_field']]); + $this->assertInstanceOf(\MongoDB\BSON\UTCDateTime::class, $data[$this->options['expiry_field']]); + $this->assertGreaterThanOrEqual($expectedExpiry, round((string) $data[$this->options['expiry_field']] / 1000)); + }); $this->assertTrue($this->storage->write('foo', 'bar')); - - if (phpversion('mongodb')) { - $this->assertEquals('bar', $data[$this->options['data_field']]->getData()); - $this->assertInstanceOf('MongoDB\BSON\UTCDateTime', $data[$this->options['time_field']]); - $this->assertInstanceOf('MongoDB\BSON\UTCDateTime', $data[$this->options['expiry_field']]); - } else { - $this->assertEquals('bar', $data[$this->options['data_field']]->bin); - $this->assertInstanceOf('MongoDate', $data[$this->options['time_field']]); - $this->assertInstanceOf('MongoDate', $data[$this->options['expiry_field']]); - } } public function testReplaceSessionData() @@ -237,26 +138,20 @@ class MongoDbSessionHandlerTest extends TestCase $this->mongo->expects($this->once()) ->method('selectCollection') ->with($this->options['database'], $this->options['collection']) - ->will($this->returnValue($collection)); - - $data = array(); + ->willReturn($collection); - $methodName = phpversion('mongodb') ? 'updateOne' : 'update'; + $data = []; $collection->expects($this->exactly(2)) - ->method($methodName) - ->will($this->returnCallback(function ($criteria, $updateData, $options) use (&$data) { + ->method('updateOne') + ->willReturnCallback(function ($criteria, $updateData, $options) use (&$data) { $data = $updateData; - })); + }); $this->storage->write('foo', 'bar'); $this->storage->write('foo', 'foobar'); - if (phpversion('mongodb')) { - $this->assertEquals('foobar', $data['$set'][$this->options['data_field']]->getData()); - } else { - $this->assertEquals('foobar', $data['$set'][$this->options['data_field']]->bin); - } + $this->assertEquals('foobar', $data['$set'][$this->options['data_field']]->getData()); } public function testDestroy() @@ -266,13 +161,11 @@ class MongoDbSessionHandlerTest extends TestCase $this->mongo->expects($this->once()) ->method('selectCollection') ->with($this->options['database'], $this->options['collection']) - ->will($this->returnValue($collection)); - - $methodName = phpversion('mongodb') ? 'deleteOne' : 'remove'; + ->willReturn($collection); $collection->expects($this->once()) - ->method($methodName) - ->with(array($this->options['id_field'] => 'foo')); + ->method('deleteOne') + ->with([$this->options['id_field'] => 'foo']); $this->assertTrue($this->storage->destroy('foo')); } @@ -284,21 +177,14 @@ class MongoDbSessionHandlerTest extends TestCase $this->mongo->expects($this->once()) ->method('selectCollection') ->with($this->options['database'], $this->options['collection']) - ->will($this->returnValue($collection)); - - $methodName = phpversion('mongodb') ? 'deleteMany' : 'remove'; + ->willReturn($collection); $collection->expects($this->once()) - ->method($methodName) - ->will($this->returnCallback(function ($criteria) { - if (phpversion('mongodb')) { - $this->assertInstanceOf('MongoDB\BSON\UTCDateTime', $criteria[$this->options['expiry_field']]['$lt']); - $this->assertGreaterThanOrEqual(time() - 1, round((string) $criteria[$this->options['expiry_field']]['$lt'] / 1000)); - } else { - $this->assertInstanceOf('MongoDate', $criteria[$this->options['expiry_field']]['$lt']); - $this->assertGreaterThanOrEqual(time() - 1, $criteria[$this->options['expiry_field']]['$lt']->sec); - } - })); + ->method('deleteMany') + ->willReturnCallback(function ($criteria) { + $this->assertInstanceOf(\MongoDB\BSON\UTCDateTime::class, $criteria[$this->options['expiry_field']]['$lt']); + $this->assertGreaterThanOrEqual(time() - 1, round((string) $criteria[$this->options['expiry_field']]['$lt'] / 1000)); + }); $this->assertTrue($this->storage->gc(1)); } @@ -308,23 +194,12 @@ class MongoDbSessionHandlerTest extends TestCase $method = new \ReflectionMethod($this->storage, 'getMongo'); $method->setAccessible(true); - if (phpversion('mongodb')) { - $mongoClass = 'MongoDB\Client'; - } else { - $mongoClass = version_compare(phpversion('mongo'), '1.3.0', '<') ? 'Mongo' : 'MongoClient'; - } - - $this->assertInstanceOf($mongoClass, $method->invoke($this->storage)); + $this->assertInstanceOf(\MongoDB\Client::class, $method->invoke($this->storage)); } private function createMongoCollectionMock() { - $collectionClass = 'MongoCollection'; - if (phpversion('mongodb')) { - $collectionClass = 'MongoDB\Collection'; - } - - $collection = $this->getMockBuilder($collectionClass) + $collection = $this->getMockBuilder(\MongoDB\Collection::class) ->disableOriginalConstructor() ->getMock(); diff --git a/vendor/symfony/http-foundation/Tests/Session/Storage/Handler/NativeFileSessionHandlerTest.php b/vendor/symfony/http-foundation/Tests/Session/Storage/Handler/NativeFileSessionHandlerTest.php index a6264e51d2a72df84268d2a63ac5485f8f5f2bdb..cd167fb13ab0db9d95c3702aa0f8887182016129 100644 --- a/vendor/symfony/http-foundation/Tests/Session/Storage/Handler/NativeFileSessionHandlerTest.php +++ b/vendor/symfony/http-foundation/Tests/Session/Storage/Handler/NativeFileSessionHandlerTest.php @@ -27,9 +27,8 @@ class NativeFileSessionHandlerTest extends TestCase { public function testConstruct() { - $storage = new NativeSessionStorage(array('name' => 'TESTING'), new NativeFileSessionHandler(sys_get_temp_dir())); + $storage = new NativeSessionStorage(['name' => 'TESTING'], new NativeFileSessionHandler(sys_get_temp_dir())); - $this->assertEquals('files', $storage->getSaveHandler()->getSaveHandlerName()); $this->assertEquals('user', ini_get('session.save_handler')); $this->assertEquals(sys_get_temp_dir(), ini_get('session.save_path')); @@ -43,7 +42,7 @@ class NativeFileSessionHandlerTest extends TestCase { $handler = new NativeFileSessionHandler($savePath); $this->assertEquals($expectedSavePath, ini_get('session.save_path')); - $this->assertTrue(is_dir(realpath($path))); + $this->assertDirectoryExists(realpath($path)); rmdir($path); } @@ -52,25 +51,23 @@ class NativeFileSessionHandlerTest extends TestCase { $base = sys_get_temp_dir(); - return array( - array("$base/foo", "$base/foo", "$base/foo"), - array("5;$base/foo", "5;$base/foo", "$base/foo"), - array("5;0600;$base/foo", "5;0600;$base/foo", "$base/foo"), - ); + return [ + ["$base/foo", "$base/foo", "$base/foo"], + ["5;$base/foo", "5;$base/foo", "$base/foo"], + ["5;0600;$base/foo", "5;0600;$base/foo", "$base/foo"], + ]; } - /** - * @expectedException \InvalidArgumentException - */ public function testConstructException() { + $this->expectException('InvalidArgumentException'); $handler = new NativeFileSessionHandler('something;invalid;with;too-many-args'); } public function testConstructDefault() { $path = ini_get('session.save_path'); - $storage = new NativeSessionStorage(array('name' => 'TESTING'), new NativeFileSessionHandler()); + $storage = new NativeSessionStorage(['name' => 'TESTING'], new NativeFileSessionHandler()); $this->assertEquals($path, ini_get('session.save_path')); } diff --git a/vendor/symfony/http-foundation/Tests/Session/Storage/Handler/NativeSessionHandlerTest.php b/vendor/symfony/http-foundation/Tests/Session/Storage/Handler/NativeSessionHandlerTest.php deleted file mode 100644 index 1a68d575e2c59fc44f070bea2a20cd7c1f574793..0000000000000000000000000000000000000000 --- a/vendor/symfony/http-foundation/Tests/Session/Storage/Handler/NativeSessionHandlerTest.php +++ /dev/null @@ -1,38 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Tests\Session\Storage\Handler; - -use PHPUnit\Framework\TestCase; -use Symfony\Component\HttpFoundation\Session\Storage\Handler\NativeSessionHandler; - -/** - * Test class for NativeSessionHandler. - * - * @author Drak <drak@zikula.org> - * - * @runTestsInSeparateProcesses - * @preserveGlobalState disabled - * @group legacy - */ -class NativeSessionHandlerTest extends TestCase -{ - /** - * @expectedDeprecation The Symfony\Component\HttpFoundation\Session\Storage\Handler\NativeSessionHandler class is deprecated since Symfony 3.4 and will be removed in 4.0. Use the \SessionHandler class instead. - */ - public function testConstruct() - { - $handler = new NativeSessionHandler(); - - $this->assertTrue($handler instanceof \SessionHandler); - $this->assertTrue($handler instanceof NativeSessionHandler); - } -} diff --git a/vendor/symfony/http-foundation/Tests/Session/Storage/Handler/NullSessionHandlerTest.php b/vendor/symfony/http-foundation/Tests/Session/Storage/Handler/NullSessionHandlerTest.php index 718fd0f830e492d68e758acdf4d33b0b09a12df5..0d246e1aa560b8d32d7c44896bbae4fa56f1d8ad 100644 --- a/vendor/symfony/http-foundation/Tests/Session/Storage/Handler/NullSessionHandlerTest.php +++ b/vendor/symfony/http-foundation/Tests/Session/Storage/Handler/NullSessionHandlerTest.php @@ -12,9 +12,9 @@ namespace Symfony\Component\HttpFoundation\Tests\Session\Storage\Handler; use PHPUnit\Framework\TestCase; +use Symfony\Component\HttpFoundation\Session\Session; use Symfony\Component\HttpFoundation\Session\Storage\Handler\NullSessionHandler; use Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage; -use Symfony\Component\HttpFoundation\Session\Session; /** * Test class for NullSessionHandler. @@ -54,6 +54,6 @@ class NullSessionHandlerTest extends TestCase public function getStorage() { - return new NativeSessionStorage(array(), new NullSessionHandler()); + return new NativeSessionStorage([], new NullSessionHandler()); } } diff --git a/vendor/symfony/http-foundation/Tests/Session/Storage/Handler/PdoSessionHandlerTest.php b/vendor/symfony/http-foundation/Tests/Session/Storage/Handler/PdoSessionHandlerTest.php index a0d7529f06a8600c861041850b74caeff26c1e7d..d080ce3ca6e5cf13be1a39a90e820b0e6c9bada1 100644 --- a/vendor/symfony/http-foundation/Tests/Session/Storage/Handler/PdoSessionHandlerTest.php +++ b/vendor/symfony/http-foundation/Tests/Session/Storage/Handler/PdoSessionHandlerTest.php @@ -22,7 +22,7 @@ class PdoSessionHandlerTest extends TestCase { private $dbFile; - protected function tearDown() + protected function tearDown(): void { // make sure the temporary database file is deleted when it has been created (even when a test fails) if ($this->dbFile) { @@ -33,7 +33,7 @@ class PdoSessionHandlerTest extends TestCase protected function getPersistentSqliteDsn() { - $this->dbFile = tempnam(sys_get_temp_dir(), 'sf2_sqlite_sessions'); + $this->dbFile = tempnam(sys_get_temp_dir(), 'sf_sqlite_sessions'); return 'sqlite:'.$this->dbFile; } @@ -48,34 +48,28 @@ class PdoSessionHandlerTest extends TestCase return $pdo; } - /** - * @expectedException \InvalidArgumentException - */ public function testWrongPdoErrMode() { + $this->expectException('InvalidArgumentException'); $pdo = $this->getMemorySqlitePdo(); $pdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_SILENT); $storage = new PdoSessionHandler($pdo); } - /** - * @expectedException \RuntimeException - */ public function testInexistentTable() { - $storage = new PdoSessionHandler($this->getMemorySqlitePdo(), array('db_table' => 'inexistent_table')); + $this->expectException('RuntimeException'); + $storage = new PdoSessionHandler($this->getMemorySqlitePdo(), ['db_table' => 'inexistent_table']); $storage->open('', 'sid'); $storage->read('id'); $storage->write('id', 'data'); $storage->close(); } - /** - * @expectedException \RuntimeException - */ public function testCreateTableTwice() { + $this->expectException('RuntimeException'); $storage = new PdoSessionHandler($this->getMemorySqlitePdo()); $storage->createTable(); } @@ -136,10 +130,6 @@ class PdoSessionHandlerTest extends TestCase public function testReadConvertsStreamToString() { - if (defined('HHVM_VERSION')) { - $this->markTestSkipped('PHPUnit_MockObject cannot mock the PDOStatement class on HHVM. See https://github.com/sebastianbergmann/phpunit-mock-objects/pull/289'); - } - $pdo = new MockPdo('pgsql'); $pdo->prepareResult = $this->getMockBuilder('PDOStatement')->getMock(); @@ -147,7 +137,7 @@ class PdoSessionHandlerTest extends TestCase $stream = $this->createStream($content); $pdo->prepareResult->expects($this->once())->method('fetchAll') - ->will($this->returnValue(array(array($stream, 42, time())))); + ->willReturn([[$stream, 42, time()]]); $storage = new PdoSessionHandler($pdo); $result = $storage->read('foo'); @@ -157,10 +147,7 @@ class PdoSessionHandlerTest extends TestCase public function testReadLockedConvertsStreamToString() { - if (defined('HHVM_VERSION')) { - $this->markTestSkipped('PHPUnit_MockObject cannot mock the PDOStatement class on HHVM. See https://github.com/sebastianbergmann/phpunit-mock-objects/pull/289'); - } - if (ini_get('session.use_strict_mode')) { + if (filter_var(ini_get('session.use_strict_mode'), FILTER_VALIDATE_BOOLEAN)) { $this->markTestSkipped('Strict mode needs no locking for new sessions.'); } @@ -177,14 +164,14 @@ class PdoSessionHandlerTest extends TestCase $exception = null; $selectStmt->expects($this->atLeast(2))->method('fetchAll') - ->will($this->returnCallback(function () use (&$exception, $stream) { - return $exception ? array(array($stream, 42, time())) : array(); - })); + ->willReturnCallback(function () use (&$exception, $stream) { + return $exception ? [[$stream, 42, time()]] : []; + }); $insertStmt->expects($this->once())->method('execute') - ->will($this->returnCallback(function () use (&$exception) { + ->willReturnCallback(function () use (&$exception) { throw $exception = new \PDOException('', '23'); - })); + }); $storage = new PdoSessionHandler($pdo); $result = $storage->read('foo'); @@ -324,6 +311,41 @@ class PdoSessionHandlerTest extends TestCase $this->assertInstanceOf('\PDO', $method->invoke($storage)); } + /** + * @dataProvider provideUrlDsnPairs + */ + public function testUrlDsn($url, $expectedDsn, $expectedUser = null, $expectedPassword = null) + { + $storage = new PdoSessionHandler($url); + $reflection = new \ReflectionClass(PdoSessionHandler::class); + + foreach (['dsn' => $expectedDsn, 'username' => $expectedUser, 'password' => $expectedPassword] as $property => $expectedValue) { + if (!isset($expectedValue)) { + continue; + } + $property = $reflection->getProperty($property); + $property->setAccessible(true); + $this->assertSame($expectedValue, $property->getValue($storage)); + } + } + + public function provideUrlDsnPairs() + { + yield ['mysql://localhost/test', 'mysql:host=localhost;dbname=test;']; + yield ['mysql://localhost:56/test', 'mysql:host=localhost;port=56;dbname=test;']; + yield ['mysql2://root:pwd@localhost/test', 'mysql:host=localhost;dbname=test;', 'root', 'pwd']; + yield ['postgres://localhost/test', 'pgsql:host=localhost;dbname=test;']; + yield ['postgresql://localhost:5634/test', 'pgsql:host=localhost;port=5634;dbname=test;']; + yield ['postgres://root:pwd@localhost/test', 'pgsql:host=localhost;dbname=test;', 'root', 'pwd']; + yield 'sqlite relative path' => ['sqlite://localhost/tmp/test', 'sqlite:tmp/test']; + yield 'sqlite absolute path' => ['sqlite://localhost//tmp/test', 'sqlite:/tmp/test']; + yield 'sqlite relative path without host' => ['sqlite:///tmp/test', 'sqlite:tmp/test']; + yield 'sqlite absolute path without host' => ['sqlite3:////tmp/test', 'sqlite:/tmp/test']; + yield ['sqlite://localhost/:memory:', 'sqlite::memory:']; + yield ['mssql://localhost/test', 'sqlsrv:server=localhost;Database=test']; + yield ['mssql://localhost:56/test', 'sqlsrv:server=localhost,56;Database=test']; + } + private function createStream($content) { $stream = tmpfile(); @@ -359,10 +381,10 @@ class MockPdo extends \PDO return parent::getAttribute($attribute); } - public function prepare($statement, $driverOptions = array()) + public function prepare($statement, $driverOptions = []) { - return is_callable($this->prepareResult) - ? call_user_func($this->prepareResult, $statement, $driverOptions) + return \is_callable($this->prepareResult) + ? ($this->prepareResult)($statement, $driverOptions) : $this->prepareResult; } diff --git a/vendor/symfony/http-foundation/Tests/Session/Storage/Handler/PredisClusterSessionHandlerTest.php b/vendor/symfony/http-foundation/Tests/Session/Storage/Handler/PredisClusterSessionHandlerTest.php new file mode 100644 index 0000000000000000000000000000000000000000..622b42da1a28e9cdf304adfd667d5b1d4f112066 --- /dev/null +++ b/vendor/symfony/http-foundation/Tests/Session/Storage/Handler/PredisClusterSessionHandlerTest.php @@ -0,0 +1,22 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\Tests\Session\Storage\Handler; + +use Predis\Client; + +class PredisClusterSessionHandlerTest extends AbstractRedisSessionHandlerTestCase +{ + protected function createRedisClient(string $host): Client + { + return new Client([['host' => $host]]); + } +} diff --git a/vendor/symfony/http-foundation/Tests/Session/Storage/Handler/PredisSessionHandlerTest.php b/vendor/symfony/http-foundation/Tests/Session/Storage/Handler/PredisSessionHandlerTest.php new file mode 100644 index 0000000000000000000000000000000000000000..5ecab116f731cbbb1e6b8435492e5b2810c5a8fc --- /dev/null +++ b/vendor/symfony/http-foundation/Tests/Session/Storage/Handler/PredisSessionHandlerTest.php @@ -0,0 +1,22 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\Tests\Session\Storage\Handler; + +use Predis\Client; + +class PredisSessionHandlerTest extends AbstractRedisSessionHandlerTestCase +{ + protected function createRedisClient(string $host): Client + { + return new Client(['host' => $host]); + } +} diff --git a/vendor/symfony/http-foundation/Tests/Session/Storage/Handler/RedisArraySessionHandlerTest.php b/vendor/symfony/http-foundation/Tests/Session/Storage/Handler/RedisArraySessionHandlerTest.php new file mode 100644 index 0000000000000000000000000000000000000000..b03a37236f57521ccc01c76b3d88e9154b5496d5 --- /dev/null +++ b/vendor/symfony/http-foundation/Tests/Session/Storage/Handler/RedisArraySessionHandlerTest.php @@ -0,0 +1,20 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\Tests\Session\Storage\Handler; + +class RedisArraySessionHandlerTest extends AbstractRedisSessionHandlerTestCase +{ + protected function createRedisClient(string $host): \RedisArray + { + return new \RedisArray([$host]); + } +} diff --git a/vendor/symfony/http-foundation/Tests/Session/Storage/Handler/RedisClusterSessionHandlerTest.php b/vendor/symfony/http-foundation/Tests/Session/Storage/Handler/RedisClusterSessionHandlerTest.php new file mode 100644 index 0000000000000000000000000000000000000000..c1ba70dcb08c21067d2ad2c25ceae0e9fbe07d2e --- /dev/null +++ b/vendor/symfony/http-foundation/Tests/Session/Storage/Handler/RedisClusterSessionHandlerTest.php @@ -0,0 +1,31 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\Tests\Session\Storage\Handler; + +class RedisClusterSessionHandlerTest extends AbstractRedisSessionHandlerTestCase +{ + public static function setUpBeforeClass(): void + { + if (!class_exists('RedisCluster')) { + self::markTestSkipped('The RedisCluster class is required.'); + } + + if (!$hosts = getenv('REDIS_CLUSTER_HOSTS')) { + self::markTestSkipped('REDIS_CLUSTER_HOSTS env var is not defined.'); + } + } + + protected function createRedisClient(string $host): \RedisCluster + { + return new \RedisCluster(null, explode(' ', getenv('REDIS_CLUSTER_HOSTS'))); + } +} diff --git a/vendor/symfony/http-foundation/Tests/Session/Storage/Handler/RedisSessionHandlerTest.php b/vendor/symfony/http-foundation/Tests/Session/Storage/Handler/RedisSessionHandlerTest.php new file mode 100644 index 0000000000000000000000000000000000000000..afdb6c503b659c11d9cd7bd6901f2bcb21e5a551 --- /dev/null +++ b/vendor/symfony/http-foundation/Tests/Session/Storage/Handler/RedisSessionHandlerTest.php @@ -0,0 +1,23 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\Tests\Session\Storage\Handler; + +class RedisSessionHandlerTest extends AbstractRedisSessionHandlerTestCase +{ + protected function createRedisClient(string $host): \Redis + { + $client = new \Redis(); + $client->connect($host); + + return $client; + } +} diff --git a/vendor/symfony/http-foundation/Tests/Session/Storage/Handler/StrictSessionHandlerTest.php b/vendor/symfony/http-foundation/Tests/Session/Storage/Handler/StrictSessionHandlerTest.php index b02c41ae898663f721cc439e2c1bdb2f4989539a..6a0d16876e8e0f6ee9104dcefae111bdf0e0d21e 100644 --- a/vendor/symfony/http-foundation/Tests/Session/Storage/Handler/StrictSessionHandlerTest.php +++ b/vendor/symfony/http-foundation/Tests/Session/Storage/Handler/StrictSessionHandlerTest.php @@ -84,7 +84,7 @@ class StrictSessionHandlerTest extends TestCase { $handler = $this->getMockBuilder('SessionHandlerInterface')->getMock(); $handler->expects($this->exactly(2))->method('read') - ->withConsecutive(array('id1'), array('id2')) + ->withConsecutive(['id1'], ['id2']) ->will($this->onConsecutiveCalls('data1', 'data2')); $proxy = new StrictSessionHandler($handler); diff --git a/vendor/symfony/http-foundation/Tests/Session/Storage/Handler/WriteCheckSessionHandlerTest.php b/vendor/symfony/http-foundation/Tests/Session/Storage/Handler/WriteCheckSessionHandlerTest.php deleted file mode 100644 index 898a7d11a5ae266de7d114af5e49b2ce0b3b5f3f..0000000000000000000000000000000000000000 --- a/vendor/symfony/http-foundation/Tests/Session/Storage/Handler/WriteCheckSessionHandlerTest.php +++ /dev/null @@ -1,97 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Tests\Session\Storage\Handler; - -use PHPUnit\Framework\TestCase; -use Symfony\Component\HttpFoundation\Session\Storage\Handler\WriteCheckSessionHandler; - -/** - * @author Adrien Brault <adrien.brault@gmail.com> - * - * @group legacy - */ -class WriteCheckSessionHandlerTest extends TestCase -{ - public function test() - { - $wrappedSessionHandlerMock = $this->getMockBuilder('SessionHandlerInterface')->getMock(); - $writeCheckSessionHandler = new WriteCheckSessionHandler($wrappedSessionHandlerMock); - - $wrappedSessionHandlerMock - ->expects($this->once()) - ->method('close') - ->with() - ->will($this->returnValue(true)) - ; - - $this->assertTrue($writeCheckSessionHandler->close()); - } - - public function testWrite() - { - $wrappedSessionHandlerMock = $this->getMockBuilder('SessionHandlerInterface')->getMock(); - $writeCheckSessionHandler = new WriteCheckSessionHandler($wrappedSessionHandlerMock); - - $wrappedSessionHandlerMock - ->expects($this->once()) - ->method('write') - ->with('foo', 'bar') - ->will($this->returnValue(true)) - ; - - $this->assertTrue($writeCheckSessionHandler->write('foo', 'bar')); - } - - public function testSkippedWrite() - { - $wrappedSessionHandlerMock = $this->getMockBuilder('SessionHandlerInterface')->getMock(); - $writeCheckSessionHandler = new WriteCheckSessionHandler($wrappedSessionHandlerMock); - - $wrappedSessionHandlerMock - ->expects($this->once()) - ->method('read') - ->with('foo') - ->will($this->returnValue('bar')) - ; - - $wrappedSessionHandlerMock - ->expects($this->never()) - ->method('write') - ; - - $this->assertEquals('bar', $writeCheckSessionHandler->read('foo')); - $this->assertTrue($writeCheckSessionHandler->write('foo', 'bar')); - } - - public function testNonSkippedWrite() - { - $wrappedSessionHandlerMock = $this->getMockBuilder('SessionHandlerInterface')->getMock(); - $writeCheckSessionHandler = new WriteCheckSessionHandler($wrappedSessionHandlerMock); - - $wrappedSessionHandlerMock - ->expects($this->once()) - ->method('read') - ->with('foo') - ->will($this->returnValue('bar')) - ; - - $wrappedSessionHandlerMock - ->expects($this->once()) - ->method('write') - ->with('foo', 'baZZZ') - ->will($this->returnValue(true)) - ; - - $this->assertEquals('bar', $writeCheckSessionHandler->read('foo')); - $this->assertTrue($writeCheckSessionHandler->write('foo', 'baZZZ')); - } -} diff --git a/vendor/symfony/http-foundation/Tests/Session/Storage/MetadataBagTest.php b/vendor/symfony/http-foundation/Tests/Session/Storage/MetadataBagTest.php index 69cf6163c16f3030f8ea0f5d83745d6fa926c55d..e040f4862755b32898fa67586b63643a1abe628d 100644 --- a/vendor/symfony/http-foundation/Tests/Session/Storage/MetadataBagTest.php +++ b/vendor/symfony/http-foundation/Tests/Session/Storage/MetadataBagTest.php @@ -26,26 +26,26 @@ class MetadataBagTest extends TestCase */ protected $bag; - protected $array = array(); + protected $array = []; - protected function setUp() + protected function setUp(): void { parent::setUp(); $this->bag = new MetadataBag(); - $this->array = array(MetadataBag::CREATED => 1234567, MetadataBag::UPDATED => 12345678, MetadataBag::LIFETIME => 0); + $this->array = [MetadataBag::CREATED => 1234567, MetadataBag::UPDATED => 12345678, MetadataBag::LIFETIME => 0]; $this->bag->initialize($this->array); } - protected function tearDown() + protected function tearDown(): void { - $this->array = array(); + $this->array = []; $this->bag = null; parent::tearDown(); } public function testInitialize() { - $sessionMetadata = array(); + $sessionMetadata = []; $bag1 = new MetadataBag(); $bag1->initialize($sessionMetadata); @@ -82,7 +82,7 @@ class MetadataBagTest extends TestCase public function testGetLifetime() { $bag = new MetadataBag(); - $array = array(MetadataBag::CREATED => 1234567, MetadataBag::UPDATED => 12345678, MetadataBag::LIFETIME => 1000); + $array = [MetadataBag::CREATED => 1234567, MetadataBag::UPDATED => 12345678, MetadataBag::LIFETIME => 1000]; $bag->initialize($array); $this->assertEquals(1000, $bag->getLifetime()); } @@ -111,11 +111,11 @@ class MetadataBagTest extends TestCase $timeStamp = time(); $created = $timeStamp - 15; - $sessionMetadata = array( + $sessionMetadata = [ MetadataBag::CREATED => $created, MetadataBag::UPDATED => $created, MetadataBag::LIFETIME => 1000, - ); + ]; $bag->initialize($sessionMetadata); $this->assertEquals($created, $sessionMetadata[MetadataBag::UPDATED]); @@ -127,11 +127,11 @@ class MetadataBagTest extends TestCase $timeStamp = time(); $created = $timeStamp - 45; - $sessionMetadata = array( + $sessionMetadata = [ MetadataBag::CREATED => $created, MetadataBag::UPDATED => $created, MetadataBag::LIFETIME => 1000, - ); + ]; $bag->initialize($sessionMetadata); $this->assertEquals($timeStamp, $sessionMetadata[MetadataBag::UPDATED]); diff --git a/vendor/symfony/http-foundation/Tests/Session/Storage/MockArraySessionStorageTest.php b/vendor/symfony/http-foundation/Tests/Session/Storage/MockArraySessionStorageTest.php index 82df5543eb540265f7e1e6eba09de94d2155fba5..b99e71985bb88f34ea0c5b9dcf699f393ab5ba03 100644 --- a/vendor/symfony/http-foundation/Tests/Session/Storage/MockArraySessionStorageTest.php +++ b/vendor/symfony/http-foundation/Tests/Session/Storage/MockArraySessionStorageTest.php @@ -12,9 +12,9 @@ namespace Symfony\Component\HttpFoundation\Tests\Session\Storage; use PHPUnit\Framework\TestCase; -use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage; use Symfony\Component\HttpFoundation\Session\Attribute\AttributeBag; use Symfony\Component\HttpFoundation\Session\Flash\FlashBag; +use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage; /** * Test class for MockArraySessionStorage. @@ -40,15 +40,15 @@ class MockArraySessionStorageTest extends TestCase private $data; - protected function setUp() + protected function setUp(): void { $this->attributes = new AttributeBag(); $this->flashes = new FlashBag(); - $this->data = array( - $this->attributes->getStorageKey() => array('foo' => 'bar'), - $this->flashes->getStorageKey() => array('notice' => 'hello'), - ); + $this->data = [ + $this->attributes->getStorageKey() => ['foo' => 'bar'], + $this->flashes->getStorageKey() => ['notice' => 'hello'], + ]; $this->storage = new MockArraySessionStorage(); $this->storage->registerBag($this->flashes); @@ -56,7 +56,7 @@ class MockArraySessionStorageTest extends TestCase $this->storage->setSessionData($this->data); } - protected function tearDown() + protected function tearDown(): void { $this->data = null; $this->flashes = null; @@ -80,14 +80,14 @@ class MockArraySessionStorageTest extends TestCase $id = $this->storage->getId(); $this->storage->regenerate(); $this->assertNotEquals($id, $this->storage->getId()); - $this->assertEquals(array('foo' => 'bar'), $this->storage->getBag('attributes')->all()); - $this->assertEquals(array('notice' => 'hello'), $this->storage->getBag('flashes')->peekAll()); + $this->assertEquals(['foo' => 'bar'], $this->storage->getBag('attributes')->all()); + $this->assertEquals(['notice' => 'hello'], $this->storage->getBag('flashes')->peekAll()); $id = $this->storage->getId(); $this->storage->regenerate(true); $this->assertNotEquals($id, $this->storage->getId()); - $this->assertEquals(array('foo' => 'bar'), $this->storage->getBag('attributes')->all()); - $this->assertEquals(array('notice' => 'hello'), $this->storage->getBag('flashes')->peekAll()); + $this->assertEquals(['foo' => 'bar'], $this->storage->getBag('attributes')->all()); + $this->assertEquals(['notice' => 'hello'], $this->storage->getBag('flashes')->peekAll()); } public function testGetId() @@ -101,8 +101,8 @@ class MockArraySessionStorageTest extends TestCase { $this->storage->clear(); - $this->assertSame(array(), $this->storage->getBag('attributes')->all()); - $this->assertSame(array(), $this->storage->getBag('flashes')->peekAll()); + $this->assertSame([], $this->storage->getBag('attributes')->all()); + $this->assertSame([], $this->storage->getBag('flashes')->peekAll()); } public function testClearStartsSession() @@ -121,11 +121,9 @@ class MockArraySessionStorageTest extends TestCase $this->assertTrue($storage->isStarted()); } - /** - * @expectedException \RuntimeException - */ public function testUnstartedSave() { + $this->expectException('RuntimeException'); $this->storage->save(); } } diff --git a/vendor/symfony/http-foundation/Tests/Session/Storage/MockFileSessionStorageTest.php b/vendor/symfony/http-foundation/Tests/Session/Storage/MockFileSessionStorageTest.php index 53accd38447d3809286da95db538bf33e10cc499..d9314075af702b01b2f028745c8c1649123b0ae0 100644 --- a/vendor/symfony/http-foundation/Tests/Session/Storage/MockFileSessionStorageTest.php +++ b/vendor/symfony/http-foundation/Tests/Session/Storage/MockFileSessionStorageTest.php @@ -12,9 +12,9 @@ namespace Symfony\Component\HttpFoundation\Tests\Session\Storage; use PHPUnit\Framework\TestCase; -use Symfony\Component\HttpFoundation\Session\Storage\MockFileSessionStorage; -use Symfony\Component\HttpFoundation\Session\Flash\FlashBag; use Symfony\Component\HttpFoundation\Session\Attribute\AttributeBag; +use Symfony\Component\HttpFoundation\Session\Flash\FlashBag; +use Symfony\Component\HttpFoundation\Session\Storage\MockFileSessionStorage; /** * Test class for MockFileSessionStorage. @@ -33,13 +33,13 @@ class MockFileSessionStorageTest extends TestCase */ protected $storage; - protected function setUp() + protected function setUp(): void { - $this->sessionDir = sys_get_temp_dir().'/sf2test'; + $this->sessionDir = sys_get_temp_dir().'/sftest'; $this->storage = $this->getStorage(); } - protected function tearDown() + protected function tearDown(): void { $this->sessionDir = null; $this->storage = null; @@ -91,7 +91,7 @@ class MockFileSessionStorageTest extends TestCase $storage->start(); $this->assertEquals('108', $storage->getBag('attributes')->get('new')); $this->assertTrue($storage->getBag('flashes')->has('newkey')); - $this->assertEquals(array('test'), $storage->getBag('flashes')->peek('newkey')); + $this->assertEquals(['test'], $storage->getBag('flashes')->peek('newkey')); } public function testMultipleInstances() @@ -107,11 +107,9 @@ class MockFileSessionStorageTest extends TestCase $this->assertEquals('bar', $storage2->getBag('attributes')->get('foo'), 'values persist between instances'); } - /** - * @expectedException \RuntimeException - */ public function testSaveWithoutStart() { + $this->expectException('RuntimeException'); $storage1 = $this->getStorage(); $storage1->save(); } diff --git a/vendor/symfony/http-foundation/Tests/Session/Storage/NativeSessionStorageTest.php b/vendor/symfony/http-foundation/Tests/Session/Storage/NativeSessionStorageTest.php index 8fb8b4222835b1c67bb2bedfdd3871000a24e129..17f46bef5e1a198c0809c1f8e8d9df316c654ec6 100644 --- a/vendor/symfony/http-foundation/Tests/Session/Storage/NativeSessionStorageTest.php +++ b/vendor/symfony/http-foundation/Tests/Session/Storage/NativeSessionStorageTest.php @@ -33,16 +33,16 @@ class NativeSessionStorageTest extends TestCase { private $savePath; - protected function setUp() + protected function setUp(): void { $this->iniSet('session.save_handler', 'files'); - $this->iniSet('session.save_path', $this->savePath = sys_get_temp_dir().'/sf2test'); + $this->iniSet('session.save_path', $this->savePath = sys_get_temp_dir().'/sftest'); if (!is_dir($this->savePath)) { mkdir($this->savePath); } } - protected function tearDown() + protected function tearDown(): void { session_write_close(); array_map('unlink', glob($this->savePath.'/*')); @@ -56,7 +56,7 @@ class NativeSessionStorageTest extends TestCase /** * @return NativeSessionStorage */ - protected function getStorage(array $options = array()) + protected function getStorage(array $options = []) { $storage = new NativeSessionStorage($options); $storage->registerBag(new AttributeBag()); @@ -72,20 +72,16 @@ class NativeSessionStorageTest extends TestCase $this->assertSame($bag, $storage->getBag($bag->getName())); } - /** - * @expectedException \InvalidArgumentException - */ public function testRegisterBagException() { + $this->expectException('InvalidArgumentException'); $storage = $this->getStorage(); $storage->getBag('non_existing'); } - /** - * @expectedException \LogicException - */ public function testRegisterBagForAStartedSessionThrowsException() { + $this->expectException('LogicException'); $storage = $this->getStorage(); $storage->start(); $storage->registerBag(new AttributeBag()); @@ -98,7 +94,7 @@ class NativeSessionStorageTest extends TestCase $storage->start(); $id = $storage->getId(); - $this->assertInternalType('string', $id); + $this->assertIsString($id); $this->assertNotSame('', $id); $storage->save(); @@ -157,23 +153,27 @@ class NativeSessionStorageTest extends TestCase { $this->iniSet('session.cache_limiter', 'nocache'); - $storage = new NativeSessionStorage(array('cache_limiter' => 'public')); + $storage = new NativeSessionStorage(['cache_limiter' => 'public']); $this->assertEquals('public', ini_get('session.cache_limiter')); } public function testCookieOptions() { - $options = array( + $options = [ 'cookie_lifetime' => 123456, 'cookie_path' => '/my/cookie/path', 'cookie_domain' => 'symfony.example.com', 'cookie_secure' => true, 'cookie_httponly' => false, - ); + ]; + + if (\PHP_VERSION_ID >= 70300) { + $options['cookie_samesite'] = 'lax'; + } $this->getStorage($options); $temp = session_get_cookie_params(); - $gco = array(); + $gco = []; foreach ($temp as $key => $value) { $gco['cookie_'.$key] = $value; @@ -182,11 +182,26 @@ class NativeSessionStorageTest extends TestCase $this->assertEquals($options, $gco); } - /** - * @expectedException \InvalidArgumentException - */ + public function testSessionOptions() + { + if (\defined('HHVM_VERSION')) { + $this->markTestSkipped('HHVM is not handled in this test case.'); + } + + $options = [ + 'url_rewriter.tags' => 'a=href', + 'cache_expire' => '200', + ]; + + $this->getStorage($options); + + $this->assertSame('a=href', ini_get('url_rewriter.tags')); + $this->assertSame('200', ini_get('session.cache_expire')); + } + public function testSetSaveHandlerException() { + $this->expectException('InvalidArgumentException'); $storage = $this->getStorage(); $storage->setSaveHandler(new \stdClass()); } @@ -209,11 +224,9 @@ class NativeSessionStorageTest extends TestCase $this->assertInstanceOf('Symfony\Component\HttpFoundation\Session\Storage\Proxy\SessionHandlerProxy', $storage->getSaveHandler()); } - /** - * @expectedException \RuntimeException - */ public function testStarted() { + $this->expectException('RuntimeException'); $storage = $this->getStorage(); $this->assertFalse($storage->getSaveHandler()->isActive()); @@ -255,9 +268,9 @@ class NativeSessionStorageTest extends TestCase public function testSetSessionOptionsOnceSessionStartedIsIgnored() { session_start(); - $this->getStorage(array( + $this->getStorage([ 'name' => 'something-else', - )); + ]); // Assert no exception has been thrown by `getStorage()` $this->addToAssertionCount(1); diff --git a/vendor/symfony/http-foundation/Tests/Session/Storage/PhpBridgeSessionStorageTest.php b/vendor/symfony/http-foundation/Tests/Session/Storage/PhpBridgeSessionStorageTest.php index 958dc0bc089841cbb80dff16b0affcf6c8d79851..7d6827079893328d6b8599392162890a7af74f60 100644 --- a/vendor/symfony/http-foundation/Tests/Session/Storage/PhpBridgeSessionStorageTest.php +++ b/vendor/symfony/http-foundation/Tests/Session/Storage/PhpBridgeSessionStorageTest.php @@ -12,8 +12,8 @@ namespace Symfony\Component\HttpFoundation\Tests\Session\Storage; use PHPUnit\Framework\TestCase; -use Symfony\Component\HttpFoundation\Session\Storage\PhpBridgeSessionStorage; use Symfony\Component\HttpFoundation\Session\Attribute\AttributeBag; +use Symfony\Component\HttpFoundation\Session\Storage\PhpBridgeSessionStorage; /** * Test class for PhpSessionStorage. @@ -29,16 +29,16 @@ class PhpBridgeSessionStorageTest extends TestCase { private $savePath; - protected function setUp() + protected function setUp(): void { $this->iniSet('session.save_handler', 'files'); - $this->iniSet('session.save_path', $this->savePath = sys_get_temp_dir().'/sf2test'); + $this->iniSet('session.save_path', $this->savePath = sys_get_temp_dir().'/sftest'); if (!is_dir($this->savePath)) { mkdir($this->savePath); } } - protected function tearDown() + protected function tearDown(): void { session_write_close(); array_map('unlink', glob($this->savePath.'/*')); @@ -64,13 +64,12 @@ class PhpBridgeSessionStorageTest extends TestCase { $storage = $this->getStorage(); - $this->assertFalse($storage->getSaveHandler()->isActive()); + $this->assertNotSame(\PHP_SESSION_ACTIVE, session_status()); $this->assertFalse($storage->isStarted()); session_start(); $this->assertTrue(isset($_SESSION)); - // in PHP 5.4 we can reliably detect a session started - $this->assertTrue($storage->getSaveHandler()->isActive()); + $this->assertSame(\PHP_SESSION_ACTIVE, session_status()); // PHP session might have started, but the storage driver has not, so false is correct here $this->assertFalse($storage->isStarted()); @@ -87,10 +86,10 @@ class PhpBridgeSessionStorageTest extends TestCase $_SESSION['drak'] = 'loves symfony'; $storage->getBag('attributes')->set('symfony', 'greatness'); $key = $storage->getBag('attributes')->getStorageKey(); - $this->assertEquals($_SESSION[$key], array('symfony' => 'greatness')); + $this->assertEquals($_SESSION[$key], ['symfony' => 'greatness']); $this->assertEquals($_SESSION['drak'], 'loves symfony'); $storage->clear(); - $this->assertEquals($_SESSION[$key], array()); + $this->assertEquals($_SESSION[$key], []); $this->assertEquals($_SESSION['drak'], 'loves symfony'); } } diff --git a/vendor/symfony/http-foundation/Tests/Session/Storage/Proxy/AbstractProxyTest.php b/vendor/symfony/http-foundation/Tests/Session/Storage/Proxy/AbstractProxyTest.php index cbb291f19fc3f3c6daf9ddbadc46230c02cbc892..4820a6593b92c921c9de00433e684d67553e5e81 100644 --- a/vendor/symfony/http-foundation/Tests/Session/Storage/Proxy/AbstractProxyTest.php +++ b/vendor/symfony/http-foundation/Tests/Session/Storage/Proxy/AbstractProxyTest.php @@ -27,12 +27,12 @@ class AbstractProxyTest extends TestCase */ protected $proxy; - protected function setUp() + protected function setUp(): void { $this->proxy = $this->getMockForAbstractClass(AbstractProxy::class); } - protected function tearDown() + protected function tearDown(): void { $this->proxy = null; } @@ -80,10 +80,10 @@ class AbstractProxyTest extends TestCase /** * @runInSeparateProcess * @preserveGlobalState disabled - * @expectedException \LogicException */ public function testNameException() { + $this->expectException('LogicException'); session_start(); $this->proxy->setName('foo'); } @@ -103,10 +103,10 @@ class AbstractProxyTest extends TestCase /** * @runInSeparateProcess * @preserveGlobalState disabled - * @expectedException \LogicException */ public function testIdException() { + $this->expectException('LogicException'); session_start(); $this->proxy->setId('foo'); } diff --git a/vendor/symfony/http-foundation/Tests/Session/Storage/Proxy/NativeProxyTest.php b/vendor/symfony/http-foundation/Tests/Session/Storage/Proxy/NativeProxyTest.php deleted file mode 100644 index ed4fee6bfec0f0ddcbac07ade06d798c40ee22dc..0000000000000000000000000000000000000000 --- a/vendor/symfony/http-foundation/Tests/Session/Storage/Proxy/NativeProxyTest.php +++ /dev/null @@ -1,38 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpFoundation\Tests\Session\Storage\Proxy; - -use PHPUnit\Framework\TestCase; -use Symfony\Component\HttpFoundation\Session\Storage\Proxy\NativeProxy; - -/** - * Test class for NativeProxy. - * - * @group legacy - * - * @author Drak <drak@zikula.org> - */ -class NativeProxyTest extends TestCase -{ - public function testIsWrapper() - { - $proxy = new NativeProxy(); - $this->assertFalse($proxy->isWrapper()); - } - - public function testGetSaveHandlerName() - { - $name = ini_get('session.save_handler'); - $proxy = new NativeProxy(); - $this->assertEquals($name, $proxy->getSaveHandlerName()); - } -} diff --git a/vendor/symfony/http-foundation/Tests/Session/Storage/Proxy/SessionHandlerProxyTest.php b/vendor/symfony/http-foundation/Tests/Session/Storage/Proxy/SessionHandlerProxyTest.php index 682825356a7246a329f25fda230fa960f061d184..1cf4aed06a25d479242f0545aa99971ce16dee39 100644 --- a/vendor/symfony/http-foundation/Tests/Session/Storage/Proxy/SessionHandlerProxyTest.php +++ b/vendor/symfony/http-foundation/Tests/Session/Storage/Proxy/SessionHandlerProxyTest.php @@ -25,7 +25,7 @@ use Symfony\Component\HttpFoundation\Session\Storage\Proxy\SessionHandlerProxy; class SessionHandlerProxyTest extends TestCase { /** - * @var \PHPUnit_Framework_MockObject_Matcher + * @var \PHPUnit\Framework\MockObject\Matcher */ private $mock; @@ -34,13 +34,13 @@ class SessionHandlerProxyTest extends TestCase */ private $proxy; - protected function setUp() + protected function setUp(): void { $this->mock = $this->getMockBuilder('SessionHandlerInterface')->getMock(); $this->proxy = new SessionHandlerProxy($this->mock); } - protected function tearDown() + protected function tearDown(): void { $this->mock = null; $this->proxy = null; @@ -50,7 +50,7 @@ class SessionHandlerProxyTest extends TestCase { $this->mock->expects($this->once()) ->method('open') - ->will($this->returnValue(true)); + ->willReturn(true); $this->assertFalse($this->proxy->isActive()); $this->proxy->open('name', 'id'); @@ -61,7 +61,7 @@ class SessionHandlerProxyTest extends TestCase { $this->mock->expects($this->once()) ->method('open') - ->will($this->returnValue(false)); + ->willReturn(false); $this->assertFalse($this->proxy->isActive()); $this->proxy->open('name', 'id'); @@ -72,7 +72,7 @@ class SessionHandlerProxyTest extends TestCase { $this->mock->expects($this->once()) ->method('close') - ->will($this->returnValue(true)); + ->willReturn(true); $this->assertFalse($this->proxy->isActive()); $this->proxy->close(); @@ -83,7 +83,7 @@ class SessionHandlerProxyTest extends TestCase { $this->mock->expects($this->once()) ->method('close') - ->will($this->returnValue(false)); + ->willReturn(false); $this->assertFalse($this->proxy->isActive()); $this->proxy->close(); @@ -121,4 +121,38 @@ class SessionHandlerProxyTest extends TestCase $this->proxy->gc(86400); } + + /** + * @requires PHPUnit 5.1 + */ + public function testValidateId() + { + $mock = $this->getMockBuilder(['SessionHandlerInterface', 'SessionUpdateTimestampHandlerInterface'])->getMock(); + $mock->expects($this->once()) + ->method('validateId'); + + $proxy = new SessionHandlerProxy($mock); + $proxy->validateId('id'); + + $this->assertTrue($this->proxy->validateId('id')); + } + + /** + * @requires PHPUnit 5.1 + */ + public function testUpdateTimestamp() + { + $mock = $this->getMockBuilder(['SessionHandlerInterface', 'SessionUpdateTimestampHandlerInterface'])->getMock(); + $mock->expects($this->once()) + ->method('updateTimestamp') + ->willReturn(false); + + $proxy = new SessionHandlerProxy($mock); + $proxy->updateTimestamp('id', 'data'); + + $this->mock->expects($this->once()) + ->method('write'); + + $this->proxy->updateTimestamp('id', 'data'); + } } diff --git a/vendor/symfony/http-foundation/Tests/StreamedResponseTest.php b/vendor/symfony/http-foundation/Tests/StreamedResponseTest.php index c2ded996fab4fa72f0bddea1d8757d55d4f22e56..a084e917dcc0e9947c3b7274cbd4816e54121d12 100644 --- a/vendor/symfony/http-foundation/Tests/StreamedResponseTest.php +++ b/vendor/symfony/http-foundation/Tests/StreamedResponseTest.php @@ -19,7 +19,7 @@ class StreamedResponseTest extends TestCase { public function testConstructor() { - $response = new StreamedResponse(function () { echo 'foo'; }, 404, array('Content-Type' => 'text/plain')); + $response = new StreamedResponse(function () { echo 'foo'; }, 404, ['Content-Type' => 'text/plain']); $this->assertEquals(404, $response->getStatusCode()); $this->assertEquals('text/plain', $response->headers->get('Content-Type')); @@ -51,7 +51,7 @@ class StreamedResponseTest extends TestCase public function testPrepareWithHeadRequest() { - $response = new StreamedResponse(function () { echo 'foo'; }, 200, array('Content-Length' => '123')); + $response = new StreamedResponse(function () { echo 'foo'; }, 200, ['Content-Length' => '123']); $request = Request::create('/', 'HEAD'); $response->prepare($request); @@ -61,7 +61,7 @@ class StreamedResponseTest extends TestCase public function testPrepareWithCacheHeaders() { - $response = new StreamedResponse(function () { echo 'foo'; }, 200, array('Cache-Control' => 'max-age=600, public')); + $response = new StreamedResponse(function () { echo 'foo'; }, 200, ['Cache-Control' => 'max-age=600, public']); $request = Request::create('/', 'GET'); $response->prepare($request); @@ -81,20 +81,16 @@ class StreamedResponseTest extends TestCase $this->assertEquals(1, $called); } - /** - * @expectedException \LogicException - */ public function testSendContentWithNonCallable() { + $this->expectException('LogicException'); $response = new StreamedResponse(null); $response->sendContent(); } - /** - * @expectedException \LogicException - */ public function testSetContent() { + $this->expectException('LogicException'); $response = new StreamedResponse(function () { echo 'foo'; }); $response->setContent('foo'); } @@ -123,4 +119,22 @@ class StreamedResponseTest extends TestCase $this->assertInstanceOf('Symfony\Component\HttpFoundation\StreamedResponse', $response->sendHeaders()); $this->assertInstanceOf('Symfony\Component\HttpFoundation\StreamedResponse', $response->sendHeaders()); } + + public function testSetNotModified() + { + $response = new StreamedResponse(function () { echo 'foo'; }); + $modified = $response->setNotModified(); + $this->assertObjectHasAttribute('headers', $modified); + $this->assertObjectHasAttribute('content', $modified); + $this->assertObjectHasAttribute('version', $modified); + $this->assertObjectHasAttribute('statusCode', $modified); + $this->assertObjectHasAttribute('statusText', $modified); + $this->assertObjectHasAttribute('charset', $modified); + $this->assertEquals(304, $modified->getStatusCode()); + + ob_start(); + $modified->sendContent(); + $string = ob_get_clean(); + $this->assertEmpty($string); + } } diff --git a/vendor/symfony/http-foundation/Tests/Test/Constraint/RequestAttributeValueSameTest.php b/vendor/symfony/http-foundation/Tests/Test/Constraint/RequestAttributeValueSameTest.php new file mode 100644 index 0000000000000000000000000000000000000000..eca8aed263e214ac4d3c5673fb25c787388f994c --- /dev/null +++ b/vendor/symfony/http-foundation/Tests/Test/Constraint/RequestAttributeValueSameTest.php @@ -0,0 +1,41 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\Tests\Test\Constraint; + +use PHPUnit\Framework\ExpectationFailedException; +use PHPUnit\Framework\TestCase; +use PHPUnit\Framework\TestFailure; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Test\Constraint\RequestAttributeValueSame; + +class RequestAttributeValueSameTest extends TestCase +{ + public function testConstraint(): void + { + $request = new Request(); + $request->attributes->set('foo', 'bar'); + $constraint = new RequestAttributeValueSame('foo', 'bar'); + $this->assertTrue($constraint->evaluate($request, '', true)); + $constraint = new RequestAttributeValueSame('bar', 'foo'); + $this->assertFalse($constraint->evaluate($request, '', true)); + + try { + $constraint->evaluate($request); + } catch (ExpectationFailedException $e) { + $this->assertEquals("Failed asserting that the Request has attribute \"bar\" with value \"foo\".\n", TestFailure::exceptionToString($e)); + + return; + } + + $this->fail(); + } +} diff --git a/vendor/symfony/http-foundation/Tests/Test/Constraint/ResponseCookieValueSameTest.php b/vendor/symfony/http-foundation/Tests/Test/Constraint/ResponseCookieValueSameTest.php new file mode 100644 index 0000000000000000000000000000000000000000..778879c328f0d2d858d35ce749324e5629e6b15d --- /dev/null +++ b/vendor/symfony/http-foundation/Tests/Test/Constraint/ResponseCookieValueSameTest.php @@ -0,0 +1,44 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\Tests\Test\Constraint; + +use PHPUnit\Framework\ExpectationFailedException; +use PHPUnit\Framework\TestCase; +use PHPUnit\Framework\TestFailure; +use Symfony\Component\HttpFoundation\Cookie; +use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpFoundation\Test\Constraint\ResponseCookieValueSame; + +class ResponseCookieValueSameTest extends TestCase +{ + public function testConstraint(): void + { + $response = new Response(); + $response->headers->setCookie(Cookie::create('foo', 'bar', 0, '/path')); + $constraint = new ResponseCookieValueSame('foo', 'bar', '/path'); + $this->assertTrue($constraint->evaluate($response, '', true)); + $constraint = new ResponseCookieValueSame('foo', 'bar', '/path'); + $this->assertTrue($constraint->evaluate($response, '', true)); + $constraint = new ResponseCookieValueSame('foo', 'babar', '/path'); + $this->assertFalse($constraint->evaluate($response, '', true)); + + try { + $constraint->evaluate($response); + } catch (ExpectationFailedException $e) { + $this->assertEquals("Failed asserting that the Response has cookie \"foo\" with path \"/path\" with value \"babar\".\n", TestFailure::exceptionToString($e)); + + return; + } + + $this->fail(); + } +} diff --git a/vendor/symfony/http-foundation/Tests/Test/Constraint/ResponseHasCookieTest.php b/vendor/symfony/http-foundation/Tests/Test/Constraint/ResponseHasCookieTest.php new file mode 100644 index 0000000000000000000000000000000000000000..05ca95fb4656da37426da619c2aa4dafce6fe64b --- /dev/null +++ b/vendor/symfony/http-foundation/Tests/Test/Constraint/ResponseHasCookieTest.php @@ -0,0 +1,42 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\Tests\Test\Constraint; + +use PHPUnit\Framework\ExpectationFailedException; +use PHPUnit\Framework\TestCase; +use PHPUnit\Framework\TestFailure; +use Symfony\Component\HttpFoundation\Cookie; +use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpFoundation\Test\Constraint\ResponseHasCookie; + +class ResponseHasCookieTest extends TestCase +{ + public function testConstraint(): void + { + $response = new Response(); + $response->headers->setCookie(Cookie::create('foo', 'bar')); + $constraint = new ResponseHasCookie('foo'); + $this->assertTrue($constraint->evaluate($response, '', true)); + $constraint = new ResponseHasCookie('bar'); + $this->assertFalse($constraint->evaluate($response, '', true)); + + try { + $constraint->evaluate($response); + } catch (ExpectationFailedException $e) { + $this->assertEquals("Failed asserting that the Response has cookie \"bar\".\n", TestFailure::exceptionToString($e)); + + return; + } + + $this->fail(); + } +} diff --git a/vendor/symfony/http-foundation/Tests/Test/Constraint/ResponseHasHeaderTest.php b/vendor/symfony/http-foundation/Tests/Test/Constraint/ResponseHasHeaderTest.php new file mode 100644 index 0000000000000000000000000000000000000000..7b811a64a2bccdc967b624897df4e06d58c502bb --- /dev/null +++ b/vendor/symfony/http-foundation/Tests/Test/Constraint/ResponseHasHeaderTest.php @@ -0,0 +1,39 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\Tests\Test\Constraint; + +use PHPUnit\Framework\ExpectationFailedException; +use PHPUnit\Framework\TestCase; +use PHPUnit\Framework\TestFailure; +use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpFoundation\Test\Constraint\ResponseHasHeader; + +class ResponseHasHeaderTest extends TestCase +{ + public function testConstraint(): void + { + $constraint = new ResponseHasHeader('Date'); + $this->assertTrue($constraint->evaluate(new Response(), '', true)); + $constraint = new ResponseHasHeader('X-Date'); + $this->assertFalse($constraint->evaluate(new Response(), '', true)); + + try { + $constraint->evaluate(new Response()); + } catch (ExpectationFailedException $e) { + $this->assertEquals("Failed asserting that the Response has header \"X-Date\".\n", TestFailure::exceptionToString($e)); + + return; + } + + $this->fail(); + } +} diff --git a/vendor/symfony/http-foundation/Tests/Test/Constraint/ResponseHeaderSameTest.php b/vendor/symfony/http-foundation/Tests/Test/Constraint/ResponseHeaderSameTest.php new file mode 100644 index 0000000000000000000000000000000000000000..d527f35de8c28861db8b81602aabcf66a3ea239c --- /dev/null +++ b/vendor/symfony/http-foundation/Tests/Test/Constraint/ResponseHeaderSameTest.php @@ -0,0 +1,39 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\Tests\Test\Constraint; + +use PHPUnit\Framework\ExpectationFailedException; +use PHPUnit\Framework\TestCase; +use PHPUnit\Framework\TestFailure; +use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpFoundation\Test\Constraint\ResponseHeaderSame; + +class ResponseHeaderSameTest extends TestCase +{ + public function testConstraint(): void + { + $constraint = new ResponseHeaderSame('Cache-Control', 'no-cache, private'); + $this->assertTrue($constraint->evaluate(new Response(), '', true)); + $constraint = new ResponseHeaderSame('Cache-Control', 'public'); + $this->assertFalse($constraint->evaluate(new Response(), '', true)); + + try { + $constraint->evaluate(new Response()); + } catch (ExpectationFailedException $e) { + $this->assertEquals("Failed asserting that the Response has header \"Cache-Control\" with value \"public\".\n", TestFailure::exceptionToString($e)); + + return; + } + + $this->fail(); + } +} diff --git a/vendor/symfony/http-foundation/Tests/Test/Constraint/ResponseIsRedirectedTest.php b/vendor/symfony/http-foundation/Tests/Test/Constraint/ResponseIsRedirectedTest.php new file mode 100644 index 0000000000000000000000000000000000000000..a8314c2599468dfd55a8b36ec41d2055bd8ae9d5 --- /dev/null +++ b/vendor/symfony/http-foundation/Tests/Test/Constraint/ResponseIsRedirectedTest.php @@ -0,0 +1,39 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\Tests\Test\Constraint; + +use PHPUnit\Framework\ExpectationFailedException; +use PHPUnit\Framework\TestCase; +use PHPUnit\Framework\TestFailure; +use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpFoundation\Test\Constraint\ResponseIsRedirected; + +class ResponseIsRedirectedTest extends TestCase +{ + public function testConstraint(): void + { + $constraint = new ResponseIsRedirected(); + + $this->assertTrue($constraint->evaluate(new Response('', 301), '', true)); + $this->assertFalse($constraint->evaluate(new Response(), '', true)); + + try { + $constraint->evaluate(new Response()); + } catch (ExpectationFailedException $e) { + $this->assertStringContainsString("Failed asserting that the Response is redirected.\nHTTP/1.0 200 OK", TestFailure::exceptionToString($e)); + + return; + } + + $this->fail(); + } +} diff --git a/vendor/symfony/http-foundation/Tests/Test/Constraint/ResponseIsSuccessfulTest.php b/vendor/symfony/http-foundation/Tests/Test/Constraint/ResponseIsSuccessfulTest.php new file mode 100644 index 0000000000000000000000000000000000000000..b59daf8a38b552078df1dc95949f16a5564786cb --- /dev/null +++ b/vendor/symfony/http-foundation/Tests/Test/Constraint/ResponseIsSuccessfulTest.php @@ -0,0 +1,39 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\Tests\Test\Constraint; + +use PHPUnit\Framework\ExpectationFailedException; +use PHPUnit\Framework\TestCase; +use PHPUnit\Framework\TestFailure; +use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpFoundation\Test\Constraint\ResponseIsSuccessful; + +class ResponseIsSuccessfulTest extends TestCase +{ + public function testConstraint(): void + { + $constraint = new ResponseIsSuccessful(); + + $this->assertTrue($constraint->evaluate(new Response(), '', true)); + $this->assertFalse($constraint->evaluate(new Response('', 404), '', true)); + + try { + $constraint->evaluate(new Response('', 404)); + } catch (ExpectationFailedException $e) { + $this->assertStringContainsString("Failed asserting that the Response is successful.\nHTTP/1.0 404 Not Found", TestFailure::exceptionToString($e)); + + return; + } + + $this->fail(); + } +} diff --git a/vendor/symfony/http-foundation/Tests/Test/Constraint/ResponseStatusCodeSameTest.php b/vendor/symfony/http-foundation/Tests/Test/Constraint/ResponseStatusCodeSameTest.php new file mode 100644 index 0000000000000000000000000000000000000000..53200fdd03397e4b3d76dcb6e0fe622664c55e03 --- /dev/null +++ b/vendor/symfony/http-foundation/Tests/Test/Constraint/ResponseStatusCodeSameTest.php @@ -0,0 +1,41 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\Tests\Test\Constraint; + +use PHPUnit\Framework\ExpectationFailedException; +use PHPUnit\Framework\TestCase; +use PHPUnit\Framework\TestFailure; +use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpFoundation\Test\Constraint\ResponseStatusCodeSame; + +class ResponseStatusCodeSameTest extends TestCase +{ + public function testConstraint(): void + { + $constraint = new ResponseStatusCodeSame(200); + $this->assertTrue($constraint->evaluate(new Response(), '', true)); + $this->assertFalse($constraint->evaluate(new Response('', 404), '', true)); + $constraint = new ResponseStatusCodeSame(404); + $this->assertTrue($constraint->evaluate(new Response('', 404), '', true)); + + $constraint = new ResponseStatusCodeSame(200); + try { + $constraint->evaluate(new Response('', 404)); + } catch (ExpectationFailedException $e) { + $this->assertStringContainsString("Failed asserting that the Response status code is 200.\nHTTP/1.0 404 Not Found", TestFailure::exceptionToString($e)); + + return; + } + + $this->fail(); + } +} diff --git a/vendor/symfony/http-foundation/Tests/UrlHelperTest.php b/vendor/symfony/http-foundation/Tests/UrlHelperTest.php new file mode 100644 index 0000000000000000000000000000000000000000..9a750bd8a3bb5d7ed22b801c6d212def2438f2f0 --- /dev/null +++ b/vendor/symfony/http-foundation/Tests/UrlHelperTest.php @@ -0,0 +1,143 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation\Tests; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\RequestStack; +use Symfony\Component\HttpFoundation\UrlHelper; +use Symfony\Component\Routing\RequestContext; + +class UrlHelperTest extends TestCase +{ + /** + * @dataProvider getGenerateAbsoluteUrlData() + */ + public function testGenerateAbsoluteUrl($expected, $path, $pathinfo) + { + $stack = new RequestStack(); + $stack->push(Request::create($pathinfo)); + $helper = new UrlHelper($stack); + + $this->assertEquals($expected, $helper->getAbsoluteUrl($path)); + } + + public function getGenerateAbsoluteUrlData() + { + return [ + ['http://localhost/foo.png', '/foo.png', '/foo/bar.html'], + ['http://localhost/foo/foo.png', 'foo.png', '/foo/bar.html'], + ['http://localhost/foo/foo.png', 'foo.png', '/foo/bar'], + ['http://localhost/foo/bar/foo.png', 'foo.png', '/foo/bar/'], + + ['http://example.com/baz', 'http://example.com/baz', '/'], + ['https://example.com/baz', 'https://example.com/baz', '/'], + ['//example.com/baz', '//example.com/baz', '/'], + + ['http://localhost/foo/bar?baz', '?baz', '/foo/bar'], + ['http://localhost/foo/bar?baz=1', '?baz=1', '/foo/bar?foo=1'], + ['http://localhost/foo/baz?baz=1', 'baz?baz=1', '/foo/bar?foo=1'], + + ['http://localhost/foo/bar#baz', '#baz', '/foo/bar'], + ['http://localhost/foo/bar?0#baz', '#baz', '/foo/bar?0'], + ['http://localhost/foo/bar?baz=1#baz', '?baz=1#baz', '/foo/bar?foo=1'], + ['http://localhost/foo/baz?baz=1#baz', 'baz?baz=1#baz', '/foo/bar?foo=1'], + ]; + } + + /** + * @dataProvider getGenerateAbsoluteUrlRequestContextData + */ + public function testGenerateAbsoluteUrlWithRequestContext($path, $baseUrl, $host, $scheme, $httpPort, $httpsPort, $expected) + { + if (!class_exists('Symfony\Component\Routing\RequestContext')) { + $this->markTestSkipped('The Routing component is needed to run tests that depend on its request context.'); + } + + $requestContext = new RequestContext($baseUrl, 'GET', $host, $scheme, $httpPort, $httpsPort, $path); + $helper = new UrlHelper(new RequestStack(), $requestContext); + + $this->assertEquals($expected, $helper->getAbsoluteUrl($path)); + } + + /** + * @dataProvider getGenerateAbsoluteUrlRequestContextData + */ + public function testGenerateAbsoluteUrlWithoutRequestAndRequestContext($path) + { + if (!class_exists('Symfony\Component\Routing\RequestContext')) { + $this->markTestSkipped('The Routing component is needed to run tests that depend on its request context.'); + } + + $helper = new UrlHelper(new RequestStack()); + + $this->assertEquals($path, $helper->getAbsoluteUrl($path)); + } + + public function getGenerateAbsoluteUrlRequestContextData() + { + return [ + ['/foo.png', '/foo', 'localhost', 'http', 80, 443, 'http://localhost/foo.png'], + ['foo.png', '/foo', 'localhost', 'http', 80, 443, 'http://localhost/foo/foo.png'], + ['foo.png', '/foo/bar/', 'localhost', 'http', 80, 443, 'http://localhost/foo/bar/foo.png'], + ['/foo.png', '/foo', 'localhost', 'https', 80, 443, 'https://localhost/foo.png'], + ['foo.png', '/foo', 'localhost', 'https', 80, 443, 'https://localhost/foo/foo.png'], + ['foo.png', '/foo/bar/', 'localhost', 'https', 80, 443, 'https://localhost/foo/bar/foo.png'], + ['/foo.png', '/foo', 'localhost', 'http', 443, 80, 'http://localhost:443/foo.png'], + ['/foo.png', '/foo', 'localhost', 'https', 443, 80, 'https://localhost:80/foo.png'], + ]; + } + + public function testGenerateAbsoluteUrlWithScriptFileName() + { + $request = Request::create('http://localhost/app/web/app_dev.php'); + $request->server->set('SCRIPT_FILENAME', '/var/www/app/web/app_dev.php'); + + $stack = new RequestStack(); + $stack->push($request); + $helper = new UrlHelper($stack); + + $this->assertEquals( + 'http://localhost/app/web/bundles/framework/css/structure.css', + $helper->getAbsoluteUrl('/app/web/bundles/framework/css/structure.css') + ); + } + + /** + * @dataProvider getGenerateRelativePathData() + */ + public function testGenerateRelativePath($expected, $path, $pathinfo) + { + if (!method_exists('Symfony\Component\HttpFoundation\Request', 'getRelativeUriForPath')) { + $this->markTestSkipped('Your version of Symfony HttpFoundation is too old.'); + } + + $stack = new RequestStack(); + $stack->push(Request::create($pathinfo)); + $urlHelper = new UrlHelper($stack); + + $this->assertEquals($expected, $urlHelper->getRelativePath($path)); + } + + public function getGenerateRelativePathData() + { + return [ + ['../foo.png', '/foo.png', '/foo/bar.html'], + ['../baz/foo.png', '/baz/foo.png', '/foo/bar.html'], + ['baz/foo.png', 'baz/foo.png', '/foo/bar.html'], + + ['http://example.com/baz', 'http://example.com/baz', '/'], + ['https://example.com/baz', 'https://example.com/baz', '/'], + ['//example.com/baz', '//example.com/baz', '/'], + ]; + } +} diff --git a/vendor/symfony/http-foundation/UrlHelper.php b/vendor/symfony/http-foundation/UrlHelper.php new file mode 100644 index 0000000000000000000000000000000000000000..f114c0a9fb838cd41a248f4996d614a0b605ba9a --- /dev/null +++ b/vendor/symfony/http-foundation/UrlHelper.php @@ -0,0 +1,102 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpFoundation; + +use Symfony\Component\Routing\RequestContext; + +/** + * A helper service for manipulating URLs within and outside the request scope. + * + * @author Valentin Udaltsov <udaltsov.valentin@gmail.com> + */ +final class UrlHelper +{ + private $requestStack; + private $requestContext; + + public function __construct(RequestStack $requestStack, RequestContext $requestContext = null) + { + $this->requestStack = $requestStack; + $this->requestContext = $requestContext; + } + + public function getAbsoluteUrl(string $path): string + { + if (false !== strpos($path, '://') || '//' === substr($path, 0, 2)) { + return $path; + } + + if (null === $request = $this->requestStack->getMasterRequest()) { + return $this->getAbsoluteUrlFromContext($path); + } + + if ('#' === $path[0]) { + $path = $request->getRequestUri().$path; + } elseif ('?' === $path[0]) { + $path = $request->getPathInfo().$path; + } + + if (!$path || '/' !== $path[0]) { + $prefix = $request->getPathInfo(); + $last = \strlen($prefix) - 1; + if ($last !== $pos = strrpos($prefix, '/')) { + $prefix = substr($prefix, 0, $pos).'/'; + } + + return $request->getUriForPath($prefix.$path); + } + + return $request->getSchemeAndHttpHost().$path; + } + + public function getRelativePath(string $path): string + { + if (false !== strpos($path, '://') || '//' === substr($path, 0, 2)) { + return $path; + } + + if (null === $request = $this->requestStack->getMasterRequest()) { + return $path; + } + + return $request->getRelativeUriForPath($path); + } + + private function getAbsoluteUrlFromContext(string $path): string + { + if (null === $this->requestContext || '' === $host = $this->requestContext->getHost()) { + return $path; + } + + $scheme = $this->requestContext->getScheme(); + $port = ''; + + if ('http' === $scheme && 80 !== $this->requestContext->getHttpPort()) { + $port = ':'.$this->requestContext->getHttpPort(); + } elseif ('https' === $scheme && 443 !== $this->requestContext->getHttpsPort()) { + $port = ':'.$this->requestContext->getHttpsPort(); + } + + if ('#' === $path[0]) { + $queryString = $this->requestContext->getQueryString(); + $path = $this->requestContext->getPathInfo().($queryString ? '?'.$queryString : '').$path; + } elseif ('?' === $path[0]) { + $path = $this->requestContext->getPathInfo().$path; + } + + if ('/' !== $path[0]) { + $path = rtrim($this->requestContext->getBaseUrl(), '/').'/'.$path; + } + + return $scheme.'://'.$host.$port.$path; + } +} diff --git a/vendor/symfony/http-foundation/composer.json b/vendor/symfony/http-foundation/composer.json index f6c6f2e623fe695e6384e606306514541cad742f..f30975114f6042dd57c221b9f2c4219bf2a8667e 100644 --- a/vendor/symfony/http-foundation/composer.json +++ b/vendor/symfony/http-foundation/composer.json @@ -16,12 +16,13 @@ } ], "require": { - "php": "^5.5.9|>=7.0.8", - "symfony/polyfill-mbstring": "~1.1", - "symfony/polyfill-php70": "~1.6" + "php": "^7.1.3", + "symfony/mime": "^4.3", + "symfony/polyfill-mbstring": "~1.1" }, "require-dev": { - "symfony/expression-language": "~2.8|~3.0|~4.0" + "predis/predis": "~1.0", + "symfony/expression-language": "~3.4|~4.0" }, "autoload": { "psr-4": { "Symfony\\Component\\HttpFoundation\\": "" }, @@ -32,7 +33,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-master": "3.4-dev" + "dev-master": "4.3-dev" } } } diff --git a/vendor/symfony/http-foundation/phpunit.xml.dist b/vendor/symfony/http-foundation/phpunit.xml.dist index c1d61f8bf1da0b6d47f92152164b63f3bb7e6f37..f57bc9e62d5eb37cc83a86db4459969d4c06864e 100644 --- a/vendor/symfony/http-foundation/phpunit.xml.dist +++ b/vendor/symfony/http-foundation/phpunit.xml.dist @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="UTF-8"?> <phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/4.1/phpunit.xsd" + xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/5.2/phpunit.xsd" backupGlobals="false" colors="true" bootstrap="vendor/autoload.php" diff --git a/vendor/symfony/http-kernel/Bundle/Bundle.php b/vendor/symfony/http-kernel/Bundle/Bundle.php index cfa576c367919ce726cb1b779c0b938fcc9b9e2e..a769e96034fabce5ccdf366ee1270f0ff8a7a6f8 100644 --- a/vendor/symfony/http-kernel/Bundle/Bundle.php +++ b/vendor/symfony/http-kernel/Bundle/Bundle.php @@ -11,16 +11,14 @@ namespace Symfony\Component\HttpKernel\Bundle; +use Symfony\Component\Console\Application; +use Symfony\Component\DependencyInjection\Container; use Symfony\Component\DependencyInjection\ContainerAwareTrait; use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Container; -use Symfony\Component\Console\Application; -use Symfony\Component\Finder\Finder; use Symfony\Component\DependencyInjection\Extension\ExtensionInterface; /** - * An implementation of BundleInterface that adds a few conventions - * for DependencyInjection extensions and Console commands. + * An implementation of BundleInterface that adds a few conventions for DependencyInjection extensions. * * @author Fabien Potencier <fabien@symfony.com> */ @@ -34,23 +32,21 @@ abstract class Bundle implements BundleInterface private $namespace; /** - * Boots the Bundle. + * {@inheritdoc} */ public function boot() { } /** - * Shutdowns the Bundle. + * {@inheritdoc} */ public function shutdown() { } /** - * Builds the bundle. - * - * It is only ever called once when the cache is empty. + * {@inheritdoc} * * This method can be overridden to register compilation passes, * other extensions, ... @@ -73,7 +69,7 @@ abstract class Bundle implements BundleInterface if (null !== $extension) { if (!$extension instanceof ExtensionInterface) { - throw new \LogicException(sprintf('Extension %s must implement Symfony\Component\DependencyInjection\Extension\ExtensionInterface.', get_class($extension))); + throw new \LogicException(sprintf('Extension %s must implement Symfony\Component\DependencyInjection\Extension\ExtensionInterface.', \get_class($extension))); } // check naming convention @@ -81,10 +77,7 @@ abstract class Bundle implements BundleInterface $expectedAlias = Container::underscore($basename); if ($expectedAlias != $extension->getAlias()) { - throw new \LogicException(sprintf( - 'Users will expect the alias of the default extension of a bundle to be the underscored version of the bundle name ("%s"). You can override "Bundle::getContainerExtension()" if you want to use "%s" or another alias.', - $expectedAlias, $extension->getAlias() - )); + throw new \LogicException(sprintf('Users will expect the alias of the default extension of a bundle to be the underscored version of the bundle name ("%s"). You can override "Bundle::getContainerExtension()" if you want to use "%s" or another alias.', $expectedAlias, $extension->getAlias())); } $this->extension = $extension; @@ -93,15 +86,11 @@ abstract class Bundle implements BundleInterface } } - if ($this->extension) { - return $this->extension; - } + return $this->extension ?: null; } /** - * Gets the Bundle namespace. - * - * @return string The Bundle namespace + * {@inheritdoc} */ public function getNamespace() { @@ -113,29 +102,18 @@ abstract class Bundle implements BundleInterface } /** - * Gets the Bundle directory path. - * - * @return string The Bundle absolute path + * {@inheritdoc} */ public function getPath() { if (null === $this->path) { $reflected = new \ReflectionObject($this); - $this->path = dirname($reflected->getFileName()); + $this->path = \dirname($reflected->getFileName()); } return $this->path; } - /** - * Returns the bundle parent name. - * - * @return string|null The Bundle parent name it overrides or null if no parent - */ - public function getParent() - { - } - /** * Returns the bundle name (the class short name). * @@ -150,48 +128,8 @@ abstract class Bundle implements BundleInterface return $this->name; } - /** - * Finds and registers Commands. - * - * Override this method if your bundle commands do not follow the conventions: - * - * * Commands are in the 'Command' sub-directory - * * Commands extend Symfony\Component\Console\Command\Command - */ public function registerCommands(Application $application) { - if (!is_dir($dir = $this->getPath().'/Command')) { - return; - } - - if (!class_exists('Symfony\Component\Finder\Finder')) { - throw new \RuntimeException('You need the symfony/finder component to register bundle commands.'); - } - - $finder = new Finder(); - $finder->files()->name('*Command.php')->in($dir); - - $prefix = $this->getNamespace().'\\Command'; - foreach ($finder as $file) { - $ns = $prefix; - if ($relativePath = $file->getRelativePath()) { - $ns .= '\\'.str_replace('/', '\\', $relativePath); - } - $class = $ns.'\\'.$file->getBasename('.php'); - if ($this->container) { - $commandIds = $this->container->hasParameter('console.command.ids') ? $this->container->getParameter('console.command.ids') : array(); - $alias = 'console.command.'.strtolower(str_replace('\\', '_', $class)); - if (isset($commandIds[$alias]) || $this->container->has($alias)) { - continue; - } - } - $r = new \ReflectionClass($class); - if ($r->isSubclassOf('Symfony\\Component\\Console\\Command\\Command') && !$r->isAbstract() && !$r->getConstructor()->getNumberOfRequiredParameters()) { - @trigger_error(sprintf('Auto-registration of the command "%s" is deprecated since Symfony 3.4 and won\'t be supported in 4.0. Use PSR-4 based service discovery instead.', $class), E_USER_DEPRECATED); - - $application->add($r->newInstance()); - } - } } /** @@ -213,9 +151,7 @@ abstract class Bundle implements BundleInterface */ protected function createContainerExtension() { - if (class_exists($class = $this->getContainerExtensionClass())) { - return new $class(); - } + return class_exists($class = $this->getContainerExtensionClass()) ? new $class() : null; } private function parseClassName() diff --git a/vendor/symfony/http-kernel/Bundle/BundleInterface.php b/vendor/symfony/http-kernel/Bundle/BundleInterface.php index 14a7f6f4fd3a3b33c64cf375ddd0fba410bb1ae8..88a95d83329429332284c8e655f1fd6572152d88 100644 --- a/vendor/symfony/http-kernel/Bundle/BundleInterface.php +++ b/vendor/symfony/http-kernel/Bundle/BundleInterface.php @@ -46,19 +46,6 @@ interface BundleInterface extends ContainerAwareInterface */ public function getContainerExtension(); - /** - * Returns the bundle name that this bundle overrides. - * - * Despite its name, this method does not imply any parent/child relationship - * between the bundles, just a way to extend and override an existing - * bundle. - * - * @return string The Bundle name it overrides or null if no parent - * - * @deprecated This method is deprecated as of 3.4 and will be removed in 4.0. - */ - public function getParent(); - /** * Returns the bundle name (the class short name). * diff --git a/vendor/symfony/http-kernel/CHANGELOG.md b/vendor/symfony/http-kernel/CHANGELOG.md index fb29f769629282601d0fe44448ab5fcc32fb6951..b1a5f5101b41d3ab12f44343b01f3a0201401e8c 100644 --- a/vendor/symfony/http-kernel/CHANGELOG.md +++ b/vendor/symfony/http-kernel/CHANGELOG.md @@ -1,6 +1,73 @@ CHANGELOG ========= +4.3.0 +----- + + * renamed `Client` to `HttpKernelBrowser` + * `KernelInterface` doesn't extend `Serializable` anymore + * deprecated the `Kernel::serialize()` and `unserialize()` methods + * increased the priority of `Symfony\Component\HttpKernel\EventListener\AddRequestFormatsListener` + * made `Symfony\Component\HttpKernel\EventListener\LocaleListener` set the default locale early + * deprecated `TranslatorListener` in favor of `LocaleAwareListener` + * added the registration of all `LocaleAwareInterface` implementations into the `LocaleAwareListener` + * made `FileLinkFormatter` final and not implement `Serializable` anymore + * the base `DataCollector` doesn't implement `Serializable` anymore, you should + store all the serialized state in the data property instead + * `DumpDataCollector` has been marked as `final` + * added an event listener to prevent search engines from indexing applications in debug mode. + * renamed `FilterControllerArgumentsEvent` to `ControllerArgumentsEvent` + * renamed `FilterControllerEvent` to `ControllerEvent` + * renamed `FilterResponseEvent` to `ResponseEvent` + * renamed `GetResponseEvent` to `RequestEvent` + * renamed `GetResponseForControllerResultEvent` to `ViewEvent` + * renamed `GetResponseForExceptionEvent` to `ExceptionEvent` + * renamed `PostResponseEvent` to `TerminateEvent` + * added `HttpClientKernel` for handling requests with an `HttpClientInterface` instance + * added `trace_header` and `trace_level` configuration options to `HttpCache` + +4.2.0 +----- + + * deprecated `KernelInterface::getRootDir()` and the `kernel.root_dir` parameter + * deprecated `KernelInterface::getName()` and the `kernel.name` parameter + * deprecated the first and second constructor argument of `ConfigDataCollector` + * deprecated `ConfigDataCollector::getApplicationName()` + * deprecated `ConfigDataCollector::getApplicationVersion()` + +4.1.0 +----- + + * added orphaned events support to `EventDataCollector` + * `ExceptionListener` now logs exceptions at priority `0` (previously logged at `-128`) + * Added support for using `service::method` to reference controllers, making it consistent with other cases. It is recommended over the `service:action` syntax with a single colon, which will be deprecated in the future. + * Added the ability to profile individual argument value resolvers via the + `Symfony\Component\HttpKernel\Controller\ArgumentResolver\TraceableValueResolver` + +4.0.0 +----- + + * removed the `DataCollector::varToString()` method, use `DataCollector::cloneVar()` + instead + * using the `DataCollector::cloneVar()` method requires the VarDumper component + * removed the `ValueExporter` class + * removed `ControllerResolverInterface::getArguments()` + * removed `TraceableControllerResolver::getArguments()` + * removed `ControllerResolver::getArguments()` and the ability to resolve arguments + * removed the `argument_resolver` service dependency from the `debug.controller_resolver` + * removed `LazyLoadingFragmentHandler::addRendererService()` + * removed `Psr6CacheClearer::addPool()` + * removed `Extension::addClassesToCompile()` and `Extension::getClassesToCompile()` + * removed `Kernel::loadClassCache()`, `Kernel::doLoadClassCache()`, `Kernel::setClassCache()`, + and `Kernel::getEnvParameters()` + * support for the `X-Status-Code` when handling exceptions in the `HttpKernel` + has been dropped, use the `HttpKernel::allowCustomResponseCode()` method + instead + * removed convention-based commands registration + * removed the `ChainCacheClearer::add()` method + * removed the `CacheaWarmerAggregate::add()` and `setWarmers()` methods + * made `CacheWarmerAggregate` and `ChainCacheClearer` classes final + 3.4.0 ----- diff --git a/vendor/symfony/http-kernel/CacheClearer/ChainCacheClearer.php b/vendor/symfony/http-kernel/CacheClearer/ChainCacheClearer.php index 8ee4275b1686746ac9117fd970d989b7d62b06ef..5061a8d1815e3874a341d052974bfd01d7b50af9 100644 --- a/vendor/symfony/http-kernel/CacheClearer/ChainCacheClearer.php +++ b/vendor/symfony/http-kernel/CacheClearer/ChainCacheClearer.php @@ -16,18 +16,13 @@ namespace Symfony\Component\HttpKernel\CacheClearer; * * @author Dustin Dobervich <ddobervich@gmail.com> * - * @final since version 3.4 + * @final */ class ChainCacheClearer implements CacheClearerInterface { - protected $clearers; + private $clearers; - /** - * Constructs a new instance of ChainCacheClearer. - * - * @param array $clearers The initial clearers - */ - public function __construct($clearers = array()) + public function __construct(iterable $clearers = []) { $this->clearers = $clearers; } @@ -41,16 +36,4 @@ class ChainCacheClearer implements CacheClearerInterface $clearer->clear($cacheDir); } } - - /** - * Adds a cache clearer to the aggregate. - * - * @deprecated since version 3.4, to be removed in 4.0, inject the list of clearers as a constructor argument instead. - */ - public function add(CacheClearerInterface $clearer) - { - @trigger_error(sprintf('The "%s()" method is deprecated since Symfony 3.4 and will be removed in 4.0, inject the list of clearers as a constructor argument instead.', __METHOD__), E_USER_DEPRECATED); - - $this->clearers[] = $clearer; - } } diff --git a/vendor/symfony/http-kernel/CacheClearer/Psr6CacheClearer.php b/vendor/symfony/http-kernel/CacheClearer/Psr6CacheClearer.php index d413d2c9d641d18952a305be9e599ed50a221ce1..47a6ece5c1e0e82790bd57f734e94dc47b1f39fe 100644 --- a/vendor/symfony/http-kernel/CacheClearer/Psr6CacheClearer.php +++ b/vendor/symfony/http-kernel/CacheClearer/Psr6CacheClearer.php @@ -11,30 +11,30 @@ namespace Symfony\Component\HttpKernel\CacheClearer; -use Psr\Cache\CacheItemPoolInterface; - /** * @author Nicolas Grekas <p@tchwork.com> */ class Psr6CacheClearer implements CacheClearerInterface { - private $pools = array(); + private $pools = []; - public function __construct(array $pools = array()) + public function __construct(array $pools = []) { $this->pools = $pools; } - public function addPool(CacheItemPoolInterface $pool) + public function hasPool($name) { - @trigger_error(sprintf('The %s() method is deprecated since Symfony 3.3 and will be removed in 4.0. Pass an array of pools indexed by name to the constructor instead.', __METHOD__), E_USER_DEPRECATED); - - $this->pools[] = $pool; + return isset($this->pools[$name]); } - public function hasPool($name) + public function getPool($name) { - return isset($this->pools[$name]); + if (!$this->hasPool($name)) { + throw new \InvalidArgumentException(sprintf('Cache pool not found: %s.', $name)); + } + + return $this->pools[$name]; } public function clearPool($name) diff --git a/vendor/symfony/http-kernel/CacheWarmer/CacheWarmer.php b/vendor/symfony/http-kernel/CacheWarmer/CacheWarmer.php index dba35a639a46c4b959dc2c2368c5a66227512121..52dc2ad2c3d83f0ae1ff482237792b90d9c89ce3 100644 --- a/vendor/symfony/http-kernel/CacheWarmer/CacheWarmer.php +++ b/vendor/symfony/http-kernel/CacheWarmer/CacheWarmer.php @@ -20,7 +20,7 @@ abstract class CacheWarmer implements CacheWarmerInterface { protected function writeCacheFile($file, $content) { - $tmpFile = @tempnam(dirname($file), basename($file)); + $tmpFile = @tempnam(\dirname($file), basename($file)); if (false !== @file_put_contents($tmpFile, $content) && @rename($tmpFile, $file)) { @chmod($file, 0666 & ~umask()); diff --git a/vendor/symfony/http-kernel/CacheWarmer/CacheWarmerAggregate.php b/vendor/symfony/http-kernel/CacheWarmer/CacheWarmerAggregate.php index ca3911ed5f9dc13bfb6d3c902d62bcfcbacb00e8..57292e07f9bae48f8377640f03686fc32f4e6aee 100644 --- a/vendor/symfony/http-kernel/CacheWarmer/CacheWarmerAggregate.php +++ b/vendor/symfony/http-kernel/CacheWarmer/CacheWarmerAggregate.php @@ -16,20 +16,21 @@ namespace Symfony\Component\HttpKernel\CacheWarmer; * * @author Fabien Potencier <fabien@symfony.com> * - * @final since version 3.4 + * @final */ class CacheWarmerAggregate implements CacheWarmerInterface { - protected $warmers = array(); - protected $optionalsEnabled = false; - private $triggerDeprecation = false; + private $warmers; + private $debug; + private $deprecationLogsFilepath; + private $optionalsEnabled = false; + private $onlyOptionalsEnabled = false; - public function __construct($warmers = array()) + public function __construct(iterable $warmers = [], bool $debug = false, string $deprecationLogsFilepath = null) { - foreach ($warmers as $warmer) { - $this->add($warmer); - } - $this->triggerDeprecation = true; + $this->warmers = $warmers; + $this->debug = $debug; + $this->deprecationLogsFilepath = $deprecationLogsFilepath; } public function enableOptionalWarmers() @@ -37,6 +38,11 @@ class CacheWarmerAggregate implements CacheWarmerInterface $this->optionalsEnabled = true; } + public function enableOnlyOptionalWarmers() + { + $this->onlyOptionalsEnabled = $this->optionalsEnabled = true; + } + /** * Warms up the cache. * @@ -44,12 +50,63 @@ class CacheWarmerAggregate implements CacheWarmerInterface */ public function warmUp($cacheDir) { - foreach ($this->warmers as $warmer) { - if (!$this->optionalsEnabled && $warmer->isOptional()) { - continue; + if ($collectDeprecations = $this->debug && !\defined('PHPUNIT_COMPOSER_INSTALL')) { + $collectedLogs = []; + $previousHandler = set_error_handler(function ($type, $message, $file, $line) use (&$collectedLogs, &$previousHandler) { + if (E_USER_DEPRECATED !== $type && E_DEPRECATED !== $type) { + return $previousHandler ? $previousHandler($type, $message, $file, $line) : false; + } + + if (isset($collectedLogs[$message])) { + ++$collectedLogs[$message]['count']; + + return null; + } + + $backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 3); + // Clean the trace by removing first frames added by the error handler itself. + for ($i = 0; isset($backtrace[$i]); ++$i) { + if (isset($backtrace[$i]['file'], $backtrace[$i]['line']) && $backtrace[$i]['line'] === $line && $backtrace[$i]['file'] === $file) { + $backtrace = \array_slice($backtrace, 1 + $i); + break; + } + } + + $collectedLogs[$message] = [ + 'type' => $type, + 'message' => $message, + 'file' => $file, + 'line' => $line, + 'trace' => $backtrace, + 'count' => 1, + ]; + + return null; + }); + } + + try { + foreach ($this->warmers as $warmer) { + if (!$this->optionalsEnabled && $warmer->isOptional()) { + continue; + } + if ($this->onlyOptionalsEnabled && !$warmer->isOptional()) { + continue; + } + + $warmer->warmUp($cacheDir); } + } finally { + if ($collectDeprecations) { + restore_error_handler(); + + if (file_exists($this->deprecationLogsFilepath)) { + $previousLogs = unserialize(file_get_contents($this->deprecationLogsFilepath)); + $collectedLogs = array_merge($previousLogs, $collectedLogs); + } - $warmer->warmUp($cacheDir); + file_put_contents($this->deprecationLogsFilepath, serialize(array_values($collectedLogs))); + } } } @@ -62,29 +119,4 @@ class CacheWarmerAggregate implements CacheWarmerInterface { return false; } - - /** - * @deprecated since version 3.4, to be removed in 4.0, inject the list of clearers as a constructor argument instead. - */ - public function setWarmers(array $warmers) - { - @trigger_error(sprintf('The "%s()" method is deprecated since Symfony 3.4 and will be removed in 4.0, inject the list of clearers as a constructor argument instead.', __METHOD__), E_USER_DEPRECATED); - - $this->warmers = array(); - foreach ($warmers as $warmer) { - $this->add($warmer); - } - } - - /** - * @deprecated since version 3.4, to be removed in 4.0, inject the list of clearers as a constructor argument instead. - */ - public function add(CacheWarmerInterface $warmer) - { - if ($this->triggerDeprecation) { - @trigger_error(sprintf('The "%s()" method is deprecated since Symfony 3.4 and will be removed in 4.0, inject the list of clearers as a constructor argument instead.', __METHOD__), E_USER_DEPRECATED); - } - - $this->warmers[] = $warmer; - } } diff --git a/vendor/symfony/http-kernel/Client.php b/vendor/symfony/http-kernel/Client.php index 7979722d164f9c8daacb579d1ebb2e19d5fa05e2..fba2562a6cb3cfad6872c0f0a900e20fb3a1ca94 100644 --- a/vendor/symfony/http-kernel/Client.php +++ b/vendor/symfony/http-kernel/Client.php @@ -11,24 +11,24 @@ namespace Symfony\Component\HttpKernel; -use Symfony\Component\BrowserKit\Client as BaseClient; +use Symfony\Component\BrowserKit\AbstractBrowser; +use Symfony\Component\BrowserKit\CookieJar; +use Symfony\Component\BrowserKit\History; use Symfony\Component\BrowserKit\Request as DomRequest; use Symfony\Component\BrowserKit\Response as DomResponse; -use Symfony\Component\BrowserKit\History; -use Symfony\Component\BrowserKit\CookieJar; use Symfony\Component\HttpFoundation\File\UploadedFile; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; /** - * Client simulates a browser and makes requests to a Kernel object. + * Client simulates a browser and makes requests to an HttpKernel instance. * - * @author Fabien Potencier <fabien@symfony.com> + * @method Request getRequest() A Request instance + * @method Response getResponse() A Response instance * - * @method Request|null getRequest() A Request instance - * @method Response|null getResponse() A Response instance + * @deprecated since Symfony 4.3, use HttpKernelBrowser instead. */ -class Client extends BaseClient +class Client extends AbstractBrowser { protected $kernel; private $catchExceptions = true; @@ -39,7 +39,7 @@ class Client extends BaseClient * @param History $history A History instance to store the browser history * @param CookieJar $cookieJar A CookieJar instance to store the cookies */ - public function __construct(HttpKernelInterface $kernel, array $server = array(), History $history = null, CookieJar $cookieJar = null) + public function __construct(HttpKernelInterface $kernel, array $server = [], History $history = null, CookieJar $cookieJar = null) { // These class properties must be set before calling the parent constructor, as it may depend on it. $this->kernel = $kernel; @@ -81,17 +81,18 @@ class Client extends BaseClient */ protected function getScript($request) { - $kernel = str_replace("'", "\\'", serialize($this->kernel)); - $request = str_replace("'", "\\'", serialize($request)); + $kernel = var_export(serialize($this->kernel), true); + $request = var_export(serialize($request), true); + $errorReporting = error_reporting(); $requires = ''; foreach (get_declared_classes() as $class) { if (0 === strpos($class, 'ComposerAutoloaderInit')) { $r = new \ReflectionClass($class); - $file = dirname(dirname($r->getFileName())).'/autoload.php'; + $file = \dirname($r->getFileName(), 2).'/autoload.php'; if (file_exists($file)) { - $requires .= "require_once '".str_replace("'", "\\'", $file)."';\n"; + $requires .= 'require_once '.var_export($file, true).";\n"; } } } @@ -107,8 +108,8 @@ error_reporting($errorReporting); $requires -\$kernel = unserialize('$kernel'); -\$request = unserialize('$request'); +\$kernel = unserialize($kernel); +\$request = unserialize($request); EOF; return $code.$this->getHandleScript(); @@ -158,9 +159,9 @@ EOF; */ protected function filterFiles(array $files) { - $filtered = array(); + $filtered = []; foreach ($files as $key => $value) { - if (is_array($value)) { + if (\is_array($value)) { $filtered[$key] = $this->filterFiles($value); } elseif ($value instanceof UploadedFile) { if ($value->isValid() && $value->getSize() > UploadedFile::getMaxFilesize()) { @@ -168,7 +169,6 @@ EOF; '', $value->getClientOriginalName(), $value->getClientMimeType(), - 0, UPLOAD_ERR_INI_SIZE, true ); @@ -177,7 +177,6 @@ EOF; $value->getPathname(), $value->getClientOriginalName(), $value->getClientMimeType(), - $value->getClientSize(), $value->getError(), true ); diff --git a/vendor/symfony/http-kernel/Config/EnvParametersResource.php b/vendor/symfony/http-kernel/Config/EnvParametersResource.php deleted file mode 100644 index f8d2a72b2a9b918174396e913395543d2567cf64..0000000000000000000000000000000000000000 --- a/vendor/symfony/http-kernel/Config/EnvParametersResource.php +++ /dev/null @@ -1,99 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Config; - -use Symfony\Component\Config\Resource\SelfCheckingResourceInterface; - -/** - * EnvParametersResource represents resources stored in prefixed environment variables. - * - * @author Chris Wilkinson <chriswilkinson84@gmail.com> - * - * @deprecated since version 3.4, to be removed in 4.0 - */ -class EnvParametersResource implements SelfCheckingResourceInterface, \Serializable -{ - /** - * @var string - */ - private $prefix; - - /** - * @var string - */ - private $variables; - - /** - * @param string $prefix - */ - public function __construct($prefix) - { - $this->prefix = $prefix; - $this->variables = $this->findVariables(); - } - - /** - * {@inheritdoc} - */ - public function __toString() - { - return serialize($this->getResource()); - } - - /** - * @return array An array with two keys: 'prefix' for the prefix used and 'variables' containing all the variables watched by this resource - */ - public function getResource() - { - return array('prefix' => $this->prefix, 'variables' => $this->variables); - } - - /** - * {@inheritdoc} - */ - public function isFresh($timestamp) - { - return $this->findVariables() === $this->variables; - } - - public function serialize() - { - return serialize(array('prefix' => $this->prefix, 'variables' => $this->variables)); - } - - public function unserialize($serialized) - { - if (\PHP_VERSION_ID >= 70000) { - $unserialized = unserialize($serialized, array('allowed_classes' => false)); - } else { - $unserialized = unserialize($serialized); - } - - $this->prefix = $unserialized['prefix']; - $this->variables = $unserialized['variables']; - } - - private function findVariables() - { - $variables = array(); - - foreach ($_SERVER as $key => $value) { - if (0 === strpos($key, $this->prefix)) { - $variables[$key] = $value; - } - } - - ksort($variables); - - return $variables; - } -} diff --git a/vendor/symfony/http-kernel/Config/FileLocator.php b/vendor/symfony/http-kernel/Config/FileLocator.php index fb1f913bdff5d1ae348cd4611d3529215b7a1be9..f88d1684fe5592cd51f191b3ea9bf97ed2b6cfa1 100644 --- a/vendor/symfony/http-kernel/Config/FileLocator.php +++ b/vendor/symfony/http-kernel/Config/FileLocator.php @@ -26,10 +26,10 @@ class FileLocator extends BaseFileLocator /** * @param KernelInterface $kernel A KernelInterface instance - * @param null|string $path The path the global resource directory + * @param string|null $path The path the global resource directory * @param array $paths An array of paths where to look for resources */ - public function __construct(KernelInterface $kernel, $path = null, array $paths = array()) + public function __construct(KernelInterface $kernel, string $path = null, array $paths = []) { $this->kernel = $kernel; if (null !== $path) { diff --git a/vendor/symfony/http-kernel/Controller/ArgumentResolver.php b/vendor/symfony/http-kernel/Controller/ArgumentResolver.php index 2c17125c5aca1095e8f0e438007b433adb4f36a6..86ceab2f264c12450478149c75e1dda21d4392df 100644 --- a/vendor/symfony/http-kernel/Controller/ArgumentResolver.php +++ b/vendor/symfony/http-kernel/Controller/ArgumentResolver.php @@ -34,7 +34,7 @@ final class ArgumentResolver implements ArgumentResolverInterface */ private $argumentValueResolvers; - public function __construct(ArgumentMetadataFactoryInterface $argumentMetadataFactory = null, $argumentValueResolvers = array()) + public function __construct(ArgumentMetadataFactoryInterface $argumentMetadataFactory = null, iterable $argumentValueResolvers = []) { $this->argumentMetadataFactory = $argumentMetadataFactory ?: new ArgumentMetadataFactory(); $this->argumentValueResolvers = $argumentValueResolvers ?: self::getDefaultArgumentValueResolvers(); @@ -45,7 +45,7 @@ final class ArgumentResolver implements ArgumentResolverInterface */ public function getArguments(Request $request, $controller) { - $arguments = array(); + $arguments = []; foreach ($this->argumentMetadataFactory->createArgumentMetadata($controller) as $metadata) { foreach ($this->argumentValueResolvers as $resolver) { @@ -56,7 +56,7 @@ final class ArgumentResolver implements ArgumentResolverInterface $resolved = $resolver->resolve($request, $metadata); if (!$resolved instanceof \Generator) { - throw new \InvalidArgumentException(sprintf('%s::resolve() must yield at least one value.', get_class($resolver))); + throw new \InvalidArgumentException(sprintf('%s::resolve() must yield at least one value.', \get_class($resolver))); } foreach ($resolved as $append) { @@ -69,10 +69,10 @@ final class ArgumentResolver implements ArgumentResolverInterface $representative = $controller; - if (is_array($representative)) { - $representative = sprintf('%s::%s()', get_class($representative[0]), $representative[1]); - } elseif (is_object($representative)) { - $representative = get_class($representative); + if (\is_array($representative)) { + $representative = sprintf('%s::%s()', \get_class($representative[0]), $representative[1]); + } elseif (\is_object($representative)) { + $representative = \get_class($representative); } throw new \RuntimeException(sprintf('Controller "%s" requires that you provide a value for the "$%s" argument. Either the argument is nullable and no null value has been provided, no default value has been provided or because there is a non optional argument after this one.', $representative, $metadata->getName())); @@ -81,14 +81,14 @@ final class ArgumentResolver implements ArgumentResolverInterface return $arguments; } - public static function getDefaultArgumentValueResolvers() + public static function getDefaultArgumentValueResolvers(): iterable { - return array( + return [ new RequestAttributeValueResolver(), new RequestValueResolver(), new SessionValueResolver(), new DefaultValueResolver(), new VariadicValueResolver(), - ); + ]; } } diff --git a/vendor/symfony/http-kernel/Controller/ArgumentResolver/NotTaggedControllerValueResolver.php b/vendor/symfony/http-kernel/Controller/ArgumentResolver/NotTaggedControllerValueResolver.php new file mode 100644 index 0000000000000000000000000000000000000000..19e324dc2495723c8e4c670e41ac6ba7e9895678 --- /dev/null +++ b/vendor/symfony/http-kernel/Controller/ArgumentResolver/NotTaggedControllerValueResolver.php @@ -0,0 +1,81 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Controller\ArgumentResolver; + +use Psr\Container\ContainerInterface; +use Symfony\Component\DependencyInjection\Exception\RuntimeException; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface; +use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata; + +/** + * Provides an intuitive error message when controller fails because it is not registered as a service. + * + * @author Simeon Kolev <simeon.kolev9@gmail.com> + */ +final class NotTaggedControllerValueResolver implements ArgumentValueResolverInterface +{ + private $container; + + public function __construct(ContainerInterface $container) + { + $this->container = $container; + } + + /** + * {@inheritdoc} + */ + public function supports(Request $request, ArgumentMetadata $argument) + { + $controller = $request->attributes->get('_controller'); + + if (\is_array($controller) && \is_callable($controller, true) && \is_string($controller[0])) { + $controller = $controller[0].'::'.$controller[1]; + } elseif (!\is_string($controller) || '' === $controller) { + return false; + } + + if ('\\' === $controller[0]) { + $controller = ltrim($controller, '\\'); + } + + if (!$this->container->has($controller) && false !== $i = strrpos($controller, ':')) { + $controller = substr($controller, 0, $i).strtolower(substr($controller, $i)); + } + + return false === $this->container->has($controller); + } + + /** + * {@inheritdoc} + */ + public function resolve(Request $request, ArgumentMetadata $argument) + { + if (\is_array($controller = $request->attributes->get('_controller'))) { + $controller = $controller[0].'::'.$controller[1]; + } + + if ('\\' === $controller[0]) { + $controller = ltrim($controller, '\\'); + } + + if (!$this->container->has($controller)) { + $i = strrpos($controller, ':'); + $controller = substr($controller, 0, $i).strtolower(substr($controller, $i)); + } + + $what = sprintf('argument $%s of "%s()"', $argument->getName(), $controller); + $message = sprintf('Could not resolve %s, maybe you forgot to register the controller as a service or missed tagging it with the "controller.service_arguments"?', $what); + + throw new RuntimeException($message); + } +} diff --git a/vendor/symfony/http-kernel/Controller/ArgumentResolver/ServiceValueResolver.php b/vendor/symfony/http-kernel/Controller/ArgumentResolver/ServiceValueResolver.php index c55564c0467efeb748b40679b2a651c1cbc4a958..e7df546b6680bbbf75c6b7a59ee09cfc7911f400 100644 --- a/vendor/symfony/http-kernel/Controller/ArgumentResolver/ServiceValueResolver.php +++ b/vendor/symfony/http-kernel/Controller/ArgumentResolver/ServiceValueResolver.php @@ -12,6 +12,7 @@ namespace Symfony\Component\HttpKernel\Controller\ArgumentResolver; use Psr\Container\ContainerInterface; +use Symfony\Component\DependencyInjection\Exception\RuntimeException; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface; use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata; @@ -39,9 +40,19 @@ final class ServiceValueResolver implements ArgumentValueResolverInterface if (\is_array($controller) && \is_callable($controller, true) && \is_string($controller[0])) { $controller = $controller[0].'::'.$controller[1]; + } elseif (!\is_string($controller) || '' === $controller) { + return false; } - return \is_string($controller) && $this->container->has($controller) && $this->container->get($controller)->has($argument->getName()); + if ('\\' === $controller[0]) { + $controller = ltrim($controller, '\\'); + } + + if (!$this->container->has($controller) && false !== $i = strrpos($controller, ':')) { + $controller = substr($controller, 0, $i).strtolower(substr($controller, $i)); + } + + return $this->container->has($controller) && $this->container->get($controller)->has($argument->getName()); } /** @@ -53,6 +64,30 @@ final class ServiceValueResolver implements ArgumentValueResolverInterface $controller = $controller[0].'::'.$controller[1]; } - yield $this->container->get($controller)->get($argument->getName()); + if ('\\' === $controller[0]) { + $controller = ltrim($controller, '\\'); + } + + if (!$this->container->has($controller)) { + $i = strrpos($controller, ':'); + $controller = substr($controller, 0, $i).strtolower(substr($controller, $i)); + } + + try { + yield $this->container->get($controller)->get($argument->getName()); + } catch (RuntimeException $e) { + $what = sprintf('argument $%s of "%s()"', $argument->getName(), $controller); + $message = preg_replace('/service "\.service_locator\.[^"]++"/', $what, $e->getMessage()); + + if ($e->getMessage() === $message) { + $message = sprintf('Cannot resolve %s: %s', $what, $message); + } + + $r = new \ReflectionProperty($e, 'message'); + $r->setAccessible(true); + $r->setValue($e, $message); + + throw $e; + } } } diff --git a/vendor/symfony/http-kernel/Controller/ArgumentResolver/SessionValueResolver.php b/vendor/symfony/http-kernel/Controller/ArgumentResolver/SessionValueResolver.php index 9e656d281b309755722e7343b0c9dad780e13e4f..276d65461caa67584520eed7fbc8b3f64ec1b458 100644 --- a/vendor/symfony/http-kernel/Controller/ArgumentResolver/SessionValueResolver.php +++ b/vendor/symfony/http-kernel/Controller/ArgumentResolver/SessionValueResolver.php @@ -28,6 +28,10 @@ final class SessionValueResolver implements ArgumentValueResolverInterface */ public function supports(Request $request, ArgumentMetadata $argument) { + if (!$request->hasSession()) { + return false; + } + $type = $argument->getType(); if (SessionInterface::class !== $type && !is_subclass_of($type, SessionInterface::class)) { return false; diff --git a/vendor/symfony/http-kernel/Controller/ArgumentResolver/TraceableValueResolver.php b/vendor/symfony/http-kernel/Controller/ArgumentResolver/TraceableValueResolver.php new file mode 100644 index 0000000000000000000000000000000000000000..bde3c90c1a634e0a8f3a90abe39d014db63aff61 --- /dev/null +++ b/vendor/symfony/http-kernel/Controller/ArgumentResolver/TraceableValueResolver.php @@ -0,0 +1,62 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Controller\ArgumentResolver; + +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface; +use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata; +use Symfony\Component\Stopwatch\Stopwatch; + +/** + * Provides timing information via the stopwatch. + * + * @author Iltar van der Berg <kjarli@gmail.com> + */ +final class TraceableValueResolver implements ArgumentValueResolverInterface +{ + private $inner; + private $stopwatch; + + public function __construct(ArgumentValueResolverInterface $inner, Stopwatch $stopwatch) + { + $this->inner = $inner; + $this->stopwatch = $stopwatch; + } + + /** + * {@inheritdoc} + */ + public function supports(Request $request, ArgumentMetadata $argument): bool + { + $method = \get_class($this->inner).'::'.__FUNCTION__; + $this->stopwatch->start($method, 'controller.argument_value_resolver'); + + $return = $this->inner->supports($request, $argument); + + $this->stopwatch->stop($method); + + return $return; + } + + /** + * {@inheritdoc} + */ + public function resolve(Request $request, ArgumentMetadata $argument): iterable + { + $method = \get_class($this->inner).'::'.__FUNCTION__; + $this->stopwatch->start($method, 'controller.argument_value_resolver'); + + yield from $this->inner->resolve($request, $argument); + + $this->stopwatch->stop($method); + } +} diff --git a/vendor/symfony/http-kernel/Controller/ArgumentResolver/VariadicValueResolver.php b/vendor/symfony/http-kernel/Controller/ArgumentResolver/VariadicValueResolver.php index 56ae5f191c4d417f6245d81f4a388805078ae45e..7ee2d7af5cee25231e9a6c234aa1766c429e5ea7 100644 --- a/vendor/symfony/http-kernel/Controller/ArgumentResolver/VariadicValueResolver.php +++ b/vendor/symfony/http-kernel/Controller/ArgumentResolver/VariadicValueResolver.php @@ -37,8 +37,8 @@ final class VariadicValueResolver implements ArgumentValueResolverInterface { $values = $request->attributes->get($argument->getName()); - if (!is_array($values)) { - throw new \InvalidArgumentException(sprintf('The action argument "...$%1$s" is required to be an array, the request attribute "%1$s" contains a type of "%2$s" instead.', $argument->getName(), gettype($values))); + if (!\is_array($values)) { + throw new \InvalidArgumentException(sprintf('The action argument "...$%1$s" is required to be an array, the request attribute "%1$s" contains a type of "%2$s" instead.', $argument->getName(), \gettype($values))); } foreach ($values as $value) { diff --git a/vendor/symfony/http-kernel/Controller/ArgumentResolverInterface.php b/vendor/symfony/http-kernel/Controller/ArgumentResolverInterface.php index 5c512309662d7d57fb32d3490c8f65b01dfc652d..ba97775a90797860e61c4c3990edf6fd76fc05cd 100644 --- a/vendor/symfony/http-kernel/Controller/ArgumentResolverInterface.php +++ b/vendor/symfony/http-kernel/Controller/ArgumentResolverInterface.php @@ -24,7 +24,6 @@ interface ArgumentResolverInterface /** * Returns the arguments to pass to the controller. * - * @param Request $request * @param callable $controller * * @return array An array of arguments to pass to the controller diff --git a/vendor/symfony/http-kernel/Controller/ArgumentValueResolverInterface.php b/vendor/symfony/http-kernel/Controller/ArgumentValueResolverInterface.php index fd7b09ecf2ede87acfeab0b16be4dd84dc04e990..6b14ed5be32dea7d18a569c59ff966bc7a223fc6 100644 --- a/vendor/symfony/http-kernel/Controller/ArgumentValueResolverInterface.php +++ b/vendor/symfony/http-kernel/Controller/ArgumentValueResolverInterface.php @@ -24,9 +24,6 @@ interface ArgumentValueResolverInterface /** * Whether this resolver can resolve the value for the given ArgumentMetadata. * - * @param Request $request - * @param ArgumentMetadata $argument - * * @return bool */ public function supports(Request $request, ArgumentMetadata $argument); @@ -34,9 +31,6 @@ interface ArgumentValueResolverInterface /** * Returns the possible value(s). * - * @param Request $request - * @param ArgumentMetadata $argument - * * @return \Generator */ public function resolve(Request $request, ArgumentMetadata $argument); diff --git a/vendor/symfony/http-kernel/Controller/ContainerControllerResolver.php b/vendor/symfony/http-kernel/Controller/ContainerControllerResolver.php index 186583d7be966954e567b9bf1eb399ff0ae7a7f9..e1da17388d70134345f10f74d6668eade1d35c99 100644 --- a/vendor/symfony/http-kernel/Controller/ContainerControllerResolver.php +++ b/vendor/symfony/http-kernel/Controller/ContainerControllerResolver.php @@ -14,7 +14,6 @@ namespace Symfony\Component\HttpKernel\Controller; use Psr\Container\ContainerInterface; use Psr\Log\LoggerInterface; use Symfony\Component\DependencyInjection\Container; -use Symfony\Component\HttpFoundation\Request; /** * A controller resolver searching for a controller in a psr-11 container when using the "service:method" notation. @@ -33,58 +32,14 @@ class ContainerControllerResolver extends ControllerResolver parent::__construct($logger); } - /** - * {@inheritdoc} - */ - public function getController(Request $request) - { - $controller = parent::getController($request); - - if (is_array($controller) && isset($controller[0]) && is_string($controller[0]) && $this->container->has($controller[0])) { - $controller[0] = $this->instantiateController($controller[0]); - } - - return $controller; - } - - /** - * Returns a callable for the given controller. - * - * @param string $controller A Controller string - * - * @return mixed A PHP callable - * - * @throws \LogicException When the name could not be parsed - * @throws \InvalidArgumentException When the controller class does not exist - */ protected function createController($controller) { - if (false !== strpos($controller, '::')) { - return parent::createController($controller); - } - - $method = null; - if (1 == substr_count($controller, ':')) { - // controller in the "service:method" notation - list($controller, $method) = explode(':', $controller, 2); + if (1 === substr_count($controller, ':')) { + $controller = str_replace(':', '::', $controller); + // TODO deprecate this in 5.1 } - if (!$this->container->has($controller)) { - $this->throwExceptionIfControllerWasRemoved($controller); - - throw new \LogicException(sprintf('Controller not found: service "%s" does not exist.', $controller)); - } - - $service = $this->container->get($controller); - if (null !== $method) { - return array($service, $method); - } - - if (!method_exists($service, '__invoke')) { - throw new \LogicException(sprintf('Controller "%s" cannot be called without a method name. Did you forget an "__invoke" method?', $controller)); - } - - return $service; + return parent::createController($controller); } /** @@ -92,30 +47,30 @@ class ContainerControllerResolver extends ControllerResolver */ protected function instantiateController($class) { + $class = ltrim($class, '\\'); + if ($this->container->has($class)) { return $this->container->get($class); } try { return parent::instantiateController($class); - } catch (\ArgumentCountError $e) { - } catch (\ErrorException $e) { - } catch (\TypeError $e) { + } catch (\Error $e) { } $this->throwExceptionIfControllerWasRemoved($class, $e); - throw $e; + if ($e instanceof \ArgumentCountError) { + throw new \InvalidArgumentException(sprintf('Controller "%s" has required constructor arguments and does not exist in the container. Did you forget to define such a service?', $class), 0, $e); + } + + throw new \InvalidArgumentException(sprintf('Controller "%s" does neither exist as service nor as class', $class), 0, $e); } - /** - * @param string $controller - * @param \Exception|\Throwable|null $previous - */ - private function throwExceptionIfControllerWasRemoved($controller, $previous = null) + private function throwExceptionIfControllerWasRemoved(string $controller, \Throwable $previous) { if ($this->container instanceof Container && isset($this->container->getRemovedIds()[$controller])) { - throw new \LogicException(sprintf('Controller "%s" cannot be fetched from the container because it is private. Did you forget to tag the service with "controller.service_arguments"?', $controller), 0, $previous); + throw new \InvalidArgumentException(sprintf('Controller "%s" cannot be fetched from the container because it is private. Did you forget to tag the service with "controller.service_arguments"?', $controller), 0, $previous); } } } diff --git a/vendor/symfony/http-kernel/Controller/ControllerReference.php b/vendor/symfony/http-kernel/Controller/ControllerReference.php index fae4e7fa449bc572be27c602fd3d01ef4eb10f6e..b4fdadd21e122826dbbf79fcae83ac73f3c72882 100644 --- a/vendor/symfony/http-kernel/Controller/ControllerReference.php +++ b/vendor/symfony/http-kernel/Controller/ControllerReference.php @@ -27,15 +27,15 @@ use Symfony\Component\HttpKernel\Fragment\FragmentRendererInterface; class ControllerReference { public $controller; - public $attributes = array(); - public $query = array(); + public $attributes = []; + public $query = []; /** * @param string $controller The controller name * @param array $attributes An array of parameters to add to the Request attributes * @param array $query An array of parameters to add to the Request query string */ - public function __construct($controller, array $attributes = array(), array $query = array()) + public function __construct(string $controller, array $attributes = [], array $query = []) { $this->controller = $controller; $this->attributes = $attributes; diff --git a/vendor/symfony/http-kernel/Controller/ControllerResolver.php b/vendor/symfony/http-kernel/Controller/ControllerResolver.php index b9d9f9fa254d94e8c8b5a28f2840e453691500db..7291c25da72800a11b78497fc44490373fd74164 100644 --- a/vendor/symfony/http-kernel/Controller/ControllerResolver.php +++ b/vendor/symfony/http-kernel/Controller/ControllerResolver.php @@ -16,44 +16,22 @@ use Symfony\Component\HttpFoundation\Request; /** * This implementation uses the '_controller' request attribute to determine - * the controller to execute and uses the request attributes to determine - * the controller method arguments. + * the controller to execute. * * @author Fabien Potencier <fabien@symfony.com> + * @author Tobias Schultze <http://tobion.de> */ -class ControllerResolver implements ArgumentResolverInterface, ControllerResolverInterface +class ControllerResolver implements ControllerResolverInterface { private $logger; - /** - * If the ...$arg functionality is available. - * - * Requires at least PHP 5.6.0 or HHVM 3.9.1 - * - * @var bool - */ - private $supportsVariadic; - - /** - * If scalar types exists. - * - * @var bool - */ - private $supportsScalarTypes; - public function __construct(LoggerInterface $logger = null) { $this->logger = $logger; - - $this->supportsVariadic = method_exists('ReflectionParameter', 'isVariadic'); - $this->supportsScalarTypes = method_exists('ReflectionParameter', 'getType'); } /** * {@inheritdoc} - * - * This method looks for a '_controller' request attribute that represents - * the controller name (a string like ClassName::MethodName). */ public function getController(Request $request) { @@ -65,98 +43,56 @@ class ControllerResolver implements ArgumentResolverInterface, ControllerResolve return false; } - if (is_array($controller)) { - return $controller; - } + if (\is_array($controller)) { + if (isset($controller[0]) && \is_string($controller[0]) && isset($controller[1])) { + try { + $controller[0] = $this->instantiateController($controller[0]); + } catch (\Error | \LogicException $e) { + try { + // We cannot just check is_callable but have to use reflection because a non-static method + // can still be called statically in PHP but we don't want that. This is deprecated in PHP 7, so we + // could simplify this with PHP 8. + if ((new \ReflectionMethod($controller[0], $controller[1]))->isStatic()) { + return $controller; + } + } catch (\ReflectionException $reflectionException) { + throw $e; + } + + throw $e; + } + } - if (is_object($controller)) { - if (method_exists($controller, '__invoke')) { - return $controller; + if (!\is_callable($controller)) { + throw new \InvalidArgumentException(sprintf('The controller for URI "%s" is not callable. %s', $request->getPathInfo(), $this->getControllerError($controller))); } - throw new \InvalidArgumentException(sprintf('Controller "%s" for URI "%s" is not callable.', get_class($controller), $request->getPathInfo())); + return $controller; } - if (false === strpos($controller, ':')) { - if (method_exists($controller, '__invoke')) { - return $this->instantiateController($controller); - } elseif (function_exists($controller)) { - return $controller; + if (\is_object($controller)) { + if (!\is_callable($controller)) { + throw new \InvalidArgumentException(sprintf('The controller for URI "%s" is not callable. %s', $request->getPathInfo(), $this->getControllerError($controller))); } - } - - $callable = $this->createController($controller); - if (!is_callable($callable)) { - throw new \InvalidArgumentException(sprintf('The controller for URI "%s" is not callable. %s', $request->getPathInfo(), $this->getControllerError($callable))); + return $controller; } - return $callable; - } - - /** - * {@inheritdoc} - * - * @deprecated This method is deprecated as of 3.1 and will be removed in 4.0. Implement the ArgumentResolverInterface and inject it in the HttpKernel instead. - */ - public function getArguments(Request $request, $controller) - { - @trigger_error(sprintf('%s is deprecated as of 3.1 and will be removed in 4.0. Implement the %s and inject it in the HttpKernel instead.', __METHOD__, ArgumentResolverInterface::class), E_USER_DEPRECATED); - - if (is_array($controller)) { - $r = new \ReflectionMethod($controller[0], $controller[1]); - } elseif (is_object($controller) && !$controller instanceof \Closure) { - $r = new \ReflectionObject($controller); - $r = $r->getMethod('__invoke'); - } else { - $r = new \ReflectionFunction($controller); + if (\function_exists($controller)) { + return $controller; } - return $this->doGetArguments($request, $controller, $r->getParameters()); - } - - /** - * @param Request $request - * @param callable $controller - * @param \ReflectionParameter[] $parameters - * - * @return array The arguments to use when calling the action - * - * @deprecated This method is deprecated as of 3.1 and will be removed in 4.0. Implement the ArgumentResolverInterface and inject it in the HttpKernel instead. - */ - protected function doGetArguments(Request $request, $controller, array $parameters) - { - @trigger_error(sprintf('%s is deprecated as of 3.1 and will be removed in 4.0. Implement the %s and inject it in the HttpKernel instead.', __METHOD__, ArgumentResolverInterface::class), E_USER_DEPRECATED); - - $attributes = $request->attributes->all(); - $arguments = array(); - foreach ($parameters as $param) { - if (array_key_exists($param->name, $attributes)) { - if ($this->supportsVariadic && $param->isVariadic() && is_array($attributes[$param->name])) { - $arguments = array_merge($arguments, array_values($attributes[$param->name])); - } else { - $arguments[] = $attributes[$param->name]; - } - } elseif ($param->getClass() && $param->getClass()->isInstance($request)) { - $arguments[] = $request; - } elseif ($param->isDefaultValueAvailable()) { - $arguments[] = $param->getDefaultValue(); - } elseif ($this->supportsScalarTypes && $param->hasType() && $param->allowsNull()) { - $arguments[] = null; - } else { - if (is_array($controller)) { - $repr = sprintf('%s::%s()', get_class($controller[0]), $controller[1]); - } elseif (is_object($controller)) { - $repr = get_class($controller); - } else { - $repr = $controller; - } + try { + $callable = $this->createController($controller); + } catch (\InvalidArgumentException $e) { + throw new \InvalidArgumentException(sprintf('The controller for URI "%s" is not callable. %s', $request->getPathInfo(), $e->getMessage())); + } - throw new \RuntimeException(sprintf('Controller "%s" requires that you provide a value for the "$%s" argument (because there is no default value or because there is a non optional argument after this one).', $repr, $param->name)); - } + if (!\is_callable($callable)) { + throw new \InvalidArgumentException(sprintf('The controller for URI "%s" is not callable. %s', $request->getPathInfo(), $this->getControllerError($callable))); } - return $arguments; + return $callable; } /** @@ -166,21 +102,41 @@ class ControllerResolver implements ArgumentResolverInterface, ControllerResolve * * @return callable A PHP callable * - * @throws \InvalidArgumentException + * @throws \InvalidArgumentException When the controller cannot be created */ protected function createController($controller) { if (false === strpos($controller, '::')) { - throw new \InvalidArgumentException(sprintf('Unable to find controller "%s".', $controller)); + $controller = $this->instantiateController($controller); + + if (!\is_callable($controller)) { + throw new \InvalidArgumentException($this->getControllerError($controller)); + } + + return $controller; } list($class, $method) = explode('::', $controller, 2); - if (!class_exists($class)) { - throw new \InvalidArgumentException(sprintf('Class "%s" does not exist.', $class)); + try { + $controller = [$this->instantiateController($class), $method]; + } catch (\Error | \LogicException $e) { + try { + if ((new \ReflectionMethod($class, $method))->isStatic()) { + return $class.'::'.$method; + } + } catch (\ReflectionException $reflectionException) { + throw $e; + } + + throw $e; } - return array($this->instantiateController($class), $method); + if (!\is_callable($controller)) { + throw new \InvalidArgumentException($this->getControllerError($controller)); + } + + return $controller; } /** @@ -197,48 +153,49 @@ class ControllerResolver implements ArgumentResolverInterface, ControllerResolve private function getControllerError($callable) { - if (is_string($callable)) { + if (\is_string($callable)) { if (false !== strpos($callable, '::')) { - $callable = explode('::', $callable); + $callable = explode('::', $callable, 2); + } else { + return sprintf('Function "%s" does not exist.', $callable); } + } - if (class_exists($callable) && !method_exists($callable, '__invoke')) { - return sprintf('Class "%s" does not have a method "__invoke".', $callable); - } + if (\is_object($callable)) { + $availableMethods = $this->getClassMethodsWithoutMagicMethods($callable); + $alternativeMsg = $availableMethods ? sprintf(' or use one of the available methods: "%s"', implode('", "', $availableMethods)) : ''; - if (!function_exists($callable)) { - return sprintf('Function "%s" does not exist.', $callable); - } + return sprintf('Controller class "%s" cannot be called without a method name. You need to implement "__invoke"%s.', \get_class($callable), $alternativeMsg); } - if (!is_array($callable)) { - return sprintf('Invalid type for controller given, expected string or array, got "%s".', gettype($callable)); + if (!\is_array($callable)) { + return sprintf('Invalid type for controller given, expected string, array or object, got "%s".', \gettype($callable)); } - if (2 !== count($callable)) { - return 'Invalid format for controller, expected array(controller, method) or controller::method.'; + if (!isset($callable[0]) || !isset($callable[1]) || 2 !== \count($callable)) { + return 'Invalid array callable, expected [controller, method].'; } list($controller, $method) = $callable; - if (is_string($controller) && !class_exists($controller)) { + if (\is_string($controller) && !class_exists($controller)) { return sprintf('Class "%s" does not exist.', $controller); } - $className = is_object($controller) ? get_class($controller) : $controller; + $className = \is_object($controller) ? \get_class($controller) : $controller; if (method_exists($controller, $method)) { return sprintf('Method "%s" on class "%s" should be public and non-abstract.', $method, $className); } - $collection = get_class_methods($controller); + $collection = $this->getClassMethodsWithoutMagicMethods($controller); - $alternatives = array(); + $alternatives = []; foreach ($collection as $item) { $lev = levenshtein($method, $item); - if ($lev <= strlen($method) / 3 || false !== strpos($item, $method)) { + if ($lev <= \strlen($method) / 3 || false !== strpos($item, $method)) { $alternatives[] = $item; } } @@ -247,7 +204,7 @@ class ControllerResolver implements ArgumentResolverInterface, ControllerResolve $message = sprintf('Expected method "%s" on class "%s"', $method, $className); - if (count($alternatives) > 0) { + if (\count($alternatives) > 0) { $message .= sprintf(', did you mean "%s"?', implode('", "', $alternatives)); } else { $message .= sprintf('. Available methods: "%s".', implode('", "', $collection)); @@ -255,4 +212,13 @@ class ControllerResolver implements ArgumentResolverInterface, ControllerResolve return $message; } + + private function getClassMethodsWithoutMagicMethods($classOrObject) + { + $methods = get_class_methods($classOrObject); + + return array_filter($methods, function (string $method) { + return 0 !== strncmp($method, '__', 2); + }); + } } diff --git a/vendor/symfony/http-kernel/Controller/ControllerResolverInterface.php b/vendor/symfony/http-kernel/Controller/ControllerResolverInterface.php index afe9fb733748f3d35ab4fb56d0835c7b69859569..8b70a88f63dc8e8f4f650d0466f00da0987090a1 100644 --- a/vendor/symfony/http-kernel/Controller/ControllerResolverInterface.php +++ b/vendor/symfony/http-kernel/Controller/ControllerResolverInterface.php @@ -17,8 +17,6 @@ use Symfony\Component\HttpFoundation\Request; * A ControllerResolverInterface implementation knows how to determine the * controller to execute based on a Request object. * - * It can also determine the arguments to pass to the Controller. - * * A Controller can be any valid PHP callable. * * @author Fabien Potencier <fabien@symfony.com> @@ -31,27 +29,13 @@ interface ControllerResolverInterface * As several resolvers can exist for a single application, a resolver must * return false when it is not able to determine the controller. * - * The resolver must only throw an exception when it should be able to load + * The resolver must only throw an exception when it should be able to load a * controller but cannot because of some errors made by the developer. * * @return callable|false A PHP callable representing the Controller, * or false if this resolver is not able to determine the controller * - * @throws \LogicException If the controller can't be found + * @throws \LogicException If a controller was found based on the request but it is not callable */ public function getController(Request $request); - - /** - * Returns the arguments to pass to the controller. - * - * @param Request $request A Request instance - * @param callable $controller A PHP callable - * - * @return array An array of arguments to pass to the controller - * - * @throws \RuntimeException When value for argument given is not provided - * - * @deprecated This method is deprecated as of 3.1 and will be removed in 4.0. Please use the {@see ArgumentResolverInterface} instead. - */ - public function getArguments(Request $request, $controller); } diff --git a/vendor/symfony/http-kernel/Controller/TraceableArgumentResolver.php b/vendor/symfony/http-kernel/Controller/TraceableArgumentResolver.php index 6fb0fa66aca7ae906fc6b8c3688c7936526ed030..39848127b76cfe2d32052118aaf3d0bbb043f65c 100644 --- a/vendor/symfony/http-kernel/Controller/TraceableArgumentResolver.php +++ b/vendor/symfony/http-kernel/Controller/TraceableArgumentResolver.php @@ -11,8 +11,8 @@ namespace Symfony\Component\HttpKernel\Controller; -use Symfony\Component\Stopwatch\Stopwatch; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\Stopwatch\Stopwatch; /** * @author Fabien Potencier <fabien@symfony.com> diff --git a/vendor/symfony/http-kernel/Controller/TraceableControllerResolver.php b/vendor/symfony/http-kernel/Controller/TraceableControllerResolver.php index 750107714026dff7d88b682a5b4d939df4a1625a..bf6b6aa1f2f8cb598832b2c61b85313b3c80970c 100644 --- a/vendor/symfony/http-kernel/Controller/TraceableControllerResolver.php +++ b/vendor/symfony/http-kernel/Controller/TraceableControllerResolver.php @@ -11,32 +11,21 @@ namespace Symfony\Component\HttpKernel\Controller; -use Symfony\Component\Stopwatch\Stopwatch; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\Stopwatch\Stopwatch; /** * @author Fabien Potencier <fabien@symfony.com> */ -class TraceableControllerResolver implements ControllerResolverInterface, ArgumentResolverInterface +class TraceableControllerResolver implements ControllerResolverInterface { private $resolver; private $stopwatch; - private $argumentResolver; - public function __construct(ControllerResolverInterface $resolver, Stopwatch $stopwatch, ArgumentResolverInterface $argumentResolver = null) + public function __construct(ControllerResolverInterface $resolver, Stopwatch $stopwatch) { $this->resolver = $resolver; $this->stopwatch = $stopwatch; - $this->argumentResolver = $argumentResolver; - - // BC - if (null === $this->argumentResolver) { - $this->argumentResolver = $resolver; - } - - if (!$this->argumentResolver instanceof TraceableArgumentResolver) { - $this->argumentResolver = new TraceableArgumentResolver($this->argumentResolver, $this->stopwatch); - } } /** @@ -52,18 +41,4 @@ class TraceableControllerResolver implements ControllerResolverInterface, Argume return $ret; } - - /** - * {@inheritdoc} - * - * @deprecated This method is deprecated as of 3.1 and will be removed in 4.0. - */ - public function getArguments(Request $request, $controller) - { - @trigger_error(sprintf('The %s method is deprecated as of 3.1 and will be removed in 4.0. Please use the %s instead.', __METHOD__, TraceableArgumentResolver::class), E_USER_DEPRECATED); - - $ret = $this->argumentResolver->getArguments($request, $controller); - - return $ret; - } } diff --git a/vendor/symfony/http-kernel/ControllerMetadata/ArgumentMetadata.php b/vendor/symfony/http-kernel/ControllerMetadata/ArgumentMetadata.php index 32316a8d519e70d9ca676d985dec51019b4af4c2..e73b848e60025ad48f8b8164dbad5148cb6735fc 100644 --- a/vendor/symfony/http-kernel/ControllerMetadata/ArgumentMetadata.php +++ b/vendor/symfony/http-kernel/ControllerMetadata/ArgumentMetadata.php @@ -25,15 +25,7 @@ class ArgumentMetadata private $defaultValue; private $isNullable; - /** - * @param string $name - * @param string $type - * @param bool $isVariadic - * @param bool $hasDefaultValue - * @param mixed $defaultValue - * @param bool $isNullable - */ - public function __construct($name, $type, $isVariadic, $hasDefaultValue, $defaultValue, $isNullable = false) + public function __construct(string $name, ?string $type, bool $isVariadic, bool $hasDefaultValue, $defaultValue, bool $isNullable = false) { $this->name = $name; $this->type = $type; @@ -58,7 +50,7 @@ class ArgumentMetadata * * The type is the PHP class in 5.5+ and additionally the basic type in PHP 7.0+. * - * @return string + * @return string|null */ public function getType() { diff --git a/vendor/symfony/http-kernel/ControllerMetadata/ArgumentMetadataFactory.php b/vendor/symfony/http-kernel/ControllerMetadata/ArgumentMetadataFactory.php index d1e7af206804b9d92e1b04edbe1a88812ffc5e86..44fe4779458b114931ae01111da0566770421a95 100644 --- a/vendor/symfony/http-kernel/ControllerMetadata/ArgumentMetadataFactory.php +++ b/vendor/symfony/http-kernel/ControllerMetadata/ArgumentMetadataFactory.php @@ -18,112 +18,52 @@ namespace Symfony\Component\HttpKernel\ControllerMetadata; */ final class ArgumentMetadataFactory implements ArgumentMetadataFactoryInterface { - /** - * If the ...$arg functionality is available. - * - * Requires at least PHP 5.6.0 or HHVM 3.9.1 - * - * @var bool - */ - private $supportsVariadic; - - /** - * If the reflection supports the getType() method to resolve types. - * - * Requires at least PHP 7.0.0 or HHVM 3.11.0 - * - * @var bool - */ - private $supportsParameterType; - - public function __construct() - { - $this->supportsVariadic = method_exists('ReflectionParameter', 'isVariadic'); - $this->supportsParameterType = method_exists('ReflectionParameter', 'getType'); - } - /** * {@inheritdoc} */ public function createArgumentMetadata($controller) { - $arguments = array(); + $arguments = []; - if (is_array($controller)) { + if (\is_array($controller)) { $reflection = new \ReflectionMethod($controller[0], $controller[1]); - } elseif (is_object($controller) && !$controller instanceof \Closure) { + } elseif (\is_object($controller) && !$controller instanceof \Closure) { $reflection = (new \ReflectionObject($controller))->getMethod('__invoke'); } else { $reflection = new \ReflectionFunction($controller); } foreach ($reflection->getParameters() as $param) { - $arguments[] = new ArgumentMetadata($param->getName(), $this->getType($param), $this->isVariadic($param), $this->hasDefaultValue($param), $this->getDefaultValue($param), $param->allowsNull()); + $arguments[] = new ArgumentMetadata($param->getName(), $this->getType($param, $reflection), $param->isVariadic(), $param->isDefaultValueAvailable(), $param->isDefaultValueAvailable() ? $param->getDefaultValue() : null, $param->allowsNull()); } return $arguments; } - /** - * Returns whether an argument is variadic. - * - * @param \ReflectionParameter $parameter - * - * @return bool - */ - private function isVariadic(\ReflectionParameter $parameter) - { - return $this->supportsVariadic && $parameter->isVariadic(); - } - - /** - * Determines whether an argument has a default value. - * - * @param \ReflectionParameter $parameter - * - * @return bool - */ - private function hasDefaultValue(\ReflectionParameter $parameter) - { - return $parameter->isDefaultValueAvailable(); - } - - /** - * Returns a default value if available. - * - * @param \ReflectionParameter $parameter - * - * @return mixed|null - */ - private function getDefaultValue(\ReflectionParameter $parameter) - { - return $this->hasDefaultValue($parameter) ? $parameter->getDefaultValue() : null; - } - /** * Returns an associated type to the given parameter if available. - * - * @param \ReflectionParameter $parameter - * - * @return null|string */ - private function getType(\ReflectionParameter $parameter) + private function getType(\ReflectionParameter $parameter, \ReflectionFunctionAbstract $function): ?string { - if ($this->supportsParameterType) { - if (!$type = $parameter->getType()) { - return; - } - $typeName = $type instanceof \ReflectionNamedType ? $type->getName() : $type->__toString(); - if ('array' === $typeName && !$type->isBuiltin()) { - // Special case for HHVM with variadics - return; - } - - return $typeName; + if (!$type = $parameter->getType()) { + return null; } + $name = $type->getName(); + $lcName = strtolower($name); - if (preg_match('/^(?:[^ ]++ ){4}([a-zA-Z_\x7F-\xFF][^ ]++)/', $parameter, $info)) { - return $info[1]; + if ('self' !== $lcName && 'parent' !== $lcName) { + return $name; + } + if (!$function instanceof \ReflectionMethod) { + return null; } + if ('self' === $lcName) { + return $function->getDeclaringClass()->name; + } + if ($parent = $function->getDeclaringClass()->getParentClass()) { + return $parent->name; + } + + return null; } } diff --git a/vendor/symfony/http-kernel/DataCollector/ConfigDataCollector.php b/vendor/symfony/http-kernel/DataCollector/ConfigDataCollector.php index 5675f073639a6a1f9586ea7dd90dbbbb87025348..7000e70d5c8794dbf67a8e53598d230222f718e7 100644 --- a/vendor/symfony/http-kernel/DataCollector/ConfigDataCollector.php +++ b/vendor/symfony/http-kernel/DataCollector/ConfigDataCollector.php @@ -11,10 +11,10 @@ namespace Symfony\Component\HttpKernel\DataCollector; -use Symfony\Component\HttpKernel\KernelInterface; -use Symfony\Component\HttpKernel\Kernel; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpKernel\Kernel; +use Symfony\Component\HttpKernel\KernelInterface; use Symfony\Component\VarDumper\Caster\LinkStub; /** @@ -30,12 +30,15 @@ class ConfigDataCollector extends DataCollector implements LateDataCollectorInte private $version; private $hasVarDumper; - /** - * @param string $name The name of the application using the web profiler - * @param string $version The version of the application using the web profiler - */ - public function __construct($name = null, $version = null) + public function __construct(string $name = null, string $version = null) { + if (1 <= \func_num_args()) { + @trigger_error(sprintf('The "$name" argument in method "%s()" is deprecated since Symfony 4.2.', __METHOD__), E_USER_DEPRECATED); + } + if (2 <= \func_num_args()) { + @trigger_error(sprintf('The "$version" argument in method "%s()" is deprecated since Symfony 4.2.', __METHOD__), E_USER_DEPRECATED); + } + $this->name = $name; $this->version = $version; $this->hasVarDumper = class_exists(LinkStub::class); @@ -54,25 +57,24 @@ class ConfigDataCollector extends DataCollector implements LateDataCollectorInte */ public function collect(Request $request, Response $response, \Exception $exception = null) { - $this->data = array( + $this->data = [ 'app_name' => $this->name, 'app_version' => $this->version, 'token' => $response->headers->get('X-Debug-Token'), 'symfony_version' => Kernel::VERSION, 'symfony_state' => 'unknown', - 'name' => isset($this->kernel) ? $this->kernel->getName() : 'n/a', 'env' => isset($this->kernel) ? $this->kernel->getEnvironment() : 'n/a', 'debug' => isset($this->kernel) ? $this->kernel->isDebug() : 'n/a', 'php_version' => PHP_VERSION, 'php_architecture' => PHP_INT_SIZE * 8, 'php_intl_locale' => class_exists('Locale', false) && \Locale::getDefault() ? \Locale::getDefault() : 'n/a', 'php_timezone' => date_default_timezone_get(), - 'xdebug_enabled' => extension_loaded('xdebug'), - 'apcu_enabled' => extension_loaded('apcu') && ini_get('apc.enabled'), - 'zend_opcache_enabled' => extension_loaded('Zend OPcache') && ini_get('opcache.enable'), - 'bundles' => array(), - 'sapi_name' => PHP_SAPI, - ); + 'xdebug_enabled' => \extension_loaded('xdebug'), + 'apcu_enabled' => \extension_loaded('apcu') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN), + 'zend_opcache_enabled' => \extension_loaded('Zend OPcache') && filter_var(ini_get('opcache.enable'), FILTER_VALIDATE_BOOLEAN), + 'bundles' => [], + 'sapi_name' => \PHP_SAPI, + ]; if (isset($this->kernel)) { foreach ($this->kernel->getBundles() as $name => $bundle) { @@ -98,7 +100,7 @@ class ConfigDataCollector extends DataCollector implements LateDataCollectorInte */ public function reset() { - $this->data = array(); + $this->data = []; } public function lateCollect() @@ -106,20 +108,30 @@ class ConfigDataCollector extends DataCollector implements LateDataCollectorInte $this->data = $this->cloneVar($this->data); } + /** + * @deprecated since Symfony 4.2 + */ public function getApplicationName() { + @trigger_error(sprintf('The method "%s()" is deprecated since Symfony 4.2.', __METHOD__), E_USER_DEPRECATED); + return $this->data['app_name']; } + /** + * @deprecated since Symfony 4.2 + */ public function getApplicationVersion() { + @trigger_error(sprintf('The method "%s()" is deprecated since Symfony 4.2.', __METHOD__), E_USER_DEPRECATED); + return $this->data['app_version']; } /** * Gets the token. * - * @return string The token + * @return string|null The token */ public function getToken() { @@ -227,10 +239,14 @@ class ConfigDataCollector extends DataCollector implements LateDataCollectorInte * Gets the application name. * * @return string The application name + * + * @deprecated since Symfony 4.2 */ public function getAppName() { - return $this->data['name']; + @trigger_error(sprintf('The "%s()" method is deprecated since Symfony 4.2.', __METHOD__), E_USER_DEPRECATED); + + return 'n/a'; } /** diff --git a/vendor/symfony/http-kernel/DataCollector/DataCollector.php b/vendor/symfony/http-kernel/DataCollector/DataCollector.php index 30887ab91c727ac12f946696a17a95804039c8e7..52ab90c669277fdf203c360261e8e300474c0f36 100644 --- a/vendor/symfony/http-kernel/DataCollector/DataCollector.php +++ b/vendor/symfony/http-kernel/DataCollector/DataCollector.php @@ -11,8 +11,8 @@ namespace Symfony\Component\HttpKernel\DataCollector; -use Symfony\Component\HttpKernel\DataCollector\Util\ValueExporter; use Symfony\Component\VarDumper\Caster\CutStub; +use Symfony\Component\VarDumper\Caster\ReflectionCaster; use Symfony\Component\VarDumper\Cloner\ClonerInterface; use Symfony\Component\VarDumper\Cloner\Data; use Symfony\Component\VarDumper\Cloner\Stub; @@ -26,28 +26,39 @@ use Symfony\Component\VarDumper\Cloner\VarCloner; * @author Fabien Potencier <fabien@symfony.com> * @author Bernhard Schussek <bschussek@symfony.com> */ -abstract class DataCollector implements DataCollectorInterface, \Serializable +abstract class DataCollector implements DataCollectorInterface { - protected $data = array(); - /** - * @var ValueExporter + * @var array|Data */ - private $valueExporter; + protected $data = []; /** * @var ClonerInterface */ private $cloner; + /** + * @deprecated since Symfony 4.3, store all the serialized state in the data property instead + */ public function serialize() { - return serialize($this->data); + @trigger_error(sprintf('The "%s" method is deprecated since Symfony 4.3, store all the serialized state in the data property instead.', __METHOD__), E_USER_DEPRECATED); + + $trace = debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT, 2); + $isCalledFromOverridingMethod = isset($trace[1]['function'], $trace[1]['object']) && 'serialize' === $trace[1]['function'] && $this === $trace[1]['object']; + + return $isCalledFromOverridingMethod ? $this->data : serialize($this->data); } + /** + * @deprecated since Symfony 4.3, store all the serialized state in the data property instead + */ public function unserialize($data) { - $this->data = unserialize($data); + @trigger_error(sprintf('The "%s" method is deprecated since Symfony 4.3, store all the serialized state in the data property instead.', __METHOD__), E_USER_DEPRECATED); + + $this->data = \is_array($data) ? $data : unserialize($data); } /** @@ -66,56 +77,27 @@ abstract class DataCollector implements DataCollectorInterface, \Serializable return $var; } if (null === $this->cloner) { - if (class_exists(CutStub::class)) { - $this->cloner = new VarCloner(); - $this->cloner->setMaxItems(-1); - $this->cloner->addCasters($this->getCasters()); - } else { - @trigger_error(sprintf('Using the %s() method without the VarDumper component is deprecated since Symfony 3.2 and won\'t be supported in 4.0. Install symfony/var-dumper version 3.2 or above.', __METHOD__), E_USER_DEPRECATED); - $this->cloner = false; + if (!class_exists(CutStub::class)) { + throw new \LogicException(sprintf('The VarDumper component is needed for the %s() method. Install symfony/var-dumper version 3.4 or above.', __METHOD__)); } - } - if (false === $this->cloner) { - if (null === $this->valueExporter) { - $this->valueExporter = new ValueExporter(); - } - - return $this->valueExporter->exportValue($var); + $this->cloner = new VarCloner(); + $this->cloner->setMaxItems(-1); + $this->cloner->addCasters($this->getCasters()); } return $this->cloner->cloneVar($var); } - /** - * Converts a PHP variable to a string. - * - * @param mixed $var A PHP variable - * - * @return string The string representation of the variable - * - * @deprecated since version 3.2, to be removed in 4.0. Use cloneVar() instead. - */ - protected function varToString($var) - { - @trigger_error(sprintf('The %s() method is deprecated since Symfony 3.2 and will be removed in 4.0. Use cloneVar() instead.', __METHOD__), E_USER_DEPRECATED); - - if (null === $this->valueExporter) { - $this->valueExporter = new ValueExporter(); - } - - return $this->valueExporter->exportValue($var); - } - /** * @return callable[] The casters to add to the cloner */ protected function getCasters() { - return array( + $casters = [ '*' => function ($v, array $a, Stub $s, $isNested) { if (!$v instanceof Stub) { foreach ($a as $k => $v) { - if (is_object($v) && !$v instanceof \DateTimeInterface && !$v instanceof Stub) { + if (\is_object($v) && !$v instanceof \DateTimeInterface && !$v instanceof Stub) { $a[$k] = new CutStub($v); } } @@ -123,6 +105,30 @@ abstract class DataCollector implements DataCollectorInterface, \Serializable return $a; }, - ); + ]; + + if (method_exists(ReflectionCaster::class, 'unsetClosureFileInfo')) { + $casters += ReflectionCaster::UNSET_CLOSURE_FILE_INFO; + } + + return $casters; + } + + public function __sleep() + { + if (__CLASS__ !== $c = (new \ReflectionMethod($this, 'serialize'))->getDeclaringClass()->name) { + @trigger_error(sprintf('Implementing the "%s::serialize()" method is deprecated since Symfony 4.3, store all the serialized state in the "data" property instead.', $c), E_USER_DEPRECATED); + $this->data = $this->serialize(); + } + + return ['data']; + } + + public function __wakeup() + { + if (__CLASS__ !== $c = (new \ReflectionMethod($this, 'unserialize'))->getDeclaringClass()->name) { + @trigger_error(sprintf('Implementing the "%s::unserialize()" method is deprecated since Symfony 4.3, store all the serialized state in the "data" property instead.', $c), E_USER_DEPRECATED); + $this->unserialize($this->data); + } } } diff --git a/vendor/symfony/http-kernel/DataCollector/DataCollectorInterface.php b/vendor/symfony/http-kernel/DataCollector/DataCollectorInterface.php index 2470089b810b2271cf47fe95529df8f5d95d1fe1..b9584110ecb7148f6a90096751446ed167e566fa 100644 --- a/vendor/symfony/http-kernel/DataCollector/DataCollectorInterface.php +++ b/vendor/symfony/http-kernel/DataCollector/DataCollectorInterface.php @@ -13,15 +13,14 @@ namespace Symfony\Component\HttpKernel\DataCollector; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Contracts\Service\ResetInterface; /** * DataCollectorInterface. * * @author Fabien Potencier <fabien@symfony.com> - * - * @method reset() Resets this data collector to its initial state. */ -interface DataCollectorInterface +interface DataCollectorInterface extends ResetInterface { /** * Collects data for the given Request and Response. diff --git a/vendor/symfony/http-kernel/DataCollector/DumpDataCollector.php b/vendor/symfony/http-kernel/DataCollector/DumpDataCollector.php index d0ca671e056b4d441ac5fae097d43b75562f07d5..577eb2ca2e4555c750e00387cd5d146c7e49eb86 100644 --- a/vendor/symfony/http-kernel/DataCollector/DumpDataCollector.php +++ b/vendor/symfony/http-kernel/DataCollector/DumpDataCollector.php @@ -18,12 +18,15 @@ use Symfony\Component\Stopwatch\Stopwatch; use Symfony\Component\VarDumper\Cloner\Data; use Symfony\Component\VarDumper\Cloner\VarCloner; use Symfony\Component\VarDumper\Dumper\CliDumper; -use Symfony\Component\VarDumper\Dumper\HtmlDumper; +use Symfony\Component\VarDumper\Dumper\ContextProvider\SourceContextProvider; use Symfony\Component\VarDumper\Dumper\DataDumperInterface; -use Twig\Template; +use Symfony\Component\VarDumper\Dumper\HtmlDumper; +use Symfony\Component\VarDumper\Server\Connection; /** * @author Nicolas Grekas <p@tchwork.com> + * + * @final since Symfony 4.3 */ class DumpDataCollector extends DataCollector implements DataDumperInterface { @@ -37,24 +40,28 @@ class DumpDataCollector extends DataCollector implements DataDumperInterface private $charset; private $requestStack; private $dumper; - private $dumperIsInjected; + private $sourceContextProvider; - public function __construct(Stopwatch $stopwatch = null, $fileLinkFormat = null, $charset = null, RequestStack $requestStack = null, DataDumperInterface $dumper = null) + /** + * @param DataDumperInterface|Connection|null $dumper + */ + public function __construct(Stopwatch $stopwatch = null, $fileLinkFormat = null, string $charset = null, RequestStack $requestStack = null, $dumper = null) { $this->stopwatch = $stopwatch; $this->fileLinkFormat = $fileLinkFormat ?: ini_get('xdebug.file_link_format') ?: get_cfg_var('xdebug.file_link_format'); $this->charset = $charset ?: ini_get('php.output_encoding') ?: ini_get('default_charset') ?: 'UTF-8'; $this->requestStack = $requestStack; $this->dumper = $dumper; - $this->dumperIsInjected = null !== $dumper; // All clones share these properties by reference: - $this->rootRefs = array( + $this->rootRefs = [ &$this->data, &$this->dataCount, &$this->isCollected, &$this->clonesCount, - ); + ]; + + $this->sourceContextProvider = $dumper instanceof Connection && isset($dumper->getContextProviders()['source']) ? $dumper->getContextProviders()['source'] : new SourceContextProvider($this->charset); } public function __clone() @@ -67,67 +74,22 @@ class DumpDataCollector extends DataCollector implements DataDumperInterface if ($this->stopwatch) { $this->stopwatch->start('dump'); } - if ($this->isCollected) { - $this->isCollected = false; - } - $trace = debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT | DEBUG_BACKTRACE_IGNORE_ARGS, 7); - - $file = $trace[0]['file']; - $line = $trace[0]['line']; - $name = false; - $fileExcerpt = false; - - for ($i = 1; $i < 7; ++$i) { - if (isset($trace[$i]['class'], $trace[$i]['function']) - && 'dump' === $trace[$i]['function'] - && 'Symfony\Component\VarDumper\VarDumper' === $trace[$i]['class'] - ) { - $file = $trace[$i]['file']; - $line = $trace[$i]['line']; - - while (++$i < 7) { - if (isset($trace[$i]['function'], $trace[$i]['file']) && empty($trace[$i]['class']) && 0 !== strpos($trace[$i]['function'], 'call_user_func')) { - $file = $trace[$i]['file']; - $line = $trace[$i]['line']; - - break; - } elseif (isset($trace[$i]['object']) && $trace[$i]['object'] instanceof Template) { - $template = $trace[$i]['object']; - $name = $template->getTemplateName(); - $src = method_exists($template, 'getSourceContext') ? $template->getSourceContext()->getCode() : (method_exists($template, 'getSource') ? $template->getSource() : false); - $info = $template->getDebugInfo(); - if (isset($info[$trace[$i - 1]['line']])) { - $line = $info[$trace[$i - 1]['line']]; - $file = method_exists($template, 'getSourceContext') ? $template->getSourceContext()->getPath() : null; - - if ($src) { - $src = explode("\n", $src); - $fileExcerpt = array(); - - for ($i = max($line - 3, 1), $max = min($line + 3, count($src)); $i <= $max; ++$i) { - $fileExcerpt[] = '<li'.($i === $line ? ' class="selected"' : '').'><code>'.$this->htmlEncode($src[$i - 1]).'</code></li>'; - } - - $fileExcerpt = '<ol start="'.max($line - 3, 1).'">'.implode("\n", $fileExcerpt).'</ol>'; - } - } - break; - } - } - break; - } - } + list('name' => $name, 'file' => $file, 'line' => $line, 'file_excerpt' => $fileExcerpt) = $this->sourceContextProvider->getContext(); - if (false === $name) { - $name = str_replace('\\', '/', $file); - $name = substr($name, strrpos($name, '/') + 1); + if ($this->dumper instanceof Connection) { + if (!$this->dumper->write($data)) { + $this->isCollected = false; + } + } elseif ($this->dumper) { + $this->doDump($this->dumper, $data, $name, $file, $line); + } else { + $this->isCollected = false; } - if ($this->dumper) { - $this->doDump($data, $name, $file, $line); + if (!$this->dataCount) { + $this->data = []; } - $this->data[] = compact('data', 'name', 'file', 'line', 'fileExcerpt'); ++$this->dataCount; @@ -138,6 +100,10 @@ class DumpDataCollector extends DataCollector implements DataDumperInterface public function collect(Request $request, Response $response, \Exception $exception = null) { + if (!$this->dataCount) { + $this->data = []; + } + // Sub-requests and programmatic calls stay in the collected profile. if ($this->dumper || ($this->requestStack && $this->requestStack->getMasterRequest() !== $request) || $request->isXmlHttpRequest() || $request->headers->has('Origin')) { return; @@ -152,14 +118,17 @@ class DumpDataCollector extends DataCollector implements DataDumperInterface || false === strripos($response->getContent(), '</body>') ) { if ($response->headers->has('Content-Type') && false !== strpos($response->headers->get('Content-Type'), 'html')) { - $this->dumper = new HtmlDumper('php://output', $this->charset); - $this->dumper->setDisplayOptions(array('fileLinkFormat' => $this->fileLinkFormat)); + $dumper = new HtmlDumper('php://output', $this->charset); + $dumper->setDisplayOptions(['fileLinkFormat' => $this->fileLinkFormat]); } else { - $this->dumper = new CliDumper('php://output', $this->charset); + $dumper = new CliDumper('php://output', $this->charset); + if (method_exists($dumper, 'setDisplayOptions')) { + $dumper->setDisplayOptions(['fileLinkFormat' => $this->fileLinkFormat]); + } } foreach ($this->data as $dump) { - $this->doDump($dump['data'], $dump['name'], $dump['file'], $dump['line']); + $this->doDump($dumper, $dump['data'], $dump['name'], $dump['file'], $dump['line']); } } } @@ -169,38 +138,45 @@ class DumpDataCollector extends DataCollector implements DataDumperInterface if ($this->stopwatch) { $this->stopwatch->reset(); } - $this->data = array(); + $this->data = []; $this->dataCount = 0; - $this->isCollected = false; + $this->isCollected = true; $this->clonesCount = 0; $this->clonesIndex = 0; } - public function serialize() + /** + * @internal + */ + public function __sleep() { + if (!$this->dataCount) { + $this->data = []; + } + if ($this->clonesCount !== $this->clonesIndex) { - return 'a:0:{}'; + return []; } $this->data[] = $this->fileLinkFormat; $this->data[] = $this->charset; - $ser = serialize($this->data); - $this->data = array(); $this->dataCount = 0; $this->isCollected = true; - if (!$this->dumperIsInjected) { - $this->dumper = null; - } - return $ser; + return parent::__sleep(); } - public function unserialize($data) + /** + * @internal + */ + public function __wakeup() { - parent::unserialize($data); + parent::__wakeup(); + $charset = array_pop($this->data); $fileLinkFormat = array_pop($this->data); - $this->dataCount = count($this->data); + $this->dataCount = \count($this->data); + self::__construct($this->stopwatch, $fileLinkFormat, $charset); } @@ -215,11 +191,15 @@ class DumpDataCollector extends DataCollector implements DataDumperInterface if ('html' === $format) { $dumper = new HtmlDumper($data, $this->charset); - $dumper->setDisplayOptions(array('fileLinkFormat' => $this->fileLinkFormat)); + $dumper->setDisplayOptions(['fileLinkFormat' => $this->fileLinkFormat]); } else { throw new \InvalidArgumentException(sprintf('Invalid dump format: %s', $format)); } - $dumps = array(); + $dumps = []; + + if (!$this->dataCount) { + return $this->data = []; + } foreach ($this->data as $dump) { $dumper->dump($dump['data']->withMaxDepth($maxDepthLimit)->withMaxItemsPerDepth($maxItemsPerDepth)); @@ -239,44 +219,53 @@ class DumpDataCollector extends DataCollector implements DataDumperInterface public function __destruct() { - if (0 === $this->clonesCount-- && !$this->isCollected && $this->data) { + if (0 === $this->clonesCount-- && !$this->isCollected && $this->dataCount) { $this->clonesCount = 0; $this->isCollected = true; $h = headers_list(); - $i = count($h); + $i = \count($h); array_unshift($h, 'Content-Type: '.ini_get('default_mimetype')); while (0 !== stripos($h[$i], 'Content-Type:')) { --$i; } - if ('cli' !== PHP_SAPI && stripos($h[$i], 'html')) { - $this->dumper = new HtmlDumper('php://output', $this->charset); - $this->dumper->setDisplayOptions(array('fileLinkFormat' => $this->fileLinkFormat)); + if (isset($_SERVER['VAR_DUMPER_FORMAT'])) { + $html = 'html' === $_SERVER['VAR_DUMPER_FORMAT']; + } else { + $html = !\in_array(\PHP_SAPI, ['cli', 'phpdbg'], true) && stripos($h[$i], 'html'); + } + + if ($html) { + $dumper = new HtmlDumper('php://output', $this->charset); + $dumper->setDisplayOptions(['fileLinkFormat' => $this->fileLinkFormat]); } else { - $this->dumper = new CliDumper('php://output', $this->charset); + $dumper = new CliDumper('php://output', $this->charset); + if (method_exists($dumper, 'setDisplayOptions')) { + $dumper->setDisplayOptions(['fileLinkFormat' => $this->fileLinkFormat]); + } } foreach ($this->data as $i => $dump) { $this->data[$i] = null; - $this->doDump($dump['data'], $dump['name'], $dump['file'], $dump['line']); + $this->doDump($dumper, $dump['data'], $dump['name'], $dump['file'], $dump['line']); } - $this->data = array(); + $this->data = []; $this->dataCount = 0; } } - private function doDump($data, $name, $file, $line) + private function doDump(DataDumperInterface $dumper, $data, $name, $file, $line) { - if ($this->dumper instanceof CliDumper) { + if ($dumper instanceof CliDumper) { $contextDumper = function ($name, $file, $line, $fmt) { if ($this instanceof HtmlDumper) { if ($file) { $s = $this->style('meta', '%s'); $f = strip_tags($this->style('', $file)); $name = strip_tags($this->style('', $name)); - if ($fmt && $link = is_string($fmt) ? strtr($fmt, array('%f' => $file, '%l' => $line)) : $fmt->format($file, $line)) { + if ($fmt && $link = \is_string($fmt) ? strtr($fmt, ['%f' => $file, '%l' => $line]) : $fmt->format($file, $line)) { $name = sprintf('<a href="%s" title="%s">'.$s.'</a>', strip_tags($this->style('', $link)), $f, $name); } else { $name = sprintf('<abbr title="%s">'.$s.'</abbr>', $f, $name); @@ -290,26 +279,12 @@ class DumpDataCollector extends DataCollector implements DataDumperInterface } $this->dumpLine(0); }; - $contextDumper = $contextDumper->bindTo($this->dumper, $this->dumper); + $contextDumper = $contextDumper->bindTo($dumper, $dumper); $contextDumper($name, $file, $line, $this->fileLinkFormat); } else { $cloner = new VarCloner(); - $this->dumper->dump($cloner->cloneVar($name.' on line '.$line.':')); + $dumper->dump($cloner->cloneVar($name.' on line '.$line.':')); } - $this->dumper->dump($data); - } - - private function htmlEncode($s) - { - $html = ''; - - $dumper = new HtmlDumper(function ($line) use (&$html) { $html .= $line; }, $this->charset); - $dumper->setDumpHeader(''); - $dumper->setDumpBoundaries('', ''); - - $cloner = new VarCloner(); - $dumper->dump($cloner->cloneVar($s)); - - return substr(strip_tags($html), 1, -1); + $dumper->dump($data); } } diff --git a/vendor/symfony/http-kernel/DataCollector/EventDataCollector.php b/vendor/symfony/http-kernel/DataCollector/EventDataCollector.php index 0a095ab68540875dc63d34c783b857ce07476fbb..639757024c6f956024a2c7053b754d14cacca48f 100644 --- a/vendor/symfony/http-kernel/DataCollector/EventDataCollector.php +++ b/vendor/symfony/http-kernel/DataCollector/EventDataCollector.php @@ -11,10 +11,13 @@ namespace Symfony\Component\HttpKernel\DataCollector; +use Symfony\Component\EventDispatcher\Debug\TraceableEventDispatcher; +use Symfony\Component\EventDispatcher\Debug\TraceableEventDispatcherInterface; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\EventDispatcher\EventDispatcherInterface; -use Symfony\Component\EventDispatcher\Debug\TraceableEventDispatcherInterface; +use Symfony\Contracts\EventDispatcher\EventDispatcherInterface; +use Symfony\Contracts\Service\ResetInterface; /** * EventDataCollector. @@ -24,13 +27,13 @@ use Symfony\Component\EventDispatcher\Debug\TraceableEventDispatcherInterface; class EventDataCollector extends DataCollector implements LateDataCollectorInterface { protected $dispatcher; + private $requestStack; + private $currentRequest; - public function __construct(EventDispatcherInterface $dispatcher = null) + public function __construct(EventDispatcherInterface $dispatcher = null, RequestStack $requestStack = null) { - if ($dispatcher instanceof TraceableEventDispatcherInterface && !method_exists($dispatcher, 'reset')) { - @trigger_error(sprintf('Implementing "%s" without the "reset()" method is deprecated since Symfony 3.4 and will be unsupported in 4.0 for class "%s".', TraceableEventDispatcherInterface::class, \get_class($dispatcher)), E_USER_DEPRECATED); - } $this->dispatcher = $dispatcher; + $this->requestStack = $requestStack; } /** @@ -38,21 +41,19 @@ class EventDataCollector extends DataCollector implements LateDataCollectorInter */ public function collect(Request $request, Response $response, \Exception $exception = null) { - $this->data = array( - 'called_listeners' => array(), - 'not_called_listeners' => array(), - ); + $this->currentRequest = $this->requestStack && $this->requestStack->getMasterRequest() !== $request ? $request : null; + $this->data = [ + 'called_listeners' => [], + 'not_called_listeners' => [], + 'orphaned_events' => [], + ]; } public function reset() { - $this->data = array(); - - if ($this->dispatcher instanceof TraceableEventDispatcherInterface) { - if (!method_exists($this->dispatcher, 'reset')) { - return; // @deprecated - } + $this->data = []; + if ($this->dispatcher instanceof ResetInterface) { $this->dispatcher->reset(); } } @@ -60,9 +61,14 @@ class EventDataCollector extends DataCollector implements LateDataCollectorInter public function lateCollect() { if ($this->dispatcher instanceof TraceableEventDispatcherInterface) { - $this->setCalledListeners($this->dispatcher->getCalledListeners()); - $this->setNotCalledListeners($this->dispatcher->getNotCalledListeners()); + $this->setCalledListeners($this->dispatcher->getCalledListeners($this->currentRequest)); + $this->setNotCalledListeners($this->dispatcher->getNotCalledListeners($this->currentRequest)); + } + + if ($this->dispatcher instanceof TraceableEventDispatcher) { + $this->setOrphanedEvents($this->dispatcher->getOrphanedEvents($this->currentRequest)); } + $this->data = $this->cloneVar($this->data); } @@ -71,7 +77,7 @@ class EventDataCollector extends DataCollector implements LateDataCollectorInter * * @param array $listeners An array of called listeners * - * @see TraceableEventDispatcherInterface + * @see TraceableEventDispatcher */ public function setCalledListeners(array $listeners) { @@ -83,7 +89,7 @@ class EventDataCollector extends DataCollector implements LateDataCollectorInter * * @return array An array of called listeners * - * @see TraceableEventDispatcherInterface + * @see TraceableEventDispatcher */ public function getCalledListeners() { @@ -93,9 +99,7 @@ class EventDataCollector extends DataCollector implements LateDataCollectorInter /** * Sets the not called listeners. * - * @param array $listeners An array of not called listeners - * - * @see TraceableEventDispatcherInterface + * @see TraceableEventDispatcher */ public function setNotCalledListeners(array $listeners) { @@ -105,15 +109,39 @@ class EventDataCollector extends DataCollector implements LateDataCollectorInter /** * Gets the not called listeners. * - * @return array An array of not called listeners + * @return array * - * @see TraceableEventDispatcherInterface + * @see TraceableEventDispatcher */ public function getNotCalledListeners() { return $this->data['not_called_listeners']; } + /** + * Sets the orphaned events. + * + * @param array $events An array of orphaned events + * + * @see TraceableEventDispatcher + */ + public function setOrphanedEvents(array $events) + { + $this->data['orphaned_events'] = $events; + } + + /** + * Gets the orphaned events. + * + * @return array An array of orphaned events + * + * @see TraceableEventDispatcher + */ + public function getOrphanedEvents() + { + return $this->data['orphaned_events']; + } + /** * {@inheritdoc} */ diff --git a/vendor/symfony/http-kernel/DataCollector/ExceptionDataCollector.php b/vendor/symfony/http-kernel/DataCollector/ExceptionDataCollector.php index 7a25f149215b8584b5cb3764d116f49b1692aecc..f9be5bddfff1f576968527d4669fbcb57e81acbb 100644 --- a/vendor/symfony/http-kernel/DataCollector/ExceptionDataCollector.php +++ b/vendor/symfony/http-kernel/DataCollector/ExceptionDataCollector.php @@ -28,9 +28,9 @@ class ExceptionDataCollector extends DataCollector public function collect(Request $request, Response $response, \Exception $exception = null) { if (null !== $exception) { - $this->data = array( + $this->data = [ 'exception' => FlattenException::create($exception), - ); + ]; } } @@ -39,7 +39,7 @@ class ExceptionDataCollector extends DataCollector */ public function reset() { - $this->data = array(); + $this->data = []; } /** @@ -55,7 +55,7 @@ class ExceptionDataCollector extends DataCollector /** * Gets the exception. * - * @return \Exception The exception + * @return \Exception|FlattenException */ public function getException() { diff --git a/vendor/symfony/http-kernel/DataCollector/LoggerDataCollector.php b/vendor/symfony/http-kernel/DataCollector/LoggerDataCollector.php index 03bfa5d842ea83fe15f89707bc727b2c143c55e5..d6cca047b97942749cf2e7911d70e35d62fcb86b 100644 --- a/vendor/symfony/http-kernel/DataCollector/LoggerDataCollector.php +++ b/vendor/symfony/http-kernel/DataCollector/LoggerDataCollector.php @@ -13,6 +13,7 @@ namespace Symfony\Component\HttpKernel\DataCollector; use Symfony\Component\Debug\Exception\SilencedErrorContext; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\Log\DebugLoggerInterface; @@ -25,18 +26,17 @@ class LoggerDataCollector extends DataCollector implements LateDataCollectorInte { private $logger; private $containerPathPrefix; + private $currentRequest; + private $requestStack; - public function __construct($logger = null, $containerPathPrefix = null) + public function __construct($logger = null, string $containerPathPrefix = null, RequestStack $requestStack = null) { if (null !== $logger && $logger instanceof DebugLoggerInterface) { - if (!method_exists($logger, 'clear')) { - @trigger_error(sprintf('Implementing "%s" without the "clear()" method is deprecated since Symfony 3.4 and will be unsupported in 4.0 for class "%s".', DebugLoggerInterface::class, \get_class($logger)), E_USER_DEPRECATED); - } - $this->logger = $logger; } $this->containerPathPrefix = $containerPathPrefix; + $this->requestStack = $requestStack; } /** @@ -44,7 +44,7 @@ class LoggerDataCollector extends DataCollector implements LateDataCollectorInte */ public function collect(Request $request, Response $response, \Exception $exception = null) { - // everything is done as late as possible + $this->currentRequest = $this->requestStack && $this->requestStack->getMasterRequest() !== $request ? $request : null; } /** @@ -52,10 +52,10 @@ class LoggerDataCollector extends DataCollector implements LateDataCollectorInte */ public function reset() { - if ($this->logger && method_exists($this->logger, 'clear')) { + if ($this->logger instanceof DebugLoggerInterface) { $this->logger->clear(); } - $this->data = array(); + $this->data = []; } /** @@ -66,25 +66,23 @@ class LoggerDataCollector extends DataCollector implements LateDataCollectorInte if (null !== $this->logger) { $containerDeprecationLogs = $this->getContainerDeprecationLogs(); $this->data = $this->computeErrorsCount($containerDeprecationLogs); - $this->data['compiler_logs'] = $this->getContainerCompilerLogs(); - $this->data['logs'] = $this->sanitizeLogs(array_merge($this->logger->getLogs(), $containerDeprecationLogs)); + // get compiler logs later (only when they are needed) to improve performance + $this->data['compiler_logs'] = []; + $this->data['compiler_logs_filepath'] = $this->containerPathPrefix.'Compiler.log'; + $this->data['logs'] = $this->sanitizeLogs(array_merge($this->logger->getLogs($this->currentRequest), $containerDeprecationLogs)); $this->data = $this->cloneVar($this->data); } + $this->currentRequest = null; } - /** - * Gets the logs. - * - * @return array An array of logs - */ public function getLogs() { - return isset($this->data['logs']) ? $this->data['logs'] : array(); + return isset($this->data['logs']) ? $this->data['logs'] : []; } public function getPriorities() { - return isset($this->data['priorities']) ? $this->data['priorities'] : array(); + return isset($this->data['priorities']) ? $this->data['priorities'] : []; } public function countErrors() @@ -109,7 +107,7 @@ class LoggerDataCollector extends DataCollector implements LateDataCollectorInte public function getCompilerLogs() { - return isset($this->data['compiler_logs']) ? $this->data['compiler_logs'] : array(); + return $this->cloneVar($this->getContainerCompilerLogs($this->data['compiler_logs_filepath'] ?? null)); } /** @@ -123,17 +121,21 @@ class LoggerDataCollector extends DataCollector implements LateDataCollectorInte private function getContainerDeprecationLogs() { if (null === $this->containerPathPrefix || !file_exists($file = $this->containerPathPrefix.'Deprecations.log')) { - return array(); + return []; + } + + if ('' === $logContent = trim(file_get_contents($file))) { + return []; } $bootTime = filemtime($file); - $logs = array(); - foreach (unserialize(file_get_contents($file)) as $log) { - $log['context'] = array('exception' => new SilencedErrorContext($log['type'], $log['file'], $log['line'], $log['trace'], $log['count'])); + $logs = []; + foreach (unserialize($logContent) as $log) { + $log['context'] = ['exception' => new SilencedErrorContext($log['type'], $log['file'], $log['line'], $log['trace'], $log['count'])]; $log['timestamp'] = $bootTime; $log['priority'] = 100; $log['priorityName'] = 'DEBUG'; - $log['channel'] = '-'; + $log['channel'] = null; $log['scream'] = false; unset($log['type'], $log['file'], $log['line'], $log['trace'], $log['trace'], $log['count']); $logs[] = $log; @@ -142,20 +144,20 @@ class LoggerDataCollector extends DataCollector implements LateDataCollectorInte return $logs; } - private function getContainerCompilerLogs() + private function getContainerCompilerLogs(string $compilerLogsFilepath = null): array { - if (null === $this->containerPathPrefix || !file_exists($file = $this->containerPathPrefix.'Compiler.log')) { - return array(); + if (!file_exists($compilerLogsFilepath)) { + return []; } - $logs = array(); - foreach (file($file, FILE_IGNORE_NEW_LINES) as $log) { + $logs = []; + foreach (file($compilerLogsFilepath, FILE_IGNORE_NEW_LINES) as $log) { $log = explode(': ', $log, 2); if (!isset($log[1]) || !preg_match('/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+(?:\\\\[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*+)++$/', $log[0])) { - $log = array('Unknown Compiler Pass', implode(': ', $log)); + $log = ['Unknown Compiler Pass', implode(': ', $log)]; } - $logs[$log[0]][] = array('message' => $log[1]); + $logs[$log[0]][] = ['message' => $log[1]]; } return $logs; @@ -163,8 +165,8 @@ class LoggerDataCollector extends DataCollector implements LateDataCollectorInte private function sanitizeLogs($logs) { - $sanitizedLogs = array(); - $silencedLogs = array(); + $sanitizedLogs = []; + $silencedLogs = []; foreach ($logs as $log) { if (!$this->isSilencedOrDeprecationErrorLog($log)) { @@ -183,10 +185,10 @@ class LoggerDataCollector extends DataCollector implements LateDataCollectorInte $silencedLogs[$h] = true; if (!isset($sanitizedLogs[$message])) { - $sanitizedLogs[$message] = $log + array( + $sanitizedLogs[$message] = $log + [ 'errorCount' => 0, 'scream' => true, - ); + ]; } $sanitizedLogs[$message]['errorCount'] += $exception->count; @@ -198,10 +200,10 @@ class LoggerDataCollector extends DataCollector implements LateDataCollectorInte if (isset($sanitizedLogs[$errorId])) { ++$sanitizedLogs[$errorId]['errorCount']; } else { - $log += array( + $log += [ 'errorCount' => 1, 'scream' => false, - ); + ]; $sanitizedLogs[$errorId] = $log; } @@ -222,7 +224,7 @@ class LoggerDataCollector extends DataCollector implements LateDataCollectorInte return true; } - if ($exception instanceof \ErrorException && in_array($exception->getSeverity(), array(E_DEPRECATED, E_USER_DEPRECATED), true)) { + if ($exception instanceof \ErrorException && \in_array($exception->getSeverity(), [E_DEPRECATED, E_USER_DEPRECATED], true)) { return true; } @@ -231,23 +233,23 @@ class LoggerDataCollector extends DataCollector implements LateDataCollectorInte private function computeErrorsCount(array $containerDeprecationLogs) { - $silencedLogs = array(); - $count = array( - 'error_count' => $this->logger->countErrors(), + $silencedLogs = []; + $count = [ + 'error_count' => $this->logger->countErrors($this->currentRequest), 'deprecation_count' => 0, 'warning_count' => 0, 'scream_count' => 0, - 'priorities' => array(), - ); + 'priorities' => [], + ]; - foreach ($this->logger->getLogs() as $log) { + foreach ($this->logger->getLogs($this->currentRequest) as $log) { if (isset($count['priorities'][$log['priority']])) { ++$count['priorities'][$log['priority']]['count']; } else { - $count['priorities'][$log['priority']] = array( + $count['priorities'][$log['priority']] = [ 'count' => 1, 'name' => $log['priorityName'], - ); + ]; } if ('WARNING' === $log['priorityName']) { ++$count['warning_count']; diff --git a/vendor/symfony/http-kernel/DataCollector/MemoryDataCollector.php b/vendor/symfony/http-kernel/DataCollector/MemoryDataCollector.php index 8d8cc1a04d1818d7cfaa0f83fd3ca5c1d6fea81a..7a6e1c06464469a81da283b733908b4ce3be7fff 100644 --- a/vendor/symfony/http-kernel/DataCollector/MemoryDataCollector.php +++ b/vendor/symfony/http-kernel/DataCollector/MemoryDataCollector.php @@ -39,10 +39,10 @@ class MemoryDataCollector extends DataCollector implements LateDataCollectorInte */ public function reset() { - $this->data = array( + $this->data = [ 'memory' => 0, 'memory_limit' => $this->convertToBytes(ini_get('memory_limit')), - ); + ]; } /** @@ -98,9 +98,9 @@ class MemoryDataCollector extends DataCollector implements LateDataCollectorInte $memoryLimit = strtolower($memoryLimit); $max = strtolower(ltrim($memoryLimit, '+')); if (0 === strpos($max, '0x')) { - $max = intval($max, 16); + $max = \intval($max, 16); } elseif (0 === strpos($max, '0')) { - $max = intval($max, 8); + $max = \intval($max, 8); } else { $max = (int) $max; } diff --git a/vendor/symfony/http-kernel/DataCollector/RequestDataCollector.php b/vendor/symfony/http-kernel/DataCollector/RequestDataCollector.php index 54d17d28c7cacd4aac76d74156c5d79776267cc6..32624c963fa0783deca4c6ad478d2938e0872583 100644 --- a/vendor/symfony/http-kernel/DataCollector/RequestDataCollector.php +++ b/vendor/symfony/http-kernel/DataCollector/RequestDataCollector.php @@ -11,14 +11,14 @@ namespace Symfony\Component\HttpKernel\DataCollector; +use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\HttpFoundation\Cookie; use Symfony\Component\HttpFoundation\ParameterBag; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpKernel\Event\FilterControllerEvent; use Symfony\Component\HttpKernel\Event\FilterResponseEvent; use Symfony\Component\HttpKernel\KernelEvents; -use Symfony\Component\HttpKernel\Event\FilterControllerEvent; -use Symfony\Component\EventDispatcher\EventSubscriberInterface; /** * @author Fabien Potencier <fabien@symfony.com> @@ -38,11 +38,11 @@ class RequestDataCollector extends DataCollector implements EventSubscriberInter public function collect(Request $request, Response $response, \Exception $exception = null) { // attributes are serialized and as they can be anything, they need to be converted to strings. - $attributes = array(); + $attributes = []; $route = ''; foreach ($request->attributes->all() as $key => $value) { if ('_route' === $key) { - $route = is_object($value) ? $value->getPath() : $value; + $route = \is_object($value) ? $value->getPath() : $value; $attributes[$key] = $route; } else { $attributes[$key] = $value; @@ -57,10 +57,10 @@ class RequestDataCollector extends DataCollector implements EventSubscriberInter $content = false; } - $sessionMetadata = array(); - $sessionAttributes = array(); + $sessionMetadata = []; + $sessionAttributes = []; $session = null; - $flashes = array(); + $flashes = []; if ($request->hasSession()) { $session = $request->getSession(); if ($session->isStarted()) { @@ -74,12 +74,19 @@ class RequestDataCollector extends DataCollector implements EventSubscriberInter $statusCode = $response->getStatusCode(); - $responseCookies = array(); + $responseCookies = []; foreach ($response->headers->getCookies() as $cookie) { $responseCookies[$cookie->getName()] = $cookie; } - $this->data = array( + $dotenvVars = []; + foreach (explode(',', getenv('SYMFONY_DOTENV_VARS')) as $name) { + if ('' !== $name && false !== $value = getenv($name)) { + $dotenvVars[$name] = $value; + } + } + + $this->data = [ 'method' => $request->getMethod(), 'format' => $request->getRequestFormat(), 'content' => $content, @@ -88,6 +95,7 @@ class RequestDataCollector extends DataCollector implements EventSubscriberInter 'status_code' => $statusCode, 'request_query' => $request->query->all(), 'request_request' => $request->request->all(), + 'request_files' => $request->files->all(), 'request_headers' => $request->headers->all(), 'request_server' => $request->server->all(), 'request_cookies' => $request->cookies->all(), @@ -101,7 +109,8 @@ class RequestDataCollector extends DataCollector implements EventSubscriberInter 'path_info' => $request->getPathInfo(), 'controller' => 'n/a', 'locale' => $request->getLocale(), - ); + 'dotenv_vars' => $dotenvVars, + ]; if (isset($this->data['request_headers']['php-auth-pw'])) { $this->data['request_headers']['php-auth-pw'] = '******'; @@ -116,7 +125,7 @@ class RequestDataCollector extends DataCollector implements EventSubscriberInter } foreach ($this->data as $key => $value) { - if (!is_array($value)) { + if (!\is_array($value)) { continue; } if ('request_headers' === $key || 'response_headers' === $key) { @@ -138,18 +147,23 @@ class RequestDataCollector extends DataCollector implements EventSubscriberInter if ($response->isRedirect()) { $response->headers->setCookie(new Cookie( 'sf_redirect', - json_encode(array( + json_encode([ 'token' => $response->headers->get('x-debug-token'), 'route' => $request->attributes->get('_route', 'n/a'), 'method' => $request->getMethod(), 'controller' => $this->parseController($request->attributes->get('_controller')), 'status_code' => $statusCode, 'status_text' => Response::$statusTexts[(int) $statusCode], - )) + ]), + 0, '/', null, $request->isSecure(), true, false, 'lax' )); } - $this->data['identifier'] = $this->data['route'] ?: (is_array($this->data['controller']) ? $this->data['controller']['class'].'::'.$this->data['controller']['method'].'()' : $this->data['controller']); + $this->data['identifier'] = $this->data['route'] ?: (\is_array($this->data['controller']) ? $this->data['controller']['class'].'::'.$this->data['controller']['method'].'()' : $this->data['controller']); + + if ($response->headers->has('x-previous-debug-token')) { + $this->data['forward_token'] = $response->headers->get('x-previous-debug-token'); + } } public function lateCollect() @@ -159,7 +173,7 @@ class RequestDataCollector extends DataCollector implements EventSubscriberInter public function reset() { - $this->data = array(); + $this->data = []; $this->controllers = new \SplObjectStorage(); } @@ -183,6 +197,11 @@ class RequestDataCollector extends DataCollector implements EventSubscriberInter return new ParameterBag($this->data['request_query']->getValue()); } + public function getRequestFiles() + { + return new ParameterBag($this->data['request_files']->getValue()); + } + public function getRequestHeaders() { return new ParameterBag($this->data['request_headers']->getValue()); @@ -233,6 +252,18 @@ class RequestDataCollector extends DataCollector implements EventSubscriberInter return $this->data['content']; } + public function isJsonRequest() + { + return 1 === preg_match('{^application/(?:\w+\++)*json$}i', $this->data['request_headers']['content-type']); + } + + public function getPrettyJson() + { + $decoded = json_decode($this->getContent()); + + return JSON_ERROR_NONE === json_last_error() ? json_encode($decoded, JSON_PRETTY_PRINT) : null; + } + public function getContentType() { return $this->data['content_type']; @@ -258,6 +289,11 @@ class RequestDataCollector extends DataCollector implements EventSubscriberInter return $this->data['locale']; } + public function getDotenvVars() + { + return new ParameterBag($this->data['dotenv_vars']->getValue()); + } + /** * Gets the route name. * @@ -284,7 +320,7 @@ class RequestDataCollector extends DataCollector implements EventSubscriberInter */ public function getRouteParams() { - return isset($this->data['request_attributes']['_route_params']) ? $this->data['request_attributes']['_route_params']->getValue() : array(); + return isset($this->data['request_attributes']['_route_params']) ? $this->data['request_attributes']['_route_params']->getValue() : []; } /** @@ -309,11 +345,22 @@ class RequestDataCollector extends DataCollector implements EventSubscriberInter return isset($this->data['redirect']) ? $this->data['redirect'] : false; } + public function getForwardToken() + { + return isset($this->data['forward_token']) ? $this->data['forward_token'] : null; + } + + /** + * @final since Symfony 4.3 + */ public function onKernelController(FilterControllerEvent $event) { $this->controllers[$event->getRequest()] = $event->getController(); } + /** + * @final since Symfony 4.3 + */ public function onKernelResponse(FilterResponseEvent $event) { if (!$event->isMasterRequest()) { @@ -327,10 +374,10 @@ class RequestDataCollector extends DataCollector implements EventSubscriberInter public static function getSubscribedEvents() { - return array( + return [ KernelEvents::CONTROLLER => 'onKernelController', KernelEvents::RESPONSE => 'onKernelResponse', - ); + ]; } /** @@ -350,29 +397,29 @@ class RequestDataCollector extends DataCollector implements EventSubscriberInter */ protected function parseController($controller) { - if (is_string($controller) && false !== strpos($controller, '::')) { + if (\is_string($controller) && false !== strpos($controller, '::')) { $controller = explode('::', $controller); } - if (is_array($controller)) { + if (\is_array($controller)) { try { $r = new \ReflectionMethod($controller[0], $controller[1]); - return array( - 'class' => is_object($controller[0]) ? get_class($controller[0]) : $controller[0], + return [ + 'class' => \is_object($controller[0]) ? \get_class($controller[0]) : $controller[0], 'method' => $controller[1], 'file' => $r->getFileName(), 'line' => $r->getStartLine(), - ); + ]; } catch (\ReflectionException $e) { - if (is_callable($controller)) { + if (\is_callable($controller)) { // using __call or __callStatic - return array( - 'class' => is_object($controller[0]) ? get_class($controller[0]) : $controller[0], + return [ + 'class' => \is_object($controller[0]) ? \get_class($controller[0]) : $controller[0], 'method' => $controller[1], 'file' => 'n/a', 'line' => 'n/a', - ); + ]; } } } @@ -380,25 +427,38 @@ class RequestDataCollector extends DataCollector implements EventSubscriberInter if ($controller instanceof \Closure) { $r = new \ReflectionFunction($controller); - return array( + $controller = [ 'class' => $r->getName(), 'method' => null, 'file' => $r->getFileName(), 'line' => $r->getStartLine(), - ); + ]; + + if (false !== strpos($r->name, '{closure}')) { + return $controller; + } + $controller['method'] = $r->name; + + if ($class = $r->getClosureScopeClass()) { + $controller['class'] = $class->name; + } else { + return $r->name; + } + + return $controller; } - if (is_object($controller)) { + if (\is_object($controller)) { $r = new \ReflectionClass($controller); - return array( + return [ 'class' => $r->getName(), 'method' => null, 'file' => $r->getFileName(), 'line' => $r->getStartLine(), - ); + ]; } - return is_string($controller) ? $controller : 'n/a'; + return \is_string($controller) ? $controller : 'n/a'; } } diff --git a/vendor/symfony/http-kernel/DataCollector/RouterDataCollector.php b/vendor/symfony/http-kernel/DataCollector/RouterDataCollector.php index afd34f8af814be60cd23f6e1e2cbc30c3d0a96b3..65fc90dc1921e0206a131c3bb47ea86915fb9070 100644 --- a/vendor/symfony/http-kernel/DataCollector/RouterDataCollector.php +++ b/vendor/symfony/http-kernel/DataCollector/RouterDataCollector.php @@ -11,14 +11,12 @@ namespace Symfony\Component\HttpKernel\DataCollector; +use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\HttpKernel\Event\FilterControllerEvent; /** - * RouterDataCollector. - * * @author Fabien Potencier <fabien@symfony.com> */ class RouterDataCollector extends DataCollector @@ -54,11 +52,11 @@ class RouterDataCollector extends DataCollector { $this->controllers = new \SplObjectStorage(); - $this->data = array( + $this->data = [ 'redirect' => false, 'url' => null, 'route' => null, - ); + ]; } protected function guessRoute(Request $request, $controller) @@ -68,6 +66,8 @@ class RouterDataCollector extends DataCollector /** * Remembers the controller associated to each request. + * + * @final since Symfony 4.3 */ public function onKernelController(FilterControllerEvent $event) { diff --git a/vendor/symfony/http-kernel/DataCollector/TimeDataCollector.php b/vendor/symfony/http-kernel/DataCollector/TimeDataCollector.php index e489d77598620b77971f2618ae914333030d42dc..cb490c2bb37d0ee9bce3dcf3f7bb66e3cb3fa7ed 100644 --- a/vendor/symfony/http-kernel/DataCollector/TimeDataCollector.php +++ b/vendor/symfony/http-kernel/DataCollector/TimeDataCollector.php @@ -15,10 +15,9 @@ use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\KernelInterface; use Symfony\Component\Stopwatch\Stopwatch; +use Symfony\Component\Stopwatch\StopwatchEvent; /** - * TimeDataCollector. - * * @author Fabien Potencier <fabien@symfony.com> */ class TimeDataCollector extends DataCollector implements LateDataCollectorInterface @@ -43,11 +42,12 @@ class TimeDataCollector extends DataCollector implements LateDataCollectorInterf $startTime = $request->server->get('REQUEST_TIME_FLOAT'); } - $this->data = array( + $this->data = [ 'token' => $response->headers->get('X-Debug-Token'), 'start_time' => $startTime * 1000, - 'events' => array(), - ); + 'events' => [], + 'stopwatch_installed' => class_exists(Stopwatch::class, false), + ]; } /** @@ -55,7 +55,7 @@ class TimeDataCollector extends DataCollector implements LateDataCollectorInterf */ public function reset() { - $this->data = array(); + $this->data = []; if (null !== $this->stopwatch) { $this->stopwatch->reset(); @@ -76,7 +76,7 @@ class TimeDataCollector extends DataCollector implements LateDataCollectorInterf /** * Sets the request events. * - * @param array $events The request events + * @param StopwatchEvent[] $events The request events */ public function setEvents(array $events) { @@ -90,7 +90,7 @@ class TimeDataCollector extends DataCollector implements LateDataCollectorInterf /** * Gets the request events. * - * @return array The request events + * @return StopwatchEvent[] The request events */ public function getEvents() { @@ -132,13 +132,21 @@ class TimeDataCollector extends DataCollector implements LateDataCollectorInterf /** * Gets the request time. * - * @return int The time + * @return float */ public function getStartTime() { return $this->data['start_time']; } + /** + * @return bool whether or not the stopwatch component is installed + */ + public function isStopwatchInstalled() + { + return $this->data['stopwatch_installed']; + } + /** * {@inheritdoc} */ diff --git a/vendor/symfony/http-kernel/DataCollector/Util/ValueExporter.php b/vendor/symfony/http-kernel/DataCollector/Util/ValueExporter.php deleted file mode 100644 index a71c00db99e5a65e59368dc94cc38a7759a69251..0000000000000000000000000000000000000000 --- a/vendor/symfony/http-kernel/DataCollector/Util/ValueExporter.php +++ /dev/null @@ -1,99 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\DataCollector\Util; - -@trigger_error('The '.__NAMESPACE__.'\ValueExporter class is deprecated since Symfony 3.2 and will be removed in 4.0. Use the VarDumper component instead.', E_USER_DEPRECATED); - -/** - * @author Bernhard Schussek <bschussek@gmail.com> - * - * @deprecated since version 3.2, to be removed in 4.0. Use the VarDumper component instead. - */ -class ValueExporter -{ - /** - * Converts a PHP value to a string. - * - * @param mixed $value The PHP value - * @param int $depth Only for internal usage - * @param bool $deep Only for internal usage - * - * @return string The string representation of the given value - */ - public function exportValue($value, $depth = 1, $deep = false) - { - if ($value instanceof \__PHP_Incomplete_Class) { - return sprintf('__PHP_Incomplete_Class(%s)', $this->getClassNameFromIncomplete($value)); - } - - if (is_object($value)) { - if ($value instanceof \DateTimeInterface) { - return sprintf('Object(%s) - %s', get_class($value), $value->format(\DateTime::ATOM)); - } - - return sprintf('Object(%s)', get_class($value)); - } - - if (is_array($value)) { - if (empty($value)) { - return '[]'; - } - - $indent = str_repeat(' ', $depth); - - $a = array(); - foreach ($value as $k => $v) { - if (is_array($v)) { - $deep = true; - } - $a[] = sprintf('%s => %s', $k, $this->exportValue($v, $depth + 1, $deep)); - } - - if ($deep) { - return sprintf("[\n%s%s\n%s]", $indent, implode(sprintf(", \n%s", $indent), $a), str_repeat(' ', $depth - 1)); - } - - $s = sprintf('[%s]', implode(', ', $a)); - - if (80 > strlen($s)) { - return $s; - } - - return sprintf("[\n%s%s\n]", $indent, implode(sprintf(",\n%s", $indent), $a)); - } - - if (is_resource($value)) { - return sprintf('Resource(%s#%d)', get_resource_type($value), $value); - } - - if (null === $value) { - return 'null'; - } - - if (false === $value) { - return 'false'; - } - - if (true === $value) { - return 'true'; - } - - return (string) $value; - } - - private function getClassNameFromIncomplete(\__PHP_Incomplete_Class $value) - { - $array = new \ArrayObject($value); - - return $array['__PHP_Incomplete_Class_Name']; - } -} diff --git a/vendor/symfony/http-kernel/Debug/FileLinkFormatter.php b/vendor/symfony/http-kernel/Debug/FileLinkFormatter.php index c340d9b67200ad8178adb68eb0d1325e5f880db9..6878258958587fa889dffb7a55ef092cf3041dbe 100644 --- a/vendor/symfony/http-kernel/Debug/FileLinkFormatter.php +++ b/vendor/symfony/http-kernel/Debug/FileLinkFormatter.php @@ -13,25 +13,32 @@ namespace Symfony\Component\HttpKernel\Debug; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\RequestStack; +use Symfony\Component\Routing\Exception\ExceptionInterface; +use Symfony\Component\Routing\Generator\UrlGeneratorInterface; /** * Formats debug file links. * * @author Jérémy Romey <jeremy@free-agent.fr> + * + * @final since Symfony 4.3 */ -class FileLinkFormatter implements \Serializable +class FileLinkFormatter { private $fileLinkFormat; private $requestStack; private $baseDir; private $urlFormat; - public function __construct($fileLinkFormat = null, RequestStack $requestStack = null, $baseDir = null, $urlFormat = null) + /** + * @param string|\Closure $urlFormat the URL format, or a closure that returns it on-demand + */ + public function __construct($fileLinkFormat = null, RequestStack $requestStack = null, string $baseDir = null, $urlFormat = null) { $fileLinkFormat = $fileLinkFormat ?: ini_get('xdebug.file_link_format') ?: get_cfg_var('xdebug.file_link_format'); - if ($fileLinkFormat && !is_array($fileLinkFormat)) { - $i = strpos($f = $fileLinkFormat, '&', max(strrpos($f, '%f'), strrpos($f, '%l'))) ?: strlen($f); - $fileLinkFormat = array(substr($f, 0, $i)) + preg_split('/&([^>]++)>/', substr($f, $i), -1, PREG_SPLIT_DELIM_CAPTURE); + if ($fileLinkFormat && !\is_array($fileLinkFormat)) { + $i = strpos($f = $fileLinkFormat, '&', max(strrpos($f, '%f'), strrpos($f, '%l'))) ?: \strlen($f); + $fileLinkFormat = [substr($f, 0, $i)] + preg_split('/&([^>]++)>/', substr($f, $i), -1, PREG_SPLIT_DELIM_CAPTURE); } $this->fileLinkFormat = $fileLinkFormat; @@ -45,28 +52,36 @@ class FileLinkFormatter implements \Serializable if ($fmt = $this->getFileLinkFormat()) { for ($i = 1; isset($fmt[$i]); ++$i) { if (0 === strpos($file, $k = $fmt[$i++])) { - $file = substr_replace($file, $fmt[$i], 0, strlen($k)); + $file = substr_replace($file, $fmt[$i], 0, \strlen($k)); break; } } - return strtr($fmt[0], array('%f' => $file, '%l' => $line)); + return strtr($fmt[0], ['%f' => $file, '%l' => $line]); } return false; } - public function serialize() + /** + * @internal + */ + public function __sleep(): array { - return serialize($this->getFileLinkFormat()); + $this->fileLinkFormat = $this->getFileLinkFormat(); + + return ['fileLinkFormat']; } - public function unserialize($serialized) + /** + * @internal + */ + public static function generateUrlFormat(UrlGeneratorInterface $router, $routeName, $queryString) { - if (\PHP_VERSION_ID >= 70000) { - $this->fileLinkFormat = unserialize($serialized, array('allowed_classes' => false)); - } else { - $this->fileLinkFormat = unserialize($serialized); + try { + return $router->generate($routeName).$queryString; + } catch (ExceptionInterface $e) { + return null; } } @@ -75,14 +90,18 @@ class FileLinkFormatter implements \Serializable if ($this->fileLinkFormat) { return $this->fileLinkFormat; } + if ($this->requestStack && $this->baseDir && $this->urlFormat) { $request = $this->requestStack->getMasterRequest(); - if ($request instanceof Request) { - return array( - $request->getSchemeAndHttpHost().$request->getBaseUrl().$this->urlFormat, - $this->baseDir.DIRECTORY_SEPARATOR, '', - ); + + if ($request instanceof Request && (!$this->urlFormat instanceof \Closure || $this->urlFormat = ($this->urlFormat)())) { + return [ + $request->getSchemeAndHttpHost().$this->urlFormat, + $this->baseDir.\DIRECTORY_SEPARATOR, '', + ]; } } + + return null; } } diff --git a/vendor/symfony/http-kernel/Debug/TraceableEventDispatcher.php b/vendor/symfony/http-kernel/Debug/TraceableEventDispatcher.php index fbc49dffc8daadc73aa734a672ce5927a7025433..ce4ddb35d3f752449d7e8afa3a31a2d0692ab034 100644 --- a/vendor/symfony/http-kernel/Debug/TraceableEventDispatcher.php +++ b/vendor/symfony/http-kernel/Debug/TraceableEventDispatcher.php @@ -13,7 +13,6 @@ namespace Symfony\Component\HttpKernel\Debug; use Symfony\Component\EventDispatcher\Debug\TraceableEventDispatcher as BaseTraceableEventDispatcher; use Symfony\Component\HttpKernel\KernelEvents; -use Symfony\Component\EventDispatcher\Event; /** * Collects some data about event listeners. @@ -27,7 +26,7 @@ class TraceableEventDispatcher extends BaseTraceableEventDispatcher /** * {@inheritdoc} */ - protected function preDispatch($eventName, Event $event) + protected function beforeDispatch(string $eventName, $event) { switch ($eventName) { case KernelEvents::REQUEST: @@ -42,6 +41,9 @@ class TraceableEventDispatcher extends BaseTraceableEventDispatcher break; case KernelEvents::TERMINATE: $token = $event->getResponse()->headers->get('X-Debug-Token'); + if (null === $token) { + break; + } // There is a very special case when using built-in AppCache class as kernel wrapper, in the case // of an ESI request leading to a `stale` response [B] inside a `fresh` cached response [A]. // In this case, `$token` contains the [B] debug token, but the open `stopwatch` section ID @@ -58,7 +60,7 @@ class TraceableEventDispatcher extends BaseTraceableEventDispatcher /** * {@inheritdoc} */ - protected function postDispatch($eventName, Event $event) + protected function afterDispatch(string $eventName, $event) { switch ($eventName) { case KernelEvents::CONTROLLER_ARGUMENTS: @@ -66,12 +68,18 @@ class TraceableEventDispatcher extends BaseTraceableEventDispatcher break; case KernelEvents::RESPONSE: $token = $event->getResponse()->headers->get('X-Debug-Token'); + if (null === $token) { + break; + } $this->stopwatch->stopSection($token); break; case KernelEvents::TERMINATE: // In the special case described in the `preDispatch` method above, the `$token` section // does not exist, then closing it throws an exception which must be caught. $token = $event->getResponse()->headers->get('X-Debug-Token'); + if (null === $token) { + break; + } try { $this->stopwatch->stopSection($token); } catch (\LogicException $e) { diff --git a/vendor/symfony/http-kernel/DependencyInjection/AddAnnotatedClassesToCachePass.php b/vendor/symfony/http-kernel/DependencyInjection/AddAnnotatedClassesToCachePass.php index b1ecebdc969a259186e87e99d657b8dea3849ee3..2659d34de649dce12d93aa6d84eb8944799290f9 100644 --- a/vendor/symfony/http-kernel/DependencyInjection/AddAnnotatedClassesToCachePass.php +++ b/vendor/symfony/http-kernel/DependencyInjection/AddAnnotatedClassesToCachePass.php @@ -13,8 +13,8 @@ namespace Symfony\Component\HttpKernel\DependencyInjection; use Composer\Autoload\ClassLoader; use Symfony\Component\Debug\DebugClassLoader; -use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; +use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\HttpKernel\Kernel; /** @@ -36,23 +36,15 @@ class AddAnnotatedClassesToCachePass implements CompilerPassInterface */ public function process(ContainerBuilder $container) { - $classes = array(); - $annotatedClasses = array(); + $annotatedClasses = $this->kernel->getAnnotatedClassesToCompile(); foreach ($container->getExtensions() as $extension) { if ($extension instanceof Extension) { - if (\PHP_VERSION_ID < 70000) { - $classes = array_merge($classes, $extension->getClassesToCompile()); - } $annotatedClasses = array_merge($annotatedClasses, $extension->getAnnotatedClassesToCompile()); } } $existingClasses = $this->getClassesInComposerClassMaps(); - if (\PHP_VERSION_ID < 70000) { - $classes = $container->getParameterBag()->resolveValue($classes); - $this->kernel->setClassCache($this->expandClasses($classes, $existingClasses)); - } $annotatedClasses = $container->getParameterBag()->resolveValue($annotatedClasses); $this->kernel->setAnnotatedClassCache($this->expandClasses($annotatedClasses, $existingClasses)); } @@ -63,11 +55,11 @@ class AddAnnotatedClassesToCachePass implements CompilerPassInterface * @param array $patterns The class patterns to expand * @param array $classes The existing classes to match against the patterns * - * @return array A list of classes derivated from the patterns + * @return array A list of classes derived from the patterns */ private function expandClasses(array $patterns, array $classes) { - $expanded = array(); + $expanded = []; // Explicit classes declared in the patterns are returned directly foreach ($patterns as $key => $pattern) { @@ -93,10 +85,10 @@ class AddAnnotatedClassesToCachePass implements CompilerPassInterface private function getClassesInComposerClassMaps() { - $classes = array(); + $classes = []; foreach (spl_autoload_functions() as $function) { - if (!is_array($function)) { + if (!\is_array($function)) { continue; } @@ -104,7 +96,7 @@ class AddAnnotatedClassesToCachePass implements CompilerPassInterface $function = $function[0]->getClassLoader(); } - if (is_array($function) && $function[0] instanceof ClassLoader) { + if (\is_array($function) && $function[0] instanceof ClassLoader) { $classes += array_filter($function[0]->getClassMap()); } } @@ -114,14 +106,14 @@ class AddAnnotatedClassesToCachePass implements CompilerPassInterface private function patternsToRegexps($patterns) { - $regexps = array(); + $regexps = []; foreach ($patterns as $pattern) { // Escape user input $regex = preg_quote(ltrim($pattern, '\\')); // Wildcards * and ** - $regex = strtr($regex, array('\\*\\*' => '.*?', '\\*' => '[^\\\\]*?')); + $regex = strtr($regex, ['\\*\\*' => '.*?', '\\*' => '[^\\\\]*?']); // If this class does not end by a slash, anchor the end if ('\\' !== substr($regex, -1)) { diff --git a/vendor/symfony/http-kernel/DependencyInjection/AddClassesToCachePass.php b/vendor/symfony/http-kernel/DependencyInjection/AddClassesToCachePass.php deleted file mode 100644 index 8ae78e0d841d7ca48557c81c4ccc4c295b19f7e9..0000000000000000000000000000000000000000 --- a/vendor/symfony/http-kernel/DependencyInjection/AddClassesToCachePass.php +++ /dev/null @@ -1,25 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\DependencyInjection; - -@trigger_error('The '.__NAMESPACE__.'\AddClassesToCachePass class is deprecated since Symfony 3.3 and will be removed in 4.0.', E_USER_DEPRECATED); - -/** - * Sets the classes to compile in the cache for the container. - * - * @author Fabien Potencier <fabien@symfony.com> - * - * @deprecated since version 3.3, to be removed in 4.0. - */ -class AddClassesToCachePass extends AddAnnotatedClassesToCachePass -{ -} diff --git a/vendor/symfony/http-kernel/DependencyInjection/ControllerArgumentValueResolverPass.php b/vendor/symfony/http-kernel/DependencyInjection/ControllerArgumentValueResolverPass.php index 343e217b9687b461e980cd60a90bc70e9b542e7b..705c88dbfaffc6d6cc1bd0237f330a4260a89bb8 100644 --- a/vendor/symfony/http-kernel/DependencyInjection/ControllerArgumentValueResolverPass.php +++ b/vendor/symfony/http-kernel/DependencyInjection/ControllerArgumentValueResolverPass.php @@ -15,6 +15,9 @@ use Symfony\Component\DependencyInjection\Argument\IteratorArgument; use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; use Symfony\Component\DependencyInjection\Compiler\PriorityTaggedServiceTrait; use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Reference; +use Symfony\Component\HttpKernel\Controller\ArgumentResolver\TraceableValueResolver; +use Symfony\Component\Stopwatch\Stopwatch; /** * Gathers and configures the argument value resolvers. @@ -27,11 +30,13 @@ class ControllerArgumentValueResolverPass implements CompilerPassInterface private $argumentResolverService; private $argumentValueResolverTag; + private $traceableResolverStopwatch; - public function __construct($argumentResolverService = 'argument_resolver', $argumentValueResolverTag = 'controller.argument_value_resolver') + public function __construct(string $argumentResolverService = 'argument_resolver', string $argumentValueResolverTag = 'controller.argument_value_resolver', string $traceableResolverStopwatch = 'debug.stopwatch') { $this->argumentResolverService = $argumentResolverService; $this->argumentValueResolverTag = $argumentValueResolverTag; + $this->traceableResolverStopwatch = $traceableResolverStopwatch; } public function process(ContainerBuilder $container) @@ -40,9 +45,20 @@ class ControllerArgumentValueResolverPass implements CompilerPassInterface return; } + $resolvers = $this->findAndSortTaggedServices($this->argumentValueResolverTag, $container); + + if ($container->getParameter('kernel.debug') && class_exists(Stopwatch::class) && $container->has($this->traceableResolverStopwatch)) { + foreach ($resolvers as $resolverReference) { + $id = (string) $resolverReference; + $container->register("debug.$id", TraceableValueResolver::class) + ->setDecoratedService($id) + ->setArguments([new Reference("debug.$id.inner"), new Reference($this->traceableResolverStopwatch)]); + } + } + $container ->getDefinition($this->argumentResolverService) - ->replaceArgument(1, new IteratorArgument($this->findAndSortTaggedServices($this->argumentValueResolverTag, $container))) + ->replaceArgument(1, new IteratorArgument($resolvers)) ; } } diff --git a/vendor/symfony/http-kernel/DependencyInjection/Extension.php b/vendor/symfony/http-kernel/DependencyInjection/Extension.php index a382c15d67b264014955afd343962d1b7a7ede08..db376e6d9fb940badff03a46ef805c768b364073 100644 --- a/vendor/symfony/http-kernel/DependencyInjection/Extension.php +++ b/vendor/symfony/http-kernel/DependencyInjection/Extension.php @@ -20,24 +20,7 @@ use Symfony\Component\DependencyInjection\Extension\Extension as BaseExtension; */ abstract class Extension extends BaseExtension { - private $classes = array(); - private $annotatedClasses = array(); - - /** - * Gets the classes to cache. - * - * @return array An array of classes - * - * @deprecated since version 3.3, to be removed in 4.0. - */ - public function getClassesToCompile() - { - if (\PHP_VERSION_ID >= 70000) { - @trigger_error(__METHOD__.'() is deprecated since Symfony 3.3, to be removed in 4.0.', E_USER_DEPRECATED); - } - - return $this->classes; - } + private $annotatedClasses = []; /** * Gets the annotated classes to cache. @@ -49,22 +32,6 @@ abstract class Extension extends BaseExtension return $this->annotatedClasses; } - /** - * Adds classes to the class cache. - * - * @param array $classes An array of class patterns - * - * @deprecated since version 3.3, to be removed in 4.0. - */ - public function addClassesToCompile(array $classes) - { - if (\PHP_VERSION_ID >= 70000) { - @trigger_error(__METHOD__.'() is deprecated since Symfony 3.3, to be removed in 4.0.', E_USER_DEPRECATED); - } - - $this->classes = array_merge($this->classes, $classes); - } - /** * Adds annotated classes to the class cache. * diff --git a/vendor/symfony/http-kernel/DependencyInjection/FragmentRendererPass.php b/vendor/symfony/http-kernel/DependencyInjection/FragmentRendererPass.php index ac52c8732bc4acfa00088d7a66cdb9afa4264d76..432f767202d770280f9bd121ff21baf7b2a75ea4 100644 --- a/vendor/symfony/http-kernel/DependencyInjection/FragmentRendererPass.php +++ b/vendor/symfony/http-kernel/DependencyInjection/FragmentRendererPass.php @@ -11,9 +11,9 @@ namespace Symfony\Component\HttpKernel\DependencyInjection; +use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; use Symfony\Component\DependencyInjection\Compiler\ServiceLocatorTagPass; use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\HttpKernel\Fragment\FragmentRendererInterface; @@ -28,11 +28,7 @@ class FragmentRendererPass implements CompilerPassInterface private $handlerService; private $rendererTag; - /** - * @param string $handlerService Service name of the fragment handler in the container - * @param string $rendererTag Tag name used for fragments - */ - public function __construct($handlerService = 'fragment.handler', $rendererTag = 'kernel.fragment_renderer') + public function __construct(string $handlerService = 'fragment.handler', string $rendererTag = 'kernel.fragment_renderer') { $this->handlerService = $handlerService; $this->rendererTag = $rendererTag; @@ -45,7 +41,7 @@ class FragmentRendererPass implements CompilerPassInterface } $definition = $container->getDefinition($this->handlerService); - $renderers = array(); + $renderers = []; foreach ($container->findTaggedServiceIds($this->rendererTag, true) as $id => $tags) { $def = $container->getDefinition($id); $class = $container->getParameterBag()->resolveValue($def->getClass()); diff --git a/vendor/symfony/http-kernel/DependencyInjection/LazyLoadingFragmentHandler.php b/vendor/symfony/http-kernel/DependencyInjection/LazyLoadingFragmentHandler.php index 00b05959cf38535bf3c6b2431284e5be5da0c4ee..526c11faacda27526e29e2ca6b7b3d21a3a97f36 100644 --- a/vendor/symfony/http-kernel/DependencyInjection/LazyLoadingFragmentHandler.php +++ b/vendor/symfony/http-kernel/DependencyInjection/LazyLoadingFragmentHandler.php @@ -23,52 +23,20 @@ use Symfony\Component\HttpKernel\Fragment\FragmentHandler; class LazyLoadingFragmentHandler extends FragmentHandler { private $container; - /** - * @deprecated since version 3.3, to be removed in 4.0 - */ - private $rendererIds = array(); - private $initialized = array(); + private $initialized = []; - /** - * @param ContainerInterface $container A container - * @param RequestStack $requestStack The Request stack that controls the lifecycle of requests - * @param bool $debug Whether the debug mode is enabled or not - */ - public function __construct(ContainerInterface $container, RequestStack $requestStack, $debug = false) + public function __construct(ContainerInterface $container, RequestStack $requestStack, bool $debug = false) { $this->container = $container; - parent::__construct($requestStack, array(), $debug); - } - - /** - * Adds a service as a fragment renderer. - * - * @param string $name The service name - * @param string $renderer The render service id - * - * @deprecated since version 3.3, to be removed in 4.0 - */ - public function addRendererService($name, $renderer) - { - @trigger_error(sprintf('The %s() method is deprecated since Symfony 3.3 and will be removed in 4.0.', __METHOD__), E_USER_DEPRECATED); - - $this->rendererIds[$name] = $renderer; + parent::__construct($requestStack, [], $debug); } /** * {@inheritdoc} */ - public function render($uri, $renderer = 'inline', array $options = array()) + public function render($uri, $renderer = 'inline', array $options = []) { - // BC 3.x, to be removed in 4.0 - if (isset($this->rendererIds[$renderer])) { - $this->addRenderer($this->container->get($this->rendererIds[$renderer])); - unset($this->rendererIds[$renderer]); - - return parent::render($uri, $renderer, $options); - } - if (!isset($this->initialized[$renderer]) && $this->container->has($renderer)) { $this->addRenderer($this->container->get($renderer)); $this->initialized[$renderer] = true; diff --git a/vendor/symfony/http-kernel/DependencyInjection/LoggerPass.php b/vendor/symfony/http-kernel/DependencyInjection/LoggerPass.php index 2ad7f322289f3bf57c07e4d5ed1a5e47afbb4691..b6df1f6e614c8b570a9b4b1f5cef5ad307707132 100644 --- a/vendor/symfony/http-kernel/DependencyInjection/LoggerPass.php +++ b/vendor/symfony/http-kernel/DependencyInjection/LoggerPass.php @@ -12,9 +12,9 @@ namespace Symfony\Component\HttpKernel\DependencyInjection; use Psr\Log\LoggerInterface; -use Symfony\Component\HttpKernel\Log\Logger; use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\HttpKernel\Log\Logger; /** * Registers the default logger if necessary. diff --git a/vendor/symfony/http-kernel/DependencyInjection/MergeExtensionConfigurationPass.php b/vendor/symfony/http-kernel/DependencyInjection/MergeExtensionConfigurationPass.php index dcd73828de0b1f03236cb1bd82df8376186a28a9..83e1b758de75b520c46e26973793a39013fa3cc8 100644 --- a/vendor/symfony/http-kernel/DependencyInjection/MergeExtensionConfigurationPass.php +++ b/vendor/symfony/http-kernel/DependencyInjection/MergeExtensionConfigurationPass.php @@ -31,8 +31,8 @@ class MergeExtensionConfigurationPass extends BaseMergeExtensionConfigurationPas public function process(ContainerBuilder $container) { foreach ($this->extensions as $extension) { - if (!count($container->getExtensionConfig($extension))) { - $container->loadFromExtension($extension, array()); + if (!\count($container->getExtensionConfig($extension))) { + $container->loadFromExtension($extension, []); } } diff --git a/vendor/symfony/http-kernel/DependencyInjection/RegisterControllerArgumentLocatorsPass.php b/vendor/symfony/http-kernel/DependencyInjection/RegisterControllerArgumentLocatorsPass.php index 985dfb71d706431a06784e9e7318e959ee77dfe7..a3f5012e3268ff73d1886275ea575b49af29fa4f 100644 --- a/vendor/symfony/http-kernel/DependencyInjection/RegisterControllerArgumentLocatorsPass.php +++ b/vendor/symfony/http-kernel/DependencyInjection/RegisterControllerArgumentLocatorsPass.php @@ -22,6 +22,7 @@ use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; use Symfony\Component\DependencyInjection\LazyProxy\ProxyHelper; use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\DependencyInjection\TypedReference; +use Symfony\Component\HttpFoundation\Request; /** * Creates the service-locators required by ServiceValueResolver. @@ -32,21 +33,25 @@ class RegisterControllerArgumentLocatorsPass implements CompilerPassInterface { private $resolverServiceId; private $controllerTag; + private $controllerLocator; + private $notTaggedControllerResolverServiceId; - public function __construct($resolverServiceId = 'argument_resolver.service', $controllerTag = 'controller.service_arguments') + public function __construct(string $resolverServiceId = 'argument_resolver.service', string $controllerTag = 'controller.service_arguments', string $controllerLocator = 'argument_resolver.controller_locator', string $notTaggedControllerResolverServiceId = 'argument_resolver.not_tagged_controller') { $this->resolverServiceId = $resolverServiceId; $this->controllerTag = $controllerTag; + $this->controllerLocator = $controllerLocator; + $this->notTaggedControllerResolverServiceId = $notTaggedControllerResolverServiceId; } public function process(ContainerBuilder $container) { - if (false === $container->hasDefinition($this->resolverServiceId)) { + if (false === $container->hasDefinition($this->resolverServiceId) && false === $container->hasDefinition($this->notTaggedControllerResolverServiceId)) { return; } $parameterBag = $container->getParameterBag(); - $controllers = array(); + $controllers = []; foreach ($container->findTaggedServiceIds($this->controllerTag, true) as $id => $tags) { $def = $container->getDefinition($id); @@ -59,7 +64,7 @@ class RegisterControllerArgumentLocatorsPass implements CompilerPassInterface while ($def instanceof ChildDefinition) { $def = $container->findDefinition($def->getParent()); $class = $class ?: $def->getClass(); - $bindings = $def->getBindings(); + $bindings += $def->getBindings(); } $class = $parameterBag->resolveValue($class); @@ -69,14 +74,14 @@ class RegisterControllerArgumentLocatorsPass implements CompilerPassInterface $isContainerAware = $r->implementsInterface(ContainerAwareInterface::class) || is_subclass_of($class, AbstractController::class); // get regular public methods - $methods = array(); - $arguments = array(); + $methods = []; + $arguments = []; foreach ($r->getMethods(\ReflectionMethod::IS_PUBLIC) as $r) { if ('setContainer' === $r->name && $isContainerAware) { continue; } if (!$r->isConstructor() && !$r->isDestructor() && !$r->isAbstract()) { - $methods[strtolower($r->name)] = array($r, $r->getParameters()); + $methods[strtolower($r->name)] = [$r, $r->getParameters()]; } } @@ -86,7 +91,7 @@ class RegisterControllerArgumentLocatorsPass implements CompilerPassInterface $autowire = true; continue; } - foreach (array('action', 'argument', 'id') as $k) { + foreach (['action', 'argument', 'id'] as $k) { if (!isset($attributes[$k][0])) { throw new InvalidArgumentException(sprintf('Missing "%s" attribute on tag "%s" %s for service "%s".', $k, $this->controllerTag, json_encode($attributes, JSON_UNESCAPED_UNICODE), $id)); } @@ -116,35 +121,44 @@ class RegisterControllerArgumentLocatorsPass implements CompilerPassInterface /** @var \ReflectionMethod $r */ // create a per-method map of argument-names to service/type-references - $args = array(); + $args = []; foreach ($parameters as $p) { /** @var \ReflectionParameter $p */ - $type = $target = ProxyHelper::getTypeHint($r, $p, true); + $type = ltrim($target = ProxyHelper::getTypeHint($r, $p), '\\'); $invalidBehavior = ContainerInterface::IGNORE_ON_INVALID_REFERENCE; if (isset($arguments[$r->name][$p->name])) { $target = $arguments[$r->name][$p->name]; if ('?' !== $target[0]) { - $invalidBehavior = ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE; + $invalidBehavior = ContainerInterface::RUNTIME_EXCEPTION_ON_INVALID_REFERENCE; } elseif ('' === $target = (string) substr($target, 1)) { throw new InvalidArgumentException(sprintf('A "%s" tag must have non-empty "id" attributes for service "%s".', $this->controllerTag, $id)); } elseif ($p->allowsNull() && !$p->isOptional()) { $invalidBehavior = ContainerInterface::NULL_ON_INVALID_REFERENCE; } - } elseif (isset($bindings[$bindingName = '$'.$p->name]) || isset($bindings[$bindingName = $type])) { + } elseif (isset($bindings[$bindingName = $type.' $'.$p->name]) || isset($bindings[$bindingName = '$'.$p->name]) || isset($bindings[$bindingName = $type])) { $binding = $bindings[$bindingName]; - list($bindingValue, $bindingId) = $binding->getValues(); + list($bindingValue, $bindingId, , $bindingType, $bindingFile) = $binding->getValues(); + $binding->setValues([$bindingValue, $bindingId, true, $bindingType, $bindingFile]); if (!$bindingValue instanceof Reference) { - continue; + $args[$p->name] = new Reference('.value.'.$container->hash($bindingValue)); + $container->register((string) $args[$p->name], 'mixed') + ->setFactory('current') + ->addArgument([$bindingValue]); + } else { + $args[$p->name] = $bindingValue; } - $binding->setValues(array($bindingValue, $bindingId, true)); - $args[$p->name] = $bindingValue; - continue; - } elseif (!$type || !$autowire) { + } elseif (!$type || !$autowire || '\\' !== $target[0]) { + continue; + } elseif (!$p->allowsNull()) { + $invalidBehavior = ContainerInterface::RUNTIME_EXCEPTION_ON_INVALID_REFERENCE; + } + + if (Request::class === $type) { continue; } @@ -159,16 +173,28 @@ class RegisterControllerArgumentLocatorsPass implements CompilerPassInterface throw new InvalidArgumentException($message); } - $args[$p->name] = $type ? new TypedReference($target, $type, $r->class, $invalidBehavior) : new Reference($target, $invalidBehavior); + $target = ltrim($target, '\\'); + $args[$p->name] = $type ? new TypedReference($target, $type, $invalidBehavior, $p->name) : new Reference($target, $invalidBehavior); } // register the maps as a per-method service-locators if ($args) { - $controllers[$id.':'.$r->name] = ServiceLocatorTagPass::register($container, $args); + $controllers[$id.'::'.$r->name] = ServiceLocatorTagPass::register($container, $args); } } } - $container->getDefinition($this->resolverServiceId) - ->replaceArgument(0, ServiceLocatorTagPass::register($container, $controllers)); + $controllerLocatorRef = ServiceLocatorTagPass::register($container, $controllers); + + if ($container->hasDefinition($this->resolverServiceId)) { + $container->getDefinition($this->resolverServiceId) + ->replaceArgument(0, $controllerLocatorRef); + } + + if ($container->hasDefinition($this->notTaggedControllerResolverServiceId)) { + $container->getDefinition($this->notTaggedControllerResolverServiceId) + ->replaceArgument(0, $controllerLocatorRef); + } + + $container->setAlias($this->controllerLocator, (string) $controllerLocatorRef); } } diff --git a/vendor/symfony/http-kernel/DependencyInjection/RegisterLocaleAwareServicesPass.php b/vendor/symfony/http-kernel/DependencyInjection/RegisterLocaleAwareServicesPass.php new file mode 100644 index 0000000000000000000000000000000000000000..0efb164b72207ca26d8cac1a17304a23c03b8cb3 --- /dev/null +++ b/vendor/symfony/http-kernel/DependencyInjection/RegisterLocaleAwareServicesPass.php @@ -0,0 +1,58 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\DependencyInjection; + +use Symfony\Component\DependencyInjection\Argument\IteratorArgument; +use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Reference; + +/** + * Register all services that have the "kernel.locale_aware" tag into the listener. + * + * @author Pierre Bobiet <pierrebobiet@gmail.com> + */ +class RegisterLocaleAwareServicesPass implements CompilerPassInterface +{ + private $listenerServiceId; + private $localeAwareTag; + + public function __construct(string $listenerServiceId = 'locale_aware_listener', string $localeAwareTag = 'kernel.locale_aware') + { + $this->listenerServiceId = $listenerServiceId; + $this->localeAwareTag = $localeAwareTag; + } + + public function process(ContainerBuilder $container) + { + if (!$container->hasDefinition($this->listenerServiceId)) { + return; + } + + $services = []; + + foreach ($container->findTaggedServiceIds($this->localeAwareTag) as $id => $tags) { + $services[] = new Reference($id); + } + + if (!$services) { + $container->removeDefinition($this->listenerServiceId); + + return; + } + + $container + ->getDefinition($this->listenerServiceId) + ->setArgument(0, new IteratorArgument($services)) + ; + } +} diff --git a/vendor/symfony/http-kernel/DependencyInjection/RemoveEmptyControllerArgumentLocatorsPass.php b/vendor/symfony/http-kernel/DependencyInjection/RemoveEmptyControllerArgumentLocatorsPass.php index ab50cec3531bf01f146b97e2879aeb9537e832aa..596b6188f66cbea72d97cfa4a06460409ffc57ce 100644 --- a/vendor/symfony/http-kernel/DependencyInjection/RemoveEmptyControllerArgumentLocatorsPass.php +++ b/vendor/symfony/http-kernel/DependencyInjection/RemoveEmptyControllerArgumentLocatorsPass.php @@ -21,21 +21,16 @@ use Symfony\Component\DependencyInjection\ContainerBuilder; */ class RemoveEmptyControllerArgumentLocatorsPass implements CompilerPassInterface { - private $resolverServiceId; + private $controllerLocator; - public function __construct($resolverServiceId = 'argument_resolver.service') + public function __construct(string $controllerLocator = 'argument_resolver.controller_locator') { - $this->resolverServiceId = $resolverServiceId; + $this->controllerLocator = $controllerLocator; } public function process(ContainerBuilder $container) { - if (false === $container->hasDefinition($this->resolverServiceId)) { - return; - } - - $serviceResolver = $container->getDefinition($this->resolverServiceId); - $controllerLocator = $container->getDefinition((string) $serviceResolver->getArgument(0)); + $controllerLocator = $container->findDefinition($this->controllerLocator); $controllers = $controllerLocator->getArgument(0); foreach ($controllers as $controller => $argumentRef) { @@ -47,8 +42,7 @@ class RemoveEmptyControllerArgumentLocatorsPass implements CompilerPassInterface } else { // any methods listed for call-at-instantiation cannot be actions $reason = false; - $action = substr(strrchr($controller, ':'), 1); - $id = substr($controller, 0, -1 - strlen($action)); + list($id, $action) = explode('::', $controller); $controllerDef = $container->getDefinition($id); foreach ($controllerDef->getMethodCalls() as list($method)) { if (0 === strcasecmp($action, $method)) { @@ -57,9 +51,9 @@ class RemoveEmptyControllerArgumentLocatorsPass implements CompilerPassInterface } } if (!$reason) { - if ($controllerDef->getClass() === $id) { - $controllers[$id.'::'.$action] = $argumentRef; - } + // Deprecated since Symfony 4.1. See Symfony\Component\HttpKernel\Controller\ContainerControllerResolver + $controllers[$id.':'.$action] = $argumentRef; + if ('__invoke' === $action) { $controllers[$id] = $argumentRef; } diff --git a/vendor/symfony/http-kernel/DependencyInjection/ResettableServicePass.php b/vendor/symfony/http-kernel/DependencyInjection/ResettableServicePass.php index 29433a6d5b19581f77a1ebd6ac8554300d02d53c..c1199f639edf8f2fda5ea60ec37dd0edb4699cc1 100644 --- a/vendor/symfony/http-kernel/DependencyInjection/ResettableServicePass.php +++ b/vendor/symfony/http-kernel/DependencyInjection/ResettableServicePass.php @@ -25,7 +25,7 @@ class ResettableServicePass implements CompilerPassInterface { private $tagName; - public function __construct($tagName = 'kernel.reset') + public function __construct(string $tagName = 'kernel.reset') { $this->tagName = $tagName; } @@ -39,7 +39,7 @@ class ResettableServicePass implements CompilerPassInterface return; } - $services = $methods = array(); + $services = $methods = []; foreach ($container->findTaggedServiceIds($this->tagName, true) as $id => $tags) { $services[$id] = new Reference($id, ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE); diff --git a/vendor/symfony/http-kernel/DependencyInjection/ServicesResetter.php b/vendor/symfony/http-kernel/DependencyInjection/ServicesResetter.php index b82d2fef3c0567b042ee0872887cfa740bf9b6da..734fadbd74176180d7672571dbad7df64a1e1c3f 100644 --- a/vendor/symfony/http-kernel/DependencyInjection/ServicesResetter.php +++ b/vendor/symfony/http-kernel/DependencyInjection/ServicesResetter.php @@ -11,6 +11,8 @@ namespace Symfony\Component\HttpKernel\DependencyInjection; +use Symfony\Contracts\Service\ResetInterface; + /** * Resets provided services. * @@ -19,7 +21,7 @@ namespace Symfony\Component\HttpKernel\DependencyInjection; * * @internal */ -class ServicesResetter +class ServicesResetter implements ResetInterface { private $resettableServices; private $resetMethods; diff --git a/vendor/symfony/http-kernel/Event/ControllerArgumentsEvent.php b/vendor/symfony/http-kernel/Event/ControllerArgumentsEvent.php new file mode 100644 index 0000000000000000000000000000000000000000..3dc6ea50ede17347f7432fca5344c85ed38e41b8 --- /dev/null +++ b/vendor/symfony/http-kernel/Event/ControllerArgumentsEvent.php @@ -0,0 +1,28 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Event; + +/** + * Allows filtering of controller arguments. + * + * You can call getController() to retrieve the controller and getArguments + * to retrieve the current arguments. With setArguments() you can replace + * arguments that are used to call the controller. + * + * Arguments set in the event must be compatible with the signature of the + * controller. + * + * @author Christophe Coevoet <stof@notk.org> + */ +class ControllerArgumentsEvent extends FilterControllerArgumentsEvent +{ +} diff --git a/vendor/symfony/http-kernel/Event/ControllerEvent.php b/vendor/symfony/http-kernel/Event/ControllerEvent.php new file mode 100644 index 0000000000000000000000000000000000000000..9afb818a1d4f6f7249fe4bc5d7035e528e336391 --- /dev/null +++ b/vendor/symfony/http-kernel/Event/ControllerEvent.php @@ -0,0 +1,27 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Event; + +/** + * Allows filtering of a controller callable. + * + * You can call getController() to retrieve the current controller. With + * setController() you can set a new controller that is used in the processing + * of the request. + * + * Controllers should be callables. + * + * @author Bernhard Schussek <bschussek@gmail.com> + */ +class ControllerEvent extends FilterControllerEvent +{ +} diff --git a/vendor/symfony/http-kernel/Event/ExceptionEvent.php b/vendor/symfony/http-kernel/Event/ExceptionEvent.php new file mode 100644 index 0000000000000000000000000000000000000000..d3b2d8f6061f33594de04ff29603e70575cf33c4 --- /dev/null +++ b/vendor/symfony/http-kernel/Event/ExceptionEvent.php @@ -0,0 +1,29 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Event; + +/** + * Allows to create a response for a thrown exception. + * + * Call setResponse() to set the response that will be returned for the + * current request. The propagation of this event is stopped as soon as a + * response is set. + * + * You can also call setException() to replace the thrown exception. This + * exception will be thrown if no response is set during processing of this + * event. + * + * @author Bernhard Schussek <bschussek@gmail.com> + */ +class ExceptionEvent extends GetResponseForExceptionEvent +{ +} diff --git a/vendor/symfony/http-kernel/Event/FilterControllerArgumentsEvent.php b/vendor/symfony/http-kernel/Event/FilterControllerArgumentsEvent.php index 2b08f2d770020115eec2b5829baae421b31f7179..f3c5dc34aa50a6e7840839e8e93b3e2152f303e9 100644 --- a/vendor/symfony/http-kernel/Event/FilterControllerArgumentsEvent.php +++ b/vendor/symfony/http-kernel/Event/FilterControllerArgumentsEvent.php @@ -11,26 +11,17 @@ namespace Symfony\Component\HttpKernel\Event; -use Symfony\Component\HttpKernel\HttpKernelInterface; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpKernel\HttpKernelInterface; /** - * Allows filtering of controller arguments. - * - * You can call getController() to retrieve the controller and getArguments - * to retrieve the current arguments. With setArguments() you can replace - * arguments that are used to call the controller. - * - * Arguments set in the event must be compatible with the signature of the - * controller. - * - * @author Christophe Coevoet <stof@notk.org> + * @deprecated since Symfony 4.3, use ControllerArgumentsEvent instead */ class FilterControllerArgumentsEvent extends FilterControllerEvent { private $arguments; - public function __construct(HttpKernelInterface $kernel, callable $controller, array $arguments, Request $request, $requestType) + public function __construct(HttpKernelInterface $kernel, callable $controller, array $arguments, Request $request, ?int $requestType) { parent::__construct($kernel, $controller, $request, $requestType); diff --git a/vendor/symfony/http-kernel/Event/FilterControllerEvent.php b/vendor/symfony/http-kernel/Event/FilterControllerEvent.php index 84cbc2eaf83655c77da5b9f9be7c1d91dc319292..74fa681f809849de98c4dfbcb5ec3762c128b595 100644 --- a/vendor/symfony/http-kernel/Event/FilterControllerEvent.php +++ b/vendor/symfony/http-kernel/Event/FilterControllerEvent.php @@ -11,25 +11,17 @@ namespace Symfony\Component\HttpKernel\Event; -use Symfony\Component\HttpKernel\HttpKernelInterface; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpKernel\HttpKernelInterface; /** - * Allows filtering of a controller callable. - * - * You can call getController() to retrieve the current controller. With - * setController() you can set a new controller that is used in the processing - * of the request. - * - * Controllers should be callables. - * - * @author Bernhard Schussek <bschussek@gmail.com> + * @deprecated since Symfony 4.3, use ControllerEvent instead */ class FilterControllerEvent extends KernelEvent { private $controller; - public function __construct(HttpKernelInterface $kernel, callable $controller, Request $request, $requestType) + public function __construct(HttpKernelInterface $kernel, callable $controller, Request $request, ?int $requestType) { parent::__construct($kernel, $request, $requestType); diff --git a/vendor/symfony/http-kernel/Event/FilterResponseEvent.php b/vendor/symfony/http-kernel/Event/FilterResponseEvent.php index 53a7efce76cae6793f12df29cc2c4fbb2150ec11..eaa2e8256540eed2aab76d08d0dddb8dccd188e0 100644 --- a/vendor/symfony/http-kernel/Event/FilterResponseEvent.php +++ b/vendor/symfony/http-kernel/Event/FilterResponseEvent.php @@ -11,24 +11,18 @@ namespace Symfony\Component\HttpKernel\Event; -use Symfony\Component\HttpKernel\HttpKernelInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpKernel\HttpKernelInterface; /** - * Allows to filter a Response object. - * - * You can call getResponse() to retrieve the current response. With - * setResponse() you can set a new response that will be returned to the - * browser. - * - * @author Bernhard Schussek <bschussek@gmail.com> + * @deprecated since Symfony 4.3, use ResponseEvent instead */ class FilterResponseEvent extends KernelEvent { private $response; - public function __construct(HttpKernelInterface $kernel, Request $request, $requestType, Response $response) + public function __construct(HttpKernelInterface $kernel, Request $request, int $requestType, Response $response) { parent::__construct($kernel, $request, $requestType); diff --git a/vendor/symfony/http-kernel/Event/GetResponseEvent.php b/vendor/symfony/http-kernel/Event/GetResponseEvent.php index f7745ea3dc16028cd7b1023b9814ebe164b88d76..fbed7beef570ffa4981ab6a916e4f0e84d3351d6 100644 --- a/vendor/symfony/http-kernel/Event/GetResponseEvent.php +++ b/vendor/symfony/http-kernel/Event/GetResponseEvent.php @@ -14,13 +14,7 @@ namespace Symfony\Component\HttpKernel\Event; use Symfony\Component\HttpFoundation\Response; /** - * Allows to create a response for a request. - * - * Call setResponse() to set the response that will be returned for the - * current request. The propagation of this event is stopped as soon as a - * response is set. - * - * @author Bernhard Schussek <bschussek@gmail.com> + * @deprecated since Symfony 4.3, use RequestEvent instead */ class GetResponseEvent extends KernelEvent { @@ -29,7 +23,7 @@ class GetResponseEvent extends KernelEvent /** * Returns the response object. * - * @return Response + * @return Response|null */ public function getResponse() { diff --git a/vendor/symfony/http-kernel/Event/GetResponseForControllerResultEvent.php b/vendor/symfony/http-kernel/Event/GetResponseForControllerResultEvent.php index f70ce09e0a40a765c7400df2d611f8acec0ea21d..4e70dbc63e53e596837e11b9002a40aa6df9ea89 100644 --- a/vendor/symfony/http-kernel/Event/GetResponseForControllerResultEvent.php +++ b/vendor/symfony/http-kernel/Event/GetResponseForControllerResultEvent.php @@ -11,19 +11,13 @@ namespace Symfony\Component\HttpKernel\Event; -use Symfony\Component\HttpKernel\HttpKernelInterface; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpKernel\HttpKernelInterface; /** - * Allows to create a response for the return value of a controller. - * - * Call setResponse() to set the response that will be returned for the - * current request. The propagation of this event is stopped as soon as a - * response is set. - * - * @author Bernhard Schussek <bschussek@gmail.com> + * @deprecated since Symfony 4.3, use ViewEvent instead */ -class GetResponseForControllerResultEvent extends GetResponseEvent +class GetResponseForControllerResultEvent extends RequestEvent { /** * The return value of the controller. @@ -32,7 +26,7 @@ class GetResponseForControllerResultEvent extends GetResponseEvent */ private $controllerResult; - public function __construct(HttpKernelInterface $kernel, Request $request, $requestType, $controllerResult) + public function __construct(HttpKernelInterface $kernel, Request $request, int $requestType, $controllerResult) { parent::__construct($kernel, $request, $requestType); diff --git a/vendor/symfony/http-kernel/Event/GetResponseForExceptionEvent.php b/vendor/symfony/http-kernel/Event/GetResponseForExceptionEvent.php index 751b74515b48b23884b161f299df7cc222710342..3476c7e62a0ccd596b55e67a9fc95b89fada412f 100644 --- a/vendor/symfony/http-kernel/Event/GetResponseForExceptionEvent.php +++ b/vendor/symfony/http-kernel/Event/GetResponseForExceptionEvent.php @@ -11,23 +11,13 @@ namespace Symfony\Component\HttpKernel\Event; -use Symfony\Component\HttpKernel\HttpKernelInterface; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpKernel\HttpKernelInterface; /** - * Allows to create a response for a thrown exception. - * - * Call setResponse() to set the response that will be returned for the - * current request. The propagation of this event is stopped as soon as a - * response is set. - * - * You can also call setException() to replace the thrown exception. This - * exception will be thrown if no response is set during processing of this - * event. - * - * @author Bernhard Schussek <bschussek@gmail.com> + * @deprecated since Symfony 4.3, use ExceptionEvent instead */ -class GetResponseForExceptionEvent extends GetResponseEvent +class GetResponseForExceptionEvent extends RequestEvent { /** * The exception object. @@ -41,7 +31,7 @@ class GetResponseForExceptionEvent extends GetResponseEvent */ private $allowCustomResponseCode = false; - public function __construct(HttpKernelInterface $kernel, Request $request, $requestType, \Exception $e) + public function __construct(HttpKernelInterface $kernel, Request $request, int $requestType, \Exception $e) { parent::__construct($kernel, $request, $requestType); diff --git a/vendor/symfony/http-kernel/Event/KernelEvent.php b/vendor/symfony/http-kernel/Event/KernelEvent.php index 992f6b4dc033e3443a259564a53366a73258085c..f3db8a60d9ec23d884ba71179e5d639805257820 100644 --- a/vendor/symfony/http-kernel/Event/KernelEvent.php +++ b/vendor/symfony/http-kernel/Event/KernelEvent.php @@ -11,9 +11,9 @@ namespace Symfony\Component\HttpKernel\Event; -use Symfony\Component\HttpKernel\HttpKernelInterface; -use Symfony\Component\HttpFoundation\Request; use Symfony\Component\EventDispatcher\Event; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpKernel\HttpKernelInterface; /** * Base class for events thrown in the HttpKernel component. @@ -32,7 +32,7 @@ class KernelEvent extends Event * @param int $requestType The request type the kernel is currently processing; one of * HttpKernelInterface::MASTER_REQUEST or HttpKernelInterface::SUB_REQUEST */ - public function __construct(HttpKernelInterface $kernel, Request $request, $requestType) + public function __construct(HttpKernelInterface $kernel, Request $request, ?int $requestType) { $this->kernel = $kernel; $this->request = $request; diff --git a/vendor/symfony/http-kernel/Event/PostResponseEvent.php b/vendor/symfony/http-kernel/Event/PostResponseEvent.php index 2406fddbe89dbdd23ddce01ee79d2e781579d1ea..b86bf077424120725898e0d6fa7e173222a0fd6a 100644 --- a/vendor/symfony/http-kernel/Event/PostResponseEvent.php +++ b/vendor/symfony/http-kernel/Event/PostResponseEvent.php @@ -11,17 +11,12 @@ namespace Symfony\Component\HttpKernel\Event; -use Symfony\Component\HttpKernel\HttpKernelInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpKernel\HttpKernelInterface; /** - * Allows to execute logic after a response was sent. - * - * Since it's only triggered on master requests, the `getRequestType()` method - * will always return the value of `HttpKernelInterface::MASTER_REQUEST`. - * - * @author Jordi Boggiano <j.boggiano@seld.be> + * @deprecated since Symfony 4.3, use TerminateEvent instead */ class PostResponseEvent extends KernelEvent { diff --git a/vendor/symfony/http-kernel/Event/RequestEvent.php b/vendor/symfony/http-kernel/Event/RequestEvent.php new file mode 100644 index 0000000000000000000000000000000000000000..c1beb929f31ea6e2538afaa5819aa51dfba5d963 --- /dev/null +++ b/vendor/symfony/http-kernel/Event/RequestEvent.php @@ -0,0 +1,25 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Event; + +/** + * Allows to create a response for a request. + * + * Call setResponse() to set the response that will be returned for the + * current request. The propagation of this event is stopped as soon as a + * response is set. + * + * @author Bernhard Schussek <bschussek@gmail.com> + */ +class RequestEvent extends GetResponseEvent +{ +} diff --git a/vendor/symfony/http-kernel/Event/ResponseEvent.php b/vendor/symfony/http-kernel/Event/ResponseEvent.php new file mode 100644 index 0000000000000000000000000000000000000000..88c1996eaa95ba503fcda646d1962af9220614e1 --- /dev/null +++ b/vendor/symfony/http-kernel/Event/ResponseEvent.php @@ -0,0 +1,25 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Event; + +/** + * Allows to filter a Response object. + * + * You can call getResponse() to retrieve the current response. With + * setResponse() you can set a new response that will be returned to the + * browser. + * + * @author Bernhard Schussek <bschussek@gmail.com> + */ +class ResponseEvent extends FilterResponseEvent +{ +} diff --git a/vendor/symfony/http-kernel/Event/TerminateEvent.php b/vendor/symfony/http-kernel/Event/TerminateEvent.php new file mode 100644 index 0000000000000000000000000000000000000000..6ce23e43f310d6c3f83bb69c696b850e0104504a --- /dev/null +++ b/vendor/symfony/http-kernel/Event/TerminateEvent.php @@ -0,0 +1,24 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Event; + +/** + * Allows to execute logic after a response was sent. + * + * Since it's only triggered on master requests, the `getRequestType()` method + * will always return the value of `HttpKernelInterface::MASTER_REQUEST`. + * + * @author Jordi Boggiano <j.boggiano@seld.be> + */ +class TerminateEvent extends PostResponseEvent +{ +} diff --git a/vendor/symfony/http-kernel/Event/ViewEvent.php b/vendor/symfony/http-kernel/Event/ViewEvent.php new file mode 100644 index 0000000000000000000000000000000000000000..1cb7e23980ba995d87f93fc81525abcedb2efd04 --- /dev/null +++ b/vendor/symfony/http-kernel/Event/ViewEvent.php @@ -0,0 +1,25 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Event; + +/** + * Allows to create a response for the return value of a controller. + * + * Call setResponse() to set the response that will be returned for the + * current request. The propagation of this event is stopped as soon as a + * response is set. + * + * @author Bernhard Schussek <bschussek@gmail.com> + */ +class ViewEvent extends GetResponseForControllerResultEvent +{ +} diff --git a/vendor/symfony/http-kernel/EventListener/AbstractSessionListener.php b/vendor/symfony/http-kernel/EventListener/AbstractSessionListener.php index dff29ee80b4182b747313256cc2a50b91bf6eae5..0a6789d85ae2e7e9fb1b897eb6876ba5afff9c98 100644 --- a/vendor/symfony/http-kernel/EventListener/AbstractSessionListener.php +++ b/vendor/symfony/http-kernel/EventListener/AbstractSessionListener.php @@ -11,33 +11,60 @@ namespace Symfony\Component\HttpKernel\EventListener; +use Psr\Container\ContainerInterface; +use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\HttpFoundation\Session\Session; use Symfony\Component\HttpFoundation\Session\SessionInterface; use Symfony\Component\HttpKernel\Event\FilterResponseEvent; +use Symfony\Component\HttpKernel\Event\FinishRequestEvent; use Symfony\Component\HttpKernel\Event\GetResponseEvent; use Symfony\Component\HttpKernel\KernelEvents; -use Symfony\Component\EventDispatcher\EventSubscriberInterface; /** - * Sets the session in the request. + * Sets the session onto the request on the "kernel.request" event and saves + * it on the "kernel.response" event. + * + * In addition, if the session has been started it overrides the Cache-Control + * header in such a way that all caching is disabled in that case. + * If you have a scenario where caching responses with session information in + * them makes sense, you can disable this behaviour by setting the header + * AbstractSessionListener::NO_AUTO_CACHE_CONTROL_HEADER on the response. * * @author Johannes M. Schmitt <schmittjoh@gmail.com> + * @author Tobias Schultze <http://tobion.de> + * + * @internal since Symfony 4.3 */ abstract class AbstractSessionListener implements EventSubscriberInterface { + const NO_AUTO_CACHE_CONTROL_HEADER = 'Symfony-Session-NoAutoCacheControl'; + + protected $container; + private $sessionUsageStack = []; + + public function __construct(ContainerInterface $container = null) + { + $this->container = $container; + } + public function onKernelRequest(GetResponseEvent $event) { if (!$event->isMasterRequest()) { return; } + $session = null; $request = $event->getRequest(); - $session = $this->getSession(); - if (null === $session || $request->hasSession()) { - return; + if ($request->hasSession()) { + // no-op + } elseif (method_exists($request, 'setSessionFactory')) { + $request->setSessionFactory(function () { return $this->getSession(); }); + } elseif ($session = $this->getSession()) { + $request->setSession($session); } - $request->setSession($session); + $session = $session ?? ($this->container && $this->container->has('initialized_session') ? $this->container->get('initialized_session') : null); + $this->sessionUsageStack[] = $session instanceof Session ? $session->getUsageIndex() : 0; } public function onKernelResponse(FilterResponseEvent $event) @@ -46,25 +73,73 @@ abstract class AbstractSessionListener implements EventSubscriberInterface return; } - if (!$session = $event->getRequest()->getSession()) { + $response = $event->getResponse(); + $autoCacheControl = !$response->headers->has(self::NO_AUTO_CACHE_CONTROL_HEADER); + // Always remove the internal header if present + $response->headers->remove(self::NO_AUTO_CACHE_CONTROL_HEADER); + + if (!$session = $this->container && $this->container->has('initialized_session') ? $this->container->get('initialized_session') : $event->getRequest()->getSession()) { return; } - if ($session->isStarted() || ($session instanceof Session && $session->hasBeenStarted())) { - $event->getResponse() - ->setPrivate() - ->setMaxAge(0) - ->headers->addCacheControlDirective('must-revalidate'); + if ($session instanceof Session ? $session->getUsageIndex() !== end($this->sessionUsageStack) : $session->isStarted()) { + if ($autoCacheControl) { + $response + ->setExpires(new \DateTime()) + ->setPrivate() + ->setMaxAge(0) + ->headers->addCacheControlDirective('must-revalidate'); + } + } + + if ($session->isStarted()) { + /* + * Saves the session, in case it is still open, before sending the response/headers. + * + * This ensures several things in case the developer did not save the session explicitly: + * + * * If a session save handler without locking is used, it ensures the data is available + * on the next request, e.g. after a redirect. PHPs auto-save at script end via + * session_register_shutdown is executed after fastcgi_finish_request. So in this case + * the data could be missing the next request because it might not be saved the moment + * the new request is processed. + * * A locking save handler (e.g. the native 'files') circumvents concurrency problems like + * the one above. But by saving the session before long-running things in the terminate event, + * we ensure the session is not blocked longer than needed. + * * When regenerating the session ID no locking is involved in PHPs session design. See + * https://bugs.php.net/61470 for a discussion. So in this case, the session must + * be saved anyway before sending the headers with the new session ID. Otherwise session + * data could get lost again for concurrent requests with the new ID. One result could be + * that you get logged out after just logging in. + * + * This listener should be executed as one of the last listeners, so that previous listeners + * can still operate on the open session. This prevents the overhead of restarting it. + * Listeners after closing the session can still work with the session as usual because + * Symfonys session implementation starts the session on demand. So writing to it after + * it is saved will just restart it. + */ + $session->save(); + } + } + + /** + * @internal + */ + public function onFinishRequest(FinishRequestEvent $event) + { + if ($event->isMasterRequest()) { + array_pop($this->sessionUsageStack); } } public static function getSubscribedEvents() { - return array( - KernelEvents::REQUEST => array('onKernelRequest', 128), - // low priority to come after regular response listeners, same as SaveSessionListener - KernelEvents::RESPONSE => array('onKernelResponse', -1000), - ); + return [ + KernelEvents::REQUEST => ['onKernelRequest', 128], + // low priority to come after regular response listeners, but higher than StreamedResponseListener + KernelEvents::RESPONSE => ['onKernelResponse', -1000], + KernelEvents::FINISH_REQUEST => ['onFinishRequest'], + ]; } /** diff --git a/vendor/symfony/http-kernel/EventListener/AbstractTestSessionListener.php b/vendor/symfony/http-kernel/EventListener/AbstractTestSessionListener.php index 5f0ea5c0a9c08b727120ba790dbfe55d9f805ab6..054695e6f2ab4cf0c5603a462ddb09e8eaf940f3 100644 --- a/vendor/symfony/http-kernel/EventListener/AbstractTestSessionListener.php +++ b/vendor/symfony/http-kernel/EventListener/AbstractTestSessionListener.php @@ -11,13 +11,13 @@ namespace Symfony\Component\HttpKernel\EventListener; +use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\HttpFoundation\Cookie; use Symfony\Component\HttpFoundation\Session\Session; use Symfony\Component\HttpFoundation\Session\SessionInterface; -use Symfony\Component\HttpKernel\KernelEvents; use Symfony\Component\HttpKernel\Event\FilterResponseEvent; use Symfony\Component\HttpKernel\Event\GetResponseEvent; -use Symfony\Component\EventDispatcher\EventSubscriberInterface; +use Symfony\Component\HttpKernel\KernelEvents; /** * TestSessionListener. @@ -26,9 +26,19 @@ use Symfony\Component\EventDispatcher\EventSubscriberInterface; * * @author Bulat Shakirzyanov <mallluhuct@gmail.com> * @author Fabien Potencier <fabien@symfony.com> + * + * @internal since Symfony 4.3 */ abstract class AbstractTestSessionListener implements EventSubscriberInterface { + private $sessionId; + private $sessionOptions; + + public function __construct(array $sessionOptions = []) + { + $this->sessionOptions = $sessionOptions; + } + public function onKernelRequest(GetResponseEvent $event) { if (!$event->isMasterRequest()) { @@ -44,7 +54,8 @@ abstract class AbstractTestSessionListener implements EventSubscriberInterface $cookies = $event->getRequest()->cookies; if ($cookies->has($session->getName())) { - $session->setId($cookies->get($session->getName())); + $this->sessionId = $cookies->get($session->getName()); + $session->setId($this->sessionId); } } @@ -58,26 +69,41 @@ abstract class AbstractTestSessionListener implements EventSubscriberInterface return; } - if (!$session = $event->getRequest()->getSession()) { + $request = $event->getRequest(); + if (!$request->hasSession()) { return; } + $session = $request->getSession(); if ($wasStarted = $session->isStarted()) { $session->save(); } - if ($session instanceof Session ? !$session->isEmpty() : $wasStarted) { - $params = session_get_cookie_params(); - $event->getResponse()->headers->setCookie(new Cookie($session->getName(), $session->getId(), 0 === $params['lifetime'] ? 0 : time() + $params['lifetime'], $params['path'], $params['domain'], $params['secure'], $params['httponly'])); + if ($session instanceof Session ? !$session->isEmpty() || (null !== $this->sessionId && $session->getId() !== $this->sessionId) : $wasStarted) { + $params = session_get_cookie_params() + ['samesite' => null]; + foreach ($this->sessionOptions as $k => $v) { + if (0 === strpos($k, 'cookie_')) { + $params[substr($k, 7)] = $v; + } + } + + foreach ($event->getResponse()->headers->getCookies() as $cookie) { + if ($session->getName() === $cookie->getName() && $params['path'] === $cookie->getPath() && $params['domain'] == $cookie->getDomain()) { + return; + } + } + + $event->getResponse()->headers->setCookie(new Cookie($session->getName(), $session->getId(), 0 === $params['lifetime'] ? 0 : time() + $params['lifetime'], $params['path'], $params['domain'], $params['secure'], $params['httponly'], false, $params['samesite'] ?: null)); + $this->sessionId = $session->getId(); } } public static function getSubscribedEvents() { - return array( - KernelEvents::REQUEST => array('onKernelRequest', 192), - KernelEvents::RESPONSE => array('onKernelResponse', -128), - ); + return [ + KernelEvents::REQUEST => ['onKernelRequest', 192], + KernelEvents::RESPONSE => ['onKernelResponse', -128], + ]; } /** diff --git a/vendor/symfony/http-kernel/EventListener/AddRequestFormatsListener.php b/vendor/symfony/http-kernel/EventListener/AddRequestFormatsListener.php index f21fc6ab7c785fb6288db0f131ea348aad347ff7..47c7069c9eadc3b7a612ce141fd872c4bce92c01 100644 --- a/vendor/symfony/http-kernel/EventListener/AddRequestFormatsListener.php +++ b/vendor/symfony/http-kernel/EventListener/AddRequestFormatsListener.php @@ -12,13 +12,15 @@ namespace Symfony\Component\HttpKernel\EventListener; use Symfony\Component\EventDispatcher\EventSubscriberInterface; -use Symfony\Component\HttpKernel\KernelEvents; use Symfony\Component\HttpKernel\Event\GetResponseEvent; +use Symfony\Component\HttpKernel\KernelEvents; /** * Adds configured formats to each request. * * @author Gildas Quemener <gildas.quemener@gmail.com> + * + * @final since Symfony 4.3 */ class AddRequestFormatsListener implements EventSubscriberInterface { @@ -45,6 +47,6 @@ class AddRequestFormatsListener implements EventSubscriberInterface */ public static function getSubscribedEvents() { - return array(KernelEvents::REQUEST => array('onKernelRequest', 1)); + return [KernelEvents::REQUEST => ['onKernelRequest', 100]]; } } diff --git a/vendor/symfony/http-kernel/EventListener/DebugHandlersListener.php b/vendor/symfony/http-kernel/EventListener/DebugHandlersListener.php index 2911caa115bf20b7374c60c5efc7709a71880a93..b28ad7b83e5e4a725f252f6f3c8403456b165c02 100644 --- a/vendor/symfony/http-kernel/EventListener/DebugHandlersListener.php +++ b/vendor/symfony/http-kernel/EventListener/DebugHandlersListener.php @@ -12,15 +12,19 @@ namespace Symfony\Component\HttpKernel\EventListener; use Psr\Log\LoggerInterface; +use Symfony\Component\Console\ConsoleEvents; +use Symfony\Component\Console\Event\ConsoleEvent; +use Symfony\Component\Console\Output\ConsoleOutputInterface; use Symfony\Component\Debug\ErrorHandler; use Symfony\Component\Debug\ExceptionHandler; use Symfony\Component\EventDispatcher\Event; use Symfony\Component\EventDispatcher\EventSubscriberInterface; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpKernel\Debug\FileLinkFormatter; +use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent; use Symfony\Component\HttpKernel\Event\KernelEvent; use Symfony\Component\HttpKernel\KernelEvents; -use Symfony\Component\Console\ConsoleEvents; -use Symfony\Component\Console\Event\ConsoleEvent; -use Symfony\Component\Console\Output\ConsoleOutputInterface; /** * Configures errors and exceptions handlers. @@ -36,27 +40,29 @@ class DebugHandlersListener implements EventSubscriberInterface private $scream; private $fileLinkFormat; private $scope; + private $charset; private $firstCall = true; private $hasTerminatedWithException; /** - * @param callable|null $exceptionHandler A handler that will be called on Exception - * @param LoggerInterface|null $logger A PSR-3 logger - * @param array|int $levels An array map of E_* to LogLevel::* or an integer bit field of E_* constants - * @param int|null $throwAt Thrown errors in a bit field of E_* constants, or null to keep the current value - * @param bool $scream Enables/disables screaming mode, where even silenced errors are logged - * @param string|array $fileLinkFormat The format for links to source files - * @param bool $scope Enables/disables scoping mode + * @param callable|null $exceptionHandler A handler that will be called on Exception + * @param LoggerInterface|null $logger A PSR-3 logger + * @param array|int $levels An array map of E_* to LogLevel::* or an integer bit field of E_* constants + * @param int|null $throwAt Thrown errors in a bit field of E_* constants, or null to keep the current value + * @param bool $scream Enables/disables screaming mode, where even silenced errors are logged + * @param string|FileLinkFormatter|null $fileLinkFormat The format for links to source files + * @param bool $scope Enables/disables scoping mode */ - public function __construct(callable $exceptionHandler = null, LoggerInterface $logger = null, $levels = E_ALL, $throwAt = E_ALL, $scream = true, $fileLinkFormat = null, $scope = true) + public function __construct(callable $exceptionHandler = null, LoggerInterface $logger = null, $levels = E_ALL, ?int $throwAt = E_ALL, bool $scream = true, $fileLinkFormat = null, bool $scope = true, string $charset = null) { $this->exceptionHandler = $exceptionHandler; $this->logger = $logger; $this->levels = null === $levels ? E_ALL : $levels; - $this->throwAt = is_numeric($throwAt) ? (int) $throwAt : (null === $throwAt ? null : ($throwAt ? E_ALL : null)); - $this->scream = (bool) $scream; + $this->throwAt = \is_int($throwAt) ? $throwAt : (null === $throwAt ? null : ($throwAt ? E_ALL : null)); + $this->scream = $scream; $this->fileLinkFormat = $fileLinkFormat; - $this->scope = (bool) $scope; + $this->scope = $scope; + $this->charset = $charset; } /** @@ -70,14 +76,14 @@ class DebugHandlersListener implements EventSubscriberInterface $this->firstCall = $this->hasTerminatedWithException = false; $handler = set_exception_handler('var_dump'); - $handler = is_array($handler) ? $handler[0] : null; + $handler = \is_array($handler) ? $handler[0] : null; restore_exception_handler(); if ($this->logger || null !== $this->throwAt) { if ($handler instanceof ErrorHandler) { if ($this->logger) { $handler->setDefaultLogger($this->logger, $this->levels); - if (is_array($this->levels)) { + if (\is_array($this->levels)) { $levels = 0; foreach ($this->levels as $type => $log) { $levels |= $type; @@ -105,7 +111,7 @@ class DebugHandlersListener implements EventSubscriberInterface if (method_exists($kernel = $event->getKernel(), 'terminateWithException')) { $request = $event->getRequest(); $hasRun = &$this->hasTerminatedWithException; - $this->exceptionHandler = function (\Exception $e) use ($kernel, $request, &$hasRun) { + $this->exceptionHandler = static function (\Exception $e) use ($kernel, $request, &$hasRun) { if ($hasRun) { throw $e; } @@ -126,7 +132,7 @@ class DebugHandlersListener implements EventSubscriberInterface if ($this->exceptionHandler) { if ($handler instanceof ErrorHandler) { $h = $handler->setExceptionHandler('var_dump'); - if (is_array($h) && $h[0] instanceof ExceptionHandler) { + if (\is_array($h) && $h[0] instanceof ExceptionHandler) { $handler->setExceptionHandler($h); $handler = $h[0]; } else { @@ -143,14 +149,36 @@ class DebugHandlersListener implements EventSubscriberInterface } } + /** + * @internal + */ + public function onKernelException(GetResponseForExceptionEvent $event) + { + if (!$this->hasTerminatedWithException || !$event->isMasterRequest()) { + return; + } + + $debug = $this->scream && $this->scope; + $controller = function (Request $request) use ($debug) { + $e = $request->attributes->get('exception'); + $handler = new ExceptionHandler($debug, $this->charset, $this->fileLinkFormat); + + return new Response($handler->getHtml($e), $e->getStatusCode(), $e->getHeaders()); + }; + + (new ExceptionListener($controller, $this->logger, $debug))->onKernelException($event); + } + public static function getSubscribedEvents() { - $events = array(KernelEvents::REQUEST => array('configure', 2048)); + $events = [KernelEvents::REQUEST => ['configure', 2048]]; - if ('cli' === PHP_SAPI && defined('Symfony\Component\Console\ConsoleEvents::COMMAND')) { - $events[ConsoleEvents::COMMAND] = array('configure', 2048); + if ('cli' === \PHP_SAPI && \defined('Symfony\Component\Console\ConsoleEvents::COMMAND')) { + $events[ConsoleEvents::COMMAND] = ['configure', 2048]; } + $events[KernelEvents::EXCEPTION] = ['onKernelException', -2048]; + return $events; } } diff --git a/vendor/symfony/http-kernel/EventListener/DisallowRobotsIndexingListener.php b/vendor/symfony/http-kernel/EventListener/DisallowRobotsIndexingListener.php new file mode 100644 index 0000000000000000000000000000000000000000..6607e49e999e874e0bb8f8b38577f97205dc4bd3 --- /dev/null +++ b/vendor/symfony/http-kernel/EventListener/DisallowRobotsIndexingListener.php @@ -0,0 +1,43 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\EventListener; + +use Symfony\Component\EventDispatcher\EventSubscriberInterface; +use Symfony\Component\HttpKernel\Event\ResponseEvent; +use Symfony\Component\HttpKernel\KernelEvents; + +/** + * Ensures that the application is not indexed by search engines. + * + * @author Gary PEGEOT <garypegeot@gmail.com> + */ +class DisallowRobotsIndexingListener implements EventSubscriberInterface +{ + private const HEADER_NAME = 'X-Robots-Tag'; + + public function onResponse(ResponseEvent $event): void + { + if (!$event->getResponse()->headers->has(static::HEADER_NAME)) { + $event->getResponse()->headers->set(static::HEADER_NAME, 'noindex'); + } + } + + /** + * {@inheritdoc} + */ + public static function getSubscribedEvents() + { + return [ + KernelEvents::RESPONSE => ['onResponse', -255], + ]; + } +} diff --git a/vendor/symfony/http-kernel/EventListener/DumpListener.php b/vendor/symfony/http-kernel/EventListener/DumpListener.php index de19e13113e59f139dc6065094e9ad55ca5f53a5..30908a4f45652ea728152619dc009bf2bd15326b 100644 --- a/vendor/symfony/http-kernel/EventListener/DumpListener.php +++ b/vendor/symfony/http-kernel/EventListener/DumpListener.php @@ -15,6 +15,7 @@ use Symfony\Component\Console\ConsoleEvents; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\VarDumper\Cloner\ClonerInterface; use Symfony\Component\VarDumper\Dumper\DataDumperInterface; +use Symfony\Component\VarDumper\Server\Connection; use Symfony\Component\VarDumper\VarDumper; /** @@ -26,30 +27,37 @@ class DumpListener implements EventSubscriberInterface { private $cloner; private $dumper; + private $connection; - public function __construct(ClonerInterface $cloner, DataDumperInterface $dumper) + public function __construct(ClonerInterface $cloner, DataDumperInterface $dumper, Connection $connection = null) { $this->cloner = $cloner; $this->dumper = $dumper; + $this->connection = $connection; } public function configure() { $cloner = $this->cloner; $dumper = $this->dumper; + $connection = $this->connection; - VarDumper::setHandler(function ($var) use ($cloner, $dumper) { - $dumper->dump($cloner->cloneVar($var)); + VarDumper::setHandler(static function ($var) use ($cloner, $dumper, $connection) { + $data = $cloner->cloneVar($var); + + if (!$connection || !$connection->write($data)) { + $dumper->dump($data); + } }); } public static function getSubscribedEvents() { if (!class_exists(ConsoleEvents::class)) { - return array(); + return []; } // Register early to have a working dump() as early as possible - return array(ConsoleEvents::COMMAND => array('configure', 1024)); + return [ConsoleEvents::COMMAND => ['configure', 1024]]; } } diff --git a/vendor/symfony/http-kernel/EventListener/ExceptionListener.php b/vendor/symfony/http-kernel/EventListener/ExceptionListener.php index f18e42c7d36936ad625c496087a09633141c0f5b..ab5f65cb6319589cf3b9cbc16e63862b48936bbb 100644 --- a/vendor/symfony/http-kernel/EventListener/ExceptionListener.php +++ b/vendor/symfony/http-kernel/EventListener/ExceptionListener.php @@ -14,19 +14,19 @@ namespace Symfony\Component\HttpKernel\EventListener; use Psr\Log\LoggerInterface; use Symfony\Component\Debug\Exception\FlattenException; use Symfony\Component\EventDispatcher\EventDispatcherInterface; +use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpKernel\Event\FilterResponseEvent; -use Symfony\Component\HttpKernel\Log\DebugLoggerInterface; +use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent; -use Symfony\Component\HttpKernel\KernelEvents; -use Symfony\Component\HttpKernel\HttpKernelInterface; use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface; -use Symfony\Component\EventDispatcher\EventSubscriberInterface; +use Symfony\Component\HttpKernel\HttpKernelInterface; +use Symfony\Component\HttpKernel\KernelEvents; +use Symfony\Component\HttpKernel\Log\DebugLoggerInterface; /** - * ExceptionListener. - * * @author Fabien Potencier <fabien@symfony.com> + * + * @final since Symfony 4.3 */ class ExceptionListener implements EventSubscriberInterface { @@ -41,30 +41,38 @@ class ExceptionListener implements EventSubscriberInterface $this->debug = $debug; } - public function onKernelException(GetResponseForExceptionEvent $event) + public function logKernelException(GetResponseForExceptionEvent $event) { - $exception = $event->getException(); - $request = $event->getRequest(); - $eventDispatcher = func_num_args() > 2 ? func_get_arg(2) : null; + $e = FlattenException::create($event->getException()); - $this->logException($exception, sprintf('Uncaught PHP Exception %s: "%s" at %s line %s', get_class($exception), $exception->getMessage(), $exception->getFile(), $exception->getLine())); + $this->logException($event->getException(), sprintf('Uncaught PHP Exception %s: "%s" at %s line %s', $e->getClass(), $e->getMessage(), $e->getFile(), $e->getLine())); + } - $request = $this->duplicateRequest($exception, $request); + public function onKernelException(GetResponseForExceptionEvent $event) + { + if (null === $this->controller) { + return; + } + + $exception = $event->getException(); + $request = $this->duplicateRequest($exception, $event->getRequest()); + $eventDispatcher = \func_num_args() > 2 ? func_get_arg(2) : null; try { $response = $event->getKernel()->handle($request, HttpKernelInterface::SUB_REQUEST, false); } catch (\Exception $e) { - $this->logException($e, sprintf('Exception thrown when handling an exception (%s: %s at %s line %s)', get_class($e), $e->getMessage(), $e->getFile(), $e->getLine())); + $f = FlattenException::create($e); - $wrapper = $e; + $this->logException($e, sprintf('Exception thrown when handling an exception (%s: %s at %s line %s)', $f->getClass(), $f->getMessage(), $e->getFile(), $e->getLine())); - while ($prev = $wrapper->getPrevious()) { + $prev = $e; + do { if ($exception === $wrapper = $prev) { throw $e; } - } + } while ($prev = $wrapper->getPrevious()); - $prev = new \ReflectionProperty('Exception', 'previous'); + $prev = new \ReflectionProperty($wrapper instanceof \Exception ? \Exception::class : \Error::class, 'previous'); $prev->setAccessible(true); $prev->setValue($wrapper, $exception); @@ -74,7 +82,7 @@ class ExceptionListener implements EventSubscriberInterface $event->setResponse($response); if ($this->debug && $eventDispatcher instanceof EventDispatcherInterface) { - $cspRemovalListener = function (FilterResponseEvent $event) use (&$cspRemovalListener, $eventDispatcher) { + $cspRemovalListener = function ($event) use (&$cspRemovalListener, $eventDispatcher) { $event->getResponse()->headers->remove('Content-Security-Policy'); $eventDispatcher->removeListener(KernelEvents::RESPONSE, $cspRemovalListener); }; @@ -84,9 +92,12 @@ class ExceptionListener implements EventSubscriberInterface public static function getSubscribedEvents() { - return array( - KernelEvents::EXCEPTION => array('onKernelException', -128), - ); + return [ + KernelEvents::EXCEPTION => [ + ['logKernelException', 0], + ['onKernelException', -128], + ], + ]; } /** @@ -99,9 +110,9 @@ class ExceptionListener implements EventSubscriberInterface { if (null !== $this->logger) { if (!$exception instanceof HttpExceptionInterface || $exception->getStatusCode() >= 500) { - $this->logger->critical($message, array('exception' => $exception)); + $this->logger->critical($message, ['exception' => $exception]); } else { - $this->logger->error($message, array('exception' => $exception)); + $this->logger->error($message, ['exception' => $exception]); } } } @@ -112,15 +123,15 @@ class ExceptionListener implements EventSubscriberInterface * @param \Exception $exception The thrown exception * @param Request $request The original request * - * @return Request $request The cloned request + * @return Request The cloned request */ protected function duplicateRequest(\Exception $exception, Request $request) { - $attributes = array( + $attributes = [ '_controller' => $this->controller, 'exception' => FlattenException::create($exception), 'logger' => $this->logger instanceof DebugLoggerInterface ? $this->logger : null, - ); + ]; $request = $request->duplicate(null, null, $attributes); $request->setMethod('GET'); diff --git a/vendor/symfony/http-kernel/EventListener/FragmentListener.php b/vendor/symfony/http-kernel/EventListener/FragmentListener.php index da518fcc8e37499ff0dcac5537ad9b4f13d06481..fc4ba56d9b0d89180af4316e344681a30931b5d3 100644 --- a/vendor/symfony/http-kernel/EventListener/FragmentListener.php +++ b/vendor/symfony/http-kernel/EventListener/FragmentListener.php @@ -11,12 +11,12 @@ namespace Symfony\Component\HttpKernel\EventListener; +use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\Event\GetResponseEvent; -use Symfony\Component\HttpKernel\KernelEvents; use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException; +use Symfony\Component\HttpKernel\KernelEvents; use Symfony\Component\HttpKernel\UriSigner; -use Symfony\Component\EventDispatcher\EventSubscriberInterface; /** * Handles content fragments represented by special URIs. @@ -24,10 +24,12 @@ use Symfony\Component\EventDispatcher\EventSubscriberInterface; * All URL paths starting with /_fragment are handled as * content fragments by this listener. * - * If throws an AccessDeniedHttpException exception if the request + * Throws an AccessDeniedHttpException exception if the request * is not signed or if it is not an internal sub-request. * * @author Fabien Potencier <fabien@symfony.com> + * + * @final since Symfony 4.3 */ class FragmentListener implements EventSubscriberInterface { @@ -38,7 +40,7 @@ class FragmentListener implements EventSubscriberInterface * @param UriSigner $signer A UriSigner instance * @param string $fragmentPath The path that triggers this listener */ - public function __construct(UriSigner $signer, $fragmentPath = '/_fragment') + public function __construct(UriSigner $signer, string $fragmentPath = '/_fragment') { $this->signer = $signer; $this->fragmentPath = $fragmentPath; @@ -70,7 +72,7 @@ class FragmentListener implements EventSubscriberInterface parse_str($request->query->get('_path', ''), $attributes); $request->attributes->add($attributes); - $request->attributes->set('_route_params', array_replace($request->attributes->get('_route_params', array()), $attributes)); + $request->attributes->set('_route_params', array_replace($request->attributes->get('_route_params', []), $attributes)); $request->query->remove('_path'); } @@ -92,8 +94,8 @@ class FragmentListener implements EventSubscriberInterface public static function getSubscribedEvents() { - return array( - KernelEvents::REQUEST => array(array('onKernelRequest', 48)), - ); + return [ + KernelEvents::REQUEST => [['onKernelRequest', 48]], + ]; } } diff --git a/vendor/symfony/http-kernel/EventListener/LocaleAwareListener.php b/vendor/symfony/http-kernel/EventListener/LocaleAwareListener.php new file mode 100644 index 0000000000000000000000000000000000000000..fb8e67e7ed492f3522781ccead3a66e0dee37605 --- /dev/null +++ b/vendor/symfony/http-kernel/EventListener/LocaleAwareListener.php @@ -0,0 +1,76 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\EventListener; + +use Symfony\Component\EventDispatcher\EventSubscriberInterface; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\RequestStack; +use Symfony\Component\HttpKernel\Event\FinishRequestEvent; +use Symfony\Component\HttpKernel\Event\RequestEvent; +use Symfony\Component\HttpKernel\KernelEvents; +use Symfony\Contracts\Translation\LocaleAwareInterface; + +/** + * Pass the current locale to the provided services. + * + * @author Pierre Bobiet <pierrebobiet@gmail.com> + */ +class LocaleAwareListener implements EventSubscriberInterface +{ + private $localeAwareServices; + private $requestStack; + + /** + * @param LocaleAwareInterface[] $localeAwareServices + */ + public function __construct(iterable $localeAwareServices, RequestStack $requestStack) + { + $this->localeAwareServices = $localeAwareServices; + $this->requestStack = $requestStack; + } + + public function onKernelRequest(RequestEvent $event): void + { + $this->setLocale($event->getRequest()->getLocale(), $event->getRequest()->getDefaultLocale()); + } + + public function onKernelFinishRequest(FinishRequestEvent $event): void + { + if (null === $parentRequest = $this->requestStack->getParentRequest()) { + $this->setLocale($event->getRequest()->getDefaultLocale()); + + return; + } + + $this->setLocale($parentRequest->getLocale(), $parentRequest->getDefaultLocale()); + } + + public static function getSubscribedEvents() + { + return [ + // must be registered after the Locale listener + KernelEvents::REQUEST => [['onKernelRequest', 15]], + KernelEvents::FINISH_REQUEST => [['onKernelFinishRequest', -15]], + ]; + } + + private function setLocale(string $locale, string $defaultLocale = null): void + { + foreach ($this->localeAwareServices as $service) { + try { + $service->setLocale($locale); + } catch (\InvalidArgumentException $e) { + $service->setLocale($defaultLocale); + } + } + } +} diff --git a/vendor/symfony/http-kernel/EventListener/LocaleListener.php b/vendor/symfony/http-kernel/EventListener/LocaleListener.php index 427ea82fc8bf7370989b447e9c10b86b7f36ae7e..cb8a194d49a9d5efc1b76d3f20063da6049dbb2c 100644 --- a/vendor/symfony/http-kernel/EventListener/LocaleListener.php +++ b/vendor/symfony/http-kernel/EventListener/LocaleListener.php @@ -11,18 +11,21 @@ namespace Symfony\Component\HttpKernel\EventListener; -use Symfony\Component\HttpKernel\Event\GetResponseEvent; +use Symfony\Component\EventDispatcher\EventSubscriberInterface; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\HttpKernel\Event\FinishRequestEvent; +use Symfony\Component\HttpKernel\Event\GetResponseEvent; +use Symfony\Component\HttpKernel\Event\KernelEvent; use Symfony\Component\HttpKernel\KernelEvents; -use Symfony\Component\HttpFoundation\RequestStack; -use Symfony\Component\HttpFoundation\Request; use Symfony\Component\Routing\RequestContextAwareInterface; -use Symfony\Component\EventDispatcher\EventSubscriberInterface; /** * Initializes the locale based on the current request. * * @author Fabien Potencier <fabien@symfony.com> + * + * @final since Symfony 4.3 */ class LocaleListener implements EventSubscriberInterface { @@ -35,17 +38,21 @@ class LocaleListener implements EventSubscriberInterface * @param string $defaultLocale The default locale * @param RequestContextAwareInterface|null $router The router */ - public function __construct(RequestStack $requestStack, $defaultLocale = 'en', RequestContextAwareInterface $router = null) + public function __construct(RequestStack $requestStack, string $defaultLocale = 'en', RequestContextAwareInterface $router = null) { $this->defaultLocale = $defaultLocale; $this->requestStack = $requestStack; $this->router = $router; } + public function setDefaultLocale(KernelEvent $event) + { + $event->getRequest()->setDefaultLocale($this->defaultLocale); + } + public function onKernelRequest(GetResponseEvent $event) { $request = $event->getRequest(); - $request->setDefaultLocale($this->defaultLocale); $this->setLocale($request); $this->setRouterContext($request); @@ -74,10 +81,13 @@ class LocaleListener implements EventSubscriberInterface public static function getSubscribedEvents() { - return array( - // must be registered after the Router to have access to the _locale - KernelEvents::REQUEST => array(array('onKernelRequest', 16)), - KernelEvents::FINISH_REQUEST => array(array('onKernelFinishRequest', 0)), - ); + return [ + KernelEvents::REQUEST => [ + ['setDefaultLocale', 100], + // must be registered after the Router to have access to the _locale + ['onKernelRequest', 16], + ], + KernelEvents::FINISH_REQUEST => [['onKernelFinishRequest', 0]], + ]; } } diff --git a/vendor/symfony/http-kernel/EventListener/ProfilerListener.php b/vendor/symfony/http-kernel/EventListener/ProfilerListener.php index e3e4e7620e4ee8e31d8868e5f53377a582088f9e..85a0aacb6184c3a8bc52f8fd10d7a59adab69aae 100644 --- a/vendor/symfony/http-kernel/EventListener/ProfilerListener.php +++ b/vendor/symfony/http-kernel/EventListener/ProfilerListener.php @@ -11,19 +11,21 @@ namespace Symfony\Component\HttpKernel\EventListener; -use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent; +use Symfony\Component\EventDispatcher\EventSubscriberInterface; +use Symfony\Component\HttpFoundation\RequestMatcherInterface; +use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\HttpKernel\Event\FilterResponseEvent; +use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent; use Symfony\Component\HttpKernel\Event\PostResponseEvent; use Symfony\Component\HttpKernel\KernelEvents; use Symfony\Component\HttpKernel\Profiler\Profiler; -use Symfony\Component\HttpFoundation\RequestMatcherInterface; -use Symfony\Component\HttpFoundation\RequestStack; -use Symfony\Component\EventDispatcher\EventSubscriberInterface; /** * ProfilerListener collects data for the current request by listening to the kernel events. * * @author Fabien Potencier <fabien@symfony.com> + * + * @final since Symfony 4.3 */ class ProfilerListener implements EventSubscriberInterface { @@ -43,12 +45,12 @@ class ProfilerListener implements EventSubscriberInterface * @param bool $onlyException True if the profiler only collects data when an exception occurs, false otherwise * @param bool $onlyMasterRequests True if the profiler only collects data when the request is a master request, false otherwise */ - public function __construct(Profiler $profiler, RequestStack $requestStack, RequestMatcherInterface $matcher = null, $onlyException = false, $onlyMasterRequests = false) + public function __construct(Profiler $profiler, RequestStack $requestStack, RequestMatcherInterface $matcher = null, bool $onlyException = false, bool $onlyMasterRequests = false) { $this->profiler = $profiler; $this->matcher = $matcher; - $this->onlyException = (bool) $onlyException; - $this->onlyMasterRequests = (bool) $onlyMasterRequests; + $this->onlyException = $onlyException; + $this->onlyMasterRequests = $onlyMasterRequests; $this->profiles = new \SplObjectStorage(); $this->parents = new \SplObjectStorage(); $this->requestStack = $requestStack; @@ -119,10 +121,10 @@ class ProfilerListener implements EventSubscriberInterface public static function getSubscribedEvents() { - return array( - KernelEvents::RESPONSE => array('onKernelResponse', -100), - KernelEvents::EXCEPTION => 'onKernelException', - KernelEvents::TERMINATE => array('onKernelTerminate', -1024), - ); + return [ + KernelEvents::RESPONSE => ['onKernelResponse', -100], + KernelEvents::EXCEPTION => ['onKernelException', 0], + KernelEvents::TERMINATE => ['onKernelTerminate', -1024], + ]; } } diff --git a/vendor/symfony/http-kernel/EventListener/ResponseListener.php b/vendor/symfony/http-kernel/EventListener/ResponseListener.php index 6d56197a737e7e09bb42edd52ad628e3d1d79045..01973e222a0978f4b0021e782c8302965433a146 100644 --- a/vendor/symfony/http-kernel/EventListener/ResponseListener.php +++ b/vendor/symfony/http-kernel/EventListener/ResponseListener.php @@ -11,20 +11,22 @@ namespace Symfony\Component\HttpKernel\EventListener; +use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\HttpKernel\Event\FilterResponseEvent; use Symfony\Component\HttpKernel\KernelEvents; -use Symfony\Component\EventDispatcher\EventSubscriberInterface; /** * ResponseListener fixes the Response headers based on the Request. * * @author Fabien Potencier <fabien@symfony.com> + * + * @final since Symfony 4.3 */ class ResponseListener implements EventSubscriberInterface { private $charset; - public function __construct($charset) + public function __construct(string $charset) { $this->charset = $charset; } @@ -49,8 +51,8 @@ class ResponseListener implements EventSubscriberInterface public static function getSubscribedEvents() { - return array( + return [ KernelEvents::RESPONSE => 'onKernelResponse', - ); + ]; } } diff --git a/vendor/symfony/http-kernel/EventListener/RouterListener.php b/vendor/symfony/http-kernel/EventListener/RouterListener.php index caaf80f86b8920a5afe7313ef77d46321ec1fcc8..2f1735d26fe7b0d1782aa4a942c4fad7e50f8aef 100644 --- a/vendor/symfony/http-kernel/EventListener/RouterListener.php +++ b/vendor/symfony/http-kernel/EventListener/RouterListener.php @@ -12,30 +12,33 @@ namespace Symfony\Component\HttpKernel\EventListener; use Psr\Log\LoggerInterface; +use Symfony\Component\EventDispatcher\EventSubscriberInterface; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\HttpKernel\Event\GetResponseEvent; use Symfony\Component\HttpKernel\Event\FinishRequestEvent; -use Symfony\Component\HttpKernel\Kernel; -use Symfony\Component\HttpKernel\KernelEvents; +use Symfony\Component\HttpKernel\Event\GetResponseEvent; +use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent; use Symfony\Component\HttpKernel\Exception\BadRequestHttpException; use Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException; use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; -use Symfony\Component\HttpFoundation\RequestStack; +use Symfony\Component\HttpKernel\Kernel; +use Symfony\Component\HttpKernel\KernelEvents; use Symfony\Component\Routing\Exception\MethodNotAllowedException; use Symfony\Component\Routing\Exception\NoConfigurationException; use Symfony\Component\Routing\Exception\ResourceNotFoundException; -use Symfony\Component\Routing\Matcher\UrlMatcherInterface; use Symfony\Component\Routing\Matcher\RequestMatcherInterface; +use Symfony\Component\Routing\Matcher\UrlMatcherInterface; use Symfony\Component\Routing\RequestContext; use Symfony\Component\Routing\RequestContextAwareInterface; -use Symfony\Component\EventDispatcher\EventSubscriberInterface; -use Symfony\Component\HttpFoundation\Request; /** * Initializes the context from the request and sets request attributes based on a matching route. * * @author Fabien Potencier <fabien@symfony.com> * @author Yonel Ceruto <yonelceruto@gmail.com> + * + * @final since Symfony 4.3 */ class RouterListener implements EventSubscriberInterface { @@ -52,11 +55,10 @@ class RouterListener implements EventSubscriberInterface * @param RequestContext|null $context The RequestContext (can be null when $matcher implements RequestContextAwareInterface) * @param LoggerInterface|null $logger The logger * @param string $projectDir - * @param bool $debug * * @throws \InvalidArgumentException */ - public function __construct($matcher, RequestStack $requestStack, RequestContext $context = null, LoggerInterface $logger = null, $projectDir = null, $debug = true) + public function __construct($matcher, RequestStack $requestStack, RequestContext $context = null, LoggerInterface $logger = null, string $projectDir = null, bool $debug = true) { if (!$matcher instanceof UrlMatcherInterface && !$matcher instanceof RequestMatcherInterface) { throw new \InvalidArgumentException('Matcher must either implement UrlMatcherInterface or RequestMatcherInterface.'); @@ -88,8 +90,6 @@ class RouterListener implements EventSubscriberInterface /** * After a sub-request is done, we need to reset the routing context to the parent request so that the URL generator * operates on the correct context again. - * - * @param FinishRequestEvent $event */ public function onKernelFinishRequest(FinishRequestEvent $event) { @@ -117,24 +117,18 @@ class RouterListener implements EventSubscriberInterface } if (null !== $this->logger) { - $this->logger->info('Matched route "{route}".', array( + $this->logger->info('Matched route "{route}".', [ 'route' => isset($parameters['_route']) ? $parameters['_route'] : 'n/a', 'route_parameters' => $parameters, 'request_uri' => $request->getUri(), 'method' => $request->getMethod(), - )); + ]); } $request->attributes->add($parameters); unset($parameters['_route'], $parameters['_controller']); $request->attributes->set('_route_params', $parameters); } catch (ResourceNotFoundException $e) { - if ($this->debug && $e instanceof NoConfigurationException) { - $event->setResponse($this->createWelcomeResponse()); - - return; - } - $message = sprintf('No route found for "%s %s"', $request->getMethod(), $request->getPathInfo()); if ($referer = $request->headers->get('referer')) { @@ -149,18 +143,30 @@ class RouterListener implements EventSubscriberInterface } } + public function onKernelException(GetResponseForExceptionEvent $event) + { + if (!$this->debug || !($e = $event->getException()) instanceof NotFoundHttpException) { + return; + } + + if ($e->getPrevious() instanceof NoConfigurationException) { + $event->setResponse($this->createWelcomeResponse()); + } + } + public static function getSubscribedEvents() { - return array( - KernelEvents::REQUEST => array(array('onKernelRequest', 32)), - KernelEvents::FINISH_REQUEST => array(array('onKernelFinishRequest', 0)), - ); + return [ + KernelEvents::REQUEST => [['onKernelRequest', 32]], + KernelEvents::FINISH_REQUEST => [['onKernelFinishRequest', 0]], + KernelEvents::EXCEPTION => ['onKernelException', -64], + ]; } private function createWelcomeResponse() { $version = Kernel::VERSION; - $baseDir = realpath($this->projectDir).DIRECTORY_SEPARATOR; + $baseDir = realpath($this->projectDir).\DIRECTORY_SEPARATOR; $docVersion = substr(Kernel::VERSION, 0, 3); ob_start(); diff --git a/vendor/symfony/http-kernel/EventListener/SaveSessionListener.php b/vendor/symfony/http-kernel/EventListener/SaveSessionListener.php index 36809b59af914aecf4865a91a673b8ec87b68f8d..b14153ad3cf8b053bb984a28ffa4654e68cc7195 100644 --- a/vendor/symfony/http-kernel/EventListener/SaveSessionListener.php +++ b/vendor/symfony/http-kernel/EventListener/SaveSessionListener.php @@ -11,36 +11,16 @@ namespace Symfony\Component\HttpKernel\EventListener; +@trigger_error(sprintf('The "%s" class is deprecated since Symfony 4.1, use AbstractSessionListener instead.', SaveSessionListener::class), E_USER_DEPRECATED); + use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\HttpKernel\Event\FilterResponseEvent; use Symfony\Component\HttpKernel\KernelEvents; /** - * Saves the session, in case it is still open, before sending the response/headers. - * - * This ensures several things in case the developer did not save the session explicitly: - * - * * If a session save handler without locking is used, it ensures the data is available - * on the next request, e.g. after a redirect. PHPs auto-save at script end via - * session_register_shutdown is executed after fastcgi_finish_request. So in this case - * the data could be missing the next request because it might not be saved the moment - * the new request is processed. - * * A locking save handler (e.g. the native 'files') circumvents concurrency problems like - * the one above. But by saving the session before long-running things in the terminate event, - * we ensure the session is not blocked longer than needed. - * * When regenerating the session ID no locking is involved in PHPs session design. See - * https://bugs.php.net/bug.php?id=61470 for a discussion. So in this case, the session must - * be saved anyway before sending the headers with the new session ID. Otherwise session - * data could get lost again for concurrent requests with the new ID. One result could be - * that you get logged out after just logging in. - * - * This listener should be executed as one of the last listeners, so that previous listeners - * can still operate on the open session. This prevents the overhead of restarting it. - * Listeners after closing the session can still work with the session as usual because - * Symfonys session implementation starts the session on demand. So writing to it after - * it is saved will just restart it. - * * @author Tobias Schultze <http://tobion.de> + * + * @deprecated since Symfony 4.1, use AbstractSessionListener instead */ class SaveSessionListener implements EventSubscriberInterface { @@ -58,9 +38,9 @@ class SaveSessionListener implements EventSubscriberInterface public static function getSubscribedEvents() { - return array( + return [ // low priority but higher than StreamedResponseListener - KernelEvents::RESPONSE => array(array('onKernelResponse', -1000)), - ); + KernelEvents::RESPONSE => [['onKernelResponse', -1000]], + ]; } } diff --git a/vendor/symfony/http-kernel/EventListener/SessionListener.php b/vendor/symfony/http-kernel/EventListener/SessionListener.php index 39ebfd922fac67befd4d89a18cef153533ea14b2..019ccee49f21ff3cf132a3d4c721b256a58680c8 100644 --- a/vendor/symfony/http-kernel/EventListener/SessionListener.php +++ b/vendor/symfony/http-kernel/EventListener/SessionListener.php @@ -12,18 +12,21 @@ namespace Symfony\Component\HttpKernel\EventListener; use Psr\Container\ContainerInterface; +use Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage; /** * Sets the session in the request. * + * When the passed container contains a "session_storage" entry which + * holds a NativeSessionStorage instance, the "cookie_secure" option + * will be set to true whenever the current master request is secure. + * * @author Fabien Potencier <fabien@symfony.com> * - * @final since version 3.3 + * @final */ class SessionListener extends AbstractSessionListener { - private $container; - public function __construct(ContainerInterface $container) { $this->container = $container; @@ -32,7 +35,15 @@ class SessionListener extends AbstractSessionListener protected function getSession() { if (!$this->container->has('session')) { - return; + return null; + } + + if ($this->container->has('session_storage') + && ($storage = $this->container->get('session_storage')) instanceof NativeSessionStorage + && ($masterRequest = $this->container->get('request_stack')->getMasterRequest()) + && $masterRequest->isSecure() + ) { + $storage->setOptions(['cookie_secure' => true]); } return $this->container->get('session'); diff --git a/vendor/symfony/http-kernel/EventListener/StreamedResponseListener.php b/vendor/symfony/http-kernel/EventListener/StreamedResponseListener.php index 671db5d8270997d1d8dea74422a5dd0df073a0f7..f28f5d868a2bfa914304270568966f2333081ed1 100644 --- a/vendor/symfony/http-kernel/EventListener/StreamedResponseListener.php +++ b/vendor/symfony/http-kernel/EventListener/StreamedResponseListener.php @@ -11,16 +11,18 @@ namespace Symfony\Component\HttpKernel\EventListener; +use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\HttpFoundation\StreamedResponse; use Symfony\Component\HttpKernel\Event\FilterResponseEvent; use Symfony\Component\HttpKernel\KernelEvents; -use Symfony\Component\EventDispatcher\EventSubscriberInterface; /** * StreamedResponseListener is responsible for sending the Response * to the client. * * @author Fabien Potencier <fabien@symfony.com> + * + * @final since Symfony 4.3 */ class StreamedResponseListener implements EventSubscriberInterface { @@ -42,8 +44,8 @@ class StreamedResponseListener implements EventSubscriberInterface public static function getSubscribedEvents() { - return array( - KernelEvents::RESPONSE => array('onKernelResponse', -1024), - ); + return [ + KernelEvents::RESPONSE => ['onKernelResponse', -1024], + ]; } } diff --git a/vendor/symfony/http-kernel/EventListener/SurrogateListener.php b/vendor/symfony/http-kernel/EventListener/SurrogateListener.php index 37d1b9d04eaad56233528c35e5bd7a5e0bbb3843..9c3e960b007390a3859516dd1886f33d5d47f570 100644 --- a/vendor/symfony/http-kernel/EventListener/SurrogateListener.php +++ b/vendor/symfony/http-kernel/EventListener/SurrogateListener.php @@ -11,16 +11,18 @@ namespace Symfony\Component\HttpKernel\EventListener; +use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\HttpKernel\Event\FilterResponseEvent; use Symfony\Component\HttpKernel\HttpCache\HttpCache; use Symfony\Component\HttpKernel\HttpCache\SurrogateInterface; use Symfony\Component\HttpKernel\KernelEvents; -use Symfony\Component\EventDispatcher\EventSubscriberInterface; /** * SurrogateListener adds a Surrogate-Control HTTP header when the Response needs to be parsed for Surrogates. * * @author Fabien Potencier <fabien@symfony.com> + * + * @final since Symfony 4.3 */ class SurrogateListener implements EventSubscriberInterface { @@ -58,8 +60,8 @@ class SurrogateListener implements EventSubscriberInterface public static function getSubscribedEvents() { - return array( + return [ KernelEvents::RESPONSE => 'onKernelResponse', - ); + ]; } } diff --git a/vendor/symfony/http-kernel/EventListener/TestSessionListener.php b/vendor/symfony/http-kernel/EventListener/TestSessionListener.php index 36abb422f4f6dc3321fc307d0029db60659ffee1..a0a52c2a75265808c9a4afe25df54d1fbf044182 100644 --- a/vendor/symfony/http-kernel/EventListener/TestSessionListener.php +++ b/vendor/symfony/http-kernel/EventListener/TestSessionListener.php @@ -18,21 +18,22 @@ use Psr\Container\ContainerInterface; * * @author Fabien Potencier <fabien@symfony.com> * - * @final since version 3.3 + * @final */ class TestSessionListener extends AbstractTestSessionListener { private $container; - public function __construct(ContainerInterface $container) + public function __construct(ContainerInterface $container, array $sessionOptions = []) { $this->container = $container; + parent::__construct($sessionOptions); } protected function getSession() { if (!$this->container->has('session')) { - return; + return null; } return $this->container->get('session'); diff --git a/vendor/symfony/http-kernel/EventListener/TranslatorListener.php b/vendor/symfony/http-kernel/EventListener/TranslatorListener.php index 6967ad0298b59aa8955d4b894d05f69727cda1fa..d28eee2b1ad21845fa7b5f149c73365809ee0871 100644 --- a/vendor/symfony/http-kernel/EventListener/TranslatorListener.php +++ b/vendor/symfony/http-kernel/EventListener/TranslatorListener.php @@ -11,26 +11,37 @@ namespace Symfony\Component\HttpKernel\EventListener; +@trigger_error(sprintf('The "%s" class is deprecated since Symfony 4.3 and will be removed in 5.0, use LocaleAwareListener instead.', TranslatorListener::class), E_USER_DEPRECATED); + use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpKernel\Event\GetResponseEvent; +use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\HttpKernel\Event\FinishRequestEvent; +use Symfony\Component\HttpKernel\Event\GetResponseEvent; use Symfony\Component\HttpKernel\KernelEvents; -use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\Translation\TranslatorInterface; +use Symfony\Contracts\Translation\LocaleAwareInterface; /** * Synchronizes the locale between the request and the translator. * * @author Fabien Potencier <fabien@symfony.com> + * + * @deprecated since Symfony 4.3, use LocaleAwareListener instead */ class TranslatorListener implements EventSubscriberInterface { private $translator; private $requestStack; - public function __construct(TranslatorInterface $translator, RequestStack $requestStack) + /** + * @param LocaleAwareInterface $translator + */ + public function __construct($translator, RequestStack $requestStack) { + if (!$translator instanceof TranslatorInterface && !$translator instanceof LocaleAwareInterface) { + throw new \TypeError(sprintf('Argument 1 passed to %s() must be an instance of %s, %s given.', __METHOD__, LocaleAwareInterface::class, \is_object($translator) ? \get_class($translator) : \gettype($translator))); + } $this->translator = $translator; $this->requestStack = $requestStack; } @@ -51,11 +62,11 @@ class TranslatorListener implements EventSubscriberInterface public static function getSubscribedEvents() { - return array( + return [ // must be registered after the Locale listener - KernelEvents::REQUEST => array(array('onKernelRequest', 10)), - KernelEvents::FINISH_REQUEST => array(array('onKernelFinishRequest', 0)), - ); + KernelEvents::REQUEST => [['onKernelRequest', 10]], + KernelEvents::FINISH_REQUEST => [['onKernelFinishRequest', 0]], + ]; } private function setLocale(Request $request) diff --git a/vendor/symfony/http-kernel/EventListener/ValidateRequestListener.php b/vendor/symfony/http-kernel/EventListener/ValidateRequestListener.php index a33853f727badd875cd7b1593e2c64cf38a12ca0..69c86b409564b4b6fabd9ca272707910f62bdc4e 100644 --- a/vendor/symfony/http-kernel/EventListener/ValidateRequestListener.php +++ b/vendor/symfony/http-kernel/EventListener/ValidateRequestListener.php @@ -19,6 +19,8 @@ use Symfony\Component\HttpKernel\KernelEvents; * Validates Requests. * * @author Magnus Nordlander <magnus@fervo.se> + * + * @final since Symfony 4.3 */ class ValidateRequestListener implements EventSubscriberInterface { @@ -44,10 +46,10 @@ class ValidateRequestListener implements EventSubscriberInterface */ public static function getSubscribedEvents() { - return array( - KernelEvents::REQUEST => array( - array('onKernelRequest', 256), - ), - ); + return [ + KernelEvents::REQUEST => [ + ['onKernelRequest', 256], + ], + ]; } } diff --git a/vendor/symfony/http-kernel/Exception/AccessDeniedHttpException.php b/vendor/symfony/http-kernel/Exception/AccessDeniedHttpException.php index 39418842666b2f8a9fca09df20fa876efbf15416..65e5f8c7866a59a5ba62ed1b838c86cb2085c261 100644 --- a/vendor/symfony/http-kernel/Exception/AccessDeniedHttpException.php +++ b/vendor/symfony/http-kernel/Exception/AccessDeniedHttpException.php @@ -19,11 +19,11 @@ class AccessDeniedHttpException extends HttpException { /** * @param string $message The internal exception message - * @param \Exception $previous The previous exception + * @param \Throwable $previous The previous exception * @param int $code The internal exception code */ - public function __construct($message = null, \Exception $previous = null, $code = 0) + public function __construct(string $message = null, \Throwable $previous = null, int $code = 0, array $headers = []) { - parent::__construct(403, $message, $previous, array(), $code); + parent::__construct(403, $message, $previous, $headers, $code); } } diff --git a/vendor/symfony/http-kernel/Exception/BadRequestHttpException.php b/vendor/symfony/http-kernel/Exception/BadRequestHttpException.php index c28d83739c7a54e043fa050dad50ee9ddfd8794a..7de91054b4731b650073778ed02001fe9e00f364 100644 --- a/vendor/symfony/http-kernel/Exception/BadRequestHttpException.php +++ b/vendor/symfony/http-kernel/Exception/BadRequestHttpException.php @@ -18,11 +18,11 @@ class BadRequestHttpException extends HttpException { /** * @param string $message The internal exception message - * @param \Exception $previous The previous exception + * @param \Throwable $previous The previous exception * @param int $code The internal exception code */ - public function __construct($message = null, \Exception $previous = null, $code = 0) + public function __construct(string $message = null, \Throwable $previous = null, int $code = 0, array $headers = []) { - parent::__construct(400, $message, $previous, array(), $code); + parent::__construct(400, $message, $previous, $headers, $code); } } diff --git a/vendor/symfony/http-kernel/Exception/ConflictHttpException.php b/vendor/symfony/http-kernel/Exception/ConflictHttpException.php index 79f24f2e56dc0a52e63b8ed50c0c8644b5c21de6..ebb86ba6e9e1e124ce97c4e59a404cd0723d35ce 100644 --- a/vendor/symfony/http-kernel/Exception/ConflictHttpException.php +++ b/vendor/symfony/http-kernel/Exception/ConflictHttpException.php @@ -18,11 +18,11 @@ class ConflictHttpException extends HttpException { /** * @param string $message The internal exception message - * @param \Exception $previous The previous exception + * @param \Throwable $previous The previous exception * @param int $code The internal exception code */ - public function __construct($message = null, \Exception $previous = null, $code = 0) + public function __construct(string $message = null, \Throwable $previous = null, int $code = 0, array $headers = []) { - parent::__construct(409, $message, $previous, array(), $code); + parent::__construct(409, $message, $previous, $headers, $code); } } diff --git a/vendor/symfony/http-kernel/Exception/ControllerDoesNotReturnResponseException.php b/vendor/symfony/http-kernel/Exception/ControllerDoesNotReturnResponseException.php new file mode 100644 index 0000000000000000000000000000000000000000..1e87690ff1cc8c345dc7f796fdd899918a87bdca --- /dev/null +++ b/vendor/symfony/http-kernel/Exception/ControllerDoesNotReturnResponseException.php @@ -0,0 +1,84 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Exception; + +/** + * @author Grégoire Pineau <lyrixx@lyrixx.info> + */ +class ControllerDoesNotReturnResponseException extends \LogicException +{ + public function __construct(string $message, callable $controller, string $file, int $line) + { + parent::__construct($message); + + if (!$controllerDefinition = $this->parseControllerDefinition($controller)) { + return; + } + + $this->file = $controllerDefinition['file']; + $this->line = $controllerDefinition['line']; + $r = new \ReflectionProperty(\Exception::class, 'trace'); + $r->setAccessible(true); + $r->setValue($this, array_merge([ + [ + 'line' => $line, + 'file' => $file, + ], + ], $this->getTrace())); + } + + private function parseControllerDefinition(callable $controller): ?array + { + if (\is_string($controller) && false !== strpos($controller, '::')) { + $controller = explode('::', $controller); + } + + if (\is_array($controller)) { + try { + $r = new \ReflectionMethod($controller[0], $controller[1]); + + return [ + 'file' => $r->getFileName(), + 'line' => $r->getEndLine(), + ]; + } catch (\ReflectionException $e) { + return null; + } + } + + if ($controller instanceof \Closure) { + $r = new \ReflectionFunction($controller); + + return [ + 'file' => $r->getFileName(), + 'line' => $r->getEndLine(), + ]; + } + + if (\is_object($controller)) { + $r = new \ReflectionClass($controller); + + try { + $line = $r->getMethod('__invoke')->getEndLine(); + } catch (\ReflectionException $e) { + $line = $r->getEndLine(); + } + + return [ + 'file' => $r->getFileName(), + 'line' => $line, + ]; + } + + return null; + } +} diff --git a/vendor/symfony/http-kernel/Exception/GoneHttpException.php b/vendor/symfony/http-kernel/Exception/GoneHttpException.php index 84e6915df70f7acd8563a006cb262f9a7bf2a9a0..aea283a961cc526c62907c0f1956528b5f83efd7 100644 --- a/vendor/symfony/http-kernel/Exception/GoneHttpException.php +++ b/vendor/symfony/http-kernel/Exception/GoneHttpException.php @@ -18,11 +18,11 @@ class GoneHttpException extends HttpException { /** * @param string $message The internal exception message - * @param \Exception $previous The previous exception + * @param \Throwable $previous The previous exception * @param int $code The internal exception code */ - public function __construct($message = null, \Exception $previous = null, $code = 0) + public function __construct(string $message = null, \Throwable $previous = null, int $code = 0, array $headers = []) { - parent::__construct(410, $message, $previous, array(), $code); + parent::__construct(410, $message, $previous, $headers, $code); } } diff --git a/vendor/symfony/http-kernel/Exception/HttpException.php b/vendor/symfony/http-kernel/Exception/HttpException.php index e8e37605838cc6efb93b40d1e32a209fb6f798bc..d822cd5d49a77e8a9ca50f495ad4e19627558c17 100644 --- a/vendor/symfony/http-kernel/Exception/HttpException.php +++ b/vendor/symfony/http-kernel/Exception/HttpException.php @@ -21,7 +21,7 @@ class HttpException extends \RuntimeException implements HttpExceptionInterface private $statusCode; private $headers; - public function __construct($statusCode, $message = null, \Exception $previous = null, array $headers = array(), $code = 0) + public function __construct(int $statusCode, string $message = null, \Throwable $previous = null, array $headers = [], ?int $code = 0) { $this->statusCode = $statusCode; $this->headers = $headers; diff --git a/vendor/symfony/http-kernel/Exception/LengthRequiredHttpException.php b/vendor/symfony/http-kernel/Exception/LengthRequiredHttpException.php index 645efe87d7c23f1c85f94311e794a0d9547c1420..44fb770b60c8919c0d92c4602c5ee880944f346f 100644 --- a/vendor/symfony/http-kernel/Exception/LengthRequiredHttpException.php +++ b/vendor/symfony/http-kernel/Exception/LengthRequiredHttpException.php @@ -18,11 +18,11 @@ class LengthRequiredHttpException extends HttpException { /** * @param string $message The internal exception message - * @param \Exception $previous The previous exception + * @param \Throwable $previous The previous exception * @param int $code The internal exception code */ - public function __construct($message = null, \Exception $previous = null, $code = 0) + public function __construct(string $message = null, \Throwable $previous = null, int $code = 0, array $headers = []) { - parent::__construct(411, $message, $previous, array(), $code); + parent::__construct(411, $message, $previous, $headers, $code); } } diff --git a/vendor/symfony/http-kernel/Exception/MethodNotAllowedHttpException.php b/vendor/symfony/http-kernel/Exception/MethodNotAllowedHttpException.php index e308a5fee2767ecaf077d1127598f1307eb3c062..c15e46ffc3406e8c66d5f9ddbf2c392e338dd855 100644 --- a/vendor/symfony/http-kernel/Exception/MethodNotAllowedHttpException.php +++ b/vendor/symfony/http-kernel/Exception/MethodNotAllowedHttpException.php @@ -19,12 +19,12 @@ class MethodNotAllowedHttpException extends HttpException /** * @param array $allow An array of allowed methods * @param string $message The internal exception message - * @param \Exception $previous The previous exception + * @param \Throwable $previous The previous exception * @param int $code The internal exception code */ - public function __construct(array $allow, $message = null, \Exception $previous = null, $code = 0) + public function __construct(array $allow, string $message = null, \Throwable $previous = null, ?int $code = 0, array $headers = []) { - $headers = array('Allow' => strtoupper(implode(', ', $allow))); + $headers['Allow'] = strtoupper(implode(', ', $allow)); parent::__construct(405, $message, $previous, $headers, $code); } diff --git a/vendor/symfony/http-kernel/Exception/NotAcceptableHttpException.php b/vendor/symfony/http-kernel/Exception/NotAcceptableHttpException.php index 097a13fd9bc05aaa8169db436c8534081ff0a434..c5f5324b1a655ee3651fce24de0aa1ce0ca9eff3 100644 --- a/vendor/symfony/http-kernel/Exception/NotAcceptableHttpException.php +++ b/vendor/symfony/http-kernel/Exception/NotAcceptableHttpException.php @@ -18,11 +18,11 @@ class NotAcceptableHttpException extends HttpException { /** * @param string $message The internal exception message - * @param \Exception $previous The previous exception + * @param \Throwable $previous The previous exception * @param int $code The internal exception code */ - public function __construct($message = null, \Exception $previous = null, $code = 0) + public function __construct(string $message = null, \Throwable $previous = null, int $code = 0, array $headers = []) { - parent::__construct(406, $message, $previous, array(), $code); + parent::__construct(406, $message, $previous, $headers, $code); } } diff --git a/vendor/symfony/http-kernel/Exception/NotFoundHttpException.php b/vendor/symfony/http-kernel/Exception/NotFoundHttpException.php index 878173cc7b9ace62fe3b035ecd2a35f6eca1058b..146b908a1e45dbe6d93b27aed1fcf1dc04a608d0 100644 --- a/vendor/symfony/http-kernel/Exception/NotFoundHttpException.php +++ b/vendor/symfony/http-kernel/Exception/NotFoundHttpException.php @@ -18,11 +18,11 @@ class NotFoundHttpException extends HttpException { /** * @param string $message The internal exception message - * @param \Exception $previous The previous exception + * @param \Throwable $previous The previous exception * @param int $code The internal exception code */ - public function __construct($message = null, \Exception $previous = null, $code = 0) + public function __construct(string $message = null, \Throwable $previous = null, int $code = 0, array $headers = []) { - parent::__construct(404, $message, $previous, array(), $code); + parent::__construct(404, $message, $previous, $headers, $code); } } diff --git a/vendor/symfony/http-kernel/Exception/PreconditionFailedHttpException.php b/vendor/symfony/http-kernel/Exception/PreconditionFailedHttpException.php index 9f13a624cc0fb487594fb38c2ef1d07fd8f175f2..e878b10ad355efdc6e783a423146cc943883ef13 100644 --- a/vendor/symfony/http-kernel/Exception/PreconditionFailedHttpException.php +++ b/vendor/symfony/http-kernel/Exception/PreconditionFailedHttpException.php @@ -18,11 +18,11 @@ class PreconditionFailedHttpException extends HttpException { /** * @param string $message The internal exception message - * @param \Exception $previous The previous exception + * @param \Throwable $previous The previous exception * @param int $code The internal exception code */ - public function __construct($message = null, \Exception $previous = null, $code = 0) + public function __construct(string $message = null, \Throwable $previous = null, int $code = 0, array $headers = []) { - parent::__construct(412, $message, $previous, array(), $code); + parent::__construct(412, $message, $previous, $headers, $code); } } diff --git a/vendor/symfony/http-kernel/Exception/PreconditionRequiredHttpException.php b/vendor/symfony/http-kernel/Exception/PreconditionRequiredHttpException.php index 9d0a36d7d34d600b26b32eac42e11f28dbb9a114..a6cb2f09a758ea0065ce5576892abc91991fe523 100644 --- a/vendor/symfony/http-kernel/Exception/PreconditionRequiredHttpException.php +++ b/vendor/symfony/http-kernel/Exception/PreconditionRequiredHttpException.php @@ -20,11 +20,11 @@ class PreconditionRequiredHttpException extends HttpException { /** * @param string $message The internal exception message - * @param \Exception $previous The previous exception + * @param \Throwable $previous The previous exception * @param int $code The internal exception code */ - public function __construct($message = null, \Exception $previous = null, $code = 0) + public function __construct(string $message = null, \Throwable $previous = null, int $code = 0, array $headers = []) { - parent::__construct(428, $message, $previous, array(), $code); + parent::__construct(428, $message, $previous, $headers, $code); } } diff --git a/vendor/symfony/http-kernel/Exception/ServiceUnavailableHttpException.php b/vendor/symfony/http-kernel/Exception/ServiceUnavailableHttpException.php index b2767c3fd5bccc809f5efa55e59d0b7d65bb302b..c786ccf5f7fa7d9973330747624245885882ffa6 100644 --- a/vendor/symfony/http-kernel/Exception/ServiceUnavailableHttpException.php +++ b/vendor/symfony/http-kernel/Exception/ServiceUnavailableHttpException.php @@ -19,14 +19,13 @@ class ServiceUnavailableHttpException extends HttpException /** * @param int|string $retryAfter The number of seconds or HTTP-date after which the request may be retried * @param string $message The internal exception message - * @param \Exception $previous The previous exception + * @param \Throwable $previous The previous exception * @param int $code The internal exception code */ - public function __construct($retryAfter = null, $message = null, \Exception $previous = null, $code = 0) + public function __construct($retryAfter = null, string $message = null, \Throwable $previous = null, ?int $code = 0, array $headers = []) { - $headers = array(); if ($retryAfter) { - $headers = array('Retry-After' => $retryAfter); + $headers['Retry-After'] = $retryAfter; } parent::__construct(503, $message, $previous, $headers, $code); diff --git a/vendor/symfony/http-kernel/Exception/TooManyRequestsHttpException.php b/vendor/symfony/http-kernel/Exception/TooManyRequestsHttpException.php index 7d8a803323b7c4d4c428f205749160d5d523e8a5..b709f1a2f1e68f99d73d9067f9f90970d19a07d3 100644 --- a/vendor/symfony/http-kernel/Exception/TooManyRequestsHttpException.php +++ b/vendor/symfony/http-kernel/Exception/TooManyRequestsHttpException.php @@ -21,14 +21,13 @@ class TooManyRequestsHttpException extends HttpException /** * @param int|string $retryAfter The number of seconds or HTTP-date after which the request may be retried * @param string $message The internal exception message - * @param \Exception $previous The previous exception + * @param \Throwable $previous The previous exception * @param int $code The internal exception code */ - public function __construct($retryAfter = null, $message = null, \Exception $previous = null, $code = 0) + public function __construct($retryAfter = null, string $message = null, \Throwable $previous = null, ?int $code = 0, array $headers = []) { - $headers = array(); if ($retryAfter) { - $headers = array('Retry-After' => $retryAfter); + $headers['Retry-After'] = $retryAfter; } parent::__construct(429, $message, $previous, $headers, $code); diff --git a/vendor/symfony/http-kernel/Exception/UnauthorizedHttpException.php b/vendor/symfony/http-kernel/Exception/UnauthorizedHttpException.php index 05ac875c552e210bc8d9ea42692f9986a8193fd7..fb86c1ea95367638d264b46bc4f84efd8a8c62e2 100644 --- a/vendor/symfony/http-kernel/Exception/UnauthorizedHttpException.php +++ b/vendor/symfony/http-kernel/Exception/UnauthorizedHttpException.php @@ -19,12 +19,12 @@ class UnauthorizedHttpException extends HttpException /** * @param string $challenge WWW-Authenticate challenge string * @param string $message The internal exception message - * @param \Exception $previous The previous exception + * @param \Throwable $previous The previous exception * @param int $code The internal exception code */ - public function __construct($challenge, $message = null, \Exception $previous = null, $code = 0) + public function __construct(string $challenge, string $message = null, \Throwable $previous = null, ?int $code = 0, array $headers = []) { - $headers = array('WWW-Authenticate' => $challenge); + $headers['WWW-Authenticate'] = $challenge; parent::__construct(401, $message, $previous, $headers, $code); } diff --git a/vendor/symfony/http-kernel/Exception/UnprocessableEntityHttpException.php b/vendor/symfony/http-kernel/Exception/UnprocessableEntityHttpException.php index 01b8b8465a1a3aed60ba08ae3f1b2ffd2024c337..93d4bcef69158fd6a478f1594f983c5a7dc7212a 100644 --- a/vendor/symfony/http-kernel/Exception/UnprocessableEntityHttpException.php +++ b/vendor/symfony/http-kernel/Exception/UnprocessableEntityHttpException.php @@ -18,11 +18,11 @@ class UnprocessableEntityHttpException extends HttpException { /** * @param string $message The internal exception message - * @param \Exception $previous The previous exception + * @param \Throwable $previous The previous exception * @param int $code The internal exception code */ - public function __construct($message = null, \Exception $previous = null, $code = 0) + public function __construct(string $message = null, \Throwable $previous = null, int $code = 0, array $headers = []) { - parent::__construct(422, $message, $previous, array(), $code); + parent::__construct(422, $message, $previous, $headers, $code); } } diff --git a/vendor/symfony/http-kernel/Exception/UnsupportedMediaTypeHttpException.php b/vendor/symfony/http-kernel/Exception/UnsupportedMediaTypeHttpException.php index 6913504e832dc41c75616884035b1e3b895d0280..7cda3a62028d515bcf39ea970f9aadcd0291e8f1 100644 --- a/vendor/symfony/http-kernel/Exception/UnsupportedMediaTypeHttpException.php +++ b/vendor/symfony/http-kernel/Exception/UnsupportedMediaTypeHttpException.php @@ -18,11 +18,11 @@ class UnsupportedMediaTypeHttpException extends HttpException { /** * @param string $message The internal exception message - * @param \Exception $previous The previous exception + * @param \Throwable $previous The previous exception * @param int $code The internal exception code */ - public function __construct($message = null, \Exception $previous = null, $code = 0) + public function __construct(string $message = null, \Throwable $previous = null, int $code = 0, array $headers = []) { - parent::__construct(415, $message, $previous, array(), $code); + parent::__construct(415, $message, $previous, $headers, $code); } } diff --git a/vendor/symfony/http-kernel/Fragment/AbstractSurrogateFragmentRenderer.php b/vendor/symfony/http-kernel/Fragment/AbstractSurrogateFragmentRenderer.php index a8dca41ba20c12319aaaf8c68878ab10a82dc8c7..5b76f7a8d866a7682fe0c9d60e7e24630e3f1e3e 100644 --- a/vendor/symfony/http-kernel/Fragment/AbstractSurrogateFragmentRenderer.php +++ b/vendor/symfony/http-kernel/Fragment/AbstractSurrogateFragmentRenderer.php @@ -59,11 +59,11 @@ abstract class AbstractSurrogateFragmentRenderer extends RoutableFragmentRendere * * @see Symfony\Component\HttpKernel\HttpCache\SurrogateInterface */ - public function render($uri, Request $request, array $options = array()) + public function render($uri, Request $request, array $options = []) { if (!$this->surrogate || !$this->surrogate->hasSurrogateCapability($request)) { if ($uri instanceof ControllerReference && $this->containsNonScalars($uri->attributes)) { - @trigger_error('Passing non-scalar values as part of URI attributes to the ESI and SSI rendering strategies is deprecated since Symfony 3.1, and will be removed in 4.0. Use a different rendering strategy or pass scalar values.', E_USER_DEPRECATED); + throw new \InvalidArgumentException('Passing non-scalar values as part of URI attributes to the ESI and SSI rendering strategies is not supported. Use a different rendering strategy or pass scalar values.'); } return $this->inlineStrategy->render($uri, $request, $options); @@ -83,7 +83,7 @@ abstract class AbstractSurrogateFragmentRenderer extends RoutableFragmentRendere return new Response($tag); } - private function generateSignedFragmentUri($uri, Request $request) + private function generateSignedFragmentUri($uri, Request $request): string { if (null === $this->signer) { throw new \LogicException('You must use a URI when using the ESI rendering strategy or set a URL signer.'); @@ -92,13 +92,13 @@ abstract class AbstractSurrogateFragmentRenderer extends RoutableFragmentRendere // we need to sign the absolute URI, but want to return the path only. $fragmentUri = $this->signer->sign($this->generateFragmentUri($uri, $request, true)); - return substr($fragmentUri, strlen($request->getSchemeAndHttpHost())); + return substr($fragmentUri, \strlen($request->getSchemeAndHttpHost())); } - private function containsNonScalars(array $values) + private function containsNonScalars(array $values): bool { foreach ($values as $value) { - if (is_array($value)) { + if (\is_array($value)) { return $this->containsNonScalars($value); } elseif (!is_scalar($value) && null !== $value) { return true; diff --git a/vendor/symfony/http-kernel/Fragment/FragmentHandler.php b/vendor/symfony/http-kernel/Fragment/FragmentHandler.php index c9d952ffbe044441d7435b84654a3ee51bab264c..1ae550fe45cb8322b3cc3f3636e768195f0d3367 100644 --- a/vendor/symfony/http-kernel/Fragment/FragmentHandler.php +++ b/vendor/symfony/http-kernel/Fragment/FragmentHandler.php @@ -11,9 +11,9 @@ namespace Symfony\Component\HttpKernel\Fragment; +use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\StreamedResponse; -use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\HttpKernel\Controller\ControllerReference; /** @@ -29,7 +29,7 @@ use Symfony\Component\HttpKernel\Controller\ControllerReference; class FragmentHandler { private $debug; - private $renderers = array(); + private $renderers = []; private $requestStack; /** @@ -37,7 +37,7 @@ class FragmentHandler * @param FragmentRendererInterface[] $renderers An array of FragmentRendererInterface instances * @param bool $debug Whether the debug mode is enabled or not */ - public function __construct(RequestStack $requestStack, array $renderers = array(), $debug = false) + public function __construct(RequestStack $requestStack, array $renderers = [], bool $debug = false) { $this->requestStack = $requestStack; foreach ($renderers as $renderer) { @@ -70,7 +70,7 @@ class FragmentHandler * @throws \InvalidArgumentException when the renderer does not exist * @throws \LogicException when no master request is being handled */ - public function render($uri, $renderer = 'inline', array $options = array()) + public function render($uri, $renderer = 'inline', array $options = []) { if (!isset($options['ignore_errors'])) { $options['ignore_errors'] = !$this->debug; @@ -108,5 +108,7 @@ class FragmentHandler } $response->sendContent(); + + return null; } } diff --git a/vendor/symfony/http-kernel/Fragment/FragmentRendererInterface.php b/vendor/symfony/http-kernel/Fragment/FragmentRendererInterface.php index b177c3ac12ca66f73812bc48462a75695cb04cfe..8e454a01a6ecbef50762c1af9bce46618ceb3d11 100644 --- a/vendor/symfony/http-kernel/Fragment/FragmentRendererInterface.php +++ b/vendor/symfony/http-kernel/Fragment/FragmentRendererInterface.php @@ -12,8 +12,8 @@ namespace Symfony\Component\HttpKernel\Fragment; use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpKernel\Controller\ControllerReference; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpKernel\Controller\ControllerReference; /** * Interface implemented by all rendering strategies. @@ -31,7 +31,7 @@ interface FragmentRendererInterface * * @return Response A Response instance */ - public function render($uri, Request $request, array $options = array()); + public function render($uri, Request $request, array $options = []); /** * Gets the name of the strategy. diff --git a/vendor/symfony/http-kernel/Fragment/HIncludeFragmentRenderer.php b/vendor/symfony/http-kernel/Fragment/HIncludeFragmentRenderer.php index 7e957d4c95f71ea579a537598fcc458c20953fc7..5d70c190246eb8fe0e81f0bc53dcf458c6b9d5da 100644 --- a/vendor/symfony/http-kernel/Fragment/HIncludeFragmentRenderer.php +++ b/vendor/symfony/http-kernel/Fragment/HIncludeFragmentRenderer.php @@ -13,12 +13,13 @@ namespace Symfony\Component\HttpKernel\Fragment; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\Templating\EngineInterface; use Symfony\Component\HttpKernel\Controller\ControllerReference; use Symfony\Component\HttpKernel\UriSigner; +use Symfony\Component\Templating\EngineInterface; use Twig\Environment; use Twig\Error\LoaderError; use Twig\Loader\ExistsLoaderInterface; +use Twig\Loader\SourceContextLoaderInterface; /** * Implements the Hinclude rendering strategy. @@ -36,9 +37,8 @@ class HIncludeFragmentRenderer extends RoutableFragmentRenderer * @param EngineInterface|Environment $templating An EngineInterface or a Twig instance * @param UriSigner $signer A UriSigner instance * @param string $globalDefaultTemplate The global default content (it can be a template name or the content) - * @param string $charset */ - public function __construct($templating = null, UriSigner $signer = null, $globalDefaultTemplate = null, $charset = 'utf-8') + public function __construct($templating = null, UriSigner $signer = null, string $globalDefaultTemplate = null, string $charset = 'utf-8') { $this->setTemplating($templating); $this->globalDefaultTemplate = $globalDefaultTemplate; @@ -59,6 +59,10 @@ class HIncludeFragmentRenderer extends RoutableFragmentRenderer throw new \InvalidArgumentException('The hinclude rendering strategy needs an instance of Twig\Environment or Symfony\Component\Templating\EngineInterface'); } + if ($templating instanceof EngineInterface) { + @trigger_error(sprintf('Using a "%s" instance for "%s" is deprecated since version 4.3; use a \Twig\Environment instance instead.', EngineInterface::class, __CLASS__), E_USER_DEPRECATED); + } + $this->templating = $templating; } @@ -81,7 +85,7 @@ class HIncludeFragmentRenderer extends RoutableFragmentRenderer * * id: An optional hx:include tag id attribute * * attributes: An optional array of hx:include tag attributes */ - public function render($uri, Request $request, array $options = array()) + public function render($uri, Request $request, array $options = []) { if ($uri instanceof ControllerReference) { if (null === $this->signer) { @@ -89,7 +93,7 @@ class HIncludeFragmentRenderer extends RoutableFragmentRenderer } // we need to sign the absolute URI, but want to return the path only. - $uri = substr($this->signer->sign($this->generateFragmentUri($uri, $request, true)), strlen($request->getSchemeAndHttpHost())); + $uri = substr($this->signer->sign($this->generateFragmentUri($uri, $request, true)), \strlen($request->getSchemeAndHttpHost())); } // We need to replace ampersands in the URI with the encoded form in order to return valid html/xml content. @@ -102,12 +106,12 @@ class HIncludeFragmentRenderer extends RoutableFragmentRenderer $content = $template; } - $attributes = isset($options['attributes']) && is_array($options['attributes']) ? $options['attributes'] : array(); + $attributes = isset($options['attributes']) && \is_array($options['attributes']) ? $options['attributes'] : []; if (isset($options['id']) && $options['id']) { $attributes['id'] = $options['id']; } $renderedAttributes = ''; - if (count($attributes) > 0) { + if (\count($attributes) > 0) { $flags = ENT_QUOTES | ENT_SUBSTITUTE; foreach ($attributes as $attribute => $value) { $renderedAttributes .= sprintf( @@ -121,38 +125,34 @@ class HIncludeFragmentRenderer extends RoutableFragmentRenderer return new Response(sprintf('<hx:include src="%s"%s>%s</hx:include>', $uri, $renderedAttributes, $content)); } - /** - * @param string $template - * - * @return bool - */ - private function templateExists($template) + private function templateExists(string $template): bool { if ($this->templating instanceof EngineInterface) { try { return $this->templating->exists($template); - } catch (\InvalidArgumentException $e) { + } catch (\Exception $e) { return false; } } $loader = $this->templating->getLoader(); - if ($loader instanceof ExistsLoaderInterface || method_exists($loader, 'exists')) { - return $loader->exists($template); - } - try { - if (method_exists($loader, 'getSourceContext')) { - $loader->getSourceContext($template); - } else { - $loader->getSource($template); + if (1 === Environment::MAJOR_VERSION && !$loader instanceof ExistsLoaderInterface) { + try { + if ($loader instanceof SourceContextLoaderInterface) { + $loader->getSourceContext($template); + } else { + $loader->getSource($template); + } + + return true; + } catch (LoaderError $e) { } - return true; - } catch (LoaderError $e) { + return false; } - return false; + return $loader->exists($template); } /** diff --git a/vendor/symfony/http-kernel/Fragment/InlineFragmentRenderer.php b/vendor/symfony/http-kernel/Fragment/InlineFragmentRenderer.php index 3f3a51a59e14525a3d717252460b404565f06ee5..8f89733b59721234f4b88dea51ebeda3b0051c6c 100644 --- a/vendor/symfony/http-kernel/Fragment/InlineFragmentRenderer.php +++ b/vendor/symfony/http-kernel/Fragment/InlineFragmentRenderer.php @@ -11,13 +11,15 @@ namespace Symfony\Component\HttpKernel\Fragment; +use Symfony\Component\EventDispatcher\LegacyEventDispatcherProxy; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\HttpKernel\HttpKernelInterface; use Symfony\Component\HttpKernel\Controller\ControllerReference; +use Symfony\Component\HttpKernel\Event\ExceptionEvent; +use Symfony\Component\HttpKernel\HttpCache\SubRequestHandler; +use Symfony\Component\HttpKernel\HttpKernelInterface; use Symfony\Component\HttpKernel\KernelEvents; -use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent; -use Symfony\Component\EventDispatcher\EventDispatcherInterface; +use Symfony\Contracts\EventDispatcher\EventDispatcherInterface; /** * Implements the inline rendering strategy where the Request is rendered by the current HTTP kernel. @@ -32,7 +34,7 @@ class InlineFragmentRenderer extends RoutableFragmentRenderer public function __construct(HttpKernelInterface $kernel, EventDispatcherInterface $dispatcher = null) { $this->kernel = $kernel; - $this->dispatcher = $dispatcher; + $this->dispatcher = LegacyEventDispatcherProxy::decorate($dispatcher); } /** @@ -42,7 +44,7 @@ class InlineFragmentRenderer extends RoutableFragmentRenderer * * * alt: an alternative URI to render in case of an error */ - public function render($uri, Request $request, array $options = array()) + public function render($uri, Request $request, array $options = []) { $reference = null; if ($uri instanceof ControllerReference) { @@ -53,10 +55,10 @@ class InlineFragmentRenderer extends RoutableFragmentRenderer // want that as we want to preserve objects (so we manually set Request attributes // below instead) $attributes = $reference->attributes; - $reference->attributes = array(); + $reference->attributes = []; // The request format and locale might have been overridden by the user - foreach (array('_format', '_locale') as $key) { + foreach (['_format', '_locale'] as $key) { if (isset($attributes[$key])) { $reference->attributes[$key] = $attributes[$key]; } @@ -76,14 +78,14 @@ class InlineFragmentRenderer extends RoutableFragmentRenderer $level = ob_get_level(); try { - return $this->kernel->handle($subRequest, HttpKernelInterface::SUB_REQUEST, false); + return SubRequestHandler::handle($this->kernel, $subRequest, HttpKernelInterface::SUB_REQUEST, false); } catch (\Exception $e) { // we dispatch the exception event to trigger the logging - // the response that comes back is simply ignored + // the response that comes back is ignored if (isset($options['ignore_errors']) && $options['ignore_errors'] && $this->dispatcher) { - $event = new GetResponseForExceptionEvent($this->kernel, $request, HttpKernelInterface::SUB_REQUEST, $e); + $event = new ExceptionEvent($this->kernel, $request, HttpKernelInterface::SUB_REQUEST, $e); - $this->dispatcher->dispatch(KernelEvents::EXCEPTION, $event); + $this->dispatcher->dispatch($event, KernelEvents::EXCEPTION); } // let's clean up the output buffers that were created by the sub-request @@ -109,34 +111,26 @@ class InlineFragmentRenderer extends RoutableFragmentRenderer $cookies = $request->cookies->all(); $server = $request->server->all(); - // Override the arguments to emulate a sub-request. - // Sub-request object will point to localhost as client ip and real client ip - // will be included into trusted header for client ip - try { - if (Request::HEADER_X_FORWARDED_FOR & Request::getTrustedHeaderSet()) { - $currentXForwardedFor = $request->headers->get('X_FORWARDED_FOR', ''); - - $server['HTTP_X_FORWARDED_FOR'] = ($currentXForwardedFor ? $currentXForwardedFor.', ' : '').$request->getClientIp(); - } elseif (method_exists(Request::class, 'getTrustedHeaderName') && $trustedHeaderName = Request::getTrustedHeaderName(Request::HEADER_CLIENT_IP, false)) { - $currentXForwardedFor = $request->headers->get($trustedHeaderName, ''); - - $server['HTTP_'.$trustedHeaderName] = ($currentXForwardedFor ? $currentXForwardedFor.', ' : '').$request->getClientIp(); - } - } catch (\InvalidArgumentException $e) { - // Do nothing - } - - $server['REMOTE_ADDR'] = '127.0.0.1'; unset($server['HTTP_IF_MODIFIED_SINCE']); unset($server['HTTP_IF_NONE_MATCH']); - $subRequest = Request::create($uri, 'get', array(), $cookies, array(), $server); + $subRequest = Request::create($uri, 'get', [], $cookies, [], $server); if ($request->headers->has('Surrogate-Capability')) { $subRequest->headers->set('Surrogate-Capability', $request->headers->get('Surrogate-Capability')); } - if ($session = $request->getSession()) { - $subRequest->setSession($session); + static $setSession; + + if (null === $setSession) { + $setSession = \Closure::bind(static function ($subRequest, $request) { $subRequest->session = $request->session; }, null, Request::class); + } + $setSession($subRequest, $request); + + if ($request->get('_format')) { + $subRequest->attributes->set('_format', $request->get('_format')); + } + if ($request->getDefaultLocale() !== $request->getLocale()) { + $subRequest->setLocale($request->getLocale()); } return $subRequest; diff --git a/vendor/symfony/http-kernel/Fragment/RoutableFragmentRenderer.php b/vendor/symfony/http-kernel/Fragment/RoutableFragmentRenderer.php index d7eeb89a6befcae152ed34f3e29faa7cab9a5c71..0c1b95d4e939338b72664a96e2d79c0dae36778d 100644 --- a/vendor/symfony/http-kernel/Fragment/RoutableFragmentRenderer.php +++ b/vendor/symfony/http-kernel/Fragment/RoutableFragmentRenderer.php @@ -11,8 +11,8 @@ namespace Symfony\Component\HttpKernel\Fragment; -use Symfony\Component\HttpKernel\Controller\ControllerReference; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpKernel\Controller\ControllerReference; use Symfony\Component\HttpKernel\EventListener\FragmentListener; /** @@ -80,7 +80,7 @@ abstract class RoutableFragmentRenderer implements FragmentRendererInterface private function checkNonScalar($values) { foreach ($values as $key => $value) { - if (is_array($value)) { + if (\is_array($value)) { $this->checkNonScalar($value); } elseif (!is_scalar($value) && null !== $value) { throw new \LogicException(sprintf('Controller attributes cannot contain non-scalar/non-null values (value for key "%s" is not a scalar or null).', $key)); diff --git a/vendor/symfony/http-kernel/HttpCache/AbstractSurrogate.php b/vendor/symfony/http-kernel/HttpCache/AbstractSurrogate.php index 3b2d5f262cfcc9e81917f19188a1a1afbed0c855..9b4541793f05fb671843170f569f2a7bf329e22a 100644 --- a/vendor/symfony/http-kernel/HttpCache/AbstractSurrogate.php +++ b/vendor/symfony/http-kernel/HttpCache/AbstractSurrogate.php @@ -24,16 +24,16 @@ use Symfony\Component\HttpKernel\HttpKernelInterface; abstract class AbstractSurrogate implements SurrogateInterface { protected $contentTypes; - protected $phpEscapeMap = array( - array('<?', '<%', '<s', '<S'), - array('<?php echo "<?"; ?>', '<?php echo "<%"; ?>', '<?php echo "<s"; ?>', '<?php echo "<S"; ?>'), - ); + protected $phpEscapeMap = [ + ['<?', '<%', '<s', '<S'], + ['<?php echo "<?"; ?>', '<?php echo "<%"; ?>', '<?php echo "<s"; ?>', '<?php echo "<S"; ?>'], + ]; /** * @param array $contentTypes An array of content-type that should be parsed for Surrogate information * (default: text/html, text/xml, application/xhtml+xml, and application/xml) */ - public function __construct(array $contentTypes = array('text/html', 'text/xml', 'application/xhtml+xml', 'application/xml')) + public function __construct(array $contentTypes = ['text/html', 'text/xml', 'application/xhtml+xml', 'application/xml']) { $this->contentTypes = $contentTypes; } @@ -90,7 +90,7 @@ abstract class AbstractSurrogate implements SurrogateInterface */ public function handle(HttpCache $cache, $uri, $alt, $ignoreErrors) { - $subRequest = Request::create($uri, Request::METHOD_GET, array(), $cache->getRequest()->cookies->all(), array(), $cache->getRequest()->server->all()); + $subRequest = Request::create($uri, Request::METHOD_GET, [], $cache->getRequest()->cookies->all(), [], $cache->getRequest()->server->all()); try { $response = $cache->handle($subRequest, HttpKernelInterface::SUB_REQUEST, true); @@ -109,6 +109,8 @@ abstract class AbstractSurrogate implements SurrogateInterface throw $e; } } + + return ''; } /** diff --git a/vendor/symfony/http-kernel/HttpCache/Esi.php b/vendor/symfony/http-kernel/HttpCache/Esi.php index d09907ea6220746b3fbc8bbef054f4970f9897d0..96e6ca4bfe617942470dd07a76f8619c5ad99887 100644 --- a/vendor/symfony/http-kernel/HttpCache/Esi.php +++ b/vendor/symfony/http-kernel/HttpCache/Esi.php @@ -71,7 +71,7 @@ class Esi extends AbstractSurrogate } $parts = explode(';', $type); - if (!in_array($parts[0], $this->contentTypes)) { + if (!\in_array($parts[0], $this->contentTypes)) { return $response; } @@ -85,7 +85,7 @@ class Esi extends AbstractSurrogate $i = 1; while (isset($chunks[$i])) { - $options = array(); + $options = []; preg_match_all('/(src|onerror|alt)="([^"]*?)"/', $chunks[$i], $matches, PREG_SET_ORDER); foreach ($matches as $set) { $options[$set[1]] = $set[2]; @@ -111,5 +111,7 @@ class Esi extends AbstractSurrogate // remove ESI/1.0 from the Surrogate-Control header $this->removeFromControl($response); + + return $response; } } diff --git a/vendor/symfony/http-kernel/HttpCache/HttpCache.php b/vendor/symfony/http-kernel/HttpCache/HttpCache.php index 7c5a44f05ba914a77f701bbeb9dddfd4374710a9..ab178ed42c43f086fa61d3fa58bbd6f96546a7ca 100644 --- a/vendor/symfony/http-kernel/HttpCache/HttpCache.php +++ b/vendor/symfony/http-kernel/HttpCache/HttpCache.php @@ -15,10 +15,10 @@ namespace Symfony\Component\HttpKernel\HttpCache; -use Symfony\Component\HttpKernel\HttpKernelInterface; -use Symfony\Component\HttpKernel\TerminableInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpKernel\HttpKernelInterface; +use Symfony\Component\HttpKernel\TerminableInterface; /** * Cache provides HTTP caching. @@ -32,15 +32,22 @@ class HttpCache implements HttpKernelInterface, TerminableInterface private $request; private $surrogate; private $surrogateCacheStrategy; - private $options = array(); - private $traces = array(); + private $options = []; + private $traces = []; /** * Constructor. * * The available options are: * - * * debug: If true, the traces are added as a HTTP header to ease debugging + * * debug If true, exceptions are thrown when things go wrong. Otherwise, the cache + * will try to carry on and deliver a meaningful response. + * + * * trace_level May be one of 'none', 'short' and 'full'. For 'short', a concise trace of the + * master request will be added as an HTTP header. 'full' will add traces for all + * requests (including ESI subrequests). (default: 'full' if in debug; 'none' otherwise) + * + * * trace_header Header name to use for traces. (default: X-Symfony-Cache) * * * default_ttl The number of seconds that a cache entry should be considered * fresh when no explicit freshness information is provided in @@ -70,30 +77,36 @@ class HttpCache implements HttpKernelInterface, TerminableInterface * This setting is overridden by the stale-if-error HTTP Cache-Control extension * (see RFC 5861). */ - public function __construct(HttpKernelInterface $kernel, StoreInterface $store, SurrogateInterface $surrogate = null, array $options = array()) + public function __construct(HttpKernelInterface $kernel, StoreInterface $store, SurrogateInterface $surrogate = null, array $options = []) { $this->store = $store; $this->kernel = $kernel; $this->surrogate = $surrogate; // needed in case there is a fatal error because the backend is too slow to respond - register_shutdown_function(array($this->store, 'cleanup')); + register_shutdown_function([$this->store, 'cleanup']); - $this->options = array_merge(array( + $this->options = array_merge([ 'debug' => false, 'default_ttl' => 0, - 'private_headers' => array('Authorization', 'Cookie'), + 'private_headers' => ['Authorization', 'Cookie'], 'allow_reload' => false, 'allow_revalidate' => false, 'stale_while_revalidate' => 2, 'stale_if_error' => 60, - ), $options); + 'trace_level' => 'none', + 'trace_header' => 'X-Symfony-Cache', + ], $options); + + if (!isset($options['trace_level'])) { + $this->options['trace_level'] = $this->options['debug'] ? 'full' : 'none'; + } } /** * Gets the current store. * - * @return StoreInterface $store A StoreInterface instance + * @return StoreInterface A StoreInterface instance */ public function getStore() { @@ -110,6 +123,23 @@ class HttpCache implements HttpKernelInterface, TerminableInterface return $this->traces; } + private function addTraces(Response $response) + { + $traceString = null; + + if ('full' === $this->options['trace_level']) { + $traceString = $this->getLog(); + } + + if ('short' === $this->options['trace_level'] && $masterId = array_key_first($this->traces)) { + $traceString = implode('/', $this->traces[$masterId]); + } + + if (null !== $traceString) { + $response->headers->add([$this->options['trace_header'] => $traceString]); + } + } + /** * Returns a log message for the events of the last request processing. * @@ -117,7 +147,7 @@ class HttpCache implements HttpKernelInterface, TerminableInterface */ public function getLog() { - $log = array(); + $log = []; foreach ($this->traces as $request => $traces) { $log[] = sprintf('%s: %s', $request, implode(', ', $traces)); } @@ -164,14 +194,18 @@ class HttpCache implements HttpKernelInterface, TerminableInterface { // FIXME: catch exceptions and implement a 500 error page here? -> in Varnish, there is a built-in error page mechanism if (HttpKernelInterface::MASTER_REQUEST === $type) { - $this->traces = array(); - $this->request = $request; + $this->traces = []; + // Keep a clone of the original request for surrogates so they can access it. + // We must clone here to get a separate instance because the application will modify the request during + // the application flow (we know it always does because we do ourselves by setting REMOTE_ADDR to 127.0.0.1 + // and adding the X-Forwarded-For header, see HttpCache::forward()). + $this->request = clone $request; if (null !== $this->surrogate) { $this->surrogateCacheStrategy = $this->surrogate->createCacheStrategy(); } } - $this->traces[$this->getTraceKey($request)] = array(); + $this->traces[$this->getTraceKey($request)] = []; if (!$request->isMethodSafe(false)) { $response = $this->invalidate($request, $catch); @@ -190,8 +224,8 @@ class HttpCache implements HttpKernelInterface, TerminableInterface $this->restoreResponseBody($request, $response); - if (HttpKernelInterface::MASTER_REQUEST === $type && $this->options['debug']) { - $response->headers->set('X-Symfony-Cache', $this->getLog()); + if (HttpKernelInterface::MASTER_REQUEST === $type) { + $this->addTraces($response); } if (null !== $this->surrogate) { @@ -256,9 +290,9 @@ class HttpCache implements HttpKernelInterface, TerminableInterface $this->store->invalidate($request); // As per the RFC, invalidate Location and Content-Location URLs if present - foreach (array('Location', 'Content-Location') as $header) { + foreach (['Location', 'Content-Location'] as $header) { if ($uri = $response->headers->get($header)) { - $subRequest = Request::create($uri, 'get', array(), array(), array(), $request->server->all()); + $subRequest = Request::create($uri, 'get', [], [], [], $request->server->all()); $this->store->invalidate($subRequest); } @@ -353,7 +387,7 @@ class HttpCache implements HttpKernelInterface, TerminableInterface // Add our cached etag validator to the environment. // We keep the etags from the client to handle the case when the client // has a different private valid entry which is not cached here. - $cachedEtags = $entry->getEtag() ? array($entry->getEtag()) : array(); + $cachedEtags = $entry->getEtag() ? [$entry->getEtag()] : []; $requestEtags = $request->getETags(); if ($etags = array_unique(array_merge($cachedEtags, $requestEtags))) { $subRequest->headers->set('if_none_match', implode(', ', $etags)); @@ -366,14 +400,14 @@ class HttpCache implements HttpKernelInterface, TerminableInterface // return the response and not the cache entry if the response is valid but not cached $etag = $response->getEtag(); - if ($etag && in_array($etag, $requestEtags) && !in_array($etag, $cachedEtags)) { + if ($etag && \in_array($etag, $requestEtags) && !\in_array($etag, $cachedEtags)) { return $response; } $entry = clone $entry; $entry->headers->remove('Date'); - foreach (array('Date', 'Expires', 'Cache-Control', 'ETag', 'Last-Modified') as $name) { + foreach (['Date', 'Expires', 'Cache-Control', 'ETag', 'Last-Modified'] as $name) { if ($response->headers->has($name)) { $entry->headers->set($name, $response->headers->get($name)); } @@ -428,9 +462,8 @@ class HttpCache implements HttpKernelInterface, TerminableInterface * All backend requests (cache passes, fetches, cache validations) * run through this method. * - * @param Request $request A Request instance - * @param bool $catch Whether to catch exceptions or not - * @param Response $entry A Response instance (the stale entry if present, null otherwise) + * @param bool $catch Whether to catch exceptions or not + * @param Response|null $entry A Response instance (the stale entry if present, null otherwise) * * @return Response A Response instance */ @@ -440,30 +473,11 @@ class HttpCache implements HttpKernelInterface, TerminableInterface $this->surrogate->addSurrogateCapability($request); } - // modify the X-Forwarded-For header if needed - $forwardedFor = $request->headers->get('X-Forwarded-For'); - if ($forwardedFor) { - $request->headers->set('X-Forwarded-For', $forwardedFor.', '.$request->server->get('REMOTE_ADDR')); - } else { - $request->headers->set('X-Forwarded-For', $request->server->get('REMOTE_ADDR')); - } - - // fix the client IP address by setting it to 127.0.0.1 as HttpCache - // is always called from the same process as the backend. - $request->server->set('REMOTE_ADDR', '127.0.0.1'); - - // make sure HttpCache is a trusted proxy - if (!in_array('127.0.0.1', $trustedProxies = Request::getTrustedProxies())) { - $trustedProxies[] = '127.0.0.1'; - Request::setTrustedProxies($trustedProxies, Request::HEADER_X_FORWARDED_ALL); - } - // always a "master" request (as the real master request can be in cache) - $response = $this->kernel->handle($request, HttpKernelInterface::MASTER_REQUEST, $catch); - // FIXME: we probably need to also catch exceptions if raw === true + $response = SubRequestHandler::handle($this->kernel, $request, HttpKernelInterface::MASTER_REQUEST, $catch); // we don't implement the stale-if-error on Requests, which is nonetheless part of the RFC - if (null !== $entry && in_array($response->getStatusCode(), array(500, 502, 503, 504))) { + if (null !== $entry && \in_array($response->getStatusCode(), [500, 502, 503, 504])) { if (null === $age = $entry->headers->getCacheControlDirective('stale-if-error')) { $age = $this->options['stale_if_error']; } @@ -602,7 +616,7 @@ class HttpCache implements HttpKernelInterface, TerminableInterface $response->setContent(ob_get_clean()); $response->headers->remove('X-Body-Eval'); if (!$response->headers->has('Transfer-Encoding')) { - $response->headers->set('Content-Length', strlen($response->getContent())); + $response->headers->set('Content-Length', \strlen($response->getContent())); } } elseif ($response->headers->has('X-Body-File')) { // Response does not include possibly dynamic content (ESI, SSI), so we need @@ -636,7 +650,7 @@ class HttpCache implements HttpKernelInterface, TerminableInterface $key = strtolower(str_replace('HTTP_', '', $key)); if ('cookie' === $key) { - if (count($request->cookies->all())) { + if (\count($request->cookies->all())) { return true; } } elseif ($request->headers->has($key)) { @@ -649,23 +663,16 @@ class HttpCache implements HttpKernelInterface, TerminableInterface /** * Records that an event took place. - * - * @param Request $request A Request instance - * @param string $event The event name */ - private function record(Request $request, $event) + private function record(Request $request, string $event) { $this->traces[$this->getTraceKey($request)][] = $event; } /** * Calculates the key we use in the "trace" array for a given request. - * - * @param Request $request - * - * @return string */ - private function getTraceKey(Request $request) + private function getTraceKey(Request $request): string { $path = $request->getPathInfo(); if ($qs = $request->getQueryString()) { @@ -678,12 +685,8 @@ class HttpCache implements HttpKernelInterface, TerminableInterface /** * Checks whether the given (cached) response may be served as "stale" when a revalidation * is currently in progress. - * - * @param Response $entry - * - * @return bool true when the stale response may be served, false otherwise */ - private function mayServeStaleWhileRevalidate(Response $entry) + private function mayServeStaleWhileRevalidate(Response $entry): bool { $timeout = $entry->headers->getCacheControlDirective('stale-while-revalidate'); @@ -696,12 +699,8 @@ class HttpCache implements HttpKernelInterface, TerminableInterface /** * Waits for the store to release a locked entry. - * - * @param Request $request The request to wait for - * - * @return bool true if the lock was released before the internal timeout was hit; false if the wait timeout was exceeded */ - private function waitForLock(Request $request) + private function waitForLock(Request $request): bool { $wait = 0; while ($this->store->isLocked($request) && $wait < 100) { diff --git a/vendor/symfony/http-kernel/HttpCache/ResponseCacheStrategy.php b/vendor/symfony/http-kernel/HttpCache/ResponseCacheStrategy.php index 027b2b1761334cd8ab712dc3194e6017b496442b..25c071c335a02d4d24203652a701d4f37e6fca57 100644 --- a/vendor/symfony/http-kernel/HttpCache/ResponseCacheStrategy.php +++ b/vendor/symfony/http-kernel/HttpCache/ResponseCacheStrategy.php @@ -5,10 +5,6 @@ * * (c) Fabien Potencier <fabien@symfony.com> * - * This code is partially based on the Rack-Cache library by Ryan Tomayko, - * which is released under the MIT license. - * (based on commit 02d2b48d75bcb63cf1c0c7149c077ad256542801) - * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ @@ -28,30 +24,69 @@ use Symfony\Component\HttpFoundation\Response; */ class ResponseCacheStrategy implements ResponseCacheStrategyInterface { - private $cacheable = true; + /** + * Cache-Control headers that are sent to the final response if they appear in ANY of the responses. + */ + private static $overrideDirectives = ['private', 'no-cache', 'no-store', 'no-transform', 'must-revalidate', 'proxy-revalidate']; + + /** + * Cache-Control headers that are sent to the final response if they appear in ALL of the responses. + */ + private static $inheritDirectives = ['public', 'immutable']; + private $embeddedResponses = 0; - private $ttls = array(); - private $maxAges = array(); private $isNotCacheableResponseEmbedded = false; + private $age = 0; + private $flagDirectives = [ + 'no-cache' => null, + 'no-store' => null, + 'no-transform' => null, + 'must-revalidate' => null, + 'proxy-revalidate' => null, + 'public' => null, + 'private' => null, + 'immutable' => null, + ]; + private $ageDirectives = [ + 'max-age' => null, + 's-maxage' => null, + 'expires' => null, + ]; /** * {@inheritdoc} */ public function add(Response $response) { - if (!$response->isFresh() || !$response->isCacheable()) { - $this->cacheable = false; - } else { - $maxAge = $response->getMaxAge(); - $this->ttls[] = $response->getTtl(); - $this->maxAges[] = $maxAge; - - if (null === $maxAge) { - $this->isNotCacheableResponseEmbedded = true; + ++$this->embeddedResponses; + + foreach (self::$overrideDirectives as $directive) { + if ($response->headers->hasCacheControlDirective($directive)) { + $this->flagDirectives[$directive] = true; } } - ++$this->embeddedResponses; + foreach (self::$inheritDirectives as $directive) { + if (false !== $this->flagDirectives[$directive]) { + $this->flagDirectives[$directive] = $response->headers->hasCacheControlDirective($directive); + } + } + + $age = $response->getAge(); + $this->age = max($this->age, $age); + + if ($this->willMakeFinalResponseUncacheable($response)) { + $this->isNotCacheableResponseEmbedded = true; + + return; + } + + $this->storeRelativeAgeDirective('max-age', $response->headers->getCacheControlDirective('max-age'), $age); + $this->storeRelativeAgeDirective('s-maxage', $response->headers->getCacheControlDirective('s-maxage') ?: $response->headers->getCacheControlDirective('max-age'), $age); + + $expires = $response->getExpires(); + $expires = null !== $expires ? (int) $expires->format('U') - (int) $response->getDate()->format('U') : null; + $this->storeRelativeAgeDirective('expires', $expires >= 0 ? $expires : null, 0); } /** @@ -64,33 +99,124 @@ class ResponseCacheStrategy implements ResponseCacheStrategyInterface return; } - // Remove validation related headers in order to avoid browsers using - // their own cache, because some of the response content comes from - // at least one embedded response (which likely has a different caching strategy). - if ($response->isValidateable()) { - $response->setEtag(null); - $response->setLastModified(null); + // Remove validation related headers of the master response, + // because some of the response content comes from at least + // one embedded response (which likely has a different caching strategy). + $response->setEtag(null); + $response->setLastModified(null); + + $this->add($response); + + $response->headers->set('Age', $this->age); + + if ($this->isNotCacheableResponseEmbedded) { + $response->setExpires($response->getDate()); + + if ($this->flagDirectives['no-store']) { + $response->headers->set('Cache-Control', 'no-cache, no-store, must-revalidate'); + } else { + $response->headers->set('Cache-Control', 'no-cache, must-revalidate'); + } + + return; + } + + $flags = array_filter($this->flagDirectives); + + if (isset($flags['must-revalidate'])) { + $flags['no-cache'] = true; } - if (!$response->isFresh()) { - $this->cacheable = false; + $response->headers->set('Cache-Control', implode(', ', array_keys($flags))); + + $maxAge = null; + $sMaxage = null; + + if (is_numeric($this->ageDirectives['max-age'])) { + $maxAge = $this->ageDirectives['max-age'] + $this->age; + $response->headers->addCacheControlDirective('max-age', $maxAge); } - if (!$this->cacheable) { - $response->headers->set('Cache-Control', 'no-cache, must-revalidate'); + if (is_numeric($this->ageDirectives['s-maxage'])) { + $sMaxage = $this->ageDirectives['s-maxage'] + $this->age; - return; + if ($maxAge !== $sMaxage) { + $response->headers->addCacheControlDirective('s-maxage', $sMaxage); + } + } + + if (is_numeric($this->ageDirectives['expires'])) { + $date = clone $response->getDate(); + $date->modify('+'.($this->ageDirectives['expires'] + $this->age).' seconds'); + $response->setExpires($date); } + } - $this->ttls[] = $response->getTtl(); - $this->maxAges[] = $response->getMaxAge(); + /** + * RFC2616, Section 13.4. + * + * @see https://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html#sec13.4 + * + * @return bool + */ + private function willMakeFinalResponseUncacheable(Response $response) + { + // RFC2616: A response received with a status code of 200, 203, 300, 301 or 410 + // MAY be stored by a cache […] unless a cache-control directive prohibits caching. + if ($response->headers->hasCacheControlDirective('no-cache') + || $response->headers->getCacheControlDirective('no-store') + ) { + return true; + } - if ($this->isNotCacheableResponseEmbedded) { - $response->headers->removeCacheControlDirective('s-maxage'); - } elseif (null !== $maxAge = min($this->maxAges)) { - $response->setSharedMaxAge($maxAge); - $response->headers->set('Age', $maxAge - min($this->ttls)); + // Last-Modified and Etag headers cannot be merged, they render the response uncacheable + // by default (except if the response also has max-age etc.). + if (\in_array($response->getStatusCode(), [200, 203, 300, 301, 410]) + && null === $response->getLastModified() + && null === $response->getEtag() + ) { + return false; + } + + // RFC2616: A response received with any other status code (e.g. status codes 302 and 307) + // MUST NOT be returned in a reply to a subsequent request unless there are + // cache-control directives or another header(s) that explicitly allow it. + $cacheControl = ['max-age', 's-maxage', 'must-revalidate', 'proxy-revalidate', 'public', 'private']; + foreach ($cacheControl as $key) { + if ($response->headers->hasCacheControlDirective($key)) { + return false; + } + } + + if ($response->headers->has('Expires')) { + return false; + } + + return true; + } + + /** + * Store lowest max-age/s-maxage/expires for the final response. + * + * The response might have been stored in cache a while ago. To keep things comparable, + * we have to subtract the age so that the value is normalized for an age of 0. + * + * If the value is lower than the currently stored value, we update the value, to keep a rolling + * minimal value of each instruction. If the value is NULL, the directive will not be set on the final response. + * + * @param string $directive + * @param int|null $value + * @param int $age + */ + private function storeRelativeAgeDirective($directive, $value, $age) + { + if (null === $value) { + $this->ageDirectives[$directive] = false; + } + + if (false !== $this->ageDirectives[$directive]) { + $value -= $age; + $this->ageDirectives[$directive] = null !== $this->ageDirectives[$directive] ? min($this->ageDirectives[$directive], $value) : $value; } - $response->setMaxAge(0); } } diff --git a/vendor/symfony/http-kernel/HttpCache/Ssi.php b/vendor/symfony/http-kernel/HttpCache/Ssi.php index 3178c335159657a19281b74504efea1a91ef8324..40aac64f2a1324e05df009b4776de8191dc2100b 100644 --- a/vendor/symfony/http-kernel/HttpCache/Ssi.php +++ b/vendor/symfony/http-kernel/HttpCache/Ssi.php @@ -58,7 +58,7 @@ class Ssi extends AbstractSurrogate } $parts = explode(';', $type); - if (!in_array($parts[0], $this->contentTypes)) { + if (!\in_array($parts[0], $this->contentTypes)) { return $response; } @@ -70,7 +70,7 @@ class Ssi extends AbstractSurrogate $i = 1; while (isset($chunks[$i])) { - $options = array(); + $options = []; preg_match_all('/(virtual)="([^"]*?)"/', $chunks[$i], $matches, PREG_SET_ORDER); foreach ($matches as $set) { $options[$set[1]] = $set[2]; @@ -94,5 +94,7 @@ class Ssi extends AbstractSurrogate // remove SSI/1.0 from the Surrogate-Control header $this->removeFromControl($response); + + return $response; } } diff --git a/vendor/symfony/http-kernel/HttpCache/Store.php b/vendor/symfony/http-kernel/HttpCache/Store.php index fa0d4a86712b6a2709c4e6f24613db593fc70c35..7026ac3c7d878c00f99a1f1cea60a783465d4822 100644 --- a/vendor/symfony/http-kernel/HttpCache/Store.php +++ b/vendor/symfony/http-kernel/HttpCache/Store.php @@ -29,18 +29,16 @@ class Store implements StoreInterface private $locks; /** - * @param string $root The path to the cache directory - * * @throws \RuntimeException */ - public function __construct($root) + public function __construct(string $root) { $this->root = $root; if (!file_exists($this->root) && !@mkdir($this->root, 0777, true) && !is_dir($this->root)) { throw new \RuntimeException(sprintf('Unable to create the store directory (%s).', $this->root)); } $this->keyCache = new \SplObjectStorage(); - $this->locks = array(); + $this->locks = []; } /** @@ -54,7 +52,7 @@ class Store implements StoreInterface fclose($lock); } - $this->locks = array(); + $this->locks = []; } /** @@ -68,7 +66,7 @@ class Store implements StoreInterface if (!isset($this->locks[$key])) { $path = $this->getPath($key); - if (!file_exists(dirname($path)) && false === @mkdir(dirname($path), 0777, true) && !is_dir(dirname($path))) { + if (!file_exists(\dirname($path)) && false === @mkdir(\dirname($path), 0777, true) && !is_dir(\dirname($path))) { return $path; } $h = fopen($path, 'cb'); @@ -134,7 +132,7 @@ class Store implements StoreInterface $key = $this->getCacheKey($request); if (!$entries = $this->getMetadata($key)) { - return; + return null; } // find a cached entry that matches the request. @@ -148,7 +146,7 @@ class Store implements StoreInterface } if (null === $match) { - return; + return null; } $headers = $match[1]; @@ -159,6 +157,7 @@ class Store implements StoreInterface // TODO the metaStore referenced an entity that doesn't exist in // the entityStore. We definitely want to return nil but we should // also purge the entry from the meta-store when this is detected. + return null; } /** @@ -180,23 +179,23 @@ class Store implements StoreInterface if (!$response->headers->has('X-Content-Digest')) { $digest = $this->generateContentDigest($response); - if (false === $this->save($digest, $response->getContent())) { + if (!$this->save($digest, $response->getContent())) { throw new \RuntimeException('Unable to store the entity.'); } $response->headers->set('X-Content-Digest', $digest); if (!$response->headers->has('Transfer-Encoding')) { - $response->headers->set('Content-Length', strlen($response->getContent())); + $response->headers->set('Content-Length', \strlen($response->getContent())); } } // read existing cache entries, remove non-varying, and add this one to the list - $entries = array(); + $entries = []; $vary = $response->headers->get('vary'); foreach ($this->getMetadata($key) as $entry) { if (!isset($entry[1]['vary'][0])) { - $entry[1]['vary'] = array(''); + $entry[1]['vary'] = ['']; } if ($entry[1]['vary'][0] != $vary || !$this->requestsMatch($vary, $entry[0], $storedEnv)) { @@ -207,9 +206,9 @@ class Store implements StoreInterface $headers = $this->persistResponse($response); unset($headers['age']); - array_unshift($entries, array($storedEnv, $headers)); + array_unshift($entries, [$storedEnv, $headers]); - if (false === $this->save($key, serialize($entries))) { + if (!$this->save($key, serialize($entries))) { throw new \RuntimeException('Unable to store the metadata.'); } @@ -236,19 +235,19 @@ class Store implements StoreInterface $modified = false; $key = $this->getCacheKey($request); - $entries = array(); + $entries = []; foreach ($this->getMetadata($key) as $entry) { $response = $this->restoreResponse($entry[1]); if ($response->isFresh()) { $response->expire(); $modified = true; - $entries[] = array($entry[0], $this->persistResponse($response)); + $entries[] = [$entry[0], $this->persistResponse($response)]; } else { $entries[] = $entry; } } - if ($modified && false === $this->save($key, serialize($entries))) { + if ($modified && !$this->save($key, serialize($entries))) { throw new \RuntimeException('Unable to store the metadata.'); } } @@ -293,7 +292,7 @@ class Store implements StoreInterface private function getMetadata($key) { if (!$entries = $this->load($key)) { - return array(); + return []; } return unserialize($entries); @@ -349,13 +348,13 @@ class Store implements StoreInterface * * @param string $key The store key * - * @return string The data associated with the key + * @return string|null The data associated with the key */ private function load($key) { $path = $this->getPath($key); - return file_exists($path) ? file_get_contents($path) : false; + return file_exists($path) && false !== ($contents = file_get_contents($path)) ? $contents : null; } /** @@ -375,38 +374,46 @@ class Store implements StoreInterface @ftruncate($fp, 0); @fseek($fp, 0); $len = @fwrite($fp, $data); - if (strlen($data) !== $len) { + if (\strlen($data) !== $len) { @ftruncate($fp, 0); return false; } } else { - if (!file_exists(dirname($path)) && false === @mkdir(dirname($path), 0777, true) && !is_dir(dirname($path))) { + if (!file_exists(\dirname($path)) && false === @mkdir(\dirname($path), 0777, true) && !is_dir(\dirname($path))) { return false; } - $tmpFile = tempnam(dirname($path), basename($path)); + $tmpFile = tempnam(\dirname($path), basename($path)); if (false === $fp = @fopen($tmpFile, 'wb')) { + @unlink($tmpFile); + return false; } @fwrite($fp, $data); @fclose($fp); if ($data != file_get_contents($tmpFile)) { + @unlink($tmpFile); + return false; } if (false === @rename($tmpFile, $path)) { + @unlink($tmpFile); + return false; } } @chmod($path, 0666 & ~umask()); + + return true; } public function getPath($key) { - return $this->root.DIRECTORY_SEPARATOR.substr($key, 0, 2).DIRECTORY_SEPARATOR.substr($key, 2, 2).DIRECTORY_SEPARATOR.substr($key, 4, 2).DIRECTORY_SEPARATOR.substr($key, 6); + return $this->root.\DIRECTORY_SEPARATOR.substr($key, 0, 2).\DIRECTORY_SEPARATOR.substr($key, 2, 2).\DIRECTORY_SEPARATOR.substr($key, 4, 2).\DIRECTORY_SEPARATOR.substr($key, 6); } /** @@ -458,7 +465,7 @@ class Store implements StoreInterface private function persistResponse(Response $response) { $headers = $response->headers->all(); - $headers['X-Status'] = array($response->getStatusCode()); + $headers['X-Status'] = [$response->getStatusCode()]; return $headers; } @@ -477,7 +484,7 @@ class Store implements StoreInterface unset($headers['X-Status']); if (null !== $body) { - $headers['X-Body-File'] = array($body); + $headers['X-Body-File'] = [$body]; } return new Response($body, $status, $headers); diff --git a/vendor/symfony/http-kernel/HttpCache/SubRequestHandler.php b/vendor/symfony/http-kernel/HttpCache/SubRequestHandler.php new file mode 100644 index 0000000000000000000000000000000000000000..cef9817e01d6c8f42b3eb09bd8c6ceb8746756d1 --- /dev/null +++ b/vendor/symfony/http-kernel/HttpCache/SubRequestHandler.php @@ -0,0 +1,91 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\HttpCache; + +use Symfony\Component\HttpFoundation\IpUtils; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpKernel\HttpKernelInterface; + +/** + * @author Nicolas Grekas <p@tchwork.com> + * + * @internal + */ +class SubRequestHandler +{ + public static function handle(HttpKernelInterface $kernel, Request $request, $type, $catch): Response + { + // save global state related to trusted headers and proxies + $trustedProxies = Request::getTrustedProxies(); + $trustedHeaderSet = Request::getTrustedHeaderSet(); + + // remove untrusted values + $remoteAddr = $request->server->get('REMOTE_ADDR'); + if (!IpUtils::checkIp($remoteAddr, $trustedProxies)) { + $trustedHeaders = [ + 'FORWARDED' => $trustedHeaderSet & Request::HEADER_FORWARDED, + 'X_FORWARDED_FOR' => $trustedHeaderSet & Request::HEADER_X_FORWARDED_FOR, + 'X_FORWARDED_HOST' => $trustedHeaderSet & Request::HEADER_X_FORWARDED_HOST, + 'X_FORWARDED_PROTO' => $trustedHeaderSet & Request::HEADER_X_FORWARDED_PROTO, + 'X_FORWARDED_PORT' => $trustedHeaderSet & Request::HEADER_X_FORWARDED_PORT, + ]; + foreach (array_filter($trustedHeaders) as $name => $key) { + $request->headers->remove($name); + $request->server->remove('HTTP_'.$name); + } + } + + // compute trusted values, taking any trusted proxies into account + $trustedIps = []; + $trustedValues = []; + foreach (array_reverse($request->getClientIps()) as $ip) { + $trustedIps[] = $ip; + $trustedValues[] = sprintf('for="%s"', $ip); + } + if ($ip !== $remoteAddr) { + $trustedIps[] = $remoteAddr; + $trustedValues[] = sprintf('for="%s"', $remoteAddr); + } + + // set trusted values, reusing as much as possible the global trusted settings + if (Request::HEADER_FORWARDED & $trustedHeaderSet) { + $trustedValues[0] .= sprintf(';host="%s";proto=%s', $request->getHttpHost(), $request->getScheme()); + $request->headers->set('Forwarded', $v = implode(', ', $trustedValues)); + $request->server->set('HTTP_FORWARDED', $v); + } + if (Request::HEADER_X_FORWARDED_FOR & $trustedHeaderSet) { + $request->headers->set('X-Forwarded-For', $v = implode(', ', $trustedIps)); + $request->server->set('HTTP_X_FORWARDED_FOR', $v); + } elseif (!(Request::HEADER_FORWARDED & $trustedHeaderSet)) { + Request::setTrustedProxies($trustedProxies, $trustedHeaderSet | Request::HEADER_X_FORWARDED_FOR); + $request->headers->set('X-Forwarded-For', $v = implode(', ', $trustedIps)); + $request->server->set('HTTP_X_FORWARDED_FOR', $v); + } + + // fix the client IP address by setting it to 127.0.0.1, + // which is the core responsibility of this method + $request->server->set('REMOTE_ADDR', '127.0.0.1'); + + // ensure 127.0.0.1 is set as trusted proxy + if (!IpUtils::checkIp('127.0.0.1', $trustedProxies)) { + Request::setTrustedProxies(array_merge($trustedProxies, ['127.0.0.1']), Request::getTrustedHeaderSet()); + } + + try { + return $kernel->handle($request, $type, $catch); + } finally { + // restore global state + Request::setTrustedProxies($trustedProxies, $trustedHeaderSet); + } + } +} diff --git a/vendor/symfony/http-kernel/HttpClientKernel.php b/vendor/symfony/http-kernel/HttpClientKernel.php new file mode 100644 index 0000000000000000000000000000000000000000..f60a84eabe2575eb439113ce8be70d09bb10c1bf --- /dev/null +++ b/vendor/symfony/http-kernel/HttpClientKernel.php @@ -0,0 +1,106 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel; + +use Symfony\Component\HttpClient\HttpClient; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpFoundation\ResponseHeaderBag; +use Symfony\Component\Mime\Part\AbstractPart; +use Symfony\Component\Mime\Part\DataPart; +use Symfony\Component\Mime\Part\Multipart\FormDataPart; +use Symfony\Component\Mime\Part\TextPart; +use Symfony\Contracts\HttpClient\HttpClientInterface; + +/** + * An implementation of a Symfony HTTP kernel using a "real" HTTP client. + * + * @author Fabien Potencier <fabien@symfony.com> + */ +final class HttpClientKernel implements HttpKernelInterface +{ + private $client; + + public function __construct(HttpClientInterface $client = null) + { + if (!class_exists(HttpClient::class)) { + throw new \LogicException(sprintf('You cannot use "%s" as the HttpClient component is not installed. Try running "composer require symfony/http-client".', __CLASS__)); + } + + $this->client = $client ?? HttpClient::create(); + } + + public function handle(Request $request, $type = HttpKernelInterface::MASTER_REQUEST, $catch = true) + { + $headers = $this->getHeaders($request); + $body = ''; + if (null !== $part = $this->getBody($request)) { + $headers = array_merge($headers, $part->getPreparedHeaders()->toArray()); + $body = $part->bodyToIterable(); + } + $response = $this->client->request($request->getMethod(), $request->getUri(), [ + 'headers' => $headers, + 'body' => $body, + 'max_redirects' => 0, + ] + $request->attributes->get('http_client_options', [])); + + $response = new Response($response->getContent(!$catch), $response->getStatusCode(), $response->getHeaders(!$catch)); + + $response->headers = new class($response->headers->all()) extends ResponseHeaderBag { + protected function computeCacheControlValue() + { + return $this->getCacheControlHeader(); // preserve the original value + } + }; + + return $response; + } + + private function getBody(Request $request): ?AbstractPart + { + if (\in_array($request->getMethod(), ['GET', 'HEAD'])) { + return null; + } + + if (!class_exists(AbstractPart::class)) { + throw new \LogicException('You cannot pass non-empty bodies as the Mime component is not installed. Try running "composer require symfony/mime".'); + } + + if ($content = $request->getContent()) { + return new TextPart($content, 'utf-8', 'plain', '8bit'); + } + + $fields = $request->request->all(); + foreach ($request->files->all() as $name => $file) { + $fields[$name] = DataPart::fromPath($file->getPathname(), $file->getClientOriginalName(), $file->getClientMimeType()); + } + + return new FormDataPart($fields); + } + + private function getHeaders(Request $request): array + { + $headers = []; + foreach ($request->headers as $key => $value) { + $headers[$key] = $value; + } + $cookies = []; + foreach ($request->cookies->all() as $name => $value) { + $cookies[] = $name.'='.$value; + } + if ($cookies) { + $headers['cookie'] = implode('; ', $cookies); + } + + return $headers; + } +} diff --git a/vendor/symfony/http-kernel/HttpKernel.php b/vendor/symfony/http-kernel/HttpKernel.php index 41f8913bed40c312f1a7946c99bb0f5c1dfaab23..64e931f2bd40d02dd7d521485edc50c94347dbf4 100644 --- a/vendor/symfony/http-kernel/HttpKernel.php +++ b/vendor/symfony/http-kernel/HttpKernel.php @@ -11,25 +11,27 @@ namespace Symfony\Component\HttpKernel; +use Symfony\Component\EventDispatcher\LegacyEventDispatcherProxy; +use Symfony\Component\HttpFoundation\Exception\RequestExceptionInterface; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\RequestStack; +use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\Controller\ArgumentResolver; use Symfony\Component\HttpKernel\Controller\ArgumentResolverInterface; use Symfony\Component\HttpKernel\Controller\ControllerResolverInterface; -use Symfony\Component\HttpKernel\Event\FilterControllerArgumentsEvent; +use Symfony\Component\HttpKernel\Event\ControllerArgumentsEvent; +use Symfony\Component\HttpKernel\Event\ControllerEvent; +use Symfony\Component\HttpKernel\Event\ExceptionEvent; +use Symfony\Component\HttpKernel\Event\FinishRequestEvent; +use Symfony\Component\HttpKernel\Event\RequestEvent; +use Symfony\Component\HttpKernel\Event\ResponseEvent; +use Symfony\Component\HttpKernel\Event\TerminateEvent; +use Symfony\Component\HttpKernel\Event\ViewEvent; use Symfony\Component\HttpKernel\Exception\BadRequestHttpException; -use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; +use Symfony\Component\HttpKernel\Exception\ControllerDoesNotReturnResponseException; use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface; -use Symfony\Component\HttpKernel\Event\FilterControllerEvent; -use Symfony\Component\HttpKernel\Event\FilterResponseEvent; -use Symfony\Component\HttpKernel\Event\FinishRequestEvent; -use Symfony\Component\HttpKernel\Event\GetResponseEvent; -use Symfony\Component\HttpKernel\Event\GetResponseForControllerResultEvent; -use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent; -use Symfony\Component\HttpKernel\Event\PostResponseEvent; -use Symfony\Component\HttpFoundation\Exception\RequestExceptionInterface; -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\RequestStack; -use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\EventDispatcher\EventDispatcherInterface; +use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; +use Symfony\Contracts\EventDispatcher\EventDispatcherInterface; /** * HttpKernel notifies events to convert a Request object to a Response one. @@ -45,15 +47,13 @@ class HttpKernel implements HttpKernelInterface, TerminableInterface public function __construct(EventDispatcherInterface $dispatcher, ControllerResolverInterface $resolver, RequestStack $requestStack = null, ArgumentResolverInterface $argumentResolver = null) { - $this->dispatcher = $dispatcher; + $this->dispatcher = LegacyEventDispatcherProxy::decorate($dispatcher); $this->resolver = $resolver; $this->requestStack = $requestStack ?: new RequestStack(); $this->argumentResolver = $argumentResolver; if (null === $this->argumentResolver) { - @trigger_error(sprintf('As of 3.1 an %s is used to resolve arguments. In 4.0 the $argumentResolver becomes the %s if no other is provided instead of using the $resolver argument.', ArgumentResolverInterface::class, ArgumentResolver::class), E_USER_DEPRECATED); - // fallback in case of deprecations - $this->argumentResolver = $resolver; + $this->argumentResolver = new ArgumentResolver(); } } @@ -85,7 +85,7 @@ class HttpKernel implements HttpKernelInterface, TerminableInterface */ public function terminate(Request $request, Response $response) { - $this->dispatcher->dispatch(KernelEvents::TERMINATE, new PostResponseEvent($this, $request, $response)); + $this->dispatcher->dispatch(new TerminateEvent($this, $request, $response), KernelEvents::TERMINATE); } /** @@ -118,13 +118,13 @@ class HttpKernel implements HttpKernelInterface, TerminableInterface * @throws \LogicException If one of the listener does not behave as expected * @throws NotFoundHttpException When controller cannot be found */ - private function handleRaw(Request $request, $type = self::MASTER_REQUEST) + private function handleRaw(Request $request, int $type = self::MASTER_REQUEST) { $this->requestStack->push($request); // request - $event = new GetResponseEvent($this, $request, $type); - $this->dispatcher->dispatch(KernelEvents::REQUEST, $event); + $event = new RequestEvent($this, $request, $type); + $this->dispatcher->dispatch($event, KernelEvents::REQUEST); if ($event->hasResponse()) { return $this->filterResponse($event->getResponse(), $request, $type); @@ -135,38 +135,37 @@ class HttpKernel implements HttpKernelInterface, TerminableInterface throw new NotFoundHttpException(sprintf('Unable to find the controller for path "%s". The route is wrongly configured.', $request->getPathInfo())); } - $event = new FilterControllerEvent($this, $controller, $request, $type); - $this->dispatcher->dispatch(KernelEvents::CONTROLLER, $event); + $event = new ControllerEvent($this, $controller, $request, $type); + $this->dispatcher->dispatch($event, KernelEvents::CONTROLLER); $controller = $event->getController(); // controller arguments $arguments = $this->argumentResolver->getArguments($request, $controller); - $event = new FilterControllerArgumentsEvent($this, $controller, $arguments, $request, $type); - $this->dispatcher->dispatch(KernelEvents::CONTROLLER_ARGUMENTS, $event); + $event = new ControllerArgumentsEvent($this, $controller, $arguments, $request, $type); + $this->dispatcher->dispatch($event, KernelEvents::CONTROLLER_ARGUMENTS); $controller = $event->getController(); $arguments = $event->getArguments(); // call controller - $response = \call_user_func_array($controller, $arguments); + $response = $controller(...$arguments); // view if (!$response instanceof Response) { - $event = new GetResponseForControllerResultEvent($this, $request, $type, $response); - $this->dispatcher->dispatch(KernelEvents::VIEW, $event); + $event = new ViewEvent($this, $request, $type, $response); + $this->dispatcher->dispatch($event, KernelEvents::VIEW); if ($event->hasResponse()) { $response = $event->getResponse(); - } - - if (!$response instanceof Response) { - $msg = sprintf('The controller must return a response (%s given).', $this->varToString($response)); + } else { + $msg = sprintf('The controller must return a "Symfony\Component\HttpFoundation\Response" object but it returned %s.', $this->varToString($response)); // the user may have forgotten to return something if (null === $response) { $msg .= ' Did you forget to add a return statement somewhere in your controller?'; } - throw new \LogicException($msg); + + throw new ControllerDoesNotReturnResponseException($msg, $controller, __FILE__, __LINE__ - 17); } } @@ -184,11 +183,11 @@ class HttpKernel implements HttpKernelInterface, TerminableInterface * * @throws \RuntimeException if the passed object is not a Response instance */ - private function filterResponse(Response $response, Request $request, $type) + private function filterResponse(Response $response, Request $request, int $type) { - $event = new FilterResponseEvent($this, $request, $type, $response); + $event = new ResponseEvent($this, $request, $type, $response); - $this->dispatcher->dispatch(KernelEvents::RESPONSE, $event); + $this->dispatcher->dispatch($event, KernelEvents::RESPONSE); $this->finishRequest($request, $type); @@ -201,13 +200,10 @@ class HttpKernel implements HttpKernelInterface, TerminableInterface * Note that the order of the operations is important here, otherwise * operations such as {@link RequestStack::getParentRequest()} can lead to * weird results. - * - * @param Request $request - * @param int $type */ - private function finishRequest(Request $request, $type) + private function finishRequest(Request $request, int $type) { - $this->dispatcher->dispatch(KernelEvents::FINISH_REQUEST, new FinishRequestEvent($this, $request, $type)); + $this->dispatcher->dispatch(new FinishRequestEvent($this, $request, $type), KernelEvents::FINISH_REQUEST); $this->requestStack->pop(); } @@ -216,16 +212,14 @@ class HttpKernel implements HttpKernelInterface, TerminableInterface * * @param \Exception $e An \Exception instance * @param Request $request A Request instance - * @param int $type The type of the request - * - * @return Response A Response instance + * @param int $type The type of the request (one of HttpKernelInterface::MASTER_REQUEST or HttpKernelInterface::SUB_REQUEST) * * @throws \Exception */ - private function handleException(\Exception $e, $request, $type) + private function handleException(\Exception $e, Request $request, int $type): Response { - $event = new GetResponseForExceptionEvent($this, $request, $type, $e); - $this->dispatcher->dispatch(KernelEvents::EXCEPTION, $event); + $event = new ExceptionEvent($this, $request, $type, $e); + $this->dispatcher->dispatch($event, KernelEvents::EXCEPTION); // a listener might have replaced the exception $e = $event->getException(); @@ -239,13 +233,7 @@ class HttpKernel implements HttpKernelInterface, TerminableInterface $response = $event->getResponse(); // the developer asked for a specific status code - if ($response->headers->has('X-Status-Code')) { - @trigger_error(sprintf('Using the X-Status-Code header is deprecated since Symfony 3.3 and will be removed in 4.0. Use %s::allowCustomResponseCode() instead.', GetResponseForExceptionEvent::class), E_USER_DEPRECATED); - - $response->setStatusCode($response->headers->get('X-Status-Code')); - - $response->headers->remove('X-Status-Code'); - } elseif (!$event->isAllowingCustomResponseCode() && !$response->isClientError() && !$response->isServerError() && !$response->isRedirect()) { + if (!$event->isAllowingCustomResponseCode() && !$response->isClientError() && !$response->isServerError() && !$response->isRedirect()) { // ensure that we actually have an error response if ($e instanceof HttpExceptionInterface) { // keep the HTTP status code and headers @@ -263,23 +251,26 @@ class HttpKernel implements HttpKernelInterface, TerminableInterface } } - private function varToString($var) + /** + * Returns a human-readable string for the specified variable. + */ + private function varToString($var): string { - if (is_object($var)) { - return sprintf('Object(%s)', get_class($var)); + if (\is_object($var)) { + return sprintf('an object of type %s', \get_class($var)); } - if (is_array($var)) { - $a = array(); + if (\is_array($var)) { + $a = []; foreach ($var as $k => $v) { - $a[] = sprintf('%s => %s', $k, $this->varToString($v)); + $a[] = sprintf('%s => ...', $k); } - return sprintf('Array(%s)', implode(', ', $a)); + return sprintf('an array ([%s])', mb_substr(implode(', ', $a), 0, 255)); } - if (is_resource($var)) { - return sprintf('Resource(%s)', get_resource_type($var)); + if (\is_resource($var)) { + return sprintf('a resource (%s)', get_resource_type($var)); } if (null === $var) { @@ -287,11 +278,19 @@ class HttpKernel implements HttpKernelInterface, TerminableInterface } if (false === $var) { - return 'false'; + return 'a boolean value (false)'; } if (true === $var) { - return 'true'; + return 'a boolean value (true)'; + } + + if (\is_string($var)) { + return sprintf('a string ("%s%s")', mb_substr($var, 0, 255), mb_strlen($var) > 255 ? '...' : ''); + } + + if (is_numeric($var)) { + return sprintf('a number (%s)', (string) $var); } return (string) $var; diff --git a/vendor/symfony/http-kernel/HttpKernelBrowser.php b/vendor/symfony/http-kernel/HttpKernelBrowser.php new file mode 100644 index 0000000000000000000000000000000000000000..e413634755da56e65e6606f5c1ccc398984a6c74 --- /dev/null +++ b/vendor/symfony/http-kernel/HttpKernelBrowser.php @@ -0,0 +1,27 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel; + +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; + +/** + * Client simulates a browser and makes requests to an HttpKernel instance. + * + * @author Fabien Potencier <fabien@symfony.com> + * + * @method Request getRequest() A Request instance + * @method Response getResponse() A Response instance + */ +class HttpKernelBrowser extends Client +{ +} diff --git a/vendor/symfony/http-kernel/Kernel.php b/vendor/symfony/http-kernel/Kernel.php index eb2364e469ea794866a97164c1d0e73d5beb2e1d..7d18d221d5c185e24170febe06f9bb4a139f6e04 100644 --- a/vendor/symfony/http-kernel/Kernel.php +++ b/vendor/symfony/http-kernel/Kernel.php @@ -13,36 +13,38 @@ namespace Symfony\Component\HttpKernel; use Symfony\Bridge\ProxyManager\LazyProxy\Instantiator\RuntimeInstantiator; use Symfony\Bridge\ProxyManager\LazyProxy\PhpDumper\ProxyDumper; +use Symfony\Component\Config\ConfigCache; +use Symfony\Component\Config\Loader\DelegatingLoader; +use Symfony\Component\Config\Loader\LoaderResolver; +use Symfony\Component\Debug\DebugClassLoader; use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; use Symfony\Component\DependencyInjection\Compiler\PassConfig; -use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\Dumper\PhpDumper; -use Symfony\Component\DependencyInjection\Loader\XmlFileLoader; -use Symfony\Component\DependencyInjection\Loader\YamlFileLoader; +use Symfony\Component\DependencyInjection\Loader\ClosureLoader; +use Symfony\Component\DependencyInjection\Loader\DirectoryLoader; +use Symfony\Component\DependencyInjection\Loader\GlobFileLoader; use Symfony\Component\DependencyInjection\Loader\IniFileLoader; use Symfony\Component\DependencyInjection\Loader\PhpFileLoader; -use Symfony\Component\DependencyInjection\Loader\DirectoryLoader; -use Symfony\Component\DependencyInjection\Loader\ClosureLoader; +use Symfony\Component\DependencyInjection\Loader\XmlFileLoader; +use Symfony\Component\DependencyInjection\Loader\YamlFileLoader; use Symfony\Component\Filesystem\Filesystem; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\Bundle\BundleInterface; -use Symfony\Component\HttpKernel\Config\EnvParametersResource; use Symfony\Component\HttpKernel\Config\FileLocator; -use Symfony\Component\HttpKernel\DependencyInjection\MergeExtensionConfigurationPass; use Symfony\Component\HttpKernel\DependencyInjection\AddAnnotatedClassesToCachePass; -use Symfony\Component\Config\Loader\GlobFileLoader; -use Symfony\Component\Config\Loader\LoaderResolver; -use Symfony\Component\Config\Loader\DelegatingLoader; -use Symfony\Component\Config\ConfigCache; -use Symfony\Component\ClassLoader\ClassCollectionLoader; +use Symfony\Component\HttpKernel\DependencyInjection\MergeExtensionConfigurationPass; /** * The Kernel is the heart of the Symfony system. * * It manages an environment made of bundles. * + * Environment names must always start with a letter and + * they must only contain letters and numbers. + * * @author Fabien Potencier <fabien@symfony.com> */ abstract class Kernel implements KernelInterface, RebootableInterface, TerminableInterface @@ -50,55 +52,47 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl /** * @var BundleInterface[] */ - protected $bundles = array(); + protected $bundles = []; - protected $bundleMap; protected $container; + /** + * @deprecated since Symfony 4.2 + */ protected $rootDir; protected $environment; protected $debug; protected $booted = false; + /** + * @deprecated since Symfony 4.2 + */ protected $name; protected $startTime; - protected $loadClassCache; private $projectDir; private $warmupDir; private $requestStackSize = 0; private $resetServices = false; - const VERSION = '3.4.4'; - const VERSION_ID = 30404; - const MAJOR_VERSION = 3; - const MINOR_VERSION = 4; - const RELEASE_VERSION = 4; + const VERSION = '4.3.5'; + const VERSION_ID = 40305; + const MAJOR_VERSION = 4; + const MINOR_VERSION = 3; + const RELEASE_VERSION = 5; const EXTRA_VERSION = ''; - const END_OF_MAINTENANCE = '11/2020'; - const END_OF_LIFE = '11/2021'; + const END_OF_MAINTENANCE = '01/2020'; + const END_OF_LIFE = '07/2020'; - /** - * @param string $environment The environment - * @param bool $debug Whether to enable debugging or not - */ - public function __construct($environment, $debug) + public function __construct(string $environment, bool $debug) { $this->environment = $environment; - $this->debug = (bool) $debug; - $this->rootDir = $this->getRootDir(); - $this->name = $this->getName(); - - if ($this->debug) { - $this->startTime = microtime(true); - } + $this->debug = $debug; + $this->rootDir = $this->getRootDir(false); + $this->name = $this->getName(false); } public function __clone() { - if ($this->debug) { - $this->startTime = microtime(true); - } - $this->booted = false; $this->container = null; $this->requestStackSize = 0; @@ -106,7 +100,7 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl } /** - * Boots the current kernel. + * {@inheritdoc} */ public function boot() { @@ -116,20 +110,22 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl $this->container->get('services_resetter')->reset(); } $this->resetServices = false; + if ($this->debug) { + $this->startTime = microtime(true); + } } return; } + if ($this->debug) { + $this->startTime = microtime(true); + } if ($this->debug && !isset($_ENV['SHELL_VERBOSITY']) && !isset($_SERVER['SHELL_VERBOSITY'])) { putenv('SHELL_VERBOSITY=3'); $_ENV['SHELL_VERBOSITY'] = 3; $_SERVER['SHELL_VERBOSITY'] = 3; } - if ($this->loadClassCache) { - $this->doLoadClassCache($this->loadClassCache[0], $this->loadClassCache[1]); - } - // init bundles $this->initializeBundles(); @@ -208,7 +204,7 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl /** * Gets a HTTP kernel from the container. * - * @return HttpKernel + * @return HttpKernelInterface */ protected function getHttpKernel() { @@ -226,26 +222,16 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl /** * {@inheritdoc} */ - public function getBundle($name, $first = true/*, $noDeprecation = false */) + public function getBundle($name) { - $noDeprecation = false; - if (func_num_args() >= 3) { - $noDeprecation = func_get_arg(2); - } + if (!isset($this->bundles[$name])) { + $class = \get_class($this); + $class = 'c' === $class[0] && 0 === strpos($class, "class@anonymous\0") ? get_parent_class($class).'@anonymous' : $class; - if (!$first && !$noDeprecation) { - @trigger_error(sprintf('Passing "false" as the second argument to %s() is deprecated as of 3.4 and will be removed in 4.0.', __METHOD__), E_USER_DEPRECATED); + throw new \InvalidArgumentException(sprintf('Bundle "%s" does not exist or it is not enabled. Maybe you forgot to add it in the registerBundles() method of your %s.php file?', $name, $class)); } - if (!isset($this->bundleMap[$name])) { - throw new \InvalidArgumentException(sprintf('Bundle "%s" does not exist or it is not enabled. Maybe you forgot to add it in the registerBundles() method of your %s.php file?', $name, get_class($this))); - } - - if (true === $first) { - return $this->bundleMap[$name][0]; - } - - return $this->bundleMap[$name]; + return $this->bundles[$name]; } /** @@ -271,36 +257,21 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl $isResource = 0 === strpos($path, 'Resources') && null !== $dir; $overridePath = substr($path, 9); - $resourceBundle = null; - $bundles = $this->getBundle($bundleName, false, true); - $files = array(); - - foreach ($bundles as $bundle) { - if ($isResource && file_exists($file = $dir.'/'.$bundle->getName().$overridePath)) { - if (null !== $resourceBundle) { - throw new \RuntimeException(sprintf('"%s" resource is hidden by a resource from the "%s" derived bundle. Create a "%s" file to override the bundle resource.', - $file, - $resourceBundle, - $dir.'/'.$bundles[0]->getName().$overridePath - )); - } + $bundle = $this->getBundle($bundleName); + $files = []; - if ($first) { - return $file; - } - $files[] = $file; - } + if ($isResource && file_exists($file = $dir.'/'.$bundle->getName().$overridePath)) { + $files[] = $file; + } - if (file_exists($file = $bundle->getPath().'/'.$path)) { - if ($first && !$isResource) { - return $file; - } - $files[] = $file; - $resourceBundle = $bundle->getName(); + if (file_exists($file = $bundle->getPath().'/'.$path)) { + if ($first && !$isResource) { + return $file; } + $files[] = $file; } - if (count($files) > 0) { + if (\count($files) > 0) { return $first && $isResource ? $files[0] : $files; } @@ -309,9 +280,15 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl /** * {@inheritdoc} + * + * @deprecated since Symfony 4.2 */ - public function getName() + public function getName(/* $triggerDeprecation = true */) { + if (0 === \func_num_args() || func_get_arg(0)) { + @trigger_error(sprintf('The "%s()" method is deprecated since Symfony 4.2.', __METHOD__), E_USER_DEPRECATED); + } + if (null === $this->name) { $this->name = preg_replace('/[^a-zA-Z0-9_]+/', '', basename($this->rootDir)); if (ctype_digit($this->name[0])) { @@ -340,12 +317,18 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl /** * {@inheritdoc} + * + * @deprecated since Symfony 4.2, use getProjectDir() instead */ - public function getRootDir() + public function getRootDir(/* $triggerDeprecation = true */) { + if (0 === \func_num_args() || func_get_arg(0)) { + @trigger_error(sprintf('The "%s()" method is deprecated since Symfony 4.2, use getProjectDir() instead.', __METHOD__), E_USER_DEPRECATED); + } + if (null === $this->rootDir) { $r = new \ReflectionObject($this); - $this->rootDir = dirname($r->getFileName()); + $this->rootDir = \dirname($r->getFileName()); } return $this->rootDir; @@ -360,12 +343,17 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl { if (null === $this->projectDir) { $r = new \ReflectionObject($this); - $dir = $rootDir = dirname($r->getFileName()); + + if (!file_exists($dir = $r->getFileName())) { + throw new \LogicException(sprintf('Cannot auto-detect project dir for kernel of class "%s".', $r->name)); + } + + $dir = $rootDir = \dirname($dir); while (!file_exists($dir.'/composer.json')) { - if ($dir === dirname($dir)) { + if ($dir === \dirname($dir)) { return $this->projectDir = $rootDir; } - $dir = dirname($dir); + $dir = \dirname($dir); } $this->projectDir = $dir; } @@ -381,43 +369,6 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl return $this->container; } - /** - * Loads the PHP class cache. - * - * This methods only registers the fact that you want to load the cache classes. - * The cache will actually only be loaded when the Kernel is booted. - * - * That optimization is mainly useful when using the HttpCache class in which - * case the class cache is not loaded if the Response is in the cache. - * - * @param string $name The cache name prefix - * @param string $extension File extension of the resulting file - * - * @deprecated since version 3.3, to be removed in 4.0. The class cache is not needed anymore when using PHP 7.0. - */ - public function loadClassCache($name = 'classes', $extension = '.php') - { - if (\PHP_VERSION_ID >= 70000) { - @trigger_error(__METHOD__.'() is deprecated since Symfony 3.3, to be removed in 4.0.', E_USER_DEPRECATED); - } - - $this->loadClassCache = array($name, $extension); - } - - /** - * @internal - * - * @deprecated since version 3.3, to be removed in 4.0. - */ - public function setClassCache(array $classes) - { - if (\PHP_VERSION_ID >= 70000) { - @trigger_error(__METHOD__.'() is deprecated since Symfony 3.3, to be removed in 4.0.', E_USER_DEPRECATED); - } - - file_put_contents(($this->warmupDir ?: $this->getCacheDir()).'/classes.map', sprintf('<?php return %s;', var_export($classes, true))); - } - /** * @internal */ @@ -431,7 +382,7 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl */ public function getStartTime() { - return $this->debug ? $this->startTime : -INF; + return $this->debug && null !== $this->startTime ? $this->startTime : -INF; } /** @@ -439,7 +390,7 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl */ public function getCacheDir() { - return $this->rootDir.'/cache/'.$this->environment; + return $this->getProjectDir().'/var/cache/'.$this->environment; } /** @@ -447,7 +398,7 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl */ public function getLogDir() { - return $this->rootDir.'/logs'; + return $this->getProjectDir().'/var/log'; } /** @@ -459,83 +410,28 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl } /** - * @deprecated since version 3.3, to be removed in 4.0. + * Gets the patterns defining the classes to parse and cache for annotations. */ - protected function doLoadClassCache($name, $extension) + public function getAnnotatedClassesToCompile(): array { - if (\PHP_VERSION_ID >= 70000) { - @trigger_error(__METHOD__.'() is deprecated since Symfony 3.3, to be removed in 4.0.', E_USER_DEPRECATED); - } - $cacheDir = $this->warmupDir ?: $this->getCacheDir(); - - if (!$this->booted && is_file($cacheDir.'/classes.map')) { - ClassCollectionLoader::load(include($cacheDir.'/classes.map'), $cacheDir, $name, $this->debug, false, $extension); - } + return []; } /** - * Initializes the data structures related to the bundle management. - * - * - the bundles property maps a bundle name to the bundle instance, - * - the bundleMap property maps a bundle name to the bundle inheritance hierarchy (most derived bundle first). + * Initializes bundles. * * @throws \LogicException if two bundles share a common name - * @throws \LogicException if a bundle tries to extend a non-registered bundle - * @throws \LogicException if a bundle tries to extend itself - * @throws \LogicException if two bundles extend the same ancestor */ protected function initializeBundles() { // init bundles - $this->bundles = array(); - $topMostBundles = array(); - $directChildren = array(); - + $this->bundles = []; foreach ($this->registerBundles() as $bundle) { $name = $bundle->getName(); if (isset($this->bundles[$name])) { throw new \LogicException(sprintf('Trying to register two bundles with the same name "%s"', $name)); } $this->bundles[$name] = $bundle; - - if ($parentName = $bundle->getParent()) { - @trigger_error('Bundle inheritance is deprecated as of 3.4 and will be removed in 4.0.', E_USER_DEPRECATED); - - if (isset($directChildren[$parentName])) { - throw new \LogicException(sprintf('Bundle "%s" is directly extended by two bundles "%s" and "%s".', $parentName, $name, $directChildren[$parentName])); - } - if ($parentName == $name) { - throw new \LogicException(sprintf('Bundle "%s" can not extend itself.', $name)); - } - $directChildren[$parentName] = $name; - } else { - $topMostBundles[$name] = $bundle; - } - } - - // look for orphans - if (!empty($directChildren) && count($diff = array_diff_key($directChildren, $this->bundles))) { - $diff = array_keys($diff); - - throw new \LogicException(sprintf('Bundle "%s" extends bundle "%s", which is not registered.', $directChildren[$diff[0]], $diff[0])); - } - - // inheritance - $this->bundleMap = array(); - foreach ($topMostBundles as $name => $bundle) { - $bundleMap = array($bundle); - $hierarchy = array($name); - - while (isset($directChildren[$name])) { - $name = $directChildren[$name]; - array_unshift($bundleMap, $this->bundles[$name]); - $hierarchy[] = $name; - } - - foreach ($hierarchy as $hierarchyBundle) { - $this->bundleMap[$hierarchyBundle] = $bundleMap; - array_pop($bundleMap); - } } } @@ -551,11 +447,21 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl /** * Gets the container class. * + * @throws \InvalidArgumentException If the generated classname is invalid + * * @return string The container class */ protected function getContainerClass() { - return $this->name.ucfirst($this->environment).($this->debug ? 'Debug' : '').'ProjectContainer'; + $class = \get_class($this); + $class = 'c' === $class[0] && 0 === strpos($class, "class@anonymous\0") ? get_parent_class($class).str_replace('.', '_', ContainerBuilder::hash($class)) : $class; + $class = $this->name.str_replace('\\', '_', $class).ucfirst($this->environment).($this->debug ? 'Debug' : '').'Container'; + + if (!preg_match('/^[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*$/', $class)) { + throw new \InvalidArgumentException(sprintf('The environment "%s" contains invalid characters, it can only contain characters allowed in PHP class names.', $this->environment)); + } + + return $class; } /** @@ -587,13 +493,12 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl $errorLevel = error_reporting(\E_ALL ^ \E_WARNING); $fresh = $oldContainer = false; try { - if (\is_object($this->container = include $cache->getPath())) { + if (file_exists($cache->getPath()) && \is_object($this->container = include $cache->getPath())) { $this->container->set('kernel', $this); $oldContainer = $this->container; $fresh = true; } } catch (\Throwable $e) { - } catch (\Exception $e) { } finally { error_reporting($errorLevel); } @@ -603,10 +508,9 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl return; } - if ($this->debug) { - $collectedLogs = array(); - $previousHandler = defined('PHPUNIT_COMPOSER_INSTALL'); - $previousHandler = $previousHandler ?: set_error_handler(function ($type, $message, $file, $line) use (&$collectedLogs, &$previousHandler) { + if ($collectDeprecations = $this->debug && !\defined('PHPUNIT_COMPOSER_INSTALL')) { + $collectedLogs = []; + $previousHandler = set_error_handler(function ($type, $message, $file, $line) use (&$collectedLogs, &$previousHandler) { if (E_USER_DEPRECATED !== $type && E_DEPRECATED !== $type) { return $previousHandler ? $previousHandler($type, $message, $file, $line) : false; } @@ -614,26 +518,35 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl if (isset($collectedLogs[$message])) { ++$collectedLogs[$message]['count']; - return; + return null; } - $backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 3); + $backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 5); // Clean the trace by removing first frames added by the error handler itself. for ($i = 0; isset($backtrace[$i]); ++$i) { if (isset($backtrace[$i]['file'], $backtrace[$i]['line']) && $backtrace[$i]['line'] === $line && $backtrace[$i]['file'] === $file) { - $backtrace = array_slice($backtrace, 1 + $i); + $backtrace = \array_slice($backtrace, 1 + $i); + break; + } + } + // Remove frames added by DebugClassLoader. + for ($i = \count($backtrace) - 2; 0 < $i; --$i) { + if (DebugClassLoader::class === ($backtrace[$i]['class'] ?? null)) { + $backtrace = [$backtrace[$i + 1]]; break; } } - $collectedLogs[$message] = array( + $collectedLogs[$message] = [ 'type' => $type, 'message' => $message, 'file' => $file, 'line' => $line, - 'trace' => $backtrace, + 'trace' => [$backtrace[0]], 'count' => 1, - ); + ]; + + return null; }); } @@ -642,7 +555,7 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl $container = $this->buildContainer(); $container->compile(); } finally { - if ($this->debug && true !== $previousHandler) { + if ($collectDeprecations) { restore_error_handler(); file_put_contents($cacheDir.'/'.$class.'Deprecations.log', serialize(array_values($collectedLogs))); @@ -650,29 +563,30 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl } } - if (null === $oldContainer) { + if (null === $oldContainer && file_exists($cache->getPath())) { $errorLevel = error_reporting(\E_ALL ^ \E_WARNING); try { $oldContainer = include $cache->getPath(); } catch (\Throwable $e) { - } catch (\Exception $e) { } finally { error_reporting($errorLevel); } } - $oldContainer = is_object($oldContainer) ? new \ReflectionClass($oldContainer) : false; + $oldContainer = \is_object($oldContainer) ? new \ReflectionClass($oldContainer) : false; $this->dumpContainer($cache, $container, $class, $this->getContainerBaseClass()); $this->container = require $cache->getPath(); $this->container->set('kernel', $this); - if ($oldContainer && get_class($this->container) !== $oldContainer->name) { + if ($oldContainer && \get_class($this->container) !== $oldContainer->name) { // Because concurrent requests might still be using them, // old container files are not removed immediately, // but on a next dump of the container. - $oldContainerDir = dirname($oldContainer->getFileName()); - foreach (glob(dirname($oldContainerDir).'/*.legacy') as $legacyContainer) { - if ($oldContainerDir.'.legacy' !== $legacyContainer && @unlink($legacyContainer)) { + static $legacyContainers = []; + $oldContainerDir = \dirname($oldContainer->getFileName()); + $legacyContainers[$oldContainerDir.'.legacy'] = true; + foreach (glob(\dirname($oldContainerDir).\DIRECTORY_SEPARATOR.'*.legacy', GLOB_NOSORT) as $legacyContainer) { + if (!isset($legacyContainers[$legacyContainer]) && @unlink($legacyContainer)) { (new Filesystem())->remove(substr($legacyContainer, 0, -7)); } } @@ -692,60 +606,36 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl */ protected function getKernelParameters() { - $bundles = array(); - $bundlesMetadata = array(); + $bundles = []; + $bundlesMetadata = []; foreach ($this->bundles as $name => $bundle) { - $bundles[$name] = get_class($bundle); - $bundlesMetadata[$name] = array( - 'parent' => $bundle->getParent(), + $bundles[$name] = \get_class($bundle); + $bundlesMetadata[$name] = [ 'path' => $bundle->getPath(), 'namespace' => $bundle->getNamespace(), - ); - } - - return array_merge( - array( - 'kernel.root_dir' => realpath($this->rootDir) ?: $this->rootDir, - 'kernel.project_dir' => realpath($this->getProjectDir()) ?: $this->getProjectDir(), - 'kernel.environment' => $this->environment, - 'kernel.debug' => $this->debug, - 'kernel.name' => $this->name, - 'kernel.cache_dir' => realpath($cacheDir = $this->warmupDir ?: $this->getCacheDir()) ?: $cacheDir, - 'kernel.logs_dir' => realpath($this->getLogDir()) ?: $this->getLogDir(), - 'kernel.bundles' => $bundles, - 'kernel.bundles_metadata' => $bundlesMetadata, - 'kernel.charset' => $this->getCharset(), - 'kernel.container_class' => $this->getContainerClass(), - ), - $this->getEnvParameters(false) - ); - } - - /** - * Gets the environment parameters. - * - * Only the parameters starting with "SYMFONY__" are considered. - * - * @return array An array of parameters - * - * @deprecated since version 3.3, to be removed in 4.0 - */ - protected function getEnvParameters() - { - if (0 === func_num_args() || func_get_arg(0)) { - @trigger_error(sprintf('The %s() method is deprecated as of 3.3 and will be removed in 4.0. Use the %%env()%% syntax to get the value of any environment variable from configuration files instead.', __METHOD__), E_USER_DEPRECATED); - } - - $parameters = array(); - foreach ($_SERVER as $key => $value) { - if (0 === strpos($key, 'SYMFONY__')) { - @trigger_error(sprintf('The support of special environment variables that start with SYMFONY__ (such as "%s") is deprecated as of 3.3 and will be removed in 4.0. Use the %%env()%% syntax instead to get the value of environment variables in configuration files.', $key), E_USER_DEPRECATED); - $parameters[strtolower(str_replace('__', '.', substr($key, 9)))] = $value; - } - } - - return $parameters; + ]; + } + + return [ + /* + * @deprecated since Symfony 4.2, use kernel.project_dir instead + */ + 'kernel.root_dir' => realpath($this->rootDir) ?: $this->rootDir, + 'kernel.project_dir' => realpath($this->getProjectDir()) ?: $this->getProjectDir(), + 'kernel.environment' => $this->environment, + 'kernel.debug' => $this->debug, + /* + * @deprecated since Symfony 4.2 + */ + 'kernel.name' => $this->name, + 'kernel.cache_dir' => realpath($cacheDir = $this->warmupDir ?: $this->getCacheDir()) ?: $cacheDir, + 'kernel.logs_dir' => realpath($this->getLogDir()) ?: $this->getLogDir(), + 'kernel.bundles' => $bundles, + 'kernel.bundles_metadata' => $bundlesMetadata, + 'kernel.charset' => $this->getCharset(), + 'kernel.container_class' => $this->getContainerClass(), + ]; } /** @@ -757,7 +647,7 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl */ protected function buildContainer() { - foreach (array('cache' => $this->warmupDir ?: $this->getCacheDir(), 'logs' => $this->getLogDir()) as $name => $dir) { + foreach (['cache' => $this->warmupDir ?: $this->getCacheDir(), 'logs' => $this->getLogDir()] as $name => $dir) { if (!is_dir($dir)) { if (false === @mkdir($dir, 0777, true) && !is_dir($dir)) { throw new \RuntimeException(sprintf("Unable to create the %s directory (%s)\n", $name, $dir)); @@ -776,7 +666,6 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl } $container->addCompilerPass(new AddAnnotatedClassesToCachePass($this)); - $container->addResource(new EnvParametersResource('SYMFONY__')); return $container; } @@ -786,11 +675,10 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl */ protected function prepareContainer(ContainerBuilder $container) { - $extensions = array(); + $extensions = []; foreach ($this->bundles as $bundle) { if ($extension = $bundle->getContainerExtension()) { $container->registerExtension($extension); - $extensions[] = $extension->getAlias(); } if ($this->debug) { @@ -804,6 +692,10 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl $this->build($container); + foreach ($container->getExtensions() as $extension) { + $extensions[] = $extension->getAlias(); + } + // ensure these extensions are implicitly loaded $container->getCompilerPassConfig()->setMergePass(new MergeExtensionConfigurationPass($extensions)); } @@ -842,27 +734,30 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl $dumper = new PhpDumper($container); if (class_exists('ProxyManager\Configuration') && class_exists('Symfony\Bridge\ProxyManager\LazyProxy\PhpDumper\ProxyDumper')) { - $dumper->setProxyDumper(new ProxyDumper(substr(hash('sha256', $cache->getPath()), 0, 7))); + $dumper->setProxyDumper(new ProxyDumper()); } - $content = $dumper->dump(array( + $content = $dumper->dump([ 'class' => $class, 'base_class' => $baseClass, 'file' => $cache->getPath(), 'as_files' => true, 'debug' => $this->debug, - 'inline_class_loader_parameter' => \PHP_VERSION_ID >= 70000 && !$this->loadClassCache && !class_exists(ClassCollectionLoader::class, false) ? 'container.dumper.inline_class_loader' : null, - )); + 'build_time' => $container->hasParameter('kernel.container_build_time') ? $container->getParameter('kernel.container_build_time') : time(), + ]); $rootCode = array_pop($content); - $dir = dirname($cache->getPath()).'/'; + $dir = \dirname($cache->getPath()).'/'; $fs = new Filesystem(); foreach ($content as $file => $code) { $fs->dumpFile($dir.$file, $code); @chmod($dir.$file, 0666 & ~umask()); } - @unlink(dirname($dir.$file).'.legacy'); + $legacyFile = \dirname($dir.$file).'.legacy'; + if (file_exists($legacyFile)) { + @unlink($legacyFile); + } $cache->write($rootCode, $container->getResources()); } @@ -875,15 +770,15 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl protected function getContainerLoader(ContainerInterface $container) { $locator = new FileLocator($this); - $resolver = new LoaderResolver(array( + $resolver = new LoaderResolver([ new XmlFileLoader($container, $locator), new YamlFileLoader($container, $locator), new IniFileLoader($container, $locator), new PhpFileLoader($container, $locator), - new GlobFileLoader($locator), + new GlobFileLoader($container, $locator), new DirectoryLoader($container, $locator), new ClosureLoader($container), - )); + ]); return new DelegatingLoader($resolver); } @@ -900,7 +795,7 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl */ public static function stripComments($source) { - if (!function_exists('token_get_all')) { + if (!\function_exists('token_get_all')) { return $source; } @@ -927,8 +822,8 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl } // replace multiple new lines with a single newline - $rawChunk .= preg_replace(array('/\n{2,}/S'), "\n", $token[1]); - } elseif (in_array($token[0], array(T_COMMENT, T_DOC_COMMENT))) { + $rawChunk .= preg_replace(['/\n{2,}/S'], "\n", $token[1]); + } elseif (\in_array($token[0], [T_COMMENT, T_DOC_COMMENT])) { $ignoreSpace = true; } else { $rawChunk .= $token[1]; @@ -942,28 +837,54 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl $output .= $rawChunk; - if (\PHP_VERSION_ID >= 70000) { - // PHP 7 memory manager will not release after token_get_all(), see https://bugs.php.net/70098 - unset($tokens, $rawChunk); - gc_mem_caches(); - } + unset($tokens, $rawChunk); + gc_mem_caches(); return $output; } + /** + * @deprecated since Symfony 4.3 + */ public function serialize() { - return serialize(array($this->environment, $this->debug)); + @trigger_error(sprintf('The "%s" method is deprecated since Symfony 4.3.', __METHOD__), E_USER_DEPRECATED); + + return serialize([$this->environment, $this->debug]); } + /** + * @deprecated since Symfony 4.3 + */ public function unserialize($data) { - if (\PHP_VERSION_ID >= 70000) { - list($environment, $debug) = unserialize($data, array('allowed_classes' => false)); - } else { - list($environment, $debug) = unserialize($data); - } + @trigger_error(sprintf('The "%s" method is deprecated since Symfony 4.3.', __METHOD__), E_USER_DEPRECATED); + list($environment, $debug) = unserialize($data, ['allowed_classes' => false]); $this->__construct($environment, $debug); } + + public function __sleep() + { + if (__CLASS__ !== $c = (new \ReflectionMethod($this, 'serialize'))->getDeclaringClass()->name) { + @trigger_error(sprintf('Implementing the "%s::serialize()" method is deprecated since Symfony 4.3.', $c), E_USER_DEPRECATED); + $this->serialized = $this->serialize(); + + return ['serialized']; + } + + return ['environment', 'debug']; + } + + public function __wakeup() + { + if (__CLASS__ !== $c = (new \ReflectionMethod($this, 'serialize'))->getDeclaringClass()->name) { + @trigger_error(sprintf('Implementing the "%s::serialize()" method is deprecated since Symfony 4.3.', $c), E_USER_DEPRECATED); + $this->unserialize($this->serialized); + unset($this->serialized); + + return; + } + $this->__construct($this->environment, $this->debug); + } } diff --git a/vendor/symfony/http-kernel/KernelEvents.php b/vendor/symfony/http-kernel/KernelEvents.php index 6743763258597ed2b84ca53b7fbf286f51ca2c49..682561c32496605ddc171c5aaf74c6d28a94c181 100644 --- a/vendor/symfony/http-kernel/KernelEvents.php +++ b/vendor/symfony/http-kernel/KernelEvents.php @@ -25,7 +25,7 @@ final class KernelEvents * This event allows you to create a response for a request before any * other code in the framework is executed. * - * @Event("Symfony\Component\HttpKernel\Event\GetResponseEvent") + * @Event("Symfony\Component\HttpKernel\Event\RequestEvent") */ const REQUEST = 'kernel.request'; @@ -35,7 +35,7 @@ final class KernelEvents * This event allows you to create a response for a thrown exception or * to modify the thrown exception. * - * @Event("Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent") + * @Event("Symfony\Component\HttpKernel\Event\ExceptionEvent") */ const EXCEPTION = 'kernel.exception'; @@ -46,7 +46,7 @@ final class KernelEvents * This event allows you to create a response for the return value of the * controller. * - * @Event("Symfony\Component\HttpKernel\Event\GetResponseForControllerResultEvent") + * @Event("Symfony\Component\HttpKernel\Event\ViewEvent") */ const VIEW = 'kernel.view'; @@ -57,7 +57,7 @@ final class KernelEvents * This event allows you to change the controller that will handle the * request. * - * @Event("Symfony\Component\HttpKernel\Event\FilterControllerEvent") + * @Event("Symfony\Component\HttpKernel\Event\ControllerEvent") */ const CONTROLLER = 'kernel.controller'; @@ -67,7 +67,7 @@ final class KernelEvents * This event allows you to change the arguments that will be passed to * the controller. * - * @Event("Symfony\Component\HttpKernel\Event\FilterControllerArgumentsEvent") + * @Event("Symfony\Component\HttpKernel\Event\ControllerArgumentsEvent") */ const CONTROLLER_ARGUMENTS = 'kernel.controller_arguments'; @@ -78,7 +78,7 @@ final class KernelEvents * This event allows you to modify or replace the response that will be * replied. * - * @Event("Symfony\Component\HttpKernel\Event\FilterResponseEvent") + * @Event("Symfony\Component\HttpKernel\Event\ResponseEvent") */ const RESPONSE = 'kernel.response'; @@ -87,7 +87,7 @@ final class KernelEvents * * This event allows you to run expensive post-response jobs. * - * @Event("Symfony\Component\HttpKernel\Event\PostResponseEvent") + * @Event("Symfony\Component\HttpKernel\Event\TerminateEvent") */ const TERMINATE = 'kernel.terminate'; diff --git a/vendor/symfony/http-kernel/KernelInterface.php b/vendor/symfony/http-kernel/KernelInterface.php index b341e3e9fcda93f702507af3aaf961ab30c12b74..f9089dc61e8251bb324596fb60cdb06007080571 100644 --- a/vendor/symfony/http-kernel/KernelInterface.php +++ b/vendor/symfony/http-kernel/KernelInterface.php @@ -11,23 +11,25 @@ namespace Symfony\Component\HttpKernel; +use Symfony\Component\Config\Loader\LoaderInterface; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\HttpKernel\Bundle\BundleInterface; -use Symfony\Component\Config\Loader\LoaderInterface; /** * The Kernel is the heart of the Symfony system. * - * It manages an environment made of bundles. + * It manages an environment made of application kernel and bundles. * * @author Fabien Potencier <fabien@symfony.com> + * + * @method string getProjectDir() Gets the project dir (path of the project's composer file) - not defining it is deprecated since Symfony 4.2 */ -interface KernelInterface extends HttpKernelInterface, \Serializable +interface KernelInterface extends HttpKernelInterface { /** * Returns an array of bundles to register. * - * @return BundleInterface[] An array of bundle instances + * @return iterable|BundleInterface[] An iterable of bundle instances */ public function registerBundles(); @@ -56,22 +58,18 @@ interface KernelInterface extends HttpKernelInterface, \Serializable public function getBundles(); /** - * Returns a bundle and optionally its descendants by its name. + * Returns a bundle. * - * The second argument is deprecated as of 3.4 and will be removed in 4.0. This method - * will always return an instance of BundleInterface in 4.0. + * @param string $name Bundle name * - * @param string $name Bundle name - * @param bool $first Whether to return the first bundle only or together with its descendants - * - * @return BundleInterface|BundleInterface[] A BundleInterface instance or an array of BundleInterface instances if $first is false + * @return BundleInterface A BundleInterface instance * * @throws \InvalidArgumentException when the bundle is not enabled */ - public function getBundle($name, $first = true); + public function getBundle($name); /** - * Returns the file path for a given resource. + * Returns the file path for a given bundle resource. * * A Resource can be a file or a directory. * @@ -104,6 +102,8 @@ interface KernelInterface extends HttpKernelInterface, \Serializable * Gets the name of the kernel. * * @return string The kernel name + * + * @deprecated since Symfony 4.2 */ public function getName(); @@ -125,20 +125,22 @@ interface KernelInterface extends HttpKernelInterface, \Serializable * Gets the application root dir (path of the project's Kernel class). * * @return string The Kernel root dir + * + * @deprecated since Symfony 4.2 */ public function getRootDir(); /** * Gets the current container. * - * @return ContainerInterface A ContainerInterface instance + * @return ContainerInterface|null A ContainerInterface instance or null when the Kernel is shutdown */ public function getContainer(); /** * Gets the request start time (not available if debug is disabled). * - * @return int The request start timestamp + * @return float The request start timestamp */ public function getStartTime(); diff --git a/vendor/symfony/http-kernel/LICENSE b/vendor/symfony/http-kernel/LICENSE index 21d7fb9e2f29b50caca3a76f0647e94e2cc8ddc1..a677f43763ca467472898351b328aee41e2edd7c 100644 --- a/vendor/symfony/http-kernel/LICENSE +++ b/vendor/symfony/http-kernel/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-2018 Fabien Potencier +Copyright (c) 2004-2019 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/vendor/symfony/http-kernel/Log/DebugLoggerInterface.php b/vendor/symfony/http-kernel/Log/DebugLoggerInterface.php index f0606d3b0e5eebd446a4aaeb1c3044225c631c08..2a27992e20808bdd0543e91337c7f2b8f44ad356 100644 --- a/vendor/symfony/http-kernel/Log/DebugLoggerInterface.php +++ b/vendor/symfony/http-kernel/Log/DebugLoggerInterface.php @@ -11,12 +11,12 @@ namespace Symfony\Component\HttpKernel\Log; +use Symfony\Component\HttpFoundation\Request; + /** * DebugLoggerInterface. * * @author Fabien Potencier <fabien@symfony.com> - * - * @method clear() Removes all log records. */ interface DebugLoggerInterface { @@ -27,14 +27,23 @@ interface DebugLoggerInterface * timestamp, message, priority, and priorityName. * It can also have an optional context key containing an array. * + * @param Request|null $request The request to get logs for + * * @return array An array of logs */ - public function getLogs(); + public function getLogs(/* Request $request = null */); /** * Returns the number of errors. * + * @param Request|null $request The request to count logs for + * * @return int The number of errors */ - public function countErrors(); + public function countErrors(/* Request $request = null */); + + /** + * Removes all log records. + */ + public function clear(); } diff --git a/vendor/symfony/http-kernel/Log/Logger.php b/vendor/symfony/http-kernel/Log/Logger.php index 617efcf13e5a4d98559183b43abb9be5065633a3..3969487b77494a2ec1ce1839c0f9466fa553199f 100644 --- a/vendor/symfony/http-kernel/Log/Logger.php +++ b/vendor/symfony/http-kernel/Log/Logger.php @@ -22,7 +22,7 @@ use Psr\Log\LogLevel; */ class Logger extends AbstractLogger { - private static $levels = array( + private static $levels = [ LogLevel::DEBUG => 0, LogLevel::INFO => 1, LogLevel::NOTICE => 2, @@ -31,16 +31,16 @@ class Logger extends AbstractLogger LogLevel::CRITICAL => 5, LogLevel::ALERT => 6, LogLevel::EMERGENCY => 7, - ); + ]; private $minLevelIndex; private $formatter; private $handle; - public function __construct($minLevel = null, $output = 'php://stderr', callable $formatter = null) + public function __construct(string $minLevel = null, $output = 'php://stderr', callable $formatter = null) { if (null === $minLevel) { - $minLevel = LogLevel::WARNING; + $minLevel = 'php://stdout' === $output || 'php://stderr' === $output ? LogLevel::CRITICAL : LogLevel::WARNING; if (isset($_ENV['SHELL_VERBOSITY']) || isset($_SERVER['SHELL_VERBOSITY'])) { switch ((int) (isset($_ENV['SHELL_VERBOSITY']) ? $_ENV['SHELL_VERBOSITY'] : $_SERVER['SHELL_VERBOSITY'])) { @@ -57,8 +57,8 @@ class Logger extends AbstractLogger } $this->minLevelIndex = self::$levels[$minLevel]; - $this->formatter = $formatter ?: array($this, 'format'); - if (false === $this->handle = is_resource($output) ? $output : @fopen($output, 'a')) { + $this->formatter = $formatter ?: [$this, 'format']; + if (false === $this->handle = \is_resource($output) ? $output : @fopen($output, 'a')) { throw new InvalidArgumentException(sprintf('Unable to open "%s".', $output)); } } @@ -66,7 +66,7 @@ class Logger extends AbstractLogger /** * {@inheritdoc} */ - public function log($level, $message, array $context = array()) + public function log($level, $message, array $context = []) { if (!isset(self::$levels[$level])) { throw new InvalidArgumentException(sprintf('The log level "%s" does not exist.', $level)); @@ -80,17 +80,10 @@ class Logger extends AbstractLogger fwrite($this->handle, $formatter($level, $message, $context)); } - /** - * @param string $level - * @param string $message - * @param array $context - * - * @return string - */ - private function format($level, $message, array $context) + private function format(string $level, string $message, array $context): string { if (false !== strpos($message, '{')) { - $replacements = array(); + $replacements = []; foreach ($context as $key => $val) { if (null === $val || is_scalar($val) || (\is_object($val) && method_exists($val, '__toString'))) { $replacements["{{$key}}"] = $val; diff --git a/vendor/symfony/http-kernel/Profiler/FileProfilerStorage.php b/vendor/symfony/http-kernel/Profiler/FileProfilerStorage.php index e24b2e018368407d297035da6e9bfba42d720093..541187cfecd5c5254a4e71559eacf021b68eefd0 100644 --- a/vendor/symfony/http-kernel/Profiler/FileProfilerStorage.php +++ b/vendor/symfony/http-kernel/Profiler/FileProfilerStorage.php @@ -30,11 +30,9 @@ class FileProfilerStorage implements ProfilerStorageInterface * * Example : "file:/path/to/the/storage/folder" * - * @param string $dsn The DSN - * * @throws \RuntimeException */ - public function __construct($dsn) + public function __construct(string $dsn) { if (0 !== strpos($dsn, 'file:')) { throw new \RuntimeException(sprintf('Please check your configuration. You are trying to use FileStorage with an invalid dsn "%s". The expected format is "file:/path/to/the/storage/folder".', $dsn)); @@ -54,14 +52,14 @@ class FileProfilerStorage implements ProfilerStorageInterface $file = $this->getIndexFilename(); if (!file_exists($file)) { - return array(); + return []; } $file = fopen($file, 'r'); fseek($file, 0, SEEK_END); - $result = array(); - while (count($result) < $limit && $line = $this->readLineFromFile($file)) { + $result = []; + while (\count($result) < $limit && $line = $this->readLineFromFile($file)) { $values = str_getcsv($line); list($csvToken, $csvIp, $csvMethod, $csvUrl, $csvTime, $csvParent, $csvStatusCode) = $values; $csvTime = (int) $csvTime; @@ -78,7 +76,7 @@ class FileProfilerStorage implements ProfilerStorageInterface continue; } - $result[$csvToken] = array( + $result[$csvToken] = [ 'token' => $csvToken, 'ip' => $csvIp, 'method' => $csvMethod, @@ -86,7 +84,7 @@ class FileProfilerStorage implements ProfilerStorageInterface 'time' => $csvTime, 'parent' => $csvParent, 'status_code' => $csvStatusCode, - ); + ]; } fclose($file); @@ -118,7 +116,7 @@ class FileProfilerStorage implements ProfilerStorageInterface public function read($token) { if (!$token || !file_exists($file = $this->getFilename($token))) { - return; + return null; } return $this->createProfileFromData($token, unserialize(file_get_contents($file))); @@ -136,7 +134,7 @@ class FileProfilerStorage implements ProfilerStorageInterface $profileIndexed = is_file($file); if (!$profileIndexed) { // Create directory - $dir = dirname($file); + $dir = \dirname($file); if (!is_dir($dir) && false === @mkdir($dir, 0777, true) && !is_dir($dir)) { throw new \RuntimeException(sprintf('Unable to create the storage directory (%s).', $dir)); } @@ -146,12 +144,12 @@ class FileProfilerStorage implements ProfilerStorageInterface // when there are errors in sub-requests, the parent and/or children tokens // may equal the profile token, resulting in infinite loops $parentToken = $profile->getParentToken() !== $profileToken ? $profile->getParentToken() : null; - $childrenToken = array_filter(array_map(function ($p) use ($profileToken) { + $childrenToken = array_filter(array_map(function (Profile $p) use ($profileToken) { return $profileToken !== $p->getToken() ? $p->getToken() : null; }, $profile->getChildren())); // Store profile - $data = array( + $data = [ 'token' => $profileToken, 'parent' => $parentToken, 'children' => $childrenToken, @@ -161,7 +159,7 @@ class FileProfilerStorage implements ProfilerStorageInterface 'url' => $profile->getUrl(), 'time' => $profile->getTime(), 'status_code' => $profile->getStatusCode(), - ); + ]; if (false === file_put_contents($file, serialize($data))) { return false; @@ -173,7 +171,7 @@ class FileProfilerStorage implements ProfilerStorageInterface return false; } - fputcsv($file, array( + fputcsv($file, [ $profile->getToken(), $profile->getIp(), $profile->getMethod(), @@ -181,7 +179,7 @@ class FileProfilerStorage implements ProfilerStorageInterface $profile->getTime(), $profile->getParentToken(), $profile->getStatusCode(), - )); + ]); fclose($file); } @@ -229,7 +227,7 @@ class FileProfilerStorage implements ProfilerStorageInterface $position = ftell($file); if (0 === $position) { - return; + return null; } while (true) { diff --git a/vendor/symfony/http-kernel/Profiler/Profile.php b/vendor/symfony/http-kernel/Profiler/Profile.php index c21c9d38a343d7715dffe0beb8f14ebd41a81a24..01cdc89442aef993efd602fc250481ffafb716c3 100644 --- a/vendor/symfony/http-kernel/Profiler/Profile.php +++ b/vendor/symfony/http-kernel/Profiler/Profile.php @@ -25,7 +25,7 @@ class Profile /** * @var DataCollectorInterface[] */ - private $collectors = array(); + private $collectors = []; private $ip; private $method; @@ -41,12 +41,9 @@ class Profile /** * @var Profile[] */ - private $children = array(); + private $children = []; - /** - * @param string $token The token - */ - public function __construct($token) + public function __construct(string $token) { $this->token = $token; } @@ -74,7 +71,7 @@ class Profile /** * Sets the parent token. */ - public function setParent(Profile $parent) + public function setParent(self $parent) { $this->parent = $parent; } @@ -92,7 +89,7 @@ class Profile /** * Returns the parent token. * - * @return null|string The parent token + * @return string|null The parent token */ public function getParentToken() { @@ -102,7 +99,7 @@ class Profile /** * Returns the IP. * - * @return string The IP + * @return string|null The IP */ public function getIp() { @@ -122,7 +119,7 @@ class Profile /** * Returns the request method. * - * @return string The request method + * @return string|null The request method */ public function getMethod() { @@ -137,13 +134,16 @@ class Profile /** * Returns the URL. * - * @return string The URL + * @return string|null The URL */ public function getUrl() { return $this->url; } + /** + * @param string $url + */ public function setUrl($url) { $this->url = $url; @@ -180,7 +180,7 @@ class Profile } /** - * @return int + * @return int|null */ public function getStatusCode() { @@ -204,7 +204,7 @@ class Profile */ public function setChildren(array $children) { - $this->children = array(); + $this->children = []; foreach ($children as $child) { $this->addChild($child); } @@ -213,12 +213,23 @@ class Profile /** * Adds the child token. */ - public function addChild(Profile $child) + public function addChild(self $child) { $this->children[] = $child; $child->setParent($this); } + public function getChildByToken(string $token): ?self + { + foreach ($this->children as $child) { + if ($token === $child->getToken()) { + return $child; + } + } + + return null; + } + /** * Gets a Collector by name. * @@ -254,7 +265,7 @@ class Profile */ public function setCollectors(array $collectors) { - $this->collectors = array(); + $this->collectors = []; foreach ($collectors as $collector) { $this->addCollector($collector); } @@ -282,6 +293,6 @@ class Profile public function __sleep() { - return array('token', 'parent', 'children', 'collectors', 'ip', 'method', 'url', 'time', 'statusCode'); + return ['token', 'parent', 'children', 'collectors', 'ip', 'method', 'url', 'time', 'statusCode']; } } diff --git a/vendor/symfony/http-kernel/Profiler/Profiler.php b/vendor/symfony/http-kernel/Profiler/Profiler.php index 15bfbc5a07777ae51d7be9de501f65d7d7a6dca5..87a4996392c9aab61f9463776c8538b674735f26 100644 --- a/vendor/symfony/http-kernel/Profiler/Profiler.php +++ b/vendor/symfony/http-kernel/Profiler/Profiler.php @@ -11,39 +11,37 @@ namespace Symfony\Component\HttpKernel\Profiler; +use Psr\Log\LoggerInterface; use Symfony\Component\HttpFoundation\Exception\ConflictingHeadersException; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\DataCollector\DataCollectorInterface; use Symfony\Component\HttpKernel\DataCollector\LateDataCollectorInterface; -use Psr\Log\LoggerInterface; +use Symfony\Contracts\Service\ResetInterface; /** * Profiler. * * @author Fabien Potencier <fabien@symfony.com> */ -class Profiler +class Profiler implements ResetInterface { private $storage; /** * @var DataCollectorInterface[] */ - private $collectors = array(); + private $collectors = []; private $logger; private $initiallyEnabled = true; private $enabled = true; - /** - * @param bool $enable The initial enabled state - */ - public function __construct(ProfilerStorageInterface $storage, LoggerInterface $logger = null, $enable = true) + public function __construct(ProfilerStorageInterface $storage, LoggerInterface $logger = null, bool $enable = true) { $this->storage = $storage; $this->logger = $logger; - $this->initiallyEnabled = $this->enabled = (bool) $enable; + $this->initiallyEnabled = $this->enabled = $enable; } /** @@ -65,12 +63,12 @@ class Profiler /** * Loads the Profile for the given Response. * - * @return Profile|false A Profile instance + * @return Profile|null A Profile instance */ public function loadProfileFromResponse(Response $response) { if (!$token = $response->headers->get('X-Debug-Token')) { - return false; + return null; } return $this->loadProfile($token); @@ -81,7 +79,7 @@ class Profiler * * @param string $token A token * - * @return Profile A Profile instance + * @return Profile|null A Profile instance */ public function loadProfile($token) { @@ -103,7 +101,7 @@ class Profiler } if (!($ret = $this->storage->write($profile)) && null !== $this->logger) { - $this->logger->warning('Unable to store the profiler information.', array('configured_storage' => get_class($this->storage))); + $this->logger->warning('Unable to store the profiler information.', ['configured_storage' => \get_class($this->storage)]); } return $ret; @@ -130,7 +128,7 @@ class Profiler * * @return array An array of tokens * - * @see http://php.net/manual/en/datetime.formats.php for the supported date/time formats + * @see https://php.net/datetime.formats for the supported date/time formats */ public function find($ip, $url, $limit, $method, $start, $end, $statusCode = null) { @@ -145,7 +143,7 @@ class Profiler public function collect(Request $request, Response $response, \Exception $exception = null) { if (false === $this->enabled) { - return; + return null; } $profile = new Profile(substr(hash('sha256', uniqid(mt_rand(), true)), 0, 6)); @@ -159,6 +157,10 @@ class Profiler $profile->setIp('Unknown'); } + if ($prevToken = $response->headers->get('X-Debug-Token')) { + $response->headers->set('X-Previous-Debug-Token', $prevToken); + } + $response->headers->set('X-Debug-Token', $profile->getToken()); foreach ($this->collectors as $collector) { @@ -174,10 +176,6 @@ class Profiler public function reset() { foreach ($this->collectors as $collector) { - if (!method_exists($collector, 'reset')) { - continue; - } - $collector->reset(); } $this->enabled = $this->initiallyEnabled; @@ -198,9 +196,9 @@ class Profiler * * @param DataCollectorInterface[] $collectors An array of collectors */ - public function set(array $collectors = array()) + public function set(array $collectors = []) { - $this->collectors = array(); + $this->collectors = []; foreach ($collectors as $collector) { $this->add($collector); } @@ -211,10 +209,6 @@ class Profiler */ public function add(DataCollectorInterface $collector) { - if (!method_exists($collector, 'reset')) { - @trigger_error(sprintf('Implementing "%s" without the "reset()" method is deprecated since Symfony 3.4 and will be unsupported in 4.0 for class "%s".', DataCollectorInterface::class, \get_class($collector)), E_USER_DEPRECATED); - } - $this->collectors[$collector->getName()] = $collector; } @@ -248,16 +242,16 @@ class Profiler return $this->collectors[$name]; } - private function getTimestamp($value) + private function getTimestamp(?string $value): ?int { - if (null === $value || '' == $value) { - return; + if (null === $value || '' === $value) { + return null; } try { $value = new \DateTime(is_numeric($value) ? '@'.$value : $value); } catch (\Exception $e) { - return; + return null; } return $value->getTimestamp(); diff --git a/vendor/symfony/http-kernel/Profiler/ProfilerStorageInterface.php b/vendor/symfony/http-kernel/Profiler/ProfilerStorageInterface.php index 544fb1fef6ec69349f8a8d6315f409399bb7739b..c97e640b60325ec8e42a401ad4fae50cd1cc8b33 100644 --- a/vendor/symfony/http-kernel/Profiler/ProfilerStorageInterface.php +++ b/vendor/symfony/http-kernel/Profiler/ProfilerStorageInterface.php @@ -14,6 +14,14 @@ namespace Symfony\Component\HttpKernel\Profiler; /** * ProfilerStorageInterface. * + * This interface exists for historical reasons. The only supported + * implementation is FileProfilerStorage. + * + * As the profiler must only be used on non-production servers, the file storage + * is more than enough and no other implementations will ever be supported. + * + * @internal since 4.2 + * * @author Fabien Potencier <fabien@symfony.com> */ interface ProfilerStorageInterface @@ -39,7 +47,7 @@ interface ProfilerStorageInterface * * @param string $token A token * - * @return Profile The profile associated with token + * @return Profile|null The profile associated with token */ public function read($token); diff --git a/vendor/symfony/http-kernel/Resources/welcome.html.php b/vendor/symfony/http-kernel/Resources/welcome.html.php index d8c37beb56ae2a1f4768b7a4a9af91a7f1b7bcc5..8fdc00506c860f6eb8d64d8bf407e3cdc34cc472 100644 --- a/vendor/symfony/http-kernel/Resources/welcome.html.php +++ b/vendor/symfony/http-kernel/Resources/welcome.html.php @@ -51,21 +51,7 @@ <div id="next"> <h2>What's next?</h2> <p> - <svg id="icon-book" version="1.1" xmlns="http://www.w3.org/2000/svg" x="0px" y="0px" viewBox="-12.5 9 64 64" enable-background="new -12.5 9 64 64" xml:space="preserve"> - <path fill="#AAA" d="M6.8,40.8c2.4,0.8,4.5-0.7,4.9-2.5c0.2-1.2-0.3-2.1-1.3-3.2l-0.8-0.8c-0.4-0.5-0.6-1.3-0.2-1.9 - c0.4-0.5,0.9-0.8,1.8-0.5c1.3,0.4,1.9,1.3,2.9,2.2c-0.4,1.4-0.7,2.9-0.9,4.2l-0.2,1c-0.7,4-1.3,6.2-2.7,7.5 - c-0.3,0.3-0.7,0.5-1.3,0.6c-0.3,0-0.4-0.3-0.4-0.3c0-0.3,0.2-0.3,0.3-0.4c0.2-0.1,0.5-0.3,0.4-0.8c0-0.7-0.6-1.3-1.3-1.3 - c-0.6,0-1.4,0.6-1.4,1.7s1,1.9,2.4,1.8c0.8,0,2.5-0.3,4.2-2.5c2-2.5,2.5-5.4,2.9-7.4l0.5-2.8c0.3,0,0.5,0.1,0.8,0.1 - c2.4,0.1,3.7-1.3,3.7-2.3c0-0.6-0.3-1.2-0.9-1.2c-0.4,0-0.8,0.3-1,0.8c-0.1,0.6,0.8,1.1,0.1,1.5c-0.5,0.3-1.4,0.6-2.7,0.4l0.3-1.3 - c0.5-2.6,1-5.7,3.2-5.8c0.2,0,0.8,0,0.8,0.4c0,0.2,0,0.2-0.2,0.5c-0.2,0.3-0.3,0.4-0.2,0.7c0,0.7,0.5,1.1,1.2,1.1 - c0.9,0,1.2-1,1.2-1.4c0-1.2-1.2-1.8-2.6-1.8c-1.5,0.1-2.8,0.9-3.7,2.1c-1.1,1.3-1.8,2.9-2.3,4.5c-0.9-0.8-1.6-1.8-3.1-2.3 - c-1.1-0.7-2.3-0.5-3.4,0.3c-0.5,0.4-0.8,1-1,1.6c-0.4,1.5,0.4,2.9,0.8,3.4l0.9,1c0.2,0.2,0.6,0.8,0.4,1.5c-0.3,0.8-1.2,1.3-2.1,1 - c-0.4-0.2-1-0.5-0.9-0.9c0.1-0.2,0.2-0.3,0.3-0.5s0.1-0.3,0.1-0.3c0.2-0.6-0.1-1.4-0.7-1.6c-0.6-0.2-1.2,0-1.3,0.8 - C4.3,38.4,4.7,40,6.8,40.8z M46.1,20.9c0-4.2-3.2-7.5-7.1-7.5h-3.8C34.8,10.8,32.7,9,30.2,9L-2.3,9.1c-2.8,0.1-4.9,2.4-4.9,5.4 - L-7,58.6c0,4.8,8.1,13.9,11.6,14.1l34.7-0.1c3.9,0,7-3.4,7-7.6L46.1,20.9z M-0.3,36.4c0-8.6,6.5-15.6,14.5-15.6 - c8,0,14.5,7,14.5,15.6S22.1,52,14.2,52C6.1,52-0.3,45-0.3,36.4z M42.1,65.1c0,1.8-1.5,3.1-3.1,3.1H4.6c-0.7,0-3-1.8-4.5-4.4h30.4 - c2.8,0,5-2.4,5-5.4V17.9h3.7c1.6,0,2.9,1.4,2.9,3.1V65.1L42.1,65.1z"/> - </svg> + <svg id="icon-book" xmlns="http://www.w3.org/2000/svg" viewBox="-12.5 9 64 64"><path fill="#AAA" d="M6.8 40.8c2.4.8 4.5-.7 4.9-2.5.2-1.2-.3-2.1-1.3-3.2l-.8-.8c-.4-.5-.6-1.3-.2-1.9.4-.5.9-.8 1.8-.5 1.3.4 1.9 1.3 2.9 2.2-.4 1.4-.7 2.9-.9 4.2l-.2 1c-.7 4-1.3 6.2-2.7 7.5-.3.3-.7.5-1.3.6-.3 0-.4-.3-.4-.3 0-.3.2-.3.3-.4.2-.1.5-.3.4-.8 0-.7-.6-1.3-1.3-1.3-.6 0-1.4.6-1.4 1.7s1 1.9 2.4 1.8c.8 0 2.5-.3 4.2-2.5 2-2.5 2.5-5.4 2.9-7.4l.5-2.8c.3 0 .5.1.8.1 2.4.1 3.7-1.3 3.7-2.3 0-.6-.3-1.2-.9-1.2-.4 0-.8.3-1 .8-.1.6.8 1.1.1 1.5-.5.3-1.4.6-2.7.4l.3-1.3c.5-2.6 1-5.7 3.2-5.8.2 0 .8 0 .8.4 0 .2 0 .2-.2.5s-.3.4-.2.7c0 .7.5 1.1 1.2 1.1.9 0 1.2-1 1.2-1.4 0-1.2-1.2-1.8-2.6-1.8-1.5.1-2.8.9-3.7 2.1-1.1 1.3-1.8 2.9-2.3 4.5-.9-.8-1.6-1.8-3.1-2.3-1.1-.7-2.3-.5-3.4.3-.5.4-.8 1-1 1.6-.4 1.5.4 2.9.8 3.4l.9 1c.2.2.6.8.4 1.5-.3.8-1.2 1.3-2.1 1-.4-.2-1-.5-.9-.9.1-.2.2-.3.3-.5s.1-.3.1-.3c.2-.6-.1-1.4-.7-1.6-.6-.2-1.2 0-1.3.8 0 .7.4 2.3 2.5 3.1zm39.3-19.9c0-4.2-3.2-7.5-7.1-7.5h-3.8c-.4-2.6-2.5-4.4-5-4.4l-32.5.1c-2.8.1-4.9 2.4-4.9 5.4l.2 44.1c0 4.8 8.1 13.9 11.6 14.1l34.7-.1c3.9 0 7-3.4 7-7.6l-.2-44.1zM-.3 36.4c0-8.6 6.5-15.6 14.5-15.6s14.5 7 14.5 15.6S22.1 52 14.2 52C6.1 52-.3 45-.3 36.4zm42.4 28.7c0 1.8-1.5 3.1-3.1 3.1H4.6c-.7 0-3-1.8-4.5-4.4h30.4c2.8 0 5-2.4 5-5.4V17.9h3.7c1.6 0 2.9 1.4 2.9 3.1v44.1z"/></svg> Read the documentation to learn <a href="https://symfony.com/doc/<?php echo $docVersion; ?>/page_creation.html"> @@ -76,7 +62,7 @@ </div> <div id="comment"> <p> - You're seeing this message because you have debug mode enabled and you haven't configured any URLs. + You're seeing this page because debug mode is enabled and you haven't configured any homepage URL. </p> </div> </div> diff --git a/vendor/symfony/http-kernel/Tests/Bundle/BundleTest.php b/vendor/symfony/http-kernel/Tests/Bundle/BundleTest.php index 8e52b097d69469b2691da661659073e433bbb733..46dcee216267de89e52e560c2242f100500a70fb 100644 --- a/vendor/symfony/http-kernel/Tests/Bundle/BundleTest.php +++ b/vendor/symfony/http-kernel/Tests/Bundle/BundleTest.php @@ -12,12 +12,9 @@ namespace Symfony\Component\HttpKernel\Tests\Bundle; use PHPUnit\Framework\TestCase; -use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\HttpKernel\Bundle\Bundle; use Symfony\Component\HttpKernel\Tests\Fixtures\ExtensionNotValidBundle\ExtensionNotValidBundle; use Symfony\Component\HttpKernel\Tests\Fixtures\ExtensionPresentBundle\ExtensionPresentBundle; -use Symfony\Component\HttpKernel\Tests\Fixtures\ExtensionAbsentBundle\ExtensionAbsentBundle; -use Symfony\Component\HttpKernel\Tests\Fixtures\ExtensionPresentBundle\Command\FooCommand; class BundleTest extends TestCase { @@ -33,46 +30,15 @@ class BundleTest extends TestCase /** * @group legacy - * @expectedDeprecation Auto-registration of the command "Symfony\Component\HttpKernel\Tests\Fixtures\ExtensionPresentBundle\Command\FooCommand" is deprecated since Symfony 3.4 and won't be supported in 4.0. Use PSR-4 based service discovery instead. - */ - public function testRegisterCommands() - { - $cmd = new FooCommand(); - $app = $this->getMockBuilder('Symfony\Component\Console\Application')->getMock(); - $app->expects($this->once())->method('add')->with($this->equalTo($cmd)); - - $bundle = new ExtensionPresentBundle(); - $bundle->registerCommands($app); - - $bundle2 = new ExtensionAbsentBundle(); - - $this->assertNull($bundle2->registerCommands($app)); - } - - /** - * @expectedException \LogicException - * @expectedExceptionMessage must implement Symfony\Component\DependencyInjection\Extension\ExtensionInterface */ public function testGetContainerExtensionWithInvalidClass() { + $this->expectException('LogicException'); + $this->expectExceptionMessage('must implement Symfony\Component\DependencyInjection\Extension\ExtensionInterface'); $bundle = new ExtensionNotValidBundle(); $bundle->getContainerExtension(); } - public function testHttpKernelRegisterCommandsIgnoresCommandsThatAreRegisteredAsServices() - { - $container = new ContainerBuilder(); - $container->register('console.command.symfony_component_httpkernel_tests_fixtures_extensionpresentbundle_command_foocommand', 'Symfony\Component\HttpKernel\Tests\Fixtures\ExtensionPresentBundle\Command\FooCommand'); - - $application = $this->getMockBuilder('Symfony\Component\Console\Application')->getMock(); - // add() is never called when the found command classes are already registered as services - $application->expects($this->never())->method('add'); - - $bundle = new ExtensionPresentBundle(); - $bundle->setContainer($container); - $bundle->registerCommands($application); - } - public function testBundleNameIsGuessedFromClass() { $bundle = new GuessedNameBundle(); diff --git a/vendor/symfony/http-kernel/Tests/CacheClearer/ChainCacheClearerTest.php b/vendor/symfony/http-kernel/Tests/CacheClearer/ChainCacheClearerTest.php index ec2ecff948c81e8c851d223e772bf2228b4f0964..b97559e321623aa2e7ba3d006a8c3ab9b17ed497 100644 --- a/vendor/symfony/http-kernel/Tests/CacheClearer/ChainCacheClearerTest.php +++ b/vendor/symfony/http-kernel/Tests/CacheClearer/ChainCacheClearerTest.php @@ -18,12 +18,12 @@ class ChainCacheClearerTest extends TestCase { protected static $cacheDir; - public static function setUpBeforeClass() + public static function setUpBeforeClass(): void { - self::$cacheDir = tempnam(sys_get_temp_dir(), 'sf2_cache_clearer_dir'); + self::$cacheDir = tempnam(sys_get_temp_dir(), 'sf_cache_clearer_dir'); } - public static function tearDownAfterClass() + public static function tearDownAfterClass(): void { @unlink(self::$cacheDir); } @@ -35,22 +35,7 @@ class ChainCacheClearerTest extends TestCase ->expects($this->once()) ->method('clear'); - $chainClearer = new ChainCacheClearer(array($clearer)); - $chainClearer->clear(self::$cacheDir); - } - - /** - * @group legacy - */ - public function testInjectClearerUsingAdd() - { - $clearer = $this->getMockClearer(); - $clearer - ->expects($this->once()) - ->method('clear'); - - $chainClearer = new ChainCacheClearer(); - $chainClearer->add($clearer); + $chainClearer = new ChainCacheClearer([$clearer]); $chainClearer->clear(self::$cacheDir); } diff --git a/vendor/symfony/http-kernel/Tests/CacheClearer/Psr6CacheClearerTest.php b/vendor/symfony/http-kernel/Tests/CacheClearer/Psr6CacheClearerTest.php index 3e20efbf1f2c54b93bd818165d02cef9ef11fc98..cdf4a97d34c323d5d9e5e086dbb33368c24b4357 100644 --- a/vendor/symfony/http-kernel/Tests/CacheClearer/Psr6CacheClearerTest.php +++ b/vendor/symfony/http-kernel/Tests/CacheClearer/Psr6CacheClearerTest.php @@ -12,8 +12,8 @@ namespace Symfony\Component\HttpKernel\Tests\CacheClearer; use PHPUnit\Framework\TestCase; -use Symfony\Component\HttpKernel\CacheClearer\Psr6CacheClearer; use Psr\Cache\CacheItemPoolInterface; +use Symfony\Component\HttpKernel\CacheClearer\Psr6CacheClearer; class Psr6CacheClearerTest extends TestCase { @@ -24,7 +24,7 @@ class Psr6CacheClearerTest extends TestCase ->expects($this->once()) ->method('clear'); - (new Psr6CacheClearer(array('pool' => $pool)))->clear(''); + (new Psr6CacheClearer(['pool' => $pool]))->clear(''); } public function testClearPool() @@ -34,36 +34,13 @@ class Psr6CacheClearerTest extends TestCase ->expects($this->once()) ->method('clear'); - (new Psr6CacheClearer(array('pool' => $pool)))->clearPool('pool'); + (new Psr6CacheClearer(['pool' => $pool]))->clearPool('pool'); } - /** - * @expectedException \InvalidArgumentException - * @expectedExceptionMessage Cache pool not found: unknown - */ public function testClearPoolThrowsExceptionOnUnreferencedPool() { + $this->expectException('InvalidArgumentException'); + $this->expectExceptionMessage('Cache pool not found: unknown'); (new Psr6CacheClearer())->clearPool('unknown'); } - - /** - * @group legacy - * @expectedDeprecation The Symfony\Component\HttpKernel\CacheClearer\Psr6CacheClearer::addPool() method is deprecated since Symfony 3.3 and will be removed in 4.0. Pass an array of pools indexed by name to the constructor instead. - */ - public function testClearPoolsInjectedByAdder() - { - $pool1 = $this->getMockBuilder(CacheItemPoolInterface::class)->getMock(); - $pool1 - ->expects($this->once()) - ->method('clear'); - - $pool2 = $this->getMockBuilder(CacheItemPoolInterface::class)->getMock(); - $pool2 - ->expects($this->once()) - ->method('clear'); - - $clearer = new Psr6CacheClearer(array('pool1' => $pool1)); - $clearer->addPool($pool2); - $clearer->clear(''); - } } diff --git a/vendor/symfony/http-kernel/Tests/CacheWarmer/CacheWarmerAggregateTest.php b/vendor/symfony/http-kernel/Tests/CacheWarmer/CacheWarmerAggregateTest.php index ba159124c93e90f972c2a5fff1a095dd03c3bf50..4266c0a1824f9cb12e07aca183bb0ffa52ea1f77 100644 --- a/vendor/symfony/http-kernel/Tests/CacheWarmer/CacheWarmerAggregateTest.php +++ b/vendor/symfony/http-kernel/Tests/CacheWarmer/CacheWarmerAggregateTest.php @@ -18,12 +18,12 @@ class CacheWarmerAggregateTest extends TestCase { protected static $cacheDir; - public static function setUpBeforeClass() + public static function setUpBeforeClass(): void { - self::$cacheDir = tempnam(sys_get_temp_dir(), 'sf2_cache_warmer_dir'); + self::$cacheDir = tempnam(sys_get_temp_dir(), 'sf_cache_warmer_dir'); } - public static function tearDownAfterClass() + public static function tearDownAfterClass(): void { @unlink(self::$cacheDir); } @@ -34,35 +34,7 @@ class CacheWarmerAggregateTest extends TestCase $warmer ->expects($this->once()) ->method('warmUp'); - $aggregate = new CacheWarmerAggregate(array($warmer)); - $aggregate->warmUp(self::$cacheDir); - } - - /** - * @group legacy - */ - public function testInjectWarmersUsingAdd() - { - $warmer = $this->getCacheWarmerMock(); - $warmer - ->expects($this->once()) - ->method('warmUp'); - $aggregate = new CacheWarmerAggregate(); - $aggregate->add($warmer); - $aggregate->warmUp(self::$cacheDir); - } - - /** - * @group legacy - */ - public function testInjectWarmersUsingSetWarmers() - { - $warmer = $this->getCacheWarmerMock(); - $warmer - ->expects($this->once()) - ->method('warmUp'); - $aggregate = new CacheWarmerAggregate(); - $aggregate->setWarmers(array($warmer)); + $aggregate = new CacheWarmerAggregate([$warmer]); $aggregate->warmUp(self::$cacheDir); } @@ -76,7 +48,7 @@ class CacheWarmerAggregateTest extends TestCase ->expects($this->once()) ->method('warmUp'); - $aggregate = new CacheWarmerAggregate(array($warmer)); + $aggregate = new CacheWarmerAggregate([$warmer]); $aggregate->enableOptionalWarmers(); $aggregate->warmUp(self::$cacheDir); } @@ -87,12 +59,12 @@ class CacheWarmerAggregateTest extends TestCase $warmer ->expects($this->once()) ->method('isOptional') - ->will($this->returnValue(true)); + ->willReturn(true); $warmer ->expects($this->never()) ->method('warmUp'); - $aggregate = new CacheWarmerAggregate(array($warmer)); + $aggregate = new CacheWarmerAggregate([$warmer]); $aggregate->warmUp(self::$cacheDir); } diff --git a/vendor/symfony/http-kernel/Tests/CacheWarmer/CacheWarmerTest.php b/vendor/symfony/http-kernel/Tests/CacheWarmer/CacheWarmerTest.php index 05666cb0dcdc7570da7b8e8f55c48def351f3d3a..b5acb1261849329e79bb885bede96872b0dd3976 100644 --- a/vendor/symfony/http-kernel/Tests/CacheWarmer/CacheWarmerTest.php +++ b/vendor/symfony/http-kernel/Tests/CacheWarmer/CacheWarmerTest.php @@ -18,12 +18,12 @@ class CacheWarmerTest extends TestCase { protected static $cacheFile; - public static function setUpBeforeClass() + public static function setUpBeforeClass(): void { - self::$cacheFile = tempnam(sys_get_temp_dir(), 'sf2_cache_warmer_dir'); + self::$cacheFile = tempnam(sys_get_temp_dir(), 'sf_cache_warmer_dir'); } - public static function tearDownAfterClass() + public static function tearDownAfterClass(): void { @unlink(self::$cacheFile); } @@ -31,19 +31,17 @@ class CacheWarmerTest extends TestCase public function testWriteCacheFileCreatesTheFile() { $warmer = new TestCacheWarmer(self::$cacheFile); - $warmer->warmUp(dirname(self::$cacheFile)); + $warmer->warmUp(\dirname(self::$cacheFile)); $this->assertFileExists(self::$cacheFile); } - /** - * @expectedException \RuntimeException - */ public function testWriteNonWritableCacheFileThrowsARuntimeException() { + $this->expectException('RuntimeException'); $nonWritableFile = '/this/file/is/very/probably/not/writable'; $warmer = new TestCacheWarmer($nonWritableFile); - $warmer->warmUp(dirname($nonWritableFile)); + $warmer->warmUp(\dirname($nonWritableFile)); } } diff --git a/vendor/symfony/http-kernel/Tests/Config/EnvParametersResourceTest.php b/vendor/symfony/http-kernel/Tests/Config/EnvParametersResourceTest.php deleted file mode 100644 index 986e05d8b888abfadf10cf50a4fc95376886d467..0000000000000000000000000000000000000000 --- a/vendor/symfony/http-kernel/Tests/Config/EnvParametersResourceTest.php +++ /dev/null @@ -1,110 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Tests\Config; - -use PHPUnit\Framework\TestCase; -use Symfony\Component\HttpKernel\Config\EnvParametersResource; - -/** - * @group legacy - */ -class EnvParametersResourceTest extends TestCase -{ - protected $prefix = '__DUMMY_'; - protected $initialEnv; - protected $resource; - - protected function setUp() - { - $this->initialEnv = array( - $this->prefix.'1' => 'foo', - $this->prefix.'2' => 'bar', - ); - - foreach ($this->initialEnv as $key => $value) { - $_SERVER[$key] = $value; - } - - $this->resource = new EnvParametersResource($this->prefix); - } - - protected function tearDown() - { - foreach ($_SERVER as $key => $value) { - if (0 === strpos($key, $this->prefix)) { - unset($_SERVER[$key]); - } - } - } - - public function testGetResource() - { - $this->assertSame( - array('prefix' => $this->prefix, 'variables' => $this->initialEnv), - $this->resource->getResource(), - '->getResource() returns the resource' - ); - } - - public function testToString() - { - $this->assertSame( - serialize(array('prefix' => $this->prefix, 'variables' => $this->initialEnv)), - (string) $this->resource - ); - } - - public function testIsFreshNotChanged() - { - $this->assertTrue( - $this->resource->isFresh(time()), - '->isFresh() returns true if the variables have not changed' - ); - } - - public function testIsFreshValueChanged() - { - reset($this->initialEnv); - $_SERVER[key($this->initialEnv)] = 'baz'; - - $this->assertFalse( - $this->resource->isFresh(time()), - '->isFresh() returns false if a variable has been changed' - ); - } - - public function testIsFreshValueRemoved() - { - reset($this->initialEnv); - unset($_SERVER[key($this->initialEnv)]); - - $this->assertFalse( - $this->resource->isFresh(time()), - '->isFresh() returns false if a variable has been removed' - ); - } - - public function testIsFreshValueAdded() - { - $_SERVER[$this->prefix.'3'] = 'foo'; - - $this->assertFalse( - $this->resource->isFresh(time()), - '->isFresh() returns false if a variable has been added' - ); - } - - public function testSerializeUnserialize() - { - $this->assertEquals($this->resource, unserialize(serialize($this->resource))); - } -} diff --git a/vendor/symfony/http-kernel/Tests/Config/FileLocatorTest.php b/vendor/symfony/http-kernel/Tests/Config/FileLocatorTest.php index 6265f0275560ae4d4a9f018bdb966ef0ccf430fc..72b38c672ada995f08ca046c0da25fcd97921359 100644 --- a/vendor/symfony/http-kernel/Tests/Config/FileLocatorTest.php +++ b/vendor/symfony/http-kernel/Tests/Config/FileLocatorTest.php @@ -23,14 +23,14 @@ class FileLocatorTest extends TestCase ->expects($this->atLeastOnce()) ->method('locateResource') ->with('@BundleName/some/path', null, true) - ->will($this->returnValue('/bundle-name/some/path')); + ->willReturn('/bundle-name/some/path'); $locator = new FileLocator($kernel); $this->assertEquals('/bundle-name/some/path', $locator->locate('@BundleName/some/path')); $kernel ->expects($this->never()) ->method('locateResource'); - $this->{method_exists($this, $_ = 'expectException') ? $_ : 'setExpectedException'}('LogicException'); + $this->expectException('LogicException'); $locator->locate('/some/path'); } diff --git a/vendor/symfony/http-kernel/Tests/Controller/ArgumentResolver/NotTaggedControllerValueResolverTest.php b/vendor/symfony/http-kernel/Tests/Controller/ArgumentResolver/NotTaggedControllerValueResolverTest.php new file mode 100644 index 0000000000000000000000000000000000000000..4f85b0f351819a4b8af6923cf06fe9ddf11f16c1 --- /dev/null +++ b/vendor/symfony/http-kernel/Tests/Controller/ArgumentResolver/NotTaggedControllerValueResolverTest.php @@ -0,0 +1,109 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Tests\Controller\ArgumentResolver; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\DependencyInjection\ServiceLocator; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpKernel\Controller\ArgumentResolver\NotTaggedControllerValueResolver; +use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata; + +class NotTaggedControllerValueResolverTest extends TestCase +{ + public function testDoSupportWhenControllerDoNotExists() + { + $resolver = new NotTaggedControllerValueResolver(new ServiceLocator([])); + $argument = new ArgumentMetadata('dummy', \stdClass::class, false, false, null); + $request = $this->requestWithAttributes(['_controller' => 'my_controller']); + + $this->assertTrue($resolver->supports($request, $argument)); + } + + public function testDoNotSupportWhenControllerExists() + { + $resolver = new NotTaggedControllerValueResolver(new ServiceLocator([ + 'App\\Controller\\Mine::method' => function () { + return new ServiceLocator([ + 'dummy' => function () { + return new \stdClass(); + }, + ]); + }, + ])); + $argument = new ArgumentMetadata('dummy', \stdClass::class, false, false, null); + $request = $this->requestWithAttributes(['_controller' => 'App\\Controller\\Mine::method']); + + $this->assertFalse($resolver->supports($request, $argument)); + } + + public function testDoNotSupportEmptyController() + { + $resolver = new NotTaggedControllerValueResolver(new ServiceLocator([])); + $argument = new ArgumentMetadata('dummy', \stdClass::class, false, false, null); + $request = $this->requestWithAttributes(['_controller' => '']); + $this->assertFalse($resolver->supports($request, $argument)); + } + + public function testController() + { + $this->expectException('Symfony\Component\DependencyInjection\Exception\RuntimeException'); + $this->expectExceptionMessage('Could not resolve argument $dummy of "App\Controller\Mine::method()", maybe you forgot to register the controller as a service or missed tagging it with the "controller.service_arguments"?'); + $resolver = new NotTaggedControllerValueResolver(new ServiceLocator([])); + $argument = new ArgumentMetadata('dummy', \stdClass::class, false, false, null); + $request = $this->requestWithAttributes(['_controller' => 'App\\Controller\\Mine::method']); + $this->assertTrue($resolver->supports($request, $argument)); + $resolver->resolve($request, $argument); + } + + public function testControllerWithATrailingBackSlash() + { + $this->expectException('Symfony\Component\DependencyInjection\Exception\RuntimeException'); + $this->expectExceptionMessage('Could not resolve argument $dummy of "App\Controller\Mine::method()", maybe you forgot to register the controller as a service or missed tagging it with the "controller.service_arguments"?'); + $resolver = new NotTaggedControllerValueResolver(new ServiceLocator([])); + $argument = new ArgumentMetadata('dummy', \stdClass::class, false, false, null); + $request = $this->requestWithAttributes(['_controller' => '\\App\\Controller\\Mine::method']); + $this->assertTrue($resolver->supports($request, $argument)); + $resolver->resolve($request, $argument); + } + + public function testControllerWithMethodNameStartUppercase() + { + $this->expectException('Symfony\Component\DependencyInjection\Exception\RuntimeException'); + $this->expectExceptionMessage('Could not resolve argument $dummy of "App\Controller\Mine::method()", maybe you forgot to register the controller as a service or missed tagging it with the "controller.service_arguments"?'); + $resolver = new NotTaggedControllerValueResolver(new ServiceLocator([])); + $argument = new ArgumentMetadata('dummy', \stdClass::class, false, false, null); + $request = $this->requestWithAttributes(['_controller' => 'App\\Controller\\Mine::Method']); + $this->assertTrue($resolver->supports($request, $argument)); + $resolver->resolve($request, $argument); + } + + public function testControllerNameIsAnArray() + { + $this->expectException('Symfony\Component\DependencyInjection\Exception\RuntimeException'); + $this->expectExceptionMessage('Could not resolve argument $dummy of "App\Controller\Mine::method()", maybe you forgot to register the controller as a service or missed tagging it with the "controller.service_arguments"?'); + $resolver = new NotTaggedControllerValueResolver(new ServiceLocator([])); + $argument = new ArgumentMetadata('dummy', \stdClass::class, false, false, null); + $request = $this->requestWithAttributes(['_controller' => ['App\\Controller\\Mine', 'method']]); + $this->assertTrue($resolver->supports($request, $argument)); + $resolver->resolve($request, $argument); + } + + private function requestWithAttributes(array $attributes) + { + $request = Request::create('/'); + foreach ($attributes as $name => $value) { + $request->attributes->set($name, $value); + } + + return $request; + } +} diff --git a/vendor/symfony/http-kernel/Tests/Controller/ArgumentResolver/ServiceValueResolverTest.php b/vendor/symfony/http-kernel/Tests/Controller/ArgumentResolver/ServiceValueResolverTest.php index b05828f5bf6d25264738b389e0597a437e6f7e3e..4036727bce15414a1029b745a309428433177d68 100644 --- a/vendor/symfony/http-kernel/Tests/Controller/ArgumentResolver/ServiceValueResolverTest.php +++ b/vendor/symfony/http-kernel/Tests/Controller/ArgumentResolver/ServiceValueResolverTest.php @@ -12,58 +12,114 @@ namespace Symfony\Component\HttpKernel\Tests\Controller\ArgumentResolver; use PHPUnit\Framework\TestCase; +use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\ServiceLocator; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\Controller\ArgumentResolver\ServiceValueResolver; use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata; +use Symfony\Component\HttpKernel\DependencyInjection\RegisterControllerArgumentLocatorsPass; class ServiceValueResolverTest extends TestCase { public function testDoNotSupportWhenControllerDoNotExists() { - $resolver = new ServiceValueResolver(new ServiceLocator(array())); + $resolver = new ServiceValueResolver(new ServiceLocator([])); $argument = new ArgumentMetadata('dummy', DummyService::class, false, false, null); - $request = $this->requestWithAttributes(array('_controller' => 'my_controller')); + $request = $this->requestWithAttributes(['_controller' => 'my_controller']); $this->assertFalse($resolver->supports($request, $argument)); } public function testExistingController() { - $resolver = new ServiceValueResolver(new ServiceLocator(array( + $resolver = new ServiceValueResolver(new ServiceLocator([ 'App\\Controller\\Mine::method' => function () { - return new ServiceLocator(array( + return new ServiceLocator([ 'dummy' => function () { return new DummyService(); }, - )); + ]); }, - ))); + ])); - $request = $this->requestWithAttributes(array('_controller' => 'App\\Controller\\Mine::method')); + $request = $this->requestWithAttributes(['_controller' => 'App\\Controller\\Mine::method']); $argument = new ArgumentMetadata('dummy', DummyService::class, false, false, null); $this->assertTrue($resolver->supports($request, $argument)); - $this->assertYieldEquals(array(new DummyService()), $resolver->resolve($request, $argument)); + $this->assertYieldEquals([new DummyService()], $resolver->resolve($request, $argument)); + } + + public function testExistingControllerWithATrailingBackSlash() + { + $resolver = new ServiceValueResolver(new ServiceLocator([ + 'App\\Controller\\Mine::method' => function () { + return new ServiceLocator([ + 'dummy' => function () { + return new DummyService(); + }, + ]); + }, + ])); + + $request = $this->requestWithAttributes(['_controller' => '\\App\\Controller\\Mine::method']); + $argument = new ArgumentMetadata('dummy', DummyService::class, false, false, null); + + $this->assertTrue($resolver->supports($request, $argument)); + $this->assertYieldEquals([new DummyService()], $resolver->resolve($request, $argument)); + } + + public function testExistingControllerWithMethodNameStartUppercase() + { + $resolver = new ServiceValueResolver(new ServiceLocator([ + 'App\\Controller\\Mine::method' => function () { + return new ServiceLocator([ + 'dummy' => function () { + return new DummyService(); + }, + ]); + }, + ])); + $request = $this->requestWithAttributes(['_controller' => 'App\\Controller\\Mine::Method']); + $argument = new ArgumentMetadata('dummy', DummyService::class, false, false, null); + + $this->assertTrue($resolver->supports($request, $argument)); + $this->assertYieldEquals([new DummyService()], $resolver->resolve($request, $argument)); } public function testControllerNameIsAnArray() { - $resolver = new ServiceValueResolver(new ServiceLocator(array( + $resolver = new ServiceValueResolver(new ServiceLocator([ 'App\\Controller\\Mine::method' => function () { - return new ServiceLocator(array( + return new ServiceLocator([ 'dummy' => function () { return new DummyService(); }, - )); + ]); }, - ))); + ])); - $request = $this->requestWithAttributes(array('_controller' => array('App\\Controller\\Mine', 'method'))); + $request = $this->requestWithAttributes(['_controller' => ['App\\Controller\\Mine', 'method']]); $argument = new ArgumentMetadata('dummy', DummyService::class, false, false, null); $this->assertTrue($resolver->supports($request, $argument)); - $this->assertYieldEquals(array(new DummyService()), $resolver->resolve($request, $argument)); + $this->assertYieldEquals([new DummyService()], $resolver->resolve($request, $argument)); + } + + public function testErrorIsTruncated() + { + $this->expectException('Symfony\Component\DependencyInjection\Exception\RuntimeException'); + $this->expectExceptionMessage('Cannot autowire argument $dummy of "Symfony\Component\HttpKernel\Tests\Controller\ArgumentResolver\DummyController::index()": it references class "Symfony\Component\HttpKernel\Tests\Controller\ArgumentResolver\DummyService" but no such service exists.'); + $container = new ContainerBuilder(); + $container->addCompilerPass(new RegisterControllerArgumentLocatorsPass()); + + $container->register('argument_resolver.service', ServiceValueResolver::class)->addArgument(null)->setPublic(true); + $container->register(DummyController::class)->addTag('controller.service_arguments')->setPublic(true); + + $container->compile(); + + $request = $this->requestWithAttributes(['_controller' => [DummyController::class, 'index']]); + $argument = new ArgumentMetadata('dummy', DummyService::class, false, false, null); + $container->get('argument_resolver.service')->resolve($request, $argument)->current(); } private function requestWithAttributes(array $attributes) @@ -79,7 +135,7 @@ class ServiceValueResolverTest extends TestCase private function assertYieldEquals(array $expected, \Generator $generator) { - $args = array(); + $args = []; foreach ($generator as $arg) { $args[] = $arg; } @@ -91,3 +147,10 @@ class ServiceValueResolverTest extends TestCase class DummyService { } + +class DummyController +{ + public function index(DummyService $dummy) + { + } +} diff --git a/vendor/symfony/http-kernel/Tests/Controller/ArgumentResolver/TraceableValueResolverTest.php b/vendor/symfony/http-kernel/Tests/Controller/ArgumentResolver/TraceableValueResolverTest.php new file mode 100644 index 0000000000000000000000000000000000000000..3c2cc3f70040f9dd1736f57bda12aa59f2a24101 --- /dev/null +++ b/vendor/symfony/http-kernel/Tests/Controller/ArgumentResolver/TraceableValueResolverTest.php @@ -0,0 +1,76 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Tests\Controller\ArgumentResolver; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpKernel\Controller\ArgumentResolver\TraceableValueResolver; +use Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface; +use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata; +use Symfony\Component\Stopwatch\Stopwatch; + +class TraceableValueResolverTest extends TestCase +{ + public function testTimingsInSupports() + { + $stopwatch = new Stopwatch(); + $resolver = new TraceableValueResolver(new ResolverStub(), $stopwatch); + $argument = new ArgumentMetadata('dummy', 'string', false, false, null); + $request = new Request(); + + $this->assertTrue($resolver->supports($request, $argument)); + + $event = $stopwatch->getEvent(ResolverStub::class.'::supports'); + $this->assertCount(1, $event->getPeriods()); + } + + public function testTimingsInResolve() + { + $stopwatch = new Stopwatch(); + $resolver = new TraceableValueResolver(new ResolverStub(), $stopwatch); + $argument = new ArgumentMetadata('dummy', 'string', false, false, null); + $request = new Request(); + + $iterable = $resolver->resolve($request, $argument); + + foreach ($iterable as $index => $resolved) { + $event = $stopwatch->getEvent(ResolverStub::class.'::resolve'); + $this->assertTrue($event->isStarted()); + $this->assertEmpty($event->getPeriods()); + switch ($index) { + case 0: + $this->assertEquals('first', $resolved); + break; + case 1: + $this->assertEquals('second', $resolved); + break; + } + } + + $event = $stopwatch->getEvent(ResolverStub::class.'::resolve'); + $this->assertCount(1, $event->getPeriods()); + } +} + +class ResolverStub implements ArgumentValueResolverInterface +{ + public function supports(Request $request, ArgumentMetadata $argument) + { + return true; + } + + public function resolve(Request $request, ArgumentMetadata $argument) + { + yield 'first'; + yield 'second'; + } +} diff --git a/vendor/symfony/http-kernel/Tests/Controller/ArgumentResolverTest.php b/vendor/symfony/http-kernel/Tests/Controller/ArgumentResolverTest.php index 0804139030128e179d5a2aad3a945dcefaef735c..8ee9108b1bb3a871ae4c89a40a3c4d89f00f6cd2 100644 --- a/vendor/symfony/http-kernel/Tests/Controller/ArgumentResolverTest.php +++ b/vendor/symfony/http-kernel/Tests/Controller/ArgumentResolverTest.php @@ -12,6 +12,7 @@ namespace Symfony\Component\HttpKernel\Tests\Controller; use PHPUnit\Framework\TestCase; +use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Session\Session; use Symfony\Component\HttpFoundation\Session\SessionInterface; use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage; @@ -23,14 +24,13 @@ use Symfony\Component\HttpKernel\Tests\Fixtures\Controller\ExtendingRequest; use Symfony\Component\HttpKernel\Tests\Fixtures\Controller\ExtendingSession; use Symfony\Component\HttpKernel\Tests\Fixtures\Controller\NullableController; use Symfony\Component\HttpKernel\Tests\Fixtures\Controller\VariadicController; -use Symfony\Component\HttpFoundation\Request; class ArgumentResolverTest extends TestCase { /** @var ArgumentResolver */ private static $resolver; - public static function setUpBeforeClass() + public static function setUpBeforeClass(): void { $factory = new ArgumentMetadataFactory(); @@ -40,33 +40,33 @@ class ArgumentResolverTest extends TestCase public function testDefaultState() { $this->assertEquals(self::$resolver, new ArgumentResolver()); - $this->assertNotEquals(self::$resolver, new ArgumentResolver(null, array(new RequestAttributeValueResolver()))); + $this->assertNotEquals(self::$resolver, new ArgumentResolver(null, [new RequestAttributeValueResolver()])); } public function testGetArguments() { $request = Request::create('/'); $request->attributes->set('foo', 'foo'); - $controller = array(new self(), 'controllerWithFoo'); + $controller = [new self(), 'controllerWithFoo']; - $this->assertEquals(array('foo'), self::$resolver->getArguments($request, $controller), '->getArguments() returns an array of arguments for the controller method'); + $this->assertEquals(['foo'], self::$resolver->getArguments($request, $controller), '->getArguments() returns an array of arguments for the controller method'); } public function testGetArgumentsReturnsEmptyArrayWhenNoArguments() { $request = Request::create('/'); - $controller = array(new self(), 'controllerWithoutArguments'); + $controller = [new self(), 'controllerWithoutArguments']; - $this->assertEquals(array(), self::$resolver->getArguments($request, $controller), '->getArguments() returns an empty array if the method takes no arguments'); + $this->assertEquals([], self::$resolver->getArguments($request, $controller), '->getArguments() returns an empty array if the method takes no arguments'); } public function testGetArgumentsUsesDefaultValue() { $request = Request::create('/'); $request->attributes->set('foo', 'foo'); - $controller = array(new self(), 'controllerWithFooAndDefaultBar'); + $controller = [new self(), 'controllerWithFooAndDefaultBar']; - $this->assertEquals(array('foo', null), self::$resolver->getArguments($request, $controller), '->getArguments() uses default values if present'); + $this->assertEquals(['foo', null], self::$resolver->getArguments($request, $controller), '->getArguments() uses default values if present'); } public function testGetArgumentsOverrideDefaultValueByRequestAttribute() @@ -74,9 +74,9 @@ class ArgumentResolverTest extends TestCase $request = Request::create('/'); $request->attributes->set('foo', 'foo'); $request->attributes->set('bar', 'bar'); - $controller = array(new self(), 'controllerWithFooAndDefaultBar'); + $controller = [new self(), 'controllerWithFooAndDefaultBar']; - $this->assertEquals(array('foo', 'bar'), self::$resolver->getArguments($request, $controller), '->getArguments() overrides default values if provided in the request attributes'); + $this->assertEquals(['foo', 'bar'], self::$resolver->getArguments($request, $controller), '->getArguments() overrides default values if provided in the request attributes'); } public function testGetArgumentsFromClosure() @@ -85,7 +85,7 @@ class ArgumentResolverTest extends TestCase $request->attributes->set('foo', 'foo'); $controller = function ($foo) {}; - $this->assertEquals(array('foo'), self::$resolver->getArguments($request, $controller)); + $this->assertEquals(['foo'], self::$resolver->getArguments($request, $controller)); } public function testGetArgumentsUsesDefaultValueFromClosure() @@ -94,7 +94,7 @@ class ArgumentResolverTest extends TestCase $request->attributes->set('foo', 'foo'); $controller = function ($foo, $bar = 'bar') {}; - $this->assertEquals(array('foo', 'bar'), self::$resolver->getArguments($request, $controller)); + $this->assertEquals(['foo', 'bar'], self::$resolver->getArguments($request, $controller)); } public function testGetArgumentsFromInvokableObject() @@ -103,12 +103,12 @@ class ArgumentResolverTest extends TestCase $request->attributes->set('foo', 'foo'); $controller = new self(); - $this->assertEquals(array('foo', null), self::$resolver->getArguments($request, $controller)); + $this->assertEquals(['foo', null], self::$resolver->getArguments($request, $controller)); // Test default bar overridden by request attribute $request->attributes->set('bar', 'bar'); - $this->assertEquals(array('foo', 'bar'), self::$resolver->getArguments($request, $controller)); + $this->assertEquals(['foo', 'bar'], self::$resolver->getArguments($request, $controller)); } public function testGetArgumentsFromFunctionName() @@ -118,7 +118,7 @@ class ArgumentResolverTest extends TestCase $request->attributes->set('foobar', 'foobar'); $controller = __NAMESPACE__.'\controller_function'; - $this->assertEquals(array('foo', 'foobar'), self::$resolver->getArguments($request, $controller)); + $this->assertEquals(['foo', 'foobar'], self::$resolver->getArguments($request, $controller)); } public function testGetArgumentsFailsOnUnresolvedValue() @@ -126,7 +126,7 @@ class ArgumentResolverTest extends TestCase $request = Request::create('/'); $request->attributes->set('foo', 'foo'); $request->attributes->set('foobar', 'foobar'); - $controller = array(new self(), 'controllerWithFooBarFoobar'); + $controller = [new self(), 'controllerWithFooBarFoobar']; try { self::$resolver->getArguments($request, $controller); @@ -139,55 +139,46 @@ class ArgumentResolverTest extends TestCase public function testGetArgumentsInjectsRequest() { $request = Request::create('/'); - $controller = array(new self(), 'controllerWithRequest'); + $controller = [new self(), 'controllerWithRequest']; - $this->assertEquals(array($request), self::$resolver->getArguments($request, $controller), '->getArguments() injects the request'); + $this->assertEquals([$request], self::$resolver->getArguments($request, $controller), '->getArguments() injects the request'); } public function testGetArgumentsInjectsExtendingRequest() { $request = ExtendingRequest::create('/'); - $controller = array(new self(), 'controllerWithExtendingRequest'); + $controller = [new self(), 'controllerWithExtendingRequest']; - $this->assertEquals(array($request), self::$resolver->getArguments($request, $controller), '->getArguments() injects the request when extended'); + $this->assertEquals([$request], self::$resolver->getArguments($request, $controller), '->getArguments() injects the request when extended'); } - /** - * @requires PHP 5.6 - */ public function testGetVariadicArguments() { $request = Request::create('/'); $request->attributes->set('foo', 'foo'); - $request->attributes->set('bar', array('foo', 'bar')); - $controller = array(new VariadicController(), 'action'); + $request->attributes->set('bar', ['foo', 'bar']); + $controller = [new VariadicController(), 'action']; - $this->assertEquals(array('foo', 'foo', 'bar'), self::$resolver->getArguments($request, $controller)); + $this->assertEquals(['foo', 'foo', 'bar'], self::$resolver->getArguments($request, $controller)); } - /** - * @requires PHP 5.6 - * @expectedException \InvalidArgumentException - */ public function testGetVariadicArgumentsWithoutArrayInRequest() { + $this->expectException('InvalidArgumentException'); $request = Request::create('/'); $request->attributes->set('foo', 'foo'); $request->attributes->set('bar', 'foo'); - $controller = array(new VariadicController(), 'action'); + $controller = [new VariadicController(), 'action']; self::$resolver->getArguments($request, $controller); } - /** - * @requires PHP 5.6 - * @expectedException \InvalidArgumentException - */ public function testGetArgumentWithoutArray() { + $this->expectException('InvalidArgumentException'); $factory = new ArgumentMetadataFactory(); $valueResolver = $this->getMockBuilder(ArgumentValueResolverInterface::class)->getMock(); - $resolver = new ArgumentResolver($factory, array($valueResolver)); + $resolver = new ArgumentResolver($factory, [$valueResolver]); $valueResolver->expects($this->any())->method('supports')->willReturn(true); $valueResolver->expects($this->any())->method('resolve')->willReturn('foo'); @@ -195,45 +186,37 @@ class ArgumentResolverTest extends TestCase $request = Request::create('/'); $request->attributes->set('foo', 'foo'); $request->attributes->set('bar', 'foo'); - $controller = array($this, 'controllerWithFooAndDefaultBar'); + $controller = [$this, 'controllerWithFooAndDefaultBar']; $resolver->getArguments($request, $controller); } - /** - * @expectedException \RuntimeException - */ public function testIfExceptionIsThrownWhenMissingAnArgument() { + $this->expectException('RuntimeException'); $request = Request::create('/'); - $controller = array($this, 'controllerWithFoo'); + $controller = [$this, 'controllerWithFoo']; self::$resolver->getArguments($request, $controller); } - /** - * @requires PHP 7.1 - */ public function testGetNullableArguments() { $request = Request::create('/'); $request->attributes->set('foo', 'foo'); $request->attributes->set('bar', new \stdClass()); $request->attributes->set('mandatory', 'mandatory'); - $controller = array(new NullableController(), 'action'); + $controller = [new NullableController(), 'action']; - $this->assertEquals(array('foo', new \stdClass(), 'value', 'mandatory'), self::$resolver->getArguments($request, $controller)); + $this->assertEquals(['foo', new \stdClass(), 'value', 'mandatory'], self::$resolver->getArguments($request, $controller)); } - /** - * @requires PHP 7.1 - */ public function testGetNullableArgumentsWithDefaults() { $request = Request::create('/'); $request->attributes->set('mandatory', 'mandatory'); - $controller = array(new NullableController(), 'action'); + $controller = [new NullableController(), 'action']; - $this->assertEquals(array(null, null, 'value', 'mandatory'), self::$resolver->getArguments($request, $controller)); + $this->assertEquals([null, null, 'value', 'mandatory'], self::$resolver->getArguments($request, $controller)); } public function testGetSessionArguments() @@ -241,9 +224,9 @@ class ArgumentResolverTest extends TestCase $session = new Session(new MockArraySessionStorage()); $request = Request::create('/'); $request->setSession($session); - $controller = array($this, 'controllerWithSession'); + $controller = [$this, 'controllerWithSession']; - $this->assertEquals(array($session), self::$resolver->getArguments($request, $controller)); + $this->assertEquals([$session], self::$resolver->getArguments($request, $controller)); } public function testGetSessionArgumentsWithExtendedSession() @@ -251,9 +234,9 @@ class ArgumentResolverTest extends TestCase $session = new ExtendingSession(new MockArraySessionStorage()); $request = Request::create('/'); $request->setSession($session); - $controller = array($this, 'controllerWithExtendingSession'); + $controller = [$this, 'controllerWithExtendingSession']; - $this->assertEquals(array($session), self::$resolver->getArguments($request, $controller)); + $this->assertEquals([$session], self::$resolver->getArguments($request, $controller)); } public function testGetSessionArgumentsWithInterface() @@ -261,44 +244,38 @@ class ArgumentResolverTest extends TestCase $session = $this->getMockBuilder(SessionInterface::class)->getMock(); $request = Request::create('/'); $request->setSession($session); - $controller = array($this, 'controllerWithSessionInterface'); + $controller = [$this, 'controllerWithSessionInterface']; - $this->assertEquals(array($session), self::$resolver->getArguments($request, $controller)); + $this->assertEquals([$session], self::$resolver->getArguments($request, $controller)); } - /** - * @expectedException \RuntimeException - */ public function testGetSessionMissMatchWithInterface() { + $this->expectException('RuntimeException'); $session = $this->getMockBuilder(SessionInterface::class)->getMock(); $request = Request::create('/'); $request->setSession($session); - $controller = array($this, 'controllerWithExtendingSession'); + $controller = [$this, 'controllerWithExtendingSession']; self::$resolver->getArguments($request, $controller); } - /** - * @expectedException \RuntimeException - */ public function testGetSessionMissMatchWithImplementation() { + $this->expectException('RuntimeException'); $session = new Session(new MockArraySessionStorage()); $request = Request::create('/'); $request->setSession($session); - $controller = array($this, 'controllerWithExtendingSession'); + $controller = [$this, 'controllerWithExtendingSession']; self::$resolver->getArguments($request, $controller); } - /** - * @expectedException \RuntimeException - */ public function testGetSessionMissMatchOnNull() { + $this->expectException('RuntimeException'); $request = Request::create('/'); - $controller = array($this, 'controllerWithExtendingSession'); + $controller = [$this, 'controllerWithExtendingSession']; self::$resolver->getArguments($request, $controller); } diff --git a/vendor/symfony/http-kernel/Tests/Controller/ContainerControllerResolverTest.php b/vendor/symfony/http-kernel/Tests/Controller/ContainerControllerResolverTest.php index 0019123b6819c6b1c6dd964dc854f250fbb9c14e..956adb9613b6a1bf54f247d21e211117c24fbdda 100644 --- a/vendor/symfony/http-kernel/Tests/Controller/ContainerControllerResolverTest.php +++ b/vendor/symfony/http-kernel/Tests/Controller/ContainerControllerResolverTest.php @@ -13,214 +13,181 @@ namespace Symfony\Component\HttpKernel\Tests\Controller; use Psr\Container\ContainerInterface; use Psr\Log\LoggerInterface; -use Symfony\Component\Debug\ErrorHandler; use Symfony\Component\DependencyInjection\Container; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\Controller\ContainerControllerResolver; class ContainerControllerResolverTest extends ControllerResolverTest { - public function testGetControllerService() + public function testGetControllerServiceWithSingleColon() { + $service = new ControllerTestService('foo'); + $container = $this->createMockContainer(); $container->expects($this->once()) ->method('has') ->with('foo') - ->will($this->returnValue(true)); + ->willReturn(true); $container->expects($this->once()) ->method('get') ->with('foo') - ->will($this->returnValue($this)) + ->willReturn($service) ; $resolver = $this->createControllerResolver(null, $container); $request = Request::create('/'); - $request->attributes->set('_controller', 'foo:controllerMethod1'); + $request->attributes->set('_controller', 'foo:action'); $controller = $resolver->getController($request); - $this->assertInstanceOf(get_class($this), $controller[0]); - $this->assertSame('controllerMethod1', $controller[1]); + $this->assertSame($service, $controller[0]); + $this->assertSame('action', $controller[1]); } - public function testGetControllerInvokableService() + public function testGetControllerService() { - $invokableController = new InvokableController('bar'); + $service = new ControllerTestService('foo'); $container = $this->createMockContainer(); $container->expects($this->once()) ->method('has') ->with('foo') - ->will($this->returnValue(true)) - ; + ->willReturn(true); $container->expects($this->once()) ->method('get') ->with('foo') - ->will($this->returnValue($invokableController)) + ->willReturn($service) ; $resolver = $this->createControllerResolver(null, $container); $request = Request::create('/'); - $request->attributes->set('_controller', 'foo'); + $request->attributes->set('_controller', 'foo::action'); $controller = $resolver->getController($request); - $this->assertEquals($invokableController, $controller); + $this->assertSame($service, $controller[0]); + $this->assertSame('action', $controller[1]); } - public function testGetControllerInvokableServiceWithClassNameAsName() + public function testGetControllerInvokableService() { - $invokableController = new InvokableController('bar'); - $className = __NAMESPACE__.'\InvokableController'; + $service = new InvokableControllerService('bar'); $container = $this->createMockContainer(); $container->expects($this->once()) ->method('has') - ->with($className) - ->will($this->returnValue(true)) + ->with('foo') + ->willReturn(true) ; $container->expects($this->once()) ->method('get') - ->with($className) - ->will($this->returnValue($invokableController)) + ->with('foo') + ->willReturn($service) ; $resolver = $this->createControllerResolver(null, $container); $request = Request::create('/'); - $request->attributes->set('_controller', $className); + $request->attributes->set('_controller', 'foo'); $controller = $resolver->getController($request); - $this->assertEquals($invokableController, $controller); + $this->assertSame($service, $controller); } - public function testNonInstantiableController() + public function testGetControllerInvokableServiceWithClassNameAsName() { + $service = new InvokableControllerService('bar'); + $container = $this->createMockContainer(); $container->expects($this->once()) ->method('has') - ->with(NonInstantiableController::class) - ->will($this->returnValue(false)) + ->with(InvokableControllerService::class) + ->willReturn(true) + ; + $container->expects($this->once()) + ->method('get') + ->with(InvokableControllerService::class) + ->willReturn($service) ; $resolver = $this->createControllerResolver(null, $container); $request = Request::create('/'); - $request->attributes->set('_controller', array(NonInstantiableController::class, 'action')); + $request->attributes->set('_controller', InvokableControllerService::class); $controller = $resolver->getController($request); - $this->assertSame(array(NonInstantiableController::class, 'action'), $controller); + $this->assertSame($service, $controller); } /** - * @expectedException \LogicException - * @expectedExceptionMessage Controller "Symfony\Component\HttpKernel\Tests\Controller\ImpossibleConstructController" cannot be fetched from the container because it is private. Did you forget to tag the service with "controller.service_arguments"? + * @dataProvider getControllers */ - public function testNonConstructController() + public function testInstantiateControllerWhenControllerStartsWithABackslash($controller) { - $container = $this->getMockBuilder(Container::class)->getMock(); - $container->expects($this->at(0)) - ->method('has') - ->with(ImpossibleConstructController::class) - ->will($this->returnValue(true)) - ; - - $container->expects($this->at(1)) - ->method('has') - ->with(ImpossibleConstructController::class) - ->will($this->returnValue(false)) - ; - - $container->expects($this->atLeastOnce()) - ->method('getRemovedIds') - ->with() - ->will($this->returnValue(array(ImpossibleConstructController::class => true))) - ; - - $resolver = $this->createControllerResolver(null, $container); - $request = Request::create('/'); - $request->attributes->set('_controller', array(ImpossibleConstructController::class, 'action')); - - if (\PHP_VERSION_ID < 70100) { - ErrorHandler::register(); - try { - $resolver->getController($request); - } finally { - restore_error_handler(); - restore_exception_handler(); - } - } else { - $resolver->getController($request); - } - } - - public function testNonInstantiableControllerWithCorrespondingService() - { - $service = new \stdClass(); + $service = new ControllerTestService('foo'); + $class = ControllerTestService::class; $container = $this->createMockContainer(); - $container->expects($this->atLeastOnce()) - ->method('has') - ->with(NonInstantiableController::class) - ->will($this->returnValue(true)) - ; - $container->expects($this->atLeastOnce()) - ->method('get') - ->with(NonInstantiableController::class) - ->will($this->returnValue($service)) - ; + $container->expects($this->once())->method('has')->with($class)->willReturn(true); + $container->expects($this->once())->method('get')->with($class)->willReturn($service); $resolver = $this->createControllerResolver(null, $container); $request = Request::create('/'); - $request->attributes->set('_controller', array(NonInstantiableController::class, 'action')); + $request->attributes->set('_controller', $controller); $controller = $resolver->getController($request); - $this->assertSame(array($service, 'action'), $controller); + $this->assertInstanceOf(ControllerTestService::class, $controller[0]); + $this->assertSame('action', $controller[1]); } - /** - * @expectedException \LogicException - * @expectedExceptionMessage Controller "app.my_controller" cannot be fetched from the container because it is private. Did you forget to tag the service with "controller.service_arguments"? - */ - public function testExceptionWhenUsingRemovedControllerService() + public function getControllers() { + return [ + ['\\'.ControllerTestService::class.'::action'], + ['\\'.ControllerTestService::class.':action'], + ]; + } + + public function testExceptionWhenUsingRemovedControllerServiceWithClassNameAsName() + { + $this->expectException('InvalidArgumentException'); + $this->expectExceptionMessage('Controller "Symfony\Component\HttpKernel\Tests\Controller\ControllerTestService" cannot be fetched from the container because it is private. Did you forget to tag the service with "controller.service_arguments"?'); $container = $this->getMockBuilder(Container::class)->getMock(); - $container->expects($this->at(0)) + $container->expects($this->once()) ->method('has') - ->with('app.my_controller') - ->will($this->returnValue(false)) + ->with(ControllerTestService::class) + ->willReturn(false) ; $container->expects($this->atLeastOnce()) ->method('getRemovedIds') ->with() - ->will($this->returnValue(array('app.my_controller' => true))) + ->willReturn([ControllerTestService::class => true]) ; $resolver = $this->createControllerResolver(null, $container); - $request = Request::create('/'); - $request->attributes->set('_controller', 'app.my_controller'); + $request->attributes->set('_controller', [ControllerTestService::class, 'action']); + $resolver->getController($request); } - /** - * @expectedException \LogicException - * @expectedExceptionMessage Controller "app.my_controller" cannot be called without a method name. Did you forget an "__invoke" method? - */ - public function testExceptionWhenUsingControllerWithoutAnInvokeMethod() + public function testExceptionWhenUsingRemovedControllerService() { + $this->expectException('InvalidArgumentException'); + $this->expectExceptionMessage('Controller "app.my_controller" cannot be fetched from the container because it is private. Did you forget to tag the service with "controller.service_arguments"?'); $container = $this->getMockBuilder(Container::class)->getMock(); $container->expects($this->once()) ->method('has') ->with('app.my_controller') - ->will($this->returnValue(true)) + ->willReturn(false) ; - $container->expects($this->once()) - ->method('get') - ->with('app.my_controller') - ->will($this->returnValue(new ImpossibleConstructController('toto', 'controller'))) + + $container->expects($this->atLeastOnce()) + ->method('getRemovedIds') + ->with() + ->willReturn(['app.my_controller' => true]) ; $resolver = $this->createControllerResolver(null, $container); @@ -230,37 +197,28 @@ class ContainerControllerResolverTest extends ControllerResolverTest $resolver->getController($request); } - /** - * @dataProvider getUndefinedControllers - */ - public function testGetControllerOnNonUndefinedFunction($controller, $exceptionName = null, $exceptionMessage = null) - { - // All this logic needs to be duplicated, since calling parent::testGetControllerOnNonUndefinedFunction will override the expected excetion and not use the regex - $resolver = $this->createControllerResolver(); - if (method_exists($this, 'expectException')) { - $this->expectException($exceptionName); - $this->expectExceptionMessageRegExp($exceptionMessage); - } else { - $this->setExpectedExceptionRegExp($exceptionName, $exceptionMessage); - } - - $request = Request::create('/'); - $request->attributes->set('_controller', $controller); - $resolver->getController($request); - } - public function getUndefinedControllers() { - return array( - array('foo', \LogicException::class, '/Controller not found: service "foo" does not exist\./'), - array('oof::bar', \InvalidArgumentException::class, '/Class "oof" does not exist\./'), - array('stdClass', \LogicException::class, '/Controller not found: service "stdClass" does not exist\./'), - array( - 'Symfony\Component\HttpKernel\Tests\Controller\ControllerResolverTest::bar', - \InvalidArgumentException::class, - '/.?[cC]ontroller(.*?) for URI "\/" is not callable\.( Expected method(.*) Available methods)?/', - ), - ); + $tests = parent::getUndefinedControllers(); + $tests[0] = ['foo', \InvalidArgumentException::class, 'Controller "foo" does neither exist as service nor as class']; + $tests[1] = ['oof::bar', \InvalidArgumentException::class, 'Controller "oof" does neither exist as service nor as class']; + $tests[2] = [['oof', 'bar'], \InvalidArgumentException::class, 'Controller "oof" does neither exist as service nor as class']; + $tests[] = [ + [ControllerTestService::class, 'action'], + \InvalidArgumentException::class, + 'Controller "Symfony\Component\HttpKernel\Tests\Controller\ControllerTestService" has required constructor arguments and does not exist in the container. Did you forget to define such a service?', + ]; + $tests[] = [ + ControllerTestService::class.'::action', + \InvalidArgumentException::class, 'Controller "Symfony\Component\HttpKernel\Tests\Controller\ControllerTestService" has required constructor arguments and does not exist in the container. Did you forget to define such a service?', + ]; + $tests[] = [ + InvokableControllerService::class, + \InvalidArgumentException::class, + 'Controller "Symfony\Component\HttpKernel\Tests\Controller\InvokableControllerService" has required constructor arguments and does not exist in the container. Did you forget to define such a service?', + ]; + + return $tests; } protected function createControllerResolver(LoggerInterface $logger = null, ContainerInterface $container = null) @@ -278,7 +236,7 @@ class ContainerControllerResolverTest extends ControllerResolverTest } } -class InvokableController +class InvokableControllerService { public function __construct($bar) // mandatory argument to prevent automatic instantiation { @@ -289,16 +247,9 @@ class InvokableController } } -abstract class NonInstantiableController -{ - public static function action() - { - } -} - -class ImpossibleConstructController +class ControllerTestService { - public function __construct($toto, $controller) + public function __construct($foo) { } diff --git a/vendor/symfony/http-kernel/Tests/Controller/ControllerResolverTest.php b/vendor/symfony/http-kernel/Tests/Controller/ControllerResolverTest.php index 190e15ad67bca18f6c81f8c0e9cc15a81e6bfe4a..77ce524fc60a24e5ad96104964a6da732dd2d7fb 100644 --- a/vendor/symfony/http-kernel/Tests/Controller/ControllerResolverTest.php +++ b/vendor/symfony/http-kernel/Tests/Controller/ControllerResolverTest.php @@ -13,10 +13,8 @@ namespace Symfony\Component\HttpKernel\Tests\Controller; use PHPUnit\Framework\TestCase; use Psr\Log\LoggerInterface; -use Symfony\Component\HttpKernel\Controller\ControllerResolver; -use Symfony\Component\HttpKernel\Tests\Fixtures\Controller\NullableController; -use Symfony\Component\HttpKernel\Tests\Fixtures\Controller\VariadicController; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpKernel\Controller\ControllerResolver; class ControllerResolverTest extends TestCase { @@ -43,58 +41,60 @@ class ControllerResolverTest extends TestCase public function testGetControllerWithObjectAndInvokeMethod() { $resolver = $this->createControllerResolver(); + $object = new InvokableController(); $request = Request::create('/'); - $request->attributes->set('_controller', $this); + $request->attributes->set('_controller', $object); $controller = $resolver->getController($request); - $this->assertSame($this, $controller); + $this->assertSame($object, $controller); } public function testGetControllerWithObjectAndMethod() { $resolver = $this->createControllerResolver(); + $object = new ControllerTest(); $request = Request::create('/'); - $request->attributes->set('_controller', array($this, 'controllerMethod1')); + $request->attributes->set('_controller', [$object, 'publicAction']); $controller = $resolver->getController($request); - $this->assertSame(array($this, 'controllerMethod1'), $controller); + $this->assertSame([$object, 'publicAction'], $controller); } - public function testGetControllerWithClassAndMethod() + public function testGetControllerWithClassAndMethodAsArray() { $resolver = $this->createControllerResolver(); $request = Request::create('/'); - $request->attributes->set('_controller', array('Symfony\Component\HttpKernel\Tests\Controller\ControllerResolverTest', 'controllerMethod4')); + $request->attributes->set('_controller', [ControllerTest::class, 'publicAction']); $controller = $resolver->getController($request); - $this->assertSame(array('Symfony\Component\HttpKernel\Tests\Controller\ControllerResolverTest', 'controllerMethod4'), $controller); + $this->assertInstanceOf(ControllerTest::class, $controller[0]); + $this->assertSame('publicAction', $controller[1]); } - public function testGetControllerWithObjectAndMethodAsString() + public function testGetControllerWithClassAndMethodAsString() { $resolver = $this->createControllerResolver(); $request = Request::create('/'); - $request->attributes->set('_controller', 'Symfony\Component\HttpKernel\Tests\Controller\ControllerResolverTest::controllerMethod1'); + $request->attributes->set('_controller', ControllerTest::class.'::publicAction'); $controller = $resolver->getController($request); - $this->assertInstanceOf('Symfony\Component\HttpKernel\Tests\Controller\ControllerResolverTest', $controller[0], '->getController() returns a PHP callable'); + $this->assertInstanceOf(ControllerTest::class, $controller[0]); + $this->assertSame('publicAction', $controller[1]); } - public function testGetControllerWithClassAndInvokeMethod() + public function testGetControllerWithInvokableClass() { $resolver = $this->createControllerResolver(); $request = Request::create('/'); - $request->attributes->set('_controller', 'Symfony\Component\HttpKernel\Tests\Controller\ControllerResolverTest'); + $request->attributes->set('_controller', InvokableController::class); $controller = $resolver->getController($request); - $this->assertInstanceOf('Symfony\Component\HttpKernel\Tests\Controller\ControllerResolverTest', $controller); + $this->assertInstanceOf(InvokableController::class, $controller); } - /** - * @expectedException \InvalidArgumentException - */ public function testGetControllerOnObjectWithoutInvokeMethod() { + $this->expectException('InvalidArgumentException'); $resolver = $this->createControllerResolver(); $request = Request::create('/'); @@ -112,220 +112,142 @@ class ControllerResolverTest extends TestCase $this->assertSame('Symfony\Component\HttpKernel\Tests\Controller\some_controller_function', $controller); } - /** - * @dataProvider getUndefinedControllers - */ - public function testGetControllerOnNonUndefinedFunction($controller, $exceptionName = null, $exceptionMessage = null) - { - $resolver = $this->createControllerResolver(); - if (method_exists($this, 'expectException')) { - $this->expectException($exceptionName); - $this->expectExceptionMessage($exceptionMessage); - } else { - $this->setExpectedException($exceptionName, $exceptionMessage); - } - - $request = Request::create('/'); - $request->attributes->set('_controller', $controller); - $resolver->getController($request); - } - - public function getUndefinedControllers() - { - return array( - array(1, 'InvalidArgumentException', 'Unable to find controller "1".'), - array('foo', 'InvalidArgumentException', 'Unable to find controller "foo".'), - array('oof::bar', 'InvalidArgumentException', 'Class "oof" does not exist.'), - array('stdClass', 'InvalidArgumentException', 'Unable to find controller "stdClass".'), - array('Symfony\Component\HttpKernel\Tests\Controller\ControllerTest::staticsAction', 'InvalidArgumentException', 'The controller for URI "/" is not callable. Expected method "staticsAction" on class "Symfony\Component\HttpKernel\Tests\Controller\ControllerTest", did you mean "staticAction"?'), - array('Symfony\Component\HttpKernel\Tests\Controller\ControllerTest::privateAction', 'InvalidArgumentException', 'The controller for URI "/" is not callable. Method "privateAction" on class "Symfony\Component\HttpKernel\Tests\Controller\ControllerTest" should be public and non-abstract'), - array('Symfony\Component\HttpKernel\Tests\Controller\ControllerTest::protectedAction', 'InvalidArgumentException', 'The controller for URI "/" is not callable. Method "protectedAction" on class "Symfony\Component\HttpKernel\Tests\Controller\ControllerTest" should be public and non-abstract'), - array('Symfony\Component\HttpKernel\Tests\Controller\ControllerTest::undefinedAction', 'InvalidArgumentException', 'The controller for URI "/" is not callable. Expected method "undefinedAction" on class "Symfony\Component\HttpKernel\Tests\Controller\ControllerTest". Available methods: "publicAction", "staticAction"'), - ); - } - - /** - * @group legacy - */ - public function testGetArguments() + public function testGetControllerWithClosure() { $resolver = $this->createControllerResolver(); - $request = Request::create('/'); - $controller = array(new self(), 'testGetArguments'); - $this->assertEquals(array(), $resolver->getArguments($request, $controller), '->getArguments() returns an empty array if the method takes no arguments'); + $closure = function () { + return 'test'; + }; $request = Request::create('/'); - $request->attributes->set('foo', 'foo'); - $controller = array(new self(), 'controllerMethod1'); - $this->assertEquals(array('foo'), $resolver->getArguments($request, $controller), '->getArguments() returns an array of arguments for the controller method'); - - $request = Request::create('/'); - $request->attributes->set('foo', 'foo'); - $controller = array(new self(), 'controllerMethod2'); - $this->assertEquals(array('foo', null), $resolver->getArguments($request, $controller), '->getArguments() uses default values if present'); - - $request->attributes->set('bar', 'bar'); - $this->assertEquals(array('foo', 'bar'), $resolver->getArguments($request, $controller), '->getArguments() overrides default values if provided in the request attributes'); - - $request = Request::create('/'); - $request->attributes->set('foo', 'foo'); - $controller = function ($foo) {}; - $this->assertEquals(array('foo'), $resolver->getArguments($request, $controller)); - - $request = Request::create('/'); - $request->attributes->set('foo', 'foo'); - $controller = function ($foo, $bar = 'bar') {}; - $this->assertEquals(array('foo', 'bar'), $resolver->getArguments($request, $controller)); - - $request = Request::create('/'); - $request->attributes->set('foo', 'foo'); - $controller = new self(); - $this->assertEquals(array('foo', null), $resolver->getArguments($request, $controller)); - $request->attributes->set('bar', 'bar'); - $this->assertEquals(array('foo', 'bar'), $resolver->getArguments($request, $controller)); - - $request = Request::create('/'); - $request->attributes->set('foo', 'foo'); - $request->attributes->set('foobar', 'foobar'); - $controller = 'Symfony\Component\HttpKernel\Tests\Controller\some_controller_function'; - $this->assertEquals(array('foo', 'foobar'), $resolver->getArguments($request, $controller)); - - $request = Request::create('/'); - $request->attributes->set('foo', 'foo'); - $request->attributes->set('foobar', 'foobar'); - $controller = array(new self(), 'controllerMethod3'); - - try { - $resolver->getArguments($request, $controller); - $this->fail('->getArguments() throws a \RuntimeException exception if it cannot determine the argument value'); - } catch (\Exception $e) { - $this->assertInstanceOf('\RuntimeException', $e, '->getArguments() throws a \RuntimeException exception if it cannot determine the argument value'); - } - - $request = Request::create('/'); - $controller = array(new self(), 'controllerMethod5'); - $this->assertEquals(array($request), $resolver->getArguments($request, $controller), '->getArguments() injects the request'); + $request->attributes->set('_controller', $closure); + $controller = $resolver->getController($request); + $this->assertInstanceOf(\Closure::class, $controller); + $this->assertSame('test', $controller()); } /** - * @requires PHP 5.6 - * @group legacy + * @dataProvider getStaticControllers */ - public function testGetVariadicArguments() - { - $resolver = new ControllerResolver(); - - $request = Request::create('/'); - $request->attributes->set('foo', 'foo'); - $request->attributes->set('bar', array('foo', 'bar')); - $controller = array(new VariadicController(), 'action'); - $this->assertEquals(array('foo', 'foo', 'bar'), $resolver->getArguments($request, $controller)); - } - - public function testCreateControllerCanReturnAnyCallable() + public function testGetControllerWithStaticController($staticController, $returnValue) { - $mock = $this->getMockBuilder('Symfony\Component\HttpKernel\Controller\ControllerResolver')->setMethods(array('createController'))->getMock(); - $mock->expects($this->once())->method('createController')->will($this->returnValue('Symfony\Component\HttpKernel\Tests\Controller\some_controller_function')); + $resolver = $this->createControllerResolver(); $request = Request::create('/'); - $request->attributes->set('_controller', 'foobar'); - $mock->getController($request); + $request->attributes->set('_controller', $staticController); + $controller = $resolver->getController($request); + $this->assertSame($staticController, $controller); + $this->assertSame($returnValue, $controller()); } - /** - * @expectedException \RuntimeException - * @group legacy - */ - public function testIfExceptionIsThrownWhenMissingAnArgument() + public function getStaticControllers() { - $resolver = new ControllerResolver(); - $request = Request::create('/'); - - $controller = array($this, 'controllerMethod1'); - - $resolver->getArguments($request, $controller); + return [ + [TestAbstractController::class.'::staticAction', 'foo'], + [[TestAbstractController::class, 'staticAction'], 'foo'], + [PrivateConstructorController::class.'::staticAction', 'bar'], + [[PrivateConstructorController::class, 'staticAction'], 'bar'], + ]; } /** - * @requires PHP 7.1 - * @group legacy + * @dataProvider getUndefinedControllers */ - public function testGetNullableArguments() + public function testGetControllerWithUndefinedController($controller, $exceptionName = null, $exceptionMessage = null) { - $resolver = new ControllerResolver(); + $resolver = $this->createControllerResolver(); + $this->expectException($exceptionName); + $this->expectExceptionMessage($exceptionMessage); $request = Request::create('/'); - $request->attributes->set('foo', 'foo'); - $request->attributes->set('bar', new \stdClass()); - $request->attributes->set('mandatory', 'mandatory'); - $controller = array(new NullableController(), 'action'); - $this->assertEquals(array('foo', new \stdClass(), 'value', 'mandatory'), $resolver->getArguments($request, $controller)); + $request->attributes->set('_controller', $controller); + $resolver->getController($request); } - /** - * @requires PHP 7.1 - * @group legacy - */ - public function testGetNullableArgumentsWithDefaults() + public function getUndefinedControllers() { - $resolver = new ControllerResolver(); - - $request = Request::create('/'); - $request->attributes->set('mandatory', 'mandatory'); - $controller = array(new NullableController(), 'action'); - $this->assertEquals(array(null, null, 'value', 'mandatory'), $resolver->getArguments($request, $controller)); + $controller = new ControllerTest(); + + return [ + ['foo', \Error::class, 'Class \'foo\' not found'], + ['oof::bar', \Error::class, 'Class \'oof\' not found'], + [['oof', 'bar'], \Error::class, 'Class \'oof\' not found'], + ['Symfony\Component\HttpKernel\Tests\Controller\ControllerTest::staticsAction', \InvalidArgumentException::class, 'The controller for URI "/" is not callable. Expected method "staticsAction" on class "Symfony\Component\HttpKernel\Tests\Controller\ControllerTest", did you mean "staticAction"?'], + ['Symfony\Component\HttpKernel\Tests\Controller\ControllerTest::privateAction', \InvalidArgumentException::class, 'The controller for URI "/" is not callable. Method "privateAction" on class "Symfony\Component\HttpKernel\Tests\Controller\ControllerTest" should be public and non-abstract'], + ['Symfony\Component\HttpKernel\Tests\Controller\ControllerTest::protectedAction', \InvalidArgumentException::class, 'The controller for URI "/" is not callable. Method "protectedAction" on class "Symfony\Component\HttpKernel\Tests\Controller\ControllerTest" should be public and non-abstract'], + ['Symfony\Component\HttpKernel\Tests\Controller\ControllerTest::undefinedAction', \InvalidArgumentException::class, 'The controller for URI "/" is not callable. Expected method "undefinedAction" on class "Symfony\Component\HttpKernel\Tests\Controller\ControllerTest". Available methods: "publicAction", "staticAction"'], + ['Symfony\Component\HttpKernel\Tests\Controller\ControllerTest', \InvalidArgumentException::class, 'The controller for URI "/" is not callable. Controller class "Symfony\Component\HttpKernel\Tests\Controller\ControllerTest" cannot be called without a method name. You need to implement "__invoke" or use one of the available methods: "publicAction", "staticAction".'], + [[$controller, 'staticsAction'], \InvalidArgumentException::class, 'The controller for URI "/" is not callable. Expected method "staticsAction" on class "Symfony\Component\HttpKernel\Tests\Controller\ControllerTest", did you mean "staticAction"?'], + [[$controller, 'privateAction'], \InvalidArgumentException::class, 'The controller for URI "/" is not callable. Method "privateAction" on class "Symfony\Component\HttpKernel\Tests\Controller\ControllerTest" should be public and non-abstract'], + [[$controller, 'protectedAction'], \InvalidArgumentException::class, 'The controller for URI "/" is not callable. Method "protectedAction" on class "Symfony\Component\HttpKernel\Tests\Controller\ControllerTest" should be public and non-abstract'], + [[$controller, 'undefinedAction'], \InvalidArgumentException::class, 'The controller for URI "/" is not callable. Expected method "undefinedAction" on class "Symfony\Component\HttpKernel\Tests\Controller\ControllerTest". Available methods: "publicAction", "staticAction"'], + [$controller, \InvalidArgumentException::class, 'The controller for URI "/" is not callable. Controller class "Symfony\Component\HttpKernel\Tests\Controller\ControllerTest" cannot be called without a method name. You need to implement "__invoke" or use one of the available methods: "publicAction", "staticAction".'], + [['a' => 'foo', 'b' => 'bar'], \InvalidArgumentException::class, 'The controller for URI "/" is not callable. Invalid array callable, expected [controller, method].'], + ]; } protected function createControllerResolver(LoggerInterface $logger = null) { return new ControllerResolver($logger); } +} - public function __invoke($foo, $bar = null) +function some_controller_function($foo, $foobar) +{ +} + +class ControllerTest +{ + public function __construct() { } - public function controllerMethod1($foo) + public function __toString() { + return ''; } - protected function controllerMethod2($foo, $bar = null) + public function publicAction() { } - protected function controllerMethod3($foo, $bar, $foobar) + private function privateAction() { } - protected static function controllerMethod4() + protected function protectedAction() { } - protected function controllerMethod5(Request $request) + public static function staticAction() { } } -function some_controller_function($foo, $foobar) +class InvokableController { -} - -class ControllerTest -{ - public function publicAction() + public function __invoke($foo, $bar = null) { } +} - private function privateAction() +abstract class TestAbstractController +{ + public static function staticAction() { + return 'foo'; } +} - protected function protectedAction() +class PrivateConstructorController +{ + private function __construct() { } public static function staticAction() { + return 'bar'; } } diff --git a/vendor/symfony/http-kernel/Tests/ControllerMetadata/ArgumentMetadataFactoryTest.php b/vendor/symfony/http-kernel/Tests/ControllerMetadata/ArgumentMetadataFactoryTest.php index b4b449f3586111356a3b58a78be1c21661c05210..f77b6759afa6a5cb64957f372e8fcc6584ed49eb 100644 --- a/vendor/symfony/http-kernel/Tests/ControllerMetadata/ArgumentMetadataFactoryTest.php +++ b/vendor/symfony/http-kernel/Tests/ControllerMetadata/ArgumentMetadataFactoryTest.php @@ -26,111 +26,102 @@ class ArgumentMetadataFactoryTest extends TestCase */ private $factory; - protected function setUp() + protected function setUp(): void { $this->factory = new ArgumentMetadataFactory(); } public function testSignature1() { - $arguments = $this->factory->createArgumentMetadata(array($this, 'signature1')); + $arguments = $this->factory->createArgumentMetadata([$this, 'signature1']); - $this->assertEquals(array( + $this->assertEquals([ new ArgumentMetadata('foo', self::class, false, false, null), new ArgumentMetadata('bar', 'array', false, false, null), new ArgumentMetadata('baz', 'callable', false, false, null), - ), $arguments); + ], $arguments); } public function testSignature2() { - $arguments = $this->factory->createArgumentMetadata(array($this, 'signature2')); + $arguments = $this->factory->createArgumentMetadata([$this, 'signature2']); - $this->assertEquals(array( + $this->assertEquals([ new ArgumentMetadata('foo', self::class, false, true, null, true), new ArgumentMetadata('bar', __NAMESPACE__.'\FakeClassThatDoesNotExist', false, true, null, true), new ArgumentMetadata('baz', 'Fake\ImportedAndFake', false, true, null, true), - ), $arguments); + ], $arguments); } public function testSignature3() { - $arguments = $this->factory->createArgumentMetadata(array($this, 'signature3')); + $arguments = $this->factory->createArgumentMetadata([$this, 'signature3']); - $this->assertEquals(array( + $this->assertEquals([ new ArgumentMetadata('bar', __NAMESPACE__.'\FakeClassThatDoesNotExist', false, false, null), new ArgumentMetadata('baz', 'Fake\ImportedAndFake', false, false, null), - ), $arguments); + ], $arguments); } public function testSignature4() { - $arguments = $this->factory->createArgumentMetadata(array($this, 'signature4')); + $arguments = $this->factory->createArgumentMetadata([$this, 'signature4']); - $this->assertEquals(array( + $this->assertEquals([ new ArgumentMetadata('foo', null, false, true, 'default'), new ArgumentMetadata('bar', null, false, true, 500), - new ArgumentMetadata('baz', null, false, true, array()), - ), $arguments); + new ArgumentMetadata('baz', null, false, true, []), + ], $arguments); } public function testSignature5() { - $arguments = $this->factory->createArgumentMetadata(array($this, 'signature5')); + $arguments = $this->factory->createArgumentMetadata([$this, 'signature5']); - $this->assertEquals(array( + $this->assertEquals([ new ArgumentMetadata('foo', 'array', false, true, null, true), new ArgumentMetadata('bar', null, false, false, null), - ), $arguments); + ], $arguments); } - /** - * @requires PHP 5.6 - */ public function testVariadicSignature() { - $arguments = $this->factory->createArgumentMetadata(array(new VariadicController(), 'action')); + $arguments = $this->factory->createArgumentMetadata([new VariadicController(), 'action']); - $this->assertEquals(array( + $this->assertEquals([ new ArgumentMetadata('foo', null, false, false, null), new ArgumentMetadata('bar', null, true, false, null), - ), $arguments); + ], $arguments); } - /** - * @requires PHP 7.0 - */ public function testBasicTypesSignature() { - $arguments = $this->factory->createArgumentMetadata(array(new BasicTypesController(), 'action')); + $arguments = $this->factory->createArgumentMetadata([new BasicTypesController(), 'action']); - $this->assertEquals(array( + $this->assertEquals([ new ArgumentMetadata('foo', 'string', false, false, null), new ArgumentMetadata('bar', 'int', false, false, null), new ArgumentMetadata('baz', 'float', false, false, null), - ), $arguments); + ], $arguments); } - /** - * @requires PHP 7.1 - */ public function testNullableTypesSignature() { - $arguments = $this->factory->createArgumentMetadata(array(new NullableController(), 'action')); + $arguments = $this->factory->createArgumentMetadata([new NullableController(), 'action']); - $this->assertEquals(array( + $this->assertEquals([ new ArgumentMetadata('foo', 'string', false, false, null, true), new ArgumentMetadata('bar', \stdClass::class, false, false, null, true), new ArgumentMetadata('baz', 'string', false, true, 'value', true), new ArgumentMetadata('mandatory', null, false, false, null, true), - ), $arguments); + ], $arguments); } - private function signature1(ArgumentMetadataFactoryTest $foo, array $bar, callable $baz) + private function signature1(self $foo, array $bar, callable $baz) { } - private function signature2(ArgumentMetadataFactoryTest $foo = null, FakeClassThatDoesNotExist $bar = null, ImportedAndFake $baz = null) + private function signature2(self $foo = null, FakeClassThatDoesNotExist $bar = null, ImportedAndFake $baz = null) { } @@ -138,7 +129,7 @@ class ArgumentMetadataFactoryTest extends TestCase { } - private function signature4($foo = 'default', $bar = 500, $baz = array()) + private function signature4($foo = 'default', $bar = 500, $baz = []) { } diff --git a/vendor/symfony/http-kernel/Tests/ControllerMetadata/ArgumentMetadataTest.php b/vendor/symfony/http-kernel/Tests/ControllerMetadata/ArgumentMetadataTest.php index 05351445e00aa062ff23be32bcb0fc082c8a4054..5ce4b1f76be06a3d277dc0a7bbf01dad4417cff9 100644 --- a/vendor/symfony/http-kernel/Tests/ControllerMetadata/ArgumentMetadataTest.php +++ b/vendor/symfony/http-kernel/Tests/ControllerMetadata/ArgumentMetadataTest.php @@ -32,11 +32,9 @@ class ArgumentMetadataTest extends TestCase $this->assertSame('default value', $argument->getDefaultValue()); } - /** - * @expectedException \LogicException - */ public function testDefaultValueUnavailable() { + $this->expectException('LogicException'); $argument = new ArgumentMetadata('foo', 'string', false, false, null, false); $this->assertFalse($argument->isNullable()); diff --git a/vendor/symfony/http-kernel/Tests/DataCollector/ConfigDataCollectorTest.php b/vendor/symfony/http-kernel/Tests/DataCollector/ConfigDataCollectorTest.php index 4fb36afda227106f3dbecd444509e6377f4c2c17..add100d47b7dfad321f9cc7a406af2574c34e7dd 100644 --- a/vendor/symfony/http-kernel/Tests/DataCollector/ConfigDataCollectorTest.php +++ b/vendor/symfony/http-kernel/Tests/DataCollector/ConfigDataCollectorTest.php @@ -12,11 +12,11 @@ namespace Symfony\Component\HttpKernel\Tests\DataCollector; use PHPUnit\Framework\TestCase; -use Symfony\Component\HttpKernel\DataCollector\ConfigDataCollector; -use Symfony\Component\HttpKernel\Kernel; use Symfony\Component\Config\Loader\LoaderInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpKernel\DataCollector\ConfigDataCollector; +use Symfony\Component\HttpKernel\Kernel; class ConfigDataCollectorTest extends TestCase { @@ -30,7 +30,6 @@ class ConfigDataCollectorTest extends TestCase $this->assertSame('test', $c->getEnv()); $this->assertTrue($c->isDebug()); $this->assertSame('config', $c->getName()); - $this->assertSame('testkernel', $c->getAppName()); $this->assertRegExp('~^'.preg_quote($c->getPhpVersion(), '~').'~', PHP_VERSION); $this->assertRegExp('~'.preg_quote((string) $c->getPhpVersionExtra(), '~').'$~', PHP_VERSION); $this->assertSame(PHP_INT_SIZE * 8, $c->getPhpArchitecture()); @@ -38,26 +37,37 @@ class ConfigDataCollectorTest extends TestCase $this->assertSame(date_default_timezone_get(), $c->getPhpTimezone()); $this->assertSame(Kernel::VERSION, $c->getSymfonyVersion()); $this->assertNull($c->getToken()); - $this->assertSame(extension_loaded('xdebug'), $c->hasXDebug()); - $this->assertSame(extension_loaded('Zend OPcache') && ini_get('opcache.enable'), $c->hasZendOpcache()); - $this->assertSame(extension_loaded('apcu') && ini_get('apc.enabled'), $c->hasApcu()); + $this->assertSame(\extension_loaded('xdebug'), $c->hasXDebug()); + $this->assertSame(\extension_loaded('Zend OPcache') && filter_var(ini_get('opcache.enable'), FILTER_VALIDATE_BOOLEAN), $c->hasZendOpcache()); + $this->assertSame(\extension_loaded('apcu') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN), $c->hasApcu()); } -} -class KernelForTest extends Kernel -{ - public function getName() + /** + * @group legacy + * @expectedDeprecation The "$name" argument in method "Symfony\Component\HttpKernel\DataCollector\ConfigDataCollector::__construct()" is deprecated since Symfony 4.2. + * @expectedDeprecation The "$version" argument in method "Symfony\Component\HttpKernel\DataCollector\ConfigDataCollector::__construct()" is deprecated since Symfony 4.2. + * @expectedDeprecation The method "Symfony\Component\HttpKernel\DataCollector\ConfigDataCollector::getApplicationName()" is deprecated since Symfony 4.2. + * @expectedDeprecation The method "Symfony\Component\HttpKernel\DataCollector\ConfigDataCollector::getApplicationVersion()" is deprecated since Symfony 4.2. + */ + public function testLegacy() { - return 'testkernel'; + $c = new ConfigDataCollector('name', null); + $c->collect(new Request(), new Response()); + + $this->assertSame('name', $c->getApplicationName()); + $this->assertNull($c->getApplicationVersion()); } +} +class KernelForTest extends Kernel +{ public function registerBundles() { } public function getBundles() { - return array(); + return []; } public function registerContainerConfiguration(LoaderInterface $loader) diff --git a/vendor/symfony/http-kernel/Tests/DataCollector/DataCollectorTest.php b/vendor/symfony/http-kernel/Tests/DataCollector/DataCollectorTest.php index 54fd39e0d8c8f65d57ead5c5069fd5725e79c33a..ae79a3c93c5043b8c86d4956b34fe70431068430 100644 --- a/vendor/symfony/http-kernel/Tests/DataCollector/DataCollectorTest.php +++ b/vendor/symfony/http-kernel/Tests/DataCollector/DataCollectorTest.php @@ -30,7 +30,7 @@ class DataCollectorTest extends TestCase public function testCloneVarExistingFilePath() { - $c = new CloneVarDataCollector(array($filePath = tempnam(sys_get_temp_dir(), 'clone_var_data_collector_'))); + $c = new CloneVarDataCollector([$filePath = tempnam(sys_get_temp_dir(), 'clone_var_data_collector_')]); $c->collect(new Request(), new Response()); $this->assertSame($filePath, $c->getData()[0]); diff --git a/vendor/symfony/http-kernel/Tests/DataCollector/DumpDataCollectorTest.php b/vendor/symfony/http-kernel/Tests/DataCollector/DumpDataCollectorTest.php index fc4b92b5334dc6904a306f780809fac0e08a4be0..a40a482278155052f74a184f202e43b65618ad5a 100644 --- a/vendor/symfony/http-kernel/Tests/DataCollector/DumpDataCollectorTest.php +++ b/vendor/symfony/http-kernel/Tests/DataCollector/DumpDataCollectorTest.php @@ -12,10 +12,12 @@ namespace Symfony\Component\HttpKernel\Tests\DataCollector; use PHPUnit\Framework\TestCase; -use Symfony\Component\HttpKernel\DataCollector\DumpDataCollector; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpKernel\DataCollector\DumpDataCollector; use Symfony\Component\VarDumper\Cloner\Data; +use Symfony\Component\VarDumper\Dumper\CliDumper; +use Symfony\Component\VarDumper\Server\Connection; /** * @author Nicolas Grekas <p@tchwork.com> @@ -24,7 +26,7 @@ class DumpDataCollectorTest extends TestCase { public function testDump() { - $data = new Data(array(array(123))); + $data = new Data([[123]]); $collector = new DumpDataCollector(); @@ -39,25 +41,43 @@ class DumpDataCollectorTest extends TestCase $dump[0]['data'] = preg_replace('/^.*?<pre/', '<pre', $dump[0]['data']); $dump[0]['data'] = preg_replace('/sf-dump-\d+/', 'sf-dump', $dump[0]['data']); - $xDump = array( - array( + $xDump = [ + [ 'data' => "<pre class=sf-dump id=sf-dump data-indent-pad=\" \"><span class=sf-dump-num>123</span>\n</pre><script>Sfdump(\"sf-dump\")</script>\n", 'name' => 'DumpDataCollectorTest.php', 'file' => __FILE__, 'line' => $line, 'fileExcerpt' => false, - ), - ); + ], + ]; $this->assertEquals($xDump, $dump); - $this->assertStringMatchesFormat('a:3:{i:0;a:5:{s:4:"data";%c:39:"Symfony\Component\VarDumper\Cloner\Data":%a', $collector->serialize()); + $this->assertStringMatchesFormat('%a;a:%d:{i:0;a:5:{s:4:"data";%c:39:"Symfony\Component\VarDumper\Cloner\Data":%a', serialize($collector)); $this->assertSame(0, $collector->getDumpsCount()); - $this->assertSame('a:2:{i:0;b:0;i:1;s:5:"UTF-8";}', $collector->serialize()); + $this->assertSame("O:60:\"Symfony\Component\HttpKernel\DataCollector\DumpDataCollector\":1:{s:7:\"\0*\0data\";a:2:{i:0;b:0;i:1;s:5:\"UTF-8\";}}", serialize($collector)); + } + + public function testDumpWithServerConnection() + { + $data = new Data([[123]]); + + // Server is up, server dumper is used + $serverDumper = $this->getMockBuilder(Connection::class)->disableOriginalConstructor()->getMock(); + $serverDumper->expects($this->once())->method('write')->willReturn(true); + + $collector = new DumpDataCollector(null, null, null, null, $serverDumper); + $collector->dump($data); + + // Collect doesn't re-trigger dump + ob_start(); + $collector->collect(new Request(), new Response()); + $this->assertEmpty(ob_get_clean()); + $this->assertStringMatchesFormat('%a;a:%d:{i:0;a:5:{s:4:"data";%c:39:"Symfony\Component\VarDumper\Cloner\Data":%a', serialize($collector)); } public function testCollectDefault() { - $data = new Data(array(array(123))); + $data = new Data([[123]]); $collector = new DumpDataCollector(); @@ -66,16 +86,16 @@ class DumpDataCollectorTest extends TestCase ob_start(); $collector->collect(new Request(), new Response()); - $output = ob_get_clean(); + $output = preg_replace("/\033\[[^m]*m/", '', ob_get_clean()); $this->assertSame("DumpDataCollectorTest.php on line {$line}:\n123\n", $output); $this->assertSame(1, $collector->getDumpsCount()); - $collector->serialize(); + serialize($collector); } public function testCollectHtml() { - $data = new Data(array(array(123))); + $data = new Data([[123]]); $collector = new DumpDataCollector(null, 'test://%f:%l'); @@ -98,18 +118,37 @@ EOTXT; $this->assertSame($xOutput, trim($output)); $this->assertSame(1, $collector->getDumpsCount()); - $collector->serialize(); + serialize($collector); } public function testFlush() { - $data = new Data(array(array(456))); + $data = new Data([[456]]); $collector = new DumpDataCollector(); $collector->dump($data); $line = __LINE__ - 1; ob_start(); $collector->__destruct(); - $this->assertSame("DumpDataCollectorTest.php on line {$line}:\n456\n", ob_get_clean()); + $output = preg_replace("/\033\[[^m]*m/", '', ob_get_clean()); + $this->assertSame("DumpDataCollectorTest.php on line {$line}:\n456\n", $output); + } + + public function testFlushNothingWhenDataDumperIsProvided() + { + $data = new Data([[456]]); + $dumper = new CliDumper('php://output'); + $collector = new DumpDataCollector(null, null, null, null, $dumper); + + ob_start(); + $collector->dump($data); + $line = __LINE__ - 1; + $output = preg_replace("/\033\[[^m]*m/", '', ob_get_clean()); + + $this->assertSame("DumpDataCollectorTest.php on line {$line}:\n456\n", $output); + + ob_start(); + $collector->__destruct(); + $this->assertEmpty(ob_get_clean()); } } diff --git a/vendor/symfony/http-kernel/Tests/DataCollector/ExceptionDataCollectorTest.php b/vendor/symfony/http-kernel/Tests/DataCollector/ExceptionDataCollectorTest.php index 178f1f01a3fc07fdf6d7c92c302e174e561e33a7..1e8d186cc31fc7e2e6bb8cd185ccddf9f4c3dc92 100644 --- a/vendor/symfony/http-kernel/Tests/DataCollector/ExceptionDataCollectorTest.php +++ b/vendor/symfony/http-kernel/Tests/DataCollector/ExceptionDataCollectorTest.php @@ -13,9 +13,9 @@ namespace Symfony\Component\HttpKernel\Tests\DataCollector; use PHPUnit\Framework\TestCase; use Symfony\Component\Debug\Exception\FlattenException; -use Symfony\Component\HttpKernel\DataCollector\ExceptionDataCollector; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpKernel\DataCollector\ExceptionDataCollector; class ExceptionDataCollectorTest extends TestCase { diff --git a/vendor/symfony/http-kernel/Tests/DataCollector/LoggerDataCollectorTest.php b/vendor/symfony/http-kernel/Tests/DataCollector/LoggerDataCollectorTest.php index 3dec3bd7f87a00878a9167ca2508c72f5b98a1dd..faa2c7ef3714777df6427ed4330634d12cf94968 100644 --- a/vendor/symfony/http-kernel/Tests/DataCollector/LoggerDataCollectorTest.php +++ b/vendor/symfony/http-kernel/Tests/DataCollector/LoggerDataCollectorTest.php @@ -13,7 +13,11 @@ namespace Symfony\Component\HttpKernel\Tests\DataCollector; use PHPUnit\Framework\TestCase; use Symfony\Component\Debug\Exception\SilencedErrorContext; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\RequestStack; +use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\DataCollector\LoggerDataCollector; +use Symfony\Component\HttpKernel\Log\DebugLoggerInterface; class LoggerDataCollectorTest extends TestCase { @@ -21,24 +25,64 @@ class LoggerDataCollectorTest extends TestCase { $logger = $this ->getMockBuilder('Symfony\Component\HttpKernel\Log\DebugLoggerInterface') - ->setMethods(array('countErrors', 'getLogs', 'clear')) + ->setMethods(['countErrors', 'getLogs', 'clear']) ->getMock(); - $logger->expects($this->once())->method('countErrors')->will($this->returnValue('foo')); - $logger->expects($this->exactly(2))->method('getLogs')->will($this->returnValue(array())); + $logger->expects($this->once())->method('countErrors')->willReturn(123); + $logger->expects($this->exactly(2))->method('getLogs')->willReturn([]); $c = new LoggerDataCollector($logger, __DIR__.'/'); $c->lateCollect(); $compilerLogs = $c->getCompilerLogs()->getValue('message'); - $this->assertSame(array( - array('message' => 'Removed service "Psr\Container\ContainerInterface"; reason: private alias.'), - array('message' => 'Removed service "Symfony\Component\DependencyInjection\ContainerInterface"; reason: private alias.'), - ), $compilerLogs['Symfony\Component\DependencyInjection\Compiler\RemovePrivateAliasesPass']); + $this->assertSame([ + ['message' => 'Removed service "Psr\Container\ContainerInterface"; reason: private alias.'], + ['message' => 'Removed service "Symfony\Component\DependencyInjection\ContainerInterface"; reason: private alias.'], + ], $compilerLogs['Symfony\Component\DependencyInjection\Compiler\RemovePrivateAliasesPass']); - $this->assertSame(array( - array('message' => 'Some custom logging message'), - array('message' => 'With ending :'), - ), $compilerLogs['Unknown Compiler Pass']); + $this->assertSame([ + ['message' => 'Some custom logging message'], + ['message' => 'With ending :'], + ], $compilerLogs['Unknown Compiler Pass']); + } + + public function testWithMasterRequest() + { + $masterRequest = new Request(); + $stack = new RequestStack(); + $stack->push($masterRequest); + + $logger = $this + ->getMockBuilder(DebugLoggerInterface::class) + ->setMethods(['countErrors', 'getLogs', 'clear']) + ->getMock(); + $logger->expects($this->once())->method('countErrors')->with(null); + $logger->expects($this->exactly(2))->method('getLogs')->with(null)->willReturn([]); + + $c = new LoggerDataCollector($logger, __DIR__.'/', $stack); + + $c->collect($masterRequest, new Response()); + $c->lateCollect(); + } + + public function testWithSubRequest() + { + $masterRequest = new Request(); + $subRequest = new Request(); + $stack = new RequestStack(); + $stack->push($masterRequest); + $stack->push($subRequest); + + $logger = $this + ->getMockBuilder(DebugLoggerInterface::class) + ->setMethods(['countErrors', 'getLogs', 'clear']) + ->getMock(); + $logger->expects($this->once())->method('countErrors')->with($subRequest); + $logger->expects($this->exactly(2))->method('getLogs')->with($subRequest)->willReturn([]); + + $c = new LoggerDataCollector($logger, __DIR__.'/', $stack); + + $c->collect($subRequest, new Response()); + $c->lateCollect(); } /** @@ -48,10 +92,10 @@ class LoggerDataCollectorTest extends TestCase { $logger = $this ->getMockBuilder('Symfony\Component\HttpKernel\Log\DebugLoggerInterface') - ->setMethods(array('countErrors', 'getLogs', 'clear')) + ->setMethods(['countErrors', 'getLogs', 'clear']) ->getMock(); - $logger->expects($this->once())->method('countErrors')->will($this->returnValue($nb)); - $logger->expects($this->exactly(2))->method('getLogs')->will($this->returnValue($logs)); + $logger->expects($this->once())->method('countErrors')->willReturn($nb); + $logger->expects($this->exactly(2))->method('getLogs')->willReturn($logs); $c = new LoggerDataCollector($logger); $c->lateCollect(); @@ -62,7 +106,7 @@ class LoggerDataCollectorTest extends TestCase $logs = array_map(function ($v) { if (isset($v['context']['exception'])) { $e = &$v['context']['exception']; - $e = isset($e["\0*\0message"]) ? array($e["\0*\0message"], $e["\0*\0severity"]) : array($e["\0Symfony\Component\Debug\Exception\SilencedErrorContext\0severity"]); + $e = isset($e["\0*\0message"]) ? [$e["\0*\0message"], $e["\0*\0severity"]] : [$e["\0Symfony\Component\Debug\Exception\SilencedErrorContext\0severity"]]; } return $v; @@ -80,7 +124,7 @@ class LoggerDataCollectorTest extends TestCase { $logger = $this ->getMockBuilder('Symfony\Component\HttpKernel\Log\DebugLoggerInterface') - ->setMethods(array('countErrors', 'getLogs', 'clear')) + ->setMethods(['countErrors', 'getLogs', 'clear']) ->getMock(); $logger->expects($this->once())->method('clear'); @@ -90,55 +134,55 @@ class LoggerDataCollectorTest extends TestCase public function getCollectTestData() { - yield 'simple log' => array( + yield 'simple log' => [ 1, - array(array('message' => 'foo', 'context' => array(), 'priority' => 100, 'priorityName' => 'DEBUG')), - array(array('message' => 'foo', 'context' => array(), 'priority' => 100, 'priorityName' => 'DEBUG')), + [['message' => 'foo', 'context' => [], 'priority' => 100, 'priorityName' => 'DEBUG']], + [['message' => 'foo', 'context' => [], 'priority' => 100, 'priorityName' => 'DEBUG']], 0, 0, - ); + ]; - yield 'log with a context' => array( + yield 'log with a context' => [ 1, - array(array('message' => 'foo', 'context' => array('foo' => 'bar'), 'priority' => 100, 'priorityName' => 'DEBUG')), - array(array('message' => 'foo', 'context' => array('foo' => 'bar'), 'priority' => 100, 'priorityName' => 'DEBUG')), + [['message' => 'foo', 'context' => ['foo' => 'bar'], 'priority' => 100, 'priorityName' => 'DEBUG']], + [['message' => 'foo', 'context' => ['foo' => 'bar'], 'priority' => 100, 'priorityName' => 'DEBUG']], 0, 0, - ); + ]; if (!class_exists(SilencedErrorContext::class)) { return; } - yield 'logs with some deprecations' => array( + yield 'logs with some deprecations' => [ 1, - array( - array('message' => 'foo3', 'context' => array('exception' => new \ErrorException('warning', 0, E_USER_WARNING)), 'priority' => 100, 'priorityName' => 'DEBUG'), - array('message' => 'foo', 'context' => array('exception' => new \ErrorException('deprecated', 0, E_DEPRECATED)), 'priority' => 100, 'priorityName' => 'DEBUG'), - array('message' => 'foo2', 'context' => array('exception' => new \ErrorException('deprecated', 0, E_USER_DEPRECATED)), 'priority' => 100, 'priorityName' => 'DEBUG'), - ), - array( - array('message' => 'foo3', 'context' => array('exception' => array('warning', E_USER_WARNING)), 'priority' => 100, 'priorityName' => 'DEBUG'), - array('message' => 'foo', 'context' => array('exception' => array('deprecated', E_DEPRECATED)), 'priority' => 100, 'priorityName' => 'DEBUG', 'errorCount' => 1, 'scream' => false), - array('message' => 'foo2', 'context' => array('exception' => array('deprecated', E_USER_DEPRECATED)), 'priority' => 100, 'priorityName' => 'DEBUG', 'errorCount' => 1, 'scream' => false), - ), + [ + ['message' => 'foo3', 'context' => ['exception' => new \ErrorException('warning', 0, E_USER_WARNING)], 'priority' => 100, 'priorityName' => 'DEBUG'], + ['message' => 'foo', 'context' => ['exception' => new \ErrorException('deprecated', 0, E_DEPRECATED)], 'priority' => 100, 'priorityName' => 'DEBUG'], + ['message' => 'foo2', 'context' => ['exception' => new \ErrorException('deprecated', 0, E_USER_DEPRECATED)], 'priority' => 100, 'priorityName' => 'DEBUG'], + ], + [ + ['message' => 'foo3', 'context' => ['exception' => ['warning', E_USER_WARNING]], 'priority' => 100, 'priorityName' => 'DEBUG'], + ['message' => 'foo', 'context' => ['exception' => ['deprecated', E_DEPRECATED]], 'priority' => 100, 'priorityName' => 'DEBUG', 'errorCount' => 1, 'scream' => false], + ['message' => 'foo2', 'context' => ['exception' => ['deprecated', E_USER_DEPRECATED]], 'priority' => 100, 'priorityName' => 'DEBUG', 'errorCount' => 1, 'scream' => false], + ], 2, 0, - array(100 => array('count' => 3, 'name' => 'DEBUG')), - ); + [100 => ['count' => 3, 'name' => 'DEBUG']], + ]; - yield 'logs with some silent errors' => array( + yield 'logs with some silent errors' => [ 1, - array( - array('message' => 'foo3', 'context' => array('exception' => new \ErrorException('warning', 0, E_USER_WARNING)), 'priority' => 100, 'priorityName' => 'DEBUG'), - array('message' => 'foo3', 'context' => array('exception' => new SilencedErrorContext(E_USER_WARNING, __FILE__, __LINE__)), 'priority' => 100, 'priorityName' => 'DEBUG'), - ), - array( - array('message' => 'foo3', 'context' => array('exception' => array('warning', E_USER_WARNING)), 'priority' => 100, 'priorityName' => 'DEBUG'), - array('message' => 'foo3', 'context' => array('exception' => array(E_USER_WARNING)), 'priority' => 100, 'priorityName' => 'DEBUG', 'errorCount' => 1, 'scream' => true), - ), + [ + ['message' => 'foo3', 'context' => ['exception' => new \ErrorException('warning', 0, E_USER_WARNING)], 'priority' => 100, 'priorityName' => 'DEBUG'], + ['message' => 'foo3', 'context' => ['exception' => new SilencedErrorContext(E_USER_WARNING, __FILE__, __LINE__)], 'priority' => 100, 'priorityName' => 'DEBUG'], + ], + [ + ['message' => 'foo3', 'context' => ['exception' => ['warning', E_USER_WARNING]], 'priority' => 100, 'priorityName' => 'DEBUG'], + ['message' => 'foo3', 'context' => ['exception' => [E_USER_WARNING]], 'priority' => 100, 'priorityName' => 'DEBUG', 'errorCount' => 1, 'scream' => true], + ], 0, 1, - ); + ]; } } diff --git a/vendor/symfony/http-kernel/Tests/DataCollector/MemoryDataCollectorTest.php b/vendor/symfony/http-kernel/Tests/DataCollector/MemoryDataCollectorTest.php index ab78e9e8e178fcae552a78fa96aa56f50bd2f103..63dd62ce7039224ea82e670a3bbe3edb8de87639 100644 --- a/vendor/symfony/http-kernel/Tests/DataCollector/MemoryDataCollectorTest.php +++ b/vendor/symfony/http-kernel/Tests/DataCollector/MemoryDataCollectorTest.php @@ -12,9 +12,9 @@ namespace Symfony\Component\HttpKernel\Tests\DataCollector; use PHPUnit\Framework\TestCase; -use Symfony\Component\HttpKernel\DataCollector\MemoryDataCollector; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpKernel\DataCollector\MemoryDataCollector; class MemoryDataCollectorTest extends TestCase { @@ -23,8 +23,8 @@ class MemoryDataCollectorTest extends TestCase $collector = new MemoryDataCollector(); $collector->collect(new Request(), new Response()); - $this->assertInternalType('integer', $collector->getMemory()); - $this->assertInternalType('integer', $collector->getMemoryLimit()); + $this->assertIsInt($collector->getMemory()); + $this->assertIsInt($collector->getMemoryLimit()); $this->assertSame('memory', $collector->getName()); } @@ -39,21 +39,21 @@ class MemoryDataCollectorTest extends TestCase public function getBytesConversionTestData() { - return array( - array('2k', 2048), - array('2 k', 2048), - array('8m', 8 * 1024 * 1024), - array('+2 k', 2048), - array('+2???k', 2048), - array('0x10', 16), - array('0xf', 15), - array('010', 8), - array('+0x10 k', 16 * 1024), - array('1g', 1024 * 1024 * 1024), - array('1G', 1024 * 1024 * 1024), - array('-1', -1), - array('0', 0), - array('2mk', 2048), // the unit must be the last char, so in this case 'k', not 'm' - ); + return [ + ['2k', 2048], + ['2 k', 2048], + ['8m', 8 * 1024 * 1024], + ['+2 k', 2048], + ['+2???k', 2048], + ['0x10', 16], + ['0xf', 15], + ['010', 8], + ['+0x10 k', 16 * 1024], + ['1g', 1024 * 1024 * 1024], + ['1G', 1024 * 1024 * 1024], + ['-1', -1], + ['0', 0], + ['2mk', 2048], // the unit must be the last char, so in this case 'k', not 'm' + ]; } } diff --git a/vendor/symfony/http-kernel/Tests/DataCollector/RequestDataCollectorTest.php b/vendor/symfony/http-kernel/Tests/DataCollector/RequestDataCollectorTest.php index 69bef76d413527a98e1ffe00f8c060c657818cc9..42215ea0f76196a1406c7a11eb890eb4402dd91c 100644 --- a/vendor/symfony/http-kernel/Tests/DataCollector/RequestDataCollectorTest.php +++ b/vendor/symfony/http-kernel/Tests/DataCollector/RequestDataCollectorTest.php @@ -12,20 +12,20 @@ namespace Symfony\Component\HttpKernel\Tests\DataCollector; use PHPUnit\Framework\TestCase; +use Symfony\Component\EventDispatcher\EventDispatcher; +use Symfony\Component\HttpFoundation\Cookie; use Symfony\Component\HttpFoundation\ParameterBag; use Symfony\Component\HttpFoundation\RedirectResponse; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Session\Session; use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage; use Symfony\Component\HttpKernel\Controller\ArgumentResolverInterface; -use Symfony\Component\HttpKernel\Event\FilterResponseEvent; +use Symfony\Component\HttpKernel\DataCollector\RequestDataCollector; +use Symfony\Component\HttpKernel\Event\ControllerEvent; +use Symfony\Component\HttpKernel\Event\ResponseEvent; use Symfony\Component\HttpKernel\HttpKernel; use Symfony\Component\HttpKernel\HttpKernelInterface; -use Symfony\Component\HttpKernel\DataCollector\RequestDataCollector; -use Symfony\Component\HttpKernel\Event\FilterControllerEvent; -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\HttpFoundation\Cookie; -use Symfony\Component\EventDispatcher\EventDispatcher; class RequestDataCollectorTest extends TestCase { @@ -48,8 +48,8 @@ class RequestDataCollectorTest extends TestCase $this->assertInstanceOf(ParameterBag::class, $c->getResponseCookies()); $this->assertSame('html', $c->getFormat()); $this->assertEquals('foobar', $c->getRoute()); - $this->assertEquals(array('name' => 'foo'), $c->getRouteParams()); - $this->assertSame(array(), $c->getSessionAttributes()); + $this->assertEquals(['name' => 'foo'], $c->getRouteParams()); + $this->assertSame([], $c->getSessionAttributes()); $this->assertSame('en', $c->getLocale()); $this->assertContains(__FILE__, $attributes->get('resource')); $this->assertSame('stdClass', $attributes->get('object')->getType()); @@ -62,13 +62,13 @@ class RequestDataCollectorTest extends TestCase public function testCollectWithoutRouteParams() { - $request = $this->createRequest(array()); + $request = $this->createRequest([]); $c = new RequestDataCollector(); $c->collect($request, $this->createResponse()); $c->lateCollect(); - $this->assertEquals(array(), $c->getRouteParams()); + $this->assertEquals([], $c->getRouteParams()); } /** @@ -94,95 +94,95 @@ class RequestDataCollectorTest extends TestCase $r3 = new \ReflectionClass($this); // test name, callable, expected - return array( - array( + return [ + [ '"Regular" callable', - array($this, 'testControllerInspection'), - array( + [$this, 'testControllerInspection'], + [ 'class' => __NAMESPACE__.'\RequestDataCollectorTest', 'method' => 'testControllerInspection', 'file' => __FILE__, 'line' => $r1->getStartLine(), - ), - ), + ], + ], - array( + [ 'Closure', function () { return 'foo'; }, - array( + [ 'class' => __NAMESPACE__.'\{closure}', 'method' => null, 'file' => __FILE__, 'line' => __LINE__ - 5, - ), - ), + ], + ], - array( + [ 'Static callback as string', __NAMESPACE__.'\RequestDataCollectorTest::staticControllerMethod', - array( + [ 'class' => 'Symfony\Component\HttpKernel\Tests\DataCollector\RequestDataCollectorTest', 'method' => 'staticControllerMethod', 'file' => __FILE__, 'line' => $r2->getStartLine(), - ), - ), + ], + ], - array( + [ 'Static callable with instance', - array($this, 'staticControllerMethod'), - array( + [$this, 'staticControllerMethod'], + [ 'class' => 'Symfony\Component\HttpKernel\Tests\DataCollector\RequestDataCollectorTest', 'method' => 'staticControllerMethod', 'file' => __FILE__, 'line' => $r2->getStartLine(), - ), - ), + ], + ], - array( + [ 'Static callable with class name', - array('Symfony\Component\HttpKernel\Tests\DataCollector\RequestDataCollectorTest', 'staticControllerMethod'), - array( + ['Symfony\Component\HttpKernel\Tests\DataCollector\RequestDataCollectorTest', 'staticControllerMethod'], + [ 'class' => 'Symfony\Component\HttpKernel\Tests\DataCollector\RequestDataCollectorTest', 'method' => 'staticControllerMethod', 'file' => __FILE__, 'line' => $r2->getStartLine(), - ), - ), + ], + ], - array( + [ 'Callable with instance depending on __call()', - array($this, 'magicMethod'), - array( + [$this, 'magicMethod'], + [ 'class' => 'Symfony\Component\HttpKernel\Tests\DataCollector\RequestDataCollectorTest', 'method' => 'magicMethod', 'file' => 'n/a', 'line' => 'n/a', - ), - ), + ], + ], - array( + [ 'Callable with class name depending on __callStatic()', - array('Symfony\Component\HttpKernel\Tests\DataCollector\RequestDataCollectorTest', 'magicMethod'), - array( + ['Symfony\Component\HttpKernel\Tests\DataCollector\RequestDataCollectorTest', 'magicMethod'], + [ 'class' => 'Symfony\Component\HttpKernel\Tests\DataCollector\RequestDataCollectorTest', 'method' => 'magicMethod', 'file' => 'n/a', 'line' => 'n/a', - ), - ), + ], + ], - array( + [ 'Invokable controller', $this, - array( + [ 'class' => 'Symfony\Component\HttpKernel\Tests\DataCollector\RequestDataCollectorTest', 'method' => null, 'file' => __FILE__, 'line' => $r3->getStartLine(), - ), - ), - ); + ], + ], + ]; } public function testItIgnoresInvalidCallables() @@ -199,14 +199,14 @@ class RequestDataCollectorTest extends TestCase public function testItAddsRedirectedAttributesWhenRequestContainsSpecificCookie() { $request = $this->createRequest(); - $request->cookies->add(array( + $request->cookies->add([ 'sf_redirect' => '{}', - )); + ]); $kernel = $this->getMockBuilder(HttpKernelInterface::class)->getMock(); $c = new RequestDataCollector(); - $c->onKernelResponse(new FilterResponseEvent($kernel, $request, HttpKernelInterface::MASTER_REQUEST, $this->createResponse())); + $c->onKernelResponse(new ResponseEvent($kernel, $request, HttpKernelInterface::MASTER_REQUEST, $this->createResponse())); $this->assertTrue($request->attributes->get('_redirected')); } @@ -225,6 +225,8 @@ class RequestDataCollectorTest extends TestCase $cookie = $this->getCookieByName($response, 'sf_redirect'); $this->assertNotEmpty($cookie->getValue()); + $this->assertSame('lax', $cookie->getSameSite()); + $this->assertFalse($cookie->isSecure()); } public function testItCollectsTheRedirectionAndClearTheCookie() @@ -233,9 +235,9 @@ class RequestDataCollectorTest extends TestCase $request = $this->createRequest(); $request->attributes->set('_redirected', true); - $request->cookies->add(array( + $request->cookies->add([ 'sf_redirect' => '{"method": "POST"}', - )); + ]); $c->collect($request, $response = $this->createResponse()); $c->lateCollect(); @@ -246,7 +248,7 @@ class RequestDataCollectorTest extends TestCase $this->assertNull($cookie->getValue()); } - protected function createRequest($routeParams = array('name' => 'foo')) + protected function createRequest($routeParams = ['name' => 'foo']) { $request = Request::create('http://test.com/foo?bar=baz'); $request->attributes->set('foo', 'bar'); @@ -274,9 +276,9 @@ class RequestDataCollectorTest extends TestCase $response->setStatusCode(200); $response->headers->set('Content-Type', 'application/json'); $response->headers->set('X-Foo-Bar', null); - $response->headers->setCookie(new Cookie('foo', 'bar', 1, '/foo', 'localhost', true, true)); - $response->headers->setCookie(new Cookie('bar', 'foo', new \DateTime('@946684800'))); - $response->headers->setCookie(new Cookie('bazz', 'foo', '2000-12-12')); + $response->headers->setCookie(new Cookie('foo', 'bar', 1, '/foo', 'localhost', true, true, false, null)); + $response->headers->setCookie(new Cookie('bar', 'foo', new \DateTime('@946684800'), '/', null, false, true, false, null)); + $response->headers->setCookie(new Cookie('bazz', 'foo', '2000-12-12', '/', null, false, true, false, null)); return $response; } @@ -288,7 +290,7 @@ class RequestDataCollectorTest extends TestCase { $resolver = $this->getMockBuilder('Symfony\\Component\\HttpKernel\\Controller\\ControllerResolverInterface')->getMock(); $httpKernel = new HttpKernel(new EventDispatcher(), $resolver, null, $this->getMockBuilder(ArgumentResolverInterface::class)->getMock()); - $event = new FilterControllerEvent($httpKernel, $controller, $request, HttpKernelInterface::MASTER_REQUEST); + $event = new ControllerEvent($httpKernel, $controller, $request, HttpKernelInterface::MASTER_REQUEST); $collector->onKernelController($event); } @@ -331,4 +333,58 @@ class RequestDataCollectorTest extends TestCase throw new \InvalidArgumentException(sprintf('Cookie named "%s" is not in response', $name)); } + + /** + * @dataProvider provideJsonContentTypes + */ + public function testIsJson($contentType, $expected) + { + $response = $this->createResponse(); + $request = $this->createRequest(); + $request->headers->set('Content-Type', $contentType); + + $c = new RequestDataCollector(); + $c->collect($request, $response); + + $this->assertSame($expected, $c->isJsonRequest()); + } + + public function provideJsonContentTypes() + { + return [ + ['text/csv', false], + ['application/json', true], + ['application/JSON', true], + ['application/hal+json', true], + ['application/xml+json', true], + ['application/xml', false], + ['', false], + ]; + } + + /** + * @dataProvider providePrettyJson + */ + public function testGetPrettyJsonValidity($content, $expected) + { + $response = $this->createResponse(); + $request = Request::create('/', 'POST', [], [], [], [], $content); + + $c = new RequestDataCollector(); + $c->collect($request, $response); + + $this->assertSame($expected, $c->getPrettyJson()); + } + + public function providePrettyJson() + { + return [ + ['null', 'null'], + ['{ "foo": "bar" }', '{ + "foo": "bar" +}'], + ['{ "abc" }', null], + ['', null], + ]; + } } diff --git a/vendor/symfony/http-kernel/Tests/DataCollector/TimeDataCollectorTest.php b/vendor/symfony/http-kernel/Tests/DataCollector/TimeDataCollectorTest.php index 8048cc37a5fd03e9a04e2240ac8f2f1b0d6bde91..9de9eb599ad619ee451c80afd8a2ec0b835ff014 100644 --- a/vendor/symfony/http-kernel/Tests/DataCollector/TimeDataCollectorTest.php +++ b/vendor/symfony/http-kernel/Tests/DataCollector/TimeDataCollectorTest.php @@ -12,9 +12,10 @@ namespace Symfony\Component\HttpKernel\Tests\DataCollector; use PHPUnit\Framework\TestCase; -use Symfony\Component\HttpKernel\DataCollector\TimeDataCollector; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpKernel\DataCollector\TimeDataCollector; +use Symfony\Component\Stopwatch\Stopwatch; /** * @group time-sensitive @@ -43,7 +44,7 @@ class TimeDataCollectorTest extends TestCase $this->assertEquals(0, $c->getStartTime()); $kernel = $this->getMockBuilder('Symfony\Component\HttpKernel\KernelInterface')->getMock(); - $kernel->expects($this->once())->method('getStartTime')->will($this->returnValue(123456)); + $kernel->expects($this->once())->method('getStartTime')->willReturn(123456.0); $c = new TimeDataCollector($kernel); $request = new Request(); @@ -51,5 +52,6 @@ class TimeDataCollectorTest extends TestCase $c->collect($request, new Response()); $this->assertEquals(123456000, $c->getStartTime()); + $this->assertSame(class_exists(Stopwatch::class, false), $c->isStopwatchInstalled()); } } diff --git a/vendor/symfony/http-kernel/Tests/DataCollector/Util/ValueExporterTest.php b/vendor/symfony/http-kernel/Tests/DataCollector/Util/ValueExporterTest.php deleted file mode 100644 index 5fe92d60e04912ebb8d1120d94772dbac4df7547..0000000000000000000000000000000000000000 --- a/vendor/symfony/http-kernel/Tests/DataCollector/Util/ValueExporterTest.php +++ /dev/null @@ -1,51 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Tests\DataCollector\Util; - -use PHPUnit\Framework\TestCase; -use Symfony\Component\HttpKernel\DataCollector\Util\ValueExporter; - -/** - * @group legacy - */ -class ValueExporterTest extends TestCase -{ - /** - * @var ValueExporter - */ - private $valueExporter; - - protected function setUp() - { - $this->valueExporter = new ValueExporter(); - } - - public function testDateTime() - { - $dateTime = new \DateTime('2014-06-10 07:35:40', new \DateTimeZone('UTC')); - $this->assertSame('Object(DateTime) - 2014-06-10T07:35:40+00:00', $this->valueExporter->exportValue($dateTime)); - } - - public function testDateTimeImmutable() - { - $dateTime = new \DateTimeImmutable('2014-06-10 07:35:40', new \DateTimeZone('UTC')); - $this->assertSame('Object(DateTimeImmutable) - 2014-06-10T07:35:40+00:00', $this->valueExporter->exportValue($dateTime)); - } - - public function testIncompleteClass() - { - $foo = new \__PHP_Incomplete_Class(); - $array = new \ArrayObject($foo); - $array['__PHP_Incomplete_Class_Name'] = 'AppBundle/Foo'; - $this->assertSame('__PHP_Incomplete_Class(AppBundle/Foo)', $this->valueExporter->exportValue($foo)); - } -} diff --git a/vendor/symfony/http-kernel/Tests/Debug/FileLinkFormatterTest.php b/vendor/symfony/http-kernel/Tests/Debug/FileLinkFormatterTest.php index d616098a545c733f2842ff1219089ddb6404ecfe..1f4d298bf37680a0b48ac3c26eabc5a08502ba43 100644 --- a/vendor/symfony/http-kernel/Tests/Debug/FileLinkFormatterTest.php +++ b/vendor/symfony/http-kernel/Tests/Debug/FileLinkFormatterTest.php @@ -27,41 +27,28 @@ class FileLinkFormatterTest extends TestCase public function testWhenFileLinkFormatAndNoRequest() { - $file = __DIR__.DIRECTORY_SEPARATOR.'file.php'; + $file = __DIR__.\DIRECTORY_SEPARATOR.'file.php'; $sut = new FileLinkFormatter('debug://open?url=file://%f&line=%l', new RequestStack()); $this->assertSame("debug://open?url=file://$file&line=3", $sut->format($file, 3)); } - public function testWhenFileLinkFormatAndRequest() - { - $file = __DIR__.DIRECTORY_SEPARATOR.'file.php'; - $baseDir = __DIR__; - $requestStack = new RequestStack(); - $request = new Request(); - $requestStack->push($request); - - $sut = new FileLinkFormatter('debug://open?url=file://%f&line=%l', $requestStack, __DIR__, '/_profiler/open?file=%f&line=%l#line%l'); - - $this->assertSame("debug://open?url=file://$file&line=3", $sut->format($file, 3)); - } - public function testWhenNoFileLinkFormatAndRequest() { - $file = __DIR__.DIRECTORY_SEPARATOR.'file.php'; + $file = __DIR__.\DIRECTORY_SEPARATOR.'file.php'; $requestStack = new RequestStack(); $request = new Request(); $requestStack->push($request); $request->server->set('SERVER_NAME', 'www.example.org'); $request->server->set('SERVER_PORT', 80); - $request->server->set('SCRIPT_NAME', '/app.php'); - $request->server->set('SCRIPT_FILENAME', '/web/app.php'); - $request->server->set('REQUEST_URI', '/app.php/example'); + $request->server->set('SCRIPT_NAME', '/index.php'); + $request->server->set('SCRIPT_FILENAME', '/public/index.php'); + $request->server->set('REQUEST_URI', '/index.php/example'); $sut = new FileLinkFormatter(null, $requestStack, __DIR__, '/_profiler/open?file=%f&line=%l#line%l'); - $this->assertSame('http://www.example.org/app.php/_profiler/open?file=file.php&line=3#line3', $sut->format($file, 3)); + $this->assertSame('http://www.example.org/_profiler/open?file=file.php&line=3#line3', $sut->format($file, 3)); } } diff --git a/vendor/symfony/http-kernel/Tests/Debug/TraceableEventDispatcherTest.php b/vendor/symfony/http-kernel/Tests/Debug/TraceableEventDispatcherTest.php index aaa82d524cc6bd16a4a12ff764732de571a87238..cf8a3b8a1e0018df2dfa69f7156c55f0337562a3 100644 --- a/vendor/symfony/http-kernel/Tests/Debug/TraceableEventDispatcherTest.php +++ b/vendor/symfony/http-kernel/Tests/Debug/TraceableEventDispatcherTest.php @@ -12,12 +12,13 @@ namespace Symfony\Component\HttpKernel\Tests\Debug; use PHPUnit\Framework\TestCase; +use Symfony\Component\EventDispatcher\Event; use Symfony\Component\EventDispatcher\EventDispatcher; +use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\RequestStack; +use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\Debug\TraceableEventDispatcher; use Symfony\Component\HttpKernel\HttpKernel; -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\Response; use Symfony\Component\Stopwatch\Stopwatch; class TraceableEventDispatcherTest extends TestCase @@ -25,13 +26,13 @@ class TraceableEventDispatcherTest extends TestCase public function testStopwatchSections() { $dispatcher = new TraceableEventDispatcher(new EventDispatcher(), $stopwatch = new Stopwatch()); - $kernel = $this->getHttpKernel($dispatcher, function () { return new Response(); }); + $kernel = $this->getHttpKernel($dispatcher, function () { return new Response('', 200, ['X-Debug-Token' => '292e1e']); }); $request = Request::create('/'); $response = $kernel->handle($request); $kernel->terminate($request, $response); $events = $stopwatch->getSectionEvents($response->headers->get('X-Debug-Token')); - $this->assertEquals(array( + $this->assertEquals([ '__section__', 'kernel.request', 'kernel.controller', @@ -39,17 +40,17 @@ class TraceableEventDispatcherTest extends TestCase 'controller', 'kernel.response', 'kernel.terminate', - ), array_keys($events)); + ], array_keys($events)); } public function testStopwatchCheckControllerOnRequestEvent() { $stopwatch = $this->getMockBuilder('Symfony\Component\Stopwatch\Stopwatch') - ->setMethods(array('isStarted')) + ->setMethods(['isStarted']) ->getMock(); $stopwatch->expects($this->once()) ->method('isStarted') - ->will($this->returnValue(false)); + ->willReturn(false); $dispatcher = new TraceableEventDispatcher(new EventDispatcher(), $stopwatch); @@ -61,15 +62,13 @@ class TraceableEventDispatcherTest extends TestCase public function testStopwatchStopControllerOnRequestEvent() { $stopwatch = $this->getMockBuilder('Symfony\Component\Stopwatch\Stopwatch') - ->setMethods(array('isStarted', 'stop', 'stopSection')) + ->setMethods(['isStarted', 'stop']) ->getMock(); $stopwatch->expects($this->once()) ->method('isStarted') - ->will($this->returnValue(true)); + ->willReturn(true); $stopwatch->expects($this->once()) ->method('stop'); - $stopwatch->expects($this->once()) - ->method('stopSection'); $dispatcher = new TraceableEventDispatcher(new EventDispatcher(), $stopwatch); @@ -89,10 +88,10 @@ class TraceableEventDispatcherTest extends TestCase $called2 = true; }); }); - $dispatcher->dispatch('my-event'); + $dispatcher->dispatch(new Event(), 'my-event'); $this->assertTrue($called1); $this->assertFalse($called2); - $dispatcher->dispatch('my-event'); + $dispatcher->dispatch(new Event(), 'my-event'); $this->assertTrue($called2); } @@ -104,7 +103,7 @@ class TraceableEventDispatcherTest extends TestCase }; $eventDispatcher->addListener('foo', $listener1); $eventDispatcher->addListener('foo', function () {}); - $eventDispatcher->dispatch('foo'); + $eventDispatcher->dispatch(new Event(), 'foo'); $this->assertCount(1, $eventDispatcher->getListeners('foo'), 'expected listener1 to be removed'); } @@ -112,9 +111,9 @@ class TraceableEventDispatcherTest extends TestCase protected function getHttpKernel($dispatcher, $controller) { $controllerResolver = $this->getMockBuilder('Symfony\Component\HttpKernel\Controller\ControllerResolverInterface')->getMock(); - $controllerResolver->expects($this->once())->method('getController')->will($this->returnValue($controller)); + $controllerResolver->expects($this->once())->method('getController')->willReturn($controller); $argumentResolver = $this->getMockBuilder('Symfony\Component\HttpKernel\Controller\ArgumentResolverInterface')->getMock(); - $argumentResolver->expects($this->once())->method('getArguments')->will($this->returnValue(array())); + $argumentResolver->expects($this->once())->method('getArguments')->willReturn([]); return new HttpKernel($dispatcher, $controllerResolver, new RequestStack(), $argumentResolver); } diff --git a/vendor/symfony/http-kernel/Tests/DependencyInjection/AddAnnotatedClassesToCachePassTest.php b/vendor/symfony/http-kernel/Tests/DependencyInjection/AddAnnotatedClassesToCachePassTest.php index a2fb6afca4da03f9749c9428fbc9ba22288210d3..914b1dd8d68e0e35b0f0a6a2c262c9a1b69fa142 100644 --- a/vendor/symfony/http-kernel/Tests/DependencyInjection/AddAnnotatedClassesToCachePassTest.php +++ b/vendor/symfony/http-kernel/Tests/DependencyInjection/AddAnnotatedClassesToCachePassTest.php @@ -24,76 +24,76 @@ class AddAnnotatedClassesToCachePassTest extends TestCase $r->setAccessible(true); $expand = $r->getClosure($pass); - $this->assertSame('Foo', $expand(array('Foo'), array())[0]); - $this->assertSame('Foo', $expand(array('\\Foo'), array())[0]); - $this->assertSame('Foo', $expand(array('Foo'), array('\\Foo'))[0]); - $this->assertSame('Foo', $expand(array('Foo'), array('Foo'))[0]); - $this->assertSame('Foo', $expand(array('\\Foo'), array('\\Foo\\Bar'))[0]); - $this->assertSame('Foo', $expand(array('Foo'), array('\\Foo\\Bar'))[0]); - $this->assertSame('Foo', $expand(array('\\Foo'), array('\\Foo\\Bar\\Acme'))[0]); + $this->assertSame('Foo', $expand(['Foo'], [])[0]); + $this->assertSame('Foo', $expand(['\\Foo'], [])[0]); + $this->assertSame('Foo', $expand(['Foo'], ['\\Foo'])[0]); + $this->assertSame('Foo', $expand(['Foo'], ['Foo'])[0]); + $this->assertSame('Foo', $expand(['\\Foo'], ['\\Foo\\Bar'])[0]); + $this->assertSame('Foo', $expand(['Foo'], ['\\Foo\\Bar'])[0]); + $this->assertSame('Foo', $expand(['\\Foo'], ['\\Foo\\Bar\\Acme'])[0]); - $this->assertSame('Foo\\Bar', $expand(array('Foo\\'), array('\\Foo\\Bar'))[0]); - $this->assertSame('Foo\\Bar\\Acme', $expand(array('Foo\\'), array('\\Foo\\Bar\\Acme'))[0]); - $this->assertEmpty($expand(array('Foo\\'), array('\\Foo'))); + $this->assertSame('Foo\\Bar', $expand(['Foo\\'], ['\\Foo\\Bar'])[0]); + $this->assertSame('Foo\\Bar\\Acme', $expand(['Foo\\'], ['\\Foo\\Bar\\Acme'])[0]); + $this->assertEmpty($expand(['Foo\\'], ['\\Foo'])); - $this->assertSame('Acme\\Foo\\Bar', $expand(array('**\\Foo\\'), array('\\Acme\\Foo\\Bar'))[0]); - $this->assertEmpty($expand(array('**\\Foo\\'), array('\\Foo\\Bar'))); - $this->assertEmpty($expand(array('**\\Foo\\'), array('\\Acme\\Foo'))); - $this->assertEmpty($expand(array('**\\Foo\\'), array('\\Foo'))); + $this->assertSame('Acme\\Foo\\Bar', $expand(['**\\Foo\\'], ['\\Acme\\Foo\\Bar'])[0]); + $this->assertEmpty($expand(['**\\Foo\\'], ['\\Foo\\Bar'])); + $this->assertEmpty($expand(['**\\Foo\\'], ['\\Acme\\Foo'])); + $this->assertEmpty($expand(['**\\Foo\\'], ['\\Foo'])); - $this->assertSame('Acme\\Foo', $expand(array('**\\Foo'), array('\\Acme\\Foo'))[0]); - $this->assertEmpty($expand(array('**\\Foo'), array('\\Acme\\Foo\\AcmeBundle'))); - $this->assertEmpty($expand(array('**\\Foo'), array('\\Acme\\FooBar\\AcmeBundle'))); + $this->assertSame('Acme\\Foo', $expand(['**\\Foo'], ['\\Acme\\Foo'])[0]); + $this->assertEmpty($expand(['**\\Foo'], ['\\Acme\\Foo\\AcmeBundle'])); + $this->assertEmpty($expand(['**\\Foo'], ['\\Acme\\FooBar\\AcmeBundle'])); - $this->assertSame('Foo\\Acme\\Bar', $expand(array('Foo\\*\\Bar'), array('\\Foo\\Acme\\Bar'))[0]); - $this->assertEmpty($expand(array('Foo\\*\\Bar'), array('\\Foo\\Acme\\Bundle\\Bar'))); + $this->assertSame('Foo\\Acme\\Bar', $expand(['Foo\\*\\Bar'], ['\\Foo\\Acme\\Bar'])[0]); + $this->assertEmpty($expand(['Foo\\*\\Bar'], ['\\Foo\\Acme\\Bundle\\Bar'])); - $this->assertSame('Foo\\Acme\\Bar', $expand(array('Foo\\**\\Bar'), array('\\Foo\\Acme\\Bar'))[0]); - $this->assertSame('Foo\\Acme\\Bundle\\Bar', $expand(array('Foo\\**\\Bar'), array('\\Foo\\Acme\\Bundle\\Bar'))[0]); + $this->assertSame('Foo\\Acme\\Bar', $expand(['Foo\\**\\Bar'], ['\\Foo\\Acme\\Bar'])[0]); + $this->assertSame('Foo\\Acme\\Bundle\\Bar', $expand(['Foo\\**\\Bar'], ['\\Foo\\Acme\\Bundle\\Bar'])[0]); - $this->assertSame('Acme\\Bar', $expand(array('*\\Bar'), array('\\Acme\\Bar'))[0]); - $this->assertEmpty($expand(array('*\\Bar'), array('\\Bar'))); - $this->assertEmpty($expand(array('*\\Bar'), array('\\Foo\\Acme\\Bar'))); + $this->assertSame('Acme\\Bar', $expand(['*\\Bar'], ['\\Acme\\Bar'])[0]); + $this->assertEmpty($expand(['*\\Bar'], ['\\Bar'])); + $this->assertEmpty($expand(['*\\Bar'], ['\\Foo\\Acme\\Bar'])); - $this->assertSame('Foo\\Acme\\Bar', $expand(array('**\\Bar'), array('\\Foo\\Acme\\Bar'))[0]); - $this->assertSame('Foo\\Acme\\Bundle\\Bar', $expand(array('**\\Bar'), array('\\Foo\\Acme\\Bundle\\Bar'))[0]); - $this->assertEmpty($expand(array('**\\Bar'), array('\\Bar'))); + $this->assertSame('Foo\\Acme\\Bar', $expand(['**\\Bar'], ['\\Foo\\Acme\\Bar'])[0]); + $this->assertSame('Foo\\Acme\\Bundle\\Bar', $expand(['**\\Bar'], ['\\Foo\\Acme\\Bundle\\Bar'])[0]); + $this->assertEmpty($expand(['**\\Bar'], ['\\Bar'])); - $this->assertSame('Foo\\Bar', $expand(array('Foo\\*'), array('\\Foo\\Bar'))[0]); - $this->assertEmpty($expand(array('Foo\\*'), array('\\Foo\\Acme\\Bar'))); + $this->assertSame('Foo\\Bar', $expand(['Foo\\*'], ['\\Foo\\Bar'])[0]); + $this->assertEmpty($expand(['Foo\\*'], ['\\Foo\\Acme\\Bar'])); - $this->assertSame('Foo\\Bar', $expand(array('Foo\\**'), array('\\Foo\\Bar'))[0]); - $this->assertSame('Foo\\Acme\\Bar', $expand(array('Foo\\**'), array('\\Foo\\Acme\\Bar'))[0]); + $this->assertSame('Foo\\Bar', $expand(['Foo\\**'], ['\\Foo\\Bar'])[0]); + $this->assertSame('Foo\\Acme\\Bar', $expand(['Foo\\**'], ['\\Foo\\Acme\\Bar'])[0]); - $this->assertSame(array('Foo\\Bar'), $expand(array('Foo\\*'), array('Foo\\Bar', 'Foo\\BarTest'))); - $this->assertSame(array('Foo\\Bar', 'Foo\\BarTest'), $expand(array('Foo\\*', 'Foo\\*Test'), array('Foo\\Bar', 'Foo\\BarTest'))); + $this->assertSame(['Foo\\Bar'], $expand(['Foo\\*'], ['Foo\\Bar', 'Foo\\BarTest'])); + $this->assertSame(['Foo\\Bar', 'Foo\\BarTest'], $expand(['Foo\\*', 'Foo\\*Test'], ['Foo\\Bar', 'Foo\\BarTest'])); $this->assertSame( 'Acme\\FooBundle\\Controller\\DefaultController', - $expand(array('**Bundle\\Controller\\'), array('\\Acme\\FooBundle\\Controller\\DefaultController'))[0] + $expand(['**Bundle\\Controller\\'], ['\\Acme\\FooBundle\\Controller\\DefaultController'])[0] ); $this->assertSame( 'FooBundle\\Controller\\DefaultController', - $expand(array('**Bundle\\Controller\\'), array('\\FooBundle\\Controller\\DefaultController'))[0] + $expand(['**Bundle\\Controller\\'], ['\\FooBundle\\Controller\\DefaultController'])[0] ); $this->assertSame( 'Acme\\FooBundle\\Controller\\Bar\\DefaultController', - $expand(array('**Bundle\\Controller\\'), array('\\Acme\\FooBundle\\Controller\\Bar\\DefaultController'))[0] + $expand(['**Bundle\\Controller\\'], ['\\Acme\\FooBundle\\Controller\\Bar\\DefaultController'])[0] ); $this->assertSame( 'Bundle\\Controller\\Bar\\DefaultController', - $expand(array('**Bundle\\Controller\\'), array('\\Bundle\\Controller\\Bar\\DefaultController'))[0] + $expand(['**Bundle\\Controller\\'], ['\\Bundle\\Controller\\Bar\\DefaultController'])[0] ); $this->assertSame( 'Acme\\Bundle\\Controller\\Bar\\DefaultController', - $expand(array('**Bundle\\Controller\\'), array('\\Acme\\Bundle\\Controller\\Bar\\DefaultController'))[0] + $expand(['**Bundle\\Controller\\'], ['\\Acme\\Bundle\\Controller\\Bar\\DefaultController'])[0] ); - $this->assertSame('Foo\\Bar', $expand(array('Foo\\Bar'), array())[0]); - $this->assertSame('Foo\\Acme\\Bar', $expand(array('Foo\\**'), array('\\Foo\\Acme\\Bar'))[0]); + $this->assertSame('Foo\\Bar', $expand(['Foo\\Bar'], [])[0]); + $this->assertSame('Foo\\Acme\\Bar', $expand(['Foo\\**'], ['\\Foo\\Acme\\Bar'])[0]); } } diff --git a/vendor/symfony/http-kernel/Tests/DependencyInjection/ControllerArgumentValueResolverPassTest.php b/vendor/symfony/http-kernel/Tests/DependencyInjection/ControllerArgumentValueResolverPassTest.php index df8977de0b4ff07d9cca85103f99863017619520..2694d002cf5b6112d4ea91cd3dec37abbffbd7dd 100644 --- a/vendor/symfony/http-kernel/Tests/DependencyInjection/ControllerArgumentValueResolverPassTest.php +++ b/vendor/symfony/http-kernel/Tests/DependencyInjection/ControllerArgumentValueResolverPassTest.php @@ -17,24 +17,25 @@ use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\HttpKernel\Controller\ArgumentResolver; use Symfony\Component\HttpKernel\DependencyInjection\ControllerArgumentValueResolverPass; +use Symfony\Component\Stopwatch\Stopwatch; class ControllerArgumentValueResolverPassTest extends TestCase { public function testServicesAreOrderedAccordingToPriority() { - $services = array( - 'n3' => array(array()), - 'n1' => array(array('priority' => 200)), - 'n2' => array(array('priority' => 100)), - ); + $services = [ + 'n3' => [[]], + 'n1' => [['priority' => 200]], + 'n2' => [['priority' => 100]], + ]; - $expected = array( + $expected = [ new Reference('n1'), new Reference('n2'), new Reference('n3'), - ); + ]; - $definition = new Definition(ArgumentResolver::class, array(null, array())); + $definition = new Definition(ArgumentResolver::class, [null, []]); $container = new ContainerBuilder(); $container->setDefinition('argument_resolver', $definition); @@ -42,18 +43,81 @@ class ControllerArgumentValueResolverPassTest extends TestCase $container->register($id)->addTag('controller.argument_value_resolver', $tag); } + $container->setParameter('kernel.debug', false); + + (new ControllerArgumentValueResolverPass())->process($container); + $this->assertEquals($expected, $definition->getArgument(1)->getValues()); + + $this->assertFalse($container->hasDefinition('n1.traceable')); + $this->assertFalse($container->hasDefinition('n2.traceable')); + $this->assertFalse($container->hasDefinition('n3.traceable')); + } + + public function testInDebugWithStopWatchDefinition() + { + $services = [ + 'n3' => [[]], + 'n1' => [['priority' => 200]], + 'n2' => [['priority' => 100]], + ]; + + $expected = [ + new Reference('n1'), + new Reference('n2'), + new Reference('n3'), + ]; + + $definition = new Definition(ArgumentResolver::class, [null, []]); + $container = new ContainerBuilder(); + $container->register('debug.stopwatch', Stopwatch::class); + $container->setDefinition('argument_resolver', $definition); + + foreach ($services as $id => list($tag)) { + $container->register($id)->addTag('controller.argument_value_resolver', $tag); + } + + $container->setParameter('kernel.debug', true); + (new ControllerArgumentValueResolverPass())->process($container); $this->assertEquals($expected, $definition->getArgument(1)->getValues()); + + $this->assertTrue($container->hasDefinition('debug.n1')); + $this->assertTrue($container->hasDefinition('debug.n2')); + $this->assertTrue($container->hasDefinition('debug.n3')); + + $this->assertTrue($container->hasDefinition('n1')); + $this->assertTrue($container->hasDefinition('n2')); + $this->assertTrue($container->hasDefinition('n3')); + } + + public function testInDebugWithouStopWatchDefinition() + { + $expected = [new Reference('n1')]; + + $definition = new Definition(ArgumentResolver::class, [null, []]); + $container = new ContainerBuilder(); + $container->register('n1')->addTag('controller.argument_value_resolver'); + $container->setDefinition('argument_resolver', $definition); + + $container->setParameter('kernel.debug', true); + + (new ControllerArgumentValueResolverPass())->process($container); + $this->assertEquals($expected, $definition->getArgument(1)->getValues()); + + $this->assertFalse($container->hasDefinition('debug.n1')); + $this->assertTrue($container->hasDefinition('n1')); } public function testReturningEmptyArrayWhenNoService() { - $definition = new Definition(ArgumentResolver::class, array(null, array())); + $definition = new Definition(ArgumentResolver::class, [null, []]); $container = new ContainerBuilder(); $container->setDefinition('argument_resolver', $definition); + $container->setParameter('kernel.debug', false); + (new ControllerArgumentValueResolverPass())->process($container); - $this->assertEquals(array(), $definition->getArgument(1)->getValues()); + $this->assertEquals([], $definition->getArgument(1)->getValues()); } public function testNoArgumentResolver() diff --git a/vendor/symfony/http-kernel/Tests/DependencyInjection/FragmentRendererPassTest.php b/vendor/symfony/http-kernel/Tests/DependencyInjection/FragmentRendererPassTest.php index d28c6eca57d92ea4bda444a9a034e48d06964eac..1d521368e1dfa36017420c94db20d0a17efade2e 100644 --- a/vendor/symfony/http-kernel/Tests/DependencyInjection/FragmentRendererPassTest.php +++ b/vendor/symfony/http-kernel/Tests/DependencyInjection/FragmentRendererPassTest.php @@ -12,8 +12,10 @@ namespace Symfony\Component\HttpKernel\Tests\DependencyInjection; use PHPUnit\Framework\TestCase; -use Symfony\Component\DependencyInjection\Definition; +use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument; +use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Reference; +use Symfony\Component\DependencyInjection\ServiceLocator; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\DependencyInjection\FragmentRendererPass; use Symfony\Component\HttpKernel\Fragment\FragmentRendererInterface; @@ -22,79 +24,42 @@ class FragmentRendererPassTest extends TestCase { /** * Tests that content rendering not implementing FragmentRendererInterface - * trigger an exception. - * - * @expectedException \InvalidArgumentException + * triggers an exception. */ public function testContentRendererWithoutInterface() { - // one service, not implementing any interface - $services = array( - 'my_content_renderer' => array(array('alias' => 'foo')), - ); - - $definition = $this->getMockBuilder('Symfony\Component\DependencyInjection\Definition')->getMock(); - - $builder = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerBuilder')->setMethods(array('hasDefinition', 'findTaggedServiceIds', 'getDefinition'))->getMock(); - $builder->expects($this->any()) - ->method('hasDefinition') - ->will($this->returnValue(true)); - - // We don't test kernel.fragment_renderer here - $builder->expects($this->atLeastOnce()) - ->method('findTaggedServiceIds') - ->will($this->returnValue($services)); - - $builder->expects($this->atLeastOnce()) - ->method('getDefinition') - ->will($this->returnValue($definition)); + $this->expectException('InvalidArgumentException'); + $builder = new ContainerBuilder(); + $fragmentHandlerDefinition = $builder->register('fragment.handler'); + $builder->register('my_content_renderer', 'Symfony\Component\DependencyInjection\Definition') + ->addTag('kernel.fragment_renderer', ['alias' => 'foo']); $pass = new FragmentRendererPass(); $pass->process($builder); + + $this->assertEquals([['addRendererService', ['foo', 'my_content_renderer']]], $fragmentHandlerDefinition->getMethodCalls()); } public function testValidContentRenderer() { - $services = array( - 'my_content_renderer' => array(array('alias' => 'foo')), - ); - - $renderer = new Definition('', array(null)); - - $definition = $this->getMockBuilder('Symfony\Component\DependencyInjection\Definition')->getMock(); - $definition->expects($this->atLeastOnce()) - ->method('getClass') - ->will($this->returnValue('Symfony\Component\HttpKernel\Tests\DependencyInjection\RendererService')); - - $builder = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerBuilder')->setMethods(array('hasDefinition', 'findTaggedServiceIds', 'getDefinition', 'getReflectionClass'))->getMock(); - $builder->expects($this->any()) - ->method('hasDefinition') - ->will($this->returnValue(true)); - - // We don't test kernel.fragment_renderer here - $builder->expects($this->atLeastOnce()) - ->method('findTaggedServiceIds') - ->will($this->returnValue($services)); - - $builder->expects($this->atLeastOnce()) - ->method('getDefinition') - ->will($this->onConsecutiveCalls($renderer, $definition)); - - $builder->expects($this->atLeastOnce()) - ->method('getReflectionClass') - ->with('Symfony\Component\HttpKernel\Tests\DependencyInjection\RendererService') - ->will($this->returnValue(new \ReflectionClass('Symfony\Component\HttpKernel\Tests\DependencyInjection\RendererService'))); + $builder = new ContainerBuilder(); + $fragmentHandlerDefinition = $builder->register('fragment.handler') + ->addArgument(null); + $builder->register('my_content_renderer', 'Symfony\Component\HttpKernel\Tests\DependencyInjection\RendererService') + ->addTag('kernel.fragment_renderer', ['alias' => 'foo']); $pass = new FragmentRendererPass(); $pass->process($builder); - $this->assertInstanceOf(Reference::class, $renderer->getArgument(0)); + $serviceLocatorDefinition = $builder->getDefinition((string) $fragmentHandlerDefinition->getArgument(0)); + $this->assertSame(ServiceLocator::class, $serviceLocatorDefinition->getClass()); + $this->assertEquals(['foo' => new ServiceClosureArgument(new Reference('my_content_renderer'))], $serviceLocatorDefinition->getArgument(0)); } } class RendererService implements FragmentRendererInterface { - public function render($uri, Request $request = null, array $options = array()) + public function render($uri, Request $request = null, array $options = []) { } diff --git a/vendor/symfony/http-kernel/Tests/DependencyInjection/LazyLoadingFragmentHandlerTest.php b/vendor/symfony/http-kernel/Tests/DependencyInjection/LazyLoadingFragmentHandlerTest.php index 73021483738f151da64c9cab7c88619ff7930727..39a1cb73b1127b5e9de5856d135ed8ba017a62d3 100644 --- a/vendor/symfony/http-kernel/Tests/DependencyInjection/LazyLoadingFragmentHandlerTest.php +++ b/vendor/symfony/http-kernel/Tests/DependencyInjection/LazyLoadingFragmentHandlerTest.php @@ -12,49 +12,24 @@ namespace Symfony\Component\HttpKernel\Tests\DependencyInjection; use PHPUnit\Framework\TestCase; -use Symfony\Component\HttpKernel\DependencyInjection\LazyLoadingFragmentHandler; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpKernel\DependencyInjection\LazyLoadingFragmentHandler; class LazyLoadingFragmentHandlerTest extends TestCase { - /** - * @group legacy - * @expectedDeprecation The Symfony\Component\HttpKernel\DependencyInjection\LazyLoadingFragmentHandler::addRendererService() method is deprecated since Symfony 3.3 and will be removed in 4.0. - */ - public function testRenderWithLegacyMapping() - { - $renderer = $this->getMockBuilder('Symfony\Component\HttpKernel\Fragment\FragmentRendererInterface')->getMock(); - $renderer->expects($this->once())->method('getName')->will($this->returnValue('foo')); - $renderer->expects($this->any())->method('render')->will($this->returnValue(new Response())); - - $requestStack = $this->getMockBuilder('Symfony\Component\HttpFoundation\RequestStack')->getMock(); - $requestStack->expects($this->any())->method('getCurrentRequest')->will($this->returnValue(Request::create('/'))); - - $container = $this->getMockBuilder('Symfony\Component\DependencyInjection\ContainerInterface')->getMock(); - $container->expects($this->once())->method('get')->will($this->returnValue($renderer)); - - $handler = new LazyLoadingFragmentHandler($container, $requestStack, false); - $handler->addRendererService('foo', 'foo'); - - $handler->render('/foo', 'foo'); - - // second call should not lazy-load anymore (see once() above on the get() method) - $handler->render('/foo', 'foo'); - } - public function testRender() { $renderer = $this->getMockBuilder('Symfony\Component\HttpKernel\Fragment\FragmentRendererInterface')->getMock(); - $renderer->expects($this->once())->method('getName')->will($this->returnValue('foo')); - $renderer->expects($this->any())->method('render')->will($this->returnValue(new Response())); + $renderer->expects($this->once())->method('getName')->willReturn('foo'); + $renderer->expects($this->any())->method('render')->willReturn(new Response()); $requestStack = $this->getMockBuilder('Symfony\Component\HttpFoundation\RequestStack')->getMock(); - $requestStack->expects($this->any())->method('getCurrentRequest')->will($this->returnValue(Request::create('/'))); + $requestStack->expects($this->any())->method('getCurrentRequest')->willReturn(Request::create('/')); $container = $this->getMockBuilder('Psr\Container\ContainerInterface')->getMock(); $container->expects($this->once())->method('has')->with('foo')->willReturn(true); - $container->expects($this->once())->method('get')->will($this->returnValue($renderer)); + $container->expects($this->once())->method('get')->willReturn($renderer); $handler = new LazyLoadingFragmentHandler($container, $requestStack, false); diff --git a/vendor/symfony/http-kernel/Tests/DependencyInjection/LoggerPassTest.php b/vendor/symfony/http-kernel/Tests/DependencyInjection/LoggerPassTest.php index b199e11dabe758a50829d0d4de63387eef3ce946..cb504877cdc447fa0eb6bc28a73305fee950e56e 100644 --- a/vendor/symfony/http-kernel/Tests/DependencyInjection/LoggerPassTest.php +++ b/vendor/symfony/http-kernel/Tests/DependencyInjection/LoggerPassTest.php @@ -13,9 +13,9 @@ namespace Symfony\Component\HttpKernel\Tests\DependencyInjection; use PHPUnit\Framework\TestCase; use Psr\Log\LoggerInterface; +use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\HttpKernel\DependencyInjection\LoggerPass; use Symfony\Component\HttpKernel\Log\Logger; -use Symfony\Component\DependencyInjection\ContainerBuilder; /** * @author Kévin Dunglas <dunglas@gmail.com> diff --git a/vendor/symfony/http-kernel/Tests/DependencyInjection/MergeExtensionConfigurationPassTest.php b/vendor/symfony/http-kernel/Tests/DependencyInjection/MergeExtensionConfigurationPassTest.php index 81fc8b455d18366b8555138e22063330b1c8e375..7af756e0b8c100c423ea1f2ed24eabf0d25bb7f2 100644 --- a/vendor/symfony/http-kernel/Tests/DependencyInjection/MergeExtensionConfigurationPassTest.php +++ b/vendor/symfony/http-kernel/Tests/DependencyInjection/MergeExtensionConfigurationPassTest.php @@ -12,44 +12,39 @@ namespace Symfony\Component\HttpKernel\Tests\DependencyInjection; use PHPUnit\Framework\TestCase; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\HttpKernel\DependencyInjection\Extension; use Symfony\Component\HttpKernel\DependencyInjection\MergeExtensionConfigurationPass; class MergeExtensionConfigurationPassTest extends TestCase { public function testAutoloadMainExtension() { - $container = $this->getMockBuilder('Symfony\\Component\\DependencyInjection\\ContainerBuilder')->setMethods(array('getExtensionConfig', 'loadFromExtension', 'getParameterBag', 'getDefinitions', 'getAliases', 'getExtensions'))->getMock(); - $params = $this->getMockBuilder('Symfony\\Component\\DependencyInjection\\ParameterBag\\ParameterBag')->getMock(); - - $container->expects($this->at(0)) - ->method('getExtensionConfig') - ->with('loaded') - ->will($this->returnValue(array(array()))); - $container->expects($this->at(1)) - ->method('getExtensionConfig') - ->with('notloaded') - ->will($this->returnValue(array())); - $container->expects($this->once()) - ->method('loadFromExtension') - ->with('notloaded', array()); - - $container->expects($this->any()) - ->method('getParameterBag') - ->will($this->returnValue($params)); - $params->expects($this->any()) - ->method('all') - ->will($this->returnValue(array())); - $container->expects($this->any()) - ->method('getDefinitions') - ->will($this->returnValue(array())); - $container->expects($this->any()) - ->method('getAliases') - ->will($this->returnValue(array())); - $container->expects($this->any()) - ->method('getExtensions') - ->will($this->returnValue(array())); - - $configPass = new MergeExtensionConfigurationPass(array('loaded', 'notloaded')); + $container = new ContainerBuilder(); + $container->registerExtension(new LoadedExtension()); + $container->registerExtension(new NotLoadedExtension()); + $container->loadFromExtension('loaded', []); + + $configPass = new MergeExtensionConfigurationPass(['loaded', 'not_loaded']); $configPass->process($container); + + $this->assertTrue($container->hasDefinition('loaded.foo')); + $this->assertTrue($container->hasDefinition('not_loaded.bar')); + } +} + +class LoadedExtension extends Extension +{ + public function load(array $configs, ContainerBuilder $container) + { + $container->register('loaded.foo'); + } +} + +class NotLoadedExtension extends Extension +{ + public function load(array $configs, ContainerBuilder $container) + { + $container->register('not_loaded.bar'); } } diff --git a/vendor/symfony/http-kernel/Tests/DependencyInjection/RegisterControllerArgumentLocatorsPassTest.php b/vendor/symfony/http-kernel/Tests/DependencyInjection/RegisterControllerArgumentLocatorsPassTest.php index 4016deb4ab294f78d2d3e269a63d2b8bdb234859..3c5b19783774f6cef54ff457ef3bd043d80eb389 100644 --- a/vendor/symfony/http-kernel/Tests/DependencyInjection/RegisterControllerArgumentLocatorsPassTest.php +++ b/vendor/symfony/http-kernel/Tests/DependencyInjection/RegisterControllerArgumentLocatorsPassTest.php @@ -13,25 +13,24 @@ namespace Symfony\Component\HttpKernel\Tests\DependencyInjection; use PHPUnit\Framework\TestCase; use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument; +use Symfony\Component\DependencyInjection\ChildDefinition; use Symfony\Component\DependencyInjection\ContainerAwareInterface; use Symfony\Component\DependencyInjection\ContainerAwareTrait; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\ContainerInterface; +use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\DependencyInjection\ServiceLocator; use Symfony\Component\DependencyInjection\TypedReference; -use Symfony\Component\DependencyInjection\Reference; use Symfony\Component\HttpKernel\DependencyInjection\RegisterControllerArgumentLocatorsPass; class RegisterControllerArgumentLocatorsPassTest extends TestCase { - /** - * @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException - * @expectedExceptionMessage Class "Symfony\Component\HttpKernel\Tests\DependencyInjection\NotFound" used for service "foo" cannot be found. - */ public function testInvalidClass() { + $this->expectException('Symfony\Component\DependencyInjection\Exception\InvalidArgumentException'); + $this->expectExceptionMessage('Class "Symfony\Component\HttpKernel\Tests\DependencyInjection\NotFound" used for service "foo" cannot be found.'); $container = new ContainerBuilder(); - $container->register('argument_resolver.service')->addArgument(array()); + $container->register('argument_resolver.service')->addArgument([]); $container->register('foo', NotFound::class) ->addTag('controller.service_arguments') @@ -41,85 +40,75 @@ class RegisterControllerArgumentLocatorsPassTest extends TestCase $pass->process($container); } - /** - * @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException - * @expectedExceptionMessage Missing "action" attribute on tag "controller.service_arguments" {"argument":"bar"} for service "foo". - */ public function testNoAction() { + $this->expectException('Symfony\Component\DependencyInjection\Exception\InvalidArgumentException'); + $this->expectExceptionMessage('Missing "action" attribute on tag "controller.service_arguments" {"argument":"bar"} for service "foo".'); $container = new ContainerBuilder(); - $container->register('argument_resolver.service')->addArgument(array()); + $container->register('argument_resolver.service')->addArgument([]); $container->register('foo', RegisterTestController::class) - ->addTag('controller.service_arguments', array('argument' => 'bar')) + ->addTag('controller.service_arguments', ['argument' => 'bar']) ; $pass = new RegisterControllerArgumentLocatorsPass(); $pass->process($container); } - /** - * @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException - * @expectedExceptionMessage Missing "argument" attribute on tag "controller.service_arguments" {"action":"fooAction"} for service "foo". - */ public function testNoArgument() { + $this->expectException('Symfony\Component\DependencyInjection\Exception\InvalidArgumentException'); + $this->expectExceptionMessage('Missing "argument" attribute on tag "controller.service_arguments" {"action":"fooAction"} for service "foo".'); $container = new ContainerBuilder(); - $container->register('argument_resolver.service')->addArgument(array()); + $container->register('argument_resolver.service')->addArgument([]); $container->register('foo', RegisterTestController::class) - ->addTag('controller.service_arguments', array('action' => 'fooAction')) + ->addTag('controller.service_arguments', ['action' => 'fooAction']) ; $pass = new RegisterControllerArgumentLocatorsPass(); $pass->process($container); } - /** - * @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException - * @expectedExceptionMessage Missing "id" attribute on tag "controller.service_arguments" {"action":"fooAction","argument":"bar"} for service "foo". - */ public function testNoService() { + $this->expectException('Symfony\Component\DependencyInjection\Exception\InvalidArgumentException'); + $this->expectExceptionMessage('Missing "id" attribute on tag "controller.service_arguments" {"action":"fooAction","argument":"bar"} for service "foo".'); $container = new ContainerBuilder(); - $container->register('argument_resolver.service')->addArgument(array()); + $container->register('argument_resolver.service')->addArgument([]); $container->register('foo', RegisterTestController::class) - ->addTag('controller.service_arguments', array('action' => 'fooAction', 'argument' => 'bar')) + ->addTag('controller.service_arguments', ['action' => 'fooAction', 'argument' => 'bar']) ; $pass = new RegisterControllerArgumentLocatorsPass(); $pass->process($container); } - /** - * @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException - * @expectedExceptionMessage Invalid "action" attribute on tag "controller.service_arguments" for service "foo": no public "barAction()" method found on class "Symfony\Component\HttpKernel\Tests\DependencyInjection\RegisterTestController". - */ public function testInvalidMethod() { + $this->expectException('Symfony\Component\DependencyInjection\Exception\InvalidArgumentException'); + $this->expectExceptionMessage('Invalid "action" attribute on tag "controller.service_arguments" for service "foo": no public "barAction()" method found on class "Symfony\Component\HttpKernel\Tests\DependencyInjection\RegisterTestController".'); $container = new ContainerBuilder(); - $container->register('argument_resolver.service')->addArgument(array()); + $container->register('argument_resolver.service')->addArgument([]); $container->register('foo', RegisterTestController::class) - ->addTag('controller.service_arguments', array('action' => 'barAction', 'argument' => 'bar', 'id' => 'bar_service')) + ->addTag('controller.service_arguments', ['action' => 'barAction', 'argument' => 'bar', 'id' => 'bar_service']) ; $pass = new RegisterControllerArgumentLocatorsPass(); $pass->process($container); } - /** - * @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException - * @expectedExceptionMessage Invalid "controller.service_arguments" tag for service "foo": method "fooAction()" has no "baz" argument on class "Symfony\Component\HttpKernel\Tests\DependencyInjection\RegisterTestController". - */ public function testInvalidArgument() { + $this->expectException('Symfony\Component\DependencyInjection\Exception\InvalidArgumentException'); + $this->expectExceptionMessage('Invalid "controller.service_arguments" tag for service "foo": method "fooAction()" has no "baz" argument on class "Symfony\Component\HttpKernel\Tests\DependencyInjection\RegisterTestController".'); $container = new ContainerBuilder(); - $container->register('argument_resolver.service')->addArgument(array()); + $container->register('argument_resolver.service')->addArgument([]); $container->register('foo', RegisterTestController::class) - ->addTag('controller.service_arguments', array('action' => 'fooAction', 'argument' => 'baz', 'id' => 'bar')) + ->addTag('controller.service_arguments', ['action' => 'fooAction', 'argument' => 'baz', 'id' => 'bar']) ; $pass = new RegisterControllerArgumentLocatorsPass(); @@ -129,7 +118,7 @@ class RegisterControllerArgumentLocatorsPassTest extends TestCase public function testAllActions() { $container = new ContainerBuilder(); - $resolver = $container->register('argument_resolver.service')->addArgument(array()); + $resolver = $container->register('argument_resolver.service')->addArgument([]); $container->register('foo', RegisterTestController::class) ->addTag('controller.service_arguments') @@ -140,61 +129,61 @@ class RegisterControllerArgumentLocatorsPassTest extends TestCase $locator = $container->getDefinition((string) $resolver->getArgument(0))->getArgument(0); - $this->assertEquals(array('foo:fooAction'), array_keys($locator)); - $this->assertInstanceof(ServiceClosureArgument::class, $locator['foo:fooAction']); + $this->assertEquals(['foo::fooAction'], array_keys($locator)); + $this->assertInstanceof(ServiceClosureArgument::class, $locator['foo::fooAction']); - $locator = $container->getDefinition((string) $locator['foo:fooAction']->getValues()[0]); + $locator = $container->getDefinition((string) $locator['foo::fooAction']->getValues()[0]); $this->assertSame(ServiceLocator::class, $locator->getClass()); $this->assertFalse($locator->isPublic()); - $expected = array('bar' => new ServiceClosureArgument(new TypedReference(ControllerDummy::class, ControllerDummy::class, RegisterTestController::class, ContainerInterface::IGNORE_ON_INVALID_REFERENCE))); + $expected = ['bar' => new ServiceClosureArgument(new TypedReference(ControllerDummy::class, ControllerDummy::class, ContainerInterface::RUNTIME_EXCEPTION_ON_INVALID_REFERENCE, 'bar'))]; $this->assertEquals($expected, $locator->getArgument(0)); } public function testExplicitArgument() { $container = new ContainerBuilder(); - $resolver = $container->register('argument_resolver.service')->addArgument(array()); + $resolver = $container->register('argument_resolver.service')->addArgument([]); $container->register('foo', RegisterTestController::class) - ->addTag('controller.service_arguments', array('action' => 'fooAction', 'argument' => 'bar', 'id' => 'bar')) - ->addTag('controller.service_arguments', array('action' => 'fooAction', 'argument' => 'bar', 'id' => 'baz')) // should be ignored, the first wins + ->addTag('controller.service_arguments', ['action' => 'fooAction', 'argument' => 'bar', 'id' => 'bar']) + ->addTag('controller.service_arguments', ['action' => 'fooAction', 'argument' => 'bar', 'id' => 'baz']) // should be ignored, the first wins ; $pass = new RegisterControllerArgumentLocatorsPass(); $pass->process($container); $locator = $container->getDefinition((string) $resolver->getArgument(0))->getArgument(0); - $locator = $container->getDefinition((string) $locator['foo:fooAction']->getValues()[0]); + $locator = $container->getDefinition((string) $locator['foo::fooAction']->getValues()[0]); - $expected = array('bar' => new ServiceClosureArgument(new TypedReference('bar', ControllerDummy::class, RegisterTestController::class))); + $expected = ['bar' => new ServiceClosureArgument(new TypedReference('bar', ControllerDummy::class, ContainerInterface::RUNTIME_EXCEPTION_ON_INVALID_REFERENCE))]; $this->assertEquals($expected, $locator->getArgument(0)); } public function testOptionalArgument() { $container = new ContainerBuilder(); - $resolver = $container->register('argument_resolver.service')->addArgument(array()); + $resolver = $container->register('argument_resolver.service')->addArgument([]); $container->register('foo', RegisterTestController::class) - ->addTag('controller.service_arguments', array('action' => 'fooAction', 'argument' => 'bar', 'id' => '?bar')) + ->addTag('controller.service_arguments', ['action' => 'fooAction', 'argument' => 'bar', 'id' => '?bar']) ; $pass = new RegisterControllerArgumentLocatorsPass(); $pass->process($container); $locator = $container->getDefinition((string) $resolver->getArgument(0))->getArgument(0); - $locator = $container->getDefinition((string) $locator['foo:fooAction']->getValues()[0]); + $locator = $container->getDefinition((string) $locator['foo::fooAction']->getValues()[0]); - $expected = array('bar' => new ServiceClosureArgument(new TypedReference('bar', ControllerDummy::class, RegisterTestController::class, ContainerInterface::IGNORE_ON_INVALID_REFERENCE))); + $expected = ['bar' => new ServiceClosureArgument(new TypedReference('bar', ControllerDummy::class, ContainerInterface::IGNORE_ON_INVALID_REFERENCE))]; $this->assertEquals($expected, $locator->getArgument(0)); } public function testSkipSetContainer() { $container = new ContainerBuilder(); - $resolver = $container->register('argument_resolver.service')->addArgument(array()); + $resolver = $container->register('argument_resolver.service')->addArgument([]); $container->register('foo', ContainerAwareRegisterTestController::class) ->addTag('controller.service_arguments'); @@ -203,17 +192,15 @@ class RegisterControllerArgumentLocatorsPassTest extends TestCase $pass->process($container); $locator = $container->getDefinition((string) $resolver->getArgument(0))->getArgument(0); - $this->assertSame(array('foo:fooAction'), array_keys($locator)); + $this->assertSame(['foo::fooAction'], array_keys($locator)); } - /** - * @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException - * @expectedExceptionMessage Cannot determine controller argument for "Symfony\Component\HttpKernel\Tests\DependencyInjection\NonExistentClassController::fooAction()": the $nonExistent argument is type-hinted with the non-existent class or interface: "Symfony\Component\HttpKernel\Tests\DependencyInjection\NonExistentClass". Did you forget to add a use statement? - */ public function testExceptionOnNonExistentTypeHint() { + $this->expectException('Symfony\Component\DependencyInjection\Exception\InvalidArgumentException'); + $this->expectExceptionMessage('Cannot determine controller argument for "Symfony\Component\HttpKernel\Tests\DependencyInjection\NonExistentClassController::fooAction()": the $nonExistent argument is type-hinted with the non-existent class or interface: "Symfony\Component\HttpKernel\Tests\DependencyInjection\NonExistentClass". Did you forget to add a use statement?'); $container = new ContainerBuilder(); - $container->register('argument_resolver.service')->addArgument(array()); + $container->register('argument_resolver.service')->addArgument([]); $container->register('foo', NonExistentClassController::class) ->addTag('controller.service_arguments'); @@ -222,14 +209,12 @@ class RegisterControllerArgumentLocatorsPassTest extends TestCase $pass->process($container); } - /** - * @expectedException \Symfony\Component\DependencyInjection\Exception\InvalidArgumentException - * @expectedExceptionMessage Cannot determine controller argument for "Symfony\Component\HttpKernel\Tests\DependencyInjection\NonExistentClassDifferentNamespaceController::fooAction()": the $nonExistent argument is type-hinted with the non-existent class or interface: "Acme\NonExistentClass". - */ public function testExceptionOnNonExistentTypeHintDifferentNamespace() { + $this->expectException('Symfony\Component\DependencyInjection\Exception\InvalidArgumentException'); + $this->expectExceptionMessage('Cannot determine controller argument for "Symfony\Component\HttpKernel\Tests\DependencyInjection\NonExistentClassDifferentNamespaceController::fooAction()": the $nonExistent argument is type-hinted with the non-existent class or interface: "Acme\NonExistentClass".'); $container = new ContainerBuilder(); - $container->register('argument_resolver.service')->addArgument(array()); + $container->register('argument_resolver.service')->addArgument([]); $container->register('foo', NonExistentClassDifferentNamespaceController::class) ->addTag('controller.service_arguments'); @@ -241,7 +226,7 @@ class RegisterControllerArgumentLocatorsPassTest extends TestCase public function testNoExceptionOnNonExistentTypeHintOptionalArg() { $container = new ContainerBuilder(); - $resolver = $container->register('argument_resolver.service')->addArgument(array()); + $resolver = $container->register('argument_resolver.service')->addArgument([]); $container->register('foo', NonExistentClassOptionalController::class) ->addTag('controller.service_arguments'); @@ -250,13 +235,13 @@ class RegisterControllerArgumentLocatorsPassTest extends TestCase $pass->process($container); $locator = $container->getDefinition((string) $resolver->getArgument(0))->getArgument(0); - $this->assertSame(array('foo:barAction', 'foo:fooAction'), array_keys($locator)); + $this->assertSame(['foo::barAction', 'foo::fooAction'], array_keys($locator)); } public function testArgumentWithNoTypeHintIsOk() { $container = new ContainerBuilder(); - $resolver = $container->register('argument_resolver.service')->addArgument(array()); + $resolver = $container->register('argument_resolver.service')->addArgument([]); $container->register('foo', ArgumentWithoutTypeController::class) ->addTag('controller.service_arguments'); @@ -271,7 +256,7 @@ class RegisterControllerArgumentLocatorsPassTest extends TestCase public function testControllersAreMadePublic() { $container = new ContainerBuilder(); - $resolver = $container->register('argument_resolver.service')->addArgument(array()); + $resolver = $container->register('argument_resolver.service')->addArgument([]); $container->register('foo', ArgumentWithoutTypeController::class) ->setPublic(false) @@ -289,10 +274,10 @@ class RegisterControllerArgumentLocatorsPassTest extends TestCase public function testBindings($bindingName) { $container = new ContainerBuilder(); - $resolver = $container->register('argument_resolver.service')->addArgument(array()); + $resolver = $container->register('argument_resolver.service')->addArgument([]); $container->register('foo', RegisterTestController::class) - ->setBindings(array($bindingName => new Reference('foo'))) + ->setBindings([$bindingName => new Reference('foo')]) ->addTag('controller.service_arguments'); $pass = new RegisterControllerArgumentLocatorsPass(); @@ -300,31 +285,93 @@ class RegisterControllerArgumentLocatorsPassTest extends TestCase $locator = $container->getDefinition((string) $resolver->getArgument(0))->getArgument(0); - $locator = $container->getDefinition((string) $locator['foo:fooAction']->getValues()[0]); + $locator = $container->getDefinition((string) $locator['foo::fooAction']->getValues()[0]); - $expected = array('bar' => new ServiceClosureArgument(new Reference('foo'))); + $expected = ['bar' => new ServiceClosureArgument(new Reference('foo'))]; $this->assertEquals($expected, $locator->getArgument(0)); } public function provideBindings() { - return array(array(ControllerDummy::class), array('$bar')); + return [ + [ControllerDummy::class.'$bar'], + [ControllerDummy::class], + ['$bar'], + ]; } - public function testDoNotBindScalarValueToControllerArgument() + /** + * @dataProvider provideBindScalarValueToControllerArgument + */ + public function testBindScalarValueToControllerArgument($bindingKey) { $container = new ContainerBuilder(); - $resolver = $container->register('argument_resolver.service')->addArgument(array()); + $resolver = $container->register('argument_resolver.service')->addArgument([]); $container->register('foo', ArgumentWithoutTypeController::class) - ->setBindings(array('$someArg' => '%foo%')) + ->setBindings([$bindingKey => '%foo%']) ->addTag('controller.service_arguments'); + $container->setParameter('foo', 'foo_val'); + $pass = new RegisterControllerArgumentLocatorsPass(); $pass->process($container); $locator = $container->getDefinition((string) $resolver->getArgument(0))->getArgument(0); - $this->assertEmpty($locator); + + $locator = $container->getDefinition((string) $locator['foo::fooAction']->getValues()[0]); + + // assert the locator has a someArg key + $arguments = $locator->getArgument(0); + $this->assertArrayHasKey('someArg', $arguments); + $this->assertInstanceOf(ServiceClosureArgument::class, $arguments['someArg']); + // get the Reference that someArg points to + $reference = $arguments['someArg']->getValues()[0]; + // make sure this service *does* exist and returns the correct value + $this->assertTrue($container->has((string) $reference)); + $this->assertSame('foo_val', $container->get((string) $reference)); + } + + public function provideBindScalarValueToControllerArgument() + { + yield ['$someArg']; + yield ['string $someArg']; + } + + public function testBindingsOnChildDefinitions() + { + $container = new ContainerBuilder(); + $resolver = $container->register('argument_resolver.service')->addArgument([]); + + $container->register('parent', ArgumentWithoutTypeController::class); + + $container->setDefinition('child', (new ChildDefinition('parent')) + ->setBindings(['$someArg' => new Reference('parent')]) + ->addTag('controller.service_arguments') + ); + + $pass = new RegisterControllerArgumentLocatorsPass(); + $pass->process($container); + + $locator = $container->getDefinition((string) $resolver->getArgument(0))->getArgument(0); + $this->assertInstanceOf(ServiceClosureArgument::class, $locator['child::fooAction']); + + $locator = $container->getDefinition((string) $locator['child::fooAction']->getValues()[0])->getArgument(0); + $this->assertInstanceOf(ServiceClosureArgument::class, $locator['someArg']); + $this->assertEquals(new Reference('parent'), $locator['someArg']->getValues()[0]); + } + + public function testNotTaggedControllerServiceReceivesLocatorArgument() + { + $container = new ContainerBuilder(); + $resolver = $container->register('argument_resolver.not_tagged_controller')->addArgument([]); + + $pass = new RegisterControllerArgumentLocatorsPass(); + $pass->process($container); + + $locatorArgument = $container->getDefinition('argument_resolver.not_tagged_controller')->getArgument(0); + + $this->assertInstanceOf(Reference::class, $locatorArgument); } } @@ -383,7 +430,7 @@ class NonExistentClassOptionalController class ArgumentWithoutTypeController { - public function fooAction($someArg) + public function fooAction(string $someArg) { } } diff --git a/vendor/symfony/http-kernel/Tests/DependencyInjection/RegisterLocaleAwareServicesPassTest.php b/vendor/symfony/http-kernel/Tests/DependencyInjection/RegisterLocaleAwareServicesPassTest.php new file mode 100644 index 0000000000000000000000000000000000000000..aa3c6aa0c46c55a1c04357a359ae4aa3f8b148dc --- /dev/null +++ b/vendor/symfony/http-kernel/Tests/DependencyInjection/RegisterLocaleAwareServicesPassTest.php @@ -0,0 +1,59 @@ +<?php + +namespace Symfony\Component\HttpKernel\Tests\DependencyInjection; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\DependencyInjection\Argument\IteratorArgument; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Reference; +use Symfony\Component\HttpKernel\DependencyInjection\RegisterLocaleAwareServicesPass; +use Symfony\Component\HttpKernel\EventListener\LocaleAwareListener; +use Symfony\Contracts\Translation\LocaleAwareInterface; + +class RegisterLocaleAwareServicesPassTest extends TestCase +{ + public function testCompilerPass() + { + $container = new ContainerBuilder(); + + $container->register('locale_aware_listener', LocaleAwareListener::class) + ->setPublic(true) + ->setArguments([null, null]); + + $container->register('some_locale_aware_service', LocaleAwareInterface::class) + ->setPublic(true) + ->addTag('kernel.locale_aware'); + + $container->register('another_locale_aware_service', LocaleAwareInterface::class) + ->setPublic(true) + ->addTag('kernel.locale_aware'); + + $container->addCompilerPass(new RegisterLocaleAwareServicesPass()); + $container->compile(); + + $this->assertEquals( + [ + new IteratorArgument([ + 0 => new Reference('some_locale_aware_service'), + 1 => new Reference('another_locale_aware_service'), + ]), + null, + ], + $container->getDefinition('locale_aware_listener')->getArguments() + ); + } + + public function testListenerUnregisteredWhenNoLocaleAwareServices() + { + $container = new ContainerBuilder(); + + $container->register('locale_aware_listener', LocaleAwareListener::class) + ->setPublic(true) + ->setArguments([null, null]); + + $container->addCompilerPass(new RegisterLocaleAwareServicesPass()); + $container->compile(); + + $this->assertFalse($container->hasDefinition('locale_aware_listener')); + } +} diff --git a/vendor/symfony/http-kernel/Tests/DependencyInjection/RemoveEmptyControllerArgumentLocatorsPassTest.php b/vendor/symfony/http-kernel/Tests/DependencyInjection/RemoveEmptyControllerArgumentLocatorsPassTest.php index 9cac9681857f89a5a4dee42f5e437d6ce44da5e2..b5e55bdea9e9793f826b858c384111fa2e617d98 100644 --- a/vendor/symfony/http-kernel/Tests/DependencyInjection/RemoveEmptyControllerArgumentLocatorsPassTest.php +++ b/vendor/symfony/http-kernel/Tests/DependencyInjection/RemoveEmptyControllerArgumentLocatorsPassTest.php @@ -23,66 +23,47 @@ class RemoveEmptyControllerArgumentLocatorsPassTest extends TestCase public function testProcess() { $container = new ContainerBuilder(); - $resolver = $container->register('argument_resolver.service')->addArgument(array()); + $resolver = $container->register('argument_resolver.service')->addArgument([]); $container->register('stdClass', 'stdClass'); - $container->register(parent::class, 'stdClass'); + $container->register(TestCase::class, 'stdClass'); $container->register('c1', RemoveTestController1::class)->addTag('controller.service_arguments'); $container->register('c2', RemoveTestController2::class)->addTag('controller.service_arguments') - ->addMethodCall('setTestCase', array(new Reference('c1'))); + ->addMethodCall('setTestCase', [new Reference('c1')]); $pass = new RegisterControllerArgumentLocatorsPass(); $pass->process($container); $controllers = $container->getDefinition((string) $resolver->getArgument(0))->getArgument(0); - $this->assertCount(2, $container->getDefinition((string) $controllers['c1:fooAction']->getValues()[0])->getArgument(0)); - $this->assertCount(1, $container->getDefinition((string) $controllers['c2:setTestCase']->getValues()[0])->getArgument(0)); - $this->assertCount(1, $container->getDefinition((string) $controllers['c2:fooAction']->getValues()[0])->getArgument(0)); + $this->assertCount(2, $container->getDefinition((string) $controllers['c1::fooAction']->getValues()[0])->getArgument(0)); + $this->assertCount(1, $container->getDefinition((string) $controllers['c2::setTestCase']->getValues()[0])->getArgument(0)); + $this->assertCount(1, $container->getDefinition((string) $controllers['c2::fooAction']->getValues()[0])->getArgument(0)); (new ResolveInvalidReferencesPass())->process($container); - $this->assertCount(1, $container->getDefinition((string) $controllers['c2:setTestCase']->getValues()[0])->getArgument(0)); - $this->assertSame(array(), $container->getDefinition((string) $controllers['c2:fooAction']->getValues()[0])->getArgument(0)); + $this->assertCount(1, $container->getDefinition((string) $controllers['c2::setTestCase']->getValues()[0])->getArgument(0)); + $this->assertSame([], $container->getDefinition((string) $controllers['c2::fooAction']->getValues()[0])->getArgument(0)); (new RemoveEmptyControllerArgumentLocatorsPass())->process($container); $controllers = $container->getDefinition((string) $resolver->getArgument(0))->getArgument(0); - $this->assertSame(array('c1:fooAction'), array_keys($controllers)); - $this->assertSame(array('bar'), array_keys($container->getDefinition((string) $controllers['c1:fooAction']->getValues()[0])->getArgument(0))); + $this->assertSame(['c1::fooAction', 'c1:fooAction'], array_keys($controllers)); + $this->assertSame(['bar'], array_keys($container->getDefinition((string) $controllers['c1::fooAction']->getValues()[0])->getArgument(0))); - $expectedLog = array( - 'Symfony\Component\HttpKernel\DependencyInjection\RemoveEmptyControllerArgumentLocatorsPass: Removing service-argument resolver for controller "c2:fooAction": no corresponding services exist for the referenced types.', + $expectedLog = [ + 'Symfony\Component\HttpKernel\DependencyInjection\RemoveEmptyControllerArgumentLocatorsPass: Removing service-argument resolver for controller "c2::fooAction": no corresponding services exist for the referenced types.', 'Symfony\Component\HttpKernel\DependencyInjection\RemoveEmptyControllerArgumentLocatorsPass: Removing method "setTestCase" of service "c2" from controller candidates: the method is called at instantiation, thus cannot be an action.', - ); + ]; $this->assertSame($expectedLog, $container->getCompiler()->getLog()); } - public function testSameIdClass() - { - $container = new ContainerBuilder(); - $resolver = $container->register('argument_resolver.service')->addArgument(array()); - - $container->register(RegisterTestController::class, RegisterTestController::class) - ->addTag('controller.service_arguments') - ; - - (new RegisterControllerArgumentLocatorsPass())->process($container); - (new RemoveEmptyControllerArgumentLocatorsPass())->process($container); - - $expected = array( - RegisterTestController::class.':fooAction', - RegisterTestController::class.'::fooAction', - ); - $this->assertEquals($expected, array_keys($container->getDefinition((string) $resolver->getArgument(0))->getArgument(0))); - } - public function testInvoke() { $container = new ContainerBuilder(); - $resolver = $container->register('argument_resolver.service')->addArgument(array()); + $resolver = $container->register('argument_resolver.service')->addArgument([]); $container->register('invokable', InvokableRegisterTestController::class) ->addTag('controller.service_arguments') @@ -92,35 +73,15 @@ class RemoveEmptyControllerArgumentLocatorsPassTest extends TestCase (new RemoveEmptyControllerArgumentLocatorsPass())->process($container); $this->assertEquals( - array('invokable:__invoke', 'invokable'), + ['invokable::__invoke', 'invokable:__invoke', 'invokable'], array_keys($container->getDefinition((string) $resolver->getArgument(0))->getArgument(0)) ); } - - public function testInvokeSameIdClass() - { - $container = new ContainerBuilder(); - $resolver = $container->register('argument_resolver.service')->addArgument(array()); - - $container->register(InvokableRegisterTestController::class, InvokableRegisterTestController::class) - ->addTag('controller.service_arguments') - ; - - (new RegisterControllerArgumentLocatorsPass())->process($container); - (new RemoveEmptyControllerArgumentLocatorsPass())->process($container); - - $expected = array( - InvokableRegisterTestController::class.':__invoke', - InvokableRegisterTestController::class.'::__invoke', - InvokableRegisterTestController::class, - ); - $this->assertEquals($expected, array_keys($container->getDefinition((string) $resolver->getArgument(0))->getArgument(0))); - } } class RemoveTestController1 { - public function fooAction(\stdClass $bar, ClassNotInContainer $baz) + public function fooAction(\stdClass $bar, ClassNotInContainer $baz = null) { } } @@ -131,7 +92,7 @@ class RemoveTestController2 { } - public function fooAction(ClassNotInContainer $bar) + public function fooAction(ClassNotInContainer $bar = null) { } } diff --git a/vendor/symfony/http-kernel/Tests/DependencyInjection/ResettableServicePassTest.php b/vendor/symfony/http-kernel/Tests/DependencyInjection/ResettableServicePassTest.php index f7ea16dbfb0360436ee3b7b8c9f9fa496d12bc31..d3c6869320910595da0608d43a78eae38788d39c 100644 --- a/vendor/symfony/http-kernel/Tests/DependencyInjection/ResettableServicePassTest.php +++ b/vendor/symfony/http-kernel/Tests/DependencyInjection/ResettableServicePassTest.php @@ -19,14 +19,14 @@ class ResettableServicePassTest extends TestCase $container = new ContainerBuilder(); $container->register('one', ResettableService::class) ->setPublic(true) - ->addTag('kernel.reset', array('method' => 'reset')); + ->addTag('kernel.reset', ['method' => 'reset']); $container->register('two', ClearableService::class) ->setPublic(true) - ->addTag('kernel.reset', array('method' => 'clear')); + ->addTag('kernel.reset', ['method' => 'clear']); $container->register('services_resetter', ServicesResetter::class) ->setPublic(true) - ->setArguments(array(null, array())); + ->setArguments([null, []]); $container->addCompilerPass(new ResettableServicePass()); $container->compile(); @@ -34,31 +34,29 @@ class ResettableServicePassTest extends TestCase $definition = $container->getDefinition('services_resetter'); $this->assertEquals( - array( - new IteratorArgument(array( + [ + new IteratorArgument([ 'one' => new Reference('one', ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE), 'two' => new Reference('two', ContainerInterface::IGNORE_ON_UNINITIALIZED_REFERENCE), - )), - array( + ]), + [ 'one' => 'reset', 'two' => 'clear', - ), - ), + ], + ], $definition->getArguments() ); } - /** - * @expectedException \Symfony\Component\DependencyInjection\Exception\RuntimeException - * @expectedExceptionMessage Tag kernel.reset requires the "method" attribute to be set. - */ public function testMissingMethod() { + $this->expectException('Symfony\Component\DependencyInjection\Exception\RuntimeException'); + $this->expectExceptionMessage('Tag kernel.reset requires the "method" attribute to be set.'); $container = new ContainerBuilder(); $container->register(ResettableService::class) ->addTag('kernel.reset'); $container->register('services_resetter', ServicesResetter::class) - ->setArguments(array(null, array())); + ->setArguments([null, []]); $container->addCompilerPass(new ResettableServicePass()); $container->compile(); @@ -68,7 +66,7 @@ class ResettableServicePassTest extends TestCase { $container = new ContainerBuilder(); $container->register('services_resetter', ServicesResetter::class) - ->setArguments(array(null, array())); + ->setArguments([null, []]); $container->addCompilerPass(new ResettableServicePass()); $container->compile(); diff --git a/vendor/symfony/http-kernel/Tests/DependencyInjection/ServicesResetterTest.php b/vendor/symfony/http-kernel/Tests/DependencyInjection/ServicesResetterTest.php index 47c62abd0d99894522f1391cc768f283232c608b..5be6026c90a678db20ffe929ca1a666f34215fd8 100644 --- a/vendor/symfony/http-kernel/Tests/DependencyInjection/ServicesResetterTest.php +++ b/vendor/symfony/http-kernel/Tests/DependencyInjection/ServicesResetterTest.php @@ -18,7 +18,7 @@ use Symfony\Component\HttpKernel\Tests\Fixtures\ResettableService; class ServicesResetterTest extends TestCase { - protected function setUp() + protected function setUp(): void { ResettableService::$counter = 0; ClearableService::$counter = 0; @@ -26,13 +26,13 @@ class ServicesResetterTest extends TestCase public function testResetServices() { - $resetter = new ServicesResetter(new \ArrayIterator(array( + $resetter = new ServicesResetter(new \ArrayIterator([ 'id1' => new ResettableService(), 'id2' => new ClearableService(), - )), array( + ]), [ 'id1' => 'reset', 'id2' => 'clear', - )); + ]); $resetter->reset(); diff --git a/vendor/symfony/http-kernel/Tests/Event/ControllerArgumentsEventTest.php b/vendor/symfony/http-kernel/Tests/Event/ControllerArgumentsEventTest.php new file mode 100644 index 0000000000000000000000000000000000000000..7758a66667f6dee2b8ccfbbf815670681d38275a --- /dev/null +++ b/vendor/symfony/http-kernel/Tests/Event/ControllerArgumentsEventTest.php @@ -0,0 +1,17 @@ +<?php + +namespace Symfony\Component\HttpKernel\Tests\Event; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpKernel\Event\ControllerArgumentsEvent; +use Symfony\Component\HttpKernel\Tests\TestHttpKernel; + +class ControllerArgumentsEventTest extends TestCase +{ + public function testControllerArgumentsEvent() + { + $filterController = new ControllerArgumentsEvent(new TestHttpKernel(), function () {}, ['test'], new Request(), 1); + $this->assertEquals($filterController->getArguments(), ['test']); + } +} diff --git a/vendor/symfony/http-kernel/Tests/Event/GetResponseForExceptionEventTest.php b/vendor/symfony/http-kernel/Tests/Event/ExceptionEventTest.php similarity index 71% rename from vendor/symfony/http-kernel/Tests/Event/GetResponseForExceptionEventTest.php rename to vendor/symfony/http-kernel/Tests/Event/ExceptionEventTest.php index 7242579301d9c8f07fd36dba5ac18bd3b064084e..6b061d3a33887b66add8d0dcae0017192518669b 100644 --- a/vendor/symfony/http-kernel/Tests/Event/GetResponseForExceptionEventTest.php +++ b/vendor/symfony/http-kernel/Tests/Event/ExceptionEventTest.php @@ -13,14 +13,14 @@ namespace Symfony\Component\HttpKernel\Tests\Event; use PHPUnit\Framework\TestCase; use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent; +use Symfony\Component\HttpKernel\Event\ExceptionEvent; use Symfony\Component\HttpKernel\Tests\TestHttpKernel; -class GetResponseForExceptionEventTest extends TestCase +class ExceptionEventTest extends TestCase { public function testAllowSuccessfulResponseIsFalseByDefault() { - $event = new GetResponseForExceptionEvent(new TestHttpKernel(), new Request(), 1, new \Exception()); + $event = new ExceptionEvent(new TestHttpKernel(), new Request(), 1, new \Exception()); $this->assertFalse($event->isAllowingCustomResponseCode()); } diff --git a/vendor/symfony/http-kernel/Tests/Event/FilterControllerArgumentsEventTest.php b/vendor/symfony/http-kernel/Tests/Event/FilterControllerArgumentsEventTest.php deleted file mode 100644 index 9165d31f24a152e28ac447eeec1937e7c2be0203..0000000000000000000000000000000000000000 --- a/vendor/symfony/http-kernel/Tests/Event/FilterControllerArgumentsEventTest.php +++ /dev/null @@ -1,17 +0,0 @@ -<?php - -namespace Symfony\Component\HttpKernel\Tests\Event; - -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpKernel\Event\FilterControllerArgumentsEvent; -use PHPUnit\Framework\TestCase; -use Symfony\Component\HttpKernel\Tests\TestHttpKernel; - -class FilterControllerArgumentsEventTest extends TestCase -{ - public function testFilterControllerArgumentsEvent() - { - $filterController = new FilterControllerArgumentsEvent(new TestHttpKernel(), function () {}, array('test'), new Request(), 1); - $this->assertEquals($filterController->getArguments(), array('test')); - } -} diff --git a/vendor/symfony/http-kernel/Tests/EventListener/AddRequestFormatsListenerTest.php b/vendor/symfony/http-kernel/Tests/EventListener/AddRequestFormatsListenerTest.php index f4878f626f05d6e8dd7bd081f9971287c3a0fc5a..da8dc6fb0b75f5b2a3321385783bed0ab90287db 100644 --- a/vendor/symfony/http-kernel/Tests/EventListener/AddRequestFormatsListenerTest.php +++ b/vendor/symfony/http-kernel/Tests/EventListener/AddRequestFormatsListenerTest.php @@ -12,8 +12,9 @@ namespace Symfony\Component\HttpKernel\Tests\EventListener; use PHPUnit\Framework\TestCase; -use Symfony\Component\HttpKernel\EventListener\AddRequestFormatsListener; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpKernel\Event\RequestEvent; +use Symfony\Component\HttpKernel\EventListener\AddRequestFormatsListener; use Symfony\Component\HttpKernel\KernelEvents; /** @@ -28,12 +29,12 @@ class AddRequestFormatsListenerTest extends TestCase */ private $listener; - protected function setUp() + protected function setUp(): void { - $this->listener = new AddRequestFormatsListener(array('csv' => array('text/csv', 'text/plain'))); + $this->listener = new AddRequestFormatsListener(['csv' => ['text/csv', 'text/plain']]); } - protected function tearDown() + protected function tearDown(): void { $this->listener = null; } @@ -46,7 +47,7 @@ class AddRequestFormatsListenerTest extends TestCase public function testRegisteredEvent() { $this->assertEquals( - array(KernelEvents::REQUEST => array('onKernelRequest', 1)), + [KernelEvents::REQUEST => ['onKernelRequest', 100]], AddRequestFormatsListener::getSubscribedEvents() ); } @@ -54,11 +55,11 @@ class AddRequestFormatsListenerTest extends TestCase public function testSetAdditionalFormats() { $request = $this->getRequestMock(); - $event = $this->getGetResponseEventMock($request); + $event = $this->getRequestEventMock($request); $request->expects($this->once()) ->method('setFormat') - ->with('csv', array('text/csv', 'text/plain')); + ->with('csv', ['text/csv', 'text/plain']); $this->listener->onKernelRequest($event); } @@ -68,16 +69,16 @@ class AddRequestFormatsListenerTest extends TestCase return $this->getMockBuilder('Symfony\Component\HttpFoundation\Request')->getMock(); } - protected function getGetResponseEventMock(Request $request) + protected function getRequestEventMock(Request $request) { $event = $this - ->getMockBuilder('Symfony\Component\HttpKernel\Event\GetResponseEvent') + ->getMockBuilder(RequestEvent::class) ->disableOriginalConstructor() ->getMock(); $event->expects($this->any()) ->method('getRequest') - ->will($this->returnValue($request)); + ->willReturn($request); return $event; } diff --git a/vendor/symfony/http-kernel/Tests/EventListener/DebugHandlersListenerTest.php b/vendor/symfony/http-kernel/Tests/EventListener/DebugHandlersListenerTest.php index 467b8dde8849a51ca300735140a8d1dbdc6a83a9..1e52bce7a359bf6bca47c1c8e85d28a63960f17b 100644 --- a/vendor/symfony/http-kernel/Tests/EventListener/DebugHandlersListenerTest.php +++ b/vendor/symfony/http-kernel/Tests/EventListener/DebugHandlersListenerTest.php @@ -13,9 +13,9 @@ namespace Symfony\Component\HttpKernel\Tests\EventListener; use PHPUnit\Framework\TestCase; use Psr\Log\LogLevel; -use Symfony\Component\Console\Event\ConsoleEvent; use Symfony\Component\Console\Command\Command; use Symfony\Component\Console\ConsoleEvents; +use Symfony\Component\Console\Event\ConsoleEvent; use Symfony\Component\Console\Helper\HelperSet; use Symfony\Component\Console\Input\ArgvInput; use Symfony\Component\Console\Output\ConsoleOutput; @@ -40,11 +40,11 @@ class DebugHandlersListenerTest extends TestCase $listener = new DebugHandlersListener($userHandler, $logger); $xHandler = new ExceptionHandler(); $eHandler = new ErrorHandler(); - $eHandler->setExceptionHandler(array($xHandler, 'handle')); + $eHandler->setExceptionHandler([$xHandler, 'handle']); $exception = null; - set_error_handler(array($eHandler, 'handleError')); - set_exception_handler(array($eHandler, 'handleException')); + set_error_handler([$eHandler, 'handleError']); + set_exception_handler([$eHandler, 'handleException']); try { $listener->configure(); } catch (\Exception $exception) { @@ -58,10 +58,10 @@ class DebugHandlersListenerTest extends TestCase $this->assertSame($userHandler, $xHandler->setHandler('var_dump')); - $loggers = $eHandler->setLoggers(array()); + $loggers = $eHandler->setLoggers([]); $this->assertArrayHasKey(E_DEPRECATED, $loggers); - $this->assertSame(array($logger, LogLevel::INFO), $loggers[E_DEPRECATED]); + $this->assertSame([$logger, LogLevel::INFO], $loggers[E_DEPRECATED]); } public function testConfigureForHttpKernelWithNoTerminateWithException() @@ -75,7 +75,7 @@ class DebugHandlersListenerTest extends TestCase ); $exception = null; - $h = set_exception_handler(array($eHandler, 'handleException')); + $h = set_exception_handler([$eHandler, 'handleException']); try { $listener->configure($event); } catch (\Exception $exception) { @@ -94,25 +94,26 @@ class DebugHandlersListenerTest extends TestCase $dispatcher = new EventDispatcher(); $listener = new DebugHandlersListener(null); $app = $this->getMockBuilder('Symfony\Component\Console\Application')->getMock(); - $app->expects($this->once())->method('getHelperSet')->will($this->returnValue(new HelperSet())); + $app->expects($this->once())->method('getHelperSet')->willReturn(new HelperSet()); $command = new Command(__FUNCTION__); $command->setApplication($app); $event = new ConsoleEvent($command, new ArgvInput(), new ConsoleOutput()); $dispatcher->addSubscriber($listener); - $xListeners = array( - KernelEvents::REQUEST => array(array($listener, 'configure')), - ConsoleEvents::COMMAND => array(array($listener, 'configure')), - ); + $xListeners = [ + KernelEvents::REQUEST => [[$listener, 'configure']], + ConsoleEvents::COMMAND => [[$listener, 'configure']], + KernelEvents::EXCEPTION => [[$listener, 'onKernelException']], + ]; $this->assertSame($xListeners, $dispatcher->getListeners()); $exception = null; $eHandler = new ErrorHandler(); - set_error_handler(array($eHandler, 'handleError')); - set_exception_handler(array($eHandler, 'handleException')); + set_error_handler([$eHandler, 'handleError']); + set_exception_handler([$eHandler, 'handleException']); try { - $dispatcher->dispatch(ConsoleEvents::COMMAND, $event); + $dispatcher->dispatch($event, ConsoleEvents::COMMAND); } catch (\Exception $exception) { } restore_exception_handler(); @@ -139,7 +140,7 @@ class DebugHandlersListenerTest extends TestCase $eHandler->setExceptionHandler('var_dump'); $exception = null; - set_exception_handler(array($eHandler, 'handleException')); + set_exception_handler([$eHandler, 'handleException']); try { $listener->configure(); } catch (\Exception $exception) { diff --git a/vendor/symfony/http-kernel/Tests/EventListener/DisallowRobotsIndexingListenerTest.php b/vendor/symfony/http-kernel/Tests/EventListener/DisallowRobotsIndexingListenerTest.php new file mode 100644 index 0000000000000000000000000000000000000000..53b317b7611ce5c4e45da773cba742b34212c705 --- /dev/null +++ b/vendor/symfony/http-kernel/Tests/EventListener/DisallowRobotsIndexingListenerTest.php @@ -0,0 +1,47 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Tests\EventListener; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpKernel\Event\ResponseEvent; +use Symfony\Component\HttpKernel\EventListener\DisallowRobotsIndexingListener; +use Symfony\Component\HttpKernel\HttpKernelInterface; +use Symfony\Component\HttpKernel\KernelInterface; + +class DisallowRobotsIndexingListenerTest extends TestCase +{ + /** + * @dataProvider provideResponses + */ + public function testInvoke(?string $expected, Response $response): void + { + $listener = new DisallowRobotsIndexingListener(); + + $event = new ResponseEvent($this->createMock(HttpKernelInterface::class), $this->createMock(Request::class), KernelInterface::MASTER_REQUEST, $response); + + $listener->onResponse($event); + + $this->assertSame($expected, $response->headers->get('X-Robots-Tag'), 'Header doesn\'t match expectations'); + } + + public function provideResponses(): iterable + { + yield 'No header' => ['noindex', new Response()]; + + yield 'Header already set' => [ + 'something else', + new Response('', 204, ['X-Robots-Tag' => 'something else']), + ]; + } +} diff --git a/vendor/symfony/http-kernel/Tests/EventListener/DumpListenerTest.php b/vendor/symfony/http-kernel/Tests/EventListener/DumpListenerTest.php index 509f443087ebe4de5cba010d0fea310a163c6212..b86a7552f85e4eab8ce1629136eb691b58afaf37 100644 --- a/vendor/symfony/http-kernel/Tests/EventListener/DumpListenerTest.php +++ b/vendor/symfony/http-kernel/Tests/EventListener/DumpListenerTest.php @@ -29,7 +29,7 @@ class DumpListenerTest extends TestCase public function testSubscribedEvents() { $this->assertSame( - array(ConsoleEvents::COMMAND => array('configure', 1024)), + [ConsoleEvents::COMMAND => ['configure', 1024]], DumpListener::getSubscribedEvents() ); } @@ -68,7 +68,7 @@ class MockCloner implements ClonerInterface { public function cloneVar($var) { - return new Data(array(array($var.'-'))); + return new Data([[$var.'-']]); } } diff --git a/vendor/symfony/http-kernel/Tests/EventListener/ExceptionListenerTest.php b/vendor/symfony/http-kernel/Tests/EventListener/ExceptionListenerTest.php index 3cb0b298bb07aa8d858215cf749fbd446fa1deb3..4a24066b2ceb718316da09c9087c52bac948a2fd 100644 --- a/vendor/symfony/http-kernel/Tests/EventListener/ExceptionListenerTest.php +++ b/vendor/symfony/http-kernel/Tests/EventListener/ExceptionListenerTest.php @@ -13,14 +13,14 @@ namespace Symfony\Component\HttpKernel\Tests\EventListener; use PHPUnit\Framework\TestCase; use Symfony\Component\EventDispatcher\EventDispatcher; -use Symfony\Component\HttpKernel\Event\FilterResponseEvent; -use Symfony\Component\HttpKernel\HttpKernelInterface; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpKernel\Event\ExceptionEvent; +use Symfony\Component\HttpKernel\Event\ResponseEvent; use Symfony\Component\HttpKernel\EventListener\ExceptionListener; +use Symfony\Component\HttpKernel\HttpKernelInterface; use Symfony\Component\HttpKernel\KernelEvents; use Symfony\Component\HttpKernel\Log\DebugLoggerInterface; -use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent; -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\Tests\Logger; /** @@ -37,9 +37,9 @@ class ExceptionListenerTest extends TestCase $logger = new TestLogger(); $l = new ExceptionListener('foo', $logger); - $_logger = new \ReflectionProperty(get_class($l), 'logger'); + $_logger = new \ReflectionProperty(\get_class($l), 'logger'); $_logger->setAccessible(true); - $_controller = new \ReflectionProperty(get_class($l), 'controller'); + $_controller = new \ReflectionProperty(\get_class($l), 'controller'); $_controller->setAccessible(true); $this->assertSame($logger, $_logger->getValue($l)); @@ -54,11 +54,13 @@ class ExceptionListenerTest extends TestCase $this->iniSet('error_log', file_exists('/dev/null') ? '/dev/null' : 'nul'); $l = new ExceptionListener('foo'); + $l->logKernelException($event); $l->onKernelException($event); $this->assertEquals(new Response('foo'), $event->getResponse()); try { + $l->logKernelException($event2); $l->onKernelException($event2); $this->fail('RuntimeException expected'); } catch (\RuntimeException $e) { @@ -75,11 +77,13 @@ class ExceptionListenerTest extends TestCase $logger = new TestLogger(); $l = new ExceptionListener('foo', $logger); + $l->logKernelException($event); $l->onKernelException($event); $this->assertEquals(new Response('foo'), $event->getResponse()); try { + $l->logKernelException($event2); $l->onKernelException($event2); $this->fail('RuntimeException expected'); } catch (\RuntimeException $e) { @@ -94,17 +98,17 @@ class ExceptionListenerTest extends TestCase public function provider() { if (!class_exists('Symfony\Component\HttpFoundation\Request')) { - return array(array(null, null)); + return [[null, null]]; } $request = new Request(); $exception = new \Exception('foo'); - $event = new GetResponseForExceptionEvent(new TestKernel(), $request, HttpKernelInterface::MASTER_REQUEST, $exception); - $event2 = new GetResponseForExceptionEvent(new TestKernelThatThrowsException(), $request, HttpKernelInterface::MASTER_REQUEST, $exception); + $event = new ExceptionEvent(new TestKernel(), $request, HttpKernelInterface::MASTER_REQUEST, $exception); + $event2 = new ExceptionEvent(new TestKernelThatThrowsException(), $request, HttpKernelInterface::MASTER_REQUEST, $exception); - return array( - array($event, $event2), - ); + return [ + [$event, $event2], + ]; } public function testSubRequestFormat() @@ -112,14 +116,14 @@ class ExceptionListenerTest extends TestCase $listener = new ExceptionListener('foo', $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock()); $kernel = $this->getMockBuilder('Symfony\Component\HttpKernel\HttpKernelInterface')->getMock(); - $kernel->expects($this->once())->method('handle')->will($this->returnCallback(function (Request $request) { + $kernel->expects($this->once())->method('handle')->willReturnCallback(function (Request $request) { return new Response($request->getRequestFormat()); - })); + }); $request = Request::create('/'); $request->setRequestFormat('xml'); - $event = new GetResponseForExceptionEvent($kernel, $request, HttpKernelInterface::MASTER_REQUEST, new \Exception('foo')); + $event = new ExceptionEvent($kernel, $request, HttpKernelInterface::MASTER_REQUEST, new \Exception('foo')); $listener->onKernelException($event); $response = $event->getResponse(); @@ -130,23 +134,23 @@ class ExceptionListenerTest extends TestCase { $dispatcher = new EventDispatcher(); $kernel = $this->getMockBuilder('Symfony\Component\HttpKernel\HttpKernelInterface')->getMock(); - $kernel->expects($this->once())->method('handle')->will($this->returnCallback(function (Request $request) { + $kernel->expects($this->once())->method('handle')->willReturnCallback(function (Request $request) { return new Response($request->getRequestFormat()); - })); + }); $listener = new ExceptionListener('foo', $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock(), true); $dispatcher->addSubscriber($listener); $request = Request::create('/'); - $event = new GetResponseForExceptionEvent($kernel, $request, HttpKernelInterface::MASTER_REQUEST, new \Exception('foo')); - $dispatcher->dispatch(KernelEvents::EXCEPTION, $event); + $event = new ExceptionEvent($kernel, $request, HttpKernelInterface::MASTER_REQUEST, new \Exception('foo')); + $dispatcher->dispatch($event, KernelEvents::EXCEPTION); - $response = new Response('', 200, array('content-security-policy' => "style-src 'self'")); + $response = new Response('', 200, ['content-security-policy' => "style-src 'self'"]); $this->assertTrue($response->headers->has('content-security-policy')); - $event = new FilterResponseEvent($kernel, $request, HttpKernelInterface::MASTER_REQUEST, $response); - $dispatcher->dispatch(KernelEvents::RESPONSE, $event); + $event = new ResponseEvent($kernel, $request, HttpKernelInterface::MASTER_REQUEST, $response); + $dispatcher->dispatch($event, KernelEvents::RESPONSE); $this->assertFalse($response->headers->has('content-security-policy'), 'CSP header has been removed'); $this->assertFalse($dispatcher->hasListeners(KernelEvents::RESPONSE), 'CSP removal listener has been removed'); @@ -155,9 +159,9 @@ class ExceptionListenerTest extends TestCase class TestLogger extends Logger implements DebugLoggerInterface { - public function countErrors() + public function countErrors(Request $request = null): int { - return count($this->logs['critical']); + return \count($this->logs['critical']); } } diff --git a/vendor/symfony/http-kernel/Tests/EventListener/FragmentListenerTest.php b/vendor/symfony/http-kernel/Tests/EventListener/FragmentListenerTest.php index 464b2ab462f1d7d750f4c271cecc9228987f66ef..5b045a8fc4b5276a4fa18602509d56f68d9565b3 100644 --- a/vendor/symfony/http-kernel/Tests/EventListener/FragmentListenerTest.php +++ b/vendor/symfony/http-kernel/Tests/EventListener/FragmentListenerTest.php @@ -12,10 +12,10 @@ namespace Symfony\Component\HttpKernel\Tests\EventListener; use PHPUnit\Framework\TestCase; -use Symfony\Component\HttpKernel\EventListener\FragmentListener; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpKernel\Event\RequestEvent; +use Symfony\Component\HttpKernel\EventListener\FragmentListener; use Symfony\Component\HttpKernel\HttpKernelInterface; -use Symfony\Component\HttpKernel\Event\GetResponseEvent; use Symfony\Component\HttpKernel\UriSigner; class FragmentListenerTest extends TestCase @@ -25,7 +25,7 @@ class FragmentListenerTest extends TestCase $request = Request::create('http://example.com/foo?_path=foo%3Dbar%26_controller%3Dfoo'); $listener = new FragmentListener(new UriSigner('foo')); - $event = $this->createGetResponseEvent($request); + $event = $this->createRequestEvent($request); $expected = $request->attributes->all(); @@ -41,7 +41,7 @@ class FragmentListenerTest extends TestCase $request->attributes->set('_controller', 'bar'); $listener = new FragmentListener(new UriSigner('foo')); - $event = $this->createGetResponseEvent($request, HttpKernelInterface::SUB_REQUEST); + $event = $this->createRequestEvent($request, HttpKernelInterface::SUB_REQUEST); $expected = $request->attributes->all(); @@ -50,28 +50,24 @@ class FragmentListenerTest extends TestCase $this->assertEquals($expected, $request->attributes->all()); } - /** - * @expectedException \Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException - */ public function testAccessDeniedWithNonSafeMethods() { + $this->expectException('Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException'); $request = Request::create('http://example.com/_fragment', 'POST'); $listener = new FragmentListener(new UriSigner('foo')); - $event = $this->createGetResponseEvent($request); + $event = $this->createRequestEvent($request); $listener->onKernelRequest($event); } - /** - * @expectedException \Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException - */ public function testAccessDeniedWithWrongSignature() { - $request = Request::create('http://example.com/_fragment', 'GET', array(), array(), array(), array('REMOTE_ADDR' => '10.0.0.1')); + $this->expectException('Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException'); + $request = Request::create('http://example.com/_fragment', 'GET', [], [], [], ['REMOTE_ADDR' => '10.0.0.1']); $listener = new FragmentListener(new UriSigner('foo')); - $event = $this->createGetResponseEvent($request); + $event = $this->createRequestEvent($request); $listener->onKernelRequest($event); } @@ -79,14 +75,14 @@ class FragmentListenerTest extends TestCase public function testWithSignature() { $signer = new UriSigner('foo'); - $request = Request::create($signer->sign('http://example.com/_fragment?_path=foo%3Dbar%26_controller%3Dfoo'), 'GET', array(), array(), array(), array('REMOTE_ADDR' => '10.0.0.1')); + $request = Request::create($signer->sign('http://example.com/_fragment?_path=foo%3Dbar%26_controller%3Dfoo'), 'GET', [], [], [], ['REMOTE_ADDR' => '10.0.0.1']); $listener = new FragmentListener($signer); - $event = $this->createGetResponseEvent($request); + $event = $this->createRequestEvent($request); $listener->onKernelRequest($event); - $this->assertEquals(array('foo' => 'bar', '_controller' => 'foo'), $request->attributes->get('_route_params')); + $this->assertEquals(['foo' => 'bar', '_controller' => 'foo'], $request->attributes->get('_route_params')); $this->assertFalse($request->query->has('_path')); } @@ -95,7 +91,7 @@ class FragmentListenerTest extends TestCase $request = Request::create('http://example.com/_fragment?_path=foo%3Dbar%26_controller%3Dfoo'); $listener = new FragmentListener(new UriSigner('foo')); - $event = $this->createGetResponseEvent($request, HttpKernelInterface::SUB_REQUEST); + $event = $this->createRequestEvent($request, HttpKernelInterface::SUB_REQUEST); $listener->onKernelRequest($event); @@ -105,18 +101,18 @@ class FragmentListenerTest extends TestCase public function testRemovesPathWithControllerNotDefined() { $signer = new UriSigner('foo'); - $request = Request::create($signer->sign('http://example.com/_fragment?_path=foo%3Dbar'), 'GET', array(), array(), array(), array('REMOTE_ADDR' => '10.0.0.1')); + $request = Request::create($signer->sign('http://example.com/_fragment?_path=foo%3Dbar'), 'GET', [], [], [], ['REMOTE_ADDR' => '10.0.0.1']); $listener = new FragmentListener($signer); - $event = $this->createGetResponseEvent($request); + $event = $this->createRequestEvent($request); $listener->onKernelRequest($event); $this->assertFalse($request->query->has('_path')); } - private function createGetResponseEvent(Request $request, $requestType = HttpKernelInterface::MASTER_REQUEST) + private function createRequestEvent(Request $request, $requestType = HttpKernelInterface::MASTER_REQUEST) { - return new GetResponseEvent($this->getMockBuilder('Symfony\Component\HttpKernel\HttpKernelInterface')->getMock(), $request, $requestType); + return new RequestEvent($this->getMockBuilder(HttpKernelInterface::class)->getMock(), $request, $requestType); } } diff --git a/vendor/symfony/http-kernel/Tests/EventListener/LocaleAwareListenerTest.php b/vendor/symfony/http-kernel/Tests/EventListener/LocaleAwareListenerTest.php new file mode 100644 index 0000000000000000000000000000000000000000..ef3b7d1b429970049a2dd67292bad0e83bcc371e --- /dev/null +++ b/vendor/symfony/http-kernel/Tests/EventListener/LocaleAwareListenerTest.php @@ -0,0 +1,119 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Tests\EventListener; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\RequestStack; +use Symfony\Component\HttpKernel\Event\FinishRequestEvent; +use Symfony\Component\HttpKernel\Event\RequestEvent; +use Symfony\Component\HttpKernel\EventListener\LocaleAwareListener; +use Symfony\Component\HttpKernel\HttpKernelInterface; +use Symfony\Contracts\Translation\LocaleAwareInterface; + +class LocaleAwareListenerTest extends TestCase +{ + private $listener; + private $localeAwareService; + private $requestStack; + + protected function setUp(): void + { + $this->localeAwareService = $this->getMockBuilder(LocaleAwareInterface::class)->getMock(); + $this->requestStack = new RequestStack(); + $this->listener = new LocaleAwareListener(new \ArrayIterator([$this->localeAwareService]), $this->requestStack); + } + + public function testLocaleIsSetInOnKernelRequest() + { + $this->localeAwareService + ->expects($this->once()) + ->method('setLocale') + ->with($this->equalTo('fr')); + + $event = new RequestEvent($this->createHttpKernel(), $this->createRequest('fr'), HttpKernelInterface::MASTER_REQUEST); + $this->listener->onKernelRequest($event); + } + + public function testDefaultLocaleIsUsedOnExceptionsInOnKernelRequest() + { + $this->localeAwareService + ->expects($this->at(0)) + ->method('setLocale') + ->will($this->throwException(new \InvalidArgumentException())); + $this->localeAwareService + ->expects($this->at(1)) + ->method('setLocale') + ->with($this->equalTo('en')); + + $event = new RequestEvent($this->createHttpKernel(), $this->createRequest('fr'), HttpKernelInterface::MASTER_REQUEST); + $this->listener->onKernelRequest($event); + } + + public function testLocaleIsSetInOnKernelFinishRequestWhenParentRequestExists() + { + $this->localeAwareService + ->expects($this->once()) + ->method('setLocale') + ->with($this->equalTo('fr')); + + $this->requestStack->push($this->createRequest('fr')); + $this->requestStack->push($subRequest = $this->createRequest('de')); + + $event = new FinishRequestEvent($this->createHttpKernel(), $subRequest, HttpKernelInterface::SUB_REQUEST); + $this->listener->onKernelFinishRequest($event); + } + + public function testLocaleIsSetToDefaultOnKernelFinishRequestWhenParentRequestDoesNotExist() + { + $this->localeAwareService + ->expects($this->once()) + ->method('setLocale') + ->with($this->equalTo('en')); + + $this->requestStack->push($subRequest = $this->createRequest('de')); + + $event = new FinishRequestEvent($this->createHttpKernel(), $subRequest, HttpKernelInterface::SUB_REQUEST); + $this->listener->onKernelFinishRequest($event); + } + + public function testDefaultLocaleIsUsedOnExceptionsInOnKernelFinishRequest() + { + $this->localeAwareService + ->expects($this->at(0)) + ->method('setLocale') + ->will($this->throwException(new \InvalidArgumentException())); + $this->localeAwareService + ->expects($this->at(1)) + ->method('setLocale') + ->with($this->equalTo('en')); + + $this->requestStack->push($this->createRequest('fr')); + $this->requestStack->push($subRequest = $this->createRequest('de')); + + $event = new FinishRequestEvent($this->createHttpKernel(), $subRequest, HttpKernelInterface::SUB_REQUEST); + $this->listener->onKernelFinishRequest($event); + } + + private function createHttpKernel() + { + return $this->getMockBuilder('Symfony\Component\HttpKernel\HttpKernelInterface')->getMock(); + } + + private function createRequest($locale) + { + $request = new Request(); + $request->setLocale($locale); + + return $request; + } +} diff --git a/vendor/symfony/http-kernel/Tests/EventListener/LocaleListenerTest.php b/vendor/symfony/http-kernel/Tests/EventListener/LocaleListenerTest.php index 332393eead2fcf8a895081de5be8f744d640f215..a83b81741b6f2973a3be81c31fb0fc36fad1bbae 100644 --- a/vendor/symfony/http-kernel/Tests/EventListener/LocaleListenerTest.php +++ b/vendor/symfony/http-kernel/Tests/EventListener/LocaleListenerTest.php @@ -12,26 +12,44 @@ namespace Symfony\Component\HttpKernel\Tests\EventListener; use PHPUnit\Framework\TestCase; +use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpKernel\Event\RequestEvent; use Symfony\Component\HttpKernel\EventListener\LocaleListener; use Symfony\Component\HttpKernel\HttpKernelInterface; -use Symfony\Component\HttpKernel\Event\GetResponseEvent; +use Symfony\Component\HttpKernel\KernelEvents; class LocaleListenerTest extends TestCase { private $requestStack; - protected function setUp() + protected function setUp(): void { $this->requestStack = $this->getMockBuilder('Symfony\Component\HttpFoundation\RequestStack')->disableOriginalConstructor()->getMock(); } - public function testDefaultLocaleWithoutSession() + public function testIsAnEventSubscriber() + { + $this->assertInstanceOf(EventSubscriberInterface::class, new LocaleListener($this->requestStack)); + } + + public function testRegisteredEvent() + { + $this->assertEquals( + [ + KernelEvents::REQUEST => [['setDefaultLocale', 100], ['onKernelRequest', 16]], + KernelEvents::FINISH_REQUEST => [['onKernelFinishRequest', 0]], + ], + LocaleListener::getSubscribedEvents() + ); + } + + public function testDefaultLocale() { $listener = new LocaleListener($this->requestStack, 'fr'); $event = $this->getEvent($request = Request::create('/')); - $listener->onKernelRequest($event); + $listener->setDefaultLocale($event); $this->assertEquals('fr', $request->getLocale()); } @@ -54,8 +72,8 @@ class LocaleListenerTest extends TestCase $context = $this->getMockBuilder('Symfony\Component\Routing\RequestContext')->getMock(); $context->expects($this->once())->method('setParameter')->with('_locale', 'es'); - $router = $this->getMockBuilder('Symfony\Component\Routing\Router')->setMethods(array('getContext'))->disableOriginalConstructor()->getMock(); - $router->expects($this->once())->method('getContext')->will($this->returnValue($context)); + $router = $this->getMockBuilder('Symfony\Component\Routing\Router')->setMethods(['getContext'])->disableOriginalConstructor()->getMock(); + $router->expects($this->once())->method('getContext')->willReturn($context); $request = Request::create('/'); @@ -70,13 +88,13 @@ class LocaleListenerTest extends TestCase $context = $this->getMockBuilder('Symfony\Component\Routing\RequestContext')->getMock(); $context->expects($this->once())->method('setParameter')->with('_locale', 'es'); - $router = $this->getMockBuilder('Symfony\Component\Routing\Router')->setMethods(array('getContext'))->disableOriginalConstructor()->getMock(); - $router->expects($this->once())->method('getContext')->will($this->returnValue($context)); + $router = $this->getMockBuilder('Symfony\Component\Routing\Router')->setMethods(['getContext'])->disableOriginalConstructor()->getMock(); + $router->expects($this->once())->method('getContext')->willReturn($context); $parentRequest = Request::create('/'); $parentRequest->setLocale('es'); - $this->requestStack->expects($this->once())->method('getParentRequest')->will($this->returnValue($parentRequest)); + $this->requestStack->expects($this->once())->method('getParentRequest')->willReturn($parentRequest); $event = $this->getMockBuilder('Symfony\Component\HttpKernel\Event\FinishRequestEvent')->disableOriginalConstructor()->getMock(); @@ -95,8 +113,8 @@ class LocaleListenerTest extends TestCase $this->assertEquals('de', $request->getLocale()); } - private function getEvent(Request $request) + private function getEvent(Request $request): RequestEvent { - return new GetResponseEvent($this->getMockBuilder('Symfony\Component\HttpKernel\HttpKernelInterface')->getMock(), $request, HttpKernelInterface::MASTER_REQUEST); + return new RequestEvent($this->getMockBuilder('Symfony\Component\HttpKernel\HttpKernelInterface')->getMock(), $request, HttpKernelInterface::MASTER_REQUEST); } } diff --git a/vendor/symfony/http-kernel/Tests/EventListener/ProfilerListenerTest.php b/vendor/symfony/http-kernel/Tests/EventListener/ProfilerListenerTest.php index 751aee8695f37d23c0a11eacaa6a708e13b4d396..3aaff12316d12269323d13128c5010329c8cb41c 100644 --- a/vendor/symfony/http-kernel/Tests/EventListener/ProfilerListenerTest.php +++ b/vendor/symfony/http-kernel/Tests/EventListener/ProfilerListenerTest.php @@ -13,12 +13,13 @@ namespace Symfony\Component\HttpKernel\Tests\EventListener; use PHPUnit\Framework\TestCase; use Symfony\Component\HttpFoundation\RequestStack; +use Symfony\Component\HttpKernel\Event\ExceptionEvent; +use Symfony\Component\HttpKernel\Event\ResponseEvent; +use Symfony\Component\HttpKernel\Event\TerminateEvent; use Symfony\Component\HttpKernel\EventListener\ProfilerListener; -use Symfony\Component\HttpKernel\Event\FilterResponseEvent; -use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent; -use Symfony\Component\HttpKernel\Event\PostResponseEvent; use Symfony\Component\HttpKernel\Exception\HttpException; use Symfony\Component\HttpKernel\Kernel; +use Symfony\Component\HttpKernel\Profiler\Profile; class ProfilerListenerTest extends TestCase { @@ -27,9 +28,7 @@ class ProfilerListenerTest extends TestCase */ public function testKernelTerminate() { - $profile = $this->getMockBuilder('Symfony\Component\HttpKernel\Profiler\Profile') - ->disableOriginalConstructor() - ->getMock(); + $profile = new Profile('token'); $profiler = $this->getMockBuilder('Symfony\Component\HttpKernel\Profiler\Profiler') ->disableOriginalConstructor() @@ -37,7 +36,7 @@ class ProfilerListenerTest extends TestCase $profiler->expects($this->once()) ->method('collect') - ->will($this->returnValue($profile)); + ->willReturn($profile); $kernel = $this->getMockBuilder('Symfony\Component\HttpKernel\HttpKernelInterface')->getMock(); @@ -60,12 +59,12 @@ class ProfilerListenerTest extends TestCase $listener = new ProfilerListener($profiler, $requestStack, null, $onlyException); // master request - $listener->onKernelResponse(new FilterResponseEvent($kernel, $masterRequest, Kernel::MASTER_REQUEST, $response)); + $listener->onKernelResponse(new ResponseEvent($kernel, $masterRequest, Kernel::MASTER_REQUEST, $response)); // sub request - $listener->onKernelException(new GetResponseForExceptionEvent($kernel, $subRequest, Kernel::SUB_REQUEST, new HttpException(404))); - $listener->onKernelResponse(new FilterResponseEvent($kernel, $subRequest, Kernel::SUB_REQUEST, $response)); + $listener->onKernelException(new ExceptionEvent($kernel, $subRequest, Kernel::SUB_REQUEST, new HttpException(404))); + $listener->onKernelResponse(new ResponseEvent($kernel, $subRequest, Kernel::SUB_REQUEST, $response)); - $listener->onKernelTerminate(new PostResponseEvent($kernel, $masterRequest, $response)); + $listener->onKernelTerminate(new TerminateEvent($kernel, $masterRequest, $response)); } } diff --git a/vendor/symfony/http-kernel/Tests/EventListener/ResponseListenerTest.php b/vendor/symfony/http-kernel/Tests/EventListener/ResponseListenerTest.php index 12a31eb3eeedfb2f3fe0d6ce030267c0bf892d9c..1aaa64bc89ced517431f65f331cc09a6c0118394 100644 --- a/vendor/symfony/http-kernel/Tests/EventListener/ResponseListenerTest.php +++ b/vendor/symfony/http-kernel/Tests/EventListener/ResponseListenerTest.php @@ -12,13 +12,13 @@ namespace Symfony\Component\HttpKernel\Tests\EventListener; use PHPUnit\Framework\TestCase; -use Symfony\Component\HttpKernel\EventListener\ResponseListener; +use Symfony\Component\EventDispatcher\EventDispatcher; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpKernel\Event\ResponseEvent; +use Symfony\Component\HttpKernel\EventListener\ResponseListener; use Symfony\Component\HttpKernel\HttpKernelInterface; -use Symfony\Component\HttpKernel\Event\FilterResponseEvent; use Symfony\Component\HttpKernel\KernelEvents; -use Symfony\Component\EventDispatcher\EventDispatcher; class ResponseListenerTest extends TestCase { @@ -26,16 +26,16 @@ class ResponseListenerTest extends TestCase private $kernel; - protected function setUp() + protected function setUp(): void { $this->dispatcher = new EventDispatcher(); $listener = new ResponseListener('UTF-8'); - $this->dispatcher->addListener(KernelEvents::RESPONSE, array($listener, 'onKernelResponse')); + $this->dispatcher->addListener(KernelEvents::RESPONSE, [$listener, 'onKernelResponse']); $this->kernel = $this->getMockBuilder('Symfony\Component\HttpKernel\HttpKernelInterface')->getMock(); } - protected function tearDown() + protected function tearDown(): void { $this->dispatcher = null; $this->kernel = null; @@ -45,8 +45,8 @@ class ResponseListenerTest extends TestCase { $response = new Response('foo'); - $event = new FilterResponseEvent($this->kernel, new Request(), HttpKernelInterface::SUB_REQUEST, $response); - $this->dispatcher->dispatch(KernelEvents::RESPONSE, $event); + $event = new ResponseEvent($this->kernel, new Request(), HttpKernelInterface::SUB_REQUEST, $response); + $this->dispatcher->dispatch($event, KernelEvents::RESPONSE); $this->assertEquals('', $event->getResponse()->headers->get('content-type')); } @@ -54,12 +54,12 @@ class ResponseListenerTest extends TestCase public function testFilterSetsNonDefaultCharsetIfNotOverridden() { $listener = new ResponseListener('ISO-8859-15'); - $this->dispatcher->addListener(KernelEvents::RESPONSE, array($listener, 'onKernelResponse'), 1); + $this->dispatcher->addListener(KernelEvents::RESPONSE, [$listener, 'onKernelResponse'], 1); $response = new Response('foo'); - $event = new FilterResponseEvent($this->kernel, Request::create('/'), HttpKernelInterface::MASTER_REQUEST, $response); - $this->dispatcher->dispatch(KernelEvents::RESPONSE, $event); + $event = new ResponseEvent($this->kernel, Request::create('/'), HttpKernelInterface::MASTER_REQUEST, $response); + $this->dispatcher->dispatch($event, KernelEvents::RESPONSE); $this->assertEquals('ISO-8859-15', $response->getCharset()); } @@ -67,13 +67,13 @@ class ResponseListenerTest extends TestCase public function testFilterDoesNothingIfCharsetIsOverridden() { $listener = new ResponseListener('ISO-8859-15'); - $this->dispatcher->addListener(KernelEvents::RESPONSE, array($listener, 'onKernelResponse'), 1); + $this->dispatcher->addListener(KernelEvents::RESPONSE, [$listener, 'onKernelResponse'], 1); $response = new Response('foo'); $response->setCharset('ISO-8859-1'); - $event = new FilterResponseEvent($this->kernel, Request::create('/'), HttpKernelInterface::MASTER_REQUEST, $response); - $this->dispatcher->dispatch(KernelEvents::RESPONSE, $event); + $event = new ResponseEvent($this->kernel, Request::create('/'), HttpKernelInterface::MASTER_REQUEST, $response); + $this->dispatcher->dispatch($event, KernelEvents::RESPONSE); $this->assertEquals('ISO-8859-1', $response->getCharset()); } @@ -81,14 +81,14 @@ class ResponseListenerTest extends TestCase public function testFiltersSetsNonDefaultCharsetIfNotOverriddenOnNonTextContentType() { $listener = new ResponseListener('ISO-8859-15'); - $this->dispatcher->addListener(KernelEvents::RESPONSE, array($listener, 'onKernelResponse'), 1); + $this->dispatcher->addListener(KernelEvents::RESPONSE, [$listener, 'onKernelResponse'], 1); $response = new Response('foo'); $request = Request::create('/'); $request->setRequestFormat('application/json'); - $event = new FilterResponseEvent($this->kernel, $request, HttpKernelInterface::MASTER_REQUEST, $response); - $this->dispatcher->dispatch(KernelEvents::RESPONSE, $event); + $event = new ResponseEvent($this->kernel, $request, HttpKernelInterface::MASTER_REQUEST, $response); + $this->dispatcher->dispatch($event, KernelEvents::RESPONSE); $this->assertEquals('ISO-8859-15', $response->getCharset()); } diff --git a/vendor/symfony/http-kernel/Tests/EventListener/RouterListenerTest.php b/vendor/symfony/http-kernel/Tests/EventListener/RouterListenerTest.php index 342dfc367527df49f99a9631a50c31bc8a60c2de..ea88d4b34fa31c908fd328d1cfd028c100316523 100644 --- a/vendor/symfony/http-kernel/Tests/EventListener/RouterListenerTest.php +++ b/vendor/symfony/http-kernel/Tests/EventListener/RouterListenerTest.php @@ -18,12 +18,12 @@ use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\Controller\ArgumentResolver; use Symfony\Component\HttpKernel\Controller\ControllerResolver; +use Symfony\Component\HttpKernel\Event\RequestEvent; use Symfony\Component\HttpKernel\EventListener\ExceptionListener; use Symfony\Component\HttpKernel\EventListener\RouterListener; use Symfony\Component\HttpKernel\EventListener\ValidateRequestListener; -use Symfony\Component\HttpKernel\HttpKernelInterface; use Symfony\Component\HttpKernel\HttpKernel; -use Symfony\Component\HttpKernel\Event\GetResponseEvent; +use Symfony\Component\HttpKernel\HttpKernelInterface; use Symfony\Component\Routing\Exception\NoConfigurationException; use Symfony\Component\Routing\RequestContext; @@ -31,7 +31,7 @@ class RouterListenerTest extends TestCase { private $requestStack; - protected function setUp() + protected function setUp(): void { $this->requestStack = $this->getMockBuilder('Symfony\Component\HttpFoundation\RequestStack')->disableOriginalConstructor()->getMock(); } @@ -49,10 +49,10 @@ class RouterListenerTest extends TestCase $context->setHttpsPort($defaultHttpsPort); $urlMatcher->expects($this->any()) ->method('getContext') - ->will($this->returnValue($context)); + ->willReturn($context); $listener = new RouterListener($urlMatcher, $this->requestStack); - $event = $this->createGetResponseEventForUri($uri); + $event = $this->createRequestEventForUri($uri); $listener->onKernelRequest($event); $this->assertEquals($expectedHttpPort, $context->getHttpPort()); @@ -62,47 +62,40 @@ class RouterListenerTest extends TestCase public function getPortData() { - return array( - array(80, 443, 'http://localhost/', 80, 443), - array(80, 443, 'http://localhost:90/', 90, 443), - array(80, 443, 'https://localhost/', 80, 443), - array(80, 443, 'https://localhost:90/', 80, 90), - ); + return [ + [80, 443, 'http://localhost/', 80, 443], + [80, 443, 'http://localhost:90/', 90, 443], + [80, 443, 'https://localhost/', 80, 443], + [80, 443, 'https://localhost:90/', 80, 90], + ]; } - /** - * @param string $uri - * - * @return GetResponseEvent - */ - private function createGetResponseEventForUri($uri) + private function createRequestEventForUri(string $uri): RequestEvent { - $kernel = $this->getMockBuilder('Symfony\Component\HttpKernel\HttpKernelInterface')->getMock(); + $kernel = $this->getMockBuilder(HttpKernelInterface::class)->getMock(); $request = Request::create($uri); $request->attributes->set('_controller', null); // Prevents going in to routing process - return new GetResponseEvent($kernel, $request, HttpKernelInterface::MASTER_REQUEST); + return new RequestEvent($kernel, $request, HttpKernelInterface::MASTER_REQUEST); } - /** - * @expectedException \InvalidArgumentException - */ public function testInvalidMatcher() { + $this->expectException('InvalidArgumentException'); new RouterListener(new \stdClass(), $this->requestStack); } public function testRequestMatcher() { - $kernel = $this->getMockBuilder('Symfony\Component\HttpKernel\HttpKernelInterface')->getMock(); + $kernel = $this->getMockBuilder(HttpKernelInterface::class)->getMock(); $request = Request::create('http://localhost/'); - $event = new GetResponseEvent($kernel, $request, HttpKernelInterface::MASTER_REQUEST); + $event = new RequestEvent($kernel, $request, HttpKernelInterface::MASTER_REQUEST); $requestMatcher = $this->getMockBuilder('Symfony\Component\Routing\Matcher\RequestMatcherInterface')->getMock(); $requestMatcher->expects($this->once()) ->method('matchRequest') ->with($this->isInstanceOf('Symfony\Component\HttpFoundation\Request')) - ->will($this->returnValue(array())); + ->willReturn([]); $listener = new RouterListener($requestMatcher, $this->requestStack, new RequestContext()); $listener->onKernelRequest($event); @@ -110,15 +103,15 @@ class RouterListenerTest extends TestCase public function testSubRequestWithDifferentMethod() { - $kernel = $this->getMockBuilder('Symfony\Component\HttpKernel\HttpKernelInterface')->getMock(); + $kernel = $this->getMockBuilder(HttpKernelInterface::class)->getMock(); $request = Request::create('http://localhost/', 'post'); - $event = new GetResponseEvent($kernel, $request, HttpKernelInterface::MASTER_REQUEST); + $event = new RequestEvent($kernel, $request, HttpKernelInterface::MASTER_REQUEST); $requestMatcher = $this->getMockBuilder('Symfony\Component\Routing\Matcher\RequestMatcherInterface')->getMock(); $requestMatcher->expects($this->any()) ->method('matchRequest') ->with($this->isInstanceOf('Symfony\Component\HttpFoundation\Request')) - ->will($this->returnValue(array())); + ->willReturn([]); $context = new RequestContext(); @@ -126,9 +119,9 @@ class RouterListenerTest extends TestCase $listener->onKernelRequest($event); // sub-request with another HTTP method - $kernel = $this->getMockBuilder('Symfony\Component\HttpKernel\HttpKernelInterface')->getMock(); + $kernel = $this->getMockBuilder(HttpKernelInterface::class)->getMock(); $request = Request::create('http://localhost/', 'get'); - $event = new GetResponseEvent($kernel, $request, HttpKernelInterface::SUB_REQUEST); + $event = new RequestEvent($kernel, $request, HttpKernelInterface::SUB_REQUEST); $listener->onKernelRequest($event); @@ -143,26 +136,26 @@ class RouterListenerTest extends TestCase $requestMatcher = $this->getMockBuilder('Symfony\Component\Routing\Matcher\RequestMatcherInterface')->getMock(); $requestMatcher->expects($this->once()) ->method('matchRequest') - ->will($this->returnValue($parameter)); + ->willReturn($parameter); $logger = $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock(); $logger->expects($this->once()) ->method('info') ->with($this->equalTo($log), $this->equalTo($parameters)); - $kernel = $this->getMockBuilder('Symfony\Component\HttpKernel\HttpKernelInterface')->getMock(); + $kernel = $this->getMockBuilder(HttpKernelInterface::class)->getMock(); $request = Request::create('http://localhost/'); $listener = new RouterListener($requestMatcher, $this->requestStack, new RequestContext(), $logger); - $listener->onKernelRequest(new GetResponseEvent($kernel, $request, HttpKernelInterface::MASTER_REQUEST)); + $listener->onKernelRequest(new RequestEvent($kernel, $request, HttpKernelInterface::MASTER_REQUEST)); } public function getLoggingParameterData() { - return array( - array(array('_route' => 'foo'), 'Matched route "{route}".', array('route' => 'foo', 'route_parameters' => array('_route' => 'foo'), 'request_uri' => 'http://localhost/', 'method' => 'GET')), - array(array(), 'Matched route "{route}".', array('route' => 'n/a', 'route_parameters' => array(), 'request_uri' => 'http://localhost/', 'method' => 'GET')), - ); + return [ + [['_route' => 'foo'], 'Matched route "{route}".', ['route' => 'foo', 'route_parameters' => ['_route' => 'foo'], 'request_uri' => 'http://localhost/', 'method' => 'GET']], + [[], 'Matched route "{route}".', ['route' => 'n/a', 'route_parameters' => [], 'request_uri' => 'http://localhost/', 'method' => 'GET']], + ]; } public function testWithBadRequest() @@ -206,17 +199,15 @@ class RouterListenerTest extends TestCase $request = Request::create('http://localhost/'); $response = $kernel->handle($request); $this->assertSame(404, $response->getStatusCode()); - $this->assertContains('Welcome', $response->getContent()); + $this->assertStringContainsString('Welcome', $response->getContent()); } - /** - * @expectedException \Symfony\Component\HttpKernel\Exception\BadRequestHttpException - */ public function testRequestWithBadHost() { - $kernel = $this->getMockBuilder('Symfony\Component\HttpKernel\HttpKernelInterface')->getMock(); + $this->expectException('Symfony\Component\HttpKernel\Exception\BadRequestHttpException'); + $kernel = $this->getMockBuilder(HttpKernelInterface::class)->getMock(); $request = Request::create('http://bad host %22/'); - $event = new GetResponseEvent($kernel, $request, HttpKernelInterface::MASTER_REQUEST); + $event = new RequestEvent($kernel, $request, HttpKernelInterface::MASTER_REQUEST); $requestMatcher = $this->getMockBuilder('Symfony\Component\Routing\Matcher\RequestMatcherInterface')->getMock(); diff --git a/vendor/symfony/http-kernel/Tests/EventListener/SaveSessionListenerTest.php b/vendor/symfony/http-kernel/Tests/EventListener/SaveSessionListenerTest.php index 5492c3d78480530640f4dca16bbbbff606fa3c74..6cdd7476c9b7f1a44556d55f912628ab6a38ae59 100644 --- a/vendor/symfony/http-kernel/Tests/EventListener/SaveSessionListenerTest.php +++ b/vendor/symfony/http-kernel/Tests/EventListener/SaveSessionListenerTest.php @@ -15,16 +15,19 @@ use PHPUnit\Framework\TestCase; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Session\SessionInterface; -use Symfony\Component\HttpKernel\Event\FilterResponseEvent; +use Symfony\Component\HttpKernel\Event\ResponseEvent; use Symfony\Component\HttpKernel\EventListener\SaveSessionListener; use Symfony\Component\HttpKernel\HttpKernelInterface; +/** + * @group legacy + */ class SaveSessionListenerTest extends TestCase { public function testOnlyTriggeredOnMasterRequest() { $listener = new SaveSessionListener(); - $event = $this->getMockBuilder(FilterResponseEvent::class)->disableOriginalConstructor()->getMock(); + $event = $this->getMockBuilder(ResponseEvent::class)->disableOriginalConstructor()->getMock(); $event->expects($this->once())->method('isMasterRequest')->willReturn(false); $event->expects($this->never())->method('getRequest'); @@ -44,6 +47,6 @@ class SaveSessionListenerTest extends TestCase $request = new Request(); $request->setSession($session); $response = new Response(); - $listener->onKernelResponse(new FilterResponseEvent($kernel, $request, HttpKernelInterface::MASTER_REQUEST, $response)); + $listener->onKernelResponse(new ResponseEvent($kernel, $request, HttpKernelInterface::MASTER_REQUEST, $response)); } } diff --git a/vendor/symfony/http-kernel/Tests/EventListener/SessionListenerTest.php b/vendor/symfony/http-kernel/Tests/EventListener/SessionListenerTest.php index 34598363c8914b30e043e7a79eef01434c6b8f4c..8fc9f6bc9c3772b1f161356e0e9a0c7b63837a79 100644 --- a/vendor/symfony/http-kernel/Tests/EventListener/SessionListenerTest.php +++ b/vendor/symfony/http-kernel/Tests/EventListener/SessionListenerTest.php @@ -13,11 +13,15 @@ namespace Symfony\Component\HttpKernel\Tests\EventListener; use PHPUnit\Framework\TestCase; use Symfony\Component\DependencyInjection\Container; +use Symfony\Component\DependencyInjection\ServiceLocator; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Session\Session; -use Symfony\Component\HttpKernel\Event\GetResponseEvent; -use Symfony\Component\HttpKernel\Event\FilterResponseEvent; +use Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage; +use Symfony\Component\HttpKernel\Event\FinishRequestEvent; +use Symfony\Component\HttpKernel\Event\RequestEvent; +use Symfony\Component\HttpKernel\Event\ResponseEvent; use Symfony\Component\HttpKernel\EventListener\AbstractSessionListener; use Symfony\Component\HttpKernel\EventListener\SessionListener; use Symfony\Component\HttpKernel\HttpKernelInterface; @@ -27,7 +31,7 @@ class SessionListenerTest extends TestCase public function testOnlyTriggeredOnMasterRequest() { $listener = $this->getMockForAbstractClass(AbstractSessionListener::class); - $event = $this->getMockBuilder(GetResponseEvent::class)->disableOriginalConstructor()->getMock(); + $event = $this->getMockBuilder(RequestEvent::class)->disableOriginalConstructor()->getMock(); $event->expects($this->once())->method('isMasterRequest')->willReturn(false); $event->expects($this->never())->method('getRequest'); @@ -39,13 +43,21 @@ class SessionListenerTest extends TestCase { $session = $this->getMockBuilder(Session::class)->disableOriginalConstructor()->getMock(); + $requestStack = $this->getMockBuilder(RequestStack::class)->getMock(); + $requestStack->expects($this->once())->method('getMasterRequest')->willReturn(null); + + $sessionStorage = $this->getMockBuilder(NativeSessionStorage::class)->getMock(); + $sessionStorage->expects($this->never())->method('setOptions')->with(['cookie_secure' => true]); + $container = new Container(); $container->set('session', $session); + $container->set('request_stack', $requestStack); + $container->set('session_storage', $sessionStorage); $request = new Request(); $listener = new SessionListener($container); - $event = $this->getMockBuilder(GetResponseEvent::class)->disableOriginalConstructor()->getMock(); + $event = $this->getMockBuilder(RequestEvent::class)->disableOriginalConstructor()->getMock(); $event->expects($this->once())->method('isMasterRequest')->willReturn(true); $event->expects($this->once())->method('getRequest')->willReturn($request); @@ -55,13 +67,86 @@ class SessionListenerTest extends TestCase $this->assertSame($session, $request->getSession()); } - public function testResponseIsPrivate() + public function testResponseIsPrivateIfSessionStarted() { $session = $this->getMockBuilder(Session::class)->disableOriginalConstructor()->getMock(); - $session->expects($this->once())->method('isStarted')->willReturn(false); - $session->expects($this->once())->method('hasBeenStarted')->willReturn(true); + $session->expects($this->exactly(2))->method('getUsageIndex')->will($this->onConsecutiveCalls(0, 1)); $container = new Container(); + $container->set('initialized_session', $session); + + $listener = new SessionListener($container); + $kernel = $this->getMockBuilder(HttpKernelInterface::class)->disableOriginalConstructor()->getMock(); + + $request = new Request(); + $listener->onKernelRequest(new RequestEvent($kernel, $request, HttpKernelInterface::MASTER_REQUEST)); + + $response = new Response(); + $listener->onKernelResponse(new ResponseEvent($kernel, new Request(), HttpKernelInterface::MASTER_REQUEST, $response)); + + $this->assertTrue($response->headers->has('Expires')); + $this->assertTrue($response->headers->hasCacheControlDirective('private')); + $this->assertTrue($response->headers->hasCacheControlDirective('must-revalidate')); + $this->assertSame('0', $response->headers->getCacheControlDirective('max-age')); + $this->assertLessThanOrEqual((new \DateTime('now', new \DateTimeZone('UTC'))), (new \DateTime($response->headers->get('Expires')))); + $this->assertFalse($response->headers->has(AbstractSessionListener::NO_AUTO_CACHE_CONTROL_HEADER)); + } + + public function testResponseIsStillPublicIfSessionStartedAndHeaderPresent() + { + $session = $this->getMockBuilder(Session::class)->disableOriginalConstructor()->getMock(); + $session->expects($this->exactly(2))->method('getUsageIndex')->will($this->onConsecutiveCalls(0, 1)); + + $container = new Container(); + $container->set('initialized_session', $session); + + $listener = new SessionListener($container); + $kernel = $this->getMockBuilder(HttpKernelInterface::class)->disableOriginalConstructor()->getMock(); + + $request = new Request(); + $listener->onKernelRequest(new RequestEvent($kernel, $request, HttpKernelInterface::MASTER_REQUEST)); + + $response = new Response(); + $response->setSharedMaxAge(60); + $response->headers->set(AbstractSessionListener::NO_AUTO_CACHE_CONTROL_HEADER, 'true'); + $listener->onKernelResponse(new ResponseEvent($kernel, new Request(), HttpKernelInterface::MASTER_REQUEST, $response)); + + $this->assertTrue($response->headers->hasCacheControlDirective('public')); + $this->assertFalse($response->headers->has('Expires')); + $this->assertFalse($response->headers->hasCacheControlDirective('private')); + $this->assertFalse($response->headers->hasCacheControlDirective('must-revalidate')); + $this->assertSame('60', $response->headers->getCacheControlDirective('s-maxage')); + $this->assertFalse($response->headers->has(AbstractSessionListener::NO_AUTO_CACHE_CONTROL_HEADER)); + } + + public function testUninitializedSession() + { + $kernel = $this->getMockBuilder(HttpKernelInterface::class)->disableOriginalConstructor()->getMock(); + $response = new Response(); + $response->setSharedMaxAge(60); + $response->headers->set(AbstractSessionListener::NO_AUTO_CACHE_CONTROL_HEADER, 'true'); + + $container = new ServiceLocator([ + 'initialized_session' => function () {}, + ]); + + $listener = new SessionListener($container); + $listener->onKernelResponse(new ResponseEvent($kernel, new Request(), HttpKernelInterface::MASTER_REQUEST, $response)); + $this->assertFalse($response->headers->has('Expires')); + $this->assertTrue($response->headers->hasCacheControlDirective('public')); + $this->assertFalse($response->headers->hasCacheControlDirective('private')); + $this->assertFalse($response->headers->hasCacheControlDirective('must-revalidate')); + $this->assertSame('60', $response->headers->getCacheControlDirective('s-maxage')); + $this->assertFalse($response->headers->has(AbstractSessionListener::NO_AUTO_CACHE_CONTROL_HEADER)); + } + + public function testSurrogateMasterRequestIsPublic() + { + $session = $this->getMockBuilder(Session::class)->disableOriginalConstructor()->getMock(); + $session->expects($this->exactly(4))->method('getUsageIndex')->will($this->onConsecutiveCalls(0, 1, 1, 1)); + + $container = new Container(); + $container->set('initialized_session', $session); $container->set('session', $session); $listener = new SessionListener($container); @@ -69,11 +154,28 @@ class SessionListenerTest extends TestCase $request = new Request(); $response = new Response(); - $listener->onKernelRequest(new GetResponseEvent($kernel, $request, HttpKernelInterface::MASTER_REQUEST)); - $listener->onKernelResponse(new FilterResponseEvent($kernel, $request, HttpKernelInterface::MASTER_REQUEST, $response)); + $response->setCache(['public' => true, 'max_age' => '30']); + $listener->onKernelRequest(new RequestEvent($kernel, $request, HttpKernelInterface::MASTER_REQUEST)); + $this->assertTrue($request->hasSession()); + + $subRequest = clone $request; + $this->assertSame($request->getSession(), $subRequest->getSession()); + $listener->onKernelRequest(new RequestEvent($kernel, $subRequest, HttpKernelInterface::MASTER_REQUEST)); + $listener->onKernelResponse(new ResponseEvent($kernel, $subRequest, HttpKernelInterface::MASTER_REQUEST, $response)); + $listener->onFinishRequest(new FinishRequestEvent($kernel, $subRequest, HttpKernelInterface::MASTER_REQUEST)); + + $this->assertFalse($response->headers->has('Expires')); + $this->assertFalse($response->headers->hasCacheControlDirective('private')); + $this->assertFalse($response->headers->hasCacheControlDirective('must-revalidate')); + $this->assertSame('30', $response->headers->getCacheControlDirective('max-age')); + + $listener->onKernelResponse(new ResponseEvent($kernel, $request, HttpKernelInterface::MASTER_REQUEST, $response)); $this->assertTrue($response->headers->hasCacheControlDirective('private')); $this->assertTrue($response->headers->hasCacheControlDirective('must-revalidate')); $this->assertSame('0', $response->headers->getCacheControlDirective('max-age')); + + $this->assertTrue($response->headers->has('Expires')); + $this->assertLessThanOrEqual((new \DateTime('now', new \DateTimeZone('UTC'))), (new \DateTime($response->headers->get('Expires')))); } } diff --git a/vendor/symfony/http-kernel/Tests/EventListener/SurrogateListenerTest.php b/vendor/symfony/http-kernel/Tests/EventListener/SurrogateListenerTest.php index 1e79ebe0523911e80a021cf705c9b1436ce9ee03..fc51de252e81dc18bba4cad1211beda8c48fc7b3 100644 --- a/vendor/symfony/http-kernel/Tests/EventListener/SurrogateListenerTest.php +++ b/vendor/symfony/http-kernel/Tests/EventListener/SurrogateListenerTest.php @@ -12,14 +12,14 @@ namespace Symfony\Component\HttpKernel\Tests\EventListener; use PHPUnit\Framework\TestCase; -use Symfony\Component\HttpKernel\HttpCache\Esi; +use Symfony\Component\EventDispatcher\EventDispatcher; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpKernel\Event\ResponseEvent; use Symfony\Component\HttpKernel\EventListener\SurrogateListener; -use Symfony\Component\HttpKernel\Event\FilterResponseEvent; -use Symfony\Component\HttpKernel\KernelEvents; +use Symfony\Component\HttpKernel\HttpCache\Esi; use Symfony\Component\HttpKernel\HttpKernelInterface; -use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\EventDispatcher\EventDispatcher; +use Symfony\Component\HttpKernel\KernelEvents; class SurrogateListenerTest extends TestCase { @@ -30,9 +30,9 @@ class SurrogateListenerTest extends TestCase $response = new Response('foo <esi:include src="" />'); $listener = new SurrogateListener(new Esi()); - $dispatcher->addListener(KernelEvents::RESPONSE, array($listener, 'onKernelResponse')); - $event = new FilterResponseEvent($kernel, new Request(), HttpKernelInterface::SUB_REQUEST, $response); - $dispatcher->dispatch(KernelEvents::RESPONSE, $event); + $dispatcher->addListener(KernelEvents::RESPONSE, [$listener, 'onKernelResponse']); + $event = new ResponseEvent($kernel, new Request(), HttpKernelInterface::SUB_REQUEST, $response); + $dispatcher->dispatch($event, KernelEvents::RESPONSE); $this->assertEquals('', $event->getResponse()->headers->get('Surrogate-Control')); } @@ -44,9 +44,9 @@ class SurrogateListenerTest extends TestCase $response = new Response('foo <esi:include src="" />'); $listener = new SurrogateListener(new Esi()); - $dispatcher->addListener(KernelEvents::RESPONSE, array($listener, 'onKernelResponse')); - $event = new FilterResponseEvent($kernel, new Request(), HttpKernelInterface::MASTER_REQUEST, $response); - $dispatcher->dispatch(KernelEvents::RESPONSE, $event); + $dispatcher->addListener(KernelEvents::RESPONSE, [$listener, 'onKernelResponse']); + $event = new ResponseEvent($kernel, new Request(), HttpKernelInterface::MASTER_REQUEST, $response); + $dispatcher->dispatch($event, KernelEvents::RESPONSE); $this->assertEquals('content="ESI/1.0"', $event->getResponse()->headers->get('Surrogate-Control')); } @@ -58,9 +58,9 @@ class SurrogateListenerTest extends TestCase $response = new Response('foo'); $listener = new SurrogateListener(new Esi()); - $dispatcher->addListener(KernelEvents::RESPONSE, array($listener, 'onKernelResponse')); - $event = new FilterResponseEvent($kernel, new Request(), HttpKernelInterface::MASTER_REQUEST, $response); - $dispatcher->dispatch(KernelEvents::RESPONSE, $event); + $dispatcher->addListener(KernelEvents::RESPONSE, [$listener, 'onKernelResponse']); + $event = new ResponseEvent($kernel, new Request(), HttpKernelInterface::MASTER_REQUEST, $response); + $dispatcher->dispatch($event, KernelEvents::RESPONSE); $this->assertEquals('', $event->getResponse()->headers->get('Surrogate-Control')); } diff --git a/vendor/symfony/http-kernel/Tests/EventListener/TestSessionListenerTest.php b/vendor/symfony/http-kernel/Tests/EventListener/TestSessionListenerTest.php index 4452f48771b8b73d3a32829faca13fceac5bf0d9..1ae3bb38b5482a08f71bd510388d3417c05f4d36 100644 --- a/vendor/symfony/http-kernel/Tests/EventListener/TestSessionListenerTest.php +++ b/vendor/symfony/http-kernel/Tests/EventListener/TestSessionListenerTest.php @@ -12,14 +12,14 @@ namespace Symfony\Component\HttpKernel\Tests\EventListener; use PHPUnit\Framework\TestCase; -use Symfony\Component\DependencyInjection\ServiceSubscriberInterface; -use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpKernel\HttpKernelInterface; -use Symfony\Component\HttpKernel\Event\FilterResponseEvent; +use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpFoundation\Session\SessionInterface; +use Symfony\Component\HttpKernel\Event\RequestEvent; +use Symfony\Component\HttpKernel\Event\ResponseEvent; use Symfony\Component\HttpKernel\EventListener\SessionListener; use Symfony\Component\HttpKernel\EventListener\TestSessionListener; -use Symfony\Component\HttpFoundation\Session\SessionInterface; +use Symfony\Component\HttpKernel\HttpKernelInterface; /** * SessionListenerTest. @@ -40,10 +40,13 @@ class TestSessionListenerTest extends TestCase */ private $session; - protected function setUp() + protected function setUp(): void { $this->listener = $this->getMockForAbstractClass('Symfony\Component\HttpKernel\EventListener\AbstractTestSessionListener'); $this->session = $this->getSession(); + $this->listener->expects($this->any()) + ->method('getSession') + ->willReturn($this->session); } public function testShouldSaveMasterRequestSession() @@ -83,7 +86,53 @@ class TestSessionListenerTest extends TestCase $response = $this->filterResponse(new Request(), HttpKernelInterface::MASTER_REQUEST); - $this->assertSame(array(), $response->headers->getCookies()); + $this->assertSame([], $response->headers->getCookies()); + } + + public function testEmptySessionWithNewSessionIdDoesSendCookie() + { + $this->sessionHasBeenStarted(); + $this->sessionIsEmpty(); + $this->fixSessionId('456'); + + $kernel = $this->getMockBuilder(HttpKernelInterface::class)->getMock(); + $request = Request::create('/', 'GET', [], ['MOCKSESSID' => '123']); + $event = new RequestEvent($kernel, $request, HttpKernelInterface::MASTER_REQUEST); + $this->listener->onKernelRequest($event); + + $response = $this->filterResponse(new Request(), HttpKernelInterface::MASTER_REQUEST); + + $this->assertNotEmpty($response->headers->getCookies()); + } + + /** + * @dataProvider anotherCookieProvider + */ + public function testSessionWithNewSessionIdAndNewCookieDoesNotSendAnotherCookie($existing, array $expected) + { + $this->sessionHasBeenStarted(); + $this->sessionIsEmpty(); + $this->fixSessionId('456'); + + $kernel = $this->getMockBuilder(HttpKernelInterface::class)->getMock(); + $request = Request::create('/', 'GET', [], ['MOCKSESSID' => '123']); + $event = new RequestEvent($kernel, $request, HttpKernelInterface::MASTER_REQUEST); + $this->listener->onKernelRequest($event); + + $response = new Response('', 200, ['Set-Cookie' => $existing]); + + $response = $this->filterResponse(new Request(), HttpKernelInterface::MASTER_REQUEST, $response); + + $this->assertSame($expected, $response->headers->get('Set-Cookie', null, false)); + } + + public function anotherCookieProvider() + { + return [ + 'same' => ['MOCKSESSID=789; path=/', ['MOCKSESSID=789; path=/']], + 'different domain' => ['MOCKSESSID=789; path=/; domain=example.com', ['MOCKSESSID=789; path=/; domain=example.com', 'MOCKSESSID=456; path=/']], + 'different path' => ['MOCKSESSID=789; path=/foo', ['MOCKSESSID=789; path=/foo', 'MOCKSESSID=456; path=/']], + ]; } public function testUnstartedSessionIsNotSave() @@ -94,21 +143,22 @@ class TestSessionListenerTest extends TestCase $this->filterResponse(new Request()); } - public function testDoesNotImplementServiceSubscriberInterface() + public function testDoesNotThrowIfRequestDoesNotHaveASession() { - $this->assertTrue(interface_exists(ServiceSubscriberInterface::class)); - $this->assertTrue(class_exists(SessionListener::class)); - $this->assertTrue(class_exists(TestSessionListener::class)); - $this->assertFalse(is_subclass_of(SessionListener::class, ServiceSubscriberInterface::class), 'Implementing ServiceSubscriberInterface would create a dep on the DI component, which eg Silex cannot afford'); - $this->assertFalse(is_subclass_of(TestSessionListener::class, ServiceSubscriberInterface::class, 'Implementing ServiceSubscriberInterface would create a dep on the DI component, which eg Silex cannot afford')); + $kernel = $this->getMockBuilder(HttpKernelInterface::class)->getMock(); + $event = new ResponseEvent($kernel, new Request(), HttpKernelInterface::MASTER_REQUEST, new Response()); + + $this->listener->onKernelResponse($event); + + $this->assertTrue(true); } - private function filterResponse(Request $request, $type = HttpKernelInterface::MASTER_REQUEST) + private function filterResponse(Request $request, $type = HttpKernelInterface::MASTER_REQUEST, Response $response = null) { $request->setSession($this->session); - $response = new Response(); - $kernel = $this->getMockBuilder('Symfony\Component\HttpKernel\HttpKernelInterface')->getMock(); - $event = new FilterResponseEvent($kernel, $request, $type, $response); + $response = $response ?: new Response(); + $kernel = $this->getMockBuilder(HttpKernelInterface::class)->getMock(); + $event = new ResponseEvent($kernel, $request, $type, $response); $this->listener->onKernelResponse($event); @@ -133,21 +183,28 @@ class TestSessionListenerTest extends TestCase { $this->session->expects($this->once()) ->method('isStarted') - ->will($this->returnValue(true)); + ->willReturn(true); } private function sessionHasNotBeenStarted() { $this->session->expects($this->once()) ->method('isStarted') - ->will($this->returnValue(false)); + ->willReturn(false); } private function sessionIsEmpty() { $this->session->expects($this->once()) ->method('isEmpty') - ->will($this->returnValue(true)); + ->willReturn(true); + } + + private function fixSessionId($sessionId) + { + $this->session->expects($this->any()) + ->method('getId') + ->willReturn($sessionId); } private function getSession() @@ -157,7 +214,7 @@ class TestSessionListenerTest extends TestCase ->getMock(); // set return value for getName() - $mock->expects($this->any())->method('getName')->will($this->returnValue('MOCKSESSID')); + $mock->expects($this->any())->method('getName')->willReturn('MOCKSESSID'); return $mock; } diff --git a/vendor/symfony/http-kernel/Tests/EventListener/TranslatorListenerTest.php b/vendor/symfony/http-kernel/Tests/EventListener/TranslatorListenerTest.php index 23b833177ab61932cd28a128c164f76f08544e12..17bf4261f95b928f5226b2441c52c44d534bf116 100644 --- a/vendor/symfony/http-kernel/Tests/EventListener/TranslatorListenerTest.php +++ b/vendor/symfony/http-kernel/Tests/EventListener/TranslatorListenerTest.php @@ -14,19 +14,23 @@ namespace Symfony\Component\HttpKernel\Tests\EventListener; use PHPUnit\Framework\TestCase; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\Event\FinishRequestEvent; -use Symfony\Component\HttpKernel\Event\GetResponseEvent; +use Symfony\Component\HttpKernel\Event\RequestEvent; use Symfony\Component\HttpKernel\EventListener\TranslatorListener; use Symfony\Component\HttpKernel\HttpKernelInterface; +use Symfony\Contracts\Translation\LocaleAwareInterface; +/** + * @group legacy + */ class TranslatorListenerTest extends TestCase { private $listener; private $translator; private $requestStack; - protected function setUp() + protected function setUp(): void { - $this->translator = $this->getMockBuilder('Symfony\Component\Translation\TranslatorInterface')->getMock(); + $this->translator = $this->getMockBuilder(LocaleAwareInterface::class)->getMock(); $this->requestStack = $this->getMockBuilder('Symfony\Component\HttpFoundation\RequestStack')->getMock(); $this->listener = new TranslatorListener($this->translator, $this->requestStack); } @@ -38,7 +42,7 @@ class TranslatorListenerTest extends TestCase ->method('setLocale') ->with($this->equalTo('fr')); - $event = new GetResponseEvent($this->createHttpKernel(), $this->createRequest('fr'), HttpKernelInterface::MASTER_REQUEST); + $event = new RequestEvent($this->createHttpKernel(), $this->createRequest('fr'), HttpKernelInterface::MASTER_REQUEST); $this->listener->onKernelRequest($event); } @@ -47,13 +51,13 @@ class TranslatorListenerTest extends TestCase $this->translator ->expects($this->at(0)) ->method('setLocale') - ->will($this->throwException(new \InvalidArgumentException())); + ->willThrowException(new \InvalidArgumentException()); $this->translator ->expects($this->at(1)) ->method('setLocale') ->with($this->equalTo('en')); - $event = new GetResponseEvent($this->createHttpKernel(), $this->createRequest('fr'), HttpKernelInterface::MASTER_REQUEST); + $event = new RequestEvent($this->createHttpKernel(), $this->createRequest('fr'), HttpKernelInterface::MASTER_REQUEST); $this->listener->onKernelRequest($event); } @@ -84,7 +88,7 @@ class TranslatorListenerTest extends TestCase $this->translator ->expects($this->at(0)) ->method('setLocale') - ->will($this->throwException(new \InvalidArgumentException())); + ->willThrowException(new \InvalidArgumentException()); $this->translator ->expects($this->at(1)) ->method('setLocale') @@ -113,6 +117,6 @@ class TranslatorListenerTest extends TestCase $this->requestStack ->expects($this->any()) ->method('getParentRequest') - ->will($this->returnValue($request)); + ->willReturn($request); } } diff --git a/vendor/symfony/http-kernel/Tests/EventListener/ValidateRequestListenerTest.php b/vendor/symfony/http-kernel/Tests/EventListener/ValidateRequestListenerTest.php index d0609432554e19ea16a6806b938157b5a55fefd6..7cec68143bb5423fd799a2d414efad7f137adb55 100644 --- a/vendor/symfony/http-kernel/Tests/EventListener/ValidateRequestListenerTest.php +++ b/vendor/symfony/http-kernel/Tests/EventListener/ValidateRequestListenerTest.php @@ -14,30 +14,33 @@ namespace Symfony\Component\HttpKernel\Tests\EventListener; use PHPUnit\Framework\TestCase; use Symfony\Component\EventDispatcher\EventDispatcher; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpKernel\Event\RequestEvent; use Symfony\Component\HttpKernel\EventListener\ValidateRequestListener; -use Symfony\Component\HttpKernel\Event\GetResponseEvent; use Symfony\Component\HttpKernel\HttpKernelInterface; use Symfony\Component\HttpKernel\KernelEvents; class ValidateRequestListenerTest extends TestCase { - /** - * @expectedException \Symfony\Component\HttpFoundation\Exception\ConflictingHeadersException - */ + protected function tearDown(): void + { + Request::setTrustedProxies([], -1); + } + public function testListenerThrowsWhenMasterRequestHasInconsistentClientIps() { + $this->expectException('Symfony\Component\HttpFoundation\Exception\ConflictingHeadersException'); $dispatcher = new EventDispatcher(); $kernel = $this->getMockBuilder('Symfony\Component\HttpKernel\HttpKernelInterface')->getMock(); $request = new Request(); - $request->setTrustedProxies(array('1.1.1.1'), Request::HEADER_X_FORWARDED_FOR | Request::HEADER_FORWARDED); + $request->setTrustedProxies(['1.1.1.1'], Request::HEADER_X_FORWARDED_FOR | Request::HEADER_FORWARDED); $request->server->set('REMOTE_ADDR', '1.1.1.1'); $request->headers->set('FORWARDED', 'for=2.2.2.2'); $request->headers->set('X_FORWARDED_FOR', '3.3.3.3'); - $dispatcher->addListener(KernelEvents::REQUEST, array(new ValidateRequestListener(), 'onKernelRequest')); - $event = new GetResponseEvent($kernel, $request, HttpKernelInterface::MASTER_REQUEST); + $dispatcher->addListener(KernelEvents::REQUEST, [new ValidateRequestListener(), 'onKernelRequest']); + $event = new RequestEvent($kernel, $request, HttpKernelInterface::MASTER_REQUEST); - $dispatcher->dispatch(KernelEvents::REQUEST, $event); + $dispatcher->dispatch($event, KernelEvents::REQUEST); } } diff --git a/vendor/symfony/http-kernel/Tests/Exception/AccessDeniedHttpExceptionTest.php b/vendor/symfony/http-kernel/Tests/Exception/AccessDeniedHttpExceptionTest.php index 2bfcb2bf8030669a3582256530b2b711b1789316..3a34cc47bce72c0ae1fde02ee1a89df25af17d2e 100644 --- a/vendor/symfony/http-kernel/Tests/Exception/AccessDeniedHttpExceptionTest.php +++ b/vendor/symfony/http-kernel/Tests/Exception/AccessDeniedHttpExceptionTest.php @@ -6,8 +6,8 @@ use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException; class AccessDeniedHttpExceptionTest extends HttpExceptionTest { - protected function createException() + protected function createException(string $message = null, \Throwable $previous = null, ?int $code = 0, array $headers = []) { - return new AccessDeniedHttpException(); + return new AccessDeniedHttpException($message, $previous, $code, $headers); } } diff --git a/vendor/symfony/http-kernel/Tests/Exception/BadRequestHttpExceptionTest.php b/vendor/symfony/http-kernel/Tests/Exception/BadRequestHttpExceptionTest.php index 5fd54ccf44a0bbb02bb162f7b51b25a1a08b6bb3..462fd9cb1dbc3ba51f6cfe4125ce9dadcb37fc94 100644 --- a/vendor/symfony/http-kernel/Tests/Exception/BadRequestHttpExceptionTest.php +++ b/vendor/symfony/http-kernel/Tests/Exception/BadRequestHttpExceptionTest.php @@ -6,8 +6,8 @@ use Symfony\Component\HttpKernel\Exception\BadRequestHttpException; class BadRequestHttpExceptionTest extends HttpExceptionTest { - protected function createException() + protected function createException(string $message = null, \Throwable $previous = null, ?int $code = 0, array $headers = []) { - return new BadRequestHttpException(); + return new BadRequestHttpException($message, $previous, $code, $headers); } } diff --git a/vendor/symfony/http-kernel/Tests/Exception/ConflictHttpExceptionTest.php b/vendor/symfony/http-kernel/Tests/Exception/ConflictHttpExceptionTest.php index 63cb49e6e05b9a747f2cd65a3dc1d6b5677cac46..760600a10fc3284c21eb35982bf7c7cfa24750ec 100644 --- a/vendor/symfony/http-kernel/Tests/Exception/ConflictHttpExceptionTest.php +++ b/vendor/symfony/http-kernel/Tests/Exception/ConflictHttpExceptionTest.php @@ -6,8 +6,8 @@ use Symfony\Component\HttpKernel\Exception\ConflictHttpException; class ConflictHttpExceptionTest extends HttpExceptionTest { - protected function createException() + protected function createException(string $message = null, \Throwable $previous = null, ?int $code = 0, array $headers = []) { - return new ConflictHttpException(); + return new ConflictHttpException($message, $previous, $code, $headers); } } diff --git a/vendor/symfony/http-kernel/Tests/Exception/GoneHttpExceptionTest.php b/vendor/symfony/http-kernel/Tests/Exception/GoneHttpExceptionTest.php index ec5339d2af5624349c3e8555bd04e15f570970d4..30dafe49227518ec6ce9b799deb557505010e3b2 100644 --- a/vendor/symfony/http-kernel/Tests/Exception/GoneHttpExceptionTest.php +++ b/vendor/symfony/http-kernel/Tests/Exception/GoneHttpExceptionTest.php @@ -6,8 +6,8 @@ use Symfony\Component\HttpKernel\Exception\GoneHttpException; class GoneHttpExceptionTest extends HttpExceptionTest { - protected function createException() + protected function createException(string $message = null, \Throwable $previous = null, ?int $code = 0, array $headers = []) { - return new GoneHttpException(); + return new GoneHttpException($message, $previous, $code, $headers); } } diff --git a/vendor/symfony/http-kernel/Tests/Exception/HttpExceptionTest.php b/vendor/symfony/http-kernel/Tests/Exception/HttpExceptionTest.php index b64773551eb31c865c717a695bb9ca8c424f850b..a9431f4b5a7223df3e13366356f75543848e7aa7 100644 --- a/vendor/symfony/http-kernel/Tests/Exception/HttpExceptionTest.php +++ b/vendor/symfony/http-kernel/Tests/Exception/HttpExceptionTest.php @@ -9,22 +9,22 @@ class HttpExceptionTest extends TestCase { public function headerDataProvider() { - return array( - array(array('X-Test' => 'Test')), - array(array('X-Test' => 1)), - array( - array( - array('X-Test' => 'Test'), - array('X-Test-2' => 'Test-2'), - ), - ), - ); + return [ + [['X-Test' => 'Test']], + [['X-Test' => 1]], + [ + [ + ['X-Test' => 'Test'], + ['X-Test-2' => 'Test-2'], + ], + ], + ]; } public function testHeadersDefault() { $exception = $this->createException(); - $this->assertSame(array(), $exception->getHeaders()); + $this->assertSame([], $exception->getHeaders()); } /** @@ -46,8 +46,16 @@ class HttpExceptionTest extends TestCase $this->assertSame($headers, $exception->getHeaders()); } - protected function createException() + public function testThrowableIsAllowedForPrevious() { - return new HttpException(200); + $previous = new class('Error of PHP 7+') extends \Error { + }; + $exception = $this->createException(null, $previous); + $this->assertSame($previous, $exception->getPrevious()); + } + + protected function createException(string $message = null, \Throwable $previous = null, ?int $code = 0, array $headers = []) + { + return new HttpException(200, $message, $previous, $headers, $code); } } diff --git a/vendor/symfony/http-kernel/Tests/Exception/LengthRequiredHttpExceptionTest.php b/vendor/symfony/http-kernel/Tests/Exception/LengthRequiredHttpExceptionTest.php index 462d3ca4fcf27f48750b40579903e43ca9c4c2d9..8676d67238c149d85de67bff6d092a2b31b1611e 100644 --- a/vendor/symfony/http-kernel/Tests/Exception/LengthRequiredHttpExceptionTest.php +++ b/vendor/symfony/http-kernel/Tests/Exception/LengthRequiredHttpExceptionTest.php @@ -6,8 +6,8 @@ use Symfony\Component\HttpKernel\Exception\LengthRequiredHttpException; class LengthRequiredHttpExceptionTest extends HttpExceptionTest { - protected function createException() + protected function createException(string $message = null, \Throwable $previous = null, ?int $code = 0, array $headers = []) { - return new LengthRequiredHttpException(); + return new LengthRequiredHttpException($message, $previous, $code, $headers); } } diff --git a/vendor/symfony/http-kernel/Tests/Exception/MethodNotAllowedHttpExceptionTest.php b/vendor/symfony/http-kernel/Tests/Exception/MethodNotAllowedHttpExceptionTest.php index b5def13ce38d7d06372b199a09abe2b2ce244d35..efb0b50cafd00a56abea6e9228d64420d4dc34b2 100644 --- a/vendor/symfony/http-kernel/Tests/Exception/MethodNotAllowedHttpExceptionTest.php +++ b/vendor/symfony/http-kernel/Tests/Exception/MethodNotAllowedHttpExceptionTest.php @@ -8,8 +8,21 @@ class MethodNotAllowedHttpExceptionTest extends HttpExceptionTest { public function testHeadersDefault() { - $exception = new MethodNotAllowedHttpException(array('GET', 'PUT')); - $this->assertSame(array('Allow' => 'GET, PUT'), $exception->getHeaders()); + $exception = new MethodNotAllowedHttpException(['GET', 'PUT']); + $this->assertSame(['Allow' => 'GET, PUT'], $exception->getHeaders()); + } + + public function testWithHeaderConstruct() + { + $headers = [ + 'Cache-Control' => 'public, s-maxage=1200', + ]; + + $exception = new MethodNotAllowedHttpException(['get'], null, null, null, $headers); + + $headers['Allow'] = 'GET'; + + $this->assertSame($headers, $exception->getHeaders()); } /** @@ -17,8 +30,13 @@ class MethodNotAllowedHttpExceptionTest extends HttpExceptionTest */ public function testHeadersSetter($headers) { - $exception = new MethodNotAllowedHttpException(array('GET')); + $exception = new MethodNotAllowedHttpException(['GET']); $exception->setHeaders($headers); $this->assertSame($headers, $exception->getHeaders()); } + + protected function createException(string $message = null, \Throwable $previous = null, ?int $code = 0, array $headers = []) + { + return new MethodNotAllowedHttpException(['get'], $message, $previous, $code, $headers); + } } diff --git a/vendor/symfony/http-kernel/Tests/Exception/NotAcceptableHttpExceptionTest.php b/vendor/symfony/http-kernel/Tests/Exception/NotAcceptableHttpExceptionTest.php index 4c0db7a3cb659ef3787d4e928d8ca86da1ac3917..021c69e28954b2c031752045bd9093f4ad9d375c 100644 --- a/vendor/symfony/http-kernel/Tests/Exception/NotAcceptableHttpExceptionTest.php +++ b/vendor/symfony/http-kernel/Tests/Exception/NotAcceptableHttpExceptionTest.php @@ -6,8 +6,8 @@ use Symfony\Component\HttpKernel\Exception\NotAcceptableHttpException; class NotAcceptableHttpExceptionTest extends HttpExceptionTest { - protected function createException() + protected function createException(string $message = null, \Throwable $previous = null, ?int $code = 0, array $headers = []) { - return new NotAcceptableHttpException(); + return new NotAcceptableHttpException($message, $previous, $code, $headers); } } diff --git a/vendor/symfony/http-kernel/Tests/Exception/NotFoundHttpExceptionTest.php b/vendor/symfony/http-kernel/Tests/Exception/NotFoundHttpExceptionTest.php index 62ede5b4b82a20733d6820271e33c54f7bf30446..0bf369b1a0ce4f7e7a92371030db0cad1f3f698d 100644 --- a/vendor/symfony/http-kernel/Tests/Exception/NotFoundHttpExceptionTest.php +++ b/vendor/symfony/http-kernel/Tests/Exception/NotFoundHttpExceptionTest.php @@ -6,8 +6,8 @@ use Symfony\Component\HttpKernel\Exception\NotFoundHttpException; class NotFoundHttpExceptionTest extends HttpExceptionTest { - protected function createException() + protected function createException(string $message = null, \Throwable $previous = null, ?int $code = 0, array $headers = []) { - return new NotFoundHttpException(); + return new NotFoundHttpException($message, $previous, $code, $headers); } } diff --git a/vendor/symfony/http-kernel/Tests/Exception/PreconditionFailedHttpExceptionTest.php b/vendor/symfony/http-kernel/Tests/Exception/PreconditionFailedHttpExceptionTest.php index 809252b75780c57ddbd90be12c8cebaf8130186c..04d79c499d037472550299f9f72b5060bcf969d0 100644 --- a/vendor/symfony/http-kernel/Tests/Exception/PreconditionFailedHttpExceptionTest.php +++ b/vendor/symfony/http-kernel/Tests/Exception/PreconditionFailedHttpExceptionTest.php @@ -6,8 +6,8 @@ use Symfony\Component\HttpKernel\Exception\PreconditionFailedHttpException; class PreconditionFailedHttpExceptionTest extends HttpExceptionTest { - protected function createException() + protected function createException(string $message = null, \Throwable $previous = null, ?int $code = 0, array $headers = []) { - return new PreconditionFailedHttpException(); + return new PreconditionFailedHttpException($message, $previous, $code, $headers); } } diff --git a/vendor/symfony/http-kernel/Tests/Exception/PreconditionRequiredHttpExceptionTest.php b/vendor/symfony/http-kernel/Tests/Exception/PreconditionRequiredHttpExceptionTest.php index 69d362e3f6cf9fa648fb2f8ef9513aff2068554d..82076617a8779db772371c1f8ceb28248a420328 100644 --- a/vendor/symfony/http-kernel/Tests/Exception/PreconditionRequiredHttpExceptionTest.php +++ b/vendor/symfony/http-kernel/Tests/Exception/PreconditionRequiredHttpExceptionTest.php @@ -6,8 +6,8 @@ use Symfony\Component\HttpKernel\Exception\PreconditionRequiredHttpException; class PreconditionRequiredHttpExceptionTest extends HttpExceptionTest { - protected function createException() + protected function createException(string $message = null, \Throwable $previous = null, ?int $code = 0, array $headers = []) { - return new PreconditionRequiredHttpException(); + return new PreconditionRequiredHttpException($message, $previous, $code, $headers); } } diff --git a/vendor/symfony/http-kernel/Tests/Exception/ServiceUnavailableHttpExceptionTest.php b/vendor/symfony/http-kernel/Tests/Exception/ServiceUnavailableHttpExceptionTest.php index e41a23d4e7719a407ad4f9fb42bba282404d992f..fac197c852e3e9dab0c551e63e3f19991f11e44f 100644 --- a/vendor/symfony/http-kernel/Tests/Exception/ServiceUnavailableHttpExceptionTest.php +++ b/vendor/symfony/http-kernel/Tests/Exception/ServiceUnavailableHttpExceptionTest.php @@ -9,7 +9,20 @@ class ServiceUnavailableHttpExceptionTest extends HttpExceptionTest public function testHeadersDefaultRetryAfter() { $exception = new ServiceUnavailableHttpException(10); - $this->assertSame(array('Retry-After' => 10), $exception->getHeaders()); + $this->assertSame(['Retry-After' => 10], $exception->getHeaders()); + } + + public function testWithHeaderConstruct() + { + $headers = [ + 'Cache-Control' => 'public, s-maxage=1337', + ]; + + $exception = new ServiceUnavailableHttpException(1337, null, null, null, $headers); + + $headers['Retry-After'] = 1337; + + $this->assertSame($headers, $exception->getHeaders()); } /** @@ -22,8 +35,8 @@ class ServiceUnavailableHttpExceptionTest extends HttpExceptionTest $this->assertSame($headers, $exception->getHeaders()); } - protected function createException() + protected function createException(string $message = null, \Throwable $previous = null, ?int $code = 0, array $headers = []) { - return new ServiceUnavailableHttpException(); + return new ServiceUnavailableHttpException(null, $message, $previous, $code, $headers); } } diff --git a/vendor/symfony/http-kernel/Tests/Exception/TooManyRequestsHttpExceptionTest.php b/vendor/symfony/http-kernel/Tests/Exception/TooManyRequestsHttpExceptionTest.php index 2079bb3380d20b086d6b597ef5501a4eed0ae424..8b59e9894adb56c72b3bf3d40134a1d62b6304a5 100644 --- a/vendor/symfony/http-kernel/Tests/Exception/TooManyRequestsHttpExceptionTest.php +++ b/vendor/symfony/http-kernel/Tests/Exception/TooManyRequestsHttpExceptionTest.php @@ -9,7 +9,20 @@ class TooManyRequestsHttpExceptionTest extends HttpExceptionTest public function testHeadersDefaultRertyAfter() { $exception = new TooManyRequestsHttpException(10); - $this->assertSame(array('Retry-After' => 10), $exception->getHeaders()); + $this->assertSame(['Retry-After' => 10], $exception->getHeaders()); + } + + public function testWithHeaderConstruct() + { + $headers = [ + 'Cache-Control' => 'public, s-maxage=69', + ]; + + $exception = new TooManyRequestsHttpException(69, null, null, null, $headers); + + $headers['Retry-After'] = 69; + + $this->assertSame($headers, $exception->getHeaders()); } /** @@ -22,8 +35,8 @@ class TooManyRequestsHttpExceptionTest extends HttpExceptionTest $this->assertSame($headers, $exception->getHeaders()); } - protected function createException() + protected function createException(string $message = null, \Throwable $previous = null, ?int $code = 0, array $headers = []) { - return new TooManyRequestsHttpException(); + return new TooManyRequestsHttpException(null, $message, $previous, $code, $headers); } } diff --git a/vendor/symfony/http-kernel/Tests/Exception/UnauthorizedHttpExceptionTest.php b/vendor/symfony/http-kernel/Tests/Exception/UnauthorizedHttpExceptionTest.php index 37a0028dc82573de82e916d2041d0bfc06a9f225..92d427b6e4a9e517052cb98ee80daf628154a018 100644 --- a/vendor/symfony/http-kernel/Tests/Exception/UnauthorizedHttpExceptionTest.php +++ b/vendor/symfony/http-kernel/Tests/Exception/UnauthorizedHttpExceptionTest.php @@ -9,7 +9,20 @@ class UnauthorizedHttpExceptionTest extends HttpExceptionTest public function testHeadersDefault() { $exception = new UnauthorizedHttpException('Challenge'); - $this->assertSame(array('WWW-Authenticate' => 'Challenge'), $exception->getHeaders()); + $this->assertSame(['WWW-Authenticate' => 'Challenge'], $exception->getHeaders()); + } + + public function testWithHeaderConstruct() + { + $headers = [ + 'Cache-Control' => 'public, s-maxage=1200', + ]; + + $exception = new UnauthorizedHttpException('Challenge', null, null, null, $headers); + + $headers['WWW-Authenticate'] = 'Challenge'; + + $this->assertSame($headers, $exception->getHeaders()); } /** @@ -21,4 +34,9 @@ class UnauthorizedHttpExceptionTest extends HttpExceptionTest $exception->setHeaders($headers); $this->assertSame($headers, $exception->getHeaders()); } + + protected function createException(string $message = null, \Throwable $previous = null, ?int $code = 0, array $headers = []) + { + return new UnauthorizedHttpException('Challenge', $message, $previous, $code, $headers); + } } diff --git a/vendor/symfony/http-kernel/Tests/Exception/UnprocessableEntityHttpExceptionTest.php b/vendor/symfony/http-kernel/Tests/Exception/UnprocessableEntityHttpExceptionTest.php index 760366c6943a18298b7e5694c890e4571ead2463..ffa4e177ee52601b6562e55b9c9fecd6c150cc90 100644 --- a/vendor/symfony/http-kernel/Tests/Exception/UnprocessableEntityHttpExceptionTest.php +++ b/vendor/symfony/http-kernel/Tests/Exception/UnprocessableEntityHttpExceptionTest.php @@ -6,23 +6,8 @@ use Symfony\Component\HttpKernel\Exception\UnprocessableEntityHttpException; class UnprocessableEntityHttpExceptionTest extends HttpExceptionTest { - /** - * Test that setting the headers using the setter function - * is working as expected. - * - * @param array $headers The headers to set - * - * @dataProvider headerDataProvider - */ - public function testHeadersSetter($headers) + protected function createException(string $message = null, \Throwable $previous = null, ?int $code = 0, array $headers = []) { - $exception = new UnprocessableEntityHttpException(10); - $exception->setHeaders($headers); - $this->assertSame($headers, $exception->getHeaders()); - } - - protected function createException() - { - return new UnprocessableEntityHttpException(); + return new UnprocessableEntityHttpException($message, $previous, $code, $headers); } } diff --git a/vendor/symfony/http-kernel/Tests/Exception/UnsupportedMediaTypeHttpExceptionTest.php b/vendor/symfony/http-kernel/Tests/Exception/UnsupportedMediaTypeHttpExceptionTest.php index d47287a1fbc69b4250323991ff5add25a288883e..fa28bbd19b41033a647fa421906a5e915f972519 100644 --- a/vendor/symfony/http-kernel/Tests/Exception/UnsupportedMediaTypeHttpExceptionTest.php +++ b/vendor/symfony/http-kernel/Tests/Exception/UnsupportedMediaTypeHttpExceptionTest.php @@ -6,18 +6,8 @@ use Symfony\Component\HttpKernel\Exception\UnsupportedMediaTypeHttpException; class UnsupportedMediaTypeHttpExceptionTest extends HttpExceptionTest { - /** - * @dataProvider headerDataProvider - */ - public function testHeadersSetter($headers) + protected function createException(string $message = null, \Throwable $previous = null, ?int $code = 0, array $headers = []) { - $exception = new UnsupportedMediaTypeHttpException(10); - $exception->setHeaders($headers); - $this->assertSame($headers, $exception->getHeaders()); - } - - protected function createException($headers = array()) - { - return new UnsupportedMediaTypeHttpException(); + return new UnsupportedMediaTypeHttpException($message, $previous, $code, $headers); } } diff --git a/vendor/symfony/http-kernel/Tests/Fixtures/123/Kernel123.php b/vendor/symfony/http-kernel/Tests/Fixtures/123/Kernel123.php deleted file mode 100644 index b6cf1cba20e75f5ad0d53ee0628195a059ce3be4..0000000000000000000000000000000000000000 --- a/vendor/symfony/http-kernel/Tests/Fixtures/123/Kernel123.php +++ /dev/null @@ -1,37 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Tests\Fixtures\_123; - -use Symfony\Component\HttpKernel\Kernel; -use Symfony\Component\Config\Loader\LoaderInterface; - -class Kernel123 extends Kernel -{ - public function registerBundles() - { - return array(); - } - - public function registerContainerConfiguration(LoaderInterface $loader) - { - } - - public function getCacheDir() - { - return sys_get_temp_dir().'/'.Kernel::VERSION.'/kernel123/cache/'.$this->environment; - } - - public function getLogDir() - { - return sys_get_temp_dir().'/'.Kernel::VERSION.'/kernel123/logs'; - } -} diff --git a/vendor/symfony/http-kernel/Tests/Fixtures/BaseBundle/Resources/foo.txt b/vendor/symfony/http-kernel/Tests/Fixtures/Bundle1Bundle/Resources/.gitkeep similarity index 100% rename from vendor/symfony/http-kernel/Tests/Fixtures/BaseBundle/Resources/foo.txt rename to vendor/symfony/http-kernel/Tests/Fixtures/Bundle1Bundle/Resources/.gitkeep diff --git a/vendor/symfony/http-kernel/Tests/Fixtures/Bundle1Bundle/bar.txt b/vendor/symfony/http-kernel/Tests/Fixtures/Bundle1Bundle/bar.txt deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/vendor/symfony/http-kernel/Tests/Fixtures/Bundle2Bundle/foo.txt b/vendor/symfony/http-kernel/Tests/Fixtures/Bundle2Bundle/foo.txt deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/vendor/symfony/http-kernel/Tests/Fixtures/ChildBundle/Resources/foo.txt b/vendor/symfony/http-kernel/Tests/Fixtures/ChildBundle/Resources/foo.txt deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/vendor/symfony/http-kernel/Tests/Fixtures/ChildBundle/Resources/hide.txt b/vendor/symfony/http-kernel/Tests/Fixtures/ChildBundle/Resources/hide.txt deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/vendor/symfony/http-kernel/Tests/Fixtures/DataCollector/CloneVarDataCollector.php b/vendor/symfony/http-kernel/Tests/Fixtures/DataCollector/CloneVarDataCollector.php index 89dec36af4110194ecb9b9b77706a07e8d68cabc..4f5de182fd17f1f5713f0295a6ea7579170de697 100644 --- a/vendor/symfony/http-kernel/Tests/Fixtures/DataCollector/CloneVarDataCollector.php +++ b/vendor/symfony/http-kernel/Tests/Fixtures/DataCollector/CloneVarDataCollector.php @@ -31,7 +31,7 @@ class CloneVarDataCollector extends DataCollector public function reset() { - $this->data = array(); + $this->data = []; } public function getData() diff --git a/vendor/symfony/http-kernel/Tests/Fixtures/ExtensionLoadedBundle/DependencyInjection/ExtensionLoadedExtension.php b/vendor/symfony/http-kernel/Tests/Fixtures/ExtensionLoadedBundle/DependencyInjection/ExtensionLoadedExtension.php deleted file mode 100644 index b43bc665a843ed52d1ef290863bea8b688251d7e..0000000000000000000000000000000000000000 --- a/vendor/symfony/http-kernel/Tests/Fixtures/ExtensionLoadedBundle/DependencyInjection/ExtensionLoadedExtension.php +++ /dev/null @@ -1,22 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Tests\Fixtures\ExtensionLoadedBundle\DependencyInjection; - -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Extension\Extension; - -class ExtensionLoadedExtension extends Extension -{ - public function load(array $configs, ContainerBuilder $container) - { - } -} diff --git a/vendor/symfony/http-kernel/Tests/Fixtures/ExtensionPresentBundle/Command/BarCommand.php b/vendor/symfony/http-kernel/Tests/Fixtures/ExtensionPresentBundle/Command/BarCommand.php deleted file mode 100644 index 977976b75f88b04d62aa4f9e8aa4e3391c5e9c3d..0000000000000000000000000000000000000000 --- a/vendor/symfony/http-kernel/Tests/Fixtures/ExtensionPresentBundle/Command/BarCommand.php +++ /dev/null @@ -1,17 +0,0 @@ -<?php - -namespace Symfony\Component\HttpKernel\Tests\Fixtures\ExtensionPresentBundle\Command; - -use Symfony\Component\Console\Command\Command; - -/** - * This command has a required parameter on the constructor and will be ignored by the default Bundle implementation. - * - * @see Bundle::registerCommands() - */ -class BarCommand extends Command -{ - public function __construct($example, $name = 'bar') - { - } -} diff --git a/vendor/symfony/http-kernel/Tests/Fixtures/ExtensionPresentBundle/Command/FooCommand.php b/vendor/symfony/http-kernel/Tests/Fixtures/ExtensionPresentBundle/Command/FooCommand.php deleted file mode 100644 index c6570aa046c55a10afda8cde771c3868f78205b1..0000000000000000000000000000000000000000 --- a/vendor/symfony/http-kernel/Tests/Fixtures/ExtensionPresentBundle/Command/FooCommand.php +++ /dev/null @@ -1,22 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien.potencier@symfony-project.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Tests\Fixtures\ExtensionPresentBundle\Command; - -use Symfony\Component\Console\Command\Command; - -class FooCommand extends Command -{ - protected function configure() - { - $this->setName('foo'); - } -} diff --git a/vendor/symfony/http-kernel/Tests/Fixtures/KernelForOverrideName.php b/vendor/symfony/http-kernel/Tests/Fixtures/KernelForOverrideName.php index a1102ab7843c3f3ba86a89f986e2ca7c4e0fe775..f7baaa6325fb2d9f01592404eb3f1b0082d337ec 100644 --- a/vendor/symfony/http-kernel/Tests/Fixtures/KernelForOverrideName.php +++ b/vendor/symfony/http-kernel/Tests/Fixtures/KernelForOverrideName.php @@ -11,8 +11,8 @@ namespace Symfony\Component\HttpKernel\Tests\Fixtures; -use Symfony\Component\HttpKernel\Kernel; use Symfony\Component\Config\Loader\LoaderInterface; +use Symfony\Component\HttpKernel\Kernel; class KernelForOverrideName extends Kernel { diff --git a/vendor/symfony/http-kernel/Tests/Fixtures/KernelForTest.php b/vendor/symfony/http-kernel/Tests/Fixtures/KernelForTest.php index 5fd61bbc7e7ce0713466f9d3d64f3b2a743119c5..7b870250cc7d443403240587fbae32028ec9fd57 100644 --- a/vendor/symfony/http-kernel/Tests/Fixtures/KernelForTest.php +++ b/vendor/symfony/http-kernel/Tests/Fixtures/KernelForTest.php @@ -11,8 +11,8 @@ namespace Symfony\Component\HttpKernel\Tests\Fixtures; -use Symfony\Component\HttpKernel\Kernel; use Symfony\Component\Config\Loader\LoaderInterface; +use Symfony\Component\HttpKernel\Kernel; class KernelForTest extends Kernel { @@ -23,7 +23,7 @@ class KernelForTest extends Kernel public function registerBundles() { - return array(); + return []; } public function registerContainerConfiguration(LoaderInterface $loader) @@ -34,4 +34,9 @@ class KernelForTest extends Kernel { return $this->booted; } + + public function getProjectDir(): string + { + return __DIR__; + } } diff --git a/vendor/symfony/http-kernel/Tests/Fixtures/KernelWithoutBundles.php b/vendor/symfony/http-kernel/Tests/Fixtures/KernelWithoutBundles.php index cee1b09fb22533ef1d45b63bd26c52434c64b5b5..2391557362f0724882949c1b004db665ce672530 100644 --- a/vendor/symfony/http-kernel/Tests/Fixtures/KernelWithoutBundles.php +++ b/vendor/symfony/http-kernel/Tests/Fixtures/KernelWithoutBundles.php @@ -19,13 +19,18 @@ class KernelWithoutBundles extends Kernel { public function registerBundles() { - return array(); + return []; } public function registerContainerConfiguration(LoaderInterface $loader) { } + public function getProjectDir() + { + return __DIR__; + } + protected function build(ContainerBuilder $container) { $container->setParameter('test_executed', true); diff --git a/vendor/symfony/http-kernel/Tests/Fixtures/Resources/BaseBundle/hide.txt b/vendor/symfony/http-kernel/Tests/Fixtures/Resources/BaseBundle/hide.txt deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/vendor/symfony/http-kernel/Tests/Fixtures/Resources/Bundle1Bundle/foo.txt b/vendor/symfony/http-kernel/Tests/Fixtures/Resources/Bundle1Bundle/foo.txt deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/vendor/symfony/http-kernel/Tests/Fixtures/Resources/ChildBundle/foo.txt b/vendor/symfony/http-kernel/Tests/Fixtures/Resources/ChildBundle/foo.txt deleted file mode 100644 index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0000000000000000000000000000000000000000 diff --git a/vendor/symfony/http-kernel/Tests/Fixtures/TestClient.php b/vendor/symfony/http-kernel/Tests/Fixtures/TestClient.php index e7d60cff3d0be77b2f63e7f56157311da4c83889..140cbfbf51f480bfb04ca3472aa2a60703d4aa26 100644 --- a/vendor/symfony/http-kernel/Tests/Fixtures/TestClient.php +++ b/vendor/symfony/http-kernel/Tests/Fixtures/TestClient.php @@ -11,9 +11,9 @@ namespace Symfony\Component\HttpKernel\Tests\Fixtures; -use Symfony\Component\HttpKernel\Client; +use Symfony\Component\HttpKernel\HttpKernelBrowser; -class TestClient extends Client +class TestClient extends HttpKernelBrowser { protected function getScript($request) { diff --git a/vendor/symfony/http-kernel/Tests/Fixtures/TestEventDispatcher.php b/vendor/symfony/http-kernel/Tests/Fixtures/TestEventDispatcher.php deleted file mode 100644 index ca2e6a693da6ec117539acd7c1cef4decba0a3c5..0000000000000000000000000000000000000000 --- a/vendor/symfony/http-kernel/Tests/Fixtures/TestEventDispatcher.php +++ /dev/null @@ -1,32 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\HttpKernel\Tests\Fixtures; - -use Symfony\Component\EventDispatcher\Debug\TraceableEventDispatcherInterface; -use Symfony\Component\EventDispatcher\EventDispatcher; - -class TestEventDispatcher extends EventDispatcher implements TraceableEventDispatcherInterface -{ - public function getCalledListeners() - { - return array('foo'); - } - - public function getNotCalledListeners() - { - return array('bar'); - } - - public function reset() - { - } -} diff --git a/vendor/symfony/http-kernel/Tests/Fragment/EsiFragmentRendererTest.php b/vendor/symfony/http-kernel/Tests/Fragment/EsiFragmentRendererTest.php index 7099b4d7e8bf6f4430d1effe174037d85bd9aeb0..df74ade1540d3067f979806c8bbe53920b45eacc 100644 --- a/vendor/symfony/http-kernel/Tests/Fragment/EsiFragmentRendererTest.php +++ b/vendor/symfony/http-kernel/Tests/Fragment/EsiFragmentRendererTest.php @@ -12,10 +12,10 @@ namespace Symfony\Component\HttpKernel\Tests\Fragment; use PHPUnit\Framework\TestCase; +use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\Controller\ControllerReference; use Symfony\Component\HttpKernel\Fragment\EsiFragmentRenderer; use Symfony\Component\HttpKernel\HttpCache\Esi; -use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\UriSigner; class EsiFragmentRendererTest extends TestCase @@ -26,23 +26,11 @@ class EsiFragmentRendererTest extends TestCase $strategy->render('/', Request::create('/')); } - /** - * @group legacy - * @expectedDeprecation Passing non-scalar values as part of URI attributes to the ESI and SSI rendering strategies is deprecated %s. - */ - public function testRenderFallbackWithObjectAttributesIsDeprecated() - { - $strategy = new EsiFragmentRenderer(new Esi(), $this->getInlineStrategy(true), new UriSigner('foo')); - $request = Request::create('/'); - $reference = new ControllerReference('main_controller', array('foo' => new \stdClass()), array()); - $strategy->render($reference, $request); - } - - public function testRenderFallbackWithScalarIsNotDeprecated() + public function testRenderFallbackWithScalar() { $strategy = new EsiFragmentRenderer(new Esi(), $this->getInlineStrategy(true), new UriSigner('foo')); $request = Request::create('/'); - $reference = new ControllerReference('main_controller', array('foo' => array(true)), array()); + $reference = new ControllerReference('main_controller', ['foo' => [true]], []); $strategy->render($reference, $request); } @@ -55,8 +43,8 @@ class EsiFragmentRendererTest extends TestCase $request->headers->set('Surrogate-Capability', 'ESI/1.0'); $this->assertEquals('<esi:include src="/" />', $strategy->render('/', $request)->getContent()); - $this->assertEquals("<esi:comment text=\"This is a comment\" />\n<esi:include src=\"/\" />", $strategy->render('/', $request, array('comment' => 'This is a comment'))->getContent()); - $this->assertEquals('<esi:include src="/" alt="foo" />', $strategy->render('/', $request, array('alt' => 'foo'))->getContent()); + $this->assertEquals("<esi:comment text=\"This is a comment\" />\n<esi:include src=\"/\" />", $strategy->render('/', $request, ['comment' => 'This is a comment'])->getContent()); + $this->assertEquals('<esi:include src="/" alt="foo" />', $strategy->render('/', $request, ['alt' => 'foo'])->getContent()); } public function testRenderControllerReference() @@ -68,20 +56,18 @@ class EsiFragmentRendererTest extends TestCase $request->setLocale('fr'); $request->headers->set('Surrogate-Capability', 'ESI/1.0'); - $reference = new ControllerReference('main_controller', array(), array()); - $altReference = new ControllerReference('alt_controller', array(), array()); + $reference = new ControllerReference('main_controller', [], []); + $altReference = new ControllerReference('alt_controller', [], []); $this->assertEquals( - '<esi:include src="/_fragment?_path=_format%3Dhtml%26_locale%3Dfr%26_controller%3Dmain_controller&_hash=Jz1P8NErmhKTeI6onI1EdAXTB85359MY3RIk5mSJ60w%3D" alt="/_fragment?_path=_format%3Dhtml%26_locale%3Dfr%26_controller%3Dalt_controller&_hash=iPJEdRoUpGrM1ztqByiorpfMPtiW%2FOWwdH1DBUXHhEc%3D" />', - $strategy->render($reference, $request, array('alt' => $altReference))->getContent() + '<esi:include src="/_fragment?_hash=Jz1P8NErmhKTeI6onI1EdAXTB85359MY3RIk5mSJ60w%3D&_path=_format%3Dhtml%26_locale%3Dfr%26_controller%3Dmain_controller" alt="/_fragment?_hash=iPJEdRoUpGrM1ztqByiorpfMPtiW%2FOWwdH1DBUXHhEc%3D&_path=_format%3Dhtml%26_locale%3Dfr%26_controller%3Dalt_controller" />', + $strategy->render($reference, $request, ['alt' => $altReference])->getContent() ); } - /** - * @expectedException \LogicException - */ public function testRenderControllerReferenceWithoutSignerThrowsException() { + $this->expectException('LogicException'); $strategy = new EsiFragmentRenderer(new Esi(), $this->getInlineStrategy()); $request = Request::create('/'); @@ -91,18 +77,16 @@ class EsiFragmentRendererTest extends TestCase $strategy->render(new ControllerReference('main_controller'), $request); } - /** - * @expectedException \LogicException - */ public function testRenderAltControllerReferenceWithoutSignerThrowsException() { + $this->expectException('LogicException'); $strategy = new EsiFragmentRenderer(new Esi(), $this->getInlineStrategy()); $request = Request::create('/'); $request->setLocale('fr'); $request->headers->set('Surrogate-Capability', 'ESI/1.0'); - $strategy->render('/', $request, array('alt' => new ControllerReference('alt_controller'))); + $strategy->render('/', $request, ['alt' => new ControllerReference('alt_controller')]); } private function getInlineStrategy($called = false) diff --git a/vendor/symfony/http-kernel/Tests/Fragment/FragmentHandlerTest.php b/vendor/symfony/http-kernel/Tests/Fragment/FragmentHandlerTest.php index 9c906b50a0bea467f42b03d8909532c6984c009d..15e543a2142367823914e58f72fd1108047db66a 100644 --- a/vendor/symfony/http-kernel/Tests/Fragment/FragmentHandlerTest.php +++ b/vendor/symfony/http-kernel/Tests/Fragment/FragmentHandlerTest.php @@ -12,9 +12,9 @@ namespace Symfony\Component\HttpKernel\Tests\Fragment; use PHPUnit\Framework\TestCase; -use Symfony\Component\HttpKernel\Fragment\FragmentHandler; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpKernel\Fragment\FragmentHandler; /** * @group time-sensitive @@ -23,7 +23,7 @@ class FragmentHandlerTest extends TestCase { private $requestStack; - protected function setUp() + protected function setUp(): void { $this->requestStack = $this->getMockBuilder('Symfony\\Component\\HttpFoundation\\RequestStack') ->disableOriginalConstructor() @@ -32,35 +32,29 @@ class FragmentHandlerTest extends TestCase $this->requestStack ->expects($this->any()) ->method('getCurrentRequest') - ->will($this->returnValue(Request::create('/'))) + ->willReturn(Request::create('/')) ; } - /** - * @expectedException \InvalidArgumentException - */ public function testRenderWhenRendererDoesNotExist() { + $this->expectException('InvalidArgumentException'); $handler = new FragmentHandler($this->requestStack); $handler->render('/', 'foo'); } - /** - * @expectedException \InvalidArgumentException - */ public function testRenderWithUnknownRenderer() { + $this->expectException('InvalidArgumentException'); $handler = $this->getHandler($this->returnValue(new Response('foo'))); $handler->render('/', 'bar'); } - /** - * @expectedException \RuntimeException - * @expectedExceptionMessage Error when rendering "http://localhost/" (Status code is 404). - */ public function testDeliverWithUnsuccessfulResponse() { + $this->expectException('RuntimeException'); + $this->expectExceptionMessage('Error when rendering "http://localhost/" (Status code is 404).'); $handler = $this->getHandler($this->returnValue(new Response('foo', 404))); $handler->render('/', 'foo'); @@ -68,18 +62,18 @@ class FragmentHandlerTest extends TestCase public function testRender() { - $handler = $this->getHandler($this->returnValue(new Response('foo')), array('/', Request::create('/'), array('foo' => 'foo', 'ignore_errors' => true))); + $handler = $this->getHandler($this->returnValue(new Response('foo')), ['/', Request::create('/'), ['foo' => 'foo', 'ignore_errors' => true]]); - $this->assertEquals('foo', $handler->render('/', 'foo', array('foo' => 'foo'))); + $this->assertEquals('foo', $handler->render('/', 'foo', ['foo' => 'foo'])); } - protected function getHandler($returnValue, $arguments = array()) + protected function getHandler($returnValue, $arguments = []) { $renderer = $this->getMockBuilder('Symfony\Component\HttpKernel\Fragment\FragmentRendererInterface')->getMock(); $renderer ->expects($this->any()) ->method('getName') - ->will($this->returnValue('foo')) + ->willReturn('foo') ; $e = $renderer ->expects($this->any()) @@ -88,7 +82,7 @@ class FragmentHandlerTest extends TestCase ; if ($arguments) { - call_user_func_array(array($e, 'with'), $arguments); + $e->with(...$arguments); } $handler = new FragmentHandler($this->requestStack); diff --git a/vendor/symfony/http-kernel/Tests/Fragment/HIncludeFragmentRendererTest.php b/vendor/symfony/http-kernel/Tests/Fragment/HIncludeFragmentRendererTest.php index 1be052e5e62fdbc37f1caaedbbacf301a64909e9..cdef37565b5eb7a58fba2bf2329061bc42001ca9 100644 --- a/vendor/symfony/http-kernel/Tests/Fragment/HIncludeFragmentRendererTest.php +++ b/vendor/symfony/http-kernel/Tests/Fragment/HIncludeFragmentRendererTest.php @@ -12,27 +12,27 @@ namespace Symfony\Component\HttpKernel\Tests\Fragment; use PHPUnit\Framework\TestCase; +use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\Controller\ControllerReference; use Symfony\Component\HttpKernel\Fragment\HIncludeFragmentRenderer; use Symfony\Component\HttpKernel\UriSigner; -use Symfony\Component\HttpFoundation\Request; +use Twig\Environment; +use Twig\Loader\ArrayLoader; class HIncludeFragmentRendererTest extends TestCase { - /** - * @expectedException \LogicException - */ public function testRenderExceptionWhenControllerAndNoSigner() { + $this->expectException('LogicException'); $strategy = new HIncludeFragmentRenderer(); - $strategy->render(new ControllerReference('main_controller', array(), array()), Request::create('/')); + $strategy->render(new ControllerReference('main_controller', [], []), Request::create('/')); } public function testRenderWithControllerAndSigner() { $strategy = new HIncludeFragmentRenderer(null, new UriSigner('foo')); - $this->assertEquals('<hx:include src="/_fragment?_path=_format%3Dhtml%26_locale%3Den%26_controller%3Dmain_controller&_hash=BP%2BOzCD5MRUI%2BHJpgPDOmoju00FnzLhP3TGcSHbbBLs%3D"></hx:include>', $strategy->render(new ControllerReference('main_controller', array(), array()), Request::create('/'))->getContent()); + $this->assertEquals('<hx:include src="/_fragment?_hash=BP%2BOzCD5MRUI%2BHJpgPDOmoju00FnzLhP3TGcSHbbBLs%3D&_path=_format%3Dhtml%26_locale%3Den%26_controller%3Dmain_controller"></hx:include>', $strategy->render(new ControllerReference('main_controller', [], []), Request::create('/'))->getContent()); } public function testRenderWithUri() @@ -48,42 +48,52 @@ class HIncludeFragmentRendererTest extends TestCase { // only default $strategy = new HIncludeFragmentRenderer(); - $this->assertEquals('<hx:include src="/foo">default</hx:include>', $strategy->render('/foo', Request::create('/'), array('default' => 'default'))->getContent()); + $this->assertEquals('<hx:include src="/foo">default</hx:include>', $strategy->render('/foo', Request::create('/'), ['default' => 'default'])->getContent()); // only global default $strategy = new HIncludeFragmentRenderer(null, null, 'global_default'); - $this->assertEquals('<hx:include src="/foo">global_default</hx:include>', $strategy->render('/foo', Request::create('/'), array())->getContent()); + $this->assertEquals('<hx:include src="/foo">global_default</hx:include>', $strategy->render('/foo', Request::create('/'), [])->getContent()); // global default and default $strategy = new HIncludeFragmentRenderer(null, null, 'global_default'); - $this->assertEquals('<hx:include src="/foo">default</hx:include>', $strategy->render('/foo', Request::create('/'), array('default' => 'default'))->getContent()); + $this->assertEquals('<hx:include src="/foo">default</hx:include>', $strategy->render('/foo', Request::create('/'), ['default' => 'default'])->getContent()); } public function testRenderWithAttributesOptions() { // with id $strategy = new HIncludeFragmentRenderer(); - $this->assertEquals('<hx:include src="/foo" id="bar">default</hx:include>', $strategy->render('/foo', Request::create('/'), array('default' => 'default', 'id' => 'bar'))->getContent()); + $this->assertEquals('<hx:include src="/foo" id="bar">default</hx:include>', $strategy->render('/foo', Request::create('/'), ['default' => 'default', 'id' => 'bar'])->getContent()); // with attributes $strategy = new HIncludeFragmentRenderer(); - $this->assertEquals('<hx:include src="/foo" p1="v1" p2="v2">default</hx:include>', $strategy->render('/foo', Request::create('/'), array('default' => 'default', 'attributes' => array('p1' => 'v1', 'p2' => 'v2')))->getContent()); + $this->assertEquals('<hx:include src="/foo" p1="v1" p2="v2">default</hx:include>', $strategy->render('/foo', Request::create('/'), ['default' => 'default', 'attributes' => ['p1' => 'v1', 'p2' => 'v2']])->getContent()); // with id & attributes $strategy = new HIncludeFragmentRenderer(); - $this->assertEquals('<hx:include src="/foo" p1="v1" p2="v2" id="bar">default</hx:include>', $strategy->render('/foo', Request::create('/'), array('default' => 'default', 'id' => 'bar', 'attributes' => array('p1' => 'v1', 'p2' => 'v2')))->getContent()); + $this->assertEquals('<hx:include src="/foo" p1="v1" p2="v2" id="bar">default</hx:include>', $strategy->render('/foo', Request::create('/'), ['default' => 'default', 'id' => 'bar', 'attributes' => ['p1' => 'v1', 'p2' => 'v2']])->getContent()); } - public function testRenderWithDefaultText() + public function testRenderWithTwigAndDefaultText() + { + $twig = new Environment($loader = new ArrayLoader()); + $strategy = new HIncludeFragmentRenderer($twig); + $this->assertEquals('<hx:include src="/foo">loading...</hx:include>', $strategy->render('/foo', Request::create('/'), ['default' => 'loading...'])->getContent()); + } + + /** + * @group legacy + */ + public function testRenderWithDefaultTextLegacy() { $engine = $this->getMockBuilder('Symfony\\Component\\Templating\\EngineInterface')->getMock(); $engine->expects($this->once()) ->method('exists') ->with('default') - ->will($this->throwException(new \InvalidArgumentException())); + ->willThrowException(new \InvalidArgumentException()); // only default $strategy = new HIncludeFragmentRenderer($engine); - $this->assertEquals('<hx:include src="/foo">default</hx:include>', $strategy->render('/foo', Request::create('/'), array('default' => 'default'))->getContent()); + $this->assertEquals('<hx:include src="/foo">default</hx:include>', $strategy->render('/foo', Request::create('/'), ['default' => 'default'])->getContent()); } } diff --git a/vendor/symfony/http-kernel/Tests/Fragment/InlineFragmentRendererTest.php b/vendor/symfony/http-kernel/Tests/Fragment/InlineFragmentRendererTest.php index 18e55a5be0df20ee96c7871369ae16d457111004..a064a76c7dc013778095a1bd803e8f427c08d70d 100644 --- a/vendor/symfony/http-kernel/Tests/Fragment/InlineFragmentRendererTest.php +++ b/vendor/symfony/http-kernel/Tests/Fragment/InlineFragmentRendererTest.php @@ -12,16 +12,16 @@ namespace Symfony\Component\HttpKernel\Tests\Fragment; use PHPUnit\Framework\TestCase; +use Symfony\Component\EventDispatcher\EventDispatcher; +use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\RequestStack; -use Symfony\Component\HttpKernel\Controller\ArgumentResolver; -use Symfony\Component\HttpKernel\Controller\ControllerResolverInterface; +use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\Controller\ControllerReference; -use Symfony\Component\HttpKernel\HttpKernel; +use Symfony\Component\HttpKernel\Event\ExceptionEvent; use Symfony\Component\HttpKernel\Fragment\InlineFragmentRenderer; +use Symfony\Component\HttpKernel\HttpKernel; use Symfony\Component\HttpKernel\KernelEvents; -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\EventDispatcher\EventDispatcher; +use Symfony\Contracts\EventDispatcher\EventDispatcherInterface; class InlineFragmentRendererTest extends TestCase { @@ -36,7 +36,7 @@ class InlineFragmentRendererTest extends TestCase { $strategy = new InlineFragmentRenderer($this->getKernel($this->returnValue(new Response('foo')))); - $this->assertEquals('foo', $strategy->render(new ControllerReference('main_controller', array(), array()), Request::create('/'))->getContent()); + $this->assertEquals('foo', $strategy->render(new ControllerReference('main_controller', [], []), Request::create('/'))->getContent()); } public function testRenderWithObjectsAsAttributes() @@ -44,73 +44,35 @@ class InlineFragmentRendererTest extends TestCase $object = new \stdClass(); $subRequest = Request::create('/_fragment?_path=_format%3Dhtml%26_locale%3Den%26_controller%3Dmain_controller'); - $subRequest->attributes->replace(array('object' => $object, '_format' => 'html', '_controller' => 'main_controller', '_locale' => 'en')); - $subRequest->headers->set('x-forwarded-for', array('127.0.0.1')); + $subRequest->attributes->replace(['object' => $object, '_format' => 'html', '_controller' => 'main_controller', '_locale' => 'en']); + $subRequest->headers->set('x-forwarded-for', ['127.0.0.1']); + $subRequest->headers->set('forwarded', ['for="127.0.0.1";host="localhost";proto=http']); $subRequest->server->set('HTTP_X_FORWARDED_FOR', '127.0.0.1'); + $subRequest->server->set('HTTP_FORWARDED', 'for="127.0.0.1";host="localhost";proto=http'); $strategy = new InlineFragmentRenderer($this->getKernelExpectingRequest($subRequest)); - $this->assertSame('foo', $strategy->render(new ControllerReference('main_controller', array('object' => $object), array()), Request::create('/'))->getContent()); - } - - /** - * @group legacy - */ - public function testRenderWithObjectsAsAttributesPassedAsObjectsInTheControllerLegacy() - { - $resolver = $this->getMockBuilder('Symfony\\Component\\HttpKernel\\Controller\\ControllerResolver')->setMethods(array('getController'))->getMock(); - $resolver - ->expects($this->once()) - ->method('getController') - ->will($this->returnValue(function (\stdClass $object, Bar $object1) { - return new Response($object1->getBar()); - })) - ; - - $kernel = new HttpKernel(new EventDispatcher(), $resolver, new RequestStack()); - $renderer = new InlineFragmentRenderer($kernel); - - $response = $renderer->render(new ControllerReference('main_controller', array('object' => new \stdClass(), 'object1' => new Bar()), array()), Request::create('/')); - $this->assertEquals('bar', $response->getContent()); - } - - /** - * @group legacy - */ - public function testRenderWithObjectsAsAttributesPassedAsObjectsInTheController() - { - $resolver = $this->getMockBuilder(ControllerResolverInterface::class)->getMock(); - $resolver - ->expects($this->once()) - ->method('getController') - ->will($this->returnValue(function (\stdClass $object, Bar $object1) { - return new Response($object1->getBar()); - })) - ; - - $kernel = new HttpKernel(new EventDispatcher(), $resolver, new RequestStack(), new ArgumentResolver()); - $renderer = new InlineFragmentRenderer($kernel); - - $response = $renderer->render(new ControllerReference('main_controller', array('object' => new \stdClass(), 'object1' => new Bar()), array()), Request::create('/')); - $this->assertEquals('bar', $response->getContent()); + $this->assertSame('foo', $strategy->render(new ControllerReference('main_controller', ['object' => $object], []), Request::create('/'))->getContent()); } public function testRenderWithTrustedHeaderDisabled() { - Request::setTrustedProxies(array(), 0); + Request::setTrustedProxies([], 0); - $strategy = new InlineFragmentRenderer($this->getKernelExpectingRequest(Request::create('/'))); + $expectedSubRequest = Request::create('/'); + $expectedSubRequest->headers->set('x-forwarded-for', ['127.0.0.1']); + $expectedSubRequest->server->set('HTTP_X_FORWARDED_FOR', '127.0.0.1'); + + $strategy = new InlineFragmentRenderer($this->getKernelExpectingRequest($expectedSubRequest)); $this->assertSame('foo', $strategy->render('/', Request::create('/'))->getContent()); - Request::setTrustedProxies(array(), -1); + Request::setTrustedProxies([], -1); } - /** - * @expectedException \RuntimeException - */ public function testRenderExceptionNoIgnoreErrors() { - $dispatcher = $this->getMockBuilder('Symfony\Component\EventDispatcher\EventDispatcherInterface')->getMock(); + $this->expectException('RuntimeException'); + $dispatcher = $this->getMockBuilder(EventDispatcherInterface::class)->getMock(); $dispatcher->expects($this->never())->method('dispatch'); $strategy = new InlineFragmentRenderer($this->getKernel($this->throwException(new \RuntimeException('foo'))), $dispatcher); @@ -120,12 +82,16 @@ class InlineFragmentRendererTest extends TestCase public function testRenderExceptionIgnoreErrors() { - $dispatcher = $this->getMockBuilder('Symfony\Component\EventDispatcher\EventDispatcherInterface')->getMock(); - $dispatcher->expects($this->once())->method('dispatch')->with(KernelEvents::EXCEPTION); + $exception = new \RuntimeException('foo'); + $kernel = $this->getKernel($this->throwException($exception)); + $request = Request::create('/'); + $expectedEvent = new ExceptionEvent($kernel, $request, $kernel::SUB_REQUEST, $exception); + $dispatcher = $this->getMockBuilder(EventDispatcherInterface::class)->getMock(); + $dispatcher->expects($this->once())->method('dispatch')->with($expectedEvent, KernelEvents::EXCEPTION); - $strategy = new InlineFragmentRenderer($this->getKernel($this->throwException(new \RuntimeException('foo'))), $dispatcher); + $strategy = new InlineFragmentRenderer($kernel, $dispatcher); - $this->assertEmpty($strategy->render('/', Request::create('/'), array('ignore_errors' => true))->getContent()); + $this->assertEmpty($strategy->render('/', $request, ['ignore_errors' => true])->getContent()); } public function testRenderExceptionIgnoreErrorsWithAlt() @@ -135,7 +101,7 @@ class InlineFragmentRendererTest extends TestCase $this->returnValue(new Response('bar')) ))); - $this->assertEquals('bar', $strategy->render('/', Request::create('/'), array('ignore_errors' => true, 'alt' => '/foo'))->getContent()); + $this->assertEquals('bar', $strategy->render('/', Request::create('/'), ['ignore_errors' => true, 'alt' => '/foo'])->getContent()); } private function getKernel($returnValue) @@ -156,18 +122,18 @@ class InlineFragmentRendererTest extends TestCase $controllerResolver ->expects($this->once()) ->method('getController') - ->will($this->returnValue(function () { + ->willReturn(function () { ob_start(); echo 'bar'; throw new \RuntimeException(); - })) + }) ; $argumentResolver = $this->getMockBuilder('Symfony\\Component\\HttpKernel\\Controller\\ArgumentResolverInterface')->getMock(); $argumentResolver ->expects($this->once()) ->method('getArguments') - ->will($this->returnValue(array())) + ->willReturn([]) ; $kernel = new HttpKernel(new EventDispatcher(), $controllerResolver, new RequestStack(), $argumentResolver); @@ -178,20 +144,42 @@ class InlineFragmentRendererTest extends TestCase echo 'Foo'; // simulate a sub-request with output buffering and an exception - $renderer->render('/', Request::create('/'), array('ignore_errors' => true)); + $renderer->render('/', Request::create('/'), ['ignore_errors' => true]); $this->assertEquals('Foo', ob_get_clean()); } + public function testLocaleAndFormatAreIsKeptInSubrequest() + { + $expectedSubRequest = Request::create('/'); + $expectedSubRequest->attributes->set('_format', 'foo'); + $expectedSubRequest->setLocale('fr'); + if (Request::HEADER_X_FORWARDED_FOR & Request::getTrustedHeaderSet()) { + $expectedSubRequest->headers->set('x-forwarded-for', ['127.0.0.1']); + $expectedSubRequest->server->set('HTTP_X_FORWARDED_FOR', '127.0.0.1'); + } + $expectedSubRequest->headers->set('forwarded', ['for="127.0.0.1";host="localhost";proto=http']); + $expectedSubRequest->server->set('HTTP_FORWARDED', 'for="127.0.0.1";host="localhost";proto=http'); + + $strategy = new InlineFragmentRenderer($this->getKernelExpectingRequest($expectedSubRequest)); + + $request = Request::create('/'); + $request->attributes->set('_format', 'foo'); + $request->setLocale('fr'); + $strategy->render('/', $request); + } + public function testESIHeaderIsKeptInSubrequest() { $expectedSubRequest = Request::create('/'); $expectedSubRequest->headers->set('Surrogate-Capability', 'abc="ESI/1.0"'); if (Request::HEADER_X_FORWARDED_FOR & Request::getTrustedHeaderSet()) { - $expectedSubRequest->headers->set('x-forwarded-for', array('127.0.0.1')); + $expectedSubRequest->headers->set('x-forwarded-for', ['127.0.0.1']); $expectedSubRequest->server->set('HTTP_X_FORWARDED_FOR', '127.0.0.1'); } + $expectedSubRequest->headers->set('forwarded', ['for="127.0.0.1";host="localhost";proto=http']); + $expectedSubRequest->server->set('HTTP_FORWARDED', 'for="127.0.0.1";host="localhost";proto=http'); $strategy = new InlineFragmentRenderer($this->getKernelExpectingRequest($expectedSubRequest)); @@ -202,26 +190,68 @@ class InlineFragmentRendererTest extends TestCase public function testESIHeaderIsKeptInSubrequestWithTrustedHeaderDisabled() { - Request::setTrustedProxies(array(), 0); + Request::setTrustedProxies([], Request::HEADER_FORWARDED); $this->testESIHeaderIsKeptInSubrequest(); - Request::setTrustedProxies(array(), -1); + Request::setTrustedProxies([], -1); } public function testHeadersPossiblyResultingIn304AreNotAssignedToSubrequest() { $expectedSubRequest = Request::create('/'); - if (Request::HEADER_X_FORWARDED_FOR & Request::getTrustedHeaderSet()) { - $expectedSubRequest->headers->set('x-forwarded-for', array('127.0.0.1')); - $expectedSubRequest->server->set('HTTP_X_FORWARDED_FOR', '127.0.0.1'); - } + $expectedSubRequest->headers->set('x-forwarded-for', ['127.0.0.1']); + $expectedSubRequest->headers->set('forwarded', ['for="127.0.0.1";host="localhost";proto=http']); + $expectedSubRequest->server->set('HTTP_X_FORWARDED_FOR', '127.0.0.1'); + $expectedSubRequest->server->set('HTTP_FORWARDED', 'for="127.0.0.1";host="localhost";proto=http'); $strategy = new InlineFragmentRenderer($this->getKernelExpectingRequest($expectedSubRequest)); - $request = Request::create('/', 'GET', array(), array(), array(), array('HTTP_IF_MODIFIED_SINCE' => 'Fri, 01 Jan 2016 00:00:00 GMT', 'HTTP_IF_NONE_MATCH' => '*')); + $request = Request::create('/', 'GET', [], [], [], ['HTTP_IF_MODIFIED_SINCE' => 'Fri, 01 Jan 2016 00:00:00 GMT', 'HTTP_IF_NONE_MATCH' => '*']); $strategy->render('/', $request); } + public function testFirstTrustedProxyIsSetAsRemote() + { + Request::setTrustedProxies(['1.1.1.1'], -1); + + $expectedSubRequest = Request::create('/'); + $expectedSubRequest->headers->set('Surrogate-Capability', 'abc="ESI/1.0"'); + $expectedSubRequest->server->set('REMOTE_ADDR', '127.0.0.1'); + $expectedSubRequest->headers->set('x-forwarded-for', ['127.0.0.1']); + $expectedSubRequest->headers->set('forwarded', ['for="127.0.0.1";host="localhost";proto=http']); + $expectedSubRequest->server->set('HTTP_X_FORWARDED_FOR', '127.0.0.1'); + $expectedSubRequest->server->set('HTTP_FORWARDED', 'for="127.0.0.1";host="localhost";proto=http'); + + $strategy = new InlineFragmentRenderer($this->getKernelExpectingRequest($expectedSubRequest)); + + $request = Request::create('/'); + $request->headers->set('Surrogate-Capability', 'abc="ESI/1.0"'); + $strategy->render('/', $request); + + Request::setTrustedProxies([], -1); + } + + public function testIpAddressOfRangedTrustedProxyIsSetAsRemote() + { + $expectedSubRequest = Request::create('/'); + $expectedSubRequest->headers->set('Surrogate-Capability', 'abc="ESI/1.0"'); + $expectedSubRequest->server->set('REMOTE_ADDR', '127.0.0.1'); + $expectedSubRequest->headers->set('x-forwarded-for', ['127.0.0.1']); + $expectedSubRequest->headers->set('forwarded', ['for="127.0.0.1";host="localhost";proto=http']); + $expectedSubRequest->server->set('HTTP_X_FORWARDED_FOR', '127.0.0.1'); + $expectedSubRequest->server->set('HTTP_FORWARDED', 'for="127.0.0.1";host="localhost";proto=http'); + + Request::setTrustedProxies(['1.1.1.1/24'], -1); + + $strategy = new InlineFragmentRenderer($this->getKernelExpectingRequest($expectedSubRequest)); + + $request = Request::create('/'); + $request->headers->set('Surrogate-Capability', 'abc="ESI/1.0"'); + $strategy->render('/', $request); + + Request::setTrustedProxies([], -1); + } + /** * Creates a Kernel expecting a request equals to $request * Allows delta in comparison in case REQUEST_TIME changed by 1 second. diff --git a/vendor/symfony/http-kernel/Tests/Fragment/RoutableFragmentRendererTest.php b/vendor/symfony/http-kernel/Tests/Fragment/RoutableFragmentRendererTest.php index 3a040dedd6e54051b77545555583568f8e6cdd92..151adb0e97cb4665347c6f265930beab24650966 100644 --- a/vendor/symfony/http-kernel/Tests/Fragment/RoutableFragmentRendererTest.php +++ b/vendor/symfony/http-kernel/Tests/Fragment/RoutableFragmentRendererTest.php @@ -35,14 +35,14 @@ class RoutableFragmentRendererTest extends TestCase public function getGenerateFragmentUriData() { - return array( - array('/_fragment?_path=_format%3Dhtml%26_locale%3Den%26_controller%3Dcontroller', new ControllerReference('controller', array(), array())), - array('/_fragment?_path=_format%3Dxml%26_locale%3Den%26_controller%3Dcontroller', new ControllerReference('controller', array('_format' => 'xml'), array())), - array('/_fragment?_path=foo%3Dfoo%26_format%3Djson%26_locale%3Den%26_controller%3Dcontroller', new ControllerReference('controller', array('foo' => 'foo', '_format' => 'json'), array())), - array('/_fragment?bar=bar&_path=foo%3Dfoo%26_format%3Dhtml%26_locale%3Den%26_controller%3Dcontroller', new ControllerReference('controller', array('foo' => 'foo'), array('bar' => 'bar'))), - array('/_fragment?foo=foo&_path=_format%3Dhtml%26_locale%3Den%26_controller%3Dcontroller', new ControllerReference('controller', array(), array('foo' => 'foo'))), - array('/_fragment?_path=foo%255B0%255D%3Dfoo%26foo%255B1%255D%3Dbar%26_format%3Dhtml%26_locale%3Den%26_controller%3Dcontroller', new ControllerReference('controller', array('foo' => array('foo', 'bar')), array())), - ); + return [ + ['/_fragment?_path=_format%3Dhtml%26_locale%3Den%26_controller%3Dcontroller', new ControllerReference('controller', [], [])], + ['/_fragment?_path=_format%3Dxml%26_locale%3Den%26_controller%3Dcontroller', new ControllerReference('controller', ['_format' => 'xml'], [])], + ['/_fragment?_path=foo%3Dfoo%26_format%3Djson%26_locale%3Den%26_controller%3Dcontroller', new ControllerReference('controller', ['foo' => 'foo', '_format' => 'json'], [])], + ['/_fragment?bar=bar&_path=foo%3Dfoo%26_format%3Dhtml%26_locale%3Den%26_controller%3Dcontroller', new ControllerReference('controller', ['foo' => 'foo'], ['bar' => 'bar'])], + ['/_fragment?foo=foo&_path=_format%3Dhtml%26_locale%3Den%26_controller%3Dcontroller', new ControllerReference('controller', [], ['foo' => 'foo'])], + ['/_fragment?_path=foo%255B0%255D%3Dfoo%26foo%255B1%255D%3Dbar%26_format%3Dhtml%26_locale%3Den%26_controller%3Dcontroller', new ControllerReference('controller', ['foo' => ['foo', 'bar']], [])], + ]; } public function testGenerateFragmentUriWithARequest() @@ -50,26 +50,26 @@ class RoutableFragmentRendererTest extends TestCase $request = Request::create('/'); $request->attributes->set('_format', 'json'); $request->setLocale('fr'); - $controller = new ControllerReference('controller', array(), array()); + $controller = new ControllerReference('controller', [], []); $this->assertEquals('/_fragment?_path=_format%3Djson%26_locale%3Dfr%26_controller%3Dcontroller', $this->callGenerateFragmentUriMethod($controller, $request)); } /** - * @expectedException \LogicException - * @dataProvider getGenerateFragmentUriDataWithNonScalar + * @dataProvider getGenerateFragmentUriDataWithNonScalar */ public function testGenerateFragmentUriWithNonScalar($controller) { + $this->expectException('LogicException'); $this->callGenerateFragmentUriMethod($controller, Request::create('/')); } public function getGenerateFragmentUriDataWithNonScalar() { - return array( - array(new ControllerReference('controller', array('foo' => new Foo(), 'bar' => 'bar'), array())), - array(new ControllerReference('controller', array('foo' => array('foo' => 'foo'), 'bar' => array('bar' => new Foo())), array())), - ); + return [ + [new ControllerReference('controller', ['foo' => new Foo(), 'bar' => 'bar'], [])], + [new ControllerReference('controller', ['foo' => ['foo' => 'foo'], 'bar' => ['bar' => new Foo()]], [])], + ]; } private function callGenerateFragmentUriMethod(ControllerReference $reference, Request $request, $absolute = false) diff --git a/vendor/symfony/http-kernel/Tests/Fragment/SsiFragmentRendererTest.php b/vendor/symfony/http-kernel/Tests/Fragment/SsiFragmentRendererTest.php index b537625f2401b91d2671bf23b2bf8dcb7c55b0d0..df30e6772722648aedd128e1cbf661bb6329f4f3 100644 --- a/vendor/symfony/http-kernel/Tests/Fragment/SsiFragmentRendererTest.php +++ b/vendor/symfony/http-kernel/Tests/Fragment/SsiFragmentRendererTest.php @@ -12,10 +12,10 @@ namespace Symfony\Component\HttpKernel\Tests\Fragment; use PHPUnit\Framework\TestCase; +use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\Controller\ControllerReference; use Symfony\Component\HttpKernel\Fragment\SsiFragmentRenderer; use Symfony\Component\HttpKernel\HttpCache\Ssi; -use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpKernel\UriSigner; class SsiFragmentRendererTest extends TestCase @@ -35,7 +35,7 @@ class SsiFragmentRendererTest extends TestCase $request->headers->set('Surrogate-Capability', 'SSI/1.0'); $this->assertEquals('<!--#include virtual="/" -->', $strategy->render('/', $request)->getContent()); - $this->assertEquals('<!--#include virtual="/" -->', $strategy->render('/', $request, array('comment' => 'This is a comment'))->getContent(), 'Strategy options should not impact the ssi include tag'); + $this->assertEquals('<!--#include virtual="/" -->', $strategy->render('/', $request, ['comment' => 'This is a comment'])->getContent(), 'Strategy options should not impact the ssi include tag'); } public function testRenderControllerReference() @@ -47,20 +47,18 @@ class SsiFragmentRendererTest extends TestCase $request->setLocale('fr'); $request->headers->set('Surrogate-Capability', 'SSI/1.0'); - $reference = new ControllerReference('main_controller', array(), array()); - $altReference = new ControllerReference('alt_controller', array(), array()); + $reference = new ControllerReference('main_controller', [], []); + $altReference = new ControllerReference('alt_controller', [], []); $this->assertEquals( - '<!--#include virtual="/_fragment?_path=_format%3Dhtml%26_locale%3Dfr%26_controller%3Dmain_controller&_hash=Jz1P8NErmhKTeI6onI1EdAXTB85359MY3RIk5mSJ60w%3D" -->', - $strategy->render($reference, $request, array('alt' => $altReference))->getContent() + '<!--#include virtual="/_fragment?_hash=Jz1P8NErmhKTeI6onI1EdAXTB85359MY3RIk5mSJ60w%3D&_path=_format%3Dhtml%26_locale%3Dfr%26_controller%3Dmain_controller" -->', + $strategy->render($reference, $request, ['alt' => $altReference])->getContent() ); } - /** - * @expectedException \LogicException - */ public function testRenderControllerReferenceWithoutSignerThrowsException() { + $this->expectException('LogicException'); $strategy = new SsiFragmentRenderer(new Ssi(), $this->getInlineStrategy()); $request = Request::create('/'); @@ -70,18 +68,16 @@ class SsiFragmentRendererTest extends TestCase $strategy->render(new ControllerReference('main_controller'), $request); } - /** - * @expectedException \LogicException - */ public function testRenderAltControllerReferenceWithoutSignerThrowsException() { + $this->expectException('LogicException'); $strategy = new SsiFragmentRenderer(new Ssi(), $this->getInlineStrategy()); $request = Request::create('/'); $request->setLocale('fr'); $request->headers->set('Surrogate-Capability', 'SSI/1.0'); - $strategy->render('/', $request, array('alt' => new ControllerReference('alt_controller'))); + $strategy->render('/', $request, ['alt' => new ControllerReference('alt_controller')]); } private function getInlineStrategy($called = false) diff --git a/vendor/symfony/http-kernel/Tests/HttpCache/EsiTest.php b/vendor/symfony/http-kernel/Tests/HttpCache/EsiTest.php index a8662b2a2b44b852d26cdbc38fffd6d69f969c15..cdf729e33146bba1002c0393a94a67de5cd70bf5 100644 --- a/vendor/symfony/http-kernel/Tests/HttpCache/EsiTest.php +++ b/vendor/symfony/http-kernel/Tests/HttpCache/EsiTest.php @@ -12,9 +12,9 @@ namespace Symfony\Component\HttpKernel\Tests\HttpCache; use PHPUnit\Framework\TestCase; -use Symfony\Component\HttpKernel\HttpCache\Esi; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpKernel\HttpCache\Esi; class EsiTest extends TestCase { @@ -88,7 +88,7 @@ class EsiTest extends TestCase $request = Request::create('/'); $response = new Response(); $response->headers->set('Content-Type', 'text/plain'); - $esi->process($request, $response); + $this->assertSame($response, $esi->process($request, $response)); $this->assertFalse($response->headers->has('x-body-eval')); } @@ -99,7 +99,7 @@ class EsiTest extends TestCase $request = Request::create('/'); $response = new Response('<esi:remove> <a href="http://www.example.com">www.example.com</a> </esi:remove> Keep this'."<esi:remove>\n <a>www.example.com</a> </esi:remove> And this"); - $esi->process($request, $response); + $this->assertSame($response, $esi->process($request, $response)); $this->assertEquals(' Keep this And this', $response->getContent()); } @@ -110,7 +110,7 @@ class EsiTest extends TestCase $request = Request::create('/'); $response = new Response('<esi:comment text="some comment >" /> Keep this'); - $esi->process($request, $response); + $this->assertSame($response, $esi->process($request, $response)); $this->assertEquals(' Keep this', $response->getContent()); } @@ -121,23 +121,23 @@ class EsiTest extends TestCase $request = Request::create('/'); $response = new Response('foo <esi:comment text="some comment" /><esi:include src="..." alt="alt" onerror="continue" />'); - $esi->process($request, $response); + $this->assertSame($response, $esi->process($request, $response)); $this->assertEquals('foo <?php echo $this->surrogate->handle($this, \'...\', \'alt\', true) ?>'."\n", $response->getContent()); $this->assertEquals('ESI', $response->headers->get('x-body-eval')); $response = new Response('foo <esi:comment text="some comment" /><esi:include src="foo\'" alt="bar\'" onerror="continue" />'); - $esi->process($request, $response); + $this->assertSame($response, $esi->process($request, $response)); $this->assertEquals('foo <?php echo $this->surrogate->handle($this, \'foo\\\'\', \'bar\\\'\', true) ?>'."\n", $response->getContent()); $response = new Response('foo <esi:include src="..." />'); - $esi->process($request, $response); + $this->assertSame($response, $esi->process($request, $response)); $this->assertEquals('foo <?php echo $this->surrogate->handle($this, \'...\', \'\', false) ?>'."\n", $response->getContent()); $response = new Response('foo <esi:include src="..."></esi:include>'); - $esi->process($request, $response); + $this->assertSame($response, $esi->process($request, $response)); $this->assertEquals('foo <?php echo $this->surrogate->handle($this, \'...\', \'\', false) ?>'."\n", $response->getContent()); } @@ -148,21 +148,19 @@ class EsiTest extends TestCase $request = Request::create('/'); $response = new Response('<?php <? <% <script language=php>'); - $esi->process($request, $response); + $this->assertSame($response, $esi->process($request, $response)); $this->assertEquals('<?php echo "<?"; ?>php <?php echo "<?"; ?> <?php echo "<%"; ?> <?php echo "<s"; ?>cript language=php>', $response->getContent()); } - /** - * @expectedException \RuntimeException - */ public function testProcessWhenNoSrcInAnEsi() { + $this->expectException('RuntimeException'); $esi = new Esi(); $request = Request::create('/'); $response = new Response('foo <esi:include />'); - $esi->process($request, $response); + $this->assertSame($response, $esi->process($request, $response)); } public function testProcessRemoveSurrogateControlHeader() @@ -172,16 +170,16 @@ class EsiTest extends TestCase $request = Request::create('/'); $response = new Response('foo <esi:include src="..." />'); $response->headers->set('Surrogate-Control', 'content="ESI/1.0"'); - $esi->process($request, $response); + $this->assertSame($response, $esi->process($request, $response)); $this->assertEquals('ESI', $response->headers->get('x-body-eval')); $response->headers->set('Surrogate-Control', 'no-store, content="ESI/1.0"'); - $esi->process($request, $response); + $this->assertSame($response, $esi->process($request, $response)); $this->assertEquals('ESI', $response->headers->get('x-body-eval')); $this->assertEquals('no-store', $response->headers->get('surrogate-control')); $response->headers->set('Surrogate-Control', 'content="ESI/1.0", no-store'); - $esi->process($request, $response); + $this->assertSame($response, $esi->process($request, $response)); $this->assertEquals('ESI', $response->headers->get('x-body-eval')); $this->assertEquals('no-store', $response->headers->get('surrogate-control')); } @@ -193,11 +191,9 @@ class EsiTest extends TestCase $this->assertEquals('foo', $esi->handle($cache, '/', '/alt', true)); } - /** - * @expectedException \RuntimeException - */ public function testHandleWhenResponseIsNot200() { + $this->expectException('RuntimeException'); $esi = new Esi(); $response = new Response('foo'); $response->setStatusCode(404); @@ -220,26 +216,26 @@ class EsiTest extends TestCase $response1 = new Response('foo'); $response1->setStatusCode(404); $response2 = new Response('bar'); - $cache = $this->getCache(Request::create('/'), array($response1, $response2)); + $cache = $this->getCache(Request::create('/'), [$response1, $response2]); $this->assertEquals('bar', $esi->handle($cache, '/', '/alt', false)); } protected function getCache($request, $response) { - $cache = $this->getMockBuilder('Symfony\Component\HttpKernel\HttpCache\HttpCache')->setMethods(array('getRequest', 'handle'))->disableOriginalConstructor()->getMock(); + $cache = $this->getMockBuilder('Symfony\Component\HttpKernel\HttpCache\HttpCache')->setMethods(['getRequest', 'handle'])->disableOriginalConstructor()->getMock(); $cache->expects($this->any()) ->method('getRequest') - ->will($this->returnValue($request)) + ->willReturn($request) ; - if (is_array($response)) { + if (\is_array($response)) { $cache->expects($this->any()) ->method('handle') - ->will(call_user_func_array(array($this, 'onConsecutiveCalls'), $response)) + ->will($this->onConsecutiveCalls(...$response)) ; } else { $cache->expects($this->any()) ->method('handle') - ->will($this->returnValue($response)) + ->willReturn($response) ; } diff --git a/vendor/symfony/http-kernel/Tests/HttpCache/HttpCacheTest.php b/vendor/symfony/http-kernel/Tests/HttpCache/HttpCacheTest.php index 2a9a30d9ca4092dfe255e9a36615285fd836dfa0..c5bbc8c6897c93a8e47429a103957a1b77ab0308 100644 --- a/vendor/symfony/http-kernel/Tests/HttpCache/HttpCacheTest.php +++ b/vendor/symfony/http-kernel/Tests/HttpCache/HttpCacheTest.php @@ -11,9 +11,11 @@ namespace Symfony\Component\HttpKernel\Tests\HttpCache; -use Symfony\Component\HttpKernel\HttpCache\HttpCache; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpKernel\HttpCache\Esi; +use Symfony\Component\HttpKernel\HttpCache\HttpCache; +use Symfony\Component\HttpKernel\HttpCache\Store; use Symfony\Component\HttpKernel\HttpKernelInterface; /** @@ -37,7 +39,7 @@ class HttpCacheTest extends HttpCacheTestCase // implements TerminableInterface $kernelMock = $this->getMockBuilder('Symfony\\Component\\HttpKernel\\Kernel') ->disableOriginalConstructor() - ->setMethods(array('terminate', 'registerBundles', 'registerContainerConfiguration')) + ->setMethods(['terminate', 'registerBundles', 'registerContainerConfiguration']) ->getMock(); $kernelMock->expects($this->once()) @@ -59,7 +61,7 @@ class HttpCacheTest extends HttpCacheTestCase public function testInvalidatesOnPostPutDeleteRequests() { - foreach (array('post', 'put', 'delete') as $method) { + foreach (['post', 'put', 'delete'] as $method) { $this->setNextResponse(200); $this->request($method, '/'); @@ -72,8 +74,8 @@ class HttpCacheTest extends HttpCacheTestCase public function testDoesNotCacheWithAuthorizationRequestHeaderAndNonPublicResponse() { - $this->setNextResponse(200, array('ETag' => '"Foo"')); - $this->request('GET', '/', array('HTTP_AUTHORIZATION' => 'basic foobarbaz')); + $this->setNextResponse(200, ['ETag' => '"Foo"']); + $this->request('GET', '/', ['HTTP_AUTHORIZATION' => 'basic foobarbaz']); $this->assertHttpKernelIsCalled(); $this->assertResponseOk(); @@ -86,8 +88,8 @@ class HttpCacheTest extends HttpCacheTestCase public function testDoesCacheWithAuthorizationRequestHeaderAndPublicResponse() { - $this->setNextResponse(200, array('Cache-Control' => 'public', 'ETag' => '"Foo"')); - $this->request('GET', '/', array('HTTP_AUTHORIZATION' => 'basic foobarbaz')); + $this->setNextResponse(200, ['Cache-Control' => 'public', 'ETag' => '"Foo"']); + $this->request('GET', '/', ['HTTP_AUTHORIZATION' => 'basic foobarbaz']); $this->assertHttpKernelIsCalled(); $this->assertResponseOk(); @@ -99,8 +101,8 @@ class HttpCacheTest extends HttpCacheTestCase public function testDoesNotCacheWithCookieHeaderAndNonPublicResponse() { - $this->setNextResponse(200, array('ETag' => '"Foo"')); - $this->request('GET', '/', array(), array('foo' => 'bar')); + $this->setNextResponse(200, ['ETag' => '"Foo"']); + $this->request('GET', '/', [], ['foo' => 'bar']); $this->assertHttpKernelIsCalled(); $this->assertResponseOk(); @@ -113,7 +115,7 @@ class HttpCacheTest extends HttpCacheTestCase public function testDoesNotCacheRequestsWithACookieHeader() { $this->setNextResponse(200); - $this->request('GET', '/', array(), array('foo' => 'bar')); + $this->request('GET', '/', [], ['foo' => 'bar']); $this->assertHttpKernelIsCalled(); $this->assertResponseOk(); @@ -127,8 +129,8 @@ class HttpCacheTest extends HttpCacheTestCase { $time = \DateTime::createFromFormat('U', time()); - $this->setNextResponse(200, array('Cache-Control' => 'public', 'Last-Modified' => $time->format(DATE_RFC2822), 'Content-Type' => 'text/plain'), 'Hello World'); - $this->request('GET', '/', array('HTTP_IF_MODIFIED_SINCE' => $time->format(DATE_RFC2822))); + $this->setNextResponse(200, ['Cache-Control' => 'public', 'Last-Modified' => $time->format(DATE_RFC2822), 'Content-Type' => 'text/plain'], 'Hello World'); + $this->request('GET', '/', ['HTTP_IF_MODIFIED_SINCE' => $time->format(DATE_RFC2822)]); $this->assertHttpKernelIsCalled(); $this->assertEquals(304, $this->response->getStatusCode()); @@ -140,8 +142,8 @@ class HttpCacheTest extends HttpCacheTestCase public function testRespondsWith304WhenIfNoneMatchMatchesETag() { - $this->setNextResponse(200, array('Cache-Control' => 'public', 'ETag' => '12345', 'Content-Type' => 'text/plain'), 'Hello World'); - $this->request('GET', '/', array('HTTP_IF_NONE_MATCH' => '12345')); + $this->setNextResponse(200, ['Cache-Control' => 'public', 'ETag' => '12345', 'Content-Type' => 'text/plain'], 'Hello World'); + $this->request('GET', '/', ['HTTP_IF_NONE_MATCH' => '12345']); $this->assertHttpKernelIsCalled(); $this->assertEquals(304, $this->response->getStatusCode()); @@ -156,7 +158,7 @@ class HttpCacheTest extends HttpCacheTestCase { $time = \DateTime::createFromFormat('U', time()); - $this->setNextResponse(200, array(), '', function ($request, $response) use ($time) { + $this->setNextResponse(200, [], '', function ($request, $response) use ($time) { $response->setStatusCode(200); $response->headers->set('ETag', '12345'); $response->headers->set('Last-Modified', $time->format(DATE_RFC2822)); @@ -166,17 +168,17 @@ class HttpCacheTest extends HttpCacheTestCase // only ETag matches $t = \DateTime::createFromFormat('U', time() - 3600); - $this->request('GET', '/', array('HTTP_IF_NONE_MATCH' => '12345', 'HTTP_IF_MODIFIED_SINCE' => $t->format(DATE_RFC2822))); + $this->request('GET', '/', ['HTTP_IF_NONE_MATCH' => '12345', 'HTTP_IF_MODIFIED_SINCE' => $t->format(DATE_RFC2822)]); $this->assertHttpKernelIsCalled(); $this->assertEquals(200, $this->response->getStatusCode()); // only Last-Modified matches - $this->request('GET', '/', array('HTTP_IF_NONE_MATCH' => '1234', 'HTTP_IF_MODIFIED_SINCE' => $time->format(DATE_RFC2822))); + $this->request('GET', '/', ['HTTP_IF_NONE_MATCH' => '1234', 'HTTP_IF_MODIFIED_SINCE' => $time->format(DATE_RFC2822)]); $this->assertHttpKernelIsCalled(); $this->assertEquals(200, $this->response->getStatusCode()); // Both matches - $this->request('GET', '/', array('HTTP_IF_NONE_MATCH' => '12345', 'HTTP_IF_MODIFIED_SINCE' => $time->format(DATE_RFC2822))); + $this->request('GET', '/', ['HTTP_IF_NONE_MATCH' => '12345', 'HTTP_IF_MODIFIED_SINCE' => $time->format(DATE_RFC2822)]); $this->assertHttpKernelIsCalled(); $this->assertEquals(304, $this->response->getStatusCode()); } @@ -185,10 +187,10 @@ class HttpCacheTest extends HttpCacheTestCase { $this->setNextResponse( 200, - array( + [ 'ETag' => '1234', 'Cache-Control' => 'public, s-maxage=60', - ) + ] ); $this->request('GET', '/'); @@ -208,12 +210,12 @@ class HttpCacheTest extends HttpCacheTestCase public function testValidatesPrivateResponsesCachedOnTheClient() { - $this->setNextResponse(200, array(), '', function ($request, $response) { + $this->setNextResponse(200, [], '', function ($request, $response) { $etags = preg_split('/\s*,\s*/', $request->headers->get('IF_NONE_MATCH')); if ($request->cookies->has('authenticated')) { $response->headers->set('Cache-Control', 'private, no-store'); $response->setETag('"private tag"'); - if (in_array('"private tag"', $etags)) { + if (\in_array('"private tag"', $etags)) { $response->setStatusCode(304); } else { $response->setStatusCode(200); @@ -223,7 +225,7 @@ class HttpCacheTest extends HttpCacheTestCase } else { $response->headers->set('Cache-Control', 'public'); $response->setETag('"public tag"'); - if (in_array('"public tag"', $etags)) { + if (\in_array('"public tag"', $etags)) { $response->setStatusCode(304); } else { $response->setStatusCode(200); @@ -241,7 +243,7 @@ class HttpCacheTest extends HttpCacheTestCase $this->assertTraceContains('miss'); $this->assertTraceContains('store'); - $this->request('GET', '/', array(), array('authenticated' => '')); + $this->request('GET', '/', [], ['authenticated' => '']); $this->assertHttpKernelIsCalled(); $this->assertEquals(200, $this->response->getStatusCode()); $this->assertEquals('"private tag"', $this->response->headers->get('ETag')); @@ -255,8 +257,8 @@ class HttpCacheTest extends HttpCacheTestCase { $time = \DateTime::createFromFormat('U', time() + 5); - $this->setNextResponse(200, array('Cache-Control' => 'public', 'Expires' => $time->format(DATE_RFC2822))); - $this->request('GET', '/', array('HTTP_CACHE_CONTROL' => 'no-cache')); + $this->setNextResponse(200, ['Cache-Control' => 'public', 'Expires' => $time->format(DATE_RFC2822)]); + $this->request('GET', '/', ['HTTP_CACHE_CONTROL' => 'no-cache']); $this->assertHttpKernelIsCalled(); $this->assertTraceContains('store'); @@ -267,7 +269,7 @@ class HttpCacheTest extends HttpCacheTestCase { $count = 0; - $this->setNextResponse(200, array('Cache-Control' => 'public, max-age=10000'), '', function ($request, $response) use (&$count) { + $this->setNextResponse(200, ['Cache-Control' => 'public, max-age=10000'], '', function ($request, $response) use (&$count) { ++$count; $response->setContent(1 == $count ? 'Hello World' : 'Goodbye World'); }); @@ -283,7 +285,7 @@ class HttpCacheTest extends HttpCacheTestCase $this->assertTraceContains('fresh'); $this->cacheConfig['allow_reload'] = true; - $this->request('GET', '/', array('HTTP_CACHE_CONTROL' => 'no-cache')); + $this->request('GET', '/', ['HTTP_CACHE_CONTROL' => 'no-cache']); $this->assertEquals(200, $this->response->getStatusCode()); $this->assertEquals('Goodbye World', $this->response->getContent()); $this->assertTraceContains('reload'); @@ -294,7 +296,7 @@ class HttpCacheTest extends HttpCacheTestCase { $count = 0; - $this->setNextResponse(200, array('Cache-Control' => 'public, max-age=10000'), '', function ($request, $response) use (&$count) { + $this->setNextResponse(200, ['Cache-Control' => 'public, max-age=10000'], '', function ($request, $response) use (&$count) { ++$count; $response->setContent(1 == $count ? 'Hello World' : 'Goodbye World'); }); @@ -310,12 +312,12 @@ class HttpCacheTest extends HttpCacheTestCase $this->assertTraceContains('fresh'); $this->cacheConfig['allow_reload'] = false; - $this->request('GET', '/', array('HTTP_CACHE_CONTROL' => 'no-cache')); + $this->request('GET', '/', ['HTTP_CACHE_CONTROL' => 'no-cache']); $this->assertEquals(200, $this->response->getStatusCode()); $this->assertEquals('Hello World', $this->response->getContent()); $this->assertTraceNotContains('reload'); - $this->request('GET', '/', array('HTTP_CACHE_CONTROL' => 'no-cache')); + $this->request('GET', '/', ['HTTP_CACHE_CONTROL' => 'no-cache']); $this->assertEquals(200, $this->response->getStatusCode()); $this->assertEquals('Hello World', $this->response->getContent()); $this->assertTraceNotContains('reload'); @@ -325,7 +327,7 @@ class HttpCacheTest extends HttpCacheTestCase { $count = 0; - $this->setNextResponse(200, array(), '', function ($request, $response) use (&$count) { + $this->setNextResponse(200, [], '', function ($request, $response) use (&$count) { ++$count; $response->headers->set('Cache-Control', 'public, max-age=10000'); $response->setETag($count); @@ -343,7 +345,7 @@ class HttpCacheTest extends HttpCacheTestCase $this->assertTraceContains('fresh'); $this->cacheConfig['allow_revalidate'] = true; - $this->request('GET', '/', array('HTTP_CACHE_CONTROL' => 'max-age=0')); + $this->request('GET', '/', ['HTTP_CACHE_CONTROL' => 'max-age=0']); $this->assertEquals(200, $this->response->getStatusCode()); $this->assertEquals('Goodbye World', $this->response->getContent()); $this->assertTraceContains('stale'); @@ -355,7 +357,7 @@ class HttpCacheTest extends HttpCacheTestCase { $count = 0; - $this->setNextResponse(200, array(), '', function ($request, $response) use (&$count) { + $this->setNextResponse(200, [], '', function ($request, $response) use (&$count) { ++$count; $response->headers->set('Cache-Control', 'public, max-age=10000'); $response->setETag($count); @@ -373,14 +375,14 @@ class HttpCacheTest extends HttpCacheTestCase $this->assertTraceContains('fresh'); $this->cacheConfig['allow_revalidate'] = false; - $this->request('GET', '/', array('HTTP_CACHE_CONTROL' => 'max-age=0')); + $this->request('GET', '/', ['HTTP_CACHE_CONTROL' => 'max-age=0']); $this->assertEquals(200, $this->response->getStatusCode()); $this->assertEquals('Hello World', $this->response->getContent()); $this->assertTraceNotContains('stale'); $this->assertTraceNotContains('invalid'); $this->assertTraceContains('fresh'); - $this->request('GET', '/', array('HTTP_CACHE_CONTROL' => 'max-age=0')); + $this->request('GET', '/', ['HTTP_CACHE_CONTROL' => 'max-age=0']); $this->assertEquals(200, $this->response->getStatusCode()); $this->assertEquals('Hello World', $this->response->getContent()); $this->assertTraceNotContains('stale'); @@ -391,7 +393,7 @@ class HttpCacheTest extends HttpCacheTestCase public function testFetchesResponseFromBackendWhenCacheMisses() { $time = \DateTime::createFromFormat('U', time() + 5); - $this->setNextResponse(200, array('Cache-Control' => 'public', 'Expires' => $time->format(DATE_RFC2822))); + $this->setNextResponse(200, ['Cache-Control' => 'public', 'Expires' => $time->format(DATE_RFC2822)]); $this->request('GET', '/'); $this->assertEquals(200, $this->response->getStatusCode()); @@ -403,7 +405,7 @@ class HttpCacheTest extends HttpCacheTestCase { foreach (array_merge(range(201, 202), range(204, 206), range(303, 305), range(400, 403), range(405, 409), range(411, 417), range(500, 505)) as $code) { $time = \DateTime::createFromFormat('U', time() + 5); - $this->setNextResponse($code, array('Expires' => $time->format(DATE_RFC2822))); + $this->setNextResponse($code, ['Expires' => $time->format(DATE_RFC2822)]); $this->request('GET', '/'); $this->assertEquals($code, $this->response->getStatusCode()); @@ -415,7 +417,7 @@ class HttpCacheTest extends HttpCacheTestCase public function testDoesNotCacheResponsesWithExplicitNoStoreDirective() { $time = \DateTime::createFromFormat('U', time() + 5); - $this->setNextResponse(200, array('Expires' => $time->format(DATE_RFC2822), 'Cache-Control' => 'no-store')); + $this->setNextResponse(200, ['Expires' => $time->format(DATE_RFC2822), 'Cache-Control' => 'no-store']); $this->request('GET', '/'); $this->assertTraceNotContains('store'); @@ -434,7 +436,7 @@ class HttpCacheTest extends HttpCacheTestCase public function testCachesResponsesWithExplicitNoCacheDirective() { $time = \DateTime::createFromFormat('U', time() + 5); - $this->setNextResponse(200, array('Expires' => $time->format(DATE_RFC2822), 'Cache-Control' => 'public, no-cache')); + $this->setNextResponse(200, ['Expires' => $time->format(DATE_RFC2822), 'Cache-Control' => 'public, no-cache']); $this->request('GET', '/'); $this->assertTraceContains('store'); @@ -444,7 +446,7 @@ class HttpCacheTest extends HttpCacheTestCase public function testCachesResponsesWithAnExpirationHeader() { $time = \DateTime::createFromFormat('U', time() + 5); - $this->setNextResponse(200, array('Cache-Control' => 'public', 'Expires' => $time->format(DATE_RFC2822))); + $this->setNextResponse(200, ['Cache-Control' => 'public', 'Expires' => $time->format(DATE_RFC2822)]); $this->request('GET', '/'); $this->assertEquals(200, $this->response->getStatusCode()); @@ -460,7 +462,7 @@ class HttpCacheTest extends HttpCacheTestCase public function testCachesResponsesWithAMaxAgeDirective() { - $this->setNextResponse(200, array('Cache-Control' => 'public, max-age=5')); + $this->setNextResponse(200, ['Cache-Control' => 'public, max-age=5']); $this->request('GET', '/'); $this->assertEquals(200, $this->response->getStatusCode()); @@ -476,7 +478,7 @@ class HttpCacheTest extends HttpCacheTestCase public function testCachesResponsesWithASMaxAgeDirective() { - $this->setNextResponse(200, array('Cache-Control' => 's-maxage=5')); + $this->setNextResponse(200, ['Cache-Control' => 's-maxage=5']); $this->request('GET', '/'); $this->assertEquals(200, $this->response->getStatusCode()); @@ -493,7 +495,7 @@ class HttpCacheTest extends HttpCacheTestCase public function testCachesResponsesWithALastModifiedValidatorButNoFreshnessInformation() { $time = \DateTime::createFromFormat('U', time()); - $this->setNextResponse(200, array('Cache-Control' => 'public', 'Last-Modified' => $time->format(DATE_RFC2822))); + $this->setNextResponse(200, ['Cache-Control' => 'public', 'Last-Modified' => $time->format(DATE_RFC2822)]); $this->request('GET', '/'); $this->assertEquals(200, $this->response->getStatusCode()); @@ -504,7 +506,7 @@ class HttpCacheTest extends HttpCacheTestCase public function testCachesResponsesWithAnETagValidatorButNoFreshnessInformation() { - $this->setNextResponse(200, array('Cache-Control' => 'public', 'ETag' => '"123456"')); + $this->setNextResponse(200, ['Cache-Control' => 'public', 'ETag' => '"123456"']); $this->request('GET', '/'); $this->assertEquals(200, $this->response->getStatusCode()); @@ -517,7 +519,7 @@ class HttpCacheTest extends HttpCacheTestCase { $time1 = \DateTime::createFromFormat('U', time() - 5); $time2 = \DateTime::createFromFormat('U', time() + 5); - $this->setNextResponse(200, array('Cache-Control' => 'public', 'Date' => $time1->format(DATE_RFC2822), 'Expires' => $time2->format(DATE_RFC2822))); + $this->setNextResponse(200, ['Cache-Control' => 'public', 'Date' => $time1->format(DATE_RFC2822), 'Expires' => $time2->format(DATE_RFC2822)]); $this->request('GET', '/'); $this->assertHttpKernelIsCalled(); @@ -541,7 +543,7 @@ class HttpCacheTest extends HttpCacheTestCase public function testHitsCachedResponseWithMaxAgeDirective() { $time = \DateTime::createFromFormat('U', time() - 5); - $this->setNextResponse(200, array('Date' => $time->format(DATE_RFC2822), 'Cache-Control' => 'public, max-age=10')); + $this->setNextResponse(200, ['Date' => $time->format(DATE_RFC2822), 'Cache-Control' => 'public, max-age=10']); $this->request('GET', '/'); $this->assertHttpKernelIsCalled(); @@ -564,14 +566,14 @@ class HttpCacheTest extends HttpCacheTestCase public function testDegradationWhenCacheLocked() { - if ('\\' === DIRECTORY_SEPARATOR) { + if ('\\' === \DIRECTORY_SEPARATOR) { $this->markTestSkipped('Skips on windows to avoid permissions issues.'); } $this->cacheConfig['stale_while_revalidate'] = 10; // The prescence of Last-Modified makes this cacheable (because Response::isValidateable() then). - $this->setNextResponse(200, array('Cache-Control' => 'public, s-maxage=5', 'Last-Modified' => 'some while ago'), 'Old response'); + $this->setNextResponse(200, ['Cache-Control' => 'public, s-maxage=5', 'Last-Modified' => 'some while ago'], 'Old response'); $this->request('GET', '/'); // warm the cache // Now, lock the cache @@ -605,7 +607,7 @@ class HttpCacheTest extends HttpCacheTestCase public function testHitsCachedResponseWithSMaxAgeDirective() { $time = \DateTime::createFromFormat('U', time() - 5); - $this->setNextResponse(200, array('Date' => $time->format(DATE_RFC2822), 'Cache-Control' => 's-maxage=10, max-age=0')); + $this->setNextResponse(200, ['Date' => $time->format(DATE_RFC2822), 'Cache-Control' => 's-maxage=10, max-age=0']); $this->request('GET', '/'); $this->assertHttpKernelIsCalled(); @@ -658,7 +660,7 @@ class HttpCacheTest extends HttpCacheTestCase $this->assertTraceContains('miss'); $this->assertTraceContains('store'); $this->assertEquals('Hello World', $this->response->getContent()); - $this->assertRegExp('/s-maxage=2/', $this->response->headers->get('Cache-Control')); + $this->assertRegExp('/s-maxage=(2|3)/', $this->response->headers->get('Cache-Control')); $this->request('GET', '/'); $this->assertHttpKernelIsNotCalled(); @@ -666,7 +668,7 @@ class HttpCacheTest extends HttpCacheTestCase $this->assertTraceContains('fresh'); $this->assertTraceNotContains('store'); $this->assertEquals('Hello World', $this->response->getContent()); - $this->assertRegExp('/s-maxage=2/', $this->response->headers->get('Cache-Control')); + $this->assertRegExp('/s-maxage=(2|3)/', $this->response->headers->get('Cache-Control')); // expires the cache $values = $this->getMetaStorageValues(); @@ -686,7 +688,7 @@ class HttpCacheTest extends HttpCacheTestCase $this->assertTraceContains('invalid'); $this->assertTraceContains('store'); $this->assertEquals('Hello World', $this->response->getContent()); - $this->assertRegExp('/s-maxage=2/', $this->response->headers->get('Cache-Control')); + $this->assertRegExp('/s-maxage=(2|3)/', $this->response->headers->get('Cache-Control')); $this->setNextResponse(); @@ -696,7 +698,7 @@ class HttpCacheTest extends HttpCacheTestCase $this->assertTraceContains('fresh'); $this->assertTraceNotContains('store'); $this->assertEquals('Hello World', $this->response->getContent()); - $this->assertRegExp('/s-maxage=2/', $this->response->headers->get('Cache-Control')); + $this->assertRegExp('/s-maxage=(2|3)/', $this->response->headers->get('Cache-Control')); } public function testAssignsDefaultTtlWhenResponseHasNoFreshnessInformationAndAfterTtlWasExpiredWithStatus304() @@ -709,7 +711,7 @@ class HttpCacheTest extends HttpCacheTestCase $this->assertTraceContains('miss'); $this->assertTraceContains('store'); $this->assertEquals('Hello World', $this->response->getContent()); - $this->assertRegExp('/s-maxage=2/', $this->response->headers->get('Cache-Control')); + $this->assertRegExp('/s-maxage=(2|3)/', $this->response->headers->get('Cache-Control')); $this->request('GET', '/'); $this->assertHttpKernelIsNotCalled(); @@ -737,7 +739,7 @@ class HttpCacheTest extends HttpCacheTestCase $this->assertTraceContains('store'); $this->assertTraceNotContains('miss'); $this->assertEquals('Hello World', $this->response->getContent()); - $this->assertRegExp('/s-maxage=2/', $this->response->headers->get('Cache-Control')); + $this->assertRegExp('/s-maxage=(2|3)/', $this->response->headers->get('Cache-Control')); $this->request('GET', '/'); $this->assertHttpKernelIsNotCalled(); @@ -745,12 +747,12 @@ class HttpCacheTest extends HttpCacheTestCase $this->assertTraceContains('fresh'); $this->assertTraceNotContains('store'); $this->assertEquals('Hello World', $this->response->getContent()); - $this->assertRegExp('/s-maxage=2/', $this->response->headers->get('Cache-Control')); + $this->assertRegExp('/s-maxage=(2|3)/', $this->response->headers->get('Cache-Control')); } public function testDoesNotAssignDefaultTtlWhenResponseHasMustRevalidateDirective() { - $this->setNextResponse(200, array('Cache-Control' => 'must-revalidate')); + $this->setNextResponse(200, ['Cache-Control' => 'must-revalidate']); $this->cacheConfig['default_ttl'] = 10; $this->request('GET', '/'); @@ -765,7 +767,7 @@ class HttpCacheTest extends HttpCacheTestCase public function testFetchesFullResponseWhenCacheStaleAndNoValidatorsPresent() { $time = \DateTime::createFromFormat('U', time() + 5); - $this->setNextResponse(200, array('Cache-Control' => 'public', 'Expires' => $time->format(DATE_RFC2822))); + $this->setNextResponse(200, ['Cache-Control' => 'public', 'Expires' => $time->format(DATE_RFC2822)]); // build initial request $this->request('GET', '/'); @@ -805,7 +807,7 @@ class HttpCacheTest extends HttpCacheTestCase public function testValidatesCachedResponsesWithLastModifiedAndNoFreshnessInformation() { $time = \DateTime::createFromFormat('U', time()); - $this->setNextResponse(200, array(), 'Hello World', function ($request, $response) use ($time) { + $this->setNextResponse(200, [], 'Hello World', function ($request, $response) use ($time) { $response->headers->set('Cache-Control', 'public'); $response->headers->set('Last-Modified', $time->format(DATE_RFC2822)); if ($time->format(DATE_RFC2822) == $request->headers->get('IF_MODIFIED_SINCE')) { @@ -843,7 +845,7 @@ class HttpCacheTest extends HttpCacheTestCase { $test = $this; - $this->setNextResponse(200, array(), 'Hello World', function ($request, $response) use ($test) { + $this->setNextResponse(200, [], 'Hello World', function ($request, $response) use ($test) { $test->assertSame('OPTIONS', $request->getMethod()); }); @@ -856,7 +858,7 @@ class HttpCacheTest extends HttpCacheTestCase public function testValidatesCachedResponsesWithETagAndNoFreshnessInformation() { - $this->setNextResponse(200, array(), 'Hello World', function ($request, $response) { + $this->setNextResponse(200, [], 'Hello World', function ($request, $response) { $response->headers->set('Cache-Control', 'public'); $response->headers->set('ETag', '"12345"'); if ($response->getETag() == $request->headers->get('IF_NONE_MATCH')) { @@ -893,7 +895,7 @@ class HttpCacheTest extends HttpCacheTestCase { $time = \DateTime::createFromFormat('U', time()); - $this->setNextResponse(200, array(), 'Hello World', function (Request $request, Response $response) use ($time) { + $this->setNextResponse(200, [], 'Hello World', function (Request $request, Response $response) use ($time) { $response->setSharedMaxAge(10); $response->headers->set('Last-Modified', $time->format(DATE_RFC2822)); }); @@ -911,7 +913,7 @@ class HttpCacheTest extends HttpCacheTestCase sleep(15); // expire the cache - $this->setNextResponse(304, array(), '', function (Request $request, Response $response) use ($time) { + $this->setNextResponse(304, [], '', function (Request $request, Response $response) use ($time) { $this->assertEquals($time->format(DATE_RFC2822), $request->headers->get('IF_MODIFIED_SINCE')); }); @@ -927,7 +929,7 @@ class HttpCacheTest extends HttpCacheTestCase { $time = \DateTime::createFromFormat('U', time()); $count = 0; - $this->setNextResponse(200, array(), 'Hello World', function ($request, $response) use ($time, &$count) { + $this->setNextResponse(200, [], 'Hello World', function ($request, $response) use ($time, &$count) { $response->headers->set('Last-Modified', $time->format(DATE_RFC2822)); $response->headers->set('Cache-Control', 'public'); switch (++$count) { @@ -964,20 +966,20 @@ class HttpCacheTest extends HttpCacheTestCase public function testPassesHeadRequestsThroughDirectlyOnPass() { - $this->setNextResponse(200, array(), 'Hello World', function ($request, $response) { + $this->setNextResponse(200, [], 'Hello World', function ($request, $response) { $response->setContent(''); $response->setStatusCode(200); $this->assertEquals('HEAD', $request->getMethod()); }); - $this->request('HEAD', '/', array('HTTP_EXPECT' => 'something ...')); + $this->request('HEAD', '/', ['HTTP_EXPECT' => 'something ...']); $this->assertHttpKernelIsCalled(); $this->assertEquals('', $this->response->getContent()); } public function testUsesCacheToRespondToHeadRequestsWhenFresh() { - $this->setNextResponse(200, array(), 'Hello World', function ($request, $response) { + $this->setNextResponse(200, [], 'Hello World', function ($request, $response) { $response->headers->set('Cache-Control', 'public, max-age=10'); $response->setContent('Hello World'); $response->setStatusCode(200); @@ -992,13 +994,13 @@ class HttpCacheTest extends HttpCacheTestCase $this->assertHttpKernelIsNotCalled(); $this->assertEquals(200, $this->response->getStatusCode()); $this->assertEquals('', $this->response->getContent()); - $this->assertEquals(strlen('Hello World'), $this->response->headers->get('Content-Length')); + $this->assertEquals(\strlen('Hello World'), $this->response->headers->get('Content-Length')); } public function testSendsNoContentWhenFresh() { $time = \DateTime::createFromFormat('U', time()); - $this->setNextResponse(200, array(), 'Hello World', function ($request, $response) use ($time) { + $this->setNextResponse(200, [], 'Hello World', function ($request, $response) use ($time) { $response->headers->set('Cache-Control', 'public, max-age=10'); $response->headers->set('Last-Modified', $time->format(DATE_RFC2822)); }); @@ -1007,7 +1009,7 @@ class HttpCacheTest extends HttpCacheTestCase $this->assertHttpKernelIsCalled(); $this->assertEquals('Hello World', $this->response->getContent()); - $this->request('GET', '/', array('HTTP_IF_MODIFIED_SINCE' => $time->format(DATE_RFC2822))); + $this->request('GET', '/', ['HTTP_IF_MODIFIED_SINCE' => $time->format(DATE_RFC2822)]); $this->assertHttpKernelIsNotCalled(); $this->assertEquals(304, $this->response->getStatusCode()); $this->assertEquals('', $this->response->getContent()); @@ -1015,7 +1017,7 @@ class HttpCacheTest extends HttpCacheTestCase public function testInvalidatesCachedResponsesOnPost() { - $this->setNextResponse(200, array(), 'Hello World', function ($request, $response) { + $this->setNextResponse(200, [], 'Hello World', function ($request, $response) { if ('GET' == $request->getMethod()) { $response->setStatusCode(200); $response->headers->set('Cache-Control', 'public, max-age=500'); @@ -1064,20 +1066,20 @@ class HttpCacheTest extends HttpCacheTestCase public function testServesFromCacheWhenHeadersMatch() { $count = 0; - $this->setNextResponse(200, array('Cache-Control' => 'max-age=10000'), '', function ($request, $response) use (&$count) { + $this->setNextResponse(200, ['Cache-Control' => 'max-age=10000'], '', function ($request, $response) use (&$count) { $response->headers->set('Vary', 'Accept User-Agent Foo'); $response->headers->set('Cache-Control', 'public, max-age=10'); $response->headers->set('X-Response-Count', ++$count); $response->setContent($request->headers->get('USER_AGENT')); }); - $this->request('GET', '/', array('HTTP_ACCEPT' => 'text/html', 'HTTP_USER_AGENT' => 'Bob/1.0')); + $this->request('GET', '/', ['HTTP_ACCEPT' => 'text/html', 'HTTP_USER_AGENT' => 'Bob/1.0']); $this->assertEquals(200, $this->response->getStatusCode()); $this->assertEquals('Bob/1.0', $this->response->getContent()); $this->assertTraceContains('miss'); $this->assertTraceContains('store'); - $this->request('GET', '/', array('HTTP_ACCEPT' => 'text/html', 'HTTP_USER_AGENT' => 'Bob/1.0')); + $this->request('GET', '/', ['HTTP_ACCEPT' => 'text/html', 'HTTP_USER_AGENT' => 'Bob/1.0']); $this->assertEquals(200, $this->response->getStatusCode()); $this->assertEquals('Bob/1.0', $this->response->getContent()); $this->assertTraceContains('fresh'); @@ -1088,36 +1090,36 @@ class HttpCacheTest extends HttpCacheTestCase public function testStoresMultipleResponsesWhenHeadersDiffer() { $count = 0; - $this->setNextResponse(200, array('Cache-Control' => 'max-age=10000'), '', function ($request, $response) use (&$count) { + $this->setNextResponse(200, ['Cache-Control' => 'max-age=10000'], '', function ($request, $response) use (&$count) { $response->headers->set('Vary', 'Accept User-Agent Foo'); $response->headers->set('Cache-Control', 'public, max-age=10'); $response->headers->set('X-Response-Count', ++$count); $response->setContent($request->headers->get('USER_AGENT')); }); - $this->request('GET', '/', array('HTTP_ACCEPT' => 'text/html', 'HTTP_USER_AGENT' => 'Bob/1.0')); + $this->request('GET', '/', ['HTTP_ACCEPT' => 'text/html', 'HTTP_USER_AGENT' => 'Bob/1.0']); $this->assertEquals(200, $this->response->getStatusCode()); $this->assertEquals('Bob/1.0', $this->response->getContent()); $this->assertEquals(1, $this->response->headers->get('X-Response-Count')); - $this->request('GET', '/', array('HTTP_ACCEPT' => 'text/html', 'HTTP_USER_AGENT' => 'Bob/2.0')); + $this->request('GET', '/', ['HTTP_ACCEPT' => 'text/html', 'HTTP_USER_AGENT' => 'Bob/2.0']); $this->assertEquals(200, $this->response->getStatusCode()); $this->assertTraceContains('miss'); $this->assertTraceContains('store'); $this->assertEquals('Bob/2.0', $this->response->getContent()); $this->assertEquals(2, $this->response->headers->get('X-Response-Count')); - $this->request('GET', '/', array('HTTP_ACCEPT' => 'text/html', 'HTTP_USER_AGENT' => 'Bob/1.0')); + $this->request('GET', '/', ['HTTP_ACCEPT' => 'text/html', 'HTTP_USER_AGENT' => 'Bob/1.0']); $this->assertTraceContains('fresh'); $this->assertEquals('Bob/1.0', $this->response->getContent()); $this->assertEquals(1, $this->response->headers->get('X-Response-Count')); - $this->request('GET', '/', array('HTTP_ACCEPT' => 'text/html', 'HTTP_USER_AGENT' => 'Bob/2.0')); + $this->request('GET', '/', ['HTTP_ACCEPT' => 'text/html', 'HTTP_USER_AGENT' => 'Bob/2.0']); $this->assertTraceContains('fresh'); $this->assertEquals('Bob/2.0', $this->response->getContent()); $this->assertEquals(2, $this->response->headers->get('X-Response-Count')); - $this->request('GET', '/', array('HTTP_USER_AGENT' => 'Bob/2.0')); + $this->request('GET', '/', ['HTTP_USER_AGENT' => 'Bob/2.0']); $this->assertTraceContains('miss'); $this->assertEquals('Bob/2.0', $this->response->getContent()); $this->assertEquals(3, $this->response->headers->get('X-Response-Count')); @@ -1139,7 +1141,7 @@ class HttpCacheTest extends HttpCacheTestCase $this->setNextResponse(); $this->cacheConfig['allow_reload'] = true; - $this->request('GET', '/', array(), array(), false, array('Pragma' => 'no-cache')); + $this->request('GET', '/', [], [], false, ['Pragma' => 'no-cache']); $this->assertExceptionsAreCaught(); } @@ -1156,30 +1158,30 @@ class HttpCacheTest extends HttpCacheTestCase public function testEsiCacheSendsTheLowestTtl() { - $responses = array( - array( + $responses = [ + [ 'status' => 200, 'body' => '<esi:include src="/foo" /> <esi:include src="/bar" />', - 'headers' => array( + 'headers' => [ 'Cache-Control' => 's-maxage=300', 'Surrogate-Control' => 'content="ESI/1.0"', - ), - ), - array( + ], + ], + [ 'status' => 200, 'body' => 'Hello World!', - 'headers' => array('Cache-Control' => 's-maxage=200'), - ), - array( + 'headers' => ['Cache-Control' => 's-maxage=200'], + ], + [ 'status' => 200, 'body' => 'My name is Bobby.', - 'headers' => array('Cache-Control' => 's-maxage=100'), - ), - ); + 'headers' => ['Cache-Control' => 's-maxage=100'], + ], + ]; $this->setNextResponses($responses); - $this->request('GET', '/', array(), array(), true); + $this->request('GET', '/', [], [], true); $this->assertEquals('Hello World! My name is Bobby.', $this->response->getContent()); $this->assertEquals(100, $this->response->getTtl()); @@ -1187,25 +1189,25 @@ class HttpCacheTest extends HttpCacheTestCase public function testEsiCacheSendsTheLowestTtlForHeadRequests() { - $responses = array( - array( + $responses = [ + [ 'status' => 200, 'body' => 'I am a long-lived master response, but I embed a short-lived resource: <esi:include src="/foo" />', - 'headers' => array( + 'headers' => [ 'Cache-Control' => 's-maxage=300', 'Surrogate-Control' => 'content="ESI/1.0"', - ), - ), - array( + ], + ], + [ 'status' => 200, 'body' => 'I am a short-lived resource', - 'headers' => array('Cache-Control' => 's-maxage=100'), - ), - ); + 'headers' => ['Cache-Control' => 's-maxage=100'], + ], + ]; $this->setNextResponses($responses); - $this->request('HEAD', '/', array(), array(), true); + $this->request('HEAD', '/', [], [], true); $this->assertEmpty($this->response->getContent()); $this->assertEquals(100, $this->response->getTtl()); @@ -1213,30 +1215,30 @@ class HttpCacheTest extends HttpCacheTestCase public function testEsiCacheForceValidation() { - $responses = array( - array( + $responses = [ + [ 'status' => 200, 'body' => '<esi:include src="/foo" /> <esi:include src="/bar" />', - 'headers' => array( + 'headers' => [ 'Cache-Control' => 's-maxage=300', 'Surrogate-Control' => 'content="ESI/1.0"', - ), - ), - array( + ], + ], + [ 'status' => 200, 'body' => 'Hello World!', - 'headers' => array('ETag' => 'foobar'), - ), - array( + 'headers' => ['ETag' => 'foobar'], + ], + [ 'status' => 200, 'body' => 'My name is Bobby.', - 'headers' => array('Cache-Control' => 's-maxage=100'), - ), - ); + 'headers' => ['Cache-Control' => 's-maxage=100'], + ], + ]; $this->setNextResponses($responses); - $this->request('GET', '/', array(), array(), true); + $this->request('GET', '/', [], [], true); $this->assertEquals('Hello World! My name is Bobby.', $this->response->getContent()); $this->assertNull($this->response->getTtl()); $this->assertTrue($this->response->mustRevalidate()); @@ -1246,25 +1248,25 @@ class HttpCacheTest extends HttpCacheTestCase public function testEsiCacheForceValidationForHeadRequests() { - $responses = array( - array( + $responses = [ + [ 'status' => 200, 'body' => 'I am the master response and use expiration caching, but I embed another resource: <esi:include src="/foo" />', - 'headers' => array( + 'headers' => [ 'Cache-Control' => 's-maxage=300', 'Surrogate-Control' => 'content="ESI/1.0"', - ), - ), - array( + ], + ], + [ 'status' => 200, 'body' => 'I am the embedded resource and use validation caching', - 'headers' => array('ETag' => 'foobar'), - ), - ); + 'headers' => ['ETag' => 'foobar'], + ], + ]; $this->setNextResponses($responses); - $this->request('HEAD', '/', array(), array(), true); + $this->request('HEAD', '/', [], [], true); // The response has been assembled from expiration and validation based resources // This can neither be cached nor revalidated, so it should be private/no cache @@ -1277,50 +1279,50 @@ class HttpCacheTest extends HttpCacheTestCase public function testEsiRecalculateContentLengthHeader() { - $responses = array( - array( + $responses = [ + [ 'status' => 200, 'body' => '<esi:include src="/foo" />', - 'headers' => array( + 'headers' => [ 'Content-Length' => 26, 'Surrogate-Control' => 'content="ESI/1.0"', - ), - ), - array( + ], + ], + [ 'status' => 200, 'body' => 'Hello World!', - 'headers' => array(), - ), - ); + 'headers' => [], + ], + ]; $this->setNextResponses($responses); - $this->request('GET', '/', array(), array(), true); + $this->request('GET', '/', [], [], true); $this->assertEquals('Hello World!', $this->response->getContent()); $this->assertEquals(12, $this->response->headers->get('Content-Length')); } public function testEsiRecalculateContentLengthHeaderForHeadRequest() { - $responses = array( - array( + $responses = [ + [ 'status' => 200, 'body' => '<esi:include src="/foo" />', - 'headers' => array( + 'headers' => [ 'Content-Length' => 26, 'Surrogate-Control' => 'content="ESI/1.0"', - ), - ), - array( + ], + ], + [ 'status' => 200, 'body' => 'Hello World!', - 'headers' => array(), - ), - ); + 'headers' => [], + ], + ]; $this->setNextResponses($responses); - $this->request('HEAD', '/', array(), array(), true); + $this->request('HEAD', '/', [], [], true); // https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.13 // "The Content-Length entity-header field indicates the size of the entity-body, @@ -1334,90 +1336,95 @@ class HttpCacheTest extends HttpCacheTestCase public function testClientIpIsAlwaysLocalhostForForwardedRequests() { $this->setNextResponse(); - $this->request('GET', '/', array('REMOTE_ADDR' => '10.0.0.1')); + $this->request('GET', '/', ['REMOTE_ADDR' => '10.0.0.1']); - $this->assertEquals('127.0.0.1', $this->kernel->getBackendRequest()->server->get('REMOTE_ADDR')); + $this->kernel->assert(function ($backendRequest) { + $this->assertSame('127.0.0.1', $backendRequest->server->get('REMOTE_ADDR')); + }); } /** * @dataProvider getTrustedProxyData */ - public function testHttpCacheIsSetAsATrustedProxy(array $existing, array $expected) + public function testHttpCacheIsSetAsATrustedProxy(array $existing) { Request::setTrustedProxies($existing, Request::HEADER_X_FORWARDED_ALL); $this->setNextResponse(); - $this->request('GET', '/', array('REMOTE_ADDR' => '10.0.0.1')); + $this->request('GET', '/', ['REMOTE_ADDR' => '10.0.0.1']); + $this->assertSame($existing, Request::getTrustedProxies()); + + $existing = array_unique(array_merge($existing, ['127.0.0.1'])); + $this->kernel->assert(function ($backendRequest) use ($existing) { + $this->assertSame($existing, Request::getTrustedProxies()); + $this->assertsame('10.0.0.1', $backendRequest->getClientIp()); + }); - $this->assertEquals($expected, Request::getTrustedProxies()); + Request::setTrustedProxies([], -1); } public function getTrustedProxyData() { - return array( - array(array(), array('127.0.0.1')), - array(array('10.0.0.2'), array('10.0.0.2', '127.0.0.1')), - array(array('10.0.0.2', '127.0.0.1'), array('10.0.0.2', '127.0.0.1')), - ); + return [ + [[]], + [['10.0.0.2']], + [['10.0.0.2', '127.0.0.1']], + ]; } /** - * @dataProvider getXForwardedForData + * @dataProvider getForwardedData */ - public function testXForwarderForHeaderForForwardedRequests($xForwardedFor, $expected) + public function testForwarderHeaderForForwardedRequests($forwarded, $expected) { $this->setNextResponse(); - $server = array('REMOTE_ADDR' => '10.0.0.1'); - if (false !== $xForwardedFor) { - $server['HTTP_X_FORWARDED_FOR'] = $xForwardedFor; + $server = ['REMOTE_ADDR' => '10.0.0.1']; + if (null !== $forwarded) { + Request::setTrustedProxies($server, -1); + $server['HTTP_FORWARDED'] = $forwarded; } $this->request('GET', '/', $server); - $this->assertEquals($expected, $this->kernel->getBackendRequest()->headers->get('X-Forwarded-For')); - } + $this->kernel->assert(function ($backendRequest) use ($expected) { + $this->assertSame($expected, $backendRequest->headers->get('Forwarded')); + }); - public function getXForwardedForData() - { - return array( - array(false, '10.0.0.1'), - array('10.0.0.2', '10.0.0.2, 10.0.0.1'), - array('10.0.0.2, 10.0.0.3', '10.0.0.2, 10.0.0.3, 10.0.0.1'), - ); + Request::setTrustedProxies([], -1); } - public function testXForwarderForHeaderForPassRequests() + public function getForwardedData() { - $this->setNextResponse(); - $server = array('REMOTE_ADDR' => '10.0.0.1'); - $this->request('POST', '/', $server); - - $this->assertEquals('10.0.0.1', $this->kernel->getBackendRequest()->headers->get('X-Forwarded-For')); + return [ + [null, 'for="10.0.0.1";host="localhost";proto=http'], + ['for=10.0.0.2', 'for="10.0.0.2";host="localhost";proto=http, for="10.0.0.1"'], + ['for=10.0.0.2, for=10.0.0.3', 'for="10.0.0.2";host="localhost";proto=http, for="10.0.0.3", for="10.0.0.1"'], + ]; } public function testEsiCacheRemoveValidationHeadersIfEmbeddedResponses() { $time = \DateTime::createFromFormat('U', time()); - $responses = array( - array( + $responses = [ + [ 'status' => 200, 'body' => '<esi:include src="/hey" />', - 'headers' => array( + 'headers' => [ 'Surrogate-Control' => 'content="ESI/1.0"', 'ETag' => 'hey', 'Last-Modified' => $time->format(DATE_RFC2822), - ), - ), - array( + ], + ], + [ 'status' => 200, 'body' => 'Hey!', - 'headers' => array(), - ), - ); + 'headers' => [], + ], + ]; $this->setNextResponses($responses); - $this->request('GET', '/', array(), array(), true); + $this->request('GET', '/', [], [], true); $this->assertNull($this->response->getETag()); $this->assertNull($this->response->getLastModified()); } @@ -1426,26 +1433,26 @@ class HttpCacheTest extends HttpCacheTestCase { $time = \DateTime::createFromFormat('U', time()); - $responses = array( - array( + $responses = [ + [ 'status' => 200, 'body' => '<esi:include src="/hey" />', - 'headers' => array( + 'headers' => [ 'Surrogate-Control' => 'content="ESI/1.0"', 'ETag' => 'hey', 'Last-Modified' => $time->format(DATE_RFC2822), - ), - ), - array( + ], + ], + [ 'status' => 200, 'body' => 'Hey!', - 'headers' => array(), - ), - ); + 'headers' => [], + ], + ]; $this->setNextResponses($responses); - $this->request('HEAD', '/', array(), array(), true); + $this->request('HEAD', '/', [], [], true); $this->assertEmpty($this->response->getContent()); $this->assertNull($this->response->getETag()); $this->assertNull($this->response->getLastModified()); @@ -1453,11 +1460,11 @@ class HttpCacheTest extends HttpCacheTestCase public function testDoesNotCacheOptionsRequest() { - $this->setNextResponse(200, array('Cache-Control' => 'public, s-maxage=60'), 'get'); + $this->setNextResponse(200, ['Cache-Control' => 'public, s-maxage=60'], 'get'); $this->request('GET', '/'); $this->assertHttpKernelIsCalled(); - $this->setNextResponse(200, array('Cache-Control' => 'public, s-maxage=60'), 'options'); + $this->setNextResponse(200, ['Cache-Control' => 'public, s-maxage=60'], 'options'); $this->request('OPTIONS', '/'); $this->assertHttpKernelIsCalled(); @@ -1465,6 +1472,80 @@ class HttpCacheTest extends HttpCacheTestCase $this->assertHttpKernelIsNotCalled(); $this->assertSame('get', $this->response->getContent()); } + + public function testUsesOriginalRequestForSurrogate() + { + $kernel = $this->getMockBuilder('Symfony\Component\HttpKernel\HttpKernelInterface')->getMock(); + $store = $this->getMockBuilder('Symfony\Component\HttpKernel\HttpCache\StoreInterface')->getMock(); + + $kernel + ->expects($this->exactly(2)) + ->method('handle') + ->willReturnCallback(function (Request $request) { + $this->assertSame('127.0.0.1', $request->server->get('REMOTE_ADDR')); + + return new Response(); + }); + + $cache = new HttpCache($kernel, + $store, + new Esi() + ); + + $request = Request::create('/'); + $request->server->set('REMOTE_ADDR', '10.0.0.1'); + + // Main request + $cache->handle($request, HttpKernelInterface::MASTER_REQUEST); + + // Main request was now modified by HttpCache + // The surrogate will ask for the request using $this->cache->getRequest() + // which MUST return the original request so the surrogate + // can actually behave like a reverse proxy like e.g. Varnish would. + $this->assertSame('10.0.0.1', $cache->getRequest()->getClientIp()); + $this->assertSame('10.0.0.1', $cache->getRequest()->server->get('REMOTE_ADDR')); + + // Surrogate request + $cache->handle($request, HttpKernelInterface::SUB_REQUEST); + } + + public function testTraceHeaderNameCanBeChanged() + { + $this->cacheConfig['trace_header'] = 'X-My-Header'; + $this->setNextResponse(); + $this->request('GET', '/'); + + $this->assertTrue($this->response->headers->has('X-My-Header')); + } + + public function testTraceLevelDefaultsToFullIfDebug() + { + $this->setNextResponse(); + $this->request('GET', '/'); + + $this->assertTrue($this->response->headers->has('X-Symfony-Cache')); + $this->assertEquals('GET /: miss', $this->response->headers->get('X-Symfony-Cache')); + } + + public function testTraceLevelDefaultsToNoneIfNotDebug() + { + $this->cacheConfig['debug'] = false; + $this->setNextResponse(); + $this->request('GET', '/'); + + $this->assertFalse($this->response->headers->has('X-Symfony-Cache')); + } + + public function testTraceLevelShort() + { + $this->cacheConfig['trace_level'] = 'short'; + + $this->setNextResponse(); + $this->request('GET', '/'); + + $this->assertTrue($this->response->headers->has('X-Symfony-Cache')); + $this->assertEquals('miss', $this->response->headers->get('X-Symfony-Cache')); + } } class TestKernel implements HttpKernelInterface diff --git a/vendor/symfony/http-kernel/Tests/HttpCache/HttpCacheTestCase.php b/vendor/symfony/http-kernel/Tests/HttpCache/HttpCacheTestCase.php index ed5c690d60bcb55538a1dabdf54baf72a281fc91..a73a327b53d0dc1020777a883f2a2e5e5e1b6d8c 100644 --- a/vendor/symfony/http-kernel/Tests/HttpCache/HttpCacheTestCase.php +++ b/vendor/symfony/http-kernel/Tests/HttpCache/HttpCacheTestCase.php @@ -35,25 +35,25 @@ class HttpCacheTestCase extends TestCase */ protected $store; - protected function setUp() + protected function setUp(): void { $this->kernel = null; $this->cache = null; $this->esi = null; - $this->caches = array(); - $this->cacheConfig = array(); + $this->caches = []; + $this->cacheConfig = []; $this->request = null; $this->response = null; - $this->responses = array(); + $this->responses = []; $this->catch = false; $this->clearDirectory(sys_get_temp_dir().'/http_cache'); } - protected function tearDown() + protected function tearDown(): void { if ($this->cache) { $this->cache->getStore()->cleanup(); @@ -112,7 +112,7 @@ class HttpCacheTestCase extends TestCase $this->assertFalse($this->kernel->isCatchingExceptions()); } - public function request($method, $uri = '/', $server = array(), $cookies = array(), $esi = false, $headers = array()) + public function request($method, $uri = '/', $server = [], $cookies = [], $esi = false, $headers = []) { if (null === $this->kernel) { throw new \LogicException('You must call setNextResponse() before calling request().'); @@ -122,11 +122,13 @@ class HttpCacheTestCase extends TestCase $this->store = new Store(sys_get_temp_dir().'/http_cache'); - $this->cacheConfig['debug'] = true; + if (!isset($this->cacheConfig['debug'])) { + $this->cacheConfig['debug'] = true; + } $this->esi = $esi ? new Esi() : null; $this->cache = new HttpCache($this->kernel, $this->store, $this->esi, $this->cacheConfig); - $this->request = Request::create($uri, $method, array(), $cookies, array(), $server); + $this->request = Request::create($uri, $method, [], $cookies, [], $server); $this->request->headers->add($headers); $this->response = $this->cache->handle($this->request, HttpKernelInterface::MASTER_REQUEST, $this->catch); @@ -136,7 +138,7 @@ class HttpCacheTestCase extends TestCase public function getMetaStorageValues() { - $values = array(); + $values = []; foreach (new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator(sys_get_temp_dir().'/http_cache/md', \RecursiveDirectoryIterator::SKIP_DOTS), \RecursiveIteratorIterator::LEAVES_ONLY) as $file) { $values[] = file_get_contents($file); } @@ -145,7 +147,7 @@ class HttpCacheTestCase extends TestCase } // A basic response with 200 status code and a tiny body. - public function setNextResponse($statusCode = 200, array $headers = array(), $body = 'Hello World', \Closure $customizer = null) + public function setNextResponse($statusCode = 200, array $headers = [], $body = 'Hello World', \Closure $customizer = null) { $this->kernel = new TestHttpKernel($body, $statusCode, $headers, $customizer); } @@ -168,7 +170,7 @@ class HttpCacheTestCase extends TestCase $fp = opendir($directory); while (false !== $file = readdir($fp)) { - if (!in_array($file, array('.', '..'))) { + if (!\in_array($file, ['.', '..'])) { if (is_link($directory.'/'.$file)) { unlink($directory.'/'.$file); } elseif (is_dir($directory.'/'.$file)) { diff --git a/vendor/symfony/http-kernel/Tests/HttpCache/ResponseCacheStrategyTest.php b/vendor/symfony/http-kernel/Tests/HttpCache/ResponseCacheStrategyTest.php index 5e4c322223eb386ce61d61c94ac337b64338a05f..22cadf712952896b4c7a819ad855e3b3effef612 100644 --- a/vendor/symfony/http-kernel/Tests/HttpCache/ResponseCacheStrategyTest.php +++ b/vendor/symfony/http-kernel/Tests/HttpCache/ResponseCacheStrategyTest.php @@ -175,8 +175,26 @@ class ResponseCacheStrategyTest extends TestCase $cacheStrategy->update($masterResponse); $this->assertTrue($masterResponse->headers->hasCacheControlDirective('private')); - // Not sure if we should pass "max-age: 60" in this case, as long as the response is private and - // that's the more conservative of both the master and embedded response...? + $this->assertFalse($masterResponse->headers->hasCacheControlDirective('public')); + } + + public function testEmbeddingPublicResponseDoesNotMakeMainResponsePublic() + { + $cacheStrategy = new ResponseCacheStrategy(); + + $masterResponse = new Response(); + $masterResponse->setPrivate(); // this is the default, but let's be explicit + $masterResponse->setMaxAge(100); + + $embeddedResponse = new Response(); + $embeddedResponse->setPublic(); + $embeddedResponse->setSharedMaxAge(100); + + $cacheStrategy->add($embeddedResponse); + $cacheStrategy->update($masterResponse); + + $this->assertTrue($masterResponse->headers->hasCacheControlDirective('private')); + $this->assertFalse($masterResponse->headers->hasCacheControlDirective('public')); } public function testResponseIsExiprableWhenEmbeddedResponseCombinesExpiryAndValidation() @@ -219,4 +237,233 @@ class ResponseCacheStrategyTest extends TestCase $this->assertSame('60', $masterResponse->headers->getCacheControlDirective('s-maxage')); $this->assertFalse($masterResponse->isValidateable()); } + + /** + * @dataProvider cacheControlMergingProvider + */ + public function testCacheControlMerging(array $expects, array $master, array $surrogates) + { + $cacheStrategy = new ResponseCacheStrategy(); + $buildResponse = function ($config) { + $response = new Response(); + + foreach ($config as $key => $value) { + switch ($key) { + case 'age': + $response->headers->set('Age', $value); + break; + + case 'expires': + $expires = clone $response->getDate(); + $expires->modify('+'.$value.' seconds'); + $response->setExpires($expires); + break; + + case 'max-age': + $response->setMaxAge($value); + break; + + case 's-maxage': + $response->setSharedMaxAge($value); + break; + + case 'private': + $response->setPrivate(); + break; + + case 'public': + $response->setPublic(); + break; + + default: + $response->headers->addCacheControlDirective($key, $value); + } + } + + return $response; + }; + + foreach ($surrogates as $config) { + $cacheStrategy->add($buildResponse($config)); + } + + $response = $buildResponse($master); + $cacheStrategy->update($response); + + foreach ($expects as $key => $value) { + if ('expires' === $key) { + $this->assertSame($value, $response->getExpires()->format('U') - $response->getDate()->format('U')); + } elseif ('age' === $key) { + $this->assertSame($value, $response->getAge()); + } elseif (true === $value) { + $this->assertTrue($response->headers->hasCacheControlDirective($key), sprintf('Cache-Control header must have "%s" flag', $key)); + } elseif (false === $value) { + $this->assertFalse( + $response->headers->hasCacheControlDirective($key), + sprintf('Cache-Control header must NOT have "%s" flag', $key) + ); + } else { + $this->assertSame($value, $response->headers->getCacheControlDirective($key), sprintf('Cache-Control flag "%s" should be "%s"', $key, $value)); + } + } + } + + public function cacheControlMergingProvider() + { + yield 'result is public if all responses are public' => [ + ['private' => false, 'public' => true], + ['public' => true], + [ + ['public' => true], + ], + ]; + + yield 'result is private by default' => [ + ['private' => true, 'public' => false], + ['public' => true], + [ + [], + ], + ]; + + yield 'combines public and private responses' => [ + ['must-revalidate' => false, 'private' => true, 'public' => false], + ['public' => true], + [ + ['private' => true], + ], + ]; + + yield 'inherits no-cache from surrogates' => [ + ['no-cache' => true, 'public' => false], + ['public' => true], + [ + ['no-cache' => true], + ], + ]; + + yield 'inherits no-store from surrogate' => [ + ['no-store' => true, 'public' => false], + ['public' => true], + [ + ['no-store' => true], + ], + ]; + + yield 'resolve to lowest possible max-age' => [ + ['public' => false, 'private' => true, 's-maxage' => false, 'max-age' => '60'], + ['public' => true, 'max-age' => 3600], + [ + ['private' => true, 'max-age' => 60], + ], + ]; + + yield 'resolves multiple max-age' => [ + ['public' => false, 'private' => true, 's-maxage' => false, 'max-age' => '60'], + ['private' => true, 'max-age' => 100], + [ + ['private' => true, 'max-age' => 3600], + ['public' => true, 'max-age' => 60, 's-maxage' => 60], + ['private' => true, 'max-age' => 60], + ], + ]; + + yield 'merge max-age and s-maxage' => [ + ['public' => true, 's-maxage' => '60', 'max-age' => null], + ['public' => true, 's-maxage' => 3600], + [ + ['public' => true, 'max-age' => 60], + ], + ]; + + yield 'result is private when combining private responses' => [ + ['no-cache' => false, 'must-revalidate' => false, 'private' => true], + ['s-maxage' => 60, 'private' => true], + [ + ['s-maxage' => 60, 'private' => true], + ], + ]; + + yield 'result can have s-maxage and max-age' => [ + ['public' => true, 'private' => false, 's-maxage' => '60', 'max-age' => '30'], + ['s-maxage' => 100, 'max-age' => 2000], + [ + ['s-maxage' => 1000, 'max-age' => 30], + ['s-maxage' => 500, 'max-age' => 500], + ['s-maxage' => 60, 'max-age' => 1000], + ], + ]; + + yield 'does not set headers without value' => [ + ['max-age' => null, 's-maxage' => null, 'public' => null], + ['private' => true], + [ + ['private' => true], + ], + ]; + + yield 'max-age 0 is sent to the client' => [ + ['private' => true, 'max-age' => '0'], + ['max-age' => 0, 'private' => true], + [ + ['max-age' => 60, 'private' => true], + ], + ]; + + yield 'max-age is relative to age' => [ + ['max-age' => '240', 'age' => 60], + ['max-age' => 180], + [ + ['max-age' => 600, 'age' => 60], + ], + ]; + + yield 'retains lowest age of all responses' => [ + ['max-age' => '160', 'age' => 60], + ['max-age' => 600, 'age' => 60], + [ + ['max-age' => 120, 'age' => 20], + ], + ]; + + yield 'max-age can be less than age, essentially expiring the response' => [ + ['age' => 120, 'max-age' => '90'], + ['max-age' => 90, 'age' => 120], + [ + ['max-age' => 120, 'age' => 60], + ], + ]; + + yield 'max-age is 0 regardless of age' => [ + ['max-age' => '0'], + ['max-age' => 60], + [ + ['max-age' => 0, 'age' => 60], + ], + ]; + + yield 'max-age is not negative' => [ + ['max-age' => '0'], + ['max-age' => 0], + [ + ['max-age' => 0, 'age' => 60], + ], + ]; + + yield 'calculates lowest Expires header' => [ + ['expires' => 60], + ['expires' => 60], + [ + ['expires' => 120], + ], + ]; + + yield 'calculates Expires header relative to age' => [ + ['expires' => 210, 'age' => 120], + ['expires' => 90], + [ + ['expires' => 600, 'age' => '120'], + ], + ]; + } } diff --git a/vendor/symfony/http-kernel/Tests/HttpCache/SsiTest.php b/vendor/symfony/http-kernel/Tests/HttpCache/SsiTest.php index 1079d37a2770057d650be9fd301bd7d1c55e8e63..3d68052cdcc105ac067bc9baaf1cca720ce2fa64 100644 --- a/vendor/symfony/http-kernel/Tests/HttpCache/SsiTest.php +++ b/vendor/symfony/http-kernel/Tests/HttpCache/SsiTest.php @@ -120,11 +120,9 @@ class SsiTest extends TestCase $this->assertEquals('<?php echo "<?"; ?>php <?php echo "<?"; ?> <?php echo "<%"; ?> <?php echo "<s"; ?>cript language=php>', $response->getContent()); } - /** - * @expectedException \RuntimeException - */ public function testProcessWhenNoSrcInAnSsi() { + $this->expectException('RuntimeException'); $ssi = new Ssi(); $request = Request::create('/'); @@ -160,11 +158,9 @@ class SsiTest extends TestCase $this->assertEquals('foo', $ssi->handle($cache, '/', '/alt', true)); } - /** - * @expectedException \RuntimeException - */ public function testHandleWhenResponseIsNot200() { + $this->expectException('RuntimeException'); $ssi = new Ssi(); $response = new Response('foo'); $response->setStatusCode(404); @@ -187,26 +183,26 @@ class SsiTest extends TestCase $response1 = new Response('foo'); $response1->setStatusCode(404); $response2 = new Response('bar'); - $cache = $this->getCache(Request::create('/'), array($response1, $response2)); + $cache = $this->getCache(Request::create('/'), [$response1, $response2]); $this->assertEquals('bar', $ssi->handle($cache, '/', '/alt', false)); } protected function getCache($request, $response) { - $cache = $this->getMockBuilder('Symfony\Component\HttpKernel\HttpCache\HttpCache')->setMethods(array('getRequest', 'handle'))->disableOriginalConstructor()->getMock(); + $cache = $this->getMockBuilder('Symfony\Component\HttpKernel\HttpCache\HttpCache')->setMethods(['getRequest', 'handle'])->disableOriginalConstructor()->getMock(); $cache->expects($this->any()) ->method('getRequest') - ->will($this->returnValue($request)) + ->willReturn($request) ; - if (is_array($response)) { + if (\is_array($response)) { $cache->expects($this->any()) ->method('handle') - ->will(call_user_func_array(array($this, 'onConsecutiveCalls'), $response)) + ->will($this->onConsecutiveCalls(...$response)) ; } else { $cache->expects($this->any()) ->method('handle') - ->will($this->returnValue($response)) + ->willReturn($response) ; } diff --git a/vendor/symfony/http-kernel/Tests/HttpCache/StoreTest.php b/vendor/symfony/http-kernel/Tests/HttpCache/StoreTest.php index cef019167a4efa88ab8339a4dcf6f02b947a1f35..2887c14f5d574cbed82df45e060d114bc5b11cd8 100644 --- a/vendor/symfony/http-kernel/Tests/HttpCache/StoreTest.php +++ b/vendor/symfony/http-kernel/Tests/HttpCache/StoreTest.php @@ -26,17 +26,17 @@ class StoreTest extends TestCase */ protected $store; - protected function setUp() + protected function setUp(): void { $this->request = Request::create('/'); - $this->response = new Response('hello world', 200, array()); + $this->response = new Response('hello world', 200, []); HttpCacheTestCase::clearDirectory(sys_get_temp_dir().'/http_cache'); $this->store = new Store(sys_get_temp_dir().'/http_cache'); } - protected function tearDown() + protected function tearDown(): void { $this->store = null; $this->request = null; @@ -108,7 +108,7 @@ class StoreTest extends TestCase public function testDoesNotFindAnEntryWithLookupWhenNoneExists() { - $request = Request::create('/test', 'get', array(), array(), array(), array('HTTP_FOO' => 'Foo', 'HTTP_BAR' => 'Bar')); + $request = Request::create('/test', 'get', [], [], [], ['HTTP_FOO' => 'Foo', 'HTTP_BAR' => 'Bar']); $this->assertNull($this->store->lookup($request)); } @@ -137,7 +137,7 @@ class StoreTest extends TestCase $this->storeSimpleEntry(); $response = $this->store->lookup($this->request); - $this->assertEquals($response->headers->all(), array_merge(array('content-length' => 4, 'x-body-file' => array($this->getStorePath($response->headers->get('X-Content-Digest')))), $this->response->headers->all())); + $this->assertEquals($response->headers->all(), array_merge(['content-length' => 4, 'x-body-file' => [$this->getStorePath($response->headers->get('X-Content-Digest'))]], $this->response->headers->all())); } public function testRestoresResponseContentFromEntityStoreWithLookup() @@ -165,9 +165,9 @@ class StoreTest extends TestCase public function testDoesNotReturnEntriesThatVaryWithLookup() { - $req1 = Request::create('/test', 'get', array(), array(), array(), array('HTTP_FOO' => 'Foo', 'HTTP_BAR' => 'Bar')); - $req2 = Request::create('/test', 'get', array(), array(), array(), array('HTTP_FOO' => 'Bling', 'HTTP_BAR' => 'Bam')); - $res = new Response('test', 200, array('Vary' => 'Foo Bar')); + $req1 = Request::create('/test', 'get', [], [], [], ['HTTP_FOO' => 'Foo', 'HTTP_BAR' => 'Bar']); + $req2 = Request::create('/test', 'get', [], [], [], ['HTTP_FOO' => 'Bling', 'HTTP_BAR' => 'Bam']); + $res = new Response('test', 200, ['Vary' => 'Foo Bar']); $this->store->write($req1, $res); $this->assertNull($this->store->lookup($req2)); @@ -175,9 +175,9 @@ class StoreTest extends TestCase public function testDoesNotReturnEntriesThatSlightlyVaryWithLookup() { - $req1 = Request::create('/test', 'get', array(), array(), array(), array('HTTP_FOO' => 'Foo', 'HTTP_BAR' => 'Bar')); - $req2 = Request::create('/test', 'get', array(), array(), array(), array('HTTP_FOO' => 'Foo', 'HTTP_BAR' => 'Bam')); - $res = new Response('test', 200, array('Vary' => array('Foo', 'Bar'))); + $req1 = Request::create('/test', 'get', [], [], [], ['HTTP_FOO' => 'Foo', 'HTTP_BAR' => 'Bar']); + $req2 = Request::create('/test', 'get', [], [], [], ['HTTP_FOO' => 'Foo', 'HTTP_BAR' => 'Bam']); + $res = new Response('test', 200, ['Vary' => ['Foo', 'Bar']]); $this->store->write($req1, $res); $this->assertNull($this->store->lookup($req2)); @@ -185,16 +185,16 @@ class StoreTest extends TestCase public function testStoresMultipleResponsesForEachVaryCombination() { - $req1 = Request::create('/test', 'get', array(), array(), array(), array('HTTP_FOO' => 'Foo', 'HTTP_BAR' => 'Bar')); - $res1 = new Response('test 1', 200, array('Vary' => 'Foo Bar')); + $req1 = Request::create('/test', 'get', [], [], [], ['HTTP_FOO' => 'Foo', 'HTTP_BAR' => 'Bar']); + $res1 = new Response('test 1', 200, ['Vary' => 'Foo Bar']); $key = $this->store->write($req1, $res1); - $req2 = Request::create('/test', 'get', array(), array(), array(), array('HTTP_FOO' => 'Bling', 'HTTP_BAR' => 'Bam')); - $res2 = new Response('test 2', 200, array('Vary' => 'Foo Bar')); + $req2 = Request::create('/test', 'get', [], [], [], ['HTTP_FOO' => 'Bling', 'HTTP_BAR' => 'Bam']); + $res2 = new Response('test 2', 200, ['Vary' => 'Foo Bar']); $this->store->write($req2, $res2); - $req3 = Request::create('/test', 'get', array(), array(), array(), array('HTTP_FOO' => 'Baz', 'HTTP_BAR' => 'Boom')); - $res3 = new Response('test 3', 200, array('Vary' => 'Foo Bar')); + $req3 = Request::create('/test', 'get', [], [], [], ['HTTP_FOO' => 'Baz', 'HTTP_BAR' => 'Boom']); + $res3 = new Response('test 3', 200, ['Vary' => 'Foo Bar']); $this->store->write($req3, $res3); $this->assertEquals($this->getStorePath('en'.hash('sha256', 'test 3')), $this->store->lookup($req3)->getContent()); @@ -206,18 +206,18 @@ class StoreTest extends TestCase public function testOverwritesNonVaryingResponseWithStore() { - $req1 = Request::create('/test', 'get', array(), array(), array(), array('HTTP_FOO' => 'Foo', 'HTTP_BAR' => 'Bar')); - $res1 = new Response('test 1', 200, array('Vary' => 'Foo Bar')); + $req1 = Request::create('/test', 'get', [], [], [], ['HTTP_FOO' => 'Foo', 'HTTP_BAR' => 'Bar']); + $res1 = new Response('test 1', 200, ['Vary' => 'Foo Bar']); $key = $this->store->write($req1, $res1); $this->assertEquals($this->getStorePath('en'.hash('sha256', 'test 1')), $this->store->lookup($req1)->getContent()); - $req2 = Request::create('/test', 'get', array(), array(), array(), array('HTTP_FOO' => 'Bling', 'HTTP_BAR' => 'Bam')); - $res2 = new Response('test 2', 200, array('Vary' => 'Foo Bar')); + $req2 = Request::create('/test', 'get', [], [], [], ['HTTP_FOO' => 'Bling', 'HTTP_BAR' => 'Bam']); + $res2 = new Response('test 2', 200, ['Vary' => 'Foo Bar']); $this->store->write($req2, $res2); $this->assertEquals($this->getStorePath('en'.hash('sha256', 'test 2')), $this->store->lookup($req2)->getContent()); - $req3 = Request::create('/test', 'get', array(), array(), array(), array('HTTP_FOO' => 'Foo', 'HTTP_BAR' => 'Bar')); - $res3 = new Response('test 3', 200, array('Vary' => 'Foo Bar')); + $req3 = Request::create('/test', 'get', [], [], [], ['HTTP_FOO' => 'Foo', 'HTTP_BAR' => 'Bar']); + $res3 = new Response('test 3', 200, ['Vary' => 'Foo Bar']); $key = $this->store->write($req3, $res3); $this->assertEquals($this->getStorePath('en'.hash('sha256', 'test 3')), $this->store->lookup($req3)->getContent()); @@ -226,7 +226,7 @@ class StoreTest extends TestCase public function testLocking() { - $req = Request::create('/test', 'get', array(), array(), array(), array('HTTP_FOO' => 'Foo', 'HTTP_BAR' => 'Bar')); + $req = Request::create('/test', 'get', [], [], [], ['HTTP_FOO' => 'Foo', 'HTTP_BAR' => 'Bar']); $this->assertTrue($this->store->lock($req)); $path = $this->store->lock($req); @@ -263,14 +263,14 @@ class StoreTest extends TestCase $this->assertEmpty($this->getStoreMetadata($requestHttps)); } - protected function storeSimpleEntry($path = null, $headers = array()) + protected function storeSimpleEntry($path = null, $headers = []) { if (null === $path) { $path = '/test'; } - $this->request = Request::create($path, 'get', array(), array(), array(), $headers); - $this->response = new Response('test', 200, array('Cache-Control' => 'max-age=420')); + $this->request = Request::create($path, 'get', [], [], [], $headers); + $this->response = new Response('test', 200, ['Cache-Control' => 'max-age=420']); return $this->store->write($this->request, $this->response); } diff --git a/vendor/symfony/http-kernel/Tests/HttpCache/SubRequestHandlerTest.php b/vendor/symfony/http-kernel/Tests/HttpCache/SubRequestHandlerTest.php new file mode 100644 index 0000000000000000000000000000000000000000..61e6beded5803f39f9833685088a893f41c93c5a --- /dev/null +++ b/vendor/symfony/http-kernel/Tests/HttpCache/SubRequestHandlerTest.php @@ -0,0 +1,153 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\HttpKernel\Tests\HttpCache; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpKernel\HttpCache\SubRequestHandler; +use Symfony\Component\HttpKernel\HttpKernelInterface; + +class SubRequestHandlerTest extends TestCase +{ + private static $globalState; + + protected function setUp(): void + { + self::$globalState = $this->getGlobalState(); + } + + protected function tearDown(): void + { + Request::setTrustedProxies(self::$globalState[0], self::$globalState[1]); + } + + public function testTrustedHeadersAreKept() + { + Request::setTrustedProxies(['10.0.0.1'], -1); + $globalState = $this->getGlobalState(); + + $request = Request::create('/'); + $request->server->set('REMOTE_ADDR', '10.0.0.1'); + $request->headers->set('X-Forwarded-For', '10.0.0.2'); + $request->headers->set('X-Forwarded-Host', 'Good'); + $request->headers->set('X-Forwarded-Port', '1234'); + $request->headers->set('X-Forwarded-Proto', 'https'); + + $kernel = new TestSubRequestHandlerKernel(function ($request, $type, $catch) { + $this->assertSame('127.0.0.1', $request->server->get('REMOTE_ADDR')); + $this->assertSame('10.0.0.2', $request->getClientIp()); + $this->assertSame('Good', $request->headers->get('X-Forwarded-Host')); + $this->assertSame('1234', $request->headers->get('X-Forwarded-Port')); + $this->assertSame('https', $request->headers->get('X-Forwarded-Proto')); + }); + + SubRequestHandler::handle($kernel, $request, HttpKernelInterface::MASTER_REQUEST, true); + + $this->assertSame($globalState, $this->getGlobalState()); + } + + public function testUntrustedHeadersAreRemoved() + { + $request = Request::create('/'); + $request->server->set('REMOTE_ADDR', '10.0.0.1'); + $request->headers->set('X-Forwarded-For', '10.0.0.2'); + $request->headers->set('X-Forwarded-Host', 'Evil'); + $request->headers->set('X-Forwarded-Port', '1234'); + $request->headers->set('X-Forwarded-Proto', 'http'); + $request->headers->set('Forwarded', 'Evil2'); + + $kernel = new TestSubRequestHandlerKernel(function ($request, $type, $catch) { + $this->assertSame('127.0.0.1', $request->server->get('REMOTE_ADDR')); + $this->assertSame('10.0.0.1', $request->getClientIp()); + $this->assertFalse($request->headers->has('X-Forwarded-Host')); + $this->assertFalse($request->headers->has('X-Forwarded-Port')); + $this->assertFalse($request->headers->has('X-Forwarded-Proto')); + $this->assertSame('for="10.0.0.1";host="localhost";proto=http', $request->headers->get('Forwarded')); + }); + + SubRequestHandler::handle($kernel, $request, HttpKernelInterface::MASTER_REQUEST, true); + + $this->assertSame(self::$globalState, $this->getGlobalState()); + } + + public function testTrustedForwardedHeader() + { + Request::setTrustedProxies(['10.0.0.1'], -1); + $globalState = $this->getGlobalState(); + + $request = Request::create('/'); + $request->server->set('REMOTE_ADDR', '10.0.0.1'); + $request->headers->set('Forwarded', 'for="10.0.0.2";host="foo.bar:1234";proto=https'); + + $kernel = new TestSubRequestHandlerKernel(function ($request, $type, $catch) { + $this->assertSame('127.0.0.1', $request->server->get('REMOTE_ADDR')); + $this->assertSame('10.0.0.2', $request->getClientIp()); + $this->assertSame('foo.bar:1234', $request->getHttpHost()); + $this->assertSame('https', $request->getScheme()); + $this->assertSame(1234, $request->getPort()); + }); + + SubRequestHandler::handle($kernel, $request, HttpKernelInterface::MASTER_REQUEST, true); + + $this->assertSame($globalState, $this->getGlobalState()); + } + + public function testTrustedXForwardedForHeader() + { + Request::setTrustedProxies(['10.0.0.1'], -1); + $globalState = $this->getGlobalState(); + + $request = Request::create('/'); + $request->server->set('REMOTE_ADDR', '10.0.0.1'); + $request->headers->set('X-Forwarded-For', '10.0.0.2'); + $request->headers->set('X-Forwarded-Host', 'foo.bar'); + $request->headers->set('X-Forwarded-Proto', 'https'); + + $kernel = new TestSubRequestHandlerKernel(function ($request, $type, $catch) { + $this->assertSame('127.0.0.1', $request->server->get('REMOTE_ADDR')); + $this->assertSame('10.0.0.2', $request->getClientIp()); + $this->assertSame('foo.bar', $request->getHttpHost()); + $this->assertSame('https', $request->getScheme()); + }); + + SubRequestHandler::handle($kernel, $request, HttpKernelInterface::MASTER_REQUEST, true); + + $this->assertSame($globalState, $this->getGlobalState()); + } + + private function getGlobalState() + { + return [ + Request::getTrustedProxies(), + Request::getTrustedHeaderSet(), + ]; + } +} + +class TestSubRequestHandlerKernel implements HttpKernelInterface +{ + private $assertCallback; + + public function __construct(\Closure $assertCallback) + { + $this->assertCallback = $assertCallback; + } + + public function handle(Request $request, $type = self::MASTER_REQUEST, $catch = true) + { + $assertCallback = $this->assertCallback; + $assertCallback($request, $type, $catch); + + return new Response(); + } +} diff --git a/vendor/symfony/http-kernel/Tests/HttpCache/TestHttpKernel.php b/vendor/symfony/http-kernel/Tests/HttpCache/TestHttpKernel.php index 946c7a31cb44b1de90b09fc9a7d539160d933b5f..304ff9d9e43e716cdcfe5865a16ef96b21b5c477 100644 --- a/vendor/symfony/http-kernel/Tests/HttpCache/TestHttpKernel.php +++ b/vendor/symfony/http-kernel/Tests/HttpCache/TestHttpKernel.php @@ -11,13 +11,13 @@ namespace Symfony\Component\HttpKernel\Tests\HttpCache; -use Symfony\Component\HttpKernel\Controller\ArgumentResolverInterface; -use Symfony\Component\HttpKernel\HttpKernel; -use Symfony\Component\HttpKernel\HttpKernelInterface; +use Symfony\Component\EventDispatcher\EventDispatcher; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpKernel\Controller\ArgumentResolverInterface; use Symfony\Component\HttpKernel\Controller\ControllerResolverInterface; -use Symfony\Component\EventDispatcher\EventDispatcher; +use Symfony\Component\HttpKernel\HttpKernel; +use Symfony\Component\HttpKernel\HttpKernelInterface; class TestHttpKernel extends HttpKernel implements ControllerResolverInterface, ArgumentResolverInterface { @@ -39,15 +39,25 @@ class TestHttpKernel extends HttpKernel implements ControllerResolverInterface, parent::__construct(new EventDispatcher(), $this, null, $this); } - public function getBackendRequest() + public function assert(\Closure $callback) { - return $this->backendRequest; + $trustedConfig = [Request::getTrustedProxies(), Request::getTrustedHeaderSet()]; + + list($trustedProxies, $trustedHeaderSet, $backendRequest) = $this->backendRequest; + Request::setTrustedProxies($trustedProxies, $trustedHeaderSet); + + try { + $callback($backendRequest); + } finally { + list($trustedProxies, $trustedHeaderSet) = $trustedConfig; + Request::setTrustedProxies($trustedProxies, $trustedHeaderSet); + } } public function handle(Request $request, $type = HttpKernelInterface::MASTER_REQUEST, $catch = false) { $this->catch = $catch; - $this->backendRequest = $request; + $this->backendRequest = [Request::getTrustedProxies(), Request::getTrustedHeaderSet(), $request]; return parent::handle($request, $type, $catch); } @@ -59,12 +69,12 @@ class TestHttpKernel extends HttpKernel implements ControllerResolverInterface, public function getController(Request $request) { - return array($this, 'callController'); + return [$this, 'callController']; } public function getArguments(Request $request, $controller) { - return array($request); + return [$request]; } public function callController(Request $request) diff --git a/vendor/symfony/http-kernel/Tests/HttpCache/TestMultipleHttpKernel.php b/vendor/symfony/http-kernel/Tests/HttpCache/TestMultipleHttpKernel.php index 926d8daf531155ab678788d83bf277d283e27a1a..010bee86895a76623d0c08c701402e73409bddd8 100644 --- a/vendor/symfony/http-kernel/Tests/HttpCache/TestMultipleHttpKernel.php +++ b/vendor/symfony/http-kernel/Tests/HttpCache/TestMultipleHttpKernel.php @@ -11,19 +11,19 @@ namespace Symfony\Component\HttpKernel\Tests\HttpCache; -use Symfony\Component\HttpKernel\Controller\ArgumentResolverInterface; -use Symfony\Component\HttpKernel\HttpKernel; -use Symfony\Component\HttpKernel\HttpKernelInterface; +use Symfony\Component\EventDispatcher\EventDispatcher; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpKernel\Controller\ArgumentResolverInterface; use Symfony\Component\HttpKernel\Controller\ControllerResolverInterface; -use Symfony\Component\EventDispatcher\EventDispatcher; +use Symfony\Component\HttpKernel\HttpKernel; +use Symfony\Component\HttpKernel\HttpKernelInterface; class TestMultipleHttpKernel extends HttpKernel implements ControllerResolverInterface, ArgumentResolverInterface { - protected $bodies = array(); - protected $statuses = array(); - protected $headers = array(); + protected $bodies = []; + protected $statuses = []; + protected $headers = []; protected $called = false; protected $backendRequest; @@ -52,12 +52,12 @@ class TestMultipleHttpKernel extends HttpKernel implements ControllerResolverInt public function getController(Request $request) { - return array($this, 'callController'); + return [$this, 'callController']; } public function getArguments(Request $request, $controller) { - return array($request); + return [$request]; } public function callController(Request $request) diff --git a/vendor/symfony/http-kernel/Tests/ClientTest.php b/vendor/symfony/http-kernel/Tests/HttpKernelBrowserTest.php similarity index 62% rename from vendor/symfony/http-kernel/Tests/ClientTest.php rename to vendor/symfony/http-kernel/Tests/HttpKernelBrowserTest.php index 1ac72c73595c2f791efde10e91b991f87400c520..fdcfc266675183488ad90410d123ad5fae85cafa 100644 --- a/vendor/symfony/http-kernel/Tests/ClientTest.php +++ b/vendor/symfony/http-kernel/Tests/HttpKernelBrowserTest.php @@ -12,21 +12,21 @@ namespace Symfony\Component\HttpKernel\Tests; use PHPUnit\Framework\TestCase; -use Symfony\Component\HttpKernel\Client; -use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\HttpFoundation\StreamedResponse; use Symfony\Component\HttpFoundation\Cookie; use Symfony\Component\HttpFoundation\File\UploadedFile; +use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpFoundation\StreamedResponse; +use Symfony\Component\HttpKernel\HttpKernelBrowser; use Symfony\Component\HttpKernel\Tests\Fixtures\TestClient; /** * @group time-sensitive */ -class ClientTest extends TestCase +class HttpKernelBrowserTest extends TestCase { public function testDoRequest() { - $client = new Client(new TestHttpKernel()); + $client = new HttpKernelBrowser(new TestHttpKernel()); $client->request('GET', '/'); $this->assertEquals('Request: /', $client->getResponse()->getContent(), '->doRequest() uses the request handler to make the request'); @@ -39,8 +39,8 @@ class ClientTest extends TestCase $this->assertEquals('Request: /', $client->getResponse()->getContent(), '->doRequest() uses the request handler to make the request'); $this->assertEquals('www.example.com', $client->getRequest()->getHost(), '->doRequest() uses the request handler to make the request'); - $client->request('GET', 'http://www.example.com/?parameter=http://google.com'); - $this->assertEquals('http://www.example.com/?parameter='.urlencode('http://google.com'), $client->getRequest()->getUri(), '->doRequest() uses the request handler to make the request'); + $client->request('GET', 'http://www.example.com/?parameter=http://example.com'); + $this->assertEquals('http://www.example.com/?parameter='.urlencode('http://example.com'), $client->getRequest()->getUri(), '->doRequest() uses the request handler to make the request'); } public function testGetScript() @@ -54,33 +54,28 @@ class ClientTest extends TestCase public function testFilterResponseConvertsCookies() { - $client = new Client(new TestHttpKernel()); + $client = new HttpKernelBrowser(new TestHttpKernel()); $r = new \ReflectionObject($client); $m = $r->getMethod('filterResponse'); $m->setAccessible(true); - $expected = array( - 'foo=bar; expires=Sun, 15-Feb-2009 20:00:00 GMT; max-age='.(strtotime('Sun, 15-Feb-2009 20:00:00 GMT') - time()).'; path=/foo; domain=http://example.com; secure; httponly', - 'foo1=bar1; expires=Sun, 15-Feb-2009 20:00:00 GMT; max-age='.(strtotime('Sun, 15-Feb-2009 20:00:00 GMT') - time()).'; path=/foo; domain=http://example.com; secure; httponly', - ); - $response = new Response(); - $response->headers->setCookie(new Cookie('foo', 'bar', \DateTime::createFromFormat('j-M-Y H:i:s T', '15-Feb-2009 20:00:00 GMT')->format('U'), '/foo', 'http://example.com', true, true)); + $response->headers->setCookie($cookie1 = new Cookie('foo', 'bar', \DateTime::createFromFormat('j-M-Y H:i:s T', '15-Feb-2009 20:00:00 GMT')->format('U'), '/foo', 'http://example.com', true, true, false, null)); $domResponse = $m->invoke($client, $response); - $this->assertEquals($expected[0], $domResponse->getHeader('Set-Cookie')); + $this->assertSame((string) $cookie1, $domResponse->getHeader('Set-Cookie')); $response = new Response(); - $response->headers->setCookie(new Cookie('foo', 'bar', \DateTime::createFromFormat('j-M-Y H:i:s T', '15-Feb-2009 20:00:00 GMT')->format('U'), '/foo', 'http://example.com', true, true)); - $response->headers->setCookie(new Cookie('foo1', 'bar1', \DateTime::createFromFormat('j-M-Y H:i:s T', '15-Feb-2009 20:00:00 GMT')->format('U'), '/foo', 'http://example.com', true, true)); + $response->headers->setCookie($cookie1 = new Cookie('foo', 'bar', \DateTime::createFromFormat('j-M-Y H:i:s T', '15-Feb-2009 20:00:00 GMT')->format('U'), '/foo', 'http://example.com', true, true, false, null)); + $response->headers->setCookie($cookie2 = new Cookie('foo1', 'bar1', \DateTime::createFromFormat('j-M-Y H:i:s T', '15-Feb-2009 20:00:00 GMT')->format('U'), '/foo', 'http://example.com', true, true, false, null)); $domResponse = $m->invoke($client, $response); - $this->assertEquals($expected[0], $domResponse->getHeader('Set-Cookie')); - $this->assertEquals($expected, $domResponse->getHeader('Set-Cookie', false)); + $this->assertSame((string) $cookie1, $domResponse->getHeader('Set-Cookie')); + $this->assertSame([(string) $cookie1, (string) $cookie2], $domResponse->getHeader('Set-Cookie', false)); } public function testFilterResponseSupportsStreamedResponses() { - $client = new Client(new TestHttpKernel()); + $client = new HttpKernelBrowser(new TestHttpKernel()); $r = new \ReflectionObject($client); $m = $r->getMethod('filterResponse'); @@ -97,20 +92,21 @@ class ClientTest extends TestCase public function testUploadedFile() { $source = tempnam(sys_get_temp_dir(), 'source'); + file_put_contents($source, '1'); $target = sys_get_temp_dir().'/sf.moved.file'; @unlink($target); $kernel = new TestHttpKernel(); - $client = new Client($kernel); + $client = new HttpKernelBrowser($kernel); - $files = array( - array('tmp_name' => $source, 'name' => 'original', 'type' => 'mime/original', 'size' => 123, 'error' => UPLOAD_ERR_OK), - new UploadedFile($source, 'original', 'mime/original', 123, UPLOAD_ERR_OK, true), - ); + $files = [ + ['tmp_name' => $source, 'name' => 'original', 'type' => 'mime/original', 'size' => null, 'error' => UPLOAD_ERR_OK], + new UploadedFile($source, 'original', 'mime/original', UPLOAD_ERR_OK, true), + ]; $file = null; foreach ($files as $file) { - $client->request('POST', '/', array(), array('foo' => $file)); + $client->request('POST', '/', [], ['foo' => $file]); $files = $client->getRequest()->files->all(); @@ -120,11 +116,10 @@ class ClientTest extends TestCase $this->assertEquals('original', $file->getClientOriginalName()); $this->assertEquals('mime/original', $file->getClientMimeType()); - $this->assertEquals('123', $file->getClientSize()); - $this->assertTrue($file->isValid()); + $this->assertEquals(1, $file->getSize()); } - $file->move(dirname($target), basename($target)); + $file->move(\dirname($target), basename($target)); $this->assertFileExists($target); unlink($target); @@ -133,11 +128,11 @@ class ClientTest extends TestCase public function testUploadedFileWhenNoFileSelected() { $kernel = new TestHttpKernel(); - $client = new Client($kernel); + $client = new HttpKernelBrowser($kernel); - $file = array('tmp_name' => '', 'name' => '', 'type' => '', 'size' => 0, 'error' => UPLOAD_ERR_NO_FILE); + $file = ['tmp_name' => '', 'name' => '', 'type' => '', 'size' => 0, 'error' => UPLOAD_ERR_NO_FILE]; - $client->request('POST', '/', array(), array('foo' => $file)); + $client->request('POST', '/', [], ['foo' => $file]); $files = $client->getRequest()->files->all(); @@ -150,21 +145,25 @@ class ClientTest extends TestCase $source = tempnam(sys_get_temp_dir(), 'source'); $kernel = new TestHttpKernel(); - $client = new Client($kernel); + $client = new HttpKernelBrowser($kernel); $file = $this ->getMockBuilder('Symfony\Component\HttpFoundation\File\UploadedFile') - ->setConstructorArgs(array($source, 'original', 'mime/original', 123, UPLOAD_ERR_OK, true)) - ->setMethods(array('getSize')) + ->setConstructorArgs([$source, 'original', 'mime/original', UPLOAD_ERR_OK, true]) + ->setMethods(['getSize', 'getClientSize']) ->getMock() ; - - $file->expects($this->once()) + /* should be modified when the getClientSize will be removed */ + $file->expects($this->any()) ->method('getSize') - ->will($this->returnValue(INF)) + ->willReturn(INF) + ; + $file->expects($this->any()) + ->method('getClientSize') + ->willReturn(PHP_INT_MAX) ; - $client->request('POST', '/', array(), array($file)); + $client->request('POST', '/', [], [$file]); $files = $client->getRequest()->files->all(); @@ -176,7 +175,7 @@ class ClientTest extends TestCase $this->assertEquals(UPLOAD_ERR_INI_SIZE, $file->getError()); $this->assertEquals('mime/original', $file->getClientMimeType()); $this->assertEquals('original', $file->getClientOriginalName()); - $this->assertEquals(0, $file->getClientSize()); + $this->assertEquals(0, $file->getSize()); unlink($source); } diff --git a/vendor/symfony/http-kernel/Tests/HttpKernelTest.php b/vendor/symfony/http-kernel/Tests/HttpKernelTest.php index 7aed26aa59c9c9e29f51c40169062fa9db55398e..9a6170c086d35b25eac7189b486d488e366bc4c0 100644 --- a/vendor/symfony/http-kernel/Tests/HttpKernelTest.php +++ b/vendor/symfony/http-kernel/Tests/HttpKernelTest.php @@ -12,39 +12,34 @@ namespace Symfony\Component\HttpKernel\Tests; use PHPUnit\Framework\TestCase; +use Symfony\Component\EventDispatcher\EventDispatcher; use Symfony\Component\EventDispatcher\EventDispatcherInterface; +use Symfony\Component\HttpFoundation\RedirectResponse; +use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\RequestStack; +use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\Controller\ArgumentResolverInterface; use Symfony\Component\HttpKernel\Controller\ControllerResolverInterface; -use Symfony\Component\HttpKernel\Event\FilterControllerArgumentsEvent; -use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent; +use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException; +use Symfony\Component\HttpKernel\Exception\ControllerDoesNotReturnResponseException; +use Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException; use Symfony\Component\HttpKernel\HttpKernel; use Symfony\Component\HttpKernel\HttpKernelInterface; use Symfony\Component\HttpKernel\KernelEvents; -use Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException; -use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException; -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\HttpFoundation\RedirectResponse; -use Symfony\Component\EventDispatcher\EventDispatcher; class HttpKernelTest extends TestCase { - /** - * @expectedException \RuntimeException - */ public function testHandleWhenControllerThrowsAnExceptionAndCatchIsTrue() { + $this->expectException('RuntimeException'); $kernel = $this->getHttpKernel(new EventDispatcher(), function () { throw new \RuntimeException(); }); $kernel->handle(new Request(), HttpKernelInterface::MASTER_REQUEST, true); } - /** - * @expectedException \RuntimeException - */ public function testHandleWhenControllerThrowsAnExceptionAndCatchIsFalseAndNoListenerIsRegistered() { + $this->expectException('RuntimeException'); $kernel = $this->getHttpKernel(new EventDispatcher(), function () { throw new \RuntimeException(); }); $kernel->handle(new Request(), HttpKernelInterface::MASTER_REQUEST, false); @@ -104,39 +99,21 @@ class HttpKernelTest extends TestCase $event->setResponse(new Response($event->getException()->getMessage())); }); - $kernel = $this->getHttpKernel($dispatcher, function () { throw new MethodNotAllowedHttpException(array('POST')); }); + $kernel = $this->getHttpKernel($dispatcher, function () { throw new MethodNotAllowedHttpException(['POST']); }); $response = $kernel->handle(new Request()); $this->assertEquals('405', $response->getStatusCode()); $this->assertEquals('POST', $response->headers->get('Allow')); } - /** - * @group legacy - * @dataProvider getStatusCodes - */ - public function testLegacyHandleWhenAnExceptionIsHandledWithASpecificStatusCode($responseStatusCode, $expectedStatusCode) - { - $dispatcher = new EventDispatcher(); - $dispatcher->addListener(KernelEvents::EXCEPTION, function ($event) use ($responseStatusCode, $expectedStatusCode) { - $event->setResponse(new Response('', $responseStatusCode, array('X-Status-Code' => $expectedStatusCode))); - }); - - $kernel = $this->getHttpKernel($dispatcher, function () { throw new \RuntimeException(); }); - $response = $kernel->handle(new Request()); - - $this->assertEquals($expectedStatusCode, $response->getStatusCode()); - $this->assertFalse($response->headers->has('X-Status-Code')); - } - public function getStatusCodes() { - return array( - array(200, 404), - array(404, 200), - array(301, 200), - array(500, 200), - ); + return [ + [200, 404], + [404, 200], + [301, 200], + [500, 200], + ]; } /** @@ -145,7 +122,7 @@ class HttpKernelTest extends TestCase public function testHandleWhenAnExceptionIsHandledWithASpecificStatusCode($expectedStatusCode) { $dispatcher = new EventDispatcher(); - $dispatcher->addListener(KernelEvents::EXCEPTION, function (GetResponseForExceptionEvent $event) use ($expectedStatusCode) { + $dispatcher->addListener(KernelEvents::EXCEPTION, function ($event) use ($expectedStatusCode) { $event->allowCustomResponseCode(); $event->setResponse(new Response('', $expectedStatusCode)); }); @@ -158,11 +135,11 @@ class HttpKernelTest extends TestCase public function getSpecificStatusCodes() { - return array( - array(200), - array(302), - array(403), - ); + return [ + [200], + [302], + [403], + ]; } public function testHandleWhenAListenerReturnsAResponse() @@ -177,11 +154,9 @@ class HttpKernelTest extends TestCase $this->assertEquals('hello', $kernel->handle(new Request())->getContent()); } - /** - * @expectedException \Symfony\Component\HttpKernel\Exception\NotFoundHttpException - */ public function testHandleWhenNoControllerIsFound() { + $this->expectException('Symfony\Component\HttpKernel\Exception\NotFoundHttpException'); $dispatcher = new EventDispatcher(); $kernel = $this->getHttpKernel($dispatcher, false); @@ -200,7 +175,7 @@ class HttpKernelTest extends TestCase public function testHandleWhenTheControllerIsAnObjectWithInvoke() { $dispatcher = new EventDispatcher(); - $kernel = $this->getHttpKernel($dispatcher, new Controller()); + $kernel = $this->getHttpKernel($dispatcher, new TestController()); $this->assertResponseEquals(new Response('foo'), $kernel->handle(new Request())); } @@ -216,7 +191,7 @@ class HttpKernelTest extends TestCase public function testHandleWhenTheControllerIsAnArray() { $dispatcher = new EventDispatcher(); - $kernel = $this->getHttpKernel($dispatcher, array(new Controller(), 'controller')); + $kernel = $this->getHttpKernel($dispatcher, [new TestController(), 'controller']); $this->assertResponseEquals(new Response('foo'), $kernel->handle(new Request())); } @@ -224,20 +199,27 @@ class HttpKernelTest extends TestCase public function testHandleWhenTheControllerIsAStaticArray() { $dispatcher = new EventDispatcher(); - $kernel = $this->getHttpKernel($dispatcher, array('Symfony\Component\HttpKernel\Tests\Controller', 'staticcontroller')); + $kernel = $this->getHttpKernel($dispatcher, ['Symfony\Component\HttpKernel\Tests\TestController', 'staticcontroller']); $this->assertResponseEquals(new Response('foo'), $kernel->handle(new Request())); } - /** - * @expectedException \LogicException - */ public function testHandleWhenTheControllerDoesNotReturnAResponse() { $dispatcher = new EventDispatcher(); - $kernel = $this->getHttpKernel($dispatcher, function () { return 'foo'; }); + $kernel = $this->getHttpKernel($dispatcher, function () {}); - $kernel->handle(new Request()); + try { + $kernel->handle(new Request()); + + $this->fail('The kernel should throw an exception.'); + } catch (ControllerDoesNotReturnResponseException $e) { + $first = $e->getTrace()[0]; + + // `file` index the array starting at 0, and __FILE__ starts at 1 + $line = file($first['file'])[$first['line'] - 2]; + $this->assertStringContainsString('// call controller', $line); + } } public function testHandleWhenTheControllerDoesNotReturnAResponseButAViewIsRegistered() @@ -266,8 +248,8 @@ class HttpKernelTest extends TestCase public function testHandleAllowChangingControllerArguments() { $dispatcher = new EventDispatcher(); - $dispatcher->addListener(KernelEvents::CONTROLLER_ARGUMENTS, function (FilterControllerArgumentsEvent $event) { - $event->setArguments(array('foo')); + $dispatcher->addListener(KernelEvents::CONTROLLER_ARGUMENTS, function ($event) { + $event->setArguments(['foo']); }); $kernel = $this->getHttpKernel($dispatcher, function ($content) { return new Response($content); }); @@ -278,12 +260,12 @@ class HttpKernelTest extends TestCase public function testHandleAllowChangingControllerAndArguments() { $dispatcher = new EventDispatcher(); - $dispatcher->addListener(KernelEvents::CONTROLLER_ARGUMENTS, function (FilterControllerArgumentsEvent $event) { + $dispatcher->addListener(KernelEvents::CONTROLLER_ARGUMENTS, function ($event) { $oldController = $event->getController(); $oldArguments = $event->getArguments(); $newController = function ($id) use ($oldController, $oldArguments) { - $response = call_user_func_array($oldController, $oldArguments); + $response = $oldController(...$oldArguments); $response->headers->set('X-Id', $id); @@ -291,12 +273,12 @@ class HttpKernelTest extends TestCase }; $event->setController($newController); - $event->setArguments(array('bar')); + $event->setArguments(['bar']); }); - $kernel = $this->getHttpKernel($dispatcher, function ($content) { return new Response($content); }, null, array('foo')); + $kernel = $this->getHttpKernel($dispatcher, function ($content) { return new Response($content); }, null, ['foo']); - $this->assertResponseEquals(new Response('foo', 200, array('X-Id' => 'bar')), $kernel->handle(new Request())); + $this->assertResponseEquals(new Response('foo', 200, ['X-Id' => 'bar']), $kernel->handle(new Request())); } public function testTerminate() @@ -321,7 +303,7 @@ class HttpKernelTest extends TestCase { $request = new Request(); - $stack = $this->getMockBuilder('Symfony\Component\HttpFoundation\RequestStack')->setMethods(array('push', 'pop'))->getMock(); + $stack = $this->getMockBuilder('Symfony\Component\HttpFoundation\RequestStack')->setMethods(['push', 'pop'])->getMock(); $stack->expects($this->at(0))->method('push')->with($this->equalTo($request)); $stack->expects($this->at(1))->method('pop'); @@ -331,13 +313,11 @@ class HttpKernelTest extends TestCase $kernel->handle($request, HttpKernelInterface::MASTER_REQUEST); } - /** - * @expectedException \Symfony\Component\HttpKernel\Exception\BadRequestHttpException - */ public function testInconsistentClientIpsOnMasterRequests() { + $this->expectException('Symfony\Component\HttpKernel\Exception\BadRequestHttpException'); $request = new Request(); - $request->setTrustedProxies(array('1.1.1.1'), Request::HEADER_X_FORWARDED_FOR | Request::HEADER_FORWARDED); + $request->setTrustedProxies(['1.1.1.1'], Request::HEADER_X_FORWARDED_FOR | Request::HEADER_FORWARDED); $request->server->set('REMOTE_ADDR', '1.1.1.1'); $request->headers->set('FORWARDED', 'for=2.2.2.2'); $request->headers->set('X_FORWARDED_FOR', '3.3.3.3'); @@ -349,9 +329,11 @@ class HttpKernelTest extends TestCase $kernel = $this->getHttpKernel($dispatcher); $kernel->handle($request, $kernel::MASTER_REQUEST, false); + + Request::setTrustedProxies([], -1); } - private function getHttpKernel(EventDispatcherInterface $eventDispatcher, $controller = null, RequestStack $requestStack = null, array $arguments = array()) + private function getHttpKernel(EventDispatcherInterface $eventDispatcher, $controller = null, RequestStack $requestStack = null, array $arguments = []) { if (null === $controller) { $controller = function () { return new Response('Hello'); }; @@ -361,13 +343,13 @@ class HttpKernelTest extends TestCase $controllerResolver ->expects($this->any()) ->method('getController') - ->will($this->returnValue($controller)); + ->willReturn($controller); $argumentResolver = $this->getMockBuilder(ArgumentResolverInterface::class)->getMock(); $argumentResolver ->expects($this->any()) ->method('getArguments') - ->will($this->returnValue($arguments)); + ->willReturn($arguments); return new HttpKernel($eventDispatcher, $controllerResolver, $requestStack, $argumentResolver); } @@ -379,7 +361,7 @@ class HttpKernelTest extends TestCase } } -class Controller +class TestController { public function __invoke() { diff --git a/vendor/symfony/http-kernel/Tests/KernelTest.php b/vendor/symfony/http-kernel/Tests/KernelTest.php index 755e1db2b7ddf3ddf1f7aa3ba66f5c20289272eb..26bf7d8aff265ac92faa9e420f820e9ba731a15c 100644 --- a/vendor/symfony/http-kernel/Tests/KernelTest.php +++ b/vendor/symfony/http-kernel/Tests/KernelTest.php @@ -16,25 +16,24 @@ use Symfony\Component\Config\Loader\LoaderInterface; use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\Filesystem\Filesystem; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\Bundle\BundleInterface; -use Symfony\Component\HttpKernel\Config\EnvParametersResource; use Symfony\Component\HttpKernel\DependencyInjection\ResettableServicePass; use Symfony\Component\HttpKernel\DependencyInjection\ServicesResetter; -use Symfony\Component\HttpKernel\Kernel; use Symfony\Component\HttpKernel\HttpKernelInterface; -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\Response; -use Symfony\Component\HttpKernel\Tests\Fixtures\KernelForTest; +use Symfony\Component\HttpKernel\Kernel; use Symfony\Component\HttpKernel\Tests\Fixtures\KernelForOverrideName; +use Symfony\Component\HttpKernel\Tests\Fixtures\KernelForTest; use Symfony\Component\HttpKernel\Tests\Fixtures\KernelWithoutBundles; use Symfony\Component\HttpKernel\Tests\Fixtures\ResettableService; class KernelTest extends TestCase { - public static function tearDownAfterClass() + public static function tearDownAfterClass(): void { $fs = new Filesystem(); - $fs->remove(__DIR__.'/Fixtures/cache'); + $fs->remove(__DIR__.'/Fixtures/var'); } public function testConstructor() @@ -65,18 +64,30 @@ class KernelTest extends TestCase $this->assertNull($clone->getContainer()); } + public function testClassNameValidityGetter() + { + $this->expectException('InvalidArgumentException'); + $this->expectExceptionMessage('The environment "test.env" contains invalid characters, it can only contain characters allowed in PHP class names.'); + // We check the classname that will be generated by using a $env that + // contains invalid characters. + $env = 'test.env'; + $kernel = new KernelForTest($env, false); + + $kernel->boot(); + } + public function testInitializeContainerClearsOldContainers() { $fs = new Filesystem(); - $legacyContainerDir = __DIR__.'/Fixtures/cache/custom/ContainerA123456'; + $legacyContainerDir = __DIR__.'/Fixtures/var/cache/custom/ContainerA123456'; $fs->mkdir($legacyContainerDir); touch($legacyContainerDir.'.legacy'); $kernel = new CustomProjectDirKernel(); $kernel->boot(); - $containerDir = __DIR__.'/Fixtures/cache/custom/'.substr(get_class($kernel->getContainer()), 0, 16); - $this->assertTrue(unlink(__DIR__.'/Fixtures/cache/custom/FixturesCustomDebugProjectContainer.php.meta')); + $containerDir = __DIR__.'/Fixtures/var/cache/custom/'.substr(\get_class($kernel->getContainer()), 0, 16); + $this->assertTrue(unlink(__DIR__.'/Fixtures/var/cache/custom/TestsSymfony_Component_HttpKernel_Tests_CustomProjectDirKernelCustomDebugContainer.php.meta')); $this->assertFileExists($containerDir); $this->assertFileNotExists($containerDir.'.legacy'); @@ -92,7 +103,7 @@ class KernelTest extends TestCase public function testBootInitializesBundlesAndContainer() { - $kernel = $this->getKernel(array('initializeBundles', 'initializeContainer')); + $kernel = $this->getKernel(['initializeBundles', 'initializeContainer']); $kernel->expects($this->once()) ->method('initializeBundles'); $kernel->expects($this->once()) @@ -107,10 +118,10 @@ class KernelTest extends TestCase $bundle->expects($this->once()) ->method('setContainer'); - $kernel = $this->getKernel(array('initializeBundles', 'initializeContainer', 'getBundles')); + $kernel = $this->getKernel(['initializeBundles', 'initializeContainer', 'getBundles']); $kernel->expects($this->once()) ->method('getBundles') - ->will($this->returnValue(array($bundle))); + ->willReturn([$bundle]); $kernel->boot(); } @@ -118,85 +129,24 @@ class KernelTest extends TestCase public function testBootSetsTheBootedFlagToTrue() { // use test kernel to access isBooted() - $kernel = $this->getKernelForTest(array('initializeBundles', 'initializeContainer')); + $kernel = $this->getKernel(['initializeBundles', 'initializeContainer']); $kernel->boot(); $this->assertTrue($kernel->isBooted()); } - /** - * @group legacy - */ - public function testClassCacheIsLoaded() - { - $kernel = $this->getKernel(array('initializeBundles', 'initializeContainer', 'doLoadClassCache')); - $kernel->loadClassCache('name', '.extension'); - $kernel->expects($this->once()) - ->method('doLoadClassCache') - ->with('name', '.extension'); - - $kernel->boot(); - } - public function testClassCacheIsNotLoadedByDefault() { - $kernel = $this->getKernel(array('initializeBundles', 'initializeContainer', 'doLoadClassCache')); + $kernel = $this->getKernel(['initializeBundles', 'initializeContainer', 'doLoadClassCache']); $kernel->expects($this->never()) ->method('doLoadClassCache'); $kernel->boot(); } - /** - * @group legacy - */ - public function testClassCacheIsNotLoadedWhenKernelIsNotBooted() - { - $kernel = $this->getKernel(array('initializeBundles', 'initializeContainer', 'doLoadClassCache')); - $kernel->loadClassCache(); - $kernel->expects($this->never()) - ->method('doLoadClassCache'); - } - - public function testEnvParametersResourceIsAdded() - { - $container = new ContainerBuilder(); - $kernel = $this->getMockBuilder('Symfony\Component\HttpKernel\Tests\Fixtures\KernelForTest') - ->disableOriginalConstructor() - ->setMethods(array('getContainerBuilder', 'prepareContainer', 'getCacheDir', 'getLogDir')) - ->getMock(); - $kernel->expects($this->any()) - ->method('getContainerBuilder') - ->will($this->returnValue($container)); - $kernel->expects($this->any()) - ->method('prepareContainer') - ->will($this->returnValue(null)); - $kernel->expects($this->any()) - ->method('getCacheDir') - ->will($this->returnValue(sys_get_temp_dir())); - $kernel->expects($this->any()) - ->method('getLogDir') - ->will($this->returnValue(sys_get_temp_dir())); - - $reflection = new \ReflectionClass(get_class($kernel)); - $method = $reflection->getMethod('buildContainer'); - $method->setAccessible(true); - $method->invoke($kernel); - - $found = false; - foreach ($container->getResources() as $resource) { - if ($resource instanceof EnvParametersResource) { - $found = true; - break; - } - } - - $this->assertTrue($found); - } - public function testBootKernelSeveralTimesOnlyInitializesBundlesOnce() { - $kernel = $this->getKernel(array('initializeBundles', 'initializeContainer')); + $kernel = $this->getKernel(['initializeBundles', 'initializeContainer']); $kernel->expects($this->once()) ->method('initializeBundles'); @@ -210,7 +160,7 @@ class KernelTest extends TestCase $bundle->expects($this->once()) ->method('shutdown'); - $kernel = $this->getKernel(array(), array($bundle)); + $kernel = $this->getKernel([], [$bundle]); $kernel->boot(); $kernel->shutdown(); @@ -223,10 +173,10 @@ class KernelTest extends TestCase ->method('setContainer') ->with(null); - $kernel = $this->getKernel(array('getBundles')); + $kernel = $this->getKernel(['getBundles']); $kernel->expects($this->any()) ->method('getBundles') - ->will($this->returnValue(array($bundle))); + ->willReturn([$bundle]); $kernel->boot(); $kernel->shutdown(); @@ -246,10 +196,10 @@ class KernelTest extends TestCase ->method('handle') ->with($request, $type, $catch); - $kernel = $this->getKernel(array('getHttpKernel')); + $kernel = $this->getKernel(['getHttpKernel']); $kernel->expects($this->once()) ->method('getHttpKernel') - ->will($this->returnValue($httpKernelMock)); + ->willReturn($httpKernelMock); $kernel->handle($request, $type, $catch); } @@ -264,10 +214,10 @@ class KernelTest extends TestCase ->disableOriginalConstructor() ->getMock(); - $kernel = $this->getKernel(array('getHttpKernel', 'boot')); + $kernel = $this->getKernel(['getHttpKernel', 'boot']); $kernel->expects($this->once()) ->method('getHttpKernel') - ->will($this->returnValue($httpKernelMock)); + ->willReturn($httpKernelMock); $kernel->expects($this->once()) ->method('boot'); @@ -349,7 +299,7 @@ EOF; // Heredocs are preserved, making the output mixing Unix and Windows line // endings, switching to "\n" everywhere on Windows to avoid failure. - if ('\\' === DIRECTORY_SEPARATOR) { + if ('\\' === \DIRECTORY_SEPARATOR) { $expected = str_replace("\r\n", "\n", $expected); $output = str_replace("\r\n", "\n", $output); } @@ -357,13 +307,19 @@ EOF; $this->assertEquals($expected, $output); } + /** + * @group legacy + */ public function testGetRootDir() { $kernel = new KernelForTest('test', true); - $this->assertEquals(__DIR__.DIRECTORY_SEPARATOR.'Fixtures', realpath($kernel->getRootDir())); + $this->assertEquals(__DIR__.\DIRECTORY_SEPARATOR.'Fixtures', realpath($kernel->getRootDir())); } + /** + * @group legacy + */ public function testGetName() { $kernel = new KernelForTest('test', true); @@ -371,6 +327,9 @@ EOF; $this->assertEquals('Fixtures', $kernel->getName()); } + /** + * @group legacy + */ public function testOverrideGetName() { $kernel = new KernelForOverrideName('test', true); @@ -383,45 +342,36 @@ EOF; $env = 'test_env'; $debug = true; $kernel = new KernelForTest($env, $debug); - - $expected = serialize(array($env, $debug)); - $this->assertEquals($expected, $kernel->serialize()); + $expected = "O:57:\"Symfony\Component\HttpKernel\Tests\Fixtures\KernelForTest\":2:{s:14:\"\0*\0environment\";s:8:\"test_env\";s:8:\"\0*\0debug\";b:1;}"; + $this->assertEquals($expected, serialize($kernel)); } - /** - * @expectedException \InvalidArgumentException - */ public function testLocateResourceThrowsExceptionWhenNameIsNotValid() { + $this->expectException('InvalidArgumentException'); $this->getKernel()->locateResource('Foo'); } - /** - * @expectedException \RuntimeException - */ public function testLocateResourceThrowsExceptionWhenNameIsUnsafe() { + $this->expectException('RuntimeException'); $this->getKernel()->locateResource('@FooBundle/../bar'); } - /** - * @expectedException \InvalidArgumentException - */ public function testLocateResourceThrowsExceptionWhenBundleDoesNotExist() { + $this->expectException('InvalidArgumentException'); $this->getKernel()->locateResource('@FooBundle/config/routing.xml'); } - /** - * @expectedException \InvalidArgumentException - */ public function testLocateResourceThrowsExceptionWhenResourceDoesNotExist() { - $kernel = $this->getKernel(array('getBundle')); + $this->expectException('InvalidArgumentException'); + $kernel = $this->getKernel(['getBundle']); $kernel ->expects($this->once()) ->method('getBundle') - ->will($this->returnValue(array($this->getBundle(__DIR__.'/Fixtures/Bundle1Bundle')))) + ->willReturn($this->getBundle(__DIR__.'/Fixtures/Bundle1Bundle')) ; $kernel->locateResource('@Bundle1Bundle/config/routing.xml'); @@ -429,84 +379,23 @@ EOF; public function testLocateResourceReturnsTheFirstThatMatches() { - $kernel = $this->getKernel(array('getBundle')); + $kernel = $this->getKernel(['getBundle']); $kernel ->expects($this->once()) ->method('getBundle') - ->will($this->returnValue(array($this->getBundle(__DIR__.'/Fixtures/Bundle1Bundle')))) + ->willReturn($this->getBundle(__DIR__.'/Fixtures/Bundle1Bundle')) ; $this->assertEquals(__DIR__.'/Fixtures/Bundle1Bundle/foo.txt', $kernel->locateResource('@Bundle1Bundle/foo.txt')); } - /** - * @group legacy - */ - public function testLocateResourceReturnsTheFirstThatMatchesWithParent() - { - $parent = $this->getBundle(__DIR__.'/Fixtures/Bundle1Bundle'); - $child = $this->getBundle(__DIR__.'/Fixtures/Bundle2Bundle'); - - $kernel = $this->getKernel(array('getBundle')); - $kernel - ->expects($this->exactly(2)) - ->method('getBundle') - ->will($this->returnValue(array($child, $parent))) - ; - - $this->assertEquals(__DIR__.'/Fixtures/Bundle2Bundle/foo.txt', $kernel->locateResource('@ParentAABundle/foo.txt')); - $this->assertEquals(__DIR__.'/Fixtures/Bundle1Bundle/bar.txt', $kernel->locateResource('@ParentAABundle/bar.txt')); - } - - /** - * @group legacy - */ - public function testLocateResourceReturnsAllMatches() - { - $parent = $this->getBundle(__DIR__.'/Fixtures/Bundle1Bundle'); - $child = $this->getBundle(__DIR__.'/Fixtures/Bundle2Bundle'); - - $kernel = $this->getKernel(array('getBundle')); - $kernel - ->expects($this->once()) - ->method('getBundle') - ->will($this->returnValue(array($child, $parent))) - ; - - $this->assertEquals(array( - __DIR__.'/Fixtures/Bundle2Bundle/foo.txt', - __DIR__.'/Fixtures/Bundle1Bundle/foo.txt', ), - $kernel->locateResource('@Bundle1Bundle/foo.txt', null, false)); - } - - /** - * @group legacy - */ - public function testLocateResourceReturnsAllMatchesBis() - { - $kernel = $this->getKernel(array('getBundle')); - $kernel - ->expects($this->once()) - ->method('getBundle') - ->will($this->returnValue(array( - $this->getBundle(__DIR__.'/Fixtures/Bundle1Bundle'), - $this->getBundle(__DIR__.'/Foobar'), - ))) - ; - - $this->assertEquals( - array(__DIR__.'/Fixtures/Bundle1Bundle/foo.txt'), - $kernel->locateResource('@Bundle1Bundle/foo.txt', null, false) - ); - } - public function testLocateResourceIgnoresDirOnNonResource() { - $kernel = $this->getKernel(array('getBundle')); + $kernel = $this->getKernel(['getBundle']); $kernel ->expects($this->once()) ->method('getBundle') - ->will($this->returnValue(array($this->getBundle(__DIR__.'/Fixtures/Bundle1Bundle')))) + ->willReturn($this->getBundle(__DIR__.'/Fixtures/Bundle1Bundle')) ; $this->assertEquals( @@ -517,11 +406,11 @@ EOF; public function testLocateResourceReturnsTheDirOneForResources() { - $kernel = $this->getKernel(array('getBundle')); + $kernel = $this->getKernel(['getBundle']); $kernel ->expects($this->once()) ->method('getBundle') - ->will($this->returnValue(array($this->getBundle(__DIR__.'/Fixtures/FooBundle', null, null, 'FooBundle')))) + ->willReturn($this->getBundle(__DIR__.'/Fixtures/FooBundle', null, null, 'FooBundle')) ; $this->assertEquals( @@ -530,73 +419,13 @@ EOF; ); } - /** - * @group legacy - */ - public function testLocateResourceReturnsTheDirOneForResourcesAndBundleOnes() - { - $kernel = $this->getKernel(array('getBundle')); - $kernel - ->expects($this->once()) - ->method('getBundle') - ->will($this->returnValue(array($this->getBundle(__DIR__.'/Fixtures/Bundle1Bundle', null, null, 'Bundle1Bundle')))) - ; - - $this->assertEquals(array( - __DIR__.'/Fixtures/Resources/Bundle1Bundle/foo.txt', - __DIR__.'/Fixtures/Bundle1Bundle/Resources/foo.txt', ), - $kernel->locateResource('@Bundle1Bundle/Resources/foo.txt', __DIR__.'/Fixtures/Resources', false) - ); - } - - /** - * @group legacy - */ - public function testLocateResourceOverrideBundleAndResourcesFolders() - { - $parent = $this->getBundle(__DIR__.'/Fixtures/BaseBundle', null, 'BaseBundle', 'BaseBundle'); - $child = $this->getBundle(__DIR__.'/Fixtures/ChildBundle', 'ParentBundle', 'ChildBundle', 'ChildBundle'); - - $kernel = $this->getKernel(array('getBundle')); - $kernel - ->expects($this->exactly(4)) - ->method('getBundle') - ->will($this->returnValue(array($child, $parent))) - ; - - $this->assertEquals(array( - __DIR__.'/Fixtures/Resources/ChildBundle/foo.txt', - __DIR__.'/Fixtures/ChildBundle/Resources/foo.txt', - __DIR__.'/Fixtures/BaseBundle/Resources/foo.txt', - ), - $kernel->locateResource('@BaseBundle/Resources/foo.txt', __DIR__.'/Fixtures/Resources', false) - ); - - $this->assertEquals( - __DIR__.'/Fixtures/Resources/ChildBundle/foo.txt', - $kernel->locateResource('@BaseBundle/Resources/foo.txt', __DIR__.'/Fixtures/Resources') - ); - - try { - $kernel->locateResource('@BaseBundle/Resources/hide.txt', __DIR__.'/Fixtures/Resources', false); - $this->fail('Hidden resources should raise an exception when returning an array of matching paths'); - } catch (\RuntimeException $e) { - } - - try { - $kernel->locateResource('@BaseBundle/Resources/hide.txt', __DIR__.'/Fixtures/Resources', true); - $this->fail('Hidden resources should raise an exception when returning the first matching path'); - } catch (\RuntimeException $e) { - } - } - public function testLocateResourceOnDirectories() { - $kernel = $this->getKernel(array('getBundle')); + $kernel = $this->getKernel(['getBundle']); $kernel ->expects($this->exactly(2)) ->method('getBundle') - ->will($this->returnValue(array($this->getBundle(__DIR__.'/Fixtures/FooBundle', null, null, 'FooBundle')))) + ->willReturn($this->getBundle(__DIR__.'/Fixtures/FooBundle', null, null, 'FooBundle')) ; $this->assertEquals( @@ -608,11 +437,11 @@ EOF; $kernel->locateResource('@FooBundle/Resources', __DIR__.'/Fixtures/Resources') ); - $kernel = $this->getKernel(array('getBundle')); + $kernel = $this->getKernel(['getBundle']); $kernel ->expects($this->exactly(2)) ->method('getBundle') - ->will($this->returnValue(array($this->getBundle(__DIR__.'/Fixtures/Bundle1Bundle', null, null, 'Bundle1Bundle')))) + ->willReturn($this->getBundle(__DIR__.'/Fixtures/Bundle1Bundle', null, null, 'Bundle1Bundle')) ; $this->assertEquals( @@ -625,132 +454,20 @@ EOF; ); } - /** - * @group legacy - */ - public function testInitializeBundles() - { - $parent = $this->getBundle(null, null, 'ParentABundle'); - $child = $this->getBundle(null, 'ParentABundle', 'ChildABundle'); - - // use test kernel so we can access getBundleMap() - $kernel = $this->getKernelForTest(array('registerBundles')); - $kernel - ->expects($this->once()) - ->method('registerBundles') - ->will($this->returnValue(array($parent, $child))) - ; - $kernel->boot(); - - $map = $kernel->getBundleMap(); - $this->assertEquals(array($child, $parent), $map['ParentABundle']); - } - - /** - * @group legacy - */ - public function testInitializeBundlesSupportInheritanceCascade() - { - $grandparent = $this->getBundle(null, null, 'GrandParentBBundle'); - $parent = $this->getBundle(null, 'GrandParentBBundle', 'ParentBBundle'); - $child = $this->getBundle(null, 'ParentBBundle', 'ChildBBundle'); - - // use test kernel so we can access getBundleMap() - $kernel = $this->getKernelForTest(array('registerBundles')); - $kernel - ->expects($this->once()) - ->method('registerBundles') - ->will($this->returnValue(array($grandparent, $parent, $child))) - ; - $kernel->boot(); - - $map = $kernel->getBundleMap(); - $this->assertEquals(array($child, $parent, $grandparent), $map['GrandParentBBundle']); - $this->assertEquals(array($child, $parent), $map['ParentBBundle']); - $this->assertEquals(array($child), $map['ChildBBundle']); - } - - /** - * @group legacy - * @expectedException \LogicException - * @expectedExceptionMessage Bundle "ChildCBundle" extends bundle "FooBar", which is not registered. - */ - public function testInitializeBundlesThrowsExceptionWhenAParentDoesNotExists() - { - $child = $this->getBundle(null, 'FooBar', 'ChildCBundle'); - $kernel = $this->getKernel(array(), array($child)); - $kernel->boot(); - } - - /** - * @group legacy - */ - public function testInitializeBundlesSupportsArbitraryBundleRegistrationOrder() - { - $grandparent = $this->getBundle(null, null, 'GrandParentCBundle'); - $parent = $this->getBundle(null, 'GrandParentCBundle', 'ParentCBundle'); - $child = $this->getBundle(null, 'ParentCBundle', 'ChildCBundle'); - - // use test kernel so we can access getBundleMap() - $kernel = $this->getKernelForTest(array('registerBundles')); - $kernel - ->expects($this->once()) - ->method('registerBundles') - ->will($this->returnValue(array($parent, $grandparent, $child))) - ; - $kernel->boot(); - - $map = $kernel->getBundleMap(); - $this->assertEquals(array($child, $parent, $grandparent), $map['GrandParentCBundle']); - $this->assertEquals(array($child, $parent), $map['ParentCBundle']); - $this->assertEquals(array($child), $map['ChildCBundle']); - } - - /** - * @group legacy - * @expectedException \LogicException - * @expectedExceptionMessage Bundle "ParentCBundle" is directly extended by two bundles "ChildC2Bundle" and "ChildC1Bundle". - */ - public function testInitializeBundlesThrowsExceptionWhenABundleIsDirectlyExtendedByTwoBundles() - { - $parent = $this->getBundle(null, null, 'ParentCBundle'); - $child1 = $this->getBundle(null, 'ParentCBundle', 'ChildC1Bundle'); - $child2 = $this->getBundle(null, 'ParentCBundle', 'ChildC2Bundle'); - - $kernel = $this->getKernel(array(), array($parent, $child1, $child2)); - $kernel->boot(); - } - - /** - * @group legacy - * @expectedException \LogicException - * @expectedExceptionMessage Trying to register two bundles with the same name "DuplicateName" - */ public function testInitializeBundleThrowsExceptionWhenRegisteringTwoBundlesWithTheSameName() { - $fooBundle = $this->getBundle(null, null, 'FooBundle', 'DuplicateName'); - $barBundle = $this->getBundle(null, null, 'BarBundle', 'DuplicateName'); + $this->expectException('LogicException'); + $this->expectExceptionMessage('Trying to register two bundles with the same name "DuplicateName"'); + $fooBundle = $this->getBundle(__DIR__.'/Fixtures/FooBundle', null, 'FooBundle', 'DuplicateName'); + $barBundle = $this->getBundle(__DIR__.'/Fixtures/BarBundle', null, 'BarBundle', 'DuplicateName'); - $kernel = $this->getKernel(array(), array($fooBundle, $barBundle)); - $kernel->boot(); - } - - /** - * @group legacy - * @expectedException \LogicException - * @expectedExceptionMessage Bundle "CircularRefBundle" can not extend itself. - */ - public function testInitializeBundleThrowsExceptionWhenABundleExtendsItself() - { - $circularRef = $this->getBundle(null, 'CircularRefBundle', 'CircularRefBundle'); - - $kernel = $this->getKernel(array(), array($circularRef)); + $kernel = $this->getKernel([], [$fooBundle, $barBundle]); $kernel->boot(); } public function testTerminateReturnsSilentlyIfKernelIsNotBooted() { - $kernel = $this->getKernel(array('getHttpKernel')); + $kernel = $this->getKernel(['getHttpKernel']); $kernel->expects($this->never()) ->method('getHttpKernel'); @@ -762,7 +479,7 @@ EOF; // does not implement TerminableInterface $httpKernel = new TestKernel(); - $kernel = $this->getKernel(array('getHttpKernel')); + $kernel = $this->getKernel(['getHttpKernel']); $kernel->expects($this->once()) ->method('getHttpKernel') ->willReturn($httpKernel); @@ -775,17 +492,17 @@ EOF; // implements TerminableInterface $httpKernelMock = $this->getMockBuilder('Symfony\Component\HttpKernel\HttpKernel') ->disableOriginalConstructor() - ->setMethods(array('terminate')) + ->setMethods(['terminate']) ->getMock(); $httpKernelMock ->expects($this->once()) ->method('terminate'); - $kernel = $this->getKernel(array('getHttpKernel')); + $kernel = $this->getKernel(['getHttpKernel']); $kernel->expects($this->exactly(2)) ->method('getHttpKernel') - ->will($this->returnValue($httpKernelMock)); + ->willReturn($httpKernelMock); $kernel->boot(); $kernel->terminate(Request::create('/'), new Response()); @@ -799,66 +516,39 @@ EOF; $this->assertTrue($kernel->getContainer()->getParameter('test_executed')); } - public function testKernelRootDirNameStartingWithANumber() - { - $dir = __DIR__.'/Fixtures/123'; - require_once $dir.'/Kernel123.php'; - $kernel = new \Symfony\Component\HttpKernel\Tests\Fixtures\_123\Kernel123('dev', true); - $this->assertEquals('_123', $kernel->getName()); - } - - /** - * @group legacy - * @expectedDeprecation The Symfony\Component\HttpKernel\Kernel::getEnvParameters() method is deprecated as of 3.3 and will be removed in 4.0. Use the %cenv()%c syntax to get the value of any environment variable from configuration files instead. - * @expectedDeprecation The support of special environment variables that start with SYMFONY__ (such as "SYMFONY__FOO__BAR") is deprecated as of 3.3 and will be removed in 4.0. Use the %cenv()%c syntax instead to get the value of environment variables in configuration files. - */ - public function testSymfonyEnvironmentVariables() - { - $_SERVER['SYMFONY__FOO__BAR'] = 'baz'; - - $kernel = $this->getKernel(); - $method = new \ReflectionMethod($kernel, 'getEnvParameters'); - $method->setAccessible(true); - - $envParameters = $method->invoke($kernel); - $this->assertSame('baz', $envParameters['foo.bar']); - - unset($_SERVER['SYMFONY__FOO__BAR']); - } - public function testProjectDirExtension() { $kernel = new CustomProjectDirKernel(); $kernel->boot(); - $this->assertSame('foo', $kernel->getProjectDir()); - $this->assertSame('foo', $kernel->getContainer()->getParameter('kernel.project_dir')); + $this->assertSame(__DIR__.'/Fixtures', $kernel->getProjectDir()); + $this->assertSame(__DIR__.\DIRECTORY_SEPARATOR.'Fixtures', $kernel->getContainer()->getParameter('kernel.project_dir')); } public function testKernelReset() { - (new Filesystem())->remove(__DIR__.'/Fixtures/cache'); + (new Filesystem())->remove(__DIR__.'/Fixtures/var/cache'); $kernel = new CustomProjectDirKernel(); $kernel->boot(); - $containerClass = get_class($kernel->getContainer()); + $containerClass = \get_class($kernel->getContainer()); $containerFile = (new \ReflectionClass($kernel->getContainer()))->getFileName(); - unlink(__DIR__.'/Fixtures/cache/custom/FixturesCustomDebugProjectContainer.php.meta'); + unlink(__DIR__.'/Fixtures/var/cache/custom/TestsSymfony_Component_HttpKernel_Tests_CustomProjectDirKernelCustomDebugContainer.php.meta'); $kernel = new CustomProjectDirKernel(); $kernel->boot(); - $this->assertSame($containerClass, get_class($kernel->getContainer())); + $this->assertInstanceOf($containerClass, $kernel->getContainer()); $this->assertFileExists($containerFile); - unlink(__DIR__.'/Fixtures/cache/custom/FixturesCustomDebugProjectContainer.php.meta'); + unlink(__DIR__.'/Fixtures/var/cache/custom/TestsSymfony_Component_HttpKernel_Tests_CustomProjectDirKernelCustomDebugContainer.php.meta'); $kernel = new CustomProjectDirKernel(function ($container) { $container->register('foo', 'stdClass')->setPublic(true); }); $kernel->boot(); - $this->assertTrue(get_class($kernel->getContainer()) !== $containerClass); + $this->assertNotInstanceOf($containerClass, $kernel->getContainer()); $this->assertFileExists($containerFile); - $this->assertFileExists(dirname($containerFile).'.legacy'); + $this->assertFileExists(\dirname($containerFile).'.legacy'); } public function testKernelPass() @@ -882,7 +572,7 @@ EOF; $container->addCompilerPass(new ResettableServicePass()); $container->register('one', ResettableService::class) ->setPublic(true) - ->addTag('kernel.reset', array('method' => 'reset')); + ->addTag('kernel.reset', ['method' => 'reset']); $container->register('services_resetter', ServicesResetter::class)->setPublic(true); }, $httpKernelMock, 'resetting'); @@ -901,6 +591,21 @@ EOF; $this->assertEquals(1, ResettableService::$counter); } + /** + * @group time-sensitive + */ + public function testKernelStartTimeIsResetWhileBootingAlreadyBootedKernel() + { + $kernel = $this->getKernel(['initializeBundles'], [], true); + $kernel->boot(); + $preReBoot = $kernel->getStartTime(); + + sleep(3600); //Intentionally large value to detect if ClockMock ever breaks + $kernel->reboot(null); + + $this->assertGreaterThan($preReBoot, $kernel->getStartTime()); + } + /** * Returns a mock for the BundleInterface. * @@ -910,7 +615,7 @@ EOF; { $bundle = $this ->getMockBuilder('Symfony\Component\HttpKernel\Bundle\BundleInterface') - ->setMethods(array('getPath', 'getParent', 'getName')) + ->setMethods(['getPath', 'getParent', 'getName']) ->disableOriginalConstructor() ; @@ -923,19 +628,19 @@ EOF; $bundle ->expects($this->any()) ->method('getName') - ->will($this->returnValue(null === $bundleName ? get_class($bundle) : $bundleName)) + ->willReturn(null === $bundleName ? \get_class($bundle) : $bundleName) ; $bundle ->expects($this->any()) ->method('getPath') - ->will($this->returnValue($dir)) + ->willReturn($dir) ; $bundle ->expects($this->any()) ->method('getParent') - ->will($this->returnValue($parent)) + ->willReturn($parent) ; return $bundle; @@ -949,36 +654,20 @@ EOF; * * @return Kernel */ - protected function getKernel(array $methods = array(), array $bundles = array()) + protected function getKernel(array $methods = [], array $bundles = [], bool $debug = false): Kernel { $methods[] = 'registerBundles'; $kernel = $this - ->getMockBuilder('Symfony\Component\HttpKernel\Kernel') + ->getMockBuilder(KernelForTest::class) ->setMethods($methods) - ->setConstructorArgs(array('test', false)) - ->getMockForAbstractClass() + ->setConstructorArgs(['test', $debug]) + ->getMock() ; $kernel->expects($this->any()) ->method('registerBundles') - ->will($this->returnValue($bundles)) + ->willReturn($bundles) ; - $p = new \ReflectionProperty($kernel, 'rootDir'); - $p->setAccessible(true); - $p->setValue($kernel, __DIR__.'/Fixtures'); - - return $kernel; - } - - protected function getKernelForTest(array $methods = array()) - { - $kernel = $this->getMockBuilder('Symfony\Component\HttpKernel\Tests\Fixtures\KernelForTest') - ->setConstructorArgs(array('test', false)) - ->setMethods($methods) - ->getMock(); - $p = new \ReflectionProperty($kernel, 'rootDir'); - $p->setAccessible(true); - $p->setValue($kernel, __DIR__.'/Fixtures'); return $kernel; } @@ -996,6 +685,11 @@ class TestKernel implements HttpKernelInterface public function handle(Request $request, $type = self::MASTER_REQUEST, $catch = true) { } + + public function getProjectDir(): string + { + return __DIR__.'/Fixtures'; + } } class CustomProjectDirKernel extends Kernel @@ -1004,18 +698,17 @@ class CustomProjectDirKernel extends Kernel private $buildContainer; private $httpKernel; - public function __construct(\Closure $buildContainer = null, HttpKernelInterface $httpKernel = null, $name = 'custom') + public function __construct(\Closure $buildContainer = null, HttpKernelInterface $httpKernel = null, $env = 'custom') { - parent::__construct($name, true); + parent::__construct($env, true); - $this->baseDir = 'foo'; $this->buildContainer = $buildContainer; $this->httpKernel = $httpKernel; } public function registerBundles() { - return array(); + return []; } public function registerContainerConfiguration(LoaderInterface $loader) @@ -1023,11 +716,6 @@ class CustomProjectDirKernel extends Kernel } public function getProjectDir() - { - return $this->baseDir; - } - - public function getRootDir() { return __DIR__.'/Fixtures'; } diff --git a/vendor/symfony/http-kernel/Tests/Log/LoggerTest.php b/vendor/symfony/http-kernel/Tests/Log/LoggerTest.php index ecf67af78c11510c104bf43b088547271ab2965d..79b79cc69cb95f0663f42dc01994c8b91bf1a65f 100644 --- a/vendor/symfony/http-kernel/Tests/Log/LoggerTest.php +++ b/vendor/symfony/http-kernel/Tests/Log/LoggerTest.php @@ -32,13 +32,13 @@ class LoggerTest extends TestCase */ private $tmpFile; - protected function setUp() + protected function setUp(): void { - $this->tmpFile = sys_get_temp_dir().DIRECTORY_SEPARATOR.'log'; + $this->tmpFile = tempnam(sys_get_temp_dir(), 'log'); $this->logger = new Logger(LogLevel::DEBUG, $this->tmpFile); } - protected function tearDown() + protected function tearDown(): void { if (!@unlink($this->tmpFile)) { file_put_contents($this->tmpFile, ''); @@ -72,135 +72,129 @@ class LoggerTest extends TestCase */ public function testLogsAtAllLevels($level, $message) { - $this->logger->{$level}($message, array('user' => 'Bob')); - $this->logger->log($level, $message, array('user' => 'Bob')); + $this->logger->{$level}($message, ['user' => 'Bob']); + $this->logger->log($level, $message, ['user' => 'Bob']); - $expected = array( + $expected = [ "[$level] message of level $level with context: Bob", "[$level] message of level $level with context: Bob", - ); + ]; $this->assertLogsMatch($expected, $this->getLogs()); } public function provideLevelsAndMessages() { - return array( - LogLevel::EMERGENCY => array(LogLevel::EMERGENCY, 'message of level emergency with context: {user}'), - LogLevel::ALERT => array(LogLevel::ALERT, 'message of level alert with context: {user}'), - LogLevel::CRITICAL => array(LogLevel::CRITICAL, 'message of level critical with context: {user}'), - LogLevel::ERROR => array(LogLevel::ERROR, 'message of level error with context: {user}'), - LogLevel::WARNING => array(LogLevel::WARNING, 'message of level warning with context: {user}'), - LogLevel::NOTICE => array(LogLevel::NOTICE, 'message of level notice with context: {user}'), - LogLevel::INFO => array(LogLevel::INFO, 'message of level info with context: {user}'), - LogLevel::DEBUG => array(LogLevel::DEBUG, 'message of level debug with context: {user}'), - ); + return [ + LogLevel::EMERGENCY => [LogLevel::EMERGENCY, 'message of level emergency with context: {user}'], + LogLevel::ALERT => [LogLevel::ALERT, 'message of level alert with context: {user}'], + LogLevel::CRITICAL => [LogLevel::CRITICAL, 'message of level critical with context: {user}'], + LogLevel::ERROR => [LogLevel::ERROR, 'message of level error with context: {user}'], + LogLevel::WARNING => [LogLevel::WARNING, 'message of level warning with context: {user}'], + LogLevel::NOTICE => [LogLevel::NOTICE, 'message of level notice with context: {user}'], + LogLevel::INFO => [LogLevel::INFO, 'message of level info with context: {user}'], + LogLevel::DEBUG => [LogLevel::DEBUG, 'message of level debug with context: {user}'], + ]; } public function testLogLevelDisabled() { $this->logger = new Logger(LogLevel::INFO, $this->tmpFile); - $this->logger->debug('test', array('user' => 'Bob')); - $this->logger->log(LogLevel::DEBUG, 'test', array('user' => 'Bob')); + $this->logger->debug('test', ['user' => 'Bob']); + $this->logger->log(LogLevel::DEBUG, 'test', ['user' => 'Bob']); // Will always be true, but asserts than an exception isn't thrown - $this->assertSame(array(), $this->getLogs()); + $this->assertSame([], $this->getLogs()); } - /** - * @expectedException \Psr\Log\InvalidArgumentException - */ public function testThrowsOnInvalidLevel() { + $this->expectException('Psr\Log\InvalidArgumentException'); $this->logger->log('invalid level', 'Foo'); } - /** - * @expectedException \Psr\Log\InvalidArgumentException - */ public function testThrowsOnInvalidMinLevel() { + $this->expectException('Psr\Log\InvalidArgumentException'); new Logger('invalid'); } - /** - * @expectedException \Psr\Log\InvalidArgumentException - */ public function testInvalidOutput() { + $this->expectException('Psr\Log\InvalidArgumentException'); new Logger(LogLevel::DEBUG, '/'); } public function testContextReplacement() { $logger = $this->logger; - $logger->info('{Message {nothing} {user} {foo.bar} a}', array('user' => 'Bob', 'foo.bar' => 'Bar')); + $logger->info('{Message {nothing} {user} {foo.bar} a}', ['user' => 'Bob', 'foo.bar' => 'Bar']); - $expected = array('[info] {Message {nothing} Bob Bar a}'); + $expected = ['[info] {Message {nothing} Bob Bar a}']; $this->assertLogsMatch($expected, $this->getLogs()); } public function testObjectCastToString() { if (method_exists($this, 'createPartialMock')) { - $dummy = $this->createPartialMock(DummyTest::class, array('__toString')); + $dummy = $this->createPartialMock(DummyTest::class, ['__toString']); } else { - $dummy = $this->getMock(DummyTest::class, array('__toString')); + $dummy = $this->createPartialMock(DummyTest::class, ['__toString']); } $dummy->expects($this->atLeastOnce()) ->method('__toString') - ->will($this->returnValue('DUMMY')); + ->willReturn('DUMMY'); $this->logger->warning($dummy); - $expected = array('[warning] DUMMY'); + $expected = ['[warning] DUMMY']; $this->assertLogsMatch($expected, $this->getLogs()); } public function testContextCanContainAnything() { - $context = array( + $context = [ 'bool' => true, 'null' => null, 'string' => 'Foo', 'int' => 0, 'float' => 0.5, - 'nested' => array('with object' => new DummyTest()), + 'nested' => ['with object' => new DummyTest()], 'object' => new \DateTime(), 'resource' => fopen('php://memory', 'r'), - ); + ]; $this->logger->warning('Crazy context data', $context); - $expected = array('[warning] Crazy context data'); + $expected = ['[warning] Crazy context data']; $this->assertLogsMatch($expected, $this->getLogs()); } public function testContextExceptionKeyCanBeExceptionOrOtherValues() { $logger = $this->logger; - $logger->warning('Random message', array('exception' => 'oops')); - $logger->critical('Uncaught Exception!', array('exception' => new \LogicException('Fail'))); + $logger->warning('Random message', ['exception' => 'oops']); + $logger->critical('Uncaught Exception!', ['exception' => new \LogicException('Fail')]); - $expected = array( + $expected = [ '[warning] Random message', '[critical] Uncaught Exception!', - ); + ]; $this->assertLogsMatch($expected, $this->getLogs()); } public function testFormatter() { $this->logger = new Logger(LogLevel::DEBUG, $this->tmpFile, function ($level, $message, $context) { - return json_encode(array('level' => $level, 'message' => $message, 'context' => $context)).\PHP_EOL; + return json_encode(['level' => $level, 'message' => $message, 'context' => $context]).\PHP_EOL; }); - $this->logger->error('An error', array('foo' => 'bar')); - $this->logger->warning('A warning', array('baz' => 'bar')); - $this->assertSame(array( + $this->logger->error('An error', ['foo' => 'bar']); + $this->logger->warning('A warning', ['baz' => 'bar']); + $this->assertSame([ '{"level":"error","message":"An error","context":{"foo":"bar"}}', '{"level":"warning","message":"A warning","context":{"baz":"bar"}}', - ), $this->getLogs()); + ], $this->getLogs()); } } diff --git a/vendor/symfony/http-kernel/Tests/Logger.php b/vendor/symfony/http-kernel/Tests/Logger.php index 63c70bf67aa82ec508e0eff9ce3163e52e15e20d..8453cfbd57228b95648d2c4e130d16fa93697db5 100644 --- a/vendor/symfony/http-kernel/Tests/Logger.php +++ b/vendor/symfony/http-kernel/Tests/Logger.php @@ -22,66 +22,66 @@ class Logger implements LoggerInterface $this->clear(); } - public function getLogs($level = false) + public function getLogs($level = false): array { return false === $level ? $this->logs : $this->logs[$level]; } public function clear() { - $this->logs = array( - 'emergency' => array(), - 'alert' => array(), - 'critical' => array(), - 'error' => array(), - 'warning' => array(), - 'notice' => array(), - 'info' => array(), - 'debug' => array(), - ); + $this->logs = [ + 'emergency' => [], + 'alert' => [], + 'critical' => [], + 'error' => [], + 'warning' => [], + 'notice' => [], + 'info' => [], + 'debug' => [], + ]; } - public function log($level, $message, array $context = array()) + public function log($level, $message, array $context = []) { $this->logs[$level][] = $message; } - public function emergency($message, array $context = array()) + public function emergency($message, array $context = []) { $this->log('emergency', $message, $context); } - public function alert($message, array $context = array()) + public function alert($message, array $context = []) { $this->log('alert', $message, $context); } - public function critical($message, array $context = array()) + public function critical($message, array $context = []) { $this->log('critical', $message, $context); } - public function error($message, array $context = array()) + public function error($message, array $context = []) { $this->log('error', $message, $context); } - public function warning($message, array $context = array()) + public function warning($message, array $context = []) { $this->log('warning', $message, $context); } - public function notice($message, array $context = array()) + public function notice($message, array $context = []) { $this->log('notice', $message, $context); } - public function info($message, array $context = array()) + public function info($message, array $context = []) { $this->log('info', $message, $context); } - public function debug($message, array $context = array()) + public function debug($message, array $context = []) { $this->log('debug', $message, $context); } diff --git a/vendor/symfony/http-kernel/Tests/Profiler/FileProfilerStorageTest.php b/vendor/symfony/http-kernel/Tests/Profiler/FileProfilerStorageTest.php index 99ff20756743933c05d600b0163fa0ba493c9bc5..f088fe044db1c712e6cc2adba89ed9b9388cee1f 100644 --- a/vendor/symfony/http-kernel/Tests/Profiler/FileProfilerStorageTest.php +++ b/vendor/symfony/http-kernel/Tests/Profiler/FileProfilerStorageTest.php @@ -20,9 +20,9 @@ class FileProfilerStorageTest extends TestCase private $tmpDir; private $storage; - protected function setUp() + protected function setUp(): void { - $this->tmpDir = sys_get_temp_dir().'/sf2_profiler_file_storage'; + $this->tmpDir = sys_get_temp_dir().'/sf_profiler_file_storage'; if (is_dir($this->tmpDir)) { self::cleanDir(); } @@ -30,7 +30,7 @@ class FileProfilerStorageTest extends TestCase $this->storage->purge(); } - protected function tearDown() + protected function tearDown(): void { self::cleanDir(); } @@ -83,22 +83,22 @@ class FileProfilerStorageTest extends TestCase $profile = new Profile('simple_quote'); $profile->setUrl('http://foo.bar/\''); $this->storage->write($profile); - $this->assertTrue(false !== $this->storage->read('simple_quote'), '->write() accepts single quotes in URL'); + $this->assertNotFalse($this->storage->read('simple_quote'), '->write() accepts single quotes in URL'); $profile = new Profile('double_quote'); $profile->setUrl('http://foo.bar/"'); $this->storage->write($profile); - $this->assertTrue(false !== $this->storage->read('double_quote'), '->write() accepts double quotes in URL'); + $this->assertNotFalse($this->storage->read('double_quote'), '->write() accepts double quotes in URL'); $profile = new Profile('backslash'); $profile->setUrl('http://foo.bar/\\'); $this->storage->write($profile); - $this->assertTrue(false !== $this->storage->read('backslash'), '->write() accepts backslash in URL'); + $this->assertNotFalse($this->storage->read('backslash'), '->write() accepts backslash in URL'); $profile = new Profile('comma'); $profile->setUrl('http://foo.bar/,'); $this->storage->write($profile); - $this->assertTrue(false !== $this->storage->read('comma'), '->write() accepts comma in URL'); + $this->assertNotFalse($this->storage->read('comma'), '->write() accepts comma in URL'); } public function testStoreDuplicateToken() @@ -226,7 +226,7 @@ class FileProfilerStorageTest extends TestCase public function testRetrieveByMethodAndLimit() { - foreach (array('POST', 'GET') as $method) { + foreach (['POST', 'GET'] as $method) { for ($i = 0; $i < 5; ++$i) { $profile = new Profile('token_'.$i.$method); $profile->setMethod($method); @@ -247,7 +247,7 @@ class FileProfilerStorageTest extends TestCase $profile->setMethod('GET'); $this->storage->write($profile); - $this->assertTrue(false !== $this->storage->read('token1')); + $this->assertNotFalse($this->storage->read('token1')); $this->assertCount(1, $this->storage->find('127.0.0.1', '', 10, 'GET')); $profile = new Profile('token2'); @@ -256,7 +256,7 @@ class FileProfilerStorageTest extends TestCase $profile->setMethod('GET'); $this->storage->write($profile); - $this->assertTrue(false !== $this->storage->read('token2')); + $this->assertNotFalse($this->storage->read('token2')); $this->assertCount(2, $this->storage->find('127.0.0.1', '', 10, 'GET')); $this->storage->purge(); @@ -293,8 +293,8 @@ class FileProfilerStorageTest extends TestCase $tokens = $this->storage->find('', '', 10, ''); $this->assertCount(2, $tokens); - $this->assertContains($tokens[0]['status_code'], array(200, 404)); - $this->assertContains($tokens[1]['status_code'], array(200, 404)); + $this->assertContains($tokens[0]['status_code'], [200, 404]); + $this->assertContains($tokens[1]['status_code'], [200, 404]); } public function testMultiRowIndexFile() diff --git a/vendor/symfony/http-kernel/Tests/Profiler/ProfilerTest.php b/vendor/symfony/http-kernel/Tests/Profiler/ProfilerTest.php index 243c3c5c5a7cb38a9df89a601fbb7c8875814d72..2128ea9bcd8c1606d88be36e1c5c01580be3aa88 100644 --- a/vendor/symfony/http-kernel/Tests/Profiler/ProfilerTest.php +++ b/vendor/symfony/http-kernel/Tests/Profiler/ProfilerTest.php @@ -12,12 +12,12 @@ namespace Symfony\Component\HttpKernel\Tests\Profiler; use PHPUnit\Framework\TestCase; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\DataCollector\DataCollectorInterface; use Symfony\Component\HttpKernel\DataCollector\RequestDataCollector; use Symfony\Component\HttpKernel\Profiler\FileProfilerStorage; use Symfony\Component\HttpKernel\Profiler\Profiler; -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\HttpFoundation\Response; class ProfilerTest extends TestCase { @@ -82,9 +82,9 @@ class ProfilerTest extends TestCase $this->assertCount(0, $profiler->find(null, null, null, null, null, null, '204')); } - protected function setUp() + protected function setUp(): void { - $this->tmp = tempnam(sys_get_temp_dir(), 'sf2_profiler'); + $this->tmp = tempnam(sys_get_temp_dir(), 'sf_profiler'); if (file_exists($this->tmp)) { @unlink($this->tmp); } @@ -93,7 +93,7 @@ class ProfilerTest extends TestCase $this->storage->purge(); } - protected function tearDown() + protected function tearDown(): void { if (null !== $this->storage) { $this->storage->purge(); diff --git a/vendor/symfony/http-kernel/Tests/TestHttpKernel.php b/vendor/symfony/http-kernel/Tests/TestHttpKernel.php index 3ec59272541a444de4a6e072f66351a4ab8d87e9..27ba2d6f8949901133c70c5dda934ec8d94d2ff2 100644 --- a/vendor/symfony/http-kernel/Tests/TestHttpKernel.php +++ b/vendor/symfony/http-kernel/Tests/TestHttpKernel.php @@ -11,12 +11,12 @@ namespace Symfony\Component\HttpKernel\Tests; -use Symfony\Component\HttpKernel\Controller\ArgumentResolverInterface; -use Symfony\Component\HttpKernel\HttpKernel; +use Symfony\Component\EventDispatcher\EventDispatcher; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpKernel\Controller\ArgumentResolverInterface; use Symfony\Component\HttpKernel\Controller\ControllerResolverInterface; -use Symfony\Component\EventDispatcher\EventDispatcher; +use Symfony\Component\HttpKernel\HttpKernel; class TestHttpKernel extends HttpKernel implements ControllerResolverInterface, ArgumentResolverInterface { @@ -27,12 +27,12 @@ class TestHttpKernel extends HttpKernel implements ControllerResolverInterface, public function getController(Request $request) { - return array($this, 'callController'); + return [$this, 'callController']; } public function getArguments(Request $request, $controller) { - return array($request); + return [$request]; } public function callController(Request $request) diff --git a/vendor/symfony/http-kernel/Tests/UriSignerTest.php b/vendor/symfony/http-kernel/Tests/UriSignerTest.php index 84ec19f70db2181402ca4f397ec6a2c261621ab2..b2eb59206ba03cc5757c45ef8fa331eba3b24461 100644 --- a/vendor/symfony/http-kernel/Tests/UriSignerTest.php +++ b/vendor/symfony/http-kernel/Tests/UriSignerTest.php @@ -20,8 +20,9 @@ class UriSignerTest extends TestCase { $signer = new UriSigner('foobar'); - $this->assertContains('?_hash=', $signer->sign('http://example.com/foo')); - $this->assertContains('&_hash=', $signer->sign('http://example.com/foo?foo=bar')); + $this->assertStringContainsString('?_hash=', $signer->sign('http://example.com/foo')); + $this->assertStringContainsString('?_hash=', $signer->sign('http://example.com/foo?foo=bar')); + $this->assertStringContainsString('&foo=', $signer->sign('http://example.com/foo?foo=bar')); } public function testCheck() @@ -45,7 +46,7 @@ class UriSignerTest extends TestCase $signer = new UriSigner('foobar'); $this->assertSame( - 'http://example.com/foo?baz=bay&foo=bar&_hash=rIOcC%2FF3DoEGo%2FvnESjSp7uU9zA9S%2F%2BOLhxgMexoPUM%3D', + 'http://example.com/foo?_hash=rIOcC%2FF3DoEGo%2FvnESjSp7uU9zA9S%2F%2BOLhxgMexoPUM%3D&baz=bay&foo=bar', $signer->sign('http://example.com/foo?foo=bar&baz=bay') ); $this->assertTrue($signer->check($signer->sign('http://example.com/foo?foo=bar&baz=bay'))); @@ -61,4 +62,15 @@ class UriSignerTest extends TestCase ); $this->assertTrue($signer->check($signer->sign('http://example.com/foo?foo=bar&baz=bay'))); } + + public function testSignerWorksWithFragments() + { + $signer = new UriSigner('foobar'); + + $this->assertSame( + 'http://example.com/foo?_hash=EhpAUyEobiM3QTrKxoLOtQq5IsWyWedoXDPqIjzNj5o%3D&bar=foo&foo=bar#foobar', + $signer->sign('http://example.com/foo?bar=foo&foo=bar#foobar') + ); + $this->assertTrue($signer->check($signer->sign('http://example.com/foo?bar=foo&foo=bar#foobar'))); + } } diff --git a/vendor/symfony/http-kernel/UriSigner.php b/vendor/symfony/http-kernel/UriSigner.php index 28459b4ecd394ddc3fb0b4269277af03daa5537e..1dd56ffd76fff3d4adb0af937630c7c772df3cf4 100644 --- a/vendor/symfony/http-kernel/UriSigner.php +++ b/vendor/symfony/http-kernel/UriSigner.php @@ -25,7 +25,7 @@ class UriSigner * @param string $secret A secret * @param string $parameter Query string parameter to use */ - public function __construct($secret, $parameter = '_hash') + public function __construct(string $secret, string $parameter = '_hash') { $this->secret = $secret; $this->parameter = $parameter; @@ -47,12 +47,13 @@ class UriSigner if (isset($url['query'])) { parse_str($url['query'], $params); } else { - $params = array(); + $params = []; } $uri = $this->buildUrl($url, $params); + $params[$this->parameter] = $this->computeHash($uri); - return $uri.(false === strpos($uri, '?') ? '?' : '&').$this->parameter.'='.$this->computeHash($uri); + return $this->buildUrl($url, $params); } /** @@ -68,14 +69,14 @@ class UriSigner if (isset($url['query'])) { parse_str($url['query'], $params); } else { - $params = array(); + $params = []; } if (empty($params[$this->parameter])) { return false; } - $hash = urlencode($params[$this->parameter]); + $hash = $params[$this->parameter]; unset($params[$this->parameter]); return $this->computeHash($this->buildUrl($url, $params)) === $hash; @@ -83,10 +84,10 @@ class UriSigner private function computeHash($uri) { - return urlencode(base64_encode(hash_hmac('sha256', $uri, $this->secret, true))); + return base64_encode(hash_hmac('sha256', $uri, $this->secret, true)); } - private function buildUrl(array $url, array $params = array()) + private function buildUrl(array $url, array $params = []) { ksort($params, SORT_STRING); $url['query'] = http_build_query($params, '', '&'); diff --git a/vendor/symfony/http-kernel/composer.json b/vendor/symfony/http-kernel/composer.json index b33675763f6e5104851ce9f4066ec1e19eb1a9f3..e07b453b481136c33d43826e00497bcebf429d29 100644 --- a/vendor/symfony/http-kernel/composer.json +++ b/vendor/symfony/http-kernel/composer.json @@ -16,37 +16,42 @@ } ], "require": { - "php": "^5.5.9|>=7.0.8", - "symfony/event-dispatcher": "~2.8|~3.0|~4.0", - "symfony/http-foundation": "^3.4.4|^4.0.4", - "symfony/debug": "~2.8|~3.0|~4.0", + "php": "^7.1.3", + "symfony/event-dispatcher": "^4.3", + "symfony/http-foundation": "^4.1.1", + "symfony/debug": "~3.4|~4.0", + "symfony/polyfill-ctype": "~1.8", + "symfony/polyfill-php73": "^1.9", "psr/log": "~1.0" }, "require-dev": { - "symfony/browser-kit": "~2.8|~3.0|~4.0", - "symfony/class-loader": "~2.8|~3.0", - "symfony/config": "~2.8|~3.0|~4.0", - "symfony/console": "~2.8|~3.0|~4.0", - "symfony/css-selector": "~2.8|~3.0|~4.0", - "symfony/dependency-injection": "~3.4|~4.0", - "symfony/dom-crawler": "~2.8|~3.0|~4.0", - "symfony/expression-language": "~2.8|~3.0|~4.0", - "symfony/finder": "~2.8|~3.0|~4.0", - "symfony/process": "~2.8|~3.0|~4.0", + "symfony/browser-kit": "^4.3", + "symfony/config": "~3.4|~4.0", + "symfony/console": "~3.4|~4.0", + "symfony/css-selector": "~3.4|~4.0", + "symfony/dependency-injection": "^4.3", + "symfony/dom-crawler": "~3.4|~4.0", + "symfony/expression-language": "~3.4|~4.0", + "symfony/finder": "~3.4|~4.0", + "symfony/process": "~3.4|~4.0", "symfony/routing": "~3.4|~4.0", - "symfony/stopwatch": "~2.8|~3.0|~4.0", - "symfony/templating": "~2.8|~3.0|~4.0", - "symfony/translation": "~2.8|~3.0|~4.0", - "symfony/var-dumper": "~3.3|~4.0", - "psr/cache": "~1.0" + "symfony/stopwatch": "~3.4|~4.0", + "symfony/templating": "~3.4|~4.0", + "symfony/translation": "~4.2", + "symfony/translation-contracts": "^1.1", + "symfony/var-dumper": "^4.1.1", + "psr/cache": "~1.0", + "twig/twig": "^1.34|^2.4" }, "provide": { "psr/log-implementation": "1.0" }, "conflict": { - "symfony/config": "<2.8", - "symfony/dependency-injection": "<3.4", - "symfony/var-dumper": "<3.3", + "symfony/browser-kit": "<4.3", + "symfony/config": "<3.4", + "symfony/dependency-injection": "<4.3", + "symfony/translation": "<4.2", + "symfony/var-dumper": "<4.1.1", "twig/twig": "<1.34|<2.4,>=2" }, "suggest": { @@ -54,7 +59,6 @@ "symfony/config": "", "symfony/console": "", "symfony/dependency-injection": "", - "symfony/finder": "", "symfony/var-dumper": "" }, "autoload": { @@ -66,7 +70,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-master": "3.4-dev" + "dev-master": "4.3-dev" } } } diff --git a/vendor/symfony/http-kernel/phpunit.xml.dist b/vendor/symfony/http-kernel/phpunit.xml.dist index e0de769dd7afc031a6dbc59a463b0a45530b0f27..3fc07707f2faeacf24a3ab2315390d1eebe1db41 100644 --- a/vendor/symfony/http-kernel/phpunit.xml.dist +++ b/vendor/symfony/http-kernel/phpunit.xml.dist @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="UTF-8"?> <phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/4.1/phpunit.xsd" + xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/5.2/phpunit.xsd" backupGlobals="false" colors="true" bootstrap="vendor/autoload.php" diff --git a/vendor/symfony/mime/.gitignore b/vendor/symfony/mime/.gitignore new file mode 100644 index 0000000000000000000000000000000000000000..5414c2c655e72ae741a2eccd1d69d06ce7c20f02 --- /dev/null +++ b/vendor/symfony/mime/.gitignore @@ -0,0 +1,3 @@ +composer.lock +phpunit.xml +vendor/ diff --git a/vendor/symfony/mime/Address.php b/vendor/symfony/mime/Address.php new file mode 100644 index 0000000000000000000000000000000000000000..be1ca760a7f13fd03aceabf92625e58e71570b64 --- /dev/null +++ b/vendor/symfony/mime/Address.php @@ -0,0 +1,98 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime; + +use Egulias\EmailValidator\EmailValidator; +use Egulias\EmailValidator\Validation\RFCValidation; +use Symfony\Component\Mime\Encoder\IdnAddressEncoder; +use Symfony\Component\Mime\Exception\InvalidArgumentException; +use Symfony\Component\Mime\Exception\LogicException; +use Symfony\Component\Mime\Exception\RfcComplianceException; + +/** + * @author Fabien Potencier <fabien@symfony.com> + * + * @experimental in 4.3 + */ +class Address +{ + private static $validator; + private static $encoder; + + private $address; + + public function __construct(string $address) + { + if (!class_exists(EmailValidator::class)) { + throw new LogicException(sprintf('The "%s" class cannot be used as it needs "%s"; try running "composer require egulias/email-validator".', __CLASS__, EmailValidator::class)); + } + + if (null === self::$validator) { + self::$validator = new EmailValidator(); + } + + $this->address = trim($address); + + if (!self::$validator->isValid($this->address, new RFCValidation())) { + throw new RfcComplianceException(sprintf('Email "%s" does not comply with addr-spec of RFC 2822.', $address)); + } + } + + public function getAddress(): string + { + return $this->address; + } + + public function getEncodedAddress(): string + { + if (null === self::$encoder) { + self::$encoder = new IdnAddressEncoder(); + } + + return self::$encoder->encodeString($this->address); + } + + public function toString(): string + { + return $this->getEncodedAddress(); + } + + /** + * @param Address|string $address + */ + public static function create($address): self + { + if ($address instanceof self) { + return $address; + } + if (\is_string($address)) { + return new self($address); + } + + throw new InvalidArgumentException(sprintf('An address can be an instance of Address or a string ("%s") given).', \is_object($address) ? \get_class($address) : \gettype($address))); + } + + /** + * @param (Address|string)[] $addresses + * + * @return Address[] + */ + public static function createArray(array $addresses): array + { + $addrs = []; + foreach ($addresses as $address) { + $addrs[] = self::create($address); + } + + return $addrs; + } +} diff --git a/vendor/symfony/mime/BodyRendererInterface.php b/vendor/symfony/mime/BodyRendererInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..8fcc40159554982f28682933287ca932da028a24 --- /dev/null +++ b/vendor/symfony/mime/BodyRendererInterface.php @@ -0,0 +1,22 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime; + +/** + * @author Fabien Potencier <fabien@symfony.com> + * + * @experimental in 4.3 + */ +interface BodyRendererInterface +{ + public function render(Message $message): void; +} diff --git a/vendor/symfony/mime/CHANGELOG.md b/vendor/symfony/mime/CHANGELOG.md new file mode 100644 index 0000000000000000000000000000000000000000..796cfdd155626337ebd1bfaeff76971ea89e2867 --- /dev/null +++ b/vendor/symfony/mime/CHANGELOG.md @@ -0,0 +1,12 @@ +CHANGELOG +========= + +4.3.3 +----- + + * [BC BREAK] Renamed method `Headers::getAll()` to `Headers::all()`. + +4.3.0 +----- + + * Introduced the component as experimental diff --git a/vendor/symfony/mime/CharacterStream.php b/vendor/symfony/mime/CharacterStream.php new file mode 100644 index 0000000000000000000000000000000000000000..9b80b2efa481ad0d3f163f4ac1ca6935d9537ab5 --- /dev/null +++ b/vendor/symfony/mime/CharacterStream.php @@ -0,0 +1,224 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime; + +/** + * @author Fabien Potencier <fabien@symfony.com> + * @author Xavier De Cock <xdecock@gmail.com> + * + * @internal + * + * @experimental in 4.3 + */ +final class CharacterStream +{ + /** Pre-computed for optimization */ + private const UTF8_LENGTH_MAP = [ + "\x00" => 1, "\x01" => 1, "\x02" => 1, "\x03" => 1, "\x04" => 1, "\x05" => 1, "\x06" => 1, "\x07" => 1, + "\x08" => 1, "\x09" => 1, "\x0a" => 1, "\x0b" => 1, "\x0c" => 1, "\x0d" => 1, "\x0e" => 1, "\x0f" => 1, + "\x10" => 1, "\x11" => 1, "\x12" => 1, "\x13" => 1, "\x14" => 1, "\x15" => 1, "\x16" => 1, "\x17" => 1, + "\x18" => 1, "\x19" => 1, "\x1a" => 1, "\x1b" => 1, "\x1c" => 1, "\x1d" => 1, "\x1e" => 1, "\x1f" => 1, + "\x20" => 1, "\x21" => 1, "\x22" => 1, "\x23" => 1, "\x24" => 1, "\x25" => 1, "\x26" => 1, "\x27" => 1, + "\x28" => 1, "\x29" => 1, "\x2a" => 1, "\x2b" => 1, "\x2c" => 1, "\x2d" => 1, "\x2e" => 1, "\x2f" => 1, + "\x30" => 1, "\x31" => 1, "\x32" => 1, "\x33" => 1, "\x34" => 1, "\x35" => 1, "\x36" => 1, "\x37" => 1, + "\x38" => 1, "\x39" => 1, "\x3a" => 1, "\x3b" => 1, "\x3c" => 1, "\x3d" => 1, "\x3e" => 1, "\x3f" => 1, + "\x40" => 1, "\x41" => 1, "\x42" => 1, "\x43" => 1, "\x44" => 1, "\x45" => 1, "\x46" => 1, "\x47" => 1, + "\x48" => 1, "\x49" => 1, "\x4a" => 1, "\x4b" => 1, "\x4c" => 1, "\x4d" => 1, "\x4e" => 1, "\x4f" => 1, + "\x50" => 1, "\x51" => 1, "\x52" => 1, "\x53" => 1, "\x54" => 1, "\x55" => 1, "\x56" => 1, "\x57" => 1, + "\x58" => 1, "\x59" => 1, "\x5a" => 1, "\x5b" => 1, "\x5c" => 1, "\x5d" => 1, "\x5e" => 1, "\x5f" => 1, + "\x60" => 1, "\x61" => 1, "\x62" => 1, "\x63" => 1, "\x64" => 1, "\x65" => 1, "\x66" => 1, "\x67" => 1, + "\x68" => 1, "\x69" => 1, "\x6a" => 1, "\x6b" => 1, "\x6c" => 1, "\x6d" => 1, "\x6e" => 1, "\x6f" => 1, + "\x70" => 1, "\x71" => 1, "\x72" => 1, "\x73" => 1, "\x74" => 1, "\x75" => 1, "\x76" => 1, "\x77" => 1, + "\x78" => 1, "\x79" => 1, "\x7a" => 1, "\x7b" => 1, "\x7c" => 1, "\x7d" => 1, "\x7e" => 1, "\x7f" => 1, + "\x80" => 0, "\x81" => 0, "\x82" => 0, "\x83" => 0, "\x84" => 0, "\x85" => 0, "\x86" => 0, "\x87" => 0, + "\x88" => 0, "\x89" => 0, "\x8a" => 0, "\x8b" => 0, "\x8c" => 0, "\x8d" => 0, "\x8e" => 0, "\x8f" => 0, + "\x90" => 0, "\x91" => 0, "\x92" => 0, "\x93" => 0, "\x94" => 0, "\x95" => 0, "\x96" => 0, "\x97" => 0, + "\x98" => 0, "\x99" => 0, "\x9a" => 0, "\x9b" => 0, "\x9c" => 0, "\x9d" => 0, "\x9e" => 0, "\x9f" => 0, + "\xa0" => 0, "\xa1" => 0, "\xa2" => 0, "\xa3" => 0, "\xa4" => 0, "\xa5" => 0, "\xa6" => 0, "\xa7" => 0, + "\xa8" => 0, "\xa9" => 0, "\xaa" => 0, "\xab" => 0, "\xac" => 0, "\xad" => 0, "\xae" => 0, "\xaf" => 0, + "\xb0" => 0, "\xb1" => 0, "\xb2" => 0, "\xb3" => 0, "\xb4" => 0, "\xb5" => 0, "\xb6" => 0, "\xb7" => 0, + "\xb8" => 0, "\xb9" => 0, "\xba" => 0, "\xbb" => 0, "\xbc" => 0, "\xbd" => 0, "\xbe" => 0, "\xbf" => 0, + "\xc0" => 2, "\xc1" => 2, "\xc2" => 2, "\xc3" => 2, "\xc4" => 2, "\xc5" => 2, "\xc6" => 2, "\xc7" => 2, + "\xc8" => 2, "\xc9" => 2, "\xca" => 2, "\xcb" => 2, "\xcc" => 2, "\xcd" => 2, "\xce" => 2, "\xcf" => 2, + "\xd0" => 2, "\xd1" => 2, "\xd2" => 2, "\xd3" => 2, "\xd4" => 2, "\xd5" => 2, "\xd6" => 2, "\xd7" => 2, + "\xd8" => 2, "\xd9" => 2, "\xda" => 2, "\xdb" => 2, "\xdc" => 2, "\xdd" => 2, "\xde" => 2, "\xdf" => 2, + "\xe0" => 3, "\xe1" => 3, "\xe2" => 3, "\xe3" => 3, "\xe4" => 3, "\xe5" => 3, "\xe6" => 3, "\xe7" => 3, + "\xe8" => 3, "\xe9" => 3, "\xea" => 3, "\xeb" => 3, "\xec" => 3, "\xed" => 3, "\xee" => 3, "\xef" => 3, + "\xf0" => 4, "\xf1" => 4, "\xf2" => 4, "\xf3" => 4, "\xf4" => 4, "\xf5" => 4, "\xf6" => 4, "\xf7" => 4, + "\xf8" => 5, "\xf9" => 5, "\xfa" => 5, "\xfb" => 5, "\xfc" => 6, "\xfd" => 6, "\xfe" => 0, "\xff" => 0, + ]; + + private $data = ''; + private $dataSize = 0; + private $map = []; + private $charCount = 0; + private $currentPos = 0; + private $fixedWidth = 0; + + /** + * @param resource|string $input + */ + public function __construct($input, ?string $charset = 'utf-8') + { + $charset = strtolower(trim($charset)) ?: 'utf-8'; + if ('utf-8' === $charset || 'utf8' === $charset) { + $this->fixedWidth = 0; + $this->map = ['p' => [], 'i' => []]; + } else { + switch ($charset) { + // 16 bits + case 'ucs2': + case 'ucs-2': + case 'utf16': + case 'utf-16': + $this->fixedWidth = 2; + break; + + // 32 bits + case 'ucs4': + case 'ucs-4': + case 'utf32': + case 'utf-32': + $this->fixedWidth = 4; + break; + + // 7-8 bit charsets: (us-)?ascii, (iso|iec)-?8859-?[0-9]+, windows-?125[0-9], cp-?[0-9]+, ansi, macintosh, + // koi-?7, koi-?8-?.+, mik, (cork|t1), v?iscii + // and fallback + default: + $this->fixedWidth = 1; + } + } + if (\is_resource($input)) { + $blocks = 512; + if (stream_get_meta_data($input)['seekable'] ?? false) { + rewind($input); + } + while (false !== $read = fread($input, $blocks)) { + $this->write($read); + } + } else { + $this->write($input); + } + } + + public function read(int $length): ?string + { + if ($this->currentPos >= $this->charCount) { + return null; + } + $ret = null; + $length = ($this->currentPos + $length > $this->charCount) ? $this->charCount - $this->currentPos : $length; + if ($this->fixedWidth > 0) { + $len = $length * $this->fixedWidth; + $ret = substr($this->data, $this->currentPos * $this->fixedWidth, $len); + $this->currentPos += $length; + } else { + $end = $this->currentPos + $length; + $end = $end > $this->charCount ? $this->charCount : $end; + $ret = ''; + $start = 0; + if ($this->currentPos > 0) { + $start = $this->map['p'][$this->currentPos - 1]; + } + $to = $start; + for (; $this->currentPos < $end; ++$this->currentPos) { + if (isset($this->map['i'][$this->currentPos])) { + $ret .= substr($this->data, $start, $to - $start).'?'; + $start = $this->map['p'][$this->currentPos]; + } else { + $to = $this->map['p'][$this->currentPos]; + } + } + $ret .= substr($this->data, $start, $to - $start); + } + + return $ret; + } + + public function readBytes(int $length): ?array + { + if (null !== $read = $this->read($length)) { + return array_map('ord', str_split($read, 1)); + } + + return null; + } + + public function setPointer(int $charOffset): void + { + if ($this->charCount < $charOffset) { + $charOffset = $this->charCount; + } + $this->currentPos = $charOffset; + } + + public function write(string $chars): void + { + $ignored = ''; + $this->data .= $chars; + if ($this->fixedWidth > 0) { + $strlen = \strlen($chars); + $ignoredL = $strlen % $this->fixedWidth; + $ignored = $ignoredL ? substr($chars, -$ignoredL) : ''; + $this->charCount += ($strlen - $ignoredL) / $this->fixedWidth; + } else { + $this->charCount += $this->getUtf8CharPositions($chars, $this->dataSize, $ignored); + } + $this->dataSize = \strlen($this->data) - \strlen($ignored); + } + + private function getUtf8CharPositions(string $string, int $startOffset, &$ignoredChars): int + { + $strlen = \strlen($string); + $charPos = \count($this->map['p']); + $foundChars = 0; + $invalid = false; + for ($i = 0; $i < $strlen; ++$i) { + $char = $string[$i]; + $size = self::UTF8_LENGTH_MAP[$char]; + if (0 == $size) { + /* char is invalid, we must wait for a resync */ + $invalid = true; + continue; + } + + if ($invalid) { + /* We mark the chars as invalid and start a new char */ + $this->map['p'][$charPos + $foundChars] = $startOffset + $i; + $this->map['i'][$charPos + $foundChars] = true; + ++$foundChars; + $invalid = false; + } + if (($i + $size) > $strlen) { + $ignoredChars = substr($string, $i); + break; + } + for ($j = 1; $j < $size; ++$j) { + $char = $string[$i + $j]; + if ($char > "\x7F" && $char < "\xC0") { + // Valid - continue parsing + } else { + /* char is invalid, we must wait for a resync */ + $invalid = true; + continue 2; + } + } + /* Ok we got a complete char here */ + $this->map['p'][$charPos + $foundChars] = $startOffset + $i + $size; + $i += $j - 1; + ++$foundChars; + } + + return $foundChars; + } +} diff --git a/vendor/symfony/mime/DependencyInjection/AddMimeTypeGuesserPass.php b/vendor/symfony/mime/DependencyInjection/AddMimeTypeGuesserPass.php new file mode 100644 index 0000000000000000000000000000000000000000..78450b91bd56c712546d23e8695ed844dbfd6f41 --- /dev/null +++ b/vendor/symfony/mime/DependencyInjection/AddMimeTypeGuesserPass.php @@ -0,0 +1,48 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime\DependencyInjection; + +use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Reference; + +/** + * Registers custom mime types guessers. + * + * @author Fabien Potencier <fabien@symfony.com> + * + * @experimental in 4.3 + */ +class AddMimeTypeGuesserPass implements CompilerPassInterface +{ + private $mimeTypesService; + private $mimeTypeGuesserTag; + + public function __construct(string $mimeTypesService = 'mime_types', string $mimeTypeGuesserTag = 'mime.mime_type_guesser') + { + $this->mimeTypesService = $mimeTypesService; + $this->mimeTypeGuesserTag = $mimeTypeGuesserTag; + } + + /** + * {@inheritdoc} + */ + public function process(ContainerBuilder $container) + { + if ($container->has($this->mimeTypesService)) { + $definition = $container->findDefinition($this->mimeTypesService); + foreach ($container->findTaggedServiceIds($this->mimeTypeGuesserTag, true) as $id => $attributes) { + $definition->addMethodCall('registerGuesser', [new Reference($id)]); + } + } + } +} diff --git a/vendor/symfony/mime/Email.php b/vendor/symfony/mime/Email.php new file mode 100644 index 0000000000000000000000000000000000000000..1bcdc8a1cd3bedc042c6ccd53a2e6cfca58be437 --- /dev/null +++ b/vendor/symfony/mime/Email.php @@ -0,0 +1,593 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime; + +use Symfony\Component\Mime\Exception\LogicException; +use Symfony\Component\Mime\Part\AbstractPart; +use Symfony\Component\Mime\Part\DataPart; +use Symfony\Component\Mime\Part\Multipart\AlternativePart; +use Symfony\Component\Mime\Part\Multipart\MixedPart; +use Symfony\Component\Mime\Part\Multipart\RelatedPart; +use Symfony\Component\Mime\Part\TextPart; + +/** + * @author Fabien Potencier <fabien@symfony.com> + * + * @experimental in 4.3 + */ +class Email extends Message +{ + const PRIORITY_HIGHEST = 1; + const PRIORITY_HIGH = 2; + const PRIORITY_NORMAL = 3; + const PRIORITY_LOW = 4; + const PRIORITY_LOWEST = 5; + + private const PRIORITY_MAP = [ + self::PRIORITY_HIGHEST => 'Highest', + self::PRIORITY_HIGH => 'High', + self::PRIORITY_NORMAL => 'Normal', + self::PRIORITY_LOW => 'Low', + self::PRIORITY_LOWEST => 'Lowest', + ]; + + private $text; + private $textCharset; + private $html; + private $htmlCharset; + private $attachments = []; + + /** + * @return $this + */ + public function subject(string $subject) + { + return $this->setHeaderBody('Text', 'Subject', $subject); + } + + public function getSubject(): ?string + { + return $this->getHeaders()->getHeaderBody('Subject'); + } + + /** + * @return $this + */ + public function date(\DateTimeInterface $dateTime) + { + return $this->setHeaderBody('Date', 'Date', $dateTime); + } + + public function getDate(): ?\DateTimeImmutable + { + return $this->getHeaders()->getHeaderBody('Date'); + } + + /** + * @param Address|string $address + * + * @return $this + */ + public function returnPath($address) + { + return $this->setHeaderBody('Path', 'Return-Path', Address::create($address)); + } + + public function getReturnPath(): ?Address + { + return $this->getHeaders()->getHeaderBody('Return-Path'); + } + + /** + * @param Address|string $address + * + * @return $this + */ + public function sender($address) + { + return $this->setHeaderBody('Mailbox', 'Sender', Address::create($address)); + } + + public function getSender(): ?Address + { + return $this->getHeaders()->getHeaderBody('Sender'); + } + + /** + * @param Address|NamedAddress|string ...$addresses + * + * @return $this + */ + public function addFrom(...$addresses) + { + return $this->addListAddressHeaderBody('From', $addresses); + } + + /** + * @param Address|NamedAddress|string ...$addresses + * + * @return $this + */ + public function from(...$addresses) + { + return $this->setListAddressHeaderBody('From', $addresses); + } + + /** + * @return (Address|NamedAddress)[] + */ + public function getFrom(): array + { + return $this->getHeaders()->getHeaderBody('From') ?: []; + } + + /** + * @param Address|string ...$addresses + * + * @return $this + */ + public function addReplyTo(...$addresses) + { + return $this->addListAddressHeaderBody('Reply-To', $addresses); + } + + /** + * @param Address|string ...$addresses + * + * @return $this + */ + public function replyTo(...$addresses) + { + return $this->setListAddressHeaderBody('Reply-To', $addresses); + } + + /** + * @return Address[] + */ + public function getReplyTo(): array + { + return $this->getHeaders()->getHeaderBody('Reply-To') ?: []; + } + + /** + * @param Address|NamedAddress|string ...$addresses + * + * @return $this + */ + public function addTo(...$addresses) + { + return $this->addListAddressHeaderBody('To', $addresses); + } + + /** + * @param Address|NamedAddress|string ...$addresses + * + * @return $this + */ + public function to(...$addresses) + { + return $this->setListAddressHeaderBody('To', $addresses); + } + + /** + * @return (Address|NamedAddress)[] + */ + public function getTo(): array + { + return $this->getHeaders()->getHeaderBody('To') ?: []; + } + + /** + * @param Address|NamedAddress|string ...$addresses + * + * @return $this + */ + public function addCc(...$addresses) + { + return $this->addListAddressHeaderBody('Cc', $addresses); + } + + /** + * @param Address|string ...$addresses + * + * @return $this + */ + public function cc(...$addresses) + { + return $this->setListAddressHeaderBody('Cc', $addresses); + } + + /** + * @return (Address|NamedAddress)[] + */ + public function getCc(): array + { + return $this->getHeaders()->getHeaderBody('Cc') ?: []; + } + + /** + * @param Address|NamedAddress|string ...$addresses + * + * @return $this + */ + public function addBcc(...$addresses) + { + return $this->addListAddressHeaderBody('Bcc', $addresses); + } + + /** + * @param Address|string ...$addresses + * + * @return $this + */ + public function bcc(...$addresses) + { + return $this->setListAddressHeaderBody('Bcc', $addresses); + } + + /** + * @return (Address|NamedAddress)[] + */ + public function getBcc(): array + { + return $this->getHeaders()->getHeaderBody('Bcc') ?: []; + } + + /** + * Sets the priority of this message. + * + * The value is an integer where 1 is the highest priority and 5 is the lowest. + * + * @return $this + */ + public function priority(int $priority) + { + if ($priority > 5) { + $priority = 5; + } elseif ($priority < 1) { + $priority = 1; + } + + return $this->setHeaderBody('Text', 'X-Priority', sprintf('%d (%s)', $priority, self::PRIORITY_MAP[$priority])); + } + + /** + * Get the priority of this message. + * + * The returned value is an integer where 1 is the highest priority and 5 + * is the lowest. + */ + public function getPriority(): int + { + list($priority) = sscanf($this->getHeaders()->getHeaderBody('X-Priority'), '%[1-5]'); + + return $priority ?? 3; + } + + /** + * @param resource|string $body + * + * @return $this + */ + public function text($body, string $charset = 'utf-8') + { + $this->text = $body; + $this->textCharset = $charset; + + return $this; + } + + /** + * @return resource|string|null + */ + public function getTextBody() + { + return $this->text; + } + + public function getTextCharset(): ?string + { + return $this->textCharset; + } + + /** + * @param resource|string|null $body + * + * @return $this + */ + public function html($body, string $charset = 'utf-8') + { + $this->html = $body; + $this->htmlCharset = $charset; + + return $this; + } + + /** + * @return resource|string|null + */ + public function getHtmlBody() + { + return $this->html; + } + + public function getHtmlCharset(): ?string + { + return $this->htmlCharset; + } + + /** + * @param resource|string $body + * + * @return $this + */ + public function attach($body, string $name = null, string $contentType = null) + { + $this->attachments[] = ['body' => $body, 'name' => $name, 'content-type' => $contentType, 'inline' => false]; + + return $this; + } + + /** + * @return $this + */ + public function attachFromPath(string $path, string $name = null, string $contentType = null) + { + $this->attachments[] = ['path' => $path, 'name' => $name, 'content-type' => $contentType, 'inline' => false]; + + return $this; + } + + /** + * @param resource|string $body + * + * @return $this + */ + public function embed($body, string $name = null, string $contentType = null) + { + $this->attachments[] = ['body' => $body, 'name' => $name, 'content-type' => $contentType, 'inline' => true]; + + return $this; + } + + /** + * @return $this + */ + public function embedFromPath(string $path, string $name = null, string $contentType = null) + { + $this->attachments[] = ['path' => $path, 'name' => $name, 'content-type' => $contentType, 'inline' => true]; + + return $this; + } + + /** + * @return $this + */ + public function attachPart(DataPart $part) + { + $this->attachments[] = ['part' => $part]; + + return $this; + } + + /** + * @return DataPart[] + */ + public function getAttachments(): array + { + $parts = []; + foreach ($this->attachments as $attachment) { + $parts[] = $this->createDataPart($attachment); + } + + return $parts; + } + + public function getBody(): AbstractPart + { + if (null !== $body = parent::getBody()) { + return $body; + } + + return $this->generateBody(); + } + + /** + * Generates an AbstractPart based on the raw body of a message. + * + * The most "complex" part generated by this method is when there is text and HTML bodies + * with related images for the HTML part and some attachments: + * + * multipart/mixed + * | + * |------------> multipart/related + * | | + * | |------------> multipart/alternative + * | | | + * | | ------------> text/plain (with content) + * | | | + * | | ------------> text/html (with content) + * | | + * | ------------> image/png (with content) + * | + * ------------> application/pdf (with content) + */ + private function generateBody(): AbstractPart + { + [$htmlPart, $attachmentParts, $inlineParts] = $this->prepareParts(); + if (null === $this->text && null === $this->html && !$attachmentParts) { + throw new LogicException('A message must have a text or an HTML part or attachments.'); + } + + $part = null === $this->text ? null : new TextPart($this->text, $this->textCharset); + if (null !== $htmlPart) { + if (null !== $part) { + $part = new AlternativePart($part, $htmlPart); + } else { + $part = $htmlPart; + } + } + + if ($inlineParts) { + $part = new RelatedPart($part, ...$inlineParts); + } + + if ($attachmentParts) { + if ($part) { + $part = new MixedPart($part, ...$attachmentParts); + } else { + $part = new MixedPart(...$attachmentParts); + } + } + + return $part; + } + + private function prepareParts(): ?array + { + $names = []; + $htmlPart = null; + $html = $this->html; + if (null !== $this->html) { + if (\is_resource($html)) { + if (stream_get_meta_data($html)['seekable'] ?? false) { + rewind($html); + } + + $html = stream_get_contents($html); + } + $htmlPart = new TextPart($html, $this->htmlCharset, 'html'); + preg_match_all('(<img\s+[^>]*src\s*=\s*(?:([\'"])cid:([^"]+)\\1|cid:([^>\s]+)))i', $html, $names); + $names = array_filter(array_unique(array_merge($names[2], $names[3]))); + } + + $attachmentParts = $inlineParts = []; + foreach ($this->attachments as $attachment) { + foreach ($names as $name) { + if (isset($attachment['part'])) { + continue; + } + if ($name !== $attachment['name']) { + continue; + } + if (isset($inlineParts[$name])) { + continue 2; + } + $attachment['inline'] = true; + $inlineParts[$name] = $part = $this->createDataPart($attachment); + $html = str_replace('cid:'.$name, 'cid:'.$part->getContentId(), $html); + continue 2; + } + $attachmentParts[] = $this->createDataPart($attachment); + } + if (null !== $htmlPart) { + $htmlPart = new TextPart($html, $this->htmlCharset, 'html'); + } + + return [$htmlPart, $attachmentParts, array_values($inlineParts)]; + } + + private function createDataPart(array $attachment): DataPart + { + if (isset($attachment['part'])) { + return $attachment['part']; + } + + if (isset($attachment['body'])) { + $part = new DataPart($attachment['body'], $attachment['name'] ?? null, $attachment['content-type'] ?? null); + } else { + $part = DataPart::fromPath($attachment['path'] ?? '', $attachment['name'] ?? null, $attachment['content-type'] ?? null); + } + if ($attachment['inline']) { + $part->asInline(); + } + + return $part; + } + + /** + * @return $this + */ + private function setHeaderBody(string $type, string $name, $body) + { + $this->getHeaders()->setHeaderBody($type, $name, $body); + + return $this; + } + + private function addListAddressHeaderBody($name, array $addresses) + { + if (!$to = $this->getHeaders()->get($name)) { + return $this->setListAddressHeaderBody($name, $addresses); + } + $to->addAddresses(Address::createArray($addresses)); + + return $this; + } + + private function setListAddressHeaderBody($name, array $addresses) + { + $addresses = Address::createArray($addresses); + $headers = $this->getHeaders(); + if ($to = $headers->get($name)) { + $to->setAddresses($addresses); + } else { + $headers->addMailboxListHeader($name, $addresses); + } + + return $this; + } + + /** + * @internal + */ + public function __serialize(): array + { + if (\is_resource($this->text)) { + if (stream_get_meta_data($this->text)['seekable'] ?? false) { + rewind($this->text); + } + + $this->text = stream_get_contents($this->text); + } + + if (\is_resource($this->html)) { + if (stream_get_meta_data($this->html)['seekable'] ?? false) { + rewind($this->html); + } + + $this->html = stream_get_contents($this->html); + } + + foreach ($this->attachments as $i => $attachment) { + if (isset($attachment['body']) && \is_resource($attachment['body'])) { + if (stream_get_meta_data($attachment['body'])['seekable'] ?? false) { + rewind($attachment['body']); + } + + $this->attachments[$i]['body'] = stream_get_contents($attachment['body']); + } + } + + return [$this->text, $this->textCharset, $this->html, $this->htmlCharset, $this->attachments, parent::__serialize()]; + } + + /** + * @internal + */ + public function __unserialize(array $data): void + { + [$this->text, $this->textCharset, $this->html, $this->htmlCharset, $this->attachments, $parentData] = $data; + + parent::__unserialize($parentData); + } +} diff --git a/vendor/symfony/mime/Encoder/AddressEncoderInterface.php b/vendor/symfony/mime/Encoder/AddressEncoderInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..5d6ea3c66a1ad3dbafeaedb92a4b6fdbd21f991d --- /dev/null +++ b/vendor/symfony/mime/Encoder/AddressEncoderInterface.php @@ -0,0 +1,30 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime\Encoder; + +use Symfony\Component\Mime\Exception\AddressEncoderException; + +/** + * @author Christian Schmidt + * + * @experimental in 4.3 + */ +interface AddressEncoderInterface +{ + /** + * Encodes an email address. + * + * @throws AddressEncoderException if the email cannot be represented in + * the encoding implemented by this class + */ + public function encodeString(string $address): string; +} diff --git a/vendor/symfony/mime/Encoder/Base64ContentEncoder.php b/vendor/symfony/mime/Encoder/Base64ContentEncoder.php new file mode 100644 index 0000000000000000000000000000000000000000..e9c352e20e32d35e256854e3ed58a6f8f9533205 --- /dev/null +++ b/vendor/symfony/mime/Encoder/Base64ContentEncoder.php @@ -0,0 +1,50 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime\Encoder; + +use Symfony\Component\Mime\Exception\RuntimeException; + +/** + * @author Fabien Potencier <fabien@symfony.com> + * + * @experimental in 4.3 + */ +final class Base64ContentEncoder extends Base64Encoder implements ContentEncoderInterface +{ + public function encodeByteStream($stream, int $maxLineLength = 0): iterable + { + if (!\is_resource($stream)) { + throw new \TypeError(sprintf('Method "%s" takes a stream as a first argument.', __METHOD__)); + } + + $filter = stream_filter_append($stream, 'convert.base64-encode', \STREAM_FILTER_READ, [ + 'line-length' => 0 >= $maxLineLength || 76 < $maxLineLength ? 76 : $maxLineLength, + 'line-break-chars' => "\r\n", + ]); + if (!\is_resource($filter)) { + throw new RuntimeException('Unable to set the base64 content encoder to the filter.'); + } + + if (stream_get_meta_data($stream)['seekable'] ?? false) { + rewind($stream); + } + while (!feof($stream)) { + yield fread($stream, 8192); + } + stream_filter_remove($filter); + } + + public function getName(): string + { + return 'base64'; + } +} diff --git a/vendor/symfony/mime/Encoder/Base64Encoder.php b/vendor/symfony/mime/Encoder/Base64Encoder.php new file mode 100644 index 0000000000000000000000000000000000000000..25dae670b1e137e97d4d1a376792c0a56fab129e --- /dev/null +++ b/vendor/symfony/mime/Encoder/Base64Encoder.php @@ -0,0 +1,43 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime\Encoder; + +/** + * @author Chris Corbyn + * + * @experimental in 4.3 + */ +class Base64Encoder implements EncoderInterface +{ + /** + * Takes an unencoded string and produces a Base64 encoded string from it. + * + * Base64 encoded strings have a maximum line length of 76 characters. + * If the first line needs to be shorter, indicate the difference with + * $firstLineOffset. + */ + public function encodeString(string $string, ?string $charset = 'utf-8', int $firstLineOffset = 0, int $maxLineLength = 0): string + { + if (0 >= $maxLineLength || 76 < $maxLineLength) { + $maxLineLength = 76; + } + + $encodedString = base64_encode($string); + $firstLine = ''; + if (0 !== $firstLineOffset) { + $firstLine = substr($encodedString, 0, $maxLineLength - $firstLineOffset)."\r\n"; + $encodedString = substr($encodedString, $maxLineLength - $firstLineOffset); + } + + return $firstLine.trim(chunk_split($encodedString, $maxLineLength, "\r\n")); + } +} diff --git a/vendor/symfony/mime/Encoder/Base64MimeHeaderEncoder.php b/vendor/symfony/mime/Encoder/Base64MimeHeaderEncoder.php new file mode 100644 index 0000000000000000000000000000000000000000..8baee5b02ebb2c8d5349b4ed5a801347b3be0ca3 --- /dev/null +++ b/vendor/symfony/mime/Encoder/Base64MimeHeaderEncoder.php @@ -0,0 +1,45 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime\Encoder; + +/** + * @author Chris Corbyn + * + * @experimental in 4.3 + */ +final class Base64MimeHeaderEncoder extends Base64Encoder implements MimeHeaderEncoderInterface +{ + public function getName(): string + { + return 'B'; + } + + /** + * Takes an unencoded string and produces a Base64 encoded string from it. + * + * If the charset is iso-2022-jp, it uses mb_encode_mimeheader instead of + * default encodeString, otherwise pass to the parent method. + */ + public function encodeString(string $string, ?string $charset = 'utf-8', int $firstLineOffset = 0, int $maxLineLength = 0): string + { + if ('iso-2022-jp' === strtolower($charset)) { + $old = mb_internal_encoding(); + mb_internal_encoding('utf-8'); + $newstring = mb_encode_mimeheader($string, 'iso-2022-jp', $this->getName(), "\r\n"); + mb_internal_encoding($old); + + return $newstring; + } + + return parent::encodeString($string, $charset, $firstLineOffset, $maxLineLength); + } +} diff --git a/vendor/symfony/mime/Encoder/ContentEncoderInterface.php b/vendor/symfony/mime/Encoder/ContentEncoderInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..b44e1a4a71332c4f625c3306a55acd1521349a3f --- /dev/null +++ b/vendor/symfony/mime/Encoder/ContentEncoderInterface.php @@ -0,0 +1,32 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime\Encoder; + +/** + * @author Chris Corbyn + * + * @experimental in 4.3 + */ +interface ContentEncoderInterface extends EncoderInterface +{ + /** + * Encodes the stream to a Generator. + * + * @param resource $stream + */ + public function encodeByteStream($stream, int $maxLineLength = 0): iterable; + + /** + * Gets the MIME name of this content encoding scheme. + */ + public function getName(): string; +} diff --git a/vendor/symfony/mime/Encoder/EightBitContentEncoder.php b/vendor/symfony/mime/Encoder/EightBitContentEncoder.php new file mode 100644 index 0000000000000000000000000000000000000000..94b838ce603f57df97a06db2112b5ae2e6e628cc --- /dev/null +++ b/vendor/symfony/mime/Encoder/EightBitContentEncoder.php @@ -0,0 +1,37 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime\Encoder; + +/** + * @author Fabien Potencier <fabien@symfony.com> + * + * @experimental in 4.3 + */ +final class EightBitContentEncoder implements ContentEncoderInterface +{ + public function encodeByteStream($stream, int $maxLineLength = 0): iterable + { + while (!feof($stream)) { + yield fread($stream, 16372); + } + } + + public function getName(): string + { + return '8bit'; + } + + public function encodeString(string $string, ?string $charset = 'utf-8', int $firstLineOffset = 0, int $maxLineLength = 0): string + { + return $string; + } +} diff --git a/vendor/symfony/mime/Encoder/EncoderInterface.php b/vendor/symfony/mime/Encoder/EncoderInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..3c2ef198e5873741007121b2886509e67f92c01f --- /dev/null +++ b/vendor/symfony/mime/Encoder/EncoderInterface.php @@ -0,0 +1,28 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime\Encoder; + +/** + * @author Chris Corbyn + * + * @experimental in 4.3 + */ +interface EncoderInterface +{ + /** + * Encode a given string to produce an encoded string. + * + * @param int $firstLineOffset if first line needs to be shorter + * @param int $maxLineLength - 0 indicates the default length for this encoding + */ + public function encodeString(string $string, ?string $charset = 'utf-8', int $firstLineOffset = 0, int $maxLineLength = 0): string; +} diff --git a/vendor/symfony/mime/Encoder/IdnAddressEncoder.php b/vendor/symfony/mime/Encoder/IdnAddressEncoder.php new file mode 100644 index 0000000000000000000000000000000000000000..8936047ceb05c38e9e47d87877d1204059d75889 --- /dev/null +++ b/vendor/symfony/mime/Encoder/IdnAddressEncoder.php @@ -0,0 +1,56 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime\Encoder; + +use Symfony\Component\Mime\Exception\AddressEncoderException; + +/** + * An IDN email address encoder. + * + * Encodes the domain part of an address using IDN. This is compatible will all + * SMTP servers. + * + * This encoder does not support email addresses with non-ASCII characters in + * local-part (the substring before @). To send to such addresses, use + * Utf8AddressEncoder together with SmtpUtf8Handler. Your outbound SMTP server must support + * the SMTPUTF8 extension. + * + * @author Christian Schmidt + * + * @experimental in 4.3 + */ +final class IdnAddressEncoder implements AddressEncoderInterface +{ + /** + * Encodes the domain part of an address using IDN. + * + * @throws AddressEncoderException If local-part contains non-ASCII characters + */ + public function encodeString(string $address): string + { + $i = strrpos($address, '@'); + if (false !== $i) { + $local = substr($address, 0, $i); + $domain = substr($address, $i + 1); + + if (preg_match('/[^\x00-\x7F]/', $local)) { + throw new AddressEncoderException(sprintf('Non-ASCII characters not supported in local-part os "%s".', $address)); + } + + if (preg_match('/[^\x00-\x7F]/', $domain)) { + $address = sprintf('%s@%s', $local, idn_to_ascii($domain, 0, INTL_IDNA_VARIANT_UTS46)); + } + } + + return $address; + } +} diff --git a/vendor/symfony/mime/Encoder/MimeHeaderEncoderInterface.php b/vendor/symfony/mime/Encoder/MimeHeaderEncoderInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..f5756650caa8be311bc909d426ee9cae4b4569b1 --- /dev/null +++ b/vendor/symfony/mime/Encoder/MimeHeaderEncoderInterface.php @@ -0,0 +1,25 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime\Encoder; + +/** + * @author Chris Corbyn + * + * @experimental in 4.3 + */ +interface MimeHeaderEncoderInterface +{ + /** + * Get the MIME name of this content encoding scheme. + */ + public function getName(): string; +} diff --git a/vendor/symfony/mime/Encoder/QpContentEncoder.php b/vendor/symfony/mime/Encoder/QpContentEncoder.php new file mode 100644 index 0000000000000000000000000000000000000000..ef2de46f0bb85a3d25156136f9082ac3c7fbc38a --- /dev/null +++ b/vendor/symfony/mime/Encoder/QpContentEncoder.php @@ -0,0 +1,66 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime\Encoder; + +/** + * @author Lars Strojny + * + * @experimental in 4.3 + */ +final class QpContentEncoder implements ContentEncoderInterface +{ + public function encodeByteStream($stream, int $maxLineLength = 0): iterable + { + if (!\is_resource($stream)) { + throw new \TypeError(sprintf('Method "%s" takes a stream as a first argument.', __METHOD__)); + } + + // we don't use PHP stream filters here as the content should be small enough + if (stream_get_meta_data($stream)['seekable'] ?? false) { + rewind($stream); + } + + yield $this->encodeString(stream_get_contents($stream), 'utf-8', 0, $maxLineLength); + } + + public function getName(): string + { + return 'quoted-printable'; + } + + public function encodeString(string $string, ?string $charset = 'utf-8', int $firstLineOffset = 0, int $maxLineLength = 0): string + { + return $this->standardize(quoted_printable_encode($string)); + } + + /** + * Make sure CRLF is correct and HT/SPACE are in valid places. + */ + private function standardize(string $string): string + { + // transform CR or LF to CRLF + $string = preg_replace('~=0D(?!=0A)|(?<!=0D)=0A~', '=0D=0A', $string); + // transform =0D=0A to CRLF + $string = str_replace(["\t=0D=0A", ' =0D=0A', '=0D=0A'], ["=09\r\n", "=20\r\n", "\r\n"], $string); + + switch (\ord(substr($string, -1))) { + case 0x09: + $string = substr_replace($string, '=09', -1); + break; + case 0x20: + $string = substr_replace($string, '=20', -1); + break; + } + + return $string; + } +} diff --git a/vendor/symfony/mime/Encoder/QpEncoder.php b/vendor/symfony/mime/Encoder/QpEncoder.php new file mode 100644 index 0000000000000000000000000000000000000000..4ffbaed78e9e43be1c3230d39e3c7bc5eac75883 --- /dev/null +++ b/vendor/symfony/mime/Encoder/QpEncoder.php @@ -0,0 +1,197 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime\Encoder; + +use Symfony\Component\Mime\CharacterStream; + +/** + * @author Chris Corbyn + * + * @experimental in 4.3 + */ +class QpEncoder implements EncoderInterface +{ + /** + * Pre-computed QP for HUGE optimization. + */ + private static $qpMap = [ + 0 => '=00', 1 => '=01', 2 => '=02', 3 => '=03', 4 => '=04', + 5 => '=05', 6 => '=06', 7 => '=07', 8 => '=08', 9 => '=09', + 10 => '=0A', 11 => '=0B', 12 => '=0C', 13 => '=0D', 14 => '=0E', + 15 => '=0F', 16 => '=10', 17 => '=11', 18 => '=12', 19 => '=13', + 20 => '=14', 21 => '=15', 22 => '=16', 23 => '=17', 24 => '=18', + 25 => '=19', 26 => '=1A', 27 => '=1B', 28 => '=1C', 29 => '=1D', + 30 => '=1E', 31 => '=1F', 32 => '=20', 33 => '=21', 34 => '=22', + 35 => '=23', 36 => '=24', 37 => '=25', 38 => '=26', 39 => '=27', + 40 => '=28', 41 => '=29', 42 => '=2A', 43 => '=2B', 44 => '=2C', + 45 => '=2D', 46 => '=2E', 47 => '=2F', 48 => '=30', 49 => '=31', + 50 => '=32', 51 => '=33', 52 => '=34', 53 => '=35', 54 => '=36', + 55 => '=37', 56 => '=38', 57 => '=39', 58 => '=3A', 59 => '=3B', + 60 => '=3C', 61 => '=3D', 62 => '=3E', 63 => '=3F', 64 => '=40', + 65 => '=41', 66 => '=42', 67 => '=43', 68 => '=44', 69 => '=45', + 70 => '=46', 71 => '=47', 72 => '=48', 73 => '=49', 74 => '=4A', + 75 => '=4B', 76 => '=4C', 77 => '=4D', 78 => '=4E', 79 => '=4F', + 80 => '=50', 81 => '=51', 82 => '=52', 83 => '=53', 84 => '=54', + 85 => '=55', 86 => '=56', 87 => '=57', 88 => '=58', 89 => '=59', + 90 => '=5A', 91 => '=5B', 92 => '=5C', 93 => '=5D', 94 => '=5E', + 95 => '=5F', 96 => '=60', 97 => '=61', 98 => '=62', 99 => '=63', + 100 => '=64', 101 => '=65', 102 => '=66', 103 => '=67', 104 => '=68', + 105 => '=69', 106 => '=6A', 107 => '=6B', 108 => '=6C', 109 => '=6D', + 110 => '=6E', 111 => '=6F', 112 => '=70', 113 => '=71', 114 => '=72', + 115 => '=73', 116 => '=74', 117 => '=75', 118 => '=76', 119 => '=77', + 120 => '=78', 121 => '=79', 122 => '=7A', 123 => '=7B', 124 => '=7C', + 125 => '=7D', 126 => '=7E', 127 => '=7F', 128 => '=80', 129 => '=81', + 130 => '=82', 131 => '=83', 132 => '=84', 133 => '=85', 134 => '=86', + 135 => '=87', 136 => '=88', 137 => '=89', 138 => '=8A', 139 => '=8B', + 140 => '=8C', 141 => '=8D', 142 => '=8E', 143 => '=8F', 144 => '=90', + 145 => '=91', 146 => '=92', 147 => '=93', 148 => '=94', 149 => '=95', + 150 => '=96', 151 => '=97', 152 => '=98', 153 => '=99', 154 => '=9A', + 155 => '=9B', 156 => '=9C', 157 => '=9D', 158 => '=9E', 159 => '=9F', + 160 => '=A0', 161 => '=A1', 162 => '=A2', 163 => '=A3', 164 => '=A4', + 165 => '=A5', 166 => '=A6', 167 => '=A7', 168 => '=A8', 169 => '=A9', + 170 => '=AA', 171 => '=AB', 172 => '=AC', 173 => '=AD', 174 => '=AE', + 175 => '=AF', 176 => '=B0', 177 => '=B1', 178 => '=B2', 179 => '=B3', + 180 => '=B4', 181 => '=B5', 182 => '=B6', 183 => '=B7', 184 => '=B8', + 185 => '=B9', 186 => '=BA', 187 => '=BB', 188 => '=BC', 189 => '=BD', + 190 => '=BE', 191 => '=BF', 192 => '=C0', 193 => '=C1', 194 => '=C2', + 195 => '=C3', 196 => '=C4', 197 => '=C5', 198 => '=C6', 199 => '=C7', + 200 => '=C8', 201 => '=C9', 202 => '=CA', 203 => '=CB', 204 => '=CC', + 205 => '=CD', 206 => '=CE', 207 => '=CF', 208 => '=D0', 209 => '=D1', + 210 => '=D2', 211 => '=D3', 212 => '=D4', 213 => '=D5', 214 => '=D6', + 215 => '=D7', 216 => '=D8', 217 => '=D9', 218 => '=DA', 219 => '=DB', + 220 => '=DC', 221 => '=DD', 222 => '=DE', 223 => '=DF', 224 => '=E0', + 225 => '=E1', 226 => '=E2', 227 => '=E3', 228 => '=E4', 229 => '=E5', + 230 => '=E6', 231 => '=E7', 232 => '=E8', 233 => '=E9', 234 => '=EA', + 235 => '=EB', 236 => '=EC', 237 => '=ED', 238 => '=EE', 239 => '=EF', + 240 => '=F0', 241 => '=F1', 242 => '=F2', 243 => '=F3', 244 => '=F4', + 245 => '=F5', 246 => '=F6', 247 => '=F7', 248 => '=F8', 249 => '=F9', + 250 => '=FA', 251 => '=FB', 252 => '=FC', 253 => '=FD', 254 => '=FE', + 255 => '=FF', + ]; + + private static $safeMapShare = []; + + /** + * A map of non-encoded ascii characters. + * + * @var string[] + * + * @internal + */ + protected $safeMap = []; + + public function __construct() + { + $id = \get_class($this); + if (!isset(self::$safeMapShare[$id])) { + $this->initSafeMap(); + self::$safeMapShare[$id] = $this->safeMap; + } else { + $this->safeMap = self::$safeMapShare[$id]; + } + } + + protected function initSafeMap(): void + { + foreach (array_merge([0x09, 0x20], range(0x21, 0x3C), range(0x3E, 0x7E)) as $byte) { + $this->safeMap[$byte] = \chr($byte); + } + } + + /** + * {@inheritdoc} + * + * Takes an unencoded string and produces a QP encoded string from it. + * + * QP encoded strings have a maximum line length of 76 characters. + * If the first line needs to be shorter, indicate the difference with + * $firstLineOffset. + */ + public function encodeString(string $string, ?string $charset = 'utf-8', int $firstLineOffset = 0, int $maxLineLength = 0): string + { + if ($maxLineLength > 76 || $maxLineLength <= 0) { + $maxLineLength = 76; + } + + $thisLineLength = $maxLineLength - $firstLineOffset; + + $lines = []; + $lNo = 0; + $lines[$lNo] = ''; + $currentLine = &$lines[$lNo++]; + $size = $lineLen = 0; + $charStream = new CharacterStream($string, $charset); + + // Fetching more than 4 chars at one is slower, as is fetching fewer bytes + // Conveniently 4 chars is the UTF-8 safe number since UTF-8 has up to 6 + // bytes per char and (6 * 4 * 3 = 72 chars per line) * =NN is 3 bytes + while (null !== $bytes = $charStream->readBytes(4)) { + $enc = $this->encodeByteSequence($bytes, $size); + + $i = strpos($enc, '=0D=0A'); + $newLineLength = $lineLen + (false === $i ? $size : $i); + + if ($currentLine && $newLineLength >= $thisLineLength) { + $lines[$lNo] = ''; + $currentLine = &$lines[$lNo++]; + $thisLineLength = $maxLineLength; + $lineLen = 0; + } + + $currentLine .= $enc; + + if (false === $i) { + $lineLen += $size; + } else { + // 6 is the length of '=0D=0A'. + $lineLen = $size - strrpos($enc, '=0D=0A') - 6; + } + } + + return $this->standardize(implode("=\r\n", $lines)); + } + + /** + * Encode the given byte array into a verbatim QP form. + */ + private function encodeByteSequence(array $bytes, int &$size): string + { + $ret = ''; + $size = 0; + foreach ($bytes as $b) { + if (isset($this->safeMap[$b])) { + $ret .= $this->safeMap[$b]; + ++$size; + } else { + $ret .= self::$qpMap[$b]; + $size += 3; + } + } + + return $ret; + } + + /** + * Make sure CRLF is correct and HT/SPACE are in valid places. + */ + private function standardize(string $string): string + { + $string = str_replace(["\t=0D=0A", ' =0D=0A', '=0D=0A'], ["=09\r\n", "=20\r\n", "\r\n"], $string); + switch ($end = \ord(substr($string, -1))) { + case 0x09: + case 0x20: + $string = substr_replace($string, self::$qpMap[$end], -1); + } + + return $string; + } +} diff --git a/vendor/symfony/mime/Encoder/QpMimeHeaderEncoder.php b/vendor/symfony/mime/Encoder/QpMimeHeaderEncoder.php new file mode 100644 index 0000000000000000000000000000000000000000..0413959587bcb46f32f7d87a9d470432fcf8ca5f --- /dev/null +++ b/vendor/symfony/mime/Encoder/QpMimeHeaderEncoder.php @@ -0,0 +1,42 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime\Encoder; + +/** + * @author Chris Corbyn + * + * @experimental in 4.3 + */ +final class QpMimeHeaderEncoder extends QpEncoder implements MimeHeaderEncoderInterface +{ + protected function initSafeMap(): void + { + foreach (array_merge( + range(0x61, 0x7A), range(0x41, 0x5A), + range(0x30, 0x39), [0x20, 0x21, 0x2A, 0x2B, 0x2D, 0x2F] + ) as $byte) { + $this->safeMap[$byte] = \chr($byte); + } + } + + public function getName(): string + { + return 'Q'; + } + + public function encodeString(string $string, ?string $charset = 'utf-8', int $firstLineOffset = 0, int $maxLineLength = 0): string + { + return str_replace([' ', '=20', "=\r\n"], ['_', '_', "\r\n"], + parent::encodeString($string, $charset, $firstLineOffset, $maxLineLength) + ); + } +} diff --git a/vendor/symfony/mime/Encoder/Rfc2231Encoder.php b/vendor/symfony/mime/Encoder/Rfc2231Encoder.php new file mode 100644 index 0000000000000000000000000000000000000000..4743a7217c95fa131a4ef4ff24129b73e47959d6 --- /dev/null +++ b/vendor/symfony/mime/Encoder/Rfc2231Encoder.php @@ -0,0 +1,52 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime\Encoder; + +use Symfony\Component\Mime\CharacterStream; + +/** + * @author Chris Corbyn + * + * @experimental in 4.3 + */ +final class Rfc2231Encoder implements EncoderInterface +{ + /** + * Takes an unencoded string and produces a string encoded according to RFC 2231 from it. + */ + public function encodeString(string $string, ?string $charset = 'utf-8', int $firstLineOffset = 0, int $maxLineLength = 0): string + { + $lines = []; + $lineCount = 0; + $lines[] = ''; + $currentLine = &$lines[$lineCount++]; + + if (0 >= $maxLineLength) { + $maxLineLength = 75; + } + + $charStream = new CharacterStream($string, $charset); + $thisLineLength = $maxLineLength - $firstLineOffset; + + while (null !== $char = $charStream->read(4)) { + $encodedChar = rawurlencode($char); + if (0 !== \strlen($currentLine) && \strlen($currentLine.$encodedChar) > $thisLineLength) { + $lines[] = ''; + $currentLine = &$lines[$lineCount++]; + $thisLineLength = $maxLineLength; + } + $currentLine .= $encodedChar; + } + + return implode("\r\n", $lines); + } +} diff --git a/vendor/symfony/mime/Exception/AddressEncoderException.php b/vendor/symfony/mime/Exception/AddressEncoderException.php new file mode 100644 index 0000000000000000000000000000000000000000..73ef7f32228f38095aa5283cb8911dad723039a9 --- /dev/null +++ b/vendor/symfony/mime/Exception/AddressEncoderException.php @@ -0,0 +1,21 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime\Exception; + +/** + * @author Fabien Potencier <fabien@symfony.com> + * + * @experimental in 4.3 + */ +class AddressEncoderException extends RfcComplianceException +{ +} diff --git a/vendor/symfony/http-kernel/Tests/Fixtures/ExtensionAbsentBundle/ExtensionAbsentBundle.php b/vendor/symfony/mime/Exception/ExceptionInterface.php similarity index 57% rename from vendor/symfony/http-kernel/Tests/Fixtures/ExtensionAbsentBundle/ExtensionAbsentBundle.php rename to vendor/symfony/mime/Exception/ExceptionInterface.php index c8bfd36e662f5e103a33ccfca0ad264bd53d077d..7dbcdc72b072c5dd5dbb0f5143e08836b401665b 100644 --- a/vendor/symfony/http-kernel/Tests/Fixtures/ExtensionAbsentBundle/ExtensionAbsentBundle.php +++ b/vendor/symfony/mime/Exception/ExceptionInterface.php @@ -9,10 +9,13 @@ * file that was distributed with this source code. */ -namespace Symfony\Component\HttpKernel\Tests\Fixtures\ExtensionAbsentBundle; +namespace Symfony\Component\Mime\Exception; -use Symfony\Component\HttpKernel\Bundle\Bundle; - -class ExtensionAbsentBundle extends Bundle +/** + * @author Fabien Potencier <fabien@symfony.com> + * + * @experimental in 4.3 + */ +interface ExceptionInterface extends \Throwable { } diff --git a/vendor/symfony/mime/Exception/InvalidArgumentException.php b/vendor/symfony/mime/Exception/InvalidArgumentException.php new file mode 100644 index 0000000000000000000000000000000000000000..59d04e234e75028a3578f0e28a35eec3399a9128 --- /dev/null +++ b/vendor/symfony/mime/Exception/InvalidArgumentException.php @@ -0,0 +1,21 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime\Exception; + +/** + * @author Fabien Potencier <fabien@symfony.com> + * + * @experimental in 4.3 + */ +class InvalidArgumentException extends \InvalidArgumentException implements ExceptionInterface +{ +} diff --git a/vendor/symfony/mime/Exception/LogicException.php b/vendor/symfony/mime/Exception/LogicException.php new file mode 100644 index 0000000000000000000000000000000000000000..07cb0440837f6e0a09629d1b6e235712ad7f4a97 --- /dev/null +++ b/vendor/symfony/mime/Exception/LogicException.php @@ -0,0 +1,21 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime\Exception; + +/** + * @author Fabien Potencier <fabien@symfony.com> + * + * @experimental in 4.3 + */ +class LogicException extends \LogicException implements ExceptionInterface +{ +} diff --git a/vendor/symfony/mime/Exception/RfcComplianceException.php b/vendor/symfony/mime/Exception/RfcComplianceException.php new file mode 100644 index 0000000000000000000000000000000000000000..5dc4cf5f575537208c23f7796a47fdf00c074c53 --- /dev/null +++ b/vendor/symfony/mime/Exception/RfcComplianceException.php @@ -0,0 +1,21 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime\Exception; + +/** + * @author Fabien Potencier <fabien@symfony.com> + * + * @experimental in 4.3 + */ +class RfcComplianceException extends \InvalidArgumentException implements ExceptionInterface +{ +} diff --git a/vendor/symfony/mime/Exception/RuntimeException.php b/vendor/symfony/mime/Exception/RuntimeException.php new file mode 100644 index 0000000000000000000000000000000000000000..84b11fba6ffae51635119a6d27ee6aee7dd0ded0 --- /dev/null +++ b/vendor/symfony/mime/Exception/RuntimeException.php @@ -0,0 +1,21 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime\Exception; + +/** + * @author Fabien Potencier <fabien@symfony.com> + * + * @experimental in 4.3 + */ +class RuntimeException extends \RuntimeException implements ExceptionInterface +{ +} diff --git a/vendor/symfony/mime/FileBinaryMimeTypeGuesser.php b/vendor/symfony/mime/FileBinaryMimeTypeGuesser.php new file mode 100644 index 0000000000000000000000000000000000000000..a25ebe4d5cdcd64fa6bf3ebce1ebd4ed99b4d6f7 --- /dev/null +++ b/vendor/symfony/mime/FileBinaryMimeTypeGuesser.php @@ -0,0 +1,95 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime; + +use Symfony\Component\Mime\Exception\InvalidArgumentException; +use Symfony\Component\Mime\Exception\LogicException; + +/** + * Guesses the MIME type with the binary "file" (only available on *nix). + * + * @author Bernhard Schussek <bschussek@gmail.com> + * + * @experimental in 4.3 + */ +class FileBinaryMimeTypeGuesser implements MimeTypeGuesserInterface +{ + private $cmd; + + /** + * The $cmd pattern must contain a "%s" string that will be replaced + * with the file name to guess. + * + * The command output must start with the MIME type of the file. + * + * @param string $cmd The command to run to get the MIME type of a file + */ + public function __construct(string $cmd = 'file -b --mime %s 2>/dev/null') + { + $this->cmd = $cmd; + } + + /** + * {@inheritdoc} + */ + public function isGuesserSupported(): bool + { + static $supported = null; + + if (null !== $supported) { + return $supported; + } + + if ('\\' === \DIRECTORY_SEPARATOR || !\function_exists('passthru') || !\function_exists('escapeshellarg')) { + return $supported = false; + } + + ob_start(); + passthru('command -v file', $exitStatus); + $binPath = trim(ob_get_clean()); + + return $supported = 0 === $exitStatus && '' !== $binPath; + } + + /** + * {@inheritdoc} + */ + public function guessMimeType(string $path): ?string + { + if (!is_file($path) || !is_readable($path)) { + throw new InvalidArgumentException(sprintf('The "%s" file does not exist or is not readable.', $path)); + } + + if (!$this->isGuesserSupported()) { + throw new LogicException(sprintf('The "%s" guesser is not supported.', __CLASS__)); + } + + ob_start(); + + // need to use --mime instead of -i. see #6641 + passthru(sprintf($this->cmd, escapeshellarg($path)), $return); + if ($return > 0) { + ob_end_clean(); + + return null; + } + + $type = trim(ob_get_clean()); + + if (!preg_match('#^([a-z0-9\-]+/[a-z0-9\-\.]+)#i', $type, $match)) { + // it's not a type, but an error message + return null; + } + + return $match[1]; + } +} diff --git a/vendor/symfony/mime/FileinfoMimeTypeGuesser.php b/vendor/symfony/mime/FileinfoMimeTypeGuesser.php new file mode 100644 index 0000000000000000000000000000000000000000..81c62ee2013ac73d0c1083a3fae7cc55bcf275f5 --- /dev/null +++ b/vendor/symfony/mime/FileinfoMimeTypeGuesser.php @@ -0,0 +1,65 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime; + +use Symfony\Component\Mime\Exception\InvalidArgumentException; +use Symfony\Component\Mime\Exception\LogicException; + +/** + * Guesses the MIME type using the PECL extension FileInfo. + * + * @author Bernhard Schussek <bschussek@gmail.com> + * + * @experimental in 4.3 + */ +class FileinfoMimeTypeGuesser implements MimeTypeGuesserInterface +{ + private $magicFile; + + /** + * @param string $magicFile A magic file to use with the finfo instance + * + * @see http://www.php.net/manual/en/function.finfo-open.php + */ + public function __construct(string $magicFile = null) + { + $this->magicFile = $magicFile; + } + + /** + * {@inheritdoc} + */ + public function isGuesserSupported(): bool + { + return \function_exists('finfo_open'); + } + + /** + * {@inheritdoc} + */ + public function guessMimeType(string $path): ?string + { + if (!is_file($path) || !is_readable($path)) { + throw new InvalidArgumentException(sprintf('The "%s" file does not exist or is not readable.', $path)); + } + + if (!$this->isGuesserSupported()) { + throw new LogicException(sprintf('The "%s" guesser is not supported.', __CLASS__)); + } + + if (false === $finfo = new \finfo(FILEINFO_MIME_TYPE, $this->magicFile)) { + return null; + } + + return $finfo->file($path); + } +} diff --git a/vendor/symfony/mime/Header/AbstractHeader.php b/vendor/symfony/mime/Header/AbstractHeader.php new file mode 100644 index 0000000000000000000000000000000000000000..517ee8dfb23812657bfdda6b5f2035c125fa92a5 --- /dev/null +++ b/vendor/symfony/mime/Header/AbstractHeader.php @@ -0,0 +1,281 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime\Header; + +use Symfony\Component\Mime\Encoder\QpMimeHeaderEncoder; + +/** + * An abstract base MIME Header. + * + * @author Chris Corbyn + * + * @experimental in 4.3 + */ +abstract class AbstractHeader implements HeaderInterface +{ + const PHRASE_PATTERN = '(?:(?:(?:(?:(?:(?:(?:[ \t]*(?:\r\n))?[ \t])?(\((?:(?:(?:[ \t]*(?:\r\n))?[ \t])|(?:(?:[\x01-\x08\x0B\x0C\x0E-\x19\x7F]|[\x21-\x27\x2A-\x5B\x5D-\x7E])|(?:\\[\x00-\x08\x0B\x0C\x0E-\x7F])|(?1)))*(?:(?:[ \t]*(?:\r\n))?[ \t])?\)))*(?:(?:(?:(?:[ \t]*(?:\r\n))?[ \t])?(\((?:(?:(?:[ \t]*(?:\r\n))?[ \t])|(?:(?:[\x01-\x08\x0B\x0C\x0E-\x19\x7F]|[\x21-\x27\x2A-\x5B\x5D-\x7E])|(?:\\[\x00-\x08\x0B\x0C\x0E-\x7F])|(?1)))*(?:(?:[ \t]*(?:\r\n))?[ \t])?\)))|(?:(?:[ \t]*(?:\r\n))?[ \t])))?[a-zA-Z0-9!#\$%&\'\*\+\-\/=\?\^_`\{\}\|~]+(?:(?:(?:(?:[ \t]*(?:\r\n))?[ \t])?(\((?:(?:(?:[ \t]*(?:\r\n))?[ \t])|(?:(?:[\x01-\x08\x0B\x0C\x0E-\x19\x7F]|[\x21-\x27\x2A-\x5B\x5D-\x7E])|(?:\\[\x00-\x08\x0B\x0C\x0E-\x7F])|(?1)))*(?:(?:[ \t]*(?:\r\n))?[ \t])?\)))*(?:(?:(?:(?:[ \t]*(?:\r\n))?[ \t])?(\((?:(?:(?:[ \t]*(?:\r\n))?[ \t])|(?:(?:[\x01-\x08\x0B\x0C\x0E-\x19\x7F]|[\x21-\x27\x2A-\x5B\x5D-\x7E])|(?:\\[\x00-\x08\x0B\x0C\x0E-\x7F])|(?1)))*(?:(?:[ \t]*(?:\r\n))?[ \t])?\)))|(?:(?:[ \t]*(?:\r\n))?[ \t])))?)|(?:(?:(?:(?:(?:[ \t]*(?:\r\n))?[ \t])?(\((?:(?:(?:[ \t]*(?:\r\n))?[ \t])|(?:(?:[\x01-\x08\x0B\x0C\x0E-\x19\x7F]|[\x21-\x27\x2A-\x5B\x5D-\x7E])|(?:\\[\x00-\x08\x0B\x0C\x0E-\x7F])|(?1)))*(?:(?:[ \t]*(?:\r\n))?[ \t])?\)))*(?:(?:(?:(?:[ \t]*(?:\r\n))?[ \t])?(\((?:(?:(?:[ \t]*(?:\r\n))?[ \t])|(?:(?:[\x01-\x08\x0B\x0C\x0E-\x19\x7F]|[\x21-\x27\x2A-\x5B\x5D-\x7E])|(?:\\[\x00-\x08\x0B\x0C\x0E-\x7F])|(?1)))*(?:(?:[ \t]*(?:\r\n))?[ \t])?\)))|(?:(?:[ \t]*(?:\r\n))?[ \t])))?"((?:(?:[ \t]*(?:\r\n))?[ \t])?(?:(?:[\x01-\x08\x0B\x0C\x0E-\x19\x7F]|[\x21\x23-\x5B\x5D-\x7E])|(?:\\[\x00-\x08\x0B\x0C\x0E-\x7F])))*(?:(?:[ \t]*(?:\r\n))?[ \t])?"(?:(?:(?:(?:[ \t]*(?:\r\n))?[ \t])?(\((?:(?:(?:[ \t]*(?:\r\n))?[ \t])|(?:(?:[\x01-\x08\x0B\x0C\x0E-\x19\x7F]|[\x21-\x27\x2A-\x5B\x5D-\x7E])|(?:\\[\x00-\x08\x0B\x0C\x0E-\x7F])|(?1)))*(?:(?:[ \t]*(?:\r\n))?[ \t])?\)))*(?:(?:(?:(?:[ \t]*(?:\r\n))?[ \t])?(\((?:(?:(?:[ \t]*(?:\r\n))?[ \t])|(?:(?:[\x01-\x08\x0B\x0C\x0E-\x19\x7F]|[\x21-\x27\x2A-\x5B\x5D-\x7E])|(?:\\[\x00-\x08\x0B\x0C\x0E-\x7F])|(?1)))*(?:(?:[ \t]*(?:\r\n))?[ \t])?\)))|(?:(?:[ \t]*(?:\r\n))?[ \t])))?))+?)'; + + private static $encoder; + + private $name; + private $lineLength = 76; + private $lang; + private $charset = 'utf-8'; + + public function __construct(string $name) + { + $this->name = $name; + } + + public function setCharset(string $charset) + { + $this->charset = $charset; + } + + public function getCharset(): ?string + { + return $this->charset; + } + + /** + * Set the language used in this Header. + * + * For example, for US English, 'en-us'. + */ + public function setLanguage(string $lang) + { + $this->lang = $lang; + } + + public function getLanguage(): ?string + { + return $this->lang; + } + + public function getName(): string + { + return $this->name; + } + + public function setMaxLineLength(int $lineLength) + { + $this->lineLength = $lineLength; + } + + public function getMaxLineLength(): int + { + return $this->lineLength; + } + + public function toString(): string + { + return $this->tokensToString($this->toTokens()); + } + + /** + * Produces a compliant, formatted RFC 2822 'phrase' based on the string given. + * + * @param string $string as displayed + * @param bool $shorten the first line to make remove for header name + */ + protected function createPhrase(HeaderInterface $header, string $string, string $charset, bool $shorten = false): string + { + // Treat token as exactly what was given + $phraseStr = $string; + + // If it's not valid + if (!preg_match('/^'.self::PHRASE_PATTERN.'$/D', $phraseStr)) { + // .. but it is just ascii text, try escaping some characters + // and make it a quoted-string + if (preg_match('/^[\x00-\x08\x0B\x0C\x0E-\x7F]*$/D', $phraseStr)) { + foreach (['\\', '"'] as $char) { + $phraseStr = str_replace($char, '\\'.$char, $phraseStr); + } + $phraseStr = '"'.$phraseStr.'"'; + } else { + // ... otherwise it needs encoding + // Determine space remaining on line if first line + if ($shorten) { + $usedLength = \strlen($header->getName().': '); + } else { + $usedLength = 0; + } + $phraseStr = $this->encodeWords($header, $string, $usedLength); + } + } + + return $phraseStr; + } + + /** + * Encode needed word tokens within a string of input. + */ + protected function encodeWords(HeaderInterface $header, string $input, int $usedLength = -1): string + { + $value = ''; + $tokens = $this->getEncodableWordTokens($input); + foreach ($tokens as $token) { + // See RFC 2822, Sect 2.2 (really 2.2 ??) + if ($this->tokenNeedsEncoding($token)) { + // Don't encode starting WSP + $firstChar = substr($token, 0, 1); + switch ($firstChar) { + case ' ': + case "\t": + $value .= $firstChar; + $token = substr($token, 1); + } + + if (-1 == $usedLength) { + $usedLength = \strlen($header->getName().': ') + \strlen($value); + } + $value .= $this->getTokenAsEncodedWord($token, $usedLength); + } else { + $value .= $token; + } + } + + return $value; + } + + protected function tokenNeedsEncoding(string $token): bool + { + return (bool) preg_match('~[\x00-\x08\x10-\x19\x7F-\xFF\r\n]~', $token); + } + + /** + * Splits a string into tokens in blocks of words which can be encoded quickly. + * + * @return string[] + */ + protected function getEncodableWordTokens(string $string): array + { + $tokens = []; + $encodedToken = ''; + // Split at all whitespace boundaries + foreach (preg_split('~(?=[\t ])~', $string) as $token) { + if ($this->tokenNeedsEncoding($token)) { + $encodedToken .= $token; + } else { + if (\strlen($encodedToken) > 0) { + $tokens[] = $encodedToken; + $encodedToken = ''; + } + $tokens[] = $token; + } + } + if (\strlen($encodedToken)) { + $tokens[] = $encodedToken; + } + + return $tokens; + } + + /** + * Get a token as an encoded word for safe insertion into headers. + */ + protected function getTokenAsEncodedWord(string $token, int $firstLineOffset = 0): string + { + if (null === self::$encoder) { + self::$encoder = new QpMimeHeaderEncoder(); + } + + // Adjust $firstLineOffset to account for space needed for syntax + $charsetDecl = $this->charset; + if (null !== $this->lang) { + $charsetDecl .= '*'.$this->lang; + } + $encodingWrapperLength = \strlen('=?'.$charsetDecl.'?'.self::$encoder->getName().'??='); + + if ($firstLineOffset >= 75) { + //Does this logic need to be here? + $firstLineOffset = 0; + } + + $encodedTextLines = explode("\r\n", + self::$encoder->encodeString($token, $this->charset, $firstLineOffset, 75 - $encodingWrapperLength) + ); + + if ('iso-2022-jp' !== strtolower($this->charset)) { + // special encoding for iso-2022-jp using mb_encode_mimeheader + foreach ($encodedTextLines as $lineNum => $line) { + $encodedTextLines[$lineNum] = '=?'.$charsetDecl.'?'.self::$encoder->getName().'?'.$line.'?='; + } + } + + return implode("\r\n ", $encodedTextLines); + } + + /** + * Generates tokens from the given string which include CRLF as individual tokens. + * + * @return string[] + */ + protected function generateTokenLines(string $token): array + { + return preg_split('~(\r\n)~', $token, -1, PREG_SPLIT_DELIM_CAPTURE); + } + + /** + * Generate a list of all tokens in the final header. + */ + protected function toTokens(string $string = null): array + { + if (null === $string) { + $string = $this->getBodyAsString(); + } + + $tokens = []; + // Generate atoms; split at all invisible boundaries followed by WSP + foreach (preg_split('~(?=[ \t])~', $string) as $token) { + $newTokens = $this->generateTokenLines($token); + foreach ($newTokens as $newToken) { + $tokens[] = $newToken; + } + } + + return $tokens; + } + + /** + * Takes an array of tokens which appear in the header and turns them into + * an RFC 2822 compliant string, adding FWSP where needed. + * + * @param string[] $tokens + */ + private function tokensToString(array $tokens): string + { + $lineCount = 0; + $headerLines = []; + $headerLines[] = $this->name.': '; + $currentLine = &$headerLines[$lineCount++]; + + // Build all tokens back into compliant header + foreach ($tokens as $i => $token) { + // Line longer than specified maximum or token was just a new line + if (("\r\n" === $token) || + ($i > 0 && \strlen($currentLine.$token) > $this->lineLength) + && 0 < \strlen($currentLine)) { + $headerLines[] = ''; + $currentLine = &$headerLines[$lineCount++]; + } + + // Append token to the line + if ("\r\n" !== $token) { + $currentLine .= $token; + } + } + + // Implode with FWS (RFC 2822, 2.2.3) + return implode("\r\n", $headerLines); + } +} diff --git a/vendor/symfony/mime/Header/DateHeader.php b/vendor/symfony/mime/Header/DateHeader.php new file mode 100644 index 0000000000000000000000000000000000000000..1e1a979569448033df27c4a1fa3590c26aec3753 --- /dev/null +++ b/vendor/symfony/mime/Header/DateHeader.php @@ -0,0 +1,71 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime\Header; + +/** + * A Date MIME Header. + * + * @author Chris Corbyn + * + * @experimental in 4.3 + */ +final class DateHeader extends AbstractHeader +{ + private $dateTime; + + public function __construct(string $name, \DateTimeInterface $date) + { + parent::__construct($name); + + $this->setDateTime($date); + } + + /** + * @param \DateTimeInterface $body + */ + public function setBody($body) + { + $this->setDateTime($body); + } + + /** + * @return \DateTimeImmutable + */ + public function getBody() + { + return $this->getDateTime(); + } + + public function getDateTime(): \DateTimeImmutable + { + return $this->dateTime; + } + + /** + * Set the date-time of the Date in this Header. + * + * If a DateTime instance is provided, it is converted to DateTimeImmutable. + */ + public function setDateTime(\DateTimeInterface $dateTime) + { + if ($dateTime instanceof \DateTime) { + $immutable = new \DateTimeImmutable('@'.$dateTime->getTimestamp()); + $dateTime = $immutable->setTimezone($dateTime->getTimezone()); + } + $this->dateTime = $dateTime; + } + + public function getBodyAsString(): string + { + return $this->dateTime->format(\DateTime::RFC2822); + } +} diff --git a/vendor/symfony/mime/Header/HeaderInterface.php b/vendor/symfony/mime/Header/HeaderInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..b0638bca40a3b55e55fef8e0bc679efbcfcda6b7 --- /dev/null +++ b/vendor/symfony/mime/Header/HeaderInterface.php @@ -0,0 +1,67 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime\Header; + +/** + * A MIME Header. + * + * @author Chris Corbyn + * + * @experimental in 4.3 + */ +interface HeaderInterface +{ + /** + * Sets the body. + * + * The type depends on the Header concrete class. + * + * @param mixed $body + */ + public function setBody($body); + + /** + * Gets the body. + * + * The return type depends on the Header concrete class. + * + * @return mixed + */ + public function getBody(); + + public function setCharset(string $charset); + + public function getCharset(): ?string; + + public function setLanguage(string $lang); + + public function getLanguage(): ?string; + + public function getName(): string; + + public function setMaxLineLength(int $lineLength); + + public function getMaxLineLength(): int; + + /** + * Gets this Header rendered as a compliant string. + */ + public function toString(): string; + + /** + * Gets the header's body, prepared for folding into a final header value. + * + * This is not necessarily RFC 2822 compliant since folding white space is + * not added at this stage (see {@link toString()} for that). + */ + public function getBodyAsString(): string; +} diff --git a/vendor/symfony/mime/Header/Headers.php b/vendor/symfony/mime/Header/Headers.php new file mode 100644 index 0000000000000000000000000000000000000000..57f02b25a3ef04c3a1326317267efdf62367a605 --- /dev/null +++ b/vendor/symfony/mime/Header/Headers.php @@ -0,0 +1,285 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime\Header; + +use Symfony\Component\Mime\Address; +use Symfony\Component\Mime\Exception\LogicException; +use Symfony\Component\Mime\NamedAddress; + +/** + * A collection of headers. + * + * @author Fabien Potencier <fabien@symfony.com> + * + * @experimental in 4.3 + */ +final class Headers +{ + private static $uniqueHeaders = [ + 'date', 'from', 'sender', 'reply-to', 'to', 'cc', 'bcc', + 'message-id', 'in-reply-to', 'references', 'subject', + ]; + + private $headers = []; + private $lineLength = 76; + + public function __construct(HeaderInterface ...$headers) + { + foreach ($headers as $header) { + $this->add($header); + } + } + + public function __clone() + { + foreach ($this->headers as $name => $collection) { + foreach ($collection as $i => $header) { + $this->headers[$name][$i] = clone $header; + } + } + } + + public function setMaxLineLength(int $lineLength) + { + $this->lineLength = $lineLength; + foreach ($this->all() as $header) { + $header->setMaxLineLength($lineLength); + } + } + + public function getMaxLineLength(): int + { + return $this->lineLength; + } + + /** + * @param (NamedAddress|Address|string)[] $addresses + * + * @return $this + */ + public function addMailboxListHeader(string $name, array $addresses) + { + return $this->add(new MailboxListHeader($name, Address::createArray($addresses))); + } + + /** + * @param NamedAddress|Address|string $address + * + * @return $this + */ + public function addMailboxHeader(string $name, $address) + { + return $this->add(new MailboxHeader($name, Address::create($address))); + } + + /** + * @param string|array $ids + * + * @return $this + */ + public function addIdHeader(string $name, $ids) + { + return $this->add(new IdentificationHeader($name, $ids)); + } + + /** + * @param Address|string $path + * + * @return $this + */ + public function addPathHeader(string $name, $path) + { + return $this->add(new PathHeader($name, $path instanceof Address ? $path : new Address($path))); + } + + /** + * @return $this + */ + public function addDateHeader(string $name, \DateTimeInterface $dateTime) + { + return $this->add(new DateHeader($name, $dateTime)); + } + + /** + * @return $this + */ + public function addTextHeader(string $name, string $value) + { + return $this->add(new UnstructuredHeader($name, $value)); + } + + /** + * @return $this + */ + public function addParameterizedHeader(string $name, string $value, array $params = []) + { + return $this->add(new ParameterizedHeader($name, $value, $params)); + } + + public function has(string $name): bool + { + return isset($this->headers[strtolower($name)]); + } + + /** + * @return $this + */ + public function add(HeaderInterface $header) + { + static $map = [ + 'date' => DateHeader::class, + 'from' => MailboxListHeader::class, + 'sender' => MailboxHeader::class, + 'reply-to' => MailboxListHeader::class, + 'to' => MailboxListHeader::class, + 'cc' => MailboxListHeader::class, + 'bcc' => MailboxListHeader::class, + 'message-id' => IdentificationHeader::class, + 'in-reply-to' => IdentificationHeader::class, + 'references' => IdentificationHeader::class, + 'return-path' => PathHeader::class, + ]; + + $header->setMaxLineLength($this->lineLength); + $name = strtolower($header->getName()); + + if (isset($map[$name]) && !$header instanceof $map[$name]) { + throw new LogicException(sprintf('The "%s" header must be an instance of "%s" (got "%s").', $header->getName(), $map[$name], \get_class($header))); + } + + if (\in_array($name, self::$uniqueHeaders, true) && isset($this->headers[$name]) && \count($this->headers[$name]) > 0) { + throw new LogicException(sprintf('Impossible to set header "%s" as it\'s already defined and must be unique.', $header->getName())); + } + + $this->headers[$name][] = $header; + + return $this; + } + + public function get(string $name): ?HeaderInterface + { + $name = strtolower($name); + if (!isset($this->headers[$name])) { + return null; + } + + $values = array_values($this->headers[$name]); + + return array_shift($values); + } + + public function all(string $name = null): iterable + { + if (null === $name) { + foreach ($this->headers as $name => $collection) { + foreach ($collection as $header) { + yield $name => $header; + } + } + } elseif (isset($this->headers[strtolower($name)])) { + foreach ($this->headers[strtolower($name)] as $header) { + yield $header; + } + } + } + + public function getNames(): array + { + return array_keys($this->headers); + } + + public function remove(string $name): void + { + unset($this->headers[strtolower($name)]); + } + + public static function isUniqueHeader(string $name): bool + { + return \in_array($name, self::$uniqueHeaders, true); + } + + public function toString(): string + { + $string = ''; + foreach ($this->toArray() as $str) { + $string .= $str."\r\n"; + } + + return $string; + } + + public function toArray(): array + { + $arr = []; + foreach ($this->all() as $header) { + if ('' !== $header->getBodyAsString()) { + $arr[] = $header->toString(); + } + } + + return $arr; + } + + /** + * @internal + */ + public function getHeaderBody($name) + { + return $this->has($name) ? $this->get($name)->getBody() : null; + } + + /** + * @internal + */ + public function setHeaderBody(string $type, string $name, $body): void + { + if ($this->has($name)) { + $this->get($name)->setBody($body); + } else { + $this->{'add'.$type.'Header'}($name, $body); + } + } + + /** + * @internal + */ + public function getHeaderParameter(string $name, string $parameter): ?string + { + if (!$this->has($name)) { + return null; + } + + $header = $this->get($name); + if (!$header instanceof ParameterizedHeader) { + throw new LogicException(sprintf('Unable to get parameter "%s" on header "%s" as the header is not of class "%s".', $parameter, $name, ParameterizedHeader::class)); + } + + return $header->getParameter($parameter); + } + + /** + * @internal + */ + public function setHeaderParameter(string $name, string $parameter, $value): void + { + if (!$this->has($name)) { + throw new LogicException(sprintf('Unable to set parameter "%s" on header "%s" as the header is not defined.', $parameter, $name)); + } + + $header = $this->get($name); + if (!$header instanceof ParameterizedHeader) { + throw new LogicException(sprintf('Unable to set parameter "%s" on header "%s" as the header is not of class "%s".', $parameter, $name, ParameterizedHeader::class)); + } + + $header->setParameter($parameter, $value); + } +} diff --git a/vendor/symfony/mime/Header/IdentificationHeader.php b/vendor/symfony/mime/Header/IdentificationHeader.php new file mode 100644 index 0000000000000000000000000000000000000000..0695b688da24737ab3ee24907810df6a481d2df8 --- /dev/null +++ b/vendor/symfony/mime/Header/IdentificationHeader.php @@ -0,0 +1,115 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime\Header; + +use Symfony\Component\Mime\Address; +use Symfony\Component\Mime\Exception\RfcComplianceException; + +/** + * An ID MIME Header for something like Message-ID or Content-ID (one or more addresses). + * + * @author Chris Corbyn + * + * @experimental in 4.3 + */ +final class IdentificationHeader extends AbstractHeader +{ + private $ids = []; + private $idsAsAddresses = []; + + /** + * @param string|array $ids + */ + public function __construct(string $name, $ids) + { + parent::__construct($name); + + $this->setId($ids); + } + + /** + * @param string|array $body a string ID or an array of IDs + * + * @throws RfcComplianceException + */ + public function setBody($body) + { + $this->setId($body); + } + + /** + * @return array + */ + public function getBody() + { + return $this->getIds(); + } + + /** + * Set the ID used in the value of this header. + * + * @param string|array $id + * + * @throws RfcComplianceException + */ + public function setId($id) + { + $this->setIds(\is_array($id) ? $id : [$id]); + } + + /** + * Get the ID used in the value of this Header. + * + * If multiple IDs are set only the first is returned. + */ + public function getId(): ?string + { + return $this->ids[0] ?? null; + } + + /** + * Set a collection of IDs to use in the value of this Header. + * + * @param string[] $ids + * + * @throws RfcComplianceException + */ + public function setIds(array $ids) + { + $this->ids = []; + $this->idsAsAddresses = []; + foreach ($ids as $id) { + $this->idsAsAddresses[] = new Address($id); + $this->ids[] = $id; + } + } + + /** + * Get the list of IDs used in this Header. + * + * @return string[] + */ + public function getIds(): array + { + return $this->ids; + } + + public function getBodyAsString(): string + { + $addrs = []; + foreach ($this->idsAsAddresses as $address) { + $addrs[] = '<'.$address->toString().'>'; + } + + return implode(' ', $addrs); + } +} diff --git a/vendor/symfony/mime/Header/MailboxHeader.php b/vendor/symfony/mime/Header/MailboxHeader.php new file mode 100644 index 0000000000000000000000000000000000000000..c6649232638060e9ff112c00ac3863ad62bd2c1a --- /dev/null +++ b/vendor/symfony/mime/Header/MailboxHeader.php @@ -0,0 +1,90 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime\Header; + +use Symfony\Component\Mime\Address; +use Symfony\Component\Mime\Exception\RfcComplianceException; +use Symfony\Component\Mime\NamedAddress; + +/** + * A Mailbox MIME Header for something like Sender (one named address). + * + * @author Fabien Potencier <fabien@symfony.com> + * + * @experimental in 4.3 + */ +final class MailboxHeader extends AbstractHeader +{ + private $address; + + public function __construct(string $name, Address $address) + { + parent::__construct($name); + + $this->setAddress($address); + } + + /** + * @param Address $body + * + * @throws RfcComplianceException + */ + public function setBody($body) + { + $this->setAddress($body); + } + + /** + * @throws RfcComplianceException + * + * @return Address + */ + public function getBody() + { + return $this->getAddress(); + } + + /** + * @throws RfcComplianceException + */ + public function setAddress(Address $address) + { + $this->address = $address; + } + + public function getAddress(): Address + { + return $this->address; + } + + public function getBodyAsString(): string + { + $str = $this->address->getEncodedAddress(); + if ($this->address instanceof NamedAddress && $name = $this->address->getName()) { + $str = $this->createPhrase($this, $name, $this->getCharset(), true).' <'.$str.'>'; + } + + return $str; + } + + /** + * Redefine the encoding requirements for an address. + * + * All "specials" must be encoded as the full header value will not be quoted + * + * @see RFC 2822 3.2.1 + */ + protected function tokenNeedsEncoding(string $token): bool + { + return preg_match('/[()<>\[\]:;@\,."]/', $token) || parent::tokenNeedsEncoding($token); + } +} diff --git a/vendor/symfony/mime/Header/MailboxListHeader.php b/vendor/symfony/mime/Header/MailboxListHeader.php new file mode 100644 index 0000000000000000000000000000000000000000..51af2da87caab82555e626570664f433b6d239af --- /dev/null +++ b/vendor/symfony/mime/Header/MailboxListHeader.php @@ -0,0 +1,139 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime\Header; + +use Symfony\Component\Mime\Address; +use Symfony\Component\Mime\Exception\RfcComplianceException; +use Symfony\Component\Mime\NamedAddress; + +/** + * A Mailbox list MIME Header for something like From, To, Cc, and Bcc (one or more named addresses). + * + * @author Chris Corbyn + * + * @experimental in 4.3 + */ +final class MailboxListHeader extends AbstractHeader +{ + private $addresses = []; + + /** + * @param (NamedAddress|Address)[] $addresses + */ + public function __construct(string $name, array $addresses) + { + parent::__construct($name); + + $this->setAddresses($addresses); + } + + /** + * @param (NamedAddress|Address)[] $body + * + * @throws RfcComplianceException + */ + public function setBody($body) + { + $this->setAddresses($body); + } + + /** + * @throws RfcComplianceException + * + * @return (NamedAddress|Address)[] + */ + public function getBody() + { + return $this->getAddresses(); + } + + /** + * Sets a list of addresses to be shown in this Header. + * + * @param (NamedAddress|Address)[] $addresses + * + * @throws RfcComplianceException + */ + public function setAddresses(array $addresses) + { + $this->addresses = []; + $this->addAddresses($addresses); + } + + /** + * Sets a list of addresses to be shown in this Header. + * + * @param (NamedAddress|Address)[] $addresses + * + * @throws RfcComplianceException + */ + public function addAddresses(array $addresses) + { + foreach ($addresses as $address) { + $this->addAddress($address); + } + } + + /** + * @throws RfcComplianceException + */ + public function addAddress(Address $address) + { + $this->addresses[] = $address; + } + + /** + * @return (NamedAddress|Address)[] + */ + public function getAddresses(): array + { + return $this->addresses; + } + + /** + * Gets the full mailbox list of this Header as an array of valid RFC 2822 strings. + * + * @throws RfcComplianceException + * + * @return string[] + */ + public function getAddressStrings(): array + { + $strings = []; + foreach ($this->addresses as $address) { + $str = $address->getEncodedAddress(); + if ($address instanceof NamedAddress && $name = $address->getName()) { + $str = $this->createPhrase($this, $name, $this->getCharset(), empty($strings)).' <'.$str.'>'; + } + $strings[] = $str; + } + + return $strings; + } + + public function getBodyAsString(): string + { + return implode(', ', $this->getAddressStrings()); + } + + /** + * Redefine the encoding requirements for addresses. + * + * All "specials" must be encoded as the full header value will not be quoted + * + * @see RFC 2822 3.2.1 + */ + protected function tokenNeedsEncoding(string $token): bool + { + return preg_match('/[()<>\[\]:;@\,."]/', $token) || parent::tokenNeedsEncoding($token); + } +} diff --git a/vendor/symfony/mime/Header/ParameterizedHeader.php b/vendor/symfony/mime/Header/ParameterizedHeader.php new file mode 100644 index 0000000000000000000000000000000000000000..811a969b1b040d6ca696c41956940f7d77735af0 --- /dev/null +++ b/vendor/symfony/mime/Header/ParameterizedHeader.php @@ -0,0 +1,176 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime\Header; + +use Symfony\Component\Mime\Encoder\Rfc2231Encoder; + +/** + * @author Chris Corbyn + * + * @experimental in 4.3 + */ +final class ParameterizedHeader extends UnstructuredHeader +{ + /** + * RFC 2231's definition of a token. + * + * @var string + */ + const TOKEN_REGEX = '(?:[\x21\x23-\x27\x2A\x2B\x2D\x2E\x30-\x39\x41-\x5A\x5E-\x7E]+)'; + + private $encoder; + private $parameters = []; + + public function __construct(string $name, string $value, array $parameters = []) + { + parent::__construct($name, $value); + + foreach ($parameters as $k => $v) { + $this->setParameter($k, $v); + } + + if ('content-type' !== strtolower($name)) { + $this->encoder = new Rfc2231Encoder(); + } + } + + public function setParameter(string $parameter, ?string $value) + { + $this->setParameters(array_merge($this->getParameters(), [$parameter => $value])); + } + + public function getParameter(string $parameter): string + { + return $this->getParameters()[$parameter] ?? ''; + } + + /** + * @param string[] $parameters + */ + public function setParameters(array $parameters) + { + $this->parameters = $parameters; + } + + /** + * @return string[] + */ + public function getParameters(): array + { + return $this->parameters; + } + + public function getBodyAsString(): string + { + $body = parent::getBodyAsString(); + foreach ($this->parameters as $name => $value) { + if (null !== $value) { + $body .= '; '.$this->createParameter($name, $value); + } + } + + return $body; + } + + /** + * Generate a list of all tokens in the final header. + * + * This doesn't need to be overridden in theory, but it is for implementation + * reasons to prevent potential breakage of attributes. + */ + protected function toTokens(string $string = null): array + { + $tokens = parent::toTokens(parent::getBodyAsString()); + + // Try creating any parameters + foreach ($this->parameters as $name => $value) { + if (null !== $value) { + // Add the semi-colon separator + $tokens[\count($tokens) - 1] .= ';'; + $tokens = array_merge($tokens, $this->generateTokenLines(' '.$this->createParameter($name, $value))); + } + } + + return $tokens; + } + + /** + * Render a RFC 2047 compliant header parameter from the $name and $value. + */ + private function createParameter(string $name, string $value): string + { + $origValue = $value; + + $encoded = false; + // Allow room for parameter name, indices, "=" and DQUOTEs + $maxValueLength = $this->getMaxLineLength() - \strlen($name.'=*N"";') - 1; + $firstLineOffset = 0; + + // If it's not already a valid parameter value... + if (!preg_match('/^'.self::TOKEN_REGEX.'$/D', $value)) { + // TODO: text, or something else?? + // ... and it's not ascii + if (!preg_match('/^[\x00-\x08\x0B\x0C\x0E-\x7F]*$/D', $value)) { + $encoded = true; + // Allow space for the indices, charset and language + $maxValueLength = $this->getMaxLineLength() - \strlen($name.'*N*="";') - 1; + $firstLineOffset = \strlen($this->getCharset()."'".$this->getLanguage()."'"); + } + } + + // Encode if we need to + if ($encoded || \strlen($value) > $maxValueLength) { + if (null !== $this->encoder) { + $value = $this->encoder->encodeString($origValue, $this->getCharset(), $firstLineOffset, $maxValueLength); + } else { + // We have to go against RFC 2183/2231 in some areas for interoperability + $value = $this->getTokenAsEncodedWord($origValue); + $encoded = false; + } + } + + $valueLines = $this->encoder ? explode("\r\n", $value) : [$value]; + + // Need to add indices + if (\count($valueLines) > 1) { + $paramLines = []; + foreach ($valueLines as $i => $line) { + $paramLines[] = $name.'*'.$i.$this->getEndOfParameterValue($line, true, 0 === $i); + } + + return implode(";\r\n ", $paramLines); + } else { + return $name.$this->getEndOfParameterValue($valueLines[0], $encoded, true); + } + } + + /** + * Returns the parameter value from the "=" and beyond. + * + * @param string $value to append + */ + private function getEndOfParameterValue(string $value, bool $encoded = false, bool $firstLine = false): string + { + if (!preg_match('/^'.self::TOKEN_REGEX.'$/D', $value)) { + $value = '"'.$value.'"'; + } + $prepend = '='; + if ($encoded) { + $prepend = '*='; + if ($firstLine) { + $prepend = '*='.$this->getCharset()."'".$this->getLanguage()."'"; + } + } + + return $prepend.$value; + } +} diff --git a/vendor/symfony/mime/Header/PathHeader.php b/vendor/symfony/mime/Header/PathHeader.php new file mode 100644 index 0000000000000000000000000000000000000000..6d16500a18a2298503cde524afb0d8000f4fa822 --- /dev/null +++ b/vendor/symfony/mime/Header/PathHeader.php @@ -0,0 +1,67 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime\Header; + +use Symfony\Component\Mime\Address; +use Symfony\Component\Mime\Exception\RfcComplianceException; + +/** + * A Path Header, such a Return-Path (one address). + * + * @author Chris Corbyn + * + * @experimental in 4.3 + */ +final class PathHeader extends AbstractHeader +{ + private $address; + + public function __construct(string $name, Address $address) + { + parent::__construct($name); + + $this->setAddress($address); + } + + /** + * @param Address $body + * + * @throws RfcComplianceException + */ + public function setBody($body) + { + $this->setAddress($body); + } + + /** + * @return Address + */ + public function getBody() + { + return $this->getAddress(); + } + + public function setAddress(Address $address) + { + $this->address = $address; + } + + public function getAddress(): Address + { + return $this->address; + } + + public function getBodyAsString(): string + { + return '<'.$this->address->toString().'>'; + } +} diff --git a/vendor/symfony/mime/Header/UnstructuredHeader.php b/vendor/symfony/mime/Header/UnstructuredHeader.php new file mode 100644 index 0000000000000000000000000000000000000000..afb96152570f0ba235dff5abf09057e7c95a8bd9 --- /dev/null +++ b/vendor/symfony/mime/Header/UnstructuredHeader.php @@ -0,0 +1,71 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime\Header; + +/** + * A Simple MIME Header. + * + * @author Chris Corbyn + * + * @experimental in 4.3 + */ +class UnstructuredHeader extends AbstractHeader +{ + private $value; + + public function __construct(string $name, string $value) + { + parent::__construct($name); + + $this->setValue($value); + } + + /** + * @param string $body + */ + public function setBody($body) + { + $this->setValue($body); + } + + /** + * @return string + */ + public function getBody() + { + return $this->getValue(); + } + + /** + * Get the (unencoded) value of this header. + */ + public function getValue(): string + { + return $this->value; + } + + /** + * Set the (unencoded) value of this header. + */ + public function setValue(string $value) + { + $this->value = $value; + } + + /** + * Get the value of this header prepared for rendering. + */ + public function getBodyAsString(): string + { + return $this->encodeWords($this, $this->value); + } +} diff --git a/vendor/symfony/mime/LICENSE b/vendor/symfony/mime/LICENSE new file mode 100644 index 0000000000000000000000000000000000000000..9a9a61b1c6c105466af6db0736c46666a6da7d21 --- /dev/null +++ b/vendor/symfony/mime/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2010-2019 Fabien Potencier + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/vendor/symfony/mime/Message.php b/vendor/symfony/mime/Message.php new file mode 100644 index 0000000000000000000000000000000000000000..4d6af1c94d4b48d582ba6b9684d7dca956308736 --- /dev/null +++ b/vendor/symfony/mime/Message.php @@ -0,0 +1,142 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime; + +use Symfony\Component\Mime\Exception\LogicException; +use Symfony\Component\Mime\Header\Headers; +use Symfony\Component\Mime\Part\AbstractPart; +use Symfony\Component\Mime\Part\TextPart; + +/** + * @author Fabien Potencier <fabien@symfony.com> + * + * @experimental in 4.3 + */ +class Message extends RawMessage +{ + private $headers; + private $body; + + public function __construct(Headers $headers = null, AbstractPart $body = null) + { + $this->headers = $headers ? clone $headers : new Headers(); + $this->body = $body; + } + + public function __clone() + { + if (null !== $this->headers) { + $this->headers = clone $this->headers; + } + + if (null !== $this->body) { + $this->body = clone $this->body; + } + } + + /** + * @return $this + */ + public function setBody(AbstractPart $body = null) + { + $this->body = $body; + + return $this; + } + + public function getBody(): ?AbstractPart + { + return $this->body; + } + + /** + * @return $this + */ + public function setHeaders(Headers $headers) + { + $this->headers = $headers; + + return $this; + } + + public function getHeaders(): Headers + { + return $this->headers; + } + + public function getPreparedHeaders(): Headers + { + $headers = clone $this->headers; + + if (!$headers->has('From')) { + throw new LogicException('An email must have a "From" header.'); + } + + $headers->addTextHeader('MIME-Version', '1.0'); + + if (!$headers->has('Date')) { + $headers->addDateHeader('Date', new \DateTimeImmutable()); + } + + // determine the "real" sender + $senders = $headers->get('From')->getAddresses(); + $sender = $senders[0]; + if ($headers->has('Sender')) { + $sender = $headers->get('Sender')->getAddress(); + } elseif (\count($senders) > 1) { + $headers->addMailboxHeader('Sender', $sender); + } + + if (!$headers->has('Message-ID')) { + $headers->addIdHeader('Message-ID', $this->generateMessageId($sender->getAddress())); + } + + // remove the Bcc field which should NOT be part of the sent message + $headers->remove('Bcc'); + + return $headers; + } + + public function toString(): string + { + if (null === $body = $this->getBody()) { + $body = new TextPart(''); + } + + return $this->getPreparedHeaders()->toString().$body->toString(); + } + + public function toIterable(): iterable + { + if (null === $body = $this->getBody()) { + $body = new TextPart(''); + } + + yield $this->getPreparedHeaders()->toString(); + yield from $body->toIterable(); + } + + private function generateMessageId(string $email): string + { + return bin2hex(random_bytes(16)).strstr($email, '@'); + } + + public function __serialize(): array + { + return [$this->headers, $this->body]; + } + + public function __unserialize(array $data): void + { + [$this->headers, $this->body] = $data; + } +} diff --git a/vendor/symfony/mime/MessageConverter.php b/vendor/symfony/mime/MessageConverter.php new file mode 100644 index 0000000000000000000000000000000000000000..b139f1c086db089b3e3da9aef4f23e3412ce1727 --- /dev/null +++ b/vendor/symfony/mime/MessageConverter.php @@ -0,0 +1,127 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime; + +use Symfony\Component\Mime\Exception\RuntimeException; +use Symfony\Component\Mime\Part\DataPart; +use Symfony\Component\Mime\Part\Multipart\AlternativePart; +use Symfony\Component\Mime\Part\Multipart\MixedPart; +use Symfony\Component\Mime\Part\Multipart\RelatedPart; +use Symfony\Component\Mime\Part\TextPart; + +/** + * @author Fabien Potencier <fabien@symfony.com> + * + * @experimental in 4.3 + */ +final class MessageConverter +{ + /** + * @throws RuntimeException when unable to convert the message to an email + */ + public static function toEmail(Message $message): Email + { + if ($message instanceof Email) { + return $message; + } + + // try to convert to a "simple" Email instance + $body = $message->getBody(); + if ($body instanceof TextPart) { + return self::createEmailFromTextPart($message, $body); + } + + if ($body instanceof AlternativePart) { + return self::createEmailFromAlternativePart($message, $body); + } + + if ($body instanceof RelatedPart) { + return self::createEmailFromRelatedPart($message, $body); + } + + if ($body instanceof MixedPart) { + $parts = $body->getParts(); + if ($parts[0] instanceof RelatedPart) { + $email = self::createEmailFromRelatedPart($message, $parts[0]); + } elseif ($parts[0] instanceof AlternativePart) { + $email = self::createEmailFromAlternativePart($message, $parts[0]); + } elseif ($parts[0] instanceof TextPart) { + $email = self::createEmailFromTextPart($message, $parts[0]); + } else { + throw new RuntimeException(sprintf('Unable to create an Email from an instance of "%s" as the body is too complex.', \get_class($message))); + } + + return self::attachParts($email, \array_slice($parts, 1)); + } + + throw new RuntimeException(sprintf('Unable to create an Email from an instance of "%s" as the body is too complex.', \get_class($message))); + } + + private static function createEmailFromTextPart(Message $message, TextPart $part): Email + { + if ('text' === $part->getMediaType() && 'plain' === $part->getMediaSubtype()) { + return (new Email(clone $message->getHeaders()))->text($part->getBody(), $part->getPreparedHeaders()->getHeaderParameter('Content-Type', 'charset') ?: 'utf-8'); + } + if ('text' === $part->getMediaType() && 'html' === $part->getMediaSubtype()) { + return (new Email(clone $message->getHeaders()))->html($part->getBody(), $part->getPreparedHeaders()->getHeaderParameter('Content-Type', 'charset') ?: 'utf-8'); + } + + throw new RuntimeException(sprintf('Unable to create an Email from an instance of "%s" as the body is too complex.', \get_class($message))); + } + + private static function createEmailFromAlternativePart(Message $message, AlternativePart $part): Email + { + $parts = $part->getParts(); + if ( + 2 === \count($parts) && + $parts[0] instanceof TextPart && 'text' === $parts[0]->getMediaType() && 'plain' === $parts[0]->getMediaSubtype() && + $parts[1] instanceof TextPart && 'text' === $parts[1]->getMediaType() && 'html' === $parts[1]->getMediaSubtype() + ) { + return (new Email(clone $message->getHeaders())) + ->text($parts[0]->getBody(), $parts[0]->getPreparedHeaders()->getHeaderParameter('Content-Type', 'charset') ?: 'utf-8') + ->html($parts[1]->getBody(), $parts[1]->getPreparedHeaders()->getHeaderParameter('Content-Type', 'charset') ?: 'utf-8') + ; + } + + throw new RuntimeException(sprintf('Unable to create an Email from an instance of "%s" as the body is too complex.', \get_class($message))); + } + + private static function createEmailFromRelatedPart(Message $message, RelatedPart $part): Email + { + $parts = $part->getParts(); + if ($parts[0] instanceof AlternativePart) { + $email = self::createEmailFromAlternativePart($message, $parts[0]); + } elseif ($parts[0] instanceof TextPart) { + $email = self::createEmailFromTextPart($message, $parts[0]); + } else { + throw new RuntimeException(sprintf('Unable to create an Email from an instance of "%s" as the body is too complex.', \get_class($message))); + } + + return self::attachParts($email, \array_slice($parts, 1)); + } + + private static function attachParts(Email $email, array $parts): Email + { + foreach ($parts as $part) { + if (!$part instanceof DataPart) { + throw new RuntimeException(sprintf('Unable to create an Email from an instance of "%s" as the body is too complex.', \get_class($email))); + } + + $headers = $part->getPreparedHeaders(); + $method = 'inline' === $headers->getHeaderBody('Content-Disposition') ? 'embed' : 'attach'; + $name = $headers->getHeaderParameter('Content-Disposition', 'filename'); + $email->$method($part->getBody(), $name, $part->getMediaType().'/'.$part->getMediaSubtype()); + } + + return $email; + } +} diff --git a/vendor/symfony/mime/MimeTypeGuesserInterface.php b/vendor/symfony/mime/MimeTypeGuesserInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..b7d27f53e2029d63b444e042b04cb4bc97516061 --- /dev/null +++ b/vendor/symfony/mime/MimeTypeGuesserInterface.php @@ -0,0 +1,39 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime; + +/** + * Guesses the MIME type of a file. + * + * @author Fabien Potencier <fabien@symfony.com> + * + * @experimental in 4.3 + */ +interface MimeTypeGuesserInterface +{ + /** + * Returns true if this guesser is supported. + */ + public function isGuesserSupported(): bool; + + /** + * Guesses the MIME type of the file with the given path. + * + * @param string $path The path to the file + * + * @return string|null The MIME type or null, if none could be guessed + * + * @throws \LogicException If the guesser is not supported + * @throws \InvalidArgumentException If the file does not exist or is not readable + */ + public function guessMimeType(string $path): ?string; +} diff --git a/vendor/symfony/mime/MimeTypes.php b/vendor/symfony/mime/MimeTypes.php new file mode 100644 index 0000000000000000000000000000000000000000..02e8fe50b3429600c401be4e1ac3962da981bea6 --- /dev/null +++ b/vendor/symfony/mime/MimeTypes.php @@ -0,0 +1,3154 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime; + +use Symfony\Component\Mime\Exception\LogicException; + +/** + * Manages MIME types and file extensions. + * + * For MIME type guessing, you can register custom guessers + * by calling the registerGuesser() method. + * Custom guessers are always called before any default ones: + * + * $guesser = new MimeTypes(); + * $guesser->registerGuesser(new MyCustomMimeTypeGuesser()); + * + * If you want to change the order of the default guessers, just re-register your + * preferred one as a custom one. The last registered guesser is preferred over + * previously registered ones. + * + * Re-registering a built-in guesser also allows you to configure it: + * + * $guesser = new MimeTypes(); + * $guesser->registerGuesser(new FileinfoMimeTypeGuesser('/path/to/magic/file')); + * + * @author Fabien Potencier <fabien@symfony.com> + * + * @experimental in 4.3 + */ +final class MimeTypes implements MimeTypesInterface +{ + private $extensions = []; + private $mimeTypes = []; + + /** + * @var MimeTypeGuesserInterface[] + */ + private $guessers = []; + private static $default; + + public function __construct(array $map = []) + { + foreach ($map as $mimeType => $extensions) { + $this->extensions[$mimeType] = $extensions; + + foreach ($extensions as $extension) { + $this->mimeTypes[$extension] = $mimeType; + } + } + $this->registerGuesser(new FileBinaryMimeTypeGuesser()); + $this->registerGuesser(new FileinfoMimeTypeGuesser()); + } + + public static function setDefault(self $default) + { + self::$default = $default; + } + + public static function getDefault(): self + { + return self::$default ?? self::$default = new self(); + } + + /** + * Registers a MIME type guesser. + * + * The last registered guesser has precedence over the other ones. + */ + public function registerGuesser(MimeTypeGuesserInterface $guesser) + { + array_unshift($this->guessers, $guesser); + } + + /** + * {@inheritdoc} + */ + public function getExtensions(string $mimeType): array + { + if ($this->extensions) { + $extensions = $this->extensions[$mimeType] ?? $this->extensions[$lcMimeType = strtolower($mimeType)] ?? null; + } + + return $extensions ?? self::$map[$mimeType] ?? self::$map[$lcMimeType ?? strtolower($mimeType)] ?? []; + } + + /** + * {@inheritdoc} + */ + public function getMimeTypes(string $ext): array + { + if ($this->mimeTypes) { + $mimeTypes = $this->mimeTypes[$ext] ?? $this->mimeTypes[$lcExt = strtolower($ext)] ?? null; + } + + return $mimeTypes ?? self::$reverseMap[$ext] ?? self::$reverseMap[$lcExt ?? strtolower($ext)] ?? []; + } + + /** + * {@inheritdoc} + */ + public function isGuesserSupported(): bool + { + foreach ($this->guessers as $guesser) { + if ($guesser->isGuesserSupported()) { + return true; + } + } + + return false; + } + + /** + * {@inheritdoc} + * + * The file is passed to each registered MIME type guesser in reverse order + * of their registration (last registered is queried first). Once a guesser + * returns a value that is not null, this method terminates and returns the + * value. + */ + public function guessMimeType(string $path): ?string + { + foreach ($this->guessers as $guesser) { + if (!$guesser->isGuesserSupported()) { + continue; + } + + if (null !== $mimeType = $guesser->guessMimeType($path)) { + return $mimeType; + } + } + + if (!$this->isGuesserSupported()) { + throw new LogicException('Unable to guess the MIME type as no guessers are available (have you enable the php_fileinfo extension?).'); + } + + return null; + } + + /** + * A map of MIME types and their default extensions. + * + * Updated from upstream on 2019-01-16 + * + * @see Resources/bin/update_mime_types.php + */ + private static $map = [ + 'application/acrobat' => ['pdf'], + 'application/andrew-inset' => ['ez'], + 'application/annodex' => ['anx'], + 'application/applixware' => ['aw'], + 'application/atom+xml' => ['atom'], + 'application/atomcat+xml' => ['atomcat'], + 'application/atomsvc+xml' => ['atomsvc'], + 'application/ccxml+xml' => ['ccxml'], + 'application/cdmi-capability' => ['cdmia'], + 'application/cdmi-container' => ['cdmic'], + 'application/cdmi-domain' => ['cdmid'], + 'application/cdmi-object' => ['cdmio'], + 'application/cdmi-queue' => ['cdmiq'], + 'application/cdr' => ['cdr'], + 'application/coreldraw' => ['cdr'], + 'application/cu-seeme' => ['cu'], + 'application/davmount+xml' => ['davmount'], + 'application/dbase' => ['dbf'], + 'application/dbf' => ['dbf'], + 'application/dicom' => ['dcm'], + 'application/docbook+xml' => ['dbk', 'docbook'], + 'application/dssc+der' => ['dssc'], + 'application/dssc+xml' => ['xdssc'], + 'application/ecmascript' => ['ecma', 'es'], + 'application/emf' => ['emf'], + 'application/emma+xml' => ['emma'], + 'application/epub+zip' => ['epub'], + 'application/exi' => ['exi'], + 'application/font-tdpfr' => ['pfr'], + 'application/font-woff' => ['woff'], + 'application/futuresplash' => ['swf', 'spl'], + 'application/geo+json' => ['geojson', 'geo.json'], + 'application/gml+xml' => ['gml'], + 'application/gnunet-directory' => ['gnd'], + 'application/gpx' => ['gpx'], + 'application/gpx+xml' => ['gpx'], + 'application/gxf' => ['gxf'], + 'application/gzip' => ['gz'], + 'application/hyperstudio' => ['stk'], + 'application/ico' => ['ico'], + 'application/ics' => ['vcs', 'ics'], + 'application/illustrator' => ['ai'], + 'application/inkml+xml' => ['ink', 'inkml'], + 'application/ipfix' => ['ipfix'], + 'application/java' => ['class'], + 'application/java-archive' => ['jar'], + 'application/java-byte-code' => ['class'], + 'application/java-serialized-object' => ['ser'], + 'application/java-vm' => ['class'], + 'application/javascript' => ['js', 'jsm', 'mjs'], + 'application/jrd+json' => ['jrd'], + 'application/json' => ['json'], + 'application/json-patch+json' => ['json-patch'], + 'application/jsonml+json' => ['jsonml'], + 'application/ld+json' => ['jsonld'], + 'application/lost+xml' => ['lostxml'], + 'application/lotus123' => ['123', 'wk1', 'wk3', 'wk4', 'wks'], + 'application/m3u' => ['m3u', 'm3u8', 'vlc'], + 'application/mac-binhex40' => ['hqx'], + 'application/mac-compactpro' => ['cpt'], + 'application/mads+xml' => ['mads'], + 'application/marc' => ['mrc'], + 'application/marcxml+xml' => ['mrcx'], + 'application/mathematica' => ['ma', 'nb', 'mb'], + 'application/mathml+xml' => ['mathml', 'mml'], + 'application/mbox' => ['mbox'], + 'application/mdb' => ['mdb'], + 'application/mediaservercontrol+xml' => ['mscml'], + 'application/metalink+xml' => ['metalink'], + 'application/metalink4+xml' => ['meta4'], + 'application/mets+xml' => ['mets'], + 'application/mods+xml' => ['mods'], + 'application/mp21' => ['m21', 'mp21'], + 'application/mp4' => ['mp4s'], + 'application/ms-tnef' => ['tnef', 'tnf'], + 'application/msaccess' => ['mdb'], + 'application/msexcel' => ['xls', 'xlc', 'xll', 'xlm', 'xlw', 'xla', 'xlt', 'xld'], + 'application/mspowerpoint' => ['ppz', 'ppt', 'pps', 'pot'], + 'application/msword' => ['doc', 'dot'], + 'application/msword-template' => ['dot'], + 'application/mxf' => ['mxf'], + 'application/nappdf' => ['pdf'], + 'application/octet-stream' => ['bin', 'dms', 'lrf', 'mar', 'so', 'dist', 'distz', 'pkg', 'bpk', 'dump', 'elc', 'deploy'], + 'application/oda' => ['oda'], + 'application/oebps-package+xml' => ['opf'], + 'application/ogg' => ['ogx'], + 'application/omdoc+xml' => ['omdoc'], + 'application/onenote' => ['onetoc', 'onetoc2', 'onetmp', 'onepkg'], + 'application/owl+xml' => ['owx'], + 'application/oxps' => ['oxps', 'xps'], + 'application/patch-ops-error+xml' => ['xer'], + 'application/pcap' => ['pcap', 'cap', 'dmp'], + 'application/pdf' => ['pdf'], + 'application/pgp' => ['pgp', 'gpg', 'asc'], + 'application/pgp-encrypted' => ['pgp', 'gpg', 'asc'], + 'application/pgp-keys' => ['skr', 'pkr', 'asc', 'pgp', 'gpg'], + 'application/pgp-signature' => ['asc', 'sig', 'pgp', 'gpg'], + 'application/photoshop' => ['psd'], + 'application/pics-rules' => ['prf'], + 'application/pkcs10' => ['p10'], + 'application/pkcs12' => ['p12', 'pfx'], + 'application/pkcs7-mime' => ['p7m', 'p7c'], + 'application/pkcs7-signature' => ['p7s'], + 'application/pkcs8' => ['p8'], + 'application/pkcs8-encrypted' => ['p8e'], + 'application/pkix-attr-cert' => ['ac'], + 'application/pkix-cert' => ['cer'], + 'application/pkix-crl' => ['crl'], + 'application/pkix-pkipath' => ['pkipath'], + 'application/pkixcmp' => ['pki'], + 'application/pls' => ['pls'], + 'application/pls+xml' => ['pls'], + 'application/postscript' => ['ai', 'eps', 'ps'], + 'application/powerpoint' => ['ppz', 'ppt', 'pps', 'pot'], + 'application/prs.cww' => ['cww'], + 'application/pskc+xml' => ['pskcxml'], + 'application/ram' => ['ram'], + 'application/raml+yaml' => ['raml'], + 'application/rdf+xml' => ['rdf', 'rdfs', 'owl'], + 'application/reginfo+xml' => ['rif'], + 'application/relax-ng-compact-syntax' => ['rnc'], + 'application/resource-lists+xml' => ['rl'], + 'application/resource-lists-diff+xml' => ['rld'], + 'application/rls-services+xml' => ['rs'], + 'application/rpki-ghostbusters' => ['gbr'], + 'application/rpki-manifest' => ['mft'], + 'application/rpki-roa' => ['roa'], + 'application/rsd+xml' => ['rsd'], + 'application/rss+xml' => ['rss'], + 'application/rtf' => ['rtf'], + 'application/sbml+xml' => ['sbml'], + 'application/scvp-cv-request' => ['scq'], + 'application/scvp-cv-response' => ['scs'], + 'application/scvp-vp-request' => ['spq'], + 'application/scvp-vp-response' => ['spp'], + 'application/sdp' => ['sdp'], + 'application/set-payment-initiation' => ['setpay'], + 'application/set-registration-initiation' => ['setreg'], + 'application/shf+xml' => ['shf'], + 'application/sieve' => ['siv'], + 'application/smil' => ['smil', 'smi', 'sml', 'kino'], + 'application/smil+xml' => ['smi', 'smil', 'sml', 'kino'], + 'application/sparql-query' => ['rq'], + 'application/sparql-results+xml' => ['srx'], + 'application/sql' => ['sql'], + 'application/srgs' => ['gram'], + 'application/srgs+xml' => ['grxml'], + 'application/sru+xml' => ['sru'], + 'application/ssdl+xml' => ['ssdl'], + 'application/ssml+xml' => ['ssml'], + 'application/stuffit' => ['sit'], + 'application/tei+xml' => ['tei', 'teicorpus'], + 'application/thraud+xml' => ['tfi'], + 'application/timestamped-data' => ['tsd'], + 'application/trig' => ['trig'], + 'application/vnd.3gpp.pic-bw-large' => ['plb'], + 'application/vnd.3gpp.pic-bw-small' => ['psb'], + 'application/vnd.3gpp.pic-bw-var' => ['pvb'], + 'application/vnd.3gpp2.tcap' => ['tcap'], + 'application/vnd.3m.post-it-notes' => ['pwn'], + 'application/vnd.accpac.simply.aso' => ['aso'], + 'application/vnd.accpac.simply.imp' => ['imp'], + 'application/vnd.acucobol' => ['acu'], + 'application/vnd.acucorp' => ['atc', 'acutc'], + 'application/vnd.adobe.air-application-installer-package+zip' => ['air'], + 'application/vnd.adobe.flash.movie' => ['swf', 'spl'], + 'application/vnd.adobe.formscentral.fcdt' => ['fcdt'], + 'application/vnd.adobe.fxp' => ['fxp', 'fxpl'], + 'application/vnd.adobe.illustrator' => ['ai'], + 'application/vnd.adobe.xdp+xml' => ['xdp'], + 'application/vnd.adobe.xfdf' => ['xfdf'], + 'application/vnd.ahead.space' => ['ahead'], + 'application/vnd.airzip.filesecure.azf' => ['azf'], + 'application/vnd.airzip.filesecure.azs' => ['azs'], + 'application/vnd.amazon.ebook' => ['azw'], + 'application/vnd.americandynamics.acc' => ['acc'], + 'application/vnd.amiga.ami' => ['ami'], + 'application/vnd.android.package-archive' => ['apk'], + 'application/vnd.anser-web-certificate-issue-initiation' => ['cii'], + 'application/vnd.anser-web-funds-transfer-initiation' => ['fti'], + 'application/vnd.antix.game-component' => ['atx'], + 'application/vnd.appimage' => ['appimage'], + 'application/vnd.apple.installer+xml' => ['mpkg'], + 'application/vnd.apple.keynote' => ['key'], + 'application/vnd.apple.mpegurl' => ['m3u8', 'm3u'], + 'application/vnd.aristanetworks.swi' => ['swi'], + 'application/vnd.astraea-software.iota' => ['iota'], + 'application/vnd.audiograph' => ['aep'], + 'application/vnd.blueice.multipass' => ['mpm'], + 'application/vnd.bmi' => ['bmi'], + 'application/vnd.businessobjects' => ['rep'], + 'application/vnd.chemdraw+xml' => ['cdxml'], + 'application/vnd.chess-pgn' => ['pgn'], + 'application/vnd.chipnuts.karaoke-mmd' => ['mmd'], + 'application/vnd.cinderella' => ['cdy'], + 'application/vnd.claymore' => ['cla'], + 'application/vnd.cloanto.rp9' => ['rp9'], + 'application/vnd.clonk.c4group' => ['c4g', 'c4d', 'c4f', 'c4p', 'c4u'], + 'application/vnd.cluetrust.cartomobile-config' => ['c11amc'], + 'application/vnd.cluetrust.cartomobile-config-pkg' => ['c11amz'], + 'application/vnd.coffeescript' => ['coffee'], + 'application/vnd.comicbook+zip' => ['cbz'], + 'application/vnd.comicbook-rar' => ['cbr'], + 'application/vnd.commonspace' => ['csp'], + 'application/vnd.contact.cmsg' => ['cdbcmsg'], + 'application/vnd.corel-draw' => ['cdr'], + 'application/vnd.cosmocaller' => ['cmc'], + 'application/vnd.crick.clicker' => ['clkx'], + 'application/vnd.crick.clicker.keyboard' => ['clkk'], + 'application/vnd.crick.clicker.palette' => ['clkp'], + 'application/vnd.crick.clicker.template' => ['clkt'], + 'application/vnd.crick.clicker.wordbank' => ['clkw'], + 'application/vnd.criticaltools.wbs+xml' => ['wbs'], + 'application/vnd.ctc-posml' => ['pml'], + 'application/vnd.cups-ppd' => ['ppd'], + 'application/vnd.curl.car' => ['car'], + 'application/vnd.curl.pcurl' => ['pcurl'], + 'application/vnd.dart' => ['dart'], + 'application/vnd.data-vision.rdz' => ['rdz'], + 'application/vnd.debian.binary-package' => ['deb', 'udeb'], + 'application/vnd.dece.data' => ['uvf', 'uvvf', 'uvd', 'uvvd'], + 'application/vnd.dece.ttml+xml' => ['uvt', 'uvvt'], + 'application/vnd.dece.unspecified' => ['uvx', 'uvvx'], + 'application/vnd.dece.zip' => ['uvz', 'uvvz'], + 'application/vnd.denovo.fcselayout-link' => ['fe_launch'], + 'application/vnd.dna' => ['dna'], + 'application/vnd.dolby.mlp' => ['mlp'], + 'application/vnd.dpgraph' => ['dpg'], + 'application/vnd.dreamfactory' => ['dfac'], + 'application/vnd.ds-keypoint' => ['kpxx'], + 'application/vnd.dvb.ait' => ['ait'], + 'application/vnd.dvb.service' => ['svc'], + 'application/vnd.dynageo' => ['geo'], + 'application/vnd.ecowin.chart' => ['mag'], + 'application/vnd.emusic-emusic_package' => ['emp'], + 'application/vnd.enliven' => ['nml'], + 'application/vnd.epson.esf' => ['esf'], + 'application/vnd.epson.msf' => ['msf'], + 'application/vnd.epson.quickanime' => ['qam'], + 'application/vnd.epson.salt' => ['slt'], + 'application/vnd.epson.ssf' => ['ssf'], + 'application/vnd.eszigno3+xml' => ['es3', 'et3'], + 'application/vnd.ezpix-album' => ['ez2'], + 'application/vnd.ezpix-package' => ['ez3'], + 'application/vnd.fdf' => ['fdf'], + 'application/vnd.fdsn.mseed' => ['mseed'], + 'application/vnd.fdsn.seed' => ['seed', 'dataless'], + 'application/vnd.flatpak' => ['flatpak', 'xdgapp'], + 'application/vnd.flatpak.ref' => ['flatpakref'], + 'application/vnd.flatpak.repo' => ['flatpakrepo'], + 'application/vnd.flographit' => ['gph'], + 'application/vnd.fluxtime.clip' => ['ftc'], + 'application/vnd.framemaker' => ['fm', 'frame', 'maker', 'book'], + 'application/vnd.frogans.fnc' => ['fnc'], + 'application/vnd.frogans.ltf' => ['ltf'], + 'application/vnd.fsc.weblaunch' => ['fsc'], + 'application/vnd.fujitsu.oasys' => ['oas'], + 'application/vnd.fujitsu.oasys2' => ['oa2'], + 'application/vnd.fujitsu.oasys3' => ['oa3'], + 'application/vnd.fujitsu.oasysgp' => ['fg5'], + 'application/vnd.fujitsu.oasysprs' => ['bh2'], + 'application/vnd.fujixerox.ddd' => ['ddd'], + 'application/vnd.fujixerox.docuworks' => ['xdw'], + 'application/vnd.fujixerox.docuworks.binder' => ['xbd'], + 'application/vnd.fuzzysheet' => ['fzs'], + 'application/vnd.genomatix.tuxedo' => ['txd'], + 'application/vnd.geo+json' => ['geojson', 'geo.json'], + 'application/vnd.geogebra.file' => ['ggb'], + 'application/vnd.geogebra.tool' => ['ggt'], + 'application/vnd.geometry-explorer' => ['gex', 'gre'], + 'application/vnd.geonext' => ['gxt'], + 'application/vnd.geoplan' => ['g2w'], + 'application/vnd.geospace' => ['g3w'], + 'application/vnd.gmx' => ['gmx'], + 'application/vnd.google-earth.kml+xml' => ['kml'], + 'application/vnd.google-earth.kmz' => ['kmz'], + 'application/vnd.grafeq' => ['gqf', 'gqs'], + 'application/vnd.groove-account' => ['gac'], + 'application/vnd.groove-help' => ['ghf'], + 'application/vnd.groove-identity-message' => ['gim'], + 'application/vnd.groove-injector' => ['grv'], + 'application/vnd.groove-tool-message' => ['gtm'], + 'application/vnd.groove-tool-template' => ['tpl'], + 'application/vnd.groove-vcard' => ['vcg'], + 'application/vnd.haansoft-hwp' => ['hwp'], + 'application/vnd.haansoft-hwt' => ['hwt'], + 'application/vnd.hal+xml' => ['hal'], + 'application/vnd.handheld-entertainment+xml' => ['zmm'], + 'application/vnd.hbci' => ['hbci'], + 'application/vnd.hhe.lesson-player' => ['les'], + 'application/vnd.hp-hpgl' => ['hpgl'], + 'application/vnd.hp-hpid' => ['hpid'], + 'application/vnd.hp-hps' => ['hps'], + 'application/vnd.hp-jlyt' => ['jlt'], + 'application/vnd.hp-pcl' => ['pcl'], + 'application/vnd.hp-pclxl' => ['pclxl'], + 'application/vnd.hydrostatix.sof-data' => ['sfd-hdstx'], + 'application/vnd.ibm.minipay' => ['mpy'], + 'application/vnd.ibm.modcap' => ['afp', 'listafp', 'list3820'], + 'application/vnd.ibm.rights-management' => ['irm'], + 'application/vnd.ibm.secure-container' => ['sc'], + 'application/vnd.iccprofile' => ['icc', 'icm'], + 'application/vnd.igloader' => ['igl'], + 'application/vnd.immervision-ivp' => ['ivp'], + 'application/vnd.immervision-ivu' => ['ivu'], + 'application/vnd.insors.igm' => ['igm'], + 'application/vnd.intercon.formnet' => ['xpw', 'xpx'], + 'application/vnd.intergeo' => ['i2g'], + 'application/vnd.intu.qbo' => ['qbo'], + 'application/vnd.intu.qfx' => ['qfx'], + 'application/vnd.ipunplugged.rcprofile' => ['rcprofile'], + 'application/vnd.irepository.package+xml' => ['irp'], + 'application/vnd.is-xpr' => ['xpr'], + 'application/vnd.isac.fcs' => ['fcs'], + 'application/vnd.jam' => ['jam'], + 'application/vnd.jcp.javame.midlet-rms' => ['rms'], + 'application/vnd.jisp' => ['jisp'], + 'application/vnd.joost.joda-archive' => ['joda'], + 'application/vnd.kahootz' => ['ktz', 'ktr'], + 'application/vnd.kde.karbon' => ['karbon'], + 'application/vnd.kde.kchart' => ['chrt'], + 'application/vnd.kde.kformula' => ['kfo'], + 'application/vnd.kde.kivio' => ['flw'], + 'application/vnd.kde.kontour' => ['kon'], + 'application/vnd.kde.kpresenter' => ['kpr', 'kpt'], + 'application/vnd.kde.kspread' => ['ksp'], + 'application/vnd.kde.kword' => ['kwd', 'kwt'], + 'application/vnd.kenameaapp' => ['htke'], + 'application/vnd.kidspiration' => ['kia'], + 'application/vnd.kinar' => ['kne', 'knp'], + 'application/vnd.koan' => ['skp', 'skd', 'skt', 'skm'], + 'application/vnd.kodak-descriptor' => ['sse'], + 'application/vnd.las.las+xml' => ['lasxml'], + 'application/vnd.llamagraphics.life-balance.desktop' => ['lbd'], + 'application/vnd.llamagraphics.life-balance.exchange+xml' => ['lbe'], + 'application/vnd.lotus-1-2-3' => ['123', 'wk1', 'wk3', 'wk4', 'wks'], + 'application/vnd.lotus-approach' => ['apr'], + 'application/vnd.lotus-freelance' => ['pre'], + 'application/vnd.lotus-notes' => ['nsf'], + 'application/vnd.lotus-organizer' => ['org'], + 'application/vnd.lotus-screencam' => ['scm'], + 'application/vnd.lotus-wordpro' => ['lwp'], + 'application/vnd.macports.portpkg' => ['portpkg'], + 'application/vnd.mcd' => ['mcd'], + 'application/vnd.medcalcdata' => ['mc1'], + 'application/vnd.mediastation.cdkey' => ['cdkey'], + 'application/vnd.mfer' => ['mwf'], + 'application/vnd.mfmp' => ['mfm'], + 'application/vnd.micrografx.flo' => ['flo'], + 'application/vnd.micrografx.igx' => ['igx'], + 'application/vnd.mif' => ['mif'], + 'application/vnd.mobius.daf' => ['daf'], + 'application/vnd.mobius.dis' => ['dis'], + 'application/vnd.mobius.mbk' => ['mbk'], + 'application/vnd.mobius.mqy' => ['mqy'], + 'application/vnd.mobius.msl' => ['msl'], + 'application/vnd.mobius.plc' => ['plc'], + 'application/vnd.mobius.txf' => ['txf'], + 'application/vnd.mophun.application' => ['mpn'], + 'application/vnd.mophun.certificate' => ['mpc'], + 'application/vnd.mozilla.xul+xml' => ['xul'], + 'application/vnd.ms-access' => ['mdb'], + 'application/vnd.ms-artgalry' => ['cil'], + 'application/vnd.ms-asf' => ['asf'], + 'application/vnd.ms-cab-compressed' => ['cab'], + 'application/vnd.ms-excel' => ['xls', 'xlm', 'xla', 'xlc', 'xlt', 'xlw', 'xll', 'xld'], + 'application/vnd.ms-excel.addin.macroenabled.12' => ['xlam'], + 'application/vnd.ms-excel.sheet.binary.macroenabled.12' => ['xlsb'], + 'application/vnd.ms-excel.sheet.macroenabled.12' => ['xlsm'], + 'application/vnd.ms-excel.template.macroenabled.12' => ['xltm'], + 'application/vnd.ms-fontobject' => ['eot'], + 'application/vnd.ms-htmlhelp' => ['chm'], + 'application/vnd.ms-ims' => ['ims'], + 'application/vnd.ms-lrm' => ['lrm'], + 'application/vnd.ms-officetheme' => ['thmx'], + 'application/vnd.ms-pki.seccat' => ['cat'], + 'application/vnd.ms-pki.stl' => ['stl'], + 'application/vnd.ms-powerpoint' => ['ppt', 'pps', 'pot', 'ppz'], + 'application/vnd.ms-powerpoint.addin.macroenabled.12' => ['ppam'], + 'application/vnd.ms-powerpoint.presentation.macroenabled.12' => ['pptm'], + 'application/vnd.ms-powerpoint.slide.macroenabled.12' => ['sldm'], + 'application/vnd.ms-powerpoint.slideshow.macroenabled.12' => ['ppsm'], + 'application/vnd.ms-powerpoint.template.macroenabled.12' => ['potm'], + 'application/vnd.ms-project' => ['mpp', 'mpt'], + 'application/vnd.ms-publisher' => ['pub'], + 'application/vnd.ms-tnef' => ['tnef', 'tnf'], + 'application/vnd.ms-visio.drawing.macroenabled.main+xml' => ['vsdm'], + 'application/vnd.ms-visio.drawing.main+xml' => ['vsdx'], + 'application/vnd.ms-visio.stencil.macroenabled.main+xml' => ['vssm'], + 'application/vnd.ms-visio.stencil.main+xml' => ['vssx'], + 'application/vnd.ms-visio.template.macroenabled.main+xml' => ['vstm'], + 'application/vnd.ms-visio.template.main+xml' => ['vstx'], + 'application/vnd.ms-word' => ['doc'], + 'application/vnd.ms-word.document.macroenabled.12' => ['docm'], + 'application/vnd.ms-word.template.macroenabled.12' => ['dotm'], + 'application/vnd.ms-works' => ['wps', 'wks', 'wcm', 'wdb', 'xlr'], + 'application/vnd.ms-wpl' => ['wpl'], + 'application/vnd.ms-xpsdocument' => ['xps', 'oxps'], + 'application/vnd.msaccess' => ['mdb'], + 'application/vnd.mseq' => ['mseq'], + 'application/vnd.musician' => ['mus'], + 'application/vnd.muvee.style' => ['msty'], + 'application/vnd.mynfc' => ['taglet'], + 'application/vnd.neurolanguage.nlu' => ['nlu'], + 'application/vnd.nintendo.snes.rom' => ['sfc', 'smc'], + 'application/vnd.nitf' => ['ntf', 'nitf'], + 'application/vnd.noblenet-directory' => ['nnd'], + 'application/vnd.noblenet-sealer' => ['nns'], + 'application/vnd.noblenet-web' => ['nnw'], + 'application/vnd.nokia.n-gage.data' => ['ngdat'], + 'application/vnd.nokia.n-gage.symbian.install' => ['n-gage'], + 'application/vnd.nokia.radio-preset' => ['rpst'], + 'application/vnd.nokia.radio-presets' => ['rpss'], + 'application/vnd.novadigm.edm' => ['edm'], + 'application/vnd.novadigm.edx' => ['edx'], + 'application/vnd.novadigm.ext' => ['ext'], + 'application/vnd.oasis.docbook+xml' => ['dbk', 'docbook'], + 'application/vnd.oasis.opendocument.chart' => ['odc'], + 'application/vnd.oasis.opendocument.chart-template' => ['otc'], + 'application/vnd.oasis.opendocument.database' => ['odb'], + 'application/vnd.oasis.opendocument.formula' => ['odf'], + 'application/vnd.oasis.opendocument.formula-template' => ['odft', 'otf'], + 'application/vnd.oasis.opendocument.graphics' => ['odg'], + 'application/vnd.oasis.opendocument.graphics-flat-xml' => ['fodg'], + 'application/vnd.oasis.opendocument.graphics-template' => ['otg'], + 'application/vnd.oasis.opendocument.image' => ['odi'], + 'application/vnd.oasis.opendocument.image-template' => ['oti'], + 'application/vnd.oasis.opendocument.presentation' => ['odp'], + 'application/vnd.oasis.opendocument.presentation-flat-xml' => ['fodp'], + 'application/vnd.oasis.opendocument.presentation-template' => ['otp'], + 'application/vnd.oasis.opendocument.spreadsheet' => ['ods'], + 'application/vnd.oasis.opendocument.spreadsheet-flat-xml' => ['fods'], + 'application/vnd.oasis.opendocument.spreadsheet-template' => ['ots'], + 'application/vnd.oasis.opendocument.text' => ['odt'], + 'application/vnd.oasis.opendocument.text-flat-xml' => ['fodt'], + 'application/vnd.oasis.opendocument.text-master' => ['odm'], + 'application/vnd.oasis.opendocument.text-template' => ['ott'], + 'application/vnd.oasis.opendocument.text-web' => ['oth'], + 'application/vnd.olpc-sugar' => ['xo'], + 'application/vnd.oma.dd2+xml' => ['dd2'], + 'application/vnd.openofficeorg.extension' => ['oxt'], + 'application/vnd.openxmlformats-officedocument.presentationml.presentation' => ['pptx'], + 'application/vnd.openxmlformats-officedocument.presentationml.slide' => ['sldx'], + 'application/vnd.openxmlformats-officedocument.presentationml.slideshow' => ['ppsx'], + 'application/vnd.openxmlformats-officedocument.presentationml.template' => ['potx'], + 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' => ['xlsx'], + 'application/vnd.openxmlformats-officedocument.spreadsheetml.template' => ['xltx'], + 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' => ['docx'], + 'application/vnd.openxmlformats-officedocument.wordprocessingml.template' => ['dotx'], + 'application/vnd.osgeo.mapguide.package' => ['mgp'], + 'application/vnd.osgi.dp' => ['dp'], + 'application/vnd.osgi.subsystem' => ['esa'], + 'application/vnd.palm' => ['pdb', 'pqa', 'oprc', 'prc'], + 'application/vnd.pawaafile' => ['paw'], + 'application/vnd.pg.format' => ['str'], + 'application/vnd.pg.osasli' => ['ei6'], + 'application/vnd.picsel' => ['efif'], + 'application/vnd.pmi.widget' => ['wg'], + 'application/vnd.pocketlearn' => ['plf'], + 'application/vnd.powerbuilder6' => ['pbd'], + 'application/vnd.previewsystems.box' => ['box'], + 'application/vnd.proteus.magazine' => ['mgz'], + 'application/vnd.publishare-delta-tree' => ['qps'], + 'application/vnd.pvi.ptid1' => ['ptid'], + 'application/vnd.quark.quarkxpress' => ['qxd', 'qxt', 'qwd', 'qwt', 'qxl', 'qxb'], + 'application/vnd.rar' => ['rar'], + 'application/vnd.realvnc.bed' => ['bed'], + 'application/vnd.recordare.musicxml' => ['mxl'], + 'application/vnd.recordare.musicxml+xml' => ['musicxml'], + 'application/vnd.rig.cryptonote' => ['cryptonote'], + 'application/vnd.rim.cod' => ['cod'], + 'application/vnd.rn-realmedia' => ['rm', 'rmj', 'rmm', 'rms', 'rmx', 'rmvb'], + 'application/vnd.rn-realmedia-vbr' => ['rmvb', 'rm', 'rmj', 'rmm', 'rms', 'rmx'], + 'application/vnd.route66.link66+xml' => ['link66'], + 'application/vnd.sailingtracker.track' => ['st'], + 'application/vnd.sdp' => ['sdp'], + 'application/vnd.seemail' => ['see'], + 'application/vnd.sema' => ['sema'], + 'application/vnd.semd' => ['semd'], + 'application/vnd.semf' => ['semf'], + 'application/vnd.shana.informed.formdata' => ['ifm'], + 'application/vnd.shana.informed.formtemplate' => ['itp'], + 'application/vnd.shana.informed.interchange' => ['iif'], + 'application/vnd.shana.informed.package' => ['ipk'], + 'application/vnd.simtech-mindmapper' => ['twd', 'twds'], + 'application/vnd.smaf' => ['mmf', 'smaf'], + 'application/vnd.smart.teacher' => ['teacher'], + 'application/vnd.snap' => ['snap'], + 'application/vnd.solent.sdkm+xml' => ['sdkm', 'sdkd'], + 'application/vnd.spotfire.dxp' => ['dxp'], + 'application/vnd.spotfire.sfs' => ['sfs'], + 'application/vnd.sqlite3' => ['sqlite3'], + 'application/vnd.squashfs' => ['sqsh'], + 'application/vnd.stardivision.calc' => ['sdc'], + 'application/vnd.stardivision.chart' => ['sds'], + 'application/vnd.stardivision.draw' => ['sda'], + 'application/vnd.stardivision.impress' => ['sdd', 'sdp'], + 'application/vnd.stardivision.mail' => ['smd'], + 'application/vnd.stardivision.math' => ['smf'], + 'application/vnd.stardivision.writer' => ['sdw', 'vor', 'sgl'], + 'application/vnd.stardivision.writer-global' => ['sgl', 'sdw', 'vor'], + 'application/vnd.stepmania.package' => ['smzip'], + 'application/vnd.stepmania.stepchart' => ['sm'], + 'application/vnd.sun.xml.base' => ['odb'], + 'application/vnd.sun.xml.calc' => ['sxc'], + 'application/vnd.sun.xml.calc.template' => ['stc'], + 'application/vnd.sun.xml.draw' => ['sxd'], + 'application/vnd.sun.xml.draw.template' => ['std'], + 'application/vnd.sun.xml.impress' => ['sxi'], + 'application/vnd.sun.xml.impress.template' => ['sti'], + 'application/vnd.sun.xml.math' => ['sxm'], + 'application/vnd.sun.xml.writer' => ['sxw'], + 'application/vnd.sun.xml.writer.global' => ['sxg'], + 'application/vnd.sun.xml.writer.template' => ['stw'], + 'application/vnd.sus-calendar' => ['sus', 'susp'], + 'application/vnd.svd' => ['svd'], + 'application/vnd.symbian.install' => ['sis', 'sisx'], + 'application/vnd.syncml+xml' => ['xsm'], + 'application/vnd.syncml.dm+wbxml' => ['bdm'], + 'application/vnd.syncml.dm+xml' => ['xdm'], + 'application/vnd.tao.intent-module-archive' => ['tao'], + 'application/vnd.tcpdump.pcap' => ['pcap', 'cap', 'dmp'], + 'application/vnd.tmobile-livetv' => ['tmo'], + 'application/vnd.trid.tpt' => ['tpt'], + 'application/vnd.triscape.mxs' => ['mxs'], + 'application/vnd.trueapp' => ['tra'], + 'application/vnd.ufdl' => ['ufd', 'ufdl'], + 'application/vnd.uiq.theme' => ['utz'], + 'application/vnd.umajin' => ['umj'], + 'application/vnd.unity' => ['unityweb'], + 'application/vnd.uoml+xml' => ['uoml'], + 'application/vnd.vcx' => ['vcx'], + 'application/vnd.visio' => ['vsd', 'vst', 'vss', 'vsw'], + 'application/vnd.visionary' => ['vis'], + 'application/vnd.vsf' => ['vsf'], + 'application/vnd.wap.wbxml' => ['wbxml'], + 'application/vnd.wap.wmlc' => ['wmlc'], + 'application/vnd.wap.wmlscriptc' => ['wmlsc'], + 'application/vnd.webturbo' => ['wtb'], + 'application/vnd.wolfram.player' => ['nbp'], + 'application/vnd.wordperfect' => ['wpd', 'wp', 'wp4', 'wp5', 'wp6', 'wpp'], + 'application/vnd.wqd' => ['wqd'], + 'application/vnd.wt.stf' => ['stf'], + 'application/vnd.xara' => ['xar'], + 'application/vnd.xdgapp' => ['flatpak', 'xdgapp'], + 'application/vnd.xfdl' => ['xfdl'], + 'application/vnd.yamaha.hv-dic' => ['hvd'], + 'application/vnd.yamaha.hv-script' => ['hvs'], + 'application/vnd.yamaha.hv-voice' => ['hvp'], + 'application/vnd.yamaha.openscoreformat' => ['osf'], + 'application/vnd.yamaha.openscoreformat.osfpvg+xml' => ['osfpvg'], + 'application/vnd.yamaha.smaf-audio' => ['saf'], + 'application/vnd.yamaha.smaf-phrase' => ['spf'], + 'application/vnd.yellowriver-custom-menu' => ['cmp'], + 'application/vnd.youtube.yt' => ['yt'], + 'application/vnd.zul' => ['zir', 'zirz'], + 'application/vnd.zzazz.deck+xml' => ['zaz'], + 'application/voicexml+xml' => ['vxml'], + 'application/widget' => ['wgt'], + 'application/winhlp' => ['hlp'], + 'application/wk1' => ['123', 'wk1', 'wk3', 'wk4', 'wks'], + 'application/wmf' => ['wmf'], + 'application/wordperfect' => ['wp', 'wp4', 'wp5', 'wp6', 'wpd', 'wpp'], + 'application/wsdl+xml' => ['wsdl'], + 'application/wspolicy+xml' => ['wspolicy'], + 'application/wwf' => ['wwf'], + 'application/x-123' => ['123', 'wk1', 'wk3', 'wk4', 'wks'], + 'application/x-7z-compressed' => ['7z'], + 'application/x-abiword' => ['abw', 'abw.CRASHED', 'abw.gz', 'zabw'], + 'application/x-ace' => ['ace'], + 'application/x-ace-compressed' => ['ace'], + 'application/x-alz' => ['alz'], + 'application/x-amiga-disk-format' => ['adf'], + 'application/x-amipro' => ['sam'], + 'application/x-annodex' => ['anx'], + 'application/x-aportisdoc' => ['pdb', 'pdc'], + 'application/x-apple-diskimage' => ['dmg'], + 'application/x-applix-spreadsheet' => ['as'], + 'application/x-applix-word' => ['aw'], + 'application/x-archive' => ['a', 'ar'], + 'application/x-arj' => ['arj'], + 'application/x-asp' => ['asp'], + 'application/x-atari-2600-rom' => ['a26'], + 'application/x-atari-7800-rom' => ['a78'], + 'application/x-atari-lynx-rom' => ['lnx'], + 'application/x-authorware-bin' => ['aab', 'x32', 'u32', 'vox'], + 'application/x-authorware-map' => ['aam'], + 'application/x-authorware-seg' => ['aas'], + 'application/x-awk' => ['awk'], + 'application/x-bcpio' => ['bcpio'], + 'application/x-bittorrent' => ['torrent'], + 'application/x-blender' => ['blender', 'blend', 'BLEND'], + 'application/x-blorb' => ['blb', 'blorb'], + 'application/x-bsdiff' => ['bsdiff'], + 'application/x-bzdvi' => ['dvi.bz2'], + 'application/x-bzip' => ['bz', 'bz2'], + 'application/x-bzip-compressed-tar' => ['tar.bz2', 'tar.bz', 'tbz2', 'tbz', 'tb2'], + 'application/x-bzip2' => ['bz2', 'boz', 'bz'], + 'application/x-bzpdf' => ['pdf.bz2'], + 'application/x-bzpostscript' => ['ps.bz2'], + 'application/x-cb7' => ['cb7'], + 'application/x-cbr' => ['cbr', 'cba', 'cbt', 'cbz', 'cb7'], + 'application/x-cbt' => ['cbt'], + 'application/x-cbz' => ['cbz'], + 'application/x-ccmx' => ['ccmx'], + 'application/x-cd-image' => ['iso', 'iso9660'], + 'application/x-cdlink' => ['vcd'], + 'application/x-cdr' => ['cdr'], + 'application/x-cdrdao-toc' => ['toc'], + 'application/x-cfs-compressed' => ['cfs'], + 'application/x-chat' => ['chat'], + 'application/x-chess-pgn' => ['pgn'], + 'application/x-chm' => ['chm'], + 'application/x-cisco-vpn-settings' => ['pcf'], + 'application/x-compress' => ['Z'], + 'application/x-compressed-tar' => ['tar.gz', 'tgz'], + 'application/x-conference' => ['nsc'], + 'application/x-coreldraw' => ['cdr'], + 'application/x-cpio' => ['cpio'], + 'application/x-cpio-compressed' => ['cpio.gz'], + 'application/x-csh' => ['csh'], + 'application/x-cue' => ['cue'], + 'application/x-dar' => ['dar'], + 'application/x-dbase' => ['dbf'], + 'application/x-dbf' => ['dbf'], + 'application/x-dc-rom' => ['dc'], + 'application/x-deb' => ['deb', 'udeb'], + 'application/x-debian-package' => ['deb', 'udeb'], + 'application/x-designer' => ['ui'], + 'application/x-desktop' => ['desktop', 'kdelnk'], + 'application/x-dgc-compressed' => ['dgc'], + 'application/x-dia-diagram' => ['dia'], + 'application/x-dia-shape' => ['shape'], + 'application/x-director' => ['dir', 'dcr', 'dxr', 'cst', 'cct', 'cxt', 'w3d', 'fgd', 'swa'], + 'application/x-docbook+xml' => ['dbk', 'docbook'], + 'application/x-doom' => ['wad'], + 'application/x-doom-wad' => ['wad'], + 'application/x-dtbncx+xml' => ['ncx'], + 'application/x-dtbook+xml' => ['dtb'], + 'application/x-dtbresource+xml' => ['res'], + 'application/x-dvi' => ['dvi'], + 'application/x-e-theme' => ['etheme'], + 'application/x-egon' => ['egon'], + 'application/x-emf' => ['emf'], + 'application/x-envoy' => ['evy'], + 'application/x-eva' => ['eva'], + 'application/x-fd-file' => ['fd', 'qd'], + 'application/x-fds-disk' => ['fds'], + 'application/x-fictionbook' => ['fb2'], + 'application/x-fictionbook+xml' => ['fb2'], + 'application/x-flash-video' => ['flv'], + 'application/x-fluid' => ['fl'], + 'application/x-font-afm' => ['afm'], + 'application/x-font-bdf' => ['bdf'], + 'application/x-font-ghostscript' => ['gsf'], + 'application/x-font-linux-psf' => ['psf'], + 'application/x-font-otf' => ['otf'], + 'application/x-font-pcf' => ['pcf', 'pcf.Z', 'pcf.gz'], + 'application/x-font-snf' => ['snf'], + 'application/x-font-speedo' => ['spd'], + 'application/x-font-ttf' => ['ttf'], + 'application/x-font-ttx' => ['ttx'], + 'application/x-font-type1' => ['pfa', 'pfb', 'pfm', 'afm', 'gsf'], + 'application/x-font-woff' => ['woff'], + 'application/x-frame' => ['fm'], + 'application/x-freearc' => ['arc'], + 'application/x-futuresplash' => ['spl'], + 'application/x-gameboy-color-rom' => ['gbc', 'cgb'], + 'application/x-gameboy-rom' => ['gb', 'sgb'], + 'application/x-gamecube-iso-image' => ['iso'], + 'application/x-gamecube-rom' => ['iso'], + 'application/x-gamegear-rom' => ['gg'], + 'application/x-gba-rom' => ['gba', 'agb'], + 'application/x-gca-compressed' => ['gca'], + 'application/x-gedcom' => ['ged', 'gedcom'], + 'application/x-genesis-32x-rom' => ['32x', 'mdx'], + 'application/x-genesis-rom' => ['gen', 'smd'], + 'application/x-gettext' => ['po'], + 'application/x-gettext-translation' => ['gmo', 'mo'], + 'application/x-glade' => ['glade'], + 'application/x-glulx' => ['ulx'], + 'application/x-gnome-app-info' => ['desktop', 'kdelnk'], + 'application/x-gnucash' => ['gnucash', 'gnc', 'xac'], + 'application/x-gnumeric' => ['gnumeric'], + 'application/x-gnuplot' => ['gp', 'gplt', 'gnuplot'], + 'application/x-go-sgf' => ['sgf'], + 'application/x-gpx' => ['gpx'], + 'application/x-gpx+xml' => ['gpx'], + 'application/x-gramps-xml' => ['gramps'], + 'application/x-graphite' => ['gra'], + 'application/x-gtar' => ['gtar', 'tar', 'gem'], + 'application/x-gtk-builder' => ['ui'], + 'application/x-gz-font-linux-psf' => ['psf.gz'], + 'application/x-gzdvi' => ['dvi.gz'], + 'application/x-gzip' => ['gz'], + 'application/x-gzpdf' => ['pdf.gz'], + 'application/x-gzpostscript' => ['ps.gz'], + 'application/x-hdf' => ['hdf', 'hdf4', 'h4', 'hdf5', 'h5'], + 'application/x-hfe-file' => ['hfe'], + 'application/x-hfe-floppy-image' => ['hfe'], + 'application/x-hwp' => ['hwp'], + 'application/x-hwt' => ['hwt'], + 'application/x-ica' => ['ica'], + 'application/x-install-instructions' => ['install'], + 'application/x-ipynb+json' => ['ipynb'], + 'application/x-iso9660-appimage' => ['appimage'], + 'application/x-iso9660-image' => ['iso', 'iso9660'], + 'application/x-it87' => ['it87'], + 'application/x-iwork-keynote-sffkey' => ['key'], + 'application/x-jar' => ['jar'], + 'application/x-java' => ['class'], + 'application/x-java-archive' => ['jar'], + 'application/x-java-class' => ['class'], + 'application/x-java-jce-keystore' => ['jceks'], + 'application/x-java-jnlp-file' => ['jnlp'], + 'application/x-java-keystore' => ['jks', 'ks'], + 'application/x-java-pack200' => ['pack'], + 'application/x-java-vm' => ['class'], + 'application/x-javascript' => ['js', 'jsm', 'mjs'], + 'application/x-jbuilder-project' => ['jpr', 'jpx'], + 'application/x-karbon' => ['karbon'], + 'application/x-kchart' => ['chrt'], + 'application/x-kexi-connectiondata' => ['kexic'], + 'application/x-kexiproject-shortcut' => ['kexis'], + 'application/x-kexiproject-sqlite' => ['kexi'], + 'application/x-kexiproject-sqlite2' => ['kexi'], + 'application/x-kexiproject-sqlite3' => ['kexi'], + 'application/x-kformula' => ['kfo'], + 'application/x-killustrator' => ['kil'], + 'application/x-kivio' => ['flw'], + 'application/x-kontour' => ['kon'], + 'application/x-kpovmodeler' => ['kpm'], + 'application/x-kpresenter' => ['kpr', 'kpt'], + 'application/x-krita' => ['kra'], + 'application/x-kspread' => ['ksp'], + 'application/x-kugar' => ['kud'], + 'application/x-kword' => ['kwd', 'kwt'], + 'application/x-latex' => ['latex'], + 'application/x-lha' => ['lha', 'lzh'], + 'application/x-lhz' => ['lhz'], + 'application/x-linguist' => ['ts'], + 'application/x-lotus123' => ['123', 'wk1', 'wk3', 'wk4', 'wks'], + 'application/x-lrzip' => ['lrz'], + 'application/x-lrzip-compressed-tar' => ['tar.lrz', 'tlrz'], + 'application/x-lyx' => ['lyx'], + 'application/x-lz4' => ['lz4'], + 'application/x-lz4-compressed-tar' => ['tar.lz4'], + 'application/x-lzh-compressed' => ['lzh', 'lha'], + 'application/x-lzip' => ['lz'], + 'application/x-lzip-compressed-tar' => ['tar.lz'], + 'application/x-lzma' => ['lzma'], + 'application/x-lzma-compressed-tar' => ['tar.lzma', 'tlz'], + 'application/x-lzop' => ['lzo'], + 'application/x-lzpdf' => ['pdf.lz'], + 'application/x-m4' => ['m4'], + 'application/x-magicpoint' => ['mgp'], + 'application/x-markaby' => ['mab'], + 'application/x-mathematica' => ['nb'], + 'application/x-mdb' => ['mdb'], + 'application/x-mie' => ['mie'], + 'application/x-mif' => ['mif'], + 'application/x-mimearchive' => ['mhtml', 'mht'], + 'application/x-mobipocket-ebook' => ['prc', 'mobi'], + 'application/x-ms-application' => ['application'], + 'application/x-ms-asx' => ['asx', 'wax', 'wvx', 'wmx'], + 'application/x-ms-dos-executable' => ['exe'], + 'application/x-ms-shortcut' => ['lnk'], + 'application/x-ms-wim' => ['wim', 'swm'], + 'application/x-ms-wmd' => ['wmd'], + 'application/x-ms-wmz' => ['wmz'], + 'application/x-ms-xbap' => ['xbap'], + 'application/x-msaccess' => ['mdb'], + 'application/x-msbinder' => ['obd'], + 'application/x-mscardfile' => ['crd'], + 'application/x-msclip' => ['clp'], + 'application/x-msdownload' => ['exe', 'dll', 'com', 'bat', 'msi'], + 'application/x-msexcel' => ['xls', 'xlc', 'xll', 'xlm', 'xlw', 'xla', 'xlt', 'xld'], + 'application/x-msi' => ['msi'], + 'application/x-msmediaview' => ['mvb', 'm13', 'm14'], + 'application/x-msmetafile' => ['wmf', 'wmz', 'emf', 'emz'], + 'application/x-msmoney' => ['mny'], + 'application/x-mspowerpoint' => ['ppz', 'ppt', 'pps', 'pot'], + 'application/x-mspublisher' => ['pub'], + 'application/x-msschedule' => ['scd'], + 'application/x-msterminal' => ['trm'], + 'application/x-mswinurl' => ['url'], + 'application/x-msword' => ['doc'], + 'application/x-mswrite' => ['wri'], + 'application/x-msx-rom' => ['msx'], + 'application/x-n64-rom' => ['n64', 'z64', 'v64'], + 'application/x-navi-animation' => ['ani'], + 'application/x-neo-geo-pocket-color-rom' => ['ngc'], + 'application/x-neo-geo-pocket-rom' => ['ngp'], + 'application/x-nes-rom' => ['nes', 'nez', 'unf', 'unif'], + 'application/x-netcdf' => ['nc', 'cdf'], + 'application/x-netshow-channel' => ['nsc'], + 'application/x-nintendo-ds-rom' => ['nds'], + 'application/x-nzb' => ['nzb'], + 'application/x-object' => ['o'], + 'application/x-ogg' => ['ogx'], + 'application/x-oleo' => ['oleo'], + 'application/x-pagemaker' => ['p65', 'pm', 'pm6', 'pmd'], + 'application/x-pak' => ['pak'], + 'application/x-palm-database' => ['prc', 'pdb', 'pqa', 'oprc'], + 'application/x-par2' => ['PAR2', 'par2'], + 'application/x-partial-download' => ['wkdownload', 'crdownload', 'part'], + 'application/x-pc-engine-rom' => ['pce'], + 'application/x-pcap' => ['pcap', 'cap', 'dmp'], + 'application/x-pdf' => ['pdf'], + 'application/x-perl' => ['pl', 'PL', 'pm', 'al', 'perl', 'pod', 't'], + 'application/x-photoshop' => ['psd'], + 'application/x-php' => ['php', 'php3', 'php4', 'php5', 'phps'], + 'application/x-pkcs12' => ['p12', 'pfx'], + 'application/x-pkcs7-certificates' => ['p7b', 'spc'], + 'application/x-pkcs7-certreqresp' => ['p7r'], + 'application/x-planperfect' => ['pln'], + 'application/x-pocket-word' => ['psw'], + 'application/x-pw' => ['pw'], + 'application/x-python-bytecode' => ['pyc', 'pyo'], + 'application/x-qpress' => ['qp'], + 'application/x-qtiplot' => ['qti', 'qti.gz'], + 'application/x-quattropro' => ['wb1', 'wb2', 'wb3'], + 'application/x-quicktime-media-link' => ['qtl'], + 'application/x-quicktimeplayer' => ['qtl'], + 'application/x-qw' => ['qif'], + 'application/x-rar' => ['rar'], + 'application/x-rar-compressed' => ['rar'], + 'application/x-raw-disk-image' => ['raw-disk-image', 'img'], + 'application/x-raw-disk-image-xz-compressed' => ['raw-disk-image.xz', 'img.xz'], + 'application/x-raw-floppy-disk-image' => ['fd', 'qd'], + 'application/x-redhat-package-manager' => ['rpm'], + 'application/x-reject' => ['rej'], + 'application/x-research-info-systems' => ['ris'], + 'application/x-rnc' => ['rnc'], + 'application/x-rpm' => ['rpm'], + 'application/x-ruby' => ['rb'], + 'application/x-sami' => ['smi', 'sami'], + 'application/x-sap-file' => ['sap'], + 'application/x-saturn-rom' => ['bin', 'iso'], + 'application/x-sdp' => ['sdp'], + 'application/x-sega-cd-rom' => ['bin', 'iso'], + 'application/x-sg1000-rom' => ['sg'], + 'application/x-sh' => ['sh'], + 'application/x-shar' => ['shar'], + 'application/x-shared-library-la' => ['la'], + 'application/x-sharedlib' => ['so'], + 'application/x-shellscript' => ['sh'], + 'application/x-shockwave-flash' => ['swf', 'spl'], + 'application/x-shorten' => ['shn'], + 'application/x-siag' => ['siag'], + 'application/x-silverlight-app' => ['xap'], + 'application/x-sit' => ['sit'], + 'application/x-smaf' => ['mmf', 'smaf'], + 'application/x-sms-rom' => ['sms'], + 'application/x-snes-rom' => ['sfc', 'smc'], + 'application/x-source-rpm' => ['src.rpm', 'spm'], + 'application/x-spss-por' => ['por'], + 'application/x-spss-sav' => ['sav', 'zsav'], + 'application/x-spss-savefile' => ['sav', 'zsav'], + 'application/x-sql' => ['sql'], + 'application/x-sqlite2' => ['sqlite2'], + 'application/x-sqlite3' => ['sqlite3'], + 'application/x-srt' => ['srt'], + 'application/x-stuffit' => ['sit'], + 'application/x-stuffitx' => ['sitx'], + 'application/x-subrip' => ['srt'], + 'application/x-sv4cpio' => ['sv4cpio'], + 'application/x-sv4crc' => ['sv4crc'], + 'application/x-t3vm-image' => ['t3'], + 'application/x-t602' => ['602'], + 'application/x-tads' => ['gam'], + 'application/x-tar' => ['tar', 'gtar', 'gem'], + 'application/x-tarz' => ['tar.Z', 'taz'], + 'application/x-tcl' => ['tcl'], + 'application/x-tex' => ['tex', 'ltx', 'sty', 'cls', 'dtx', 'ins', 'latex'], + 'application/x-tex-gf' => ['gf'], + 'application/x-tex-pk' => ['pk'], + 'application/x-tex-tfm' => ['tfm'], + 'application/x-texinfo' => ['texinfo', 'texi'], + 'application/x-tgif' => ['obj'], + 'application/x-theme' => ['theme'], + 'application/x-thomson-cartridge-memo7' => ['m7'], + 'application/x-thomson-cassette' => ['k7'], + 'application/x-thomson-sap-image' => ['sap'], + 'application/x-trash' => ['bak', 'old', 'sik'], + 'application/x-trig' => ['trig'], + 'application/x-troff' => ['tr', 'roff', 't'], + 'application/x-troff-man' => ['man'], + 'application/x-tzo' => ['tar.lzo', 'tzo'], + 'application/x-ufraw' => ['ufraw'], + 'application/x-ustar' => ['ustar'], + 'application/x-virtual-boy-rom' => ['vb'], + 'application/x-vnd.kde.kexi' => ['kexi'], + 'application/x-wais-source' => ['src'], + 'application/x-wbfs' => ['iso'], + 'application/x-wia' => ['iso'], + 'application/x-wii-iso-image' => ['iso'], + 'application/x-wii-rom' => ['iso'], + 'application/x-wii-wad' => ['wad'], + 'application/x-windows-themepack' => ['themepack'], + 'application/x-wmf' => ['wmf'], + 'application/x-wonderswan-color-rom' => ['wsc'], + 'application/x-wonderswan-rom' => ['ws'], + 'application/x-wordperfect' => ['wp', 'wp4', 'wp5', 'wp6', 'wpd', 'wpp'], + 'application/x-wpg' => ['wpg'], + 'application/x-wwf' => ['wwf'], + 'application/x-x509-ca-cert' => ['der', 'crt', 'cert', 'pem'], + 'application/x-xar' => ['xar', 'pkg'], + 'application/x-xbel' => ['xbel'], + 'application/x-xfig' => ['fig'], + 'application/x-xliff' => ['xlf', 'xliff'], + 'application/x-xliff+xml' => ['xlf'], + 'application/x-xpinstall' => ['xpi'], + 'application/x-xspf+xml' => ['xspf'], + 'application/x-xz' => ['xz'], + 'application/x-xz-compressed-tar' => ['tar.xz', 'txz'], + 'application/x-xzpdf' => ['pdf.xz'], + 'application/x-yaml' => ['yaml', 'yml'], + 'application/x-zip' => ['zip'], + 'application/x-zip-compressed' => ['zip'], + 'application/x-zip-compressed-fb2' => ['fb2.zip'], + 'application/x-zmachine' => ['z1', 'z2', 'z3', 'z4', 'z5', 'z6', 'z7', 'z8'], + 'application/x-zoo' => ['zoo'], + 'application/xaml+xml' => ['xaml'], + 'application/xcap-diff+xml' => ['xdf'], + 'application/xenc+xml' => ['xenc'], + 'application/xhtml+xml' => ['xhtml', 'xht'], + 'application/xliff+xml' => ['xlf', 'xliff'], + 'application/xml' => ['xml', 'xsl', 'xbl', 'xsd', 'rng'], + 'application/xml-dtd' => ['dtd'], + 'application/xml-external-parsed-entity' => ['ent'], + 'application/xop+xml' => ['xop'], + 'application/xproc+xml' => ['xpl'], + 'application/xps' => ['oxps', 'xps'], + 'application/xslt+xml' => ['xslt', 'xsl'], + 'application/xspf+xml' => ['xspf'], + 'application/xv+xml' => ['mxml', 'xhvml', 'xvml', 'xvm'], + 'application/yang' => ['yang'], + 'application/yin+xml' => ['yin'], + 'application/zip' => ['zip'], + 'application/zlib' => ['zz'], + 'audio/3gpp' => ['3gp', '3gpp', '3ga'], + 'audio/3gpp-encrypted' => ['3gp', '3gpp', '3ga'], + 'audio/3gpp2' => ['3g2', '3gp2', '3gpp2'], + 'audio/aac' => ['aac', 'adts', 'ass'], + 'audio/ac3' => ['ac3'], + 'audio/adpcm' => ['adp'], + 'audio/amr' => ['amr'], + 'audio/amr-encrypted' => ['amr'], + 'audio/amr-wb' => ['awb'], + 'audio/amr-wb-encrypted' => ['awb'], + 'audio/annodex' => ['axa'], + 'audio/basic' => ['au', 'snd'], + 'audio/flac' => ['flac'], + 'audio/imelody' => ['imy', 'ime'], + 'audio/m3u' => ['m3u', 'm3u8', 'vlc'], + 'audio/m4a' => ['m4a', 'f4a'], + 'audio/midi' => ['mid', 'midi', 'kar', 'rmi'], + 'audio/mobile-xmf' => ['xmf'], + 'audio/mp2' => ['mp2'], + 'audio/mp3' => ['mp3', 'mpga'], + 'audio/mp4' => ['m4a', 'mp4a', 'f4a'], + 'audio/mpeg' => ['mpga', 'mp2', 'mp2a', 'mp3', 'm2a', 'm3a'], + 'audio/mpegurl' => ['m3u', 'm3u8', 'vlc'], + 'audio/ogg' => ['oga', 'ogg', 'spx', 'opus'], + 'audio/prs.sid' => ['sid', 'psid'], + 'audio/s3m' => ['s3m'], + 'audio/scpls' => ['pls'], + 'audio/silk' => ['sil'], + 'audio/tta' => ['tta'], + 'audio/usac' => ['loas', 'xhe'], + 'audio/vnd.audible' => ['aa', 'aax'], + 'audio/vnd.audible.aax' => ['aa', 'aax'], + 'audio/vnd.dece.audio' => ['uva', 'uvva'], + 'audio/vnd.digital-winds' => ['eol'], + 'audio/vnd.dra' => ['dra'], + 'audio/vnd.dts' => ['dts'], + 'audio/vnd.dts.hd' => ['dtshd'], + 'audio/vnd.lucent.voice' => ['lvp'], + 'audio/vnd.m-realaudio' => ['ra', 'rax'], + 'audio/vnd.ms-playready.media.pya' => ['pya'], + 'audio/vnd.nuera.ecelp4800' => ['ecelp4800'], + 'audio/vnd.nuera.ecelp7470' => ['ecelp7470'], + 'audio/vnd.nuera.ecelp9600' => ['ecelp9600'], + 'audio/vnd.rip' => ['rip'], + 'audio/vnd.rn-realaudio' => ['ra', 'rax'], + 'audio/vnd.wave' => ['wav'], + 'audio/vorbis' => ['oga', 'ogg'], + 'audio/wav' => ['wav'], + 'audio/webm' => ['weba'], + 'audio/wma' => ['wma'], + 'audio/x-aac' => ['aac', 'adts', 'ass'], + 'audio/x-aifc' => ['aifc', 'aiffc'], + 'audio/x-aiff' => ['aif', 'aiff', 'aifc'], + 'audio/x-aiffc' => ['aifc', 'aiffc'], + 'audio/x-amzxml' => ['amz'], + 'audio/x-annodex' => ['axa'], + 'audio/x-ape' => ['ape'], + 'audio/x-caf' => ['caf'], + 'audio/x-dts' => ['dts'], + 'audio/x-dtshd' => ['dtshd'], + 'audio/x-flac' => ['flac'], + 'audio/x-flac+ogg' => ['oga', 'ogg'], + 'audio/x-gsm' => ['gsm'], + 'audio/x-hx-aac-adts' => ['aac', 'adts', 'ass'], + 'audio/x-imelody' => ['imy', 'ime'], + 'audio/x-iriver-pla' => ['pla'], + 'audio/x-it' => ['it'], + 'audio/x-m3u' => ['m3u', 'm3u8', 'vlc'], + 'audio/x-m4a' => ['m4a', 'f4a'], + 'audio/x-m4b' => ['m4b', 'f4b'], + 'audio/x-m4r' => ['m4r'], + 'audio/x-matroska' => ['mka'], + 'audio/x-midi' => ['mid', 'midi', 'kar'], + 'audio/x-minipsf' => ['minipsf'], + 'audio/x-mo3' => ['mo3'], + 'audio/x-mod' => ['mod', 'ult', 'uni', 'm15', 'mtm', '669', 'med'], + 'audio/x-mp2' => ['mp2'], + 'audio/x-mp3' => ['mp3', 'mpga'], + 'audio/x-mp3-playlist' => ['m3u', 'm3u8', 'vlc'], + 'audio/x-mpeg' => ['mp3', 'mpga'], + 'audio/x-mpegurl' => ['m3u', 'm3u8', 'vlc'], + 'audio/x-mpg' => ['mp3', 'mpga'], + 'audio/x-ms-asx' => ['asx', 'wax', 'wvx', 'wmx'], + 'audio/x-ms-wax' => ['wax'], + 'audio/x-ms-wma' => ['wma'], + 'audio/x-musepack' => ['mpc', 'mpp', 'mp+'], + 'audio/x-ogg' => ['oga', 'ogg', 'opus'], + 'audio/x-oggflac' => ['oga', 'ogg'], + 'audio/x-opus+ogg' => ['opus'], + 'audio/x-pn-audibleaudio' => ['aa', 'aax'], + 'audio/x-pn-realaudio' => ['ram', 'ra', 'rax'], + 'audio/x-pn-realaudio-plugin' => ['rmp'], + 'audio/x-psf' => ['psf'], + 'audio/x-psflib' => ['psflib'], + 'audio/x-rn-3gpp-amr' => ['3gp', '3gpp', '3ga'], + 'audio/x-rn-3gpp-amr-encrypted' => ['3gp', '3gpp', '3ga'], + 'audio/x-rn-3gpp-amr-wb' => ['3gp', '3gpp', '3ga'], + 'audio/x-rn-3gpp-amr-wb-encrypted' => ['3gp', '3gpp', '3ga'], + 'audio/x-s3m' => ['s3m'], + 'audio/x-scpls' => ['pls'], + 'audio/x-shorten' => ['shn'], + 'audio/x-speex' => ['spx'], + 'audio/x-speex+ogg' => ['oga', 'ogg'], + 'audio/x-stm' => ['stm'], + 'audio/x-tta' => ['tta'], + 'audio/x-voc' => ['voc'], + 'audio/x-vorbis' => ['oga', 'ogg'], + 'audio/x-vorbis+ogg' => ['oga', 'ogg'], + 'audio/x-wav' => ['wav'], + 'audio/x-wavpack' => ['wv', 'wvp'], + 'audio/x-wavpack-correction' => ['wvc'], + 'audio/x-xi' => ['xi'], + 'audio/x-xm' => ['xm'], + 'audio/x-xmf' => ['xmf'], + 'audio/xm' => ['xm'], + 'audio/xmf' => ['xmf'], + 'chemical/x-cdx' => ['cdx'], + 'chemical/x-cif' => ['cif'], + 'chemical/x-cmdf' => ['cmdf'], + 'chemical/x-cml' => ['cml'], + 'chemical/x-csml' => ['csml'], + 'chemical/x-xyz' => ['xyz'], + 'flv-application/octet-stream' => ['flv'], + 'font/collection' => ['ttc'], + 'font/otf' => ['otf'], + 'font/ttf' => ['ttf'], + 'font/woff' => ['woff', 'woff2'], + 'font/woff2' => ['woff2'], + 'image/bmp' => ['bmp', 'dib'], + 'image/cdr' => ['cdr'], + 'image/cgm' => ['cgm'], + 'image/emf' => ['emf'], + 'image/fax-g3' => ['g3'], + 'image/fits' => ['fits'], + 'image/g3fax' => ['g3'], + 'image/gif' => ['gif'], + 'image/heic' => ['heic', 'heif'], + 'image/heic-sequence' => ['heic', 'heif'], + 'image/heif' => ['heic', 'heif'], + 'image/heif-sequence' => ['heic', 'heif'], + 'image/ico' => ['ico'], + 'image/icon' => ['ico'], + 'image/ief' => ['ief'], + 'image/jp2' => ['jp2', 'jpg2'], + 'image/jpeg' => ['jpeg', 'jpg', 'jpe'], + 'image/jpeg2000' => ['jp2', 'jpg2'], + 'image/jpeg2000-image' => ['jp2', 'jpg2'], + 'image/jpm' => ['jpm', 'jpgm'], + 'image/jpx' => ['jpf', 'jpx'], + 'image/ktx' => ['ktx'], + 'image/openraster' => ['ora'], + 'image/pdf' => ['pdf'], + 'image/photoshop' => ['psd'], + 'image/pjpeg' => ['jpeg', 'jpg', 'jpe'], + 'image/png' => ['png'], + 'image/prs.btif' => ['btif'], + 'image/psd' => ['psd'], + 'image/rle' => ['rle'], + 'image/sgi' => ['sgi'], + 'image/svg+xml' => ['svg', 'svgz'], + 'image/svg+xml-compressed' => ['svgz'], + 'image/tiff' => ['tiff', 'tif'], + 'image/vnd.adobe.photoshop' => ['psd'], + 'image/vnd.dece.graphic' => ['uvi', 'uvvi', 'uvg', 'uvvg'], + 'image/vnd.djvu' => ['djvu', 'djv'], + 'image/vnd.djvu+multipage' => ['djvu', 'djv'], + 'image/vnd.dvb.subtitle' => ['sub'], + 'image/vnd.dwg' => ['dwg'], + 'image/vnd.dxf' => ['dxf'], + 'image/vnd.fastbidsheet' => ['fbs'], + 'image/vnd.fpx' => ['fpx'], + 'image/vnd.fst' => ['fst'], + 'image/vnd.fujixerox.edmics-mmr' => ['mmr'], + 'image/vnd.fujixerox.edmics-rlc' => ['rlc'], + 'image/vnd.microsoft.icon' => ['ico'], + 'image/vnd.ms-modi' => ['mdi'], + 'image/vnd.ms-photo' => ['wdp'], + 'image/vnd.net-fpx' => ['npx'], + 'image/vnd.rn-realpix' => ['rp'], + 'image/vnd.wap.wbmp' => ['wbmp'], + 'image/vnd.xiff' => ['xif'], + 'image/vnd.zbrush.pcx' => ['pcx'], + 'image/webp' => ['webp'], + 'image/wmf' => ['wmf'], + 'image/x-3ds' => ['3ds'], + 'image/x-adobe-dng' => ['dng'], + 'image/x-applix-graphics' => ['ag'], + 'image/x-bmp' => ['bmp', 'dib'], + 'image/x-bzeps' => ['eps.bz2', 'epsi.bz2', 'epsf.bz2'], + 'image/x-canon-cr2' => ['cr2'], + 'image/x-canon-crw' => ['crw'], + 'image/x-cdr' => ['cdr'], + 'image/x-cmu-raster' => ['ras'], + 'image/x-cmx' => ['cmx'], + 'image/x-compressed-xcf' => ['xcf.gz', 'xcf.bz2'], + 'image/x-dds' => ['dds'], + 'image/x-djvu' => ['djvu', 'djv'], + 'image/x-emf' => ['emf'], + 'image/x-eps' => ['eps', 'epsi', 'epsf'], + 'image/x-exr' => ['exr'], + 'image/x-fits' => ['fits'], + 'image/x-freehand' => ['fh', 'fhc', 'fh4', 'fh5', 'fh7'], + 'image/x-fuji-raf' => ['raf'], + 'image/x-gimp-gbr' => ['gbr'], + 'image/x-gimp-gih' => ['gih'], + 'image/x-gimp-pat' => ['pat'], + 'image/x-gzeps' => ['eps.gz', 'epsi.gz', 'epsf.gz'], + 'image/x-icb' => ['tga', 'icb', 'tpic', 'vda', 'vst'], + 'image/x-icns' => ['icns'], + 'image/x-ico' => ['ico'], + 'image/x-icon' => ['ico'], + 'image/x-iff' => ['iff', 'ilbm', 'lbm'], + 'image/x-ilbm' => ['iff', 'ilbm', 'lbm'], + 'image/x-jng' => ['jng'], + 'image/x-jp2-codestream' => ['j2c', 'j2k', 'jpc'], + 'image/x-jpeg2000-image' => ['jp2', 'jpg2'], + 'image/x-kodak-dcr' => ['dcr'], + 'image/x-kodak-k25' => ['k25'], + 'image/x-kodak-kdc' => ['kdc'], + 'image/x-lwo' => ['lwo', 'lwob'], + 'image/x-lws' => ['lws'], + 'image/x-macpaint' => ['pntg'], + 'image/x-minolta-mrw' => ['mrw'], + 'image/x-mrsid-image' => ['sid'], + 'image/x-ms-bmp' => ['bmp', 'dib'], + 'image/x-msod' => ['msod'], + 'image/x-nikon-nef' => ['nef'], + 'image/x-olympus-orf' => ['orf'], + 'image/x-panasonic-raw' => ['raw'], + 'image/x-panasonic-raw2' => ['rw2'], + 'image/x-panasonic-rw' => ['raw'], + 'image/x-panasonic-rw2' => ['rw2'], + 'image/x-pcx' => ['pcx'], + 'image/x-pentax-pef' => ['pef'], + 'image/x-photo-cd' => ['pcd'], + 'image/x-photoshop' => ['psd'], + 'image/x-pict' => ['pic', 'pct', 'pict', 'pict1', 'pict2'], + 'image/x-portable-anymap' => ['pnm'], + 'image/x-portable-bitmap' => ['pbm'], + 'image/x-portable-graymap' => ['pgm'], + 'image/x-portable-pixmap' => ['ppm'], + 'image/x-psd' => ['psd'], + 'image/x-quicktime' => ['qtif', 'qif'], + 'image/x-rgb' => ['rgb'], + 'image/x-sgi' => ['sgi'], + 'image/x-sigma-x3f' => ['x3f'], + 'image/x-skencil' => ['sk', 'sk1'], + 'image/x-sony-arw' => ['arw'], + 'image/x-sony-sr2' => ['sr2'], + 'image/x-sony-srf' => ['srf'], + 'image/x-sun-raster' => ['sun'], + 'image/x-tga' => ['tga', 'icb', 'tpic', 'vda', 'vst'], + 'image/x-win-bitmap' => ['cur'], + 'image/x-win-metafile' => ['wmf'], + 'image/x-wmf' => ['wmf'], + 'image/x-xbitmap' => ['xbm'], + 'image/x-xcf' => ['xcf'], + 'image/x-xfig' => ['fig'], + 'image/x-xpixmap' => ['xpm'], + 'image/x-xpm' => ['xpm'], + 'image/x-xwindowdump' => ['xwd'], + 'image/x.djvu' => ['djvu', 'djv'], + 'message/rfc822' => ['eml', 'mime'], + 'model/iges' => ['igs', 'iges'], + 'model/mesh' => ['msh', 'mesh', 'silo'], + 'model/stl' => ['stl'], + 'model/vnd.collada+xml' => ['dae'], + 'model/vnd.dwf' => ['dwf'], + 'model/vnd.gdl' => ['gdl'], + 'model/vnd.gtw' => ['gtw'], + 'model/vnd.mts' => ['mts'], + 'model/vnd.vtu' => ['vtu'], + 'model/vrml' => ['wrl', 'vrml', 'vrm'], + 'model/x.stl-ascii' => ['stl'], + 'model/x.stl-binary' => ['stl'], + 'model/x3d+binary' => ['x3db', 'x3dbz'], + 'model/x3d+vrml' => ['x3dv', 'x3dvz'], + 'model/x3d+xml' => ['x3d', 'x3dz'], + 'text/cache-manifest' => ['appcache', 'manifest'], + 'text/calendar' => ['ics', 'ifb', 'vcs'], + 'text/css' => ['css'], + 'text/csv' => ['csv'], + 'text/csv-schema' => ['csvs'], + 'text/directory' => ['vcard', 'vcf', 'vct', 'gcrd'], + 'text/ecmascript' => ['es'], + 'text/gedcom' => ['ged', 'gedcom'], + 'text/google-video-pointer' => ['gvp'], + 'text/html' => ['html', 'htm'], + 'text/ico' => ['ico'], + 'text/javascript' => ['js', 'jsm', 'mjs'], + 'text/markdown' => ['md', 'mkd', 'markdown'], + 'text/mathml' => ['mml'], + 'text/n3' => ['n3'], + 'text/plain' => ['txt', 'text', 'conf', 'def', 'list', 'log', 'in', 'asc'], + 'text/prs.lines.tag' => ['dsc'], + 'text/rdf' => ['rdf', 'rdfs', 'owl'], + 'text/richtext' => ['rtx'], + 'text/rss' => ['rss'], + 'text/rtf' => ['rtf'], + 'text/rust' => ['rs'], + 'text/sgml' => ['sgml', 'sgm'], + 'text/spreadsheet' => ['sylk', 'slk'], + 'text/tab-separated-values' => ['tsv'], + 'text/troff' => ['t', 'tr', 'roff', 'man', 'me', 'ms'], + 'text/turtle' => ['ttl'], + 'text/uri-list' => ['uri', 'uris', 'urls'], + 'text/vcard' => ['vcard', 'vcf', 'vct', 'gcrd'], + 'text/vnd.curl' => ['curl'], + 'text/vnd.curl.dcurl' => ['dcurl'], + 'text/vnd.curl.mcurl' => ['mcurl'], + 'text/vnd.curl.scurl' => ['scurl'], + 'text/vnd.dvb.subtitle' => ['sub'], + 'text/vnd.fly' => ['fly'], + 'text/vnd.fmi.flexstor' => ['flx'], + 'text/vnd.graphviz' => ['gv', 'dot'], + 'text/vnd.in3d.3dml' => ['3dml'], + 'text/vnd.in3d.spot' => ['spot'], + 'text/vnd.qt.linguist' => ['ts'], + 'text/vnd.rn-realtext' => ['rt'], + 'text/vnd.sun.j2me.app-descriptor' => ['jad'], + 'text/vnd.trolltech.linguist' => ['ts'], + 'text/vnd.wap.wml' => ['wml'], + 'text/vnd.wap.wmlscript' => ['wmls'], + 'text/vtt' => ['vtt'], + 'text/x-adasrc' => ['adb', 'ads'], + 'text/x-asm' => ['s', 'asm'], + 'text/x-bibtex' => ['bib'], + 'text/x-c' => ['c', 'cc', 'cxx', 'cpp', 'h', 'hh', 'dic'], + 'text/x-c++hdr' => ['hh', 'hp', 'hpp', 'h++', 'hxx'], + 'text/x-c++src' => ['cpp', 'cxx', 'cc', 'C', 'c++'], + 'text/x-chdr' => ['h'], + 'text/x-cmake' => ['cmake'], + 'text/x-cobol' => ['cbl', 'cob'], + 'text/x-comma-separated-values' => ['csv'], + 'text/x-csharp' => ['cs'], + 'text/x-csrc' => ['c'], + 'text/x-csv' => ['csv'], + 'text/x-dbus-service' => ['service'], + 'text/x-dcl' => ['dcl'], + 'text/x-diff' => ['diff', 'patch'], + 'text/x-dsl' => ['dsl'], + 'text/x-dsrc' => ['d', 'di'], + 'text/x-dtd' => ['dtd'], + 'text/x-eiffel' => ['e', 'eif'], + 'text/x-emacs-lisp' => ['el'], + 'text/x-erlang' => ['erl'], + 'text/x-fortran' => ['f', 'for', 'f77', 'f90', 'f95'], + 'text/x-genie' => ['gs'], + 'text/x-gettext-translation' => ['po'], + 'text/x-gettext-translation-template' => ['pot'], + 'text/x-gherkin' => ['feature'], + 'text/x-go' => ['go'], + 'text/x-google-video-pointer' => ['gvp'], + 'text/x-haskell' => ['hs'], + 'text/x-idl' => ['idl'], + 'text/x-imelody' => ['imy', 'ime'], + 'text/x-iptables' => ['iptables'], + 'text/x-java' => ['java'], + 'text/x-java-source' => ['java'], + 'text/x-ldif' => ['ldif'], + 'text/x-lilypond' => ['ly'], + 'text/x-literate-haskell' => ['lhs'], + 'text/x-log' => ['log'], + 'text/x-lua' => ['lua'], + 'text/x-lyx' => ['lyx'], + 'text/x-makefile' => ['mk', 'mak'], + 'text/x-markdown' => ['md', 'mkd', 'markdown'], + 'text/x-matlab' => ['m'], + 'text/x-microdvd' => ['sub'], + 'text/x-moc' => ['moc'], + 'text/x-modelica' => ['mo'], + 'text/x-mof' => ['mof'], + 'text/x-mpsub' => ['sub'], + 'text/x-mrml' => ['mrml', 'mrl'], + 'text/x-ms-regedit' => ['reg'], + 'text/x-mup' => ['mup', 'not'], + 'text/x-nfo' => ['nfo'], + 'text/x-objcsrc' => ['m'], + 'text/x-ocaml' => ['ml', 'mli'], + 'text/x-ocl' => ['ocl'], + 'text/x-octave' => ['m'], + 'text/x-ooc' => ['ooc'], + 'text/x-opencl-src' => ['cl'], + 'text/x-opml' => ['opml'], + 'text/x-opml+xml' => ['opml'], + 'text/x-pascal' => ['p', 'pas'], + 'text/x-patch' => ['diff', 'patch'], + 'text/x-perl' => ['pl', 'PL', 'pm', 'al', 'perl', 'pod', 't'], + 'text/x-po' => ['po'], + 'text/x-pot' => ['pot'], + 'text/x-python' => ['py', 'pyx', 'wsgi'], + 'text/x-python3' => ['py', 'py3', 'py3x'], + 'text/x-qml' => ['qml', 'qmltypes', 'qmlproject'], + 'text/x-reject' => ['rej'], + 'text/x-rpm-spec' => ['spec'], + 'text/x-sass' => ['sass'], + 'text/x-scala' => ['scala'], + 'text/x-scheme' => ['scm', 'ss'], + 'text/x-scss' => ['scss'], + 'text/x-setext' => ['etx'], + 'text/x-sfv' => ['sfv'], + 'text/x-sh' => ['sh'], + 'text/x-sql' => ['sql'], + 'text/x-ssa' => ['ssa', 'ass'], + 'text/x-subviewer' => ['sub'], + 'text/x-svhdr' => ['svh'], + 'text/x-svsrc' => ['sv'], + 'text/x-systemd-unit' => ['automount', 'device', 'mount', 'path', 'scope', 'service', 'slice', 'socket', 'swap', 'target', 'timer'], + 'text/x-tcl' => ['tcl', 'tk'], + 'text/x-tex' => ['tex', 'ltx', 'sty', 'cls', 'dtx', 'ins', 'latex'], + 'text/x-texinfo' => ['texi', 'texinfo'], + 'text/x-troff' => ['tr', 'roff', 't'], + 'text/x-troff-me' => ['me'], + 'text/x-troff-mm' => ['mm'], + 'text/x-troff-ms' => ['ms'], + 'text/x-twig' => ['twig'], + 'text/x-txt2tags' => ['t2t'], + 'text/x-uil' => ['uil'], + 'text/x-uuencode' => ['uu', 'uue'], + 'text/x-vala' => ['vala', 'vapi'], + 'text/x-vcalendar' => ['vcs', 'ics'], + 'text/x-vcard' => ['vcf', 'vcard', 'vct', 'gcrd'], + 'text/x-verilog' => ['v'], + 'text/x-vhdl' => ['vhd', 'vhdl'], + 'text/x-xmi' => ['xmi'], + 'text/x-xslfo' => ['fo', 'xslfo'], + 'text/x-yaml' => ['yaml', 'yml'], + 'text/x.gcode' => ['gcode'], + 'text/xml' => ['xml', 'xbl', 'xsd', 'rng'], + 'text/xml-external-parsed-entity' => ['ent'], + 'text/yaml' => ['yaml', 'yml'], + 'video/3gp' => ['3gp', '3gpp', '3ga'], + 'video/3gpp' => ['3gp', '3gpp', '3ga'], + 'video/3gpp-encrypted' => ['3gp', '3gpp', '3ga'], + 'video/3gpp2' => ['3g2', '3gp2', '3gpp2'], + 'video/annodex' => ['axv'], + 'video/avi' => ['avi', 'avf', 'divx'], + 'video/divx' => ['avi', 'avf', 'divx'], + 'video/dv' => ['dv'], + 'video/fli' => ['fli', 'flc'], + 'video/flv' => ['flv'], + 'video/h261' => ['h261'], + 'video/h263' => ['h263'], + 'video/h264' => ['h264'], + 'video/jpeg' => ['jpgv'], + 'video/jpm' => ['jpm', 'jpgm'], + 'video/mj2' => ['mj2', 'mjp2'], + 'video/mp2t' => ['m2t', 'm2ts', 'ts', 'mts', 'cpi', 'clpi', 'mpl', 'mpls', 'bdm', 'bdmv'], + 'video/mp4' => ['mp4', 'mp4v', 'mpg4', 'm4v', 'f4v', 'lrv'], + 'video/mp4v-es' => ['mp4', 'm4v', 'f4v', 'lrv'], + 'video/mpeg' => ['mpeg', 'mpg', 'mpe', 'm1v', 'm2v', 'mp2', 'vob'], + 'video/mpeg-system' => ['mpeg', 'mpg', 'mp2', 'mpe', 'vob'], + 'video/msvideo' => ['avi', 'avf', 'divx'], + 'video/ogg' => ['ogv', 'ogg'], + 'video/quicktime' => ['qt', 'mov', 'moov', 'qtvr'], + 'video/vivo' => ['viv', 'vivo'], + 'video/vnd.dece.hd' => ['uvh', 'uvvh'], + 'video/vnd.dece.mobile' => ['uvm', 'uvvm'], + 'video/vnd.dece.pd' => ['uvp', 'uvvp'], + 'video/vnd.dece.sd' => ['uvs', 'uvvs'], + 'video/vnd.dece.video' => ['uvv', 'uvvv'], + 'video/vnd.divx' => ['avi', 'avf', 'divx'], + 'video/vnd.dvb.file' => ['dvb'], + 'video/vnd.fvt' => ['fvt'], + 'video/vnd.mpegurl' => ['mxu', 'm4u', 'm1u'], + 'video/vnd.ms-playready.media.pyv' => ['pyv'], + 'video/vnd.rn-realvideo' => ['rv', 'rvx'], + 'video/vnd.uvvu.mp4' => ['uvu', 'uvvu'], + 'video/vnd.vivo' => ['viv', 'vivo'], + 'video/webm' => ['webm'], + 'video/x-anim' => ['anim[1-9j]'], + 'video/x-annodex' => ['axv'], + 'video/x-avi' => ['avi', 'avf', 'divx'], + 'video/x-f4v' => ['f4v'], + 'video/x-fli' => ['fli', 'flc'], + 'video/x-flic' => ['fli', 'flc'], + 'video/x-flv' => ['flv'], + 'video/x-javafx' => ['fxm'], + 'video/x-m4v' => ['m4v', 'mp4', 'f4v', 'lrv'], + 'video/x-matroska' => ['mkv', 'mk3d', 'mks'], + 'video/x-matroska-3d' => ['mk3d'], + 'video/x-mjpeg' => ['mjpeg', 'mjpg'], + 'video/x-mng' => ['mng'], + 'video/x-mpeg' => ['mpeg', 'mpg', 'mp2', 'mpe', 'vob'], + 'video/x-mpeg-system' => ['mpeg', 'mpg', 'mp2', 'mpe', 'vob'], + 'video/x-mpeg2' => ['mpeg', 'mpg', 'mp2', 'mpe', 'vob'], + 'video/x-mpegurl' => ['m1u', 'm4u', 'mxu'], + 'video/x-ms-asf' => ['asf', 'asx'], + 'video/x-ms-asf-plugin' => ['asf'], + 'video/x-ms-vob' => ['vob'], + 'video/x-ms-wax' => ['asx', 'wax', 'wvx', 'wmx'], + 'video/x-ms-wm' => ['wm', 'asf'], + 'video/x-ms-wmv' => ['wmv'], + 'video/x-ms-wmx' => ['wmx', 'asx', 'wax', 'wvx'], + 'video/x-ms-wvx' => ['wvx', 'asx', 'wax', 'wmx'], + 'video/x-msvideo' => ['avi', 'avf', 'divx'], + 'video/x-nsv' => ['nsv'], + 'video/x-ogg' => ['ogv', 'ogg'], + 'video/x-ogm' => ['ogm'], + 'video/x-ogm+ogg' => ['ogm'], + 'video/x-real-video' => ['rv', 'rvx'], + 'video/x-sgi-movie' => ['movie'], + 'video/x-smv' => ['smv'], + 'video/x-theora' => ['ogg'], + 'video/x-theora+ogg' => ['ogg'], + 'x-conference/x-cooltalk' => ['ice'], + 'x-epoc/x-sisx-app' => ['sisx'], + 'zz-application/zz-winassoc-123' => ['123', 'wk1', 'wk3', 'wk4', 'wks'], + 'zz-application/zz-winassoc-cab' => ['cab'], + 'zz-application/zz-winassoc-cdr' => ['cdr'], + 'zz-application/zz-winassoc-doc' => ['doc'], + 'zz-application/zz-winassoc-hlp' => ['hlp'], + 'zz-application/zz-winassoc-mdb' => ['mdb'], + 'zz-application/zz-winassoc-uu' => ['uue'], + 'zz-application/zz-winassoc-xls' => ['xls', 'xlc', 'xll', 'xlm', 'xlw', 'xla', 'xlt', 'xld'], + ]; + + private static $reverseMap = [ + '32x' => ['application/x-genesis-32x-rom'], + '3dml' => ['text/vnd.in3d.3dml'], + '3ds' => ['image/x-3ds'], + '3g2' => ['audio/3gpp2', 'video/3gpp2'], + '3ga' => ['audio/3gpp', 'audio/3gpp-encrypted', 'audio/x-rn-3gpp-amr', 'audio/x-rn-3gpp-amr-encrypted', 'audio/x-rn-3gpp-amr-wb', 'audio/x-rn-3gpp-amr-wb-encrypted', 'video/3gp', 'video/3gpp', 'video/3gpp-encrypted'], + '3gp' => ['audio/3gpp', 'audio/3gpp-encrypted', 'audio/x-rn-3gpp-amr', 'audio/x-rn-3gpp-amr-encrypted', 'audio/x-rn-3gpp-amr-wb', 'audio/x-rn-3gpp-amr-wb-encrypted', 'video/3gp', 'video/3gpp', 'video/3gpp-encrypted'], + '3gp2' => ['audio/3gpp2', 'video/3gpp2'], + '3gpp' => ['audio/3gpp', 'audio/3gpp-encrypted', 'audio/x-rn-3gpp-amr', 'audio/x-rn-3gpp-amr-encrypted', 'audio/x-rn-3gpp-amr-wb', 'audio/x-rn-3gpp-amr-wb-encrypted', 'video/3gp', 'video/3gpp', 'video/3gpp-encrypted'], + '3gpp2' => ['audio/3gpp2', 'video/3gpp2'], + '7z' => ['application/x-7z-compressed'], + 'BLEND' => ['application/x-blender'], + 'C' => ['text/x-c++src'], + 'PAR2' => ['application/x-par2'], + 'PL' => ['application/x-perl', 'text/x-perl'], + 'Z' => ['application/x-compress'], + 'a' => ['application/x-archive'], + 'a26' => ['application/x-atari-2600-rom'], + 'a78' => ['application/x-atari-7800-rom'], + 'aa' => ['audio/vnd.audible', 'audio/vnd.audible.aax', 'audio/x-pn-audibleaudio'], + 'aab' => ['application/x-authorware-bin'], + 'aac' => ['audio/aac', 'audio/x-aac', 'audio/x-hx-aac-adts'], + 'aam' => ['application/x-authorware-map'], + 'aas' => ['application/x-authorware-seg'], + 'aax' => ['audio/vnd.audible', 'audio/vnd.audible.aax', 'audio/x-pn-audibleaudio'], + 'abw' => ['application/x-abiword'], + 'abw.CRASHED' => ['application/x-abiword'], + 'abw.gz' => ['application/x-abiword'], + 'ac' => ['application/pkix-attr-cert'], + 'ac3' => ['audio/ac3'], + 'acc' => ['application/vnd.americandynamics.acc'], + 'ace' => ['application/x-ace', 'application/x-ace-compressed'], + 'acu' => ['application/vnd.acucobol'], + 'acutc' => ['application/vnd.acucorp'], + 'adb' => ['text/x-adasrc'], + 'adf' => ['application/x-amiga-disk-format'], + 'adp' => ['audio/adpcm'], + 'ads' => ['text/x-adasrc'], + 'adts' => ['audio/aac', 'audio/x-aac', 'audio/x-hx-aac-adts'], + 'aep' => ['application/vnd.audiograph'], + 'afm' => ['application/x-font-afm', 'application/x-font-type1'], + 'afp' => ['application/vnd.ibm.modcap'], + 'ag' => ['image/x-applix-graphics'], + 'agb' => ['application/x-gba-rom'], + 'ahead' => ['application/vnd.ahead.space'], + 'ai' => ['application/illustrator', 'application/postscript', 'application/vnd.adobe.illustrator'], + 'aif' => ['audio/x-aiff'], + 'aifc' => ['audio/x-aifc', 'audio/x-aiff', 'audio/x-aiffc'], + 'aiff' => ['audio/x-aiff'], + 'aiffc' => ['audio/x-aifc', 'audio/x-aiffc'], + 'air' => ['application/vnd.adobe.air-application-installer-package+zip'], + 'ait' => ['application/vnd.dvb.ait'], + 'al' => ['application/x-perl', 'text/x-perl'], + 'alz' => ['application/x-alz'], + 'ami' => ['application/vnd.amiga.ami'], + 'amr' => ['audio/amr', 'audio/amr-encrypted'], + 'amz' => ['audio/x-amzxml'], + 'ani' => ['application/x-navi-animation'], + 'anim[1-9j]' => ['video/x-anim'], + 'anx' => ['application/annodex', 'application/x-annodex'], + 'ape' => ['audio/x-ape'], + 'apk' => ['application/vnd.android.package-archive'], + 'appcache' => ['text/cache-manifest'], + 'appimage' => ['application/vnd.appimage', 'application/x-iso9660-appimage'], + 'application' => ['application/x-ms-application'], + 'apr' => ['application/vnd.lotus-approach'], + 'aps' => ['application/postscript'], + 'ar' => ['application/x-archive'], + 'arc' => ['application/x-freearc'], + 'arj' => ['application/x-arj'], + 'arw' => ['image/x-sony-arw'], + 'as' => ['application/x-applix-spreadsheet'], + 'asc' => ['application/pgp', 'application/pgp-encrypted', 'application/pgp-keys', 'application/pgp-signature', 'text/plain'], + 'asf' => ['application/vnd.ms-asf', 'video/x-ms-asf', 'video/x-ms-asf-plugin', 'video/x-ms-wm'], + 'asm' => ['text/x-asm'], + 'aso' => ['application/vnd.accpac.simply.aso'], + 'asp' => ['application/x-asp'], + 'ass' => ['audio/aac', 'audio/x-aac', 'audio/x-hx-aac-adts', 'text/x-ssa'], + 'asx' => ['application/x-ms-asx', 'audio/x-ms-asx', 'video/x-ms-asf', 'video/x-ms-wax', 'video/x-ms-wmx', 'video/x-ms-wvx'], + 'atc' => ['application/vnd.acucorp'], + 'atom' => ['application/atom+xml'], + 'atomcat' => ['application/atomcat+xml'], + 'atomsvc' => ['application/atomsvc+xml'], + 'atx' => ['application/vnd.antix.game-component'], + 'au' => ['audio/basic'], + 'automount' => ['text/x-systemd-unit'], + 'avf' => ['video/avi', 'video/divx', 'video/msvideo', 'video/vnd.divx', 'video/x-avi', 'video/x-msvideo'], + 'avi' => ['video/avi', 'video/divx', 'video/msvideo', 'video/vnd.divx', 'video/x-avi', 'video/x-msvideo'], + 'aw' => ['application/applixware', 'application/x-applix-word'], + 'awb' => ['audio/amr-wb', 'audio/amr-wb-encrypted'], + 'awk' => ['application/x-awk'], + 'axa' => ['audio/annodex', 'audio/x-annodex'], + 'axv' => ['video/annodex', 'video/x-annodex'], + 'azf' => ['application/vnd.airzip.filesecure.azf'], + 'azs' => ['application/vnd.airzip.filesecure.azs'], + 'azw' => ['application/vnd.amazon.ebook'], + 'bak' => ['application/x-trash'], + 'bat' => ['application/x-msdownload'], + 'bcpio' => ['application/x-bcpio'], + 'bdf' => ['application/x-font-bdf'], + 'bdm' => ['application/vnd.syncml.dm+wbxml', 'video/mp2t'], + 'bdmv' => ['video/mp2t'], + 'bed' => ['application/vnd.realvnc.bed'], + 'bh2' => ['application/vnd.fujitsu.oasysprs'], + 'bib' => ['text/x-bibtex'], + 'bin' => ['application/octet-stream', 'application/x-saturn-rom', 'application/x-sega-cd-rom'], + 'blb' => ['application/x-blorb'], + 'blend' => ['application/x-blender'], + 'blender' => ['application/x-blender'], + 'blorb' => ['application/x-blorb'], + 'bmi' => ['application/vnd.bmi'], + 'bmp' => ['image/bmp', 'image/x-bmp', 'image/x-ms-bmp'], + 'book' => ['application/vnd.framemaker'], + 'box' => ['application/vnd.previewsystems.box'], + 'boz' => ['application/x-bzip2'], + 'bpk' => ['application/octet-stream'], + 'bsdiff' => ['application/x-bsdiff'], + 'btif' => ['image/prs.btif'], + 'bz' => ['application/x-bzip', 'application/x-bzip2'], + 'bz2' => ['application/x-bz2', 'application/x-bzip', 'application/x-bzip2'], + 'c' => ['text/x-c', 'text/x-csrc'], + 'c++' => ['text/x-c++src'], + 'c11amc' => ['application/vnd.cluetrust.cartomobile-config'], + 'c11amz' => ['application/vnd.cluetrust.cartomobile-config-pkg'], + 'c4d' => ['application/vnd.clonk.c4group'], + 'c4f' => ['application/vnd.clonk.c4group'], + 'c4g' => ['application/vnd.clonk.c4group'], + 'c4p' => ['application/vnd.clonk.c4group'], + 'c4u' => ['application/vnd.clonk.c4group'], + 'cab' => ['application/vnd.ms-cab-compressed', 'zz-application/zz-winassoc-cab'], + 'caf' => ['audio/x-caf'], + 'cap' => ['application/pcap', 'application/vnd.tcpdump.pcap', 'application/x-pcap'], + 'car' => ['application/vnd.curl.car'], + 'cat' => ['application/vnd.ms-pki.seccat'], + 'cb7' => ['application/x-cb7', 'application/x-cbr'], + 'cba' => ['application/x-cbr'], + 'cbl' => ['text/x-cobol'], + 'cbr' => ['application/vnd.comicbook-rar', 'application/x-cbr'], + 'cbt' => ['application/x-cbr', 'application/x-cbt'], + 'cbz' => ['application/vnd.comicbook+zip', 'application/x-cbr', 'application/x-cbz'], + 'cc' => ['text/x-c', 'text/x-c++src'], + 'ccmx' => ['application/x-ccmx'], + 'cct' => ['application/x-director'], + 'ccxml' => ['application/ccxml+xml'], + 'cdbcmsg' => ['application/vnd.contact.cmsg'], + 'cdf' => ['application/x-netcdf'], + 'cdkey' => ['application/vnd.mediastation.cdkey'], + 'cdmia' => ['application/cdmi-capability'], + 'cdmic' => ['application/cdmi-container'], + 'cdmid' => ['application/cdmi-domain'], + 'cdmio' => ['application/cdmi-object'], + 'cdmiq' => ['application/cdmi-queue'], + 'cdr' => ['application/cdr', 'application/coreldraw', 'application/vnd.corel-draw', 'application/x-cdr', 'application/x-coreldraw', 'image/cdr', 'image/x-cdr', 'zz-application/zz-winassoc-cdr'], + 'cdx' => ['chemical/x-cdx'], + 'cdxml' => ['application/vnd.chemdraw+xml'], + 'cdy' => ['application/vnd.cinderella'], + 'cer' => ['application/pkix-cert'], + 'cert' => ['application/x-x509-ca-cert'], + 'cfs' => ['application/x-cfs-compressed'], + 'cgb' => ['application/x-gameboy-color-rom'], + 'cgm' => ['image/cgm'], + 'chat' => ['application/x-chat'], + 'chm' => ['application/vnd.ms-htmlhelp', 'application/x-chm'], + 'chrt' => ['application/vnd.kde.kchart', 'application/x-kchart'], + 'cif' => ['chemical/x-cif'], + 'cii' => ['application/vnd.anser-web-certificate-issue-initiation'], + 'cil' => ['application/vnd.ms-artgalry'], + 'cl' => ['text/x-opencl-src'], + 'cla' => ['application/vnd.claymore'], + 'class' => ['application/java', 'application/java-byte-code', 'application/java-vm', 'application/x-java', 'application/x-java-class', 'application/x-java-vm'], + 'clkk' => ['application/vnd.crick.clicker.keyboard'], + 'clkp' => ['application/vnd.crick.clicker.palette'], + 'clkt' => ['application/vnd.crick.clicker.template'], + 'clkw' => ['application/vnd.crick.clicker.wordbank'], + 'clkx' => ['application/vnd.crick.clicker'], + 'clp' => ['application/x-msclip'], + 'clpi' => ['video/mp2t'], + 'cls' => ['application/x-tex', 'text/x-tex'], + 'cmake' => ['text/x-cmake'], + 'cmc' => ['application/vnd.cosmocaller'], + 'cmdf' => ['chemical/x-cmdf'], + 'cml' => ['chemical/x-cml'], + 'cmp' => ['application/vnd.yellowriver-custom-menu'], + 'cmx' => ['image/x-cmx'], + 'cob' => ['text/x-cobol'], + 'cod' => ['application/vnd.rim.cod'], + 'coffee' => ['application/vnd.coffeescript'], + 'com' => ['application/x-msdownload'], + 'conf' => ['text/plain'], + 'cpi' => ['video/mp2t'], + 'cpio' => ['application/x-cpio'], + 'cpio.gz' => ['application/x-cpio-compressed'], + 'cpp' => ['text/x-c', 'text/x-c++src'], + 'cpt' => ['application/mac-compactpro'], + 'cr2' => ['image/x-canon-cr2'], + 'crd' => ['application/x-mscardfile'], + 'crdownload' => ['application/x-partial-download'], + 'crl' => ['application/pkix-crl'], + 'crt' => ['application/x-x509-ca-cert'], + 'crw' => ['image/x-canon-crw'], + 'cryptonote' => ['application/vnd.rig.cryptonote'], + 'cs' => ['text/x-csharp'], + 'csh' => ['application/x-csh'], + 'csml' => ['chemical/x-csml'], + 'csp' => ['application/vnd.commonspace'], + 'css' => ['text/css'], + 'cst' => ['application/x-director'], + 'csv' => ['text/csv', 'text/x-comma-separated-values', 'text/x-csv'], + 'csvs' => ['text/csv-schema'], + 'cu' => ['application/cu-seeme'], + 'cue' => ['application/x-cue'], + 'cur' => ['image/x-win-bitmap'], + 'curl' => ['text/vnd.curl'], + 'cww' => ['application/prs.cww'], + 'cxt' => ['application/x-director'], + 'cxx' => ['text/x-c', 'text/x-c++src'], + 'd' => ['text/x-dsrc'], + 'dae' => ['model/vnd.collada+xml'], + 'daf' => ['application/vnd.mobius.daf'], + 'dar' => ['application/x-dar'], + 'dart' => ['application/vnd.dart'], + 'dataless' => ['application/vnd.fdsn.seed'], + 'davmount' => ['application/davmount+xml'], + 'dbf' => ['application/dbase', 'application/dbf', 'application/x-dbase', 'application/x-dbf'], + 'dbk' => ['application/docbook+xml', 'application/vnd.oasis.docbook+xml', 'application/x-docbook+xml'], + 'dc' => ['application/x-dc-rom'], + 'dcl' => ['text/x-dcl'], + 'dcm' => ['application/dicom'], + 'dcr' => ['application/x-director', 'image/x-kodak-dcr'], + 'dcurl' => ['text/vnd.curl.dcurl'], + 'dd2' => ['application/vnd.oma.dd2+xml'], + 'ddd' => ['application/vnd.fujixerox.ddd'], + 'dds' => ['image/x-dds'], + 'deb' => ['application/vnd.debian.binary-package', 'application/x-deb', 'application/x-debian-package'], + 'def' => ['text/plain'], + 'deploy' => ['application/octet-stream'], + 'der' => ['application/x-x509-ca-cert'], + 'desktop' => ['application/x-desktop', 'application/x-gnome-app-info'], + 'device' => ['text/x-systemd-unit'], + 'dfac' => ['application/vnd.dreamfactory'], + 'dgc' => ['application/x-dgc-compressed'], + 'di' => ['text/x-dsrc'], + 'dia' => ['application/x-dia-diagram'], + 'dib' => ['image/bmp', 'image/x-bmp', 'image/x-ms-bmp'], + 'dic' => ['text/x-c'], + 'diff' => ['text/x-diff', 'text/x-patch'], + 'dir' => ['application/x-director'], + 'dis' => ['application/vnd.mobius.dis'], + 'dist' => ['application/octet-stream'], + 'distz' => ['application/octet-stream'], + 'divx' => ['video/avi', 'video/divx', 'video/msvideo', 'video/vnd.divx', 'video/x-avi', 'video/x-msvideo'], + 'djv' => ['image/vnd.djvu', 'image/vnd.djvu+multipage', 'image/x-djvu', 'image/x.djvu'], + 'djvu' => ['image/vnd.djvu', 'image/vnd.djvu+multipage', 'image/x-djvu', 'image/x.djvu'], + 'dll' => ['application/x-msdownload'], + 'dmg' => ['application/x-apple-diskimage'], + 'dmp' => ['application/pcap', 'application/vnd.tcpdump.pcap', 'application/x-pcap'], + 'dms' => ['application/octet-stream'], + 'dna' => ['application/vnd.dna'], + 'dng' => ['image/x-adobe-dng'], + 'doc' => ['application/msword', 'application/vnd.ms-word', 'application/x-msword', 'zz-application/zz-winassoc-doc'], + 'docbook' => ['application/docbook+xml', 'application/vnd.oasis.docbook+xml', 'application/x-docbook+xml'], + 'docm' => ['application/vnd.ms-word.document.macroenabled.12'], + 'docx' => ['application/vnd.openxmlformats-officedocument.wordprocessingml.document'], + 'dot' => ['application/msword', 'application/msword-template', 'text/vnd.graphviz'], + 'dotm' => ['application/vnd.ms-word.template.macroenabled.12'], + 'dotx' => ['application/vnd.openxmlformats-officedocument.wordprocessingml.template'], + 'dp' => ['application/vnd.osgi.dp'], + 'dpg' => ['application/vnd.dpgraph'], + 'dra' => ['audio/vnd.dra'], + 'dsc' => ['text/prs.lines.tag'], + 'dsl' => ['text/x-dsl'], + 'dssc' => ['application/dssc+der'], + 'dtb' => ['application/x-dtbook+xml'], + 'dtd' => ['application/xml-dtd', 'text/x-dtd'], + 'dts' => ['audio/vnd.dts', 'audio/x-dts'], + 'dtshd' => ['audio/vnd.dts.hd', 'audio/x-dtshd'], + 'dtx' => ['application/x-tex', 'text/x-tex'], + 'dump' => ['application/octet-stream'], + 'dv' => ['video/dv'], + 'dvb' => ['video/vnd.dvb.file'], + 'dvi' => ['application/x-dvi'], + 'dvi.bz2' => ['application/x-bzdvi'], + 'dvi.gz' => ['application/x-gzdvi'], + 'dwf' => ['model/vnd.dwf'], + 'dwg' => ['image/vnd.dwg'], + 'dxf' => ['image/vnd.dxf'], + 'dxp' => ['application/vnd.spotfire.dxp'], + 'dxr' => ['application/x-director'], + 'e' => ['text/x-eiffel'], + 'ecelp4800' => ['audio/vnd.nuera.ecelp4800'], + 'ecelp7470' => ['audio/vnd.nuera.ecelp7470'], + 'ecelp9600' => ['audio/vnd.nuera.ecelp9600'], + 'ecma' => ['application/ecmascript'], + 'edm' => ['application/vnd.novadigm.edm'], + 'edx' => ['application/vnd.novadigm.edx'], + 'efif' => ['application/vnd.picsel'], + 'egon' => ['application/x-egon'], + 'ei6' => ['application/vnd.pg.osasli'], + 'eif' => ['text/x-eiffel'], + 'el' => ['text/x-emacs-lisp'], + 'elc' => ['application/octet-stream'], + 'emf' => ['application/emf', 'application/x-emf', 'application/x-msmetafile', 'image/emf', 'image/x-emf'], + 'eml' => ['message/rfc822'], + 'emma' => ['application/emma+xml'], + 'emp' => ['application/vnd.emusic-emusic_package'], + 'emz' => ['application/x-msmetafile'], + 'ent' => ['application/xml-external-parsed-entity', 'text/xml-external-parsed-entity'], + 'eol' => ['audio/vnd.digital-winds'], + 'eot' => ['application/vnd.ms-fontobject'], + 'eps' => ['application/postscript', 'image/x-eps'], + 'eps.bz2' => ['image/x-bzeps'], + 'eps.gz' => ['image/x-gzeps'], + 'epsf' => ['image/x-eps'], + 'epsf.bz2' => ['image/x-bzeps'], + 'epsf.gz' => ['image/x-gzeps'], + 'epsi' => ['image/x-eps'], + 'epsi.bz2' => ['image/x-bzeps'], + 'epsi.gz' => ['image/x-gzeps'], + 'epub' => ['application/epub+zip'], + 'erl' => ['text/x-erlang'], + 'es' => ['application/ecmascript', 'text/ecmascript'], + 'es3' => ['application/vnd.eszigno3+xml'], + 'esa' => ['application/vnd.osgi.subsystem'], + 'esf' => ['application/vnd.epson.esf'], + 'et3' => ['application/vnd.eszigno3+xml'], + 'etheme' => ['application/x-e-theme'], + 'etx' => ['text/x-setext'], + 'eva' => ['application/x-eva'], + 'evy' => ['application/x-envoy'], + 'exe' => ['application/x-ms-dos-executable', 'application/x-msdownload'], + 'exi' => ['application/exi'], + 'exr' => ['image/x-exr'], + 'ext' => ['application/vnd.novadigm.ext'], + 'ez' => ['application/andrew-inset'], + 'ez2' => ['application/vnd.ezpix-album'], + 'ez3' => ['application/vnd.ezpix-package'], + 'f' => ['text/x-fortran'], + 'f4a' => ['audio/m4a', 'audio/mp4', 'audio/x-m4a'], + 'f4b' => ['audio/x-m4b'], + 'f4v' => ['video/mp4', 'video/mp4v-es', 'video/x-f4v', 'video/x-m4v'], + 'f77' => ['text/x-fortran'], + 'f90' => ['text/x-fortran'], + 'f95' => ['text/x-fortran'], + 'fb2' => ['application/x-fictionbook', 'application/x-fictionbook+xml'], + 'fb2.zip' => ['application/x-zip-compressed-fb2'], + 'fbs' => ['image/vnd.fastbidsheet'], + 'fcdt' => ['application/vnd.adobe.formscentral.fcdt'], + 'fcs' => ['application/vnd.isac.fcs'], + 'fd' => ['application/x-fd-file', 'application/x-raw-floppy-disk-image'], + 'fdf' => ['application/vnd.fdf'], + 'fds' => ['application/x-fds-disk'], + 'fe_launch' => ['application/vnd.denovo.fcselayout-link'], + 'feature' => ['text/x-gherkin'], + 'fg5' => ['application/vnd.fujitsu.oasysgp'], + 'fgd' => ['application/x-director'], + 'fh' => ['image/x-freehand'], + 'fh4' => ['image/x-freehand'], + 'fh5' => ['image/x-freehand'], + 'fh7' => ['image/x-freehand'], + 'fhc' => ['image/x-freehand'], + 'fig' => ['application/x-xfig', 'image/x-xfig'], + 'fits' => ['image/fits', 'image/x-fits'], + 'fl' => ['application/x-fluid'], + 'flac' => ['audio/flac', 'audio/x-flac'], + 'flatpak' => ['application/vnd.flatpak', 'application/vnd.xdgapp'], + 'flatpakref' => ['application/vnd.flatpak.ref'], + 'flatpakrepo' => ['application/vnd.flatpak.repo'], + 'flc' => ['video/fli', 'video/x-fli', 'video/x-flic'], + 'fli' => ['video/fli', 'video/x-fli', 'video/x-flic'], + 'flo' => ['application/vnd.micrografx.flo'], + 'flv' => ['video/x-flv', 'application/x-flash-video', 'flv-application/octet-stream', 'video/flv'], + 'flw' => ['application/vnd.kde.kivio', 'application/x-kivio'], + 'flx' => ['text/vnd.fmi.flexstor'], + 'fly' => ['text/vnd.fly'], + 'fm' => ['application/vnd.framemaker', 'application/x-frame'], + 'fnc' => ['application/vnd.frogans.fnc'], + 'fo' => ['text/x-xslfo'], + 'fodg' => ['application/vnd.oasis.opendocument.graphics-flat-xml'], + 'fodp' => ['application/vnd.oasis.opendocument.presentation-flat-xml'], + 'fods' => ['application/vnd.oasis.opendocument.spreadsheet-flat-xml'], + 'fodt' => ['application/vnd.oasis.opendocument.text-flat-xml'], + 'for' => ['text/x-fortran'], + 'fpx' => ['image/vnd.fpx'], + 'frame' => ['application/vnd.framemaker'], + 'fsc' => ['application/vnd.fsc.weblaunch'], + 'fst' => ['image/vnd.fst'], + 'ftc' => ['application/vnd.fluxtime.clip'], + 'fti' => ['application/vnd.anser-web-funds-transfer-initiation'], + 'fvt' => ['video/vnd.fvt'], + 'fxm' => ['video/x-javafx'], + 'fxp' => ['application/vnd.adobe.fxp'], + 'fxpl' => ['application/vnd.adobe.fxp'], + 'fzs' => ['application/vnd.fuzzysheet'], + 'g2w' => ['application/vnd.geoplan'], + 'g3' => ['image/fax-g3', 'image/g3fax'], + 'g3w' => ['application/vnd.geospace'], + 'gac' => ['application/vnd.groove-account'], + 'gam' => ['application/x-tads'], + 'gb' => ['application/x-gameboy-rom'], + 'gba' => ['application/x-gba-rom'], + 'gbc' => ['application/x-gameboy-color-rom'], + 'gbr' => ['application/rpki-ghostbusters', 'image/x-gimp-gbr'], + 'gca' => ['application/x-gca-compressed'], + 'gcode' => ['text/x.gcode'], + 'gcrd' => ['text/directory', 'text/vcard', 'text/x-vcard'], + 'gdl' => ['model/vnd.gdl'], + 'ged' => ['application/x-gedcom', 'text/gedcom'], + 'gedcom' => ['application/x-gedcom', 'text/gedcom'], + 'gem' => ['application/x-gtar', 'application/x-tar'], + 'gen' => ['application/x-genesis-rom'], + 'geo' => ['application/vnd.dynageo'], + 'geo.json' => ['application/geo+json', 'application/vnd.geo+json'], + 'geojson' => ['application/geo+json', 'application/vnd.geo+json'], + 'gex' => ['application/vnd.geometry-explorer'], + 'gf' => ['application/x-tex-gf'], + 'gg' => ['application/x-gamegear-rom'], + 'ggb' => ['application/vnd.geogebra.file'], + 'ggt' => ['application/vnd.geogebra.tool'], + 'ghf' => ['application/vnd.groove-help'], + 'gif' => ['image/gif'], + 'gih' => ['image/x-gimp-gih'], + 'gim' => ['application/vnd.groove-identity-message'], + 'glade' => ['application/x-glade'], + 'gml' => ['application/gml+xml'], + 'gmo' => ['application/x-gettext-translation'], + 'gmx' => ['application/vnd.gmx'], + 'gnc' => ['application/x-gnucash'], + 'gnd' => ['application/gnunet-directory'], + 'gnucash' => ['application/x-gnucash'], + 'gnumeric' => ['application/x-gnumeric'], + 'gnuplot' => ['application/x-gnuplot'], + 'go' => ['text/x-go'], + 'gp' => ['application/x-gnuplot'], + 'gpg' => ['application/pgp', 'application/pgp-encrypted', 'application/pgp-keys', 'application/pgp-signature'], + 'gph' => ['application/vnd.flographit'], + 'gplt' => ['application/x-gnuplot'], + 'gpx' => ['application/gpx', 'application/gpx+xml', 'application/x-gpx', 'application/x-gpx+xml'], + 'gqf' => ['application/vnd.grafeq'], + 'gqs' => ['application/vnd.grafeq'], + 'gra' => ['application/x-graphite'], + 'gram' => ['application/srgs'], + 'gramps' => ['application/x-gramps-xml'], + 'gre' => ['application/vnd.geometry-explorer'], + 'grv' => ['application/vnd.groove-injector'], + 'grxml' => ['application/srgs+xml'], + 'gs' => ['text/x-genie'], + 'gsf' => ['application/x-font-ghostscript', 'application/x-font-type1'], + 'gsm' => ['audio/x-gsm'], + 'gtar' => ['application/x-gtar', 'application/x-tar'], + 'gtm' => ['application/vnd.groove-tool-message'], + 'gtw' => ['model/vnd.gtw'], + 'gv' => ['text/vnd.graphviz'], + 'gvp' => ['text/google-video-pointer', 'text/x-google-video-pointer'], + 'gxf' => ['application/gxf'], + 'gxt' => ['application/vnd.geonext'], + 'gz' => ['application/x-gzip', 'application/gzip'], + 'h' => ['text/x-c', 'text/x-chdr'], + 'h++' => ['text/x-c++hdr'], + 'h261' => ['video/h261'], + 'h263' => ['video/h263'], + 'h264' => ['video/h264'], + 'h4' => ['application/x-hdf'], + 'h5' => ['application/x-hdf'], + 'hal' => ['application/vnd.hal+xml'], + 'hbci' => ['application/vnd.hbci'], + 'hdf' => ['application/x-hdf'], + 'hdf4' => ['application/x-hdf'], + 'hdf5' => ['application/x-hdf'], + 'heic' => ['image/heic', 'image/heic-sequence', 'image/heif', 'image/heif-sequence'], + 'heif' => ['image/heic', 'image/heic-sequence', 'image/heif', 'image/heif-sequence'], + 'hfe' => ['application/x-hfe-file', 'application/x-hfe-floppy-image'], + 'hh' => ['text/x-c', 'text/x-c++hdr'], + 'hlp' => ['application/winhlp', 'zz-application/zz-winassoc-hlp'], + 'hp' => ['text/x-c++hdr'], + 'hpgl' => ['application/vnd.hp-hpgl'], + 'hpid' => ['application/vnd.hp-hpid'], + 'hpp' => ['text/x-c++hdr'], + 'hps' => ['application/vnd.hp-hps'], + 'hqx' => ['application/stuffit', 'application/mac-binhex40'], + 'hs' => ['text/x-haskell'], + 'htke' => ['application/vnd.kenameaapp'], + 'htm' => ['text/html'], + 'html' => ['text/html'], + 'hvd' => ['application/vnd.yamaha.hv-dic'], + 'hvp' => ['application/vnd.yamaha.hv-voice'], + 'hvs' => ['application/vnd.yamaha.hv-script'], + 'hwp' => ['application/vnd.haansoft-hwp', 'application/x-hwp'], + 'hwt' => ['application/vnd.haansoft-hwt', 'application/x-hwt'], + 'hxx' => ['text/x-c++hdr'], + 'i2g' => ['application/vnd.intergeo'], + 'ica' => ['application/x-ica'], + 'icb' => ['image/x-icb', 'image/x-tga'], + 'icc' => ['application/vnd.iccprofile'], + 'ice' => ['x-conference/x-cooltalk'], + 'icm' => ['application/vnd.iccprofile'], + 'icns' => ['image/x-icns'], + 'ico' => ['application/ico', 'image/ico', 'image/icon', 'image/vnd.microsoft.icon', 'image/x-ico', 'image/x-icon', 'text/ico'], + 'ics' => ['application/ics', 'text/calendar', 'text/x-vcalendar'], + 'idl' => ['text/x-idl'], + 'ief' => ['image/ief'], + 'ifb' => ['text/calendar'], + 'iff' => ['image/x-iff', 'image/x-ilbm'], + 'ifm' => ['application/vnd.shana.informed.formdata'], + 'iges' => ['model/iges'], + 'igl' => ['application/vnd.igloader'], + 'igm' => ['application/vnd.insors.igm'], + 'igs' => ['model/iges'], + 'igx' => ['application/vnd.micrografx.igx'], + 'iif' => ['application/vnd.shana.informed.interchange'], + 'ilbm' => ['image/x-iff', 'image/x-ilbm'], + 'ime' => ['audio/imelody', 'audio/x-imelody', 'text/x-imelody'], + 'img' => ['application/x-raw-disk-image'], + 'img.xz' => ['application/x-raw-disk-image-xz-compressed'], + 'imp' => ['application/vnd.accpac.simply.imp'], + 'ims' => ['application/vnd.ms-ims'], + 'imy' => ['audio/imelody', 'audio/x-imelody', 'text/x-imelody'], + 'in' => ['text/plain'], + 'ink' => ['application/inkml+xml'], + 'inkml' => ['application/inkml+xml'], + 'ins' => ['application/x-tex', 'text/x-tex'], + 'install' => ['application/x-install-instructions'], + 'iota' => ['application/vnd.astraea-software.iota'], + 'ipfix' => ['application/ipfix'], + 'ipk' => ['application/vnd.shana.informed.package'], + 'iptables' => ['text/x-iptables'], + 'ipynb' => ['application/x-ipynb+json'], + 'irm' => ['application/vnd.ibm.rights-management'], + 'irp' => ['application/vnd.irepository.package+xml'], + 'iso' => ['application/x-cd-image', 'application/x-gamecube-iso-image', 'application/x-gamecube-rom', 'application/x-iso9660-image', 'application/x-saturn-rom', 'application/x-sega-cd-rom', 'application/x-wbfs', 'application/x-wia', 'application/x-wii-iso-image', 'application/x-wii-rom'], + 'iso9660' => ['application/x-cd-image', 'application/x-iso9660-image'], + 'it' => ['audio/x-it'], + 'it87' => ['application/x-it87'], + 'itp' => ['application/vnd.shana.informed.formtemplate'], + 'ivp' => ['application/vnd.immervision-ivp'], + 'ivu' => ['application/vnd.immervision-ivu'], + 'j2c' => ['image/x-jp2-codestream'], + 'j2k' => ['image/x-jp2-codestream'], + 'jad' => ['text/vnd.sun.j2me.app-descriptor'], + 'jam' => ['application/vnd.jam'], + 'jar' => ['application/x-java-archive', 'application/java-archive', 'application/x-jar'], + 'java' => ['text/x-java', 'text/x-java-source'], + 'jceks' => ['application/x-java-jce-keystore'], + 'jisp' => ['application/vnd.jisp'], + 'jks' => ['application/x-java-keystore'], + 'jlt' => ['application/vnd.hp-jlyt'], + 'jng' => ['image/x-jng'], + 'jnlp' => ['application/x-java-jnlp-file'], + 'joda' => ['application/vnd.joost.joda-archive'], + 'jp2' => ['image/jp2', 'image/jpeg2000', 'image/jpeg2000-image', 'image/x-jpeg2000-image'], + 'jpc' => ['image/x-jp2-codestream'], + 'jpe' => ['image/jpeg', 'image/pjpeg'], + 'jpeg' => ['image/jpeg', 'image/pjpeg'], + 'jpf' => ['image/jpx'], + 'jpg' => ['image/jpeg', 'image/pjpeg'], + 'jpg2' => ['image/jp2', 'image/jpeg2000', 'image/jpeg2000-image', 'image/x-jpeg2000-image'], + 'jpgm' => ['image/jpm', 'video/jpm'], + 'jpgv' => ['video/jpeg'], + 'jpm' => ['image/jpm', 'video/jpm'], + 'jpr' => ['application/x-jbuilder-project'], + 'jpx' => ['application/x-jbuilder-project', 'image/jpx'], + 'jrd' => ['application/jrd+json'], + 'js' => ['text/javascript', 'application/javascript', 'application/x-javascript'], + 'jsm' => ['application/javascript', 'application/x-javascript', 'text/javascript'], + 'json' => ['application/json'], + 'json-patch' => ['application/json-patch+json'], + 'jsonld' => ['application/ld+json'], + 'jsonml' => ['application/jsonml+json'], + 'k25' => ['image/x-kodak-k25'], + 'k7' => ['application/x-thomson-cassette'], + 'kar' => ['audio/midi', 'audio/x-midi'], + 'karbon' => ['application/vnd.kde.karbon', 'application/x-karbon'], + 'kdc' => ['image/x-kodak-kdc'], + 'kdelnk' => ['application/x-desktop', 'application/x-gnome-app-info'], + 'kexi' => ['application/x-kexiproject-sqlite', 'application/x-kexiproject-sqlite2', 'application/x-kexiproject-sqlite3', 'application/x-vnd.kde.kexi'], + 'kexic' => ['application/x-kexi-connectiondata'], + 'kexis' => ['application/x-kexiproject-shortcut'], + 'key' => ['application/vnd.apple.keynote', 'application/x-iwork-keynote-sffkey'], + 'kfo' => ['application/vnd.kde.kformula', 'application/x-kformula'], + 'kia' => ['application/vnd.kidspiration'], + 'kil' => ['application/x-killustrator'], + 'kino' => ['application/smil', 'application/smil+xml'], + 'kml' => ['application/vnd.google-earth.kml+xml'], + 'kmz' => ['application/vnd.google-earth.kmz'], + 'kne' => ['application/vnd.kinar'], + 'knp' => ['application/vnd.kinar'], + 'kon' => ['application/vnd.kde.kontour', 'application/x-kontour'], + 'kpm' => ['application/x-kpovmodeler'], + 'kpr' => ['application/vnd.kde.kpresenter', 'application/x-kpresenter'], + 'kpt' => ['application/vnd.kde.kpresenter', 'application/x-kpresenter'], + 'kpxx' => ['application/vnd.ds-keypoint'], + 'kra' => ['application/x-krita'], + 'ks' => ['application/x-java-keystore'], + 'ksp' => ['application/vnd.kde.kspread', 'application/x-kspread'], + 'ktr' => ['application/vnd.kahootz'], + 'ktx' => ['image/ktx'], + 'ktz' => ['application/vnd.kahootz'], + 'kud' => ['application/x-kugar'], + 'kwd' => ['application/vnd.kde.kword', 'application/x-kword'], + 'kwt' => ['application/vnd.kde.kword', 'application/x-kword'], + 'la' => ['application/x-shared-library-la'], + 'lasxml' => ['application/vnd.las.las+xml'], + 'latex' => ['application/x-latex', 'application/x-tex', 'text/x-tex'], + 'lbd' => ['application/vnd.llamagraphics.life-balance.desktop'], + 'lbe' => ['application/vnd.llamagraphics.life-balance.exchange+xml'], + 'lbm' => ['image/x-iff', 'image/x-ilbm'], + 'ldif' => ['text/x-ldif'], + 'les' => ['application/vnd.hhe.lesson-player'], + 'lha' => ['application/x-lha', 'application/x-lzh-compressed'], + 'lhs' => ['text/x-literate-haskell'], + 'lhz' => ['application/x-lhz'], + 'link66' => ['application/vnd.route66.link66+xml'], + 'list' => ['text/plain'], + 'list3820' => ['application/vnd.ibm.modcap'], + 'listafp' => ['application/vnd.ibm.modcap'], + 'lnk' => ['application/x-ms-shortcut'], + 'lnx' => ['application/x-atari-lynx-rom'], + 'loas' => ['audio/usac'], + 'log' => ['text/plain', 'text/x-log'], + 'lostxml' => ['application/lost+xml'], + 'lrf' => ['application/octet-stream'], + 'lrm' => ['application/vnd.ms-lrm'], + 'lrv' => ['video/mp4', 'video/mp4v-es', 'video/x-m4v'], + 'lrz' => ['application/x-lrzip'], + 'ltf' => ['application/vnd.frogans.ltf'], + 'ltx' => ['application/x-tex', 'text/x-tex'], + 'lua' => ['text/x-lua'], + 'lvp' => ['audio/vnd.lucent.voice'], + 'lwo' => ['image/x-lwo'], + 'lwob' => ['image/x-lwo'], + 'lwp' => ['application/vnd.lotus-wordpro'], + 'lws' => ['image/x-lws'], + 'ly' => ['text/x-lilypond'], + 'lyx' => ['application/x-lyx', 'text/x-lyx'], + 'lz' => ['application/x-lzip'], + 'lz4' => ['application/x-lz4'], + 'lzh' => ['application/x-lha', 'application/x-lzh-compressed'], + 'lzma' => ['application/x-lzma'], + 'lzo' => ['application/x-lzop'], + 'm' => ['text/x-matlab', 'text/x-objcsrc', 'text/x-octave'], + 'm13' => ['application/x-msmediaview'], + 'm14' => ['application/x-msmediaview'], + 'm15' => ['audio/x-mod'], + 'm1u' => ['video/vnd.mpegurl', 'video/x-mpegurl'], + 'm1v' => ['video/mpeg'], + 'm21' => ['application/mp21'], + 'm2a' => ['audio/mpeg'], + 'm2t' => ['video/mp2t'], + 'm2ts' => ['video/mp2t'], + 'm2v' => ['video/mpeg'], + 'm3a' => ['audio/mpeg'], + 'm3u' => ['audio/x-mpegurl', 'application/m3u', 'application/vnd.apple.mpegurl', 'audio/m3u', 'audio/mpegurl', 'audio/x-m3u', 'audio/x-mp3-playlist'], + 'm3u8' => ['application/m3u', 'application/vnd.apple.mpegurl', 'audio/m3u', 'audio/mpegurl', 'audio/x-m3u', 'audio/x-mp3-playlist', 'audio/x-mpegurl'], + 'm4' => ['application/x-m4'], + 'm4a' => ['audio/mp4', 'audio/m4a', 'audio/x-m4a'], + 'm4b' => ['audio/x-m4b'], + 'm4r' => ['audio/x-m4r'], + 'm4u' => ['video/vnd.mpegurl', 'video/x-mpegurl'], + 'm4v' => ['video/mp4', 'video/mp4v-es', 'video/x-m4v'], + 'm7' => ['application/x-thomson-cartridge-memo7'], + 'ma' => ['application/mathematica'], + 'mab' => ['application/x-markaby'], + 'mads' => ['application/mads+xml'], + 'mag' => ['application/vnd.ecowin.chart'], + 'mak' => ['text/x-makefile'], + 'maker' => ['application/vnd.framemaker'], + 'man' => ['application/x-troff-man', 'text/troff'], + 'manifest' => ['text/cache-manifest'], + 'mar' => ['application/octet-stream'], + 'markdown' => ['text/markdown', 'text/x-markdown'], + 'mathml' => ['application/mathml+xml'], + 'mb' => ['application/mathematica'], + 'mbk' => ['application/vnd.mobius.mbk'], + 'mbox' => ['application/mbox'], + 'mc1' => ['application/vnd.medcalcdata'], + 'mcd' => ['application/vnd.mcd'], + 'mcurl' => ['text/vnd.curl.mcurl'], + 'md' => ['text/markdown', 'text/x-markdown'], + 'mdb' => ['application/x-msaccess', 'application/mdb', 'application/msaccess', 'application/vnd.ms-access', 'application/vnd.msaccess', 'application/x-mdb', 'zz-application/zz-winassoc-mdb'], + 'mdi' => ['image/vnd.ms-modi'], + 'mdx' => ['application/x-genesis-32x-rom'], + 'me' => ['text/troff', 'text/x-troff-me'], + 'med' => ['audio/x-mod'], + 'mesh' => ['model/mesh'], + 'meta4' => ['application/metalink4+xml'], + 'metalink' => ['application/metalink+xml'], + 'mets' => ['application/mets+xml'], + 'mfm' => ['application/vnd.mfmp'], + 'mft' => ['application/rpki-manifest'], + 'mgp' => ['application/vnd.osgeo.mapguide.package', 'application/x-magicpoint'], + 'mgz' => ['application/vnd.proteus.magazine'], + 'mht' => ['application/x-mimearchive'], + 'mhtml' => ['application/x-mimearchive'], + 'mid' => ['audio/midi', 'audio/x-midi'], + 'midi' => ['audio/midi', 'audio/x-midi'], + 'mie' => ['application/x-mie'], + 'mif' => ['application/vnd.mif', 'application/x-mif'], + 'mime' => ['message/rfc822'], + 'minipsf' => ['audio/x-minipsf'], + 'mj2' => ['video/mj2'], + 'mjp2' => ['video/mj2'], + 'mjpeg' => ['video/x-mjpeg'], + 'mjpg' => ['video/x-mjpeg'], + 'mjs' => ['application/javascript', 'application/x-javascript', 'text/javascript'], + 'mk' => ['text/x-makefile'], + 'mk3d' => ['video/x-matroska', 'video/x-matroska-3d'], + 'mka' => ['audio/x-matroska'], + 'mkd' => ['text/markdown', 'text/x-markdown'], + 'mks' => ['video/x-matroska'], + 'mkv' => ['video/x-matroska'], + 'ml' => ['text/x-ocaml'], + 'mli' => ['text/x-ocaml'], + 'mlp' => ['application/vnd.dolby.mlp'], + 'mm' => ['text/x-troff-mm'], + 'mmd' => ['application/vnd.chipnuts.karaoke-mmd'], + 'mmf' => ['application/vnd.smaf', 'application/x-smaf'], + 'mml' => ['application/mathml+xml', 'text/mathml'], + 'mmr' => ['image/vnd.fujixerox.edmics-mmr'], + 'mng' => ['video/x-mng'], + 'mny' => ['application/x-msmoney'], + 'mo' => ['application/x-gettext-translation', 'text/x-modelica'], + 'mo3' => ['audio/x-mo3'], + 'mobi' => ['application/x-mobipocket-ebook'], + 'moc' => ['text/x-moc'], + 'mod' => ['audio/x-mod'], + 'mods' => ['application/mods+xml'], + 'mof' => ['text/x-mof'], + 'moov' => ['video/quicktime'], + 'mount' => ['text/x-systemd-unit'], + 'mov' => ['video/quicktime'], + 'movie' => ['video/x-sgi-movie'], + 'mp+' => ['audio/x-musepack'], + 'mp2' => ['audio/mp2', 'audio/mpeg', 'audio/x-mp2', 'video/mpeg', 'video/mpeg-system', 'video/x-mpeg', 'video/x-mpeg-system', 'video/x-mpeg2'], + 'mp21' => ['application/mp21'], + 'mp2a' => ['audio/mpeg'], + 'mp3' => ['audio/mpeg', 'audio/mp3', 'audio/x-mp3', 'audio/x-mpeg', 'audio/x-mpg'], + 'mp4' => ['video/mp4', 'video/mp4v-es', 'video/x-m4v'], + 'mp4a' => ['audio/mp4'], + 'mp4s' => ['application/mp4'], + 'mp4v' => ['video/mp4'], + 'mpc' => ['application/vnd.mophun.certificate', 'audio/x-musepack'], + 'mpe' => ['video/mpeg', 'video/mpeg-system', 'video/x-mpeg', 'video/x-mpeg-system', 'video/x-mpeg2'], + 'mpeg' => ['video/mpeg', 'video/mpeg-system', 'video/x-mpeg', 'video/x-mpeg-system', 'video/x-mpeg2'], + 'mpg' => ['video/mpeg', 'video/mpeg-system', 'video/x-mpeg', 'video/x-mpeg-system', 'video/x-mpeg2'], + 'mpg4' => ['video/mp4'], + 'mpga' => ['audio/mp3', 'audio/mpeg', 'audio/x-mp3', 'audio/x-mpeg', 'audio/x-mpg'], + 'mpkg' => ['application/vnd.apple.installer+xml'], + 'mpl' => ['video/mp2t'], + 'mpls' => ['video/mp2t'], + 'mpm' => ['application/vnd.blueice.multipass'], + 'mpn' => ['application/vnd.mophun.application'], + 'mpp' => ['application/vnd.ms-project', 'audio/x-musepack'], + 'mpt' => ['application/vnd.ms-project'], + 'mpy' => ['application/vnd.ibm.minipay'], + 'mqy' => ['application/vnd.mobius.mqy'], + 'mrc' => ['application/marc'], + 'mrcx' => ['application/marcxml+xml'], + 'mrl' => ['text/x-mrml'], + 'mrml' => ['text/x-mrml'], + 'mrw' => ['image/x-minolta-mrw'], + 'ms' => ['text/troff', 'text/x-troff-ms'], + 'mscml' => ['application/mediaservercontrol+xml'], + 'mseed' => ['application/vnd.fdsn.mseed'], + 'mseq' => ['application/vnd.mseq'], + 'msf' => ['application/vnd.epson.msf'], + 'msh' => ['model/mesh'], + 'msi' => ['application/x-msdownload', 'application/x-msi'], + 'msl' => ['application/vnd.mobius.msl'], + 'msod' => ['image/x-msod'], + 'msty' => ['application/vnd.muvee.style'], + 'msx' => ['application/x-msx-rom'], + 'mtm' => ['audio/x-mod'], + 'mts' => ['model/vnd.mts', 'video/mp2t'], + 'mup' => ['text/x-mup'], + 'mus' => ['application/vnd.musician'], + 'musicxml' => ['application/vnd.recordare.musicxml+xml'], + 'mvb' => ['application/x-msmediaview'], + 'mwf' => ['application/vnd.mfer'], + 'mxf' => ['application/mxf'], + 'mxl' => ['application/vnd.recordare.musicxml'], + 'mxml' => ['application/xv+xml'], + 'mxs' => ['application/vnd.triscape.mxs'], + 'mxu' => ['video/vnd.mpegurl', 'video/x-mpegurl'], + 'n-gage' => ['application/vnd.nokia.n-gage.symbian.install'], + 'n3' => ['text/n3'], + 'n64' => ['application/x-n64-rom'], + 'nb' => ['application/mathematica', 'application/x-mathematica'], + 'nbp' => ['application/vnd.wolfram.player'], + 'nc' => ['application/x-netcdf'], + 'ncx' => ['application/x-dtbncx+xml'], + 'nds' => ['application/x-nintendo-ds-rom'], + 'nef' => ['image/x-nikon-nef'], + 'nes' => ['application/x-nes-rom'], + 'nez' => ['application/x-nes-rom'], + 'nfo' => ['text/x-nfo'], + 'ngc' => ['application/x-neo-geo-pocket-color-rom'], + 'ngdat' => ['application/vnd.nokia.n-gage.data'], + 'ngp' => ['application/x-neo-geo-pocket-rom'], + 'nitf' => ['application/vnd.nitf'], + 'nlu' => ['application/vnd.neurolanguage.nlu'], + 'nml' => ['application/vnd.enliven'], + 'nnd' => ['application/vnd.noblenet-directory'], + 'nns' => ['application/vnd.noblenet-sealer'], + 'nnw' => ['application/vnd.noblenet-web'], + 'not' => ['text/x-mup'], + 'npx' => ['image/vnd.net-fpx'], + 'nsc' => ['application/x-conference', 'application/x-netshow-channel'], + 'nsf' => ['application/vnd.lotus-notes'], + 'nsv' => ['video/x-nsv'], + 'ntf' => ['application/vnd.nitf'], + 'nzb' => ['application/x-nzb'], + 'o' => ['application/x-object'], + 'oa2' => ['application/vnd.fujitsu.oasys2'], + 'oa3' => ['application/vnd.fujitsu.oasys3'], + 'oas' => ['application/vnd.fujitsu.oasys'], + 'obd' => ['application/x-msbinder'], + 'obj' => ['application/x-tgif'], + 'ocl' => ['text/x-ocl'], + 'oda' => ['application/oda'], + 'odb' => ['application/vnd.oasis.opendocument.database', 'application/vnd.sun.xml.base'], + 'odc' => ['application/vnd.oasis.opendocument.chart'], + 'odf' => ['application/vnd.oasis.opendocument.formula'], + 'odft' => ['application/vnd.oasis.opendocument.formula-template'], + 'odg' => ['application/vnd.oasis.opendocument.graphics'], + 'odi' => ['application/vnd.oasis.opendocument.image'], + 'odm' => ['application/vnd.oasis.opendocument.text-master'], + 'odp' => ['application/vnd.oasis.opendocument.presentation'], + 'ods' => ['application/vnd.oasis.opendocument.spreadsheet'], + 'odt' => ['application/vnd.oasis.opendocument.text'], + 'oga' => ['audio/ogg', 'audio/vorbis', 'audio/x-flac+ogg', 'audio/x-ogg', 'audio/x-oggflac', 'audio/x-speex+ogg', 'audio/x-vorbis', 'audio/x-vorbis+ogg'], + 'ogg' => ['audio/ogg', 'audio/vorbis', 'audio/x-flac+ogg', 'audio/x-ogg', 'audio/x-oggflac', 'audio/x-speex+ogg', 'audio/x-vorbis', 'audio/x-vorbis+ogg', 'video/ogg', 'video/x-ogg', 'video/x-theora', 'video/x-theora+ogg'], + 'ogm' => ['video/x-ogm', 'video/x-ogm+ogg'], + 'ogv' => ['video/ogg', 'video/x-ogg'], + 'ogx' => ['application/ogg', 'application/x-ogg'], + 'old' => ['application/x-trash'], + 'oleo' => ['application/x-oleo'], + 'omdoc' => ['application/omdoc+xml'], + 'onepkg' => ['application/onenote'], + 'onetmp' => ['application/onenote'], + 'onetoc' => ['application/onenote'], + 'onetoc2' => ['application/onenote'], + 'ooc' => ['text/x-ooc'], + 'opf' => ['application/oebps-package+xml'], + 'opml' => ['text/x-opml', 'text/x-opml+xml'], + 'oprc' => ['application/vnd.palm', 'application/x-palm-database'], + 'opus' => ['audio/ogg', 'audio/x-ogg', 'audio/x-opus+ogg'], + 'ora' => ['image/openraster'], + 'orf' => ['image/x-olympus-orf'], + 'org' => ['application/vnd.lotus-organizer'], + 'osf' => ['application/vnd.yamaha.openscoreformat'], + 'osfpvg' => ['application/vnd.yamaha.openscoreformat.osfpvg+xml'], + 'otc' => ['application/vnd.oasis.opendocument.chart-template'], + 'otf' => ['application/vnd.oasis.opendocument.formula-template', 'application/x-font-otf', 'font/otf'], + 'otg' => ['application/vnd.oasis.opendocument.graphics-template'], + 'oth' => ['application/vnd.oasis.opendocument.text-web'], + 'oti' => ['application/vnd.oasis.opendocument.image-template'], + 'otp' => ['application/vnd.oasis.opendocument.presentation-template'], + 'ots' => ['application/vnd.oasis.opendocument.spreadsheet-template'], + 'ott' => ['application/vnd.oasis.opendocument.text-template'], + 'owl' => ['application/rdf+xml', 'text/rdf'], + 'owx' => ['application/owl+xml'], + 'oxps' => ['application/oxps', 'application/vnd.ms-xpsdocument', 'application/xps'], + 'oxt' => ['application/vnd.openofficeorg.extension'], + 'p' => ['text/x-pascal'], + 'p10' => ['application/pkcs10'], + 'p12' => ['application/pkcs12', 'application/x-pkcs12'], + 'p65' => ['application/x-pagemaker'], + 'p7b' => ['application/x-pkcs7-certificates'], + 'p7c' => ['application/pkcs7-mime'], + 'p7m' => ['application/pkcs7-mime'], + 'p7r' => ['application/x-pkcs7-certreqresp'], + 'p7s' => ['application/pkcs7-signature'], + 'p8' => ['application/pkcs8'], + 'p8e' => ['application/pkcs8-encrypted'], + 'pack' => ['application/x-java-pack200'], + 'pak' => ['application/x-pak'], + 'par2' => ['application/x-par2'], + 'part' => ['application/x-partial-download'], + 'pas' => ['text/x-pascal'], + 'pat' => ['image/x-gimp-pat'], + 'patch' => ['text/x-diff', 'text/x-patch'], + 'path' => ['text/x-systemd-unit'], + 'paw' => ['application/vnd.pawaafile'], + 'pbd' => ['application/vnd.powerbuilder6'], + 'pbm' => ['image/x-portable-bitmap'], + 'pcap' => ['application/pcap', 'application/vnd.tcpdump.pcap', 'application/x-pcap'], + 'pcd' => ['image/x-photo-cd'], + 'pce' => ['application/x-pc-engine-rom'], + 'pcf' => ['application/x-cisco-vpn-settings', 'application/x-font-pcf'], + 'pcf.Z' => ['application/x-font-pcf'], + 'pcf.gz' => ['application/x-font-pcf'], + 'pcl' => ['application/vnd.hp-pcl'], + 'pclxl' => ['application/vnd.hp-pclxl'], + 'pct' => ['image/x-pict'], + 'pcurl' => ['application/vnd.curl.pcurl'], + 'pcx' => ['image/vnd.zbrush.pcx', 'image/x-pcx'], + 'pdb' => ['application/vnd.palm', 'application/x-aportisdoc', 'application/x-palm-database'], + 'pdc' => ['application/x-aportisdoc'], + 'pdf' => ['application/pdf', 'application/acrobat', 'application/nappdf', 'application/x-pdf', 'image/pdf'], + 'pdf.bz2' => ['application/x-bzpdf'], + 'pdf.gz' => ['application/x-gzpdf'], + 'pdf.lz' => ['application/x-lzpdf'], + 'pdf.xz' => ['application/x-xzpdf'], + 'pef' => ['image/x-pentax-pef'], + 'pem' => ['application/x-x509-ca-cert'], + 'perl' => ['application/x-perl', 'text/x-perl'], + 'pfa' => ['application/x-font-type1'], + 'pfb' => ['application/x-font-type1'], + 'pfm' => ['application/x-font-type1'], + 'pfr' => ['application/font-tdpfr'], + 'pfx' => ['application/pkcs12', 'application/x-pkcs12'], + 'pgm' => ['image/x-portable-graymap'], + 'pgn' => ['application/vnd.chess-pgn', 'application/x-chess-pgn'], + 'pgp' => ['application/pgp', 'application/pgp-encrypted', 'application/pgp-keys', 'application/pgp-signature'], + 'php' => ['application/x-php'], + 'php3' => ['application/x-php'], + 'php4' => ['application/x-php'], + 'php5' => ['application/x-php'], + 'phps' => ['application/x-php'], + 'pic' => ['image/x-pict'], + 'pict' => ['image/x-pict'], + 'pict1' => ['image/x-pict'], + 'pict2' => ['image/x-pict'], + 'pk' => ['application/x-tex-pk'], + 'pkg' => ['application/octet-stream', 'application/x-xar'], + 'pki' => ['application/pkixcmp'], + 'pkipath' => ['application/pkix-pkipath'], + 'pkr' => ['application/pgp-keys'], + 'pl' => ['application/x-perl', 'text/x-perl'], + 'pla' => ['audio/x-iriver-pla'], + 'plb' => ['application/vnd.3gpp.pic-bw-large'], + 'plc' => ['application/vnd.mobius.plc'], + 'plf' => ['application/vnd.pocketlearn'], + 'pln' => ['application/x-planperfect'], + 'pls' => ['application/pls', 'application/pls+xml', 'audio/scpls', 'audio/x-scpls'], + 'pm' => ['application/x-pagemaker', 'application/x-perl', 'text/x-perl'], + 'pm6' => ['application/x-pagemaker'], + 'pmd' => ['application/x-pagemaker'], + 'pml' => ['application/vnd.ctc-posml'], + 'png' => ['image/png'], + 'pnm' => ['image/x-portable-anymap'], + 'pntg' => ['image/x-macpaint'], + 'po' => ['application/x-gettext', 'text/x-gettext-translation', 'text/x-po'], + 'pod' => ['application/x-perl', 'text/x-perl'], + 'por' => ['application/x-spss-por'], + 'portpkg' => ['application/vnd.macports.portpkg'], + 'pot' => ['application/mspowerpoint', 'application/powerpoint', 'application/vnd.ms-powerpoint', 'application/x-mspowerpoint', 'text/x-gettext-translation-template', 'text/x-pot'], + 'potm' => ['application/vnd.ms-powerpoint.template.macroenabled.12'], + 'potx' => ['application/vnd.openxmlformats-officedocument.presentationml.template'], + 'ppam' => ['application/vnd.ms-powerpoint.addin.macroenabled.12'], + 'ppd' => ['application/vnd.cups-ppd'], + 'ppm' => ['image/x-portable-pixmap'], + 'pps' => ['application/mspowerpoint', 'application/powerpoint', 'application/vnd.ms-powerpoint', 'application/x-mspowerpoint'], + 'ppsm' => ['application/vnd.ms-powerpoint.slideshow.macroenabled.12'], + 'ppsx' => ['application/vnd.openxmlformats-officedocument.presentationml.slideshow'], + 'ppt' => ['application/vnd.ms-powerpoint', 'application/mspowerpoint', 'application/powerpoint', 'application/x-mspowerpoint'], + 'pptm' => ['application/vnd.ms-powerpoint.presentation.macroenabled.12'], + 'pptx' => ['application/vnd.openxmlformats-officedocument.presentationml.presentation'], + 'ppz' => ['application/mspowerpoint', 'application/powerpoint', 'application/vnd.ms-powerpoint', 'application/x-mspowerpoint'], + 'pqa' => ['application/vnd.palm', 'application/x-palm-database'], + 'prc' => ['application/vnd.palm', 'application/x-mobipocket-ebook', 'application/x-palm-database'], + 'pre' => ['application/vnd.lotus-freelance'], + 'prf' => ['application/pics-rules'], + 'ps' => ['application/postscript'], + 'ps.bz2' => ['application/x-bzpostscript'], + 'ps.gz' => ['application/x-gzpostscript'], + 'psb' => ['application/vnd.3gpp.pic-bw-small'], + 'psd' => ['application/photoshop', 'application/x-photoshop', 'image/photoshop', 'image/psd', 'image/vnd.adobe.photoshop', 'image/x-photoshop', 'image/x-psd'], + 'psf' => ['application/x-font-linux-psf', 'audio/x-psf'], + 'psf.gz' => ['application/x-gz-font-linux-psf'], + 'psflib' => ['audio/x-psflib'], + 'psid' => ['audio/prs.sid'], + 'pskcxml' => ['application/pskc+xml'], + 'psw' => ['application/x-pocket-word'], + 'ptid' => ['application/vnd.pvi.ptid1'], + 'pub' => ['application/vnd.ms-publisher', 'application/x-mspublisher'], + 'pvb' => ['application/vnd.3gpp.pic-bw-var'], + 'pw' => ['application/x-pw'], + 'pwn' => ['application/vnd.3m.post-it-notes'], + 'py' => ['text/x-python', 'text/x-python3'], + 'py3' => ['text/x-python3'], + 'py3x' => ['text/x-python3'], + 'pya' => ['audio/vnd.ms-playready.media.pya'], + 'pyc' => ['application/x-python-bytecode'], + 'pyo' => ['application/x-python-bytecode'], + 'pyv' => ['video/vnd.ms-playready.media.pyv'], + 'pyx' => ['text/x-python'], + 'qam' => ['application/vnd.epson.quickanime'], + 'qbo' => ['application/vnd.intu.qbo'], + 'qd' => ['application/x-fd-file', 'application/x-raw-floppy-disk-image'], + 'qfx' => ['application/vnd.intu.qfx'], + 'qif' => ['application/x-qw', 'image/x-quicktime'], + 'qml' => ['text/x-qml'], + 'qmlproject' => ['text/x-qml'], + 'qmltypes' => ['text/x-qml'], + 'qp' => ['application/x-qpress'], + 'qps' => ['application/vnd.publishare-delta-tree'], + 'qt' => ['video/quicktime'], + 'qti' => ['application/x-qtiplot'], + 'qti.gz' => ['application/x-qtiplot'], + 'qtif' => ['image/x-quicktime'], + 'qtl' => ['application/x-quicktime-media-link', 'application/x-quicktimeplayer'], + 'qtvr' => ['video/quicktime'], + 'qwd' => ['application/vnd.quark.quarkxpress'], + 'qwt' => ['application/vnd.quark.quarkxpress'], + 'qxb' => ['application/vnd.quark.quarkxpress'], + 'qxd' => ['application/vnd.quark.quarkxpress'], + 'qxl' => ['application/vnd.quark.quarkxpress'], + 'qxt' => ['application/vnd.quark.quarkxpress'], + 'ra' => ['audio/vnd.m-realaudio', 'audio/vnd.rn-realaudio', 'audio/x-pn-realaudio'], + 'raf' => ['image/x-fuji-raf'], + 'ram' => ['application/ram', 'audio/x-pn-realaudio'], + 'raml' => ['application/raml+yaml'], + 'rar' => ['application/x-rar-compressed', 'application/vnd.rar', 'application/x-rar'], + 'ras' => ['image/x-cmu-raster'], + 'raw' => ['image/x-panasonic-raw', 'image/x-panasonic-rw'], + 'raw-disk-image' => ['application/x-raw-disk-image'], + 'raw-disk-image.xz' => ['application/x-raw-disk-image-xz-compressed'], + 'rax' => ['audio/vnd.m-realaudio', 'audio/vnd.rn-realaudio', 'audio/x-pn-realaudio'], + 'rb' => ['application/x-ruby'], + 'rcprofile' => ['application/vnd.ipunplugged.rcprofile'], + 'rdf' => ['application/rdf+xml', 'text/rdf'], + 'rdfs' => ['application/rdf+xml', 'text/rdf'], + 'rdz' => ['application/vnd.data-vision.rdz'], + 'reg' => ['text/x-ms-regedit'], + 'rej' => ['application/x-reject', 'text/x-reject'], + 'rep' => ['application/vnd.businessobjects'], + 'res' => ['application/x-dtbresource+xml'], + 'rgb' => ['image/x-rgb'], + 'rif' => ['application/reginfo+xml'], + 'rip' => ['audio/vnd.rip'], + 'ris' => ['application/x-research-info-systems'], + 'rl' => ['application/resource-lists+xml'], + 'rlc' => ['image/vnd.fujixerox.edmics-rlc'], + 'rld' => ['application/resource-lists-diff+xml'], + 'rle' => ['image/rle'], + 'rm' => ['application/vnd.rn-realmedia', 'application/vnd.rn-realmedia-vbr'], + 'rmi' => ['audio/midi'], + 'rmj' => ['application/vnd.rn-realmedia', 'application/vnd.rn-realmedia-vbr'], + 'rmm' => ['application/vnd.rn-realmedia', 'application/vnd.rn-realmedia-vbr'], + 'rmp' => ['audio/x-pn-realaudio-plugin'], + 'rms' => ['application/vnd.jcp.javame.midlet-rms', 'application/vnd.rn-realmedia', 'application/vnd.rn-realmedia-vbr'], + 'rmvb' => ['application/vnd.rn-realmedia', 'application/vnd.rn-realmedia-vbr'], + 'rmx' => ['application/vnd.rn-realmedia', 'application/vnd.rn-realmedia-vbr'], + 'rnc' => ['application/relax-ng-compact-syntax', 'application/x-rnc'], + 'rng' => ['application/xml', 'text/xml'], + 'roa' => ['application/rpki-roa'], + 'roff' => ['application/x-troff', 'text/troff', 'text/x-troff'], + 'rp' => ['image/vnd.rn-realpix'], + 'rp9' => ['application/vnd.cloanto.rp9'], + 'rpm' => ['application/x-redhat-package-manager', 'application/x-rpm'], + 'rpss' => ['application/vnd.nokia.radio-presets'], + 'rpst' => ['application/vnd.nokia.radio-preset'], + 'rq' => ['application/sparql-query'], + 'rs' => ['application/rls-services+xml', 'text/rust'], + 'rsd' => ['application/rsd+xml'], + 'rss' => ['application/rss+xml', 'text/rss'], + 'rt' => ['text/vnd.rn-realtext'], + 'rtf' => ['application/rtf', 'text/rtf'], + 'rtx' => ['text/richtext'], + 'rv' => ['video/vnd.rn-realvideo', 'video/x-real-video'], + 'rvx' => ['video/vnd.rn-realvideo', 'video/x-real-video'], + 'rw2' => ['image/x-panasonic-raw2', 'image/x-panasonic-rw2'], + 's' => ['text/x-asm'], + 's3m' => ['audio/s3m', 'audio/x-s3m'], + 'saf' => ['application/vnd.yamaha.smaf-audio'], + 'sam' => ['application/x-amipro'], + 'sami' => ['application/x-sami'], + 'sap' => ['application/x-sap-file', 'application/x-thomson-sap-image'], + 'sass' => ['text/x-sass'], + 'sav' => ['application/x-spss-sav', 'application/x-spss-savefile'], + 'sbml' => ['application/sbml+xml'], + 'sc' => ['application/vnd.ibm.secure-container'], + 'scala' => ['text/x-scala'], + 'scd' => ['application/x-msschedule'], + 'scm' => ['application/vnd.lotus-screencam', 'text/x-scheme'], + 'scope' => ['text/x-systemd-unit'], + 'scq' => ['application/scvp-cv-request'], + 'scs' => ['application/scvp-cv-response'], + 'scss' => ['text/x-scss'], + 'scurl' => ['text/vnd.curl.scurl'], + 'sda' => ['application/vnd.stardivision.draw'], + 'sdc' => ['application/vnd.stardivision.calc'], + 'sdd' => ['application/vnd.stardivision.impress'], + 'sdkd' => ['application/vnd.solent.sdkm+xml'], + 'sdkm' => ['application/vnd.solent.sdkm+xml'], + 'sdp' => ['application/sdp', 'application/vnd.sdp', 'application/vnd.stardivision.impress', 'application/x-sdp'], + 'sds' => ['application/vnd.stardivision.chart'], + 'sdw' => ['application/vnd.stardivision.writer', 'application/vnd.stardivision.writer-global'], + 'see' => ['application/vnd.seemail'], + 'seed' => ['application/vnd.fdsn.seed'], + 'sema' => ['application/vnd.sema'], + 'semd' => ['application/vnd.semd'], + 'semf' => ['application/vnd.semf'], + 'ser' => ['application/java-serialized-object'], + 'service' => ['text/x-dbus-service', 'text/x-systemd-unit'], + 'setpay' => ['application/set-payment-initiation'], + 'setreg' => ['application/set-registration-initiation'], + 'sfc' => ['application/vnd.nintendo.snes.rom', 'application/x-snes-rom'], + 'sfd-hdstx' => ['application/vnd.hydrostatix.sof-data'], + 'sfs' => ['application/vnd.spotfire.sfs'], + 'sfv' => ['text/x-sfv'], + 'sg' => ['application/x-sg1000-rom'], + 'sgb' => ['application/x-gameboy-rom'], + 'sgf' => ['application/x-go-sgf'], + 'sgi' => ['image/sgi', 'image/x-sgi'], + 'sgl' => ['application/vnd.stardivision.writer', 'application/vnd.stardivision.writer-global'], + 'sgm' => ['text/sgml'], + 'sgml' => ['text/sgml'], + 'sh' => ['application/x-sh', 'application/x-shellscript', 'text/x-sh'], + 'shape' => ['application/x-dia-shape'], + 'shar' => ['application/x-shar'], + 'shf' => ['application/shf+xml'], + 'shn' => ['application/x-shorten', 'audio/x-shorten'], + 'siag' => ['application/x-siag'], + 'sid' => ['audio/prs.sid', 'image/x-mrsid-image'], + 'sig' => ['application/pgp-signature'], + 'sik' => ['application/x-trash'], + 'sil' => ['audio/silk'], + 'silo' => ['model/mesh'], + 'sis' => ['application/vnd.symbian.install'], + 'sisx' => ['application/vnd.symbian.install', 'x-epoc/x-sisx-app'], + 'sit' => ['application/x-stuffit', 'application/stuffit', 'application/x-sit'], + 'sitx' => ['application/x-stuffitx'], + 'siv' => ['application/sieve'], + 'sk' => ['image/x-skencil'], + 'sk1' => ['image/x-skencil'], + 'skd' => ['application/vnd.koan'], + 'skm' => ['application/vnd.koan'], + 'skp' => ['application/vnd.koan'], + 'skr' => ['application/pgp-keys'], + 'skt' => ['application/vnd.koan'], + 'sldm' => ['application/vnd.ms-powerpoint.slide.macroenabled.12'], + 'sldx' => ['application/vnd.openxmlformats-officedocument.presentationml.slide'], + 'slice' => ['text/x-systemd-unit'], + 'slk' => ['text/spreadsheet'], + 'slt' => ['application/vnd.epson.salt'], + 'sm' => ['application/vnd.stepmania.stepchart'], + 'smaf' => ['application/vnd.smaf', 'application/x-smaf'], + 'smc' => ['application/vnd.nintendo.snes.rom', 'application/x-snes-rom'], + 'smd' => ['application/vnd.stardivision.mail', 'application/x-genesis-rom'], + 'smf' => ['application/vnd.stardivision.math'], + 'smi' => ['application/smil', 'application/smil+xml', 'application/x-sami'], + 'smil' => ['application/smil', 'application/smil+xml'], + 'sml' => ['application/smil', 'application/smil+xml'], + 'sms' => ['application/x-sms-rom'], + 'smv' => ['video/x-smv'], + 'smzip' => ['application/vnd.stepmania.package'], + 'snap' => ['application/vnd.snap'], + 'snd' => ['audio/basic'], + 'snf' => ['application/x-font-snf'], + 'so' => ['application/octet-stream', 'application/x-sharedlib'], + 'socket' => ['text/x-systemd-unit'], + 'spc' => ['application/x-pkcs7-certificates'], + 'spd' => ['application/x-font-speedo'], + 'spec' => ['text/x-rpm-spec'], + 'spf' => ['application/vnd.yamaha.smaf-phrase'], + 'spl' => ['application/futuresplash', 'application/vnd.adobe.flash.movie', 'application/x-futuresplash', 'application/x-shockwave-flash'], + 'spm' => ['application/x-source-rpm'], + 'spot' => ['text/vnd.in3d.spot'], + 'spp' => ['application/scvp-vp-response'], + 'spq' => ['application/scvp-vp-request'], + 'spx' => ['audio/ogg', 'audio/x-speex'], + 'sql' => ['application/sql', 'application/x-sql', 'text/x-sql'], + 'sqlite2' => ['application/x-sqlite2'], + 'sqlite3' => ['application/vnd.sqlite3', 'application/x-sqlite3'], + 'sqsh' => ['application/vnd.squashfs'], + 'sr2' => ['image/x-sony-sr2'], + 'src' => ['application/x-wais-source'], + 'src.rpm' => ['application/x-source-rpm'], + 'srf' => ['image/x-sony-srf'], + 'srt' => ['application/x-srt', 'application/x-subrip'], + 'sru' => ['application/sru+xml'], + 'srx' => ['application/sparql-results+xml'], + 'ss' => ['text/x-scheme'], + 'ssa' => ['text/x-ssa'], + 'ssdl' => ['application/ssdl+xml'], + 'sse' => ['application/vnd.kodak-descriptor'], + 'ssf' => ['application/vnd.epson.ssf'], + 'ssml' => ['application/ssml+xml'], + 'st' => ['application/vnd.sailingtracker.track'], + 'stc' => ['application/vnd.sun.xml.calc.template'], + 'std' => ['application/vnd.sun.xml.draw.template'], + 'stf' => ['application/vnd.wt.stf'], + 'sti' => ['application/vnd.sun.xml.impress.template'], + 'stk' => ['application/hyperstudio'], + 'stl' => ['application/vnd.ms-pki.stl', 'model/stl', 'model/x.stl-ascii', 'model/x.stl-binary'], + 'stm' => ['audio/x-stm'], + 'str' => ['application/vnd.pg.format'], + 'stw' => ['application/vnd.sun.xml.writer.template'], + 'sty' => ['application/x-tex', 'text/x-tex'], + 'sub' => ['image/vnd.dvb.subtitle', 'text/vnd.dvb.subtitle', 'text/x-microdvd', 'text/x-mpsub', 'text/x-subviewer'], + 'sun' => ['image/x-sun-raster'], + 'sus' => ['application/vnd.sus-calendar'], + 'susp' => ['application/vnd.sus-calendar'], + 'sv' => ['text/x-svsrc'], + 'sv4cpio' => ['application/x-sv4cpio'], + 'sv4crc' => ['application/x-sv4crc'], + 'svc' => ['application/vnd.dvb.service'], + 'svd' => ['application/vnd.svd'], + 'svg' => ['image/svg+xml'], + 'svgz' => ['image/svg+xml', 'image/svg+xml-compressed'], + 'svh' => ['text/x-svhdr'], + 'swa' => ['application/x-director'], + 'swap' => ['text/x-systemd-unit'], + 'swf' => ['application/futuresplash', 'application/vnd.adobe.flash.movie', 'application/x-shockwave-flash'], + 'swi' => ['application/vnd.aristanetworks.swi'], + 'swm' => ['application/x-ms-wim'], + 'sxc' => ['application/vnd.sun.xml.calc'], + 'sxd' => ['application/vnd.sun.xml.draw'], + 'sxg' => ['application/vnd.sun.xml.writer.global'], + 'sxi' => ['application/vnd.sun.xml.impress'], + 'sxm' => ['application/vnd.sun.xml.math'], + 'sxw' => ['application/vnd.sun.xml.writer'], + 'sylk' => ['text/spreadsheet'], + 't' => ['application/x-perl', 'application/x-troff', 'text/troff', 'text/x-perl', 'text/x-troff'], + 't2t' => ['text/x-txt2tags'], + 't3' => ['application/x-t3vm-image'], + 'taglet' => ['application/vnd.mynfc'], + 'tao' => ['application/vnd.tao.intent-module-archive'], + 'tar' => ['application/x-tar', 'application/x-gtar'], + 'tar.Z' => ['application/x-tarz'], + 'tar.bz' => ['application/x-bzip-compressed-tar'], + 'tar.bz2' => ['application/x-bzip-compressed-tar'], + 'tar.gz' => ['application/x-compressed-tar'], + 'tar.lrz' => ['application/x-lrzip-compressed-tar'], + 'tar.lz' => ['application/x-lzip-compressed-tar'], + 'tar.lz4' => ['application/x-lz4-compressed-tar'], + 'tar.lzma' => ['application/x-lzma-compressed-tar'], + 'tar.lzo' => ['application/x-tzo'], + 'tar.xz' => ['application/x-xz-compressed-tar'], + 'target' => ['text/x-systemd-unit'], + 'taz' => ['application/x-tarz'], + 'tb2' => ['application/x-bzip-compressed-tar'], + 'tbz' => ['application/x-bzip-compressed-tar'], + 'tbz2' => ['application/x-bzip-compressed-tar'], + 'tcap' => ['application/vnd.3gpp2.tcap'], + 'tcl' => ['application/x-tcl', 'text/x-tcl'], + 'teacher' => ['application/vnd.smart.teacher'], + 'tei' => ['application/tei+xml'], + 'teicorpus' => ['application/tei+xml'], + 'tex' => ['application/x-tex', 'text/x-tex'], + 'texi' => ['application/x-texinfo', 'text/x-texinfo'], + 'texinfo' => ['application/x-texinfo', 'text/x-texinfo'], + 'text' => ['text/plain'], + 'tfi' => ['application/thraud+xml'], + 'tfm' => ['application/x-tex-tfm'], + 'tga' => ['image/x-icb', 'image/x-tga'], + 'tgz' => ['application/x-compressed-tar'], + 'theme' => ['application/x-theme'], + 'themepack' => ['application/x-windows-themepack'], + 'thmx' => ['application/vnd.ms-officetheme'], + 'tif' => ['image/tiff'], + 'tiff' => ['image/tiff'], + 'timer' => ['text/x-systemd-unit'], + 'tk' => ['text/x-tcl'], + 'tlrz' => ['application/x-lrzip-compressed-tar'], + 'tlz' => ['application/x-lzma-compressed-tar'], + 'tmo' => ['application/vnd.tmobile-livetv'], + 'tnef' => ['application/ms-tnef', 'application/vnd.ms-tnef'], + 'tnf' => ['application/ms-tnef', 'application/vnd.ms-tnef'], + 'toc' => ['application/x-cdrdao-toc'], + 'torrent' => ['application/x-bittorrent'], + 'tpic' => ['image/x-icb', 'image/x-tga'], + 'tpl' => ['application/vnd.groove-tool-template'], + 'tpt' => ['application/vnd.trid.tpt'], + 'tr' => ['application/x-troff', 'text/troff', 'text/x-troff'], + 'tra' => ['application/vnd.trueapp'], + 'trig' => ['application/trig', 'application/x-trig'], + 'trm' => ['application/x-msterminal'], + 'ts' => ['application/x-linguist', 'text/vnd.qt.linguist', 'text/vnd.trolltech.linguist', 'video/mp2t'], + 'tsd' => ['application/timestamped-data'], + 'tsv' => ['text/tab-separated-values'], + 'tta' => ['audio/tta', 'audio/x-tta'], + 'ttc' => ['font/collection'], + 'ttf' => ['application/x-font-truetype', 'application/x-font-ttf', 'font/ttf'], + 'ttl' => ['text/turtle'], + 'ttx' => ['application/x-font-ttx'], + 'twd' => ['application/vnd.simtech-mindmapper'], + 'twds' => ['application/vnd.simtech-mindmapper'], + 'twig' => ['text/x-twig'], + 'txd' => ['application/vnd.genomatix.tuxedo'], + 'txf' => ['application/vnd.mobius.txf'], + 'txt' => ['text/plain'], + 'txz' => ['application/x-xz-compressed-tar'], + 'tzo' => ['application/x-tzo'], + 'u32' => ['application/x-authorware-bin'], + 'udeb' => ['application/vnd.debian.binary-package', 'application/x-deb', 'application/x-debian-package'], + 'ufd' => ['application/vnd.ufdl'], + 'ufdl' => ['application/vnd.ufdl'], + 'ufraw' => ['application/x-ufraw'], + 'ui' => ['application/x-designer', 'application/x-gtk-builder'], + 'uil' => ['text/x-uil'], + 'ult' => ['audio/x-mod'], + 'ulx' => ['application/x-glulx'], + 'umj' => ['application/vnd.umajin'], + 'unf' => ['application/x-nes-rom'], + 'uni' => ['audio/x-mod'], + 'unif' => ['application/x-nes-rom'], + 'unityweb' => ['application/vnd.unity'], + 'uoml' => ['application/vnd.uoml+xml'], + 'uri' => ['text/uri-list'], + 'uris' => ['text/uri-list'], + 'url' => ['application/x-mswinurl'], + 'urls' => ['text/uri-list'], + 'ustar' => ['application/x-ustar'], + 'utz' => ['application/vnd.uiq.theme'], + 'uu' => ['text/x-uuencode'], + 'uue' => ['text/x-uuencode', 'zz-application/zz-winassoc-uu'], + 'uva' => ['audio/vnd.dece.audio'], + 'uvd' => ['application/vnd.dece.data'], + 'uvf' => ['application/vnd.dece.data'], + 'uvg' => ['image/vnd.dece.graphic'], + 'uvh' => ['video/vnd.dece.hd'], + 'uvi' => ['image/vnd.dece.graphic'], + 'uvm' => ['video/vnd.dece.mobile'], + 'uvp' => ['video/vnd.dece.pd'], + 'uvs' => ['video/vnd.dece.sd'], + 'uvt' => ['application/vnd.dece.ttml+xml'], + 'uvu' => ['video/vnd.uvvu.mp4'], + 'uvv' => ['video/vnd.dece.video'], + 'uvva' => ['audio/vnd.dece.audio'], + 'uvvd' => ['application/vnd.dece.data'], + 'uvvf' => ['application/vnd.dece.data'], + 'uvvg' => ['image/vnd.dece.graphic'], + 'uvvh' => ['video/vnd.dece.hd'], + 'uvvi' => ['image/vnd.dece.graphic'], + 'uvvm' => ['video/vnd.dece.mobile'], + 'uvvp' => ['video/vnd.dece.pd'], + 'uvvs' => ['video/vnd.dece.sd'], + 'uvvt' => ['application/vnd.dece.ttml+xml'], + 'uvvu' => ['video/vnd.uvvu.mp4'], + 'uvvv' => ['video/vnd.dece.video'], + 'uvvx' => ['application/vnd.dece.unspecified'], + 'uvvz' => ['application/vnd.dece.zip'], + 'uvx' => ['application/vnd.dece.unspecified'], + 'uvz' => ['application/vnd.dece.zip'], + 'v' => ['text/x-verilog'], + 'v64' => ['application/x-n64-rom'], + 'vala' => ['text/x-vala'], + 'vapi' => ['text/x-vala'], + 'vb' => ['application/x-virtual-boy-rom'], + 'vcard' => ['text/directory', 'text/vcard', 'text/x-vcard'], + 'vcd' => ['application/x-cdlink'], + 'vcf' => ['text/x-vcard', 'text/directory', 'text/vcard'], + 'vcg' => ['application/vnd.groove-vcard'], + 'vcs' => ['application/ics', 'text/calendar', 'text/x-vcalendar'], + 'vct' => ['text/directory', 'text/vcard', 'text/x-vcard'], + 'vcx' => ['application/vnd.vcx'], + 'vda' => ['image/x-icb', 'image/x-tga'], + 'vhd' => ['text/x-vhdl'], + 'vhdl' => ['text/x-vhdl'], + 'vis' => ['application/vnd.visionary'], + 'viv' => ['video/vivo', 'video/vnd.vivo'], + 'vivo' => ['video/vivo', 'video/vnd.vivo'], + 'vlc' => ['application/m3u', 'audio/m3u', 'audio/mpegurl', 'audio/x-m3u', 'audio/x-mp3-playlist', 'audio/x-mpegurl'], + 'vob' => ['video/mpeg', 'video/mpeg-system', 'video/x-mpeg', 'video/x-mpeg-system', 'video/x-mpeg2', 'video/x-ms-vob'], + 'voc' => ['audio/x-voc'], + 'vor' => ['application/vnd.stardivision.writer', 'application/vnd.stardivision.writer-global'], + 'vox' => ['application/x-authorware-bin'], + 'vrm' => ['model/vrml'], + 'vrml' => ['model/vrml'], + 'vsd' => ['application/vnd.visio'], + 'vsdm' => ['application/vnd.ms-visio.drawing.macroenabled.main+xml'], + 'vsdx' => ['application/vnd.ms-visio.drawing.main+xml'], + 'vsf' => ['application/vnd.vsf'], + 'vss' => ['application/vnd.visio'], + 'vssm' => ['application/vnd.ms-visio.stencil.macroenabled.main+xml'], + 'vssx' => ['application/vnd.ms-visio.stencil.main+xml'], + 'vst' => ['application/vnd.visio', 'image/x-icb', 'image/x-tga'], + 'vstm' => ['application/vnd.ms-visio.template.macroenabled.main+xml'], + 'vstx' => ['application/vnd.ms-visio.template.main+xml'], + 'vsw' => ['application/vnd.visio'], + 'vtt' => ['text/vtt'], + 'vtu' => ['model/vnd.vtu'], + 'vxml' => ['application/voicexml+xml'], + 'w3d' => ['application/x-director'], + 'wad' => ['application/x-doom', 'application/x-doom-wad', 'application/x-wii-wad'], + 'wav' => ['audio/wav', 'audio/vnd.wave', 'audio/x-wav'], + 'wax' => ['application/x-ms-asx', 'audio/x-ms-asx', 'audio/x-ms-wax', 'video/x-ms-wax', 'video/x-ms-wmx', 'video/x-ms-wvx'], + 'wb1' => ['application/x-quattropro'], + 'wb2' => ['application/x-quattropro'], + 'wb3' => ['application/x-quattropro'], + 'wbmp' => ['image/vnd.wap.wbmp'], + 'wbs' => ['application/vnd.criticaltools.wbs+xml'], + 'wbxml' => ['application/vnd.wap.wbxml'], + 'wcm' => ['application/vnd.ms-works'], + 'wdb' => ['application/vnd.ms-works'], + 'wdp' => ['image/vnd.ms-photo'], + 'weba' => ['audio/webm'], + 'webm' => ['video/webm'], + 'webp' => ['image/webp'], + 'wg' => ['application/vnd.pmi.widget'], + 'wgt' => ['application/widget'], + 'wim' => ['application/x-ms-wim'], + 'wk1' => ['application/lotus123', 'application/vnd.lotus-1-2-3', 'application/wk1', 'application/x-123', 'application/x-lotus123', 'zz-application/zz-winassoc-123'], + 'wk3' => ['application/lotus123', 'application/vnd.lotus-1-2-3', 'application/wk1', 'application/x-123', 'application/x-lotus123', 'zz-application/zz-winassoc-123'], + 'wk4' => ['application/lotus123', 'application/vnd.lotus-1-2-3', 'application/wk1', 'application/x-123', 'application/x-lotus123', 'zz-application/zz-winassoc-123'], + 'wkdownload' => ['application/x-partial-download'], + 'wks' => ['application/lotus123', 'application/vnd.lotus-1-2-3', 'application/vnd.ms-works', 'application/wk1', 'application/x-123', 'application/x-lotus123', 'zz-application/zz-winassoc-123'], + 'wm' => ['video/x-ms-wm'], + 'wma' => ['audio/x-ms-wma', 'audio/wma'], + 'wmd' => ['application/x-ms-wmd'], + 'wmf' => ['application/wmf', 'application/x-msmetafile', 'application/x-wmf', 'image/wmf', 'image/x-win-metafile', 'image/x-wmf'], + 'wml' => ['text/vnd.wap.wml'], + 'wmlc' => ['application/vnd.wap.wmlc'], + 'wmls' => ['text/vnd.wap.wmlscript'], + 'wmlsc' => ['application/vnd.wap.wmlscriptc'], + 'wmv' => ['audio/x-ms-wmv', 'video/x-ms-wmv'], + 'wmx' => ['application/x-ms-asx', 'audio/x-ms-asx', 'video/x-ms-wax', 'video/x-ms-wmx', 'video/x-ms-wvx'], + 'wmz' => ['application/x-ms-wmz', 'application/x-msmetafile'], + 'woff' => ['application/font-woff', 'application/x-font-woff', 'font/woff'], + 'woff2' => ['font/woff', 'font/woff2'], + 'wp' => ['application/vnd.wordperfect', 'application/wordperfect', 'application/x-wordperfect'], + 'wp4' => ['application/vnd.wordperfect', 'application/wordperfect', 'application/x-wordperfect'], + 'wp5' => ['application/vnd.wordperfect', 'application/wordperfect', 'application/x-wordperfect'], + 'wp6' => ['application/vnd.wordperfect', 'application/wordperfect', 'application/x-wordperfect'], + 'wpd' => ['application/vnd.wordperfect', 'application/wordperfect', 'application/x-wordperfect'], + 'wpg' => ['application/x-wpg'], + 'wpl' => ['application/vnd.ms-wpl'], + 'wpp' => ['application/vnd.wordperfect', 'application/wordperfect', 'application/x-wordperfect'], + 'wps' => ['application/vnd.ms-works'], + 'wqd' => ['application/vnd.wqd'], + 'wri' => ['application/x-mswrite'], + 'wrl' => ['model/vrml'], + 'ws' => ['application/x-wonderswan-rom'], + 'wsc' => ['application/x-wonderswan-color-rom'], + 'wsdl' => ['application/wsdl+xml'], + 'wsgi' => ['text/x-python'], + 'wspolicy' => ['application/wspolicy+xml'], + 'wtb' => ['application/vnd.webturbo'], + 'wv' => ['audio/x-wavpack'], + 'wvc' => ['audio/x-wavpack-correction'], + 'wvp' => ['audio/x-wavpack'], + 'wvx' => ['application/x-ms-asx', 'audio/x-ms-asx', 'video/x-ms-wax', 'video/x-ms-wmx', 'video/x-ms-wvx'], + 'wwf' => ['application/wwf', 'application/x-wwf'], + 'x32' => ['application/x-authorware-bin'], + 'x3d' => ['model/x3d+xml'], + 'x3db' => ['model/x3d+binary'], + 'x3dbz' => ['model/x3d+binary'], + 'x3dv' => ['model/x3d+vrml'], + 'x3dvz' => ['model/x3d+vrml'], + 'x3dz' => ['model/x3d+xml'], + 'x3f' => ['image/x-sigma-x3f'], + 'xac' => ['application/x-gnucash'], + 'xaml' => ['application/xaml+xml'], + 'xap' => ['application/x-silverlight-app'], + 'xar' => ['application/vnd.xara', 'application/x-xar'], + 'xbap' => ['application/x-ms-xbap'], + 'xbd' => ['application/vnd.fujixerox.docuworks.binder'], + 'xbel' => ['application/x-xbel'], + 'xbl' => ['application/xml', 'text/xml'], + 'xbm' => ['image/x-xbitmap'], + 'xcf' => ['image/x-xcf'], + 'xcf.bz2' => ['image/x-compressed-xcf'], + 'xcf.gz' => ['image/x-compressed-xcf'], + 'xdf' => ['application/xcap-diff+xml'], + 'xdgapp' => ['application/vnd.flatpak', 'application/vnd.xdgapp'], + 'xdm' => ['application/vnd.syncml.dm+xml'], + 'xdp' => ['application/vnd.adobe.xdp+xml'], + 'xdssc' => ['application/dssc+xml'], + 'xdw' => ['application/vnd.fujixerox.docuworks'], + 'xenc' => ['application/xenc+xml'], + 'xer' => ['application/patch-ops-error+xml'], + 'xfdf' => ['application/vnd.adobe.xfdf'], + 'xfdl' => ['application/vnd.xfdl'], + 'xhe' => ['audio/usac'], + 'xht' => ['application/xhtml+xml'], + 'xhtml' => ['application/xhtml+xml'], + 'xhvml' => ['application/xv+xml'], + 'xi' => ['audio/x-xi'], + 'xif' => ['image/vnd.xiff'], + 'xla' => ['application/msexcel', 'application/vnd.ms-excel', 'application/x-msexcel', 'zz-application/zz-winassoc-xls'], + 'xlam' => ['application/vnd.ms-excel.addin.macroenabled.12'], + 'xlc' => ['application/msexcel', 'application/vnd.ms-excel', 'application/x-msexcel', 'zz-application/zz-winassoc-xls'], + 'xld' => ['application/msexcel', 'application/vnd.ms-excel', 'application/x-msexcel', 'zz-application/zz-winassoc-xls'], + 'xlf' => ['application/x-xliff', 'application/x-xliff+xml', 'application/xliff+xml'], + 'xliff' => ['application/x-xliff', 'application/xliff+xml'], + 'xll' => ['application/msexcel', 'application/vnd.ms-excel', 'application/x-msexcel', 'zz-application/zz-winassoc-xls'], + 'xlm' => ['application/msexcel', 'application/vnd.ms-excel', 'application/x-msexcel', 'zz-application/zz-winassoc-xls'], + 'xlr' => ['application/vnd.ms-works'], + 'xls' => ['application/vnd.ms-excel', 'application/msexcel', 'application/x-msexcel', 'zz-application/zz-winassoc-xls'], + 'xlsb' => ['application/vnd.ms-excel.sheet.binary.macroenabled.12'], + 'xlsm' => ['application/vnd.ms-excel.sheet.macroenabled.12'], + 'xlsx' => ['application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'], + 'xlt' => ['application/msexcel', 'application/vnd.ms-excel', 'application/x-msexcel', 'zz-application/zz-winassoc-xls'], + 'xltm' => ['application/vnd.ms-excel.template.macroenabled.12'], + 'xltx' => ['application/vnd.openxmlformats-officedocument.spreadsheetml.template'], + 'xlw' => ['application/msexcel', 'application/vnd.ms-excel', 'application/x-msexcel', 'zz-application/zz-winassoc-xls'], + 'xm' => ['audio/x-xm', 'audio/xm'], + 'xmf' => ['audio/mobile-xmf', 'audio/x-xmf', 'audio/xmf'], + 'xmi' => ['text/x-xmi'], + 'xml' => ['application/xml', 'text/xml'], + 'xo' => ['application/vnd.olpc-sugar'], + 'xop' => ['application/xop+xml'], + 'xpi' => ['application/x-xpinstall'], + 'xpl' => ['application/xproc+xml'], + 'xpm' => ['image/x-xpixmap', 'image/x-xpm'], + 'xpr' => ['application/vnd.is-xpr'], + 'xps' => ['application/oxps', 'application/vnd.ms-xpsdocument', 'application/xps'], + 'xpw' => ['application/vnd.intercon.formnet'], + 'xpx' => ['application/vnd.intercon.formnet'], + 'xsd' => ['application/xml', 'text/xml'], + 'xsl' => ['application/xml', 'application/xslt+xml'], + 'xslfo' => ['text/x-xslfo'], + 'xslt' => ['application/xslt+xml'], + 'xsm' => ['application/vnd.syncml+xml'], + 'xspf' => ['application/x-xspf+xml', 'application/xspf+xml'], + 'xul' => ['application/vnd.mozilla.xul+xml'], + 'xvm' => ['application/xv+xml'], + 'xvml' => ['application/xv+xml'], + 'xwd' => ['image/x-xwindowdump'], + 'xyz' => ['chemical/x-xyz'], + 'xz' => ['application/x-xz'], + 'yaml' => ['application/x-yaml', 'text/x-yaml', 'text/yaml'], + 'yang' => ['application/yang'], + 'yin' => ['application/yin+xml'], + 'yml' => ['application/x-yaml', 'text/x-yaml', 'text/yaml'], + 'yt' => ['application/vnd.youtube.yt'], + 'z1' => ['application/x-zmachine'], + 'z2' => ['application/x-zmachine'], + 'z3' => ['application/x-zmachine'], + 'z4' => ['application/x-zmachine'], + 'z5' => ['application/x-zmachine'], + 'z6' => ['application/x-zmachine'], + 'z64' => ['application/x-n64-rom'], + 'z7' => ['application/x-zmachine'], + 'z8' => ['application/x-zmachine'], + 'zabw' => ['application/x-abiword'], + 'zaz' => ['application/vnd.zzazz.deck+xml'], + 'zip' => ['application/zip', 'application/x-zip', 'application/x-zip-compressed'], + 'zir' => ['application/vnd.zul'], + 'zirz' => ['application/vnd.zul'], + 'zmm' => ['application/vnd.handheld-entertainment+xml'], + 'zoo' => ['application/x-zoo'], + 'zsav' => ['application/x-spss-sav', 'application/x-spss-savefile'], + 'zz' => ['application/zlib'], + '123' => ['application/lotus123', 'application/vnd.lotus-1-2-3', 'application/wk1', 'application/x-123', 'application/x-lotus123', 'zz-application/zz-winassoc-123'], + '602' => ['application/x-t602'], + '669' => ['audio/x-mod'], + ]; +} diff --git a/vendor/symfony/mime/MimeTypesInterface.php b/vendor/symfony/mime/MimeTypesInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..bdf20429a1cd6279e28a3bd567bd5188c4f79df9 --- /dev/null +++ b/vendor/symfony/mime/MimeTypesInterface.php @@ -0,0 +1,34 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime; + +/** + * @author Fabien Potencier <fabien@symfony.com> + * + * @experimental in 4.3 + */ +interface MimeTypesInterface extends MimeTypeGuesserInterface +{ + /** + * Gets the extensions for the given MIME type. + * + * @return string[] an array of extensions (first one is the preferred one) + */ + public function getExtensions(string $mimeType): array; + + /** + * Gets the MIME types for the given extension. + * + * @return string[] an array of MIME types (first one is the preferred one) + */ + public function getMimeTypes(string $ext): array; +} diff --git a/vendor/symfony/mime/NamedAddress.php b/vendor/symfony/mime/NamedAddress.php new file mode 100644 index 0000000000000000000000000000000000000000..b13fd73526d5f5db0fa71fdd2bc9df69ae87e78f --- /dev/null +++ b/vendor/symfony/mime/NamedAddress.php @@ -0,0 +1,44 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime; + +/** + * @author Fabien Potencier <fabien@symfony.com> + * + * @experimental in 4.3 + */ +final class NamedAddress extends Address +{ + private $name; + + public function __construct(string $address, string $name) + { + parent::__construct($address); + + $this->name = trim(str_replace(["\n", "\r"], '', $name)); + } + + public function getName(): string + { + return $this->name; + } + + public function getEncodedNamedAddress(): string + { + return ($n = $this->getName()) ? $n.' <'.$this->getEncodedAddress().'>' : $this->getEncodedAddress(); + } + + public function toString(): string + { + return $this->getEncodedNamedAddress(); + } +} diff --git a/vendor/symfony/mime/Part/AbstractMultipartPart.php b/vendor/symfony/mime/Part/AbstractMultipartPart.php new file mode 100644 index 0000000000000000000000000000000000000000..34a94d25bc9491a5823e8e3d8003e3111f8067ab --- /dev/null +++ b/vendor/symfony/mime/Part/AbstractMultipartPart.php @@ -0,0 +1,87 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime\Part; + +use Symfony\Component\Mime\Header\Headers; + +/** + * @author Fabien Potencier <fabien@symfony.com> + * + * @experimental in 4.3 + */ +abstract class AbstractMultipartPart extends AbstractPart +{ + private $boundary; + private $parts = []; + + public function __construct(AbstractPart ...$parts) + { + parent::__construct(); + + foreach ($parts as $part) { + $this->parts[] = $part; + } + } + + /** + * @return AbstractPart[] + */ + public function getParts(): array + { + return $this->parts; + } + + public function getMediaType(): string + { + return 'multipart'; + } + + public function getPreparedHeaders(): Headers + { + $headers = parent::getPreparedHeaders(); + $headers->setHeaderParameter('Content-Type', 'boundary', $this->getBoundary()); + + return $headers; + } + + public function bodyToString(): string + { + $parts = $this->getParts(); + $string = ''; + foreach ($parts as $part) { + $string .= '--'.$this->getBoundary()."\r\n".$part->toString()."\r\n"; + } + $string .= '--'.$this->getBoundary()."--\r\n"; + + return $string; + } + + public function bodyToIterable(): iterable + { + $parts = $this->getParts(); + foreach ($parts as $part) { + yield '--'.$this->getBoundary()."\r\n"; + yield from $part->toIterable(); + yield "\r\n"; + } + yield '--'.$this->getBoundary()."--\r\n"; + } + + private function getBoundary(): string + { + if (null === $this->boundary) { + $this->boundary = '_=_symfony_'.time().'_'.bin2hex(random_bytes(16)).'_=_'; + } + + return $this->boundary; + } +} diff --git a/vendor/symfony/mime/Part/AbstractPart.php b/vendor/symfony/mime/Part/AbstractPart.php new file mode 100644 index 0000000000000000000000000000000000000000..29eaa1ebfdc326f079e4a70712644116390a4230 --- /dev/null +++ b/vendor/symfony/mime/Part/AbstractPart.php @@ -0,0 +1,62 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime\Part; + +use Symfony\Component\Mime\Header\Headers; + +/** + * @author Fabien Potencier <fabien@symfony.com> + * + * @experimental in 4.3 + */ +abstract class AbstractPart +{ + private $headers; + + public function __construct() + { + $this->headers = new Headers(); + } + + public function getHeaders(): Headers + { + return $this->headers; + } + + public function getPreparedHeaders(): Headers + { + $headers = clone $this->headers; + $headers->setHeaderBody('Parameterized', 'Content-Type', $this->getMediaType().'/'.$this->getMediaSubtype()); + + return $headers; + } + + public function toString(): string + { + return $this->getPreparedHeaders()->toString()."\r\n".$this->bodyToString(); + } + + public function toIterable(): iterable + { + yield $this->getPreparedHeaders()->toString(); + yield "\r\n"; + yield from $this->bodyToIterable(); + } + + abstract public function bodyToString(): string; + + abstract public function bodyToIterable(): iterable; + + abstract public function getMediaType(): string; + + abstract public function getMediaSubtype(): string; +} diff --git a/vendor/symfony/mime/Part/DataPart.php b/vendor/symfony/mime/Part/DataPart.php new file mode 100644 index 0000000000000000000000000000000000000000..1cfb1e69b08d056b84dc7d52ab5e4f658df50fc3 --- /dev/null +++ b/vendor/symfony/mime/Part/DataPart.php @@ -0,0 +1,150 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime\Part; + +use Symfony\Component\Mime\Exception\InvalidArgumentException; +use Symfony\Component\Mime\Header\Headers; +use Symfony\Component\Mime\MimeTypes; + +/** + * @author Fabien Potencier <fabien@symfony.com> + * + * @experimental in 4.3 + */ +class DataPart extends TextPart +{ + private static $mimeTypes; + + private $filename; + private $mediaType; + private $cid; + private $handle; + + /** + * @param resource|string $body + */ + public function __construct($body, string $filename = null, string $contentType = null, string $encoding = null) + { + if (null === $contentType) { + $contentType = 'application/octet-stream'; + } + list($this->mediaType, $subtype) = explode('/', $contentType); + + parent::__construct($body, null, $subtype, $encoding); + + $this->filename = $filename; + $this->setName($filename); + $this->setDisposition('attachment'); + } + + public static function fromPath(string $path, string $name = null, string $contentType = null): self + { + // FIXME: if file is not readable, exception? + + if (null === $contentType) { + $ext = strtolower(substr($path, strrpos($path, '.') + 1)); + if (null === self::$mimeTypes) { + self::$mimeTypes = new MimeTypes(); + } + $contentType = self::$mimeTypes->getMimeTypes($ext)[0] ?? 'application/octet-stream'; + } + + if (false === $handle = @fopen($path, 'r', false)) { + throw new InvalidArgumentException(sprintf('Unable to open path "%s"', $path)); + } + $p = new self($handle, $name ?: basename($path), $contentType); + $p->handle = $handle; + + return $p; + } + + /** + * @return $this + */ + public function asInline() + { + return $this->setDisposition('inline'); + } + + public function getContentId(): string + { + return $this->cid ?: $this->cid = $this->generateContentId(); + } + + public function hasContentId(): bool + { + return null !== $this->cid; + } + + public function getMediaType(): string + { + return $this->mediaType; + } + + public function getPreparedHeaders(): Headers + { + $headers = parent::getPreparedHeaders(); + + if (null !== $this->cid) { + $headers->setHeaderBody('Id', 'Content-ID', $this->cid); + } + + if (null !== $this->filename) { + $headers->setHeaderParameter('Content-Disposition', 'filename', $this->filename); + } + + return $headers; + } + + private function generateContentId(): string + { + return bin2hex(random_bytes(16)).'@symfony'; + } + + public function __destruct() + { + if (null !== $this->handle && \is_resource($this->handle)) { + fclose($this->handle); + } + } + + public function __sleep() + { + // converts the body to a string + parent::__sleep(); + + $this->_parent = []; + foreach (['body', 'charset', 'subtype', 'disposition', 'name', 'encoding'] as $name) { + $r = new \ReflectionProperty(TextPart::class, $name); + $r->setAccessible(true); + $this->_parent[$name] = $r->getValue($this); + } + $this->_headers = $this->getHeaders(); + + return ['_headers', '_parent', 'filename', 'mediaType']; + } + + public function __wakeup() + { + $r = new \ReflectionProperty(AbstractPart::class, 'headers'); + $r->setAccessible(true); + $r->setValue($this, $this->_headers); + unset($this->_headers); + + foreach (['body', 'charset', 'subtype', 'disposition', 'name', 'encoding'] as $name) { + $r = new \ReflectionProperty(TextPart::class, $name); + $r->setAccessible(true); + $r->setValue($this, $this->_parent[$name]); + } + unset($this->_parent); + } +} diff --git a/vendor/symfony/mime/Part/MessagePart.php b/vendor/symfony/mime/Part/MessagePart.php new file mode 100644 index 0000000000000000000000000000000000000000..64a53404220d0368b980f7fba9d1d0afc9d51ab6 --- /dev/null +++ b/vendor/symfony/mime/Part/MessagePart.php @@ -0,0 +1,64 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime\Part; + +use Symfony\Component\Mime\Message; +use Symfony\Component\Mime\RawMessage; + +/** + * @final + * + * @author Fabien Potencier <fabien@symfony.com> + * + * @experimental in 4.3 + */ +class MessagePart extends DataPart +{ + private $message; + + public function __construct(RawMessage $message) + { + if ($message instanceof Message) { + $name = $message->getHeaders()->getHeaderBody('Subject').'.eml'; + } else { + $name = 'email.eml'; + } + parent::__construct('', $name); + + $this->message = $message; + } + + public function getMediaType(): string + { + return 'message'; + } + + public function getMediaSubtype(): string + { + return 'rfc822'; + } + + public function getBody(): string + { + return $this->message->toString(); + } + + public function bodyToString(): string + { + return $this->getBody(); + } + + public function bodyToIterable(): iterable + { + return $this->message->toIterable(); + } +} diff --git a/vendor/symfony/mime/Part/Multipart/AlternativePart.php b/vendor/symfony/mime/Part/Multipart/AlternativePart.php new file mode 100644 index 0000000000000000000000000000000000000000..ad316a490a92a820271b218392c583c5861faad1 --- /dev/null +++ b/vendor/symfony/mime/Part/Multipart/AlternativePart.php @@ -0,0 +1,27 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime\Part\Multipart; + +use Symfony\Component\Mime\Part\AbstractMultipartPart; + +/** + * @author Fabien Potencier <fabien@symfony.com> + * + * @experimental in 4.3 + */ +final class AlternativePart extends AbstractMultipartPart +{ + public function getMediaSubtype(): string + { + return 'alternative'; + } +} diff --git a/vendor/symfony/mime/Part/Multipart/DigestPart.php b/vendor/symfony/mime/Part/Multipart/DigestPart.php new file mode 100644 index 0000000000000000000000000000000000000000..6199e5b8dba76eab955fd42e76e6e08b8c4367de --- /dev/null +++ b/vendor/symfony/mime/Part/Multipart/DigestPart.php @@ -0,0 +1,33 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime\Part\Multipart; + +use Symfony\Component\Mime\Part\AbstractMultipartPart; +use Symfony\Component\Mime\Part\MessagePart; + +/** + * @author Fabien Potencier <fabien@symfony.com> + * + * @experimental in 4.3 + */ +final class DigestPart extends AbstractMultipartPart +{ + public function __construct(MessagePart ...$parts) + { + parent::__construct(...$parts); + } + + public function getMediaSubtype(): string + { + return 'digest'; + } +} diff --git a/vendor/symfony/mime/Part/Multipart/FormDataPart.php b/vendor/symfony/mime/Part/Multipart/FormDataPart.php new file mode 100644 index 0000000000000000000000000000000000000000..75d69a88a08fc34f1a0bb859a133f54122796d42 --- /dev/null +++ b/vendor/symfony/mime/Part/Multipart/FormDataPart.php @@ -0,0 +1,96 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime\Part\Multipart; + +use Symfony\Component\Mime\Exception\InvalidArgumentException; +use Symfony\Component\Mime\Part\AbstractMultipartPart; +use Symfony\Component\Mime\Part\DataPart; +use Symfony\Component\Mime\Part\TextPart; + +/** + * Implements RFC 7578. + * + * @author Fabien Potencier <fabien@symfony.com> + * + * @experimental in 4.3 + */ +final class FormDataPart extends AbstractMultipartPart +{ + private $fields = []; + + /** + * @param (string|array|DataPart)[] $fields + */ + public function __construct(array $fields = []) + { + parent::__construct(); + + foreach ($fields as $name => $value) { + if (!\is_string($value) && !\is_array($value) && !$value instanceof TextPart) { + throw new InvalidArgumentException(sprintf('A form field value can only be a string, an array, or an instance of TextPart ("%s" given).', \is_object($value) ? \get_class($value) : \gettype($value))); + } + + $this->fields[$name] = $value; + } + // HTTP does not support \r\n in header values + $this->getHeaders()->setMaxLineLength(PHP_INT_MAX); + } + + public function getMediaSubtype(): string + { + return 'form-data'; + } + + public function getParts(): array + { + return $this->prepareFields($this->fields); + } + + private function prepareFields(array $fields): array + { + $values = []; + array_walk_recursive($fields, function ($item, $key) use (&$values) { + if (!\is_array($item)) { + $values[] = $this->preparePart($key, $item); + } + }); + + return $values; + } + + private function preparePart($name, $value): TextPart + { + if (\is_string($value)) { + return $this->configurePart($name, new TextPart($value, 'utf-8', 'plain', '8bit')); + } + + return $this->configurePart($name, $value); + } + + private function configurePart(string $name, TextPart $part): TextPart + { + static $r; + + if (null === $r) { + $r = new \ReflectionProperty(TextPart::class, 'encoding'); + $r->setAccessible(true); + } + + $part->setDisposition('form-data'); + $part->setName($name); + // HTTP does not support \r\n in header values + $part->getHeaders()->setMaxLineLength(PHP_INT_MAX); + $r->setValue($part, '8bit'); + + return $part; + } +} diff --git a/vendor/symfony/mime/Part/Multipart/MixedPart.php b/vendor/symfony/mime/Part/Multipart/MixedPart.php new file mode 100644 index 0000000000000000000000000000000000000000..eaa869fbeea897ba2e11487e520c6018cbb1ad74 --- /dev/null +++ b/vendor/symfony/mime/Part/Multipart/MixedPart.php @@ -0,0 +1,27 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime\Part\Multipart; + +use Symfony\Component\Mime\Part\AbstractMultipartPart; + +/** + * @author Fabien Potencier <fabien@symfony.com> + * + * @experimental in 4.3 + */ +final class MixedPart extends AbstractMultipartPart +{ + public function getMediaSubtype(): string + { + return 'mixed'; + } +} diff --git a/vendor/symfony/mime/Part/Multipart/RelatedPart.php b/vendor/symfony/mime/Part/Multipart/RelatedPart.php new file mode 100644 index 0000000000000000000000000000000000000000..2d5563073ce0648cb32e4625ef4fe1be9e9ba578 --- /dev/null +++ b/vendor/symfony/mime/Part/Multipart/RelatedPart.php @@ -0,0 +1,57 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime\Part\Multipart; + +use Symfony\Component\Mime\Part\AbstractMultipartPart; +use Symfony\Component\Mime\Part\AbstractPart; + +/** + * @author Fabien Potencier <fabien@symfony.com> + * + * @experimental in 4.3 + */ +final class RelatedPart extends AbstractMultipartPart +{ + private $mainPart; + + public function __construct(AbstractPart $mainPart, AbstractPart $part, AbstractPart ...$parts) + { + $this->mainPart = $mainPart; + $this->prepareParts($part, ...$parts); + + parent::__construct($part, ...$parts); + } + + public function getParts(): array + { + return array_merge([$this->mainPart], parent::getParts()); + } + + public function getMediaSubtype(): string + { + return 'related'; + } + + private function generateContentId(): string + { + return bin2hex(random_bytes(16)).'@symfony'; + } + + private function prepareParts(AbstractPart ...$parts): void + { + foreach ($parts as $part) { + if (!$part->getHeaders()->has('Content-ID')) { + $part->getHeaders()->setHeaderBody('Id', 'Content-ID', $this->generateContentId()); + } + } + } +} diff --git a/vendor/symfony/mime/Part/TextPart.php b/vendor/symfony/mime/Part/TextPart.php new file mode 100644 index 0000000000000000000000000000000000000000..6a0418531525d7eef719606d3850054ddc7edc5a --- /dev/null +++ b/vendor/symfony/mime/Part/TextPart.php @@ -0,0 +1,190 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime\Part; + +use Symfony\Component\Mime\Encoder\Base64ContentEncoder; +use Symfony\Component\Mime\Encoder\ContentEncoderInterface; +use Symfony\Component\Mime\Encoder\EightBitContentEncoder; +use Symfony\Component\Mime\Encoder\QpContentEncoder; +use Symfony\Component\Mime\Exception\InvalidArgumentException; +use Symfony\Component\Mime\Header\Headers; + +/** + * @author Fabien Potencier <fabien@symfony.com> + * + * @experimental in 4.3 + */ +class TextPart extends AbstractPart +{ + private static $encoders = []; + + private $body; + private $charset; + private $subtype; + private $disposition; + private $name; + private $encoding; + + /** + * @param resource|string $body + */ + public function __construct($body, ?string $charset = 'utf-8', $subtype = 'plain', string $encoding = null) + { + parent::__construct(); + + if (!\is_string($body) && !\is_resource($body)) { + throw new \TypeError(sprintf('The body of "%s" must be a string or a resource (got "%s").', self::class, \is_object($body) ? \get_class($body) : \gettype($body))); + } + + $this->body = $body; + $this->charset = $charset; + $this->subtype = $subtype; + + if (null === $encoding) { + $this->encoding = $this->chooseEncoding(); + } else { + if ('quoted-printable' !== $encoding && 'base64' !== $encoding && '8bit' !== $encoding) { + throw new InvalidArgumentException(sprintf('The encoding must be one of "quoted-printable", "base64", or "8bit" ("%s" given).', $encoding)); + } + $this->encoding = $encoding; + } + } + + public function getMediaType(): string + { + return 'text'; + } + + public function getMediaSubtype(): string + { + return $this->subtype; + } + + /** + * @param string $disposition one of attachment, inline, or form-data + * + * @return $this + */ + public function setDisposition(string $disposition) + { + $this->disposition = $disposition; + + return $this; + } + + /** + * Sets the name of the file (used by FormDataPart). + * + * @return $this + */ + public function setName($name) + { + $this->name = $name; + + return $this; + } + + public function getBody(): string + { + if (!\is_resource($this->body)) { + return $this->body; + } + + if (stream_get_meta_data($this->body)['seekable'] ?? false) { + rewind($this->body); + } + + return stream_get_contents($this->body) ?: ''; + } + + public function bodyToString(): string + { + return $this->getEncoder()->encodeString($this->getBody(), $this->charset); + } + + public function bodyToIterable(): iterable + { + if (\is_resource($this->body)) { + if (stream_get_meta_data($this->body)['seekable'] ?? false) { + rewind($this->body); + } + yield from $this->getEncoder()->encodeByteStream($this->body); + } else { + yield $this->getEncoder()->encodeString($this->body); + } + } + + public function getPreparedHeaders(): Headers + { + $headers = parent::getPreparedHeaders(); + + $headers->setHeaderBody('Parameterized', 'Content-Type', $this->getMediaType().'/'.$this->getMediaSubtype()); + if ($this->charset) { + $headers->setHeaderParameter('Content-Type', 'charset', $this->charset); + } + if ($this->name) { + $headers->setHeaderParameter('Content-Type', 'name', $this->name); + } + $headers->setHeaderBody('Text', 'Content-Transfer-Encoding', $this->encoding); + + if (!$headers->has('Content-Disposition') && null !== $this->disposition) { + $headers->setHeaderBody('Parameterized', 'Content-Disposition', $this->disposition); + if ($this->name) { + $headers->setHeaderParameter('Content-Disposition', 'name', $this->name); + } + } + + return $headers; + } + + private function getEncoder(): ContentEncoderInterface + { + if ('8bit' === $this->encoding) { + return self::$encoders[$this->encoding] ?? (self::$encoders[$this->encoding] = new EightBitContentEncoder()); + } + + if ('quoted-printable' === $this->encoding) { + return self::$encoders[$this->encoding] ?? (self::$encoders[$this->encoding] = new QpContentEncoder()); + } + + return self::$encoders[$this->encoding] ?? (self::$encoders[$this->encoding] = new Base64ContentEncoder()); + } + + private function chooseEncoding(): string + { + if (null === $this->charset) { + return 'base64'; + } + + return 'quoted-printable'; + } + + public function __sleep() + { + // convert resources to strings for serialization + if (\is_resource($this->body)) { + $this->body = $this->getBody(); + } + + $this->_headers = $this->getHeaders(); + + return ['_headers', 'body', 'charset', 'subtype', 'disposition', 'name', 'encoding']; + } + + public function __wakeup() + { + $r = new \ReflectionProperty(AbstractPart::class, 'headers'); + $r->setAccessible(true); + $r->setValue($this, $this->_headers); + unset($this->_headers); + } +} diff --git a/vendor/symfony/mime/README.md b/vendor/symfony/mime/README.md new file mode 100644 index 0000000000000000000000000000000000000000..32882461e2e18647ca7cd8d04480185169bb7098 --- /dev/null +++ b/vendor/symfony/mime/README.md @@ -0,0 +1,18 @@ +MIME Component +============== + +The MIME component allows manipulating MIME messages. + +**This Component is experimental**. +[Experimental features](https://symfony.com/doc/current/contributing/code/experimental.html) +are not covered by Symfony's +[Backward Compatibility Promise](https://symfony.com/doc/current/contributing/code/bc.html). + +Resources +--------- + + * [Documentation](https://symfony.com/doc/current/components/mime.html) + * [Contributing](https://symfony.com/doc/current/contributing/index.html) + * [Report issues](https://github.com/symfony/symfony/issues) and + [send Pull Requests](https://github.com/symfony/symfony/pulls) + in the [main Symfony repository](https://github.com/symfony/symfony) diff --git a/vendor/symfony/mime/RawMessage.php b/vendor/symfony/mime/RawMessage.php new file mode 100644 index 0000000000000000000000000000000000000000..40a2795e2369eccbd80f2daa620d5c5e567afafe --- /dev/null +++ b/vendor/symfony/mime/RawMessage.php @@ -0,0 +1,81 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime; + +/** + * @author Fabien Potencier <fabien@symfony.com> + * + * @experimental in 4.3 + */ +class RawMessage implements \Serializable +{ + private $message; + + /** + * @param iterable|string $message + */ + public function __construct($message) + { + $this->message = $message; + } + + public function toString(): string + { + if (\is_string($this->message)) { + return $this->message; + } + + return $this->message = implode('', iterator_to_array($this->message, false)); + } + + public function toIterable(): iterable + { + if (\is_string($this->message)) { + yield $this->message; + + return; + } + + $message = ''; + foreach ($this->message as $chunk) { + $message .= $chunk; + yield $chunk; + } + $this->message = $message; + } + + /** + * @internal + */ + final public function serialize() + { + return serialize($this->__serialize()); + } + + /** + * @internal + */ + final public function unserialize($serialized) + { + $this->__unserialize(unserialize($serialized)); + } + + public function __serialize(): array + { + return [$this->message]; + } + + public function __unserialize(array $data): void + { + [$this->message] = $data; + } +} diff --git a/vendor/symfony/mime/Resources/bin/update_mime_types.php b/vendor/symfony/mime/Resources/bin/update_mime_types.php new file mode 100644 index 0000000000000000000000000000000000000000..74a9449c75e8d015f63663c05d99d3aaee9fb07e --- /dev/null +++ b/vendor/symfony/mime/Resources/bin/update_mime_types.php @@ -0,0 +1,166 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +// load new map +$data = file_get_contents('https://svn.apache.org/repos/asf/httpd/httpd/trunk/docs/conf/mime.types'); +$new = []; +foreach (explode("\n", $data) as $line) { + if (!$line || '#' == $line[0]) { + continue; + } + $mimeType = substr($line, 0, strpos($line, "\t")); + $extensions = explode(' ', substr($line, strrpos($line, "\t") + 1)); + $new[$mimeType] = $extensions; +} + +$xml = simplexml_load_string(file_get_contents('https://raw.github.com/minad/mimemagic/master/script/freedesktop.org.xml')); +foreach ($xml as $node) { + $exts = []; + foreach ($node->glob as $glob) { + $pattern = (string) $glob['pattern']; + if ('*' != $pattern[0] || '.' != $pattern[1]) { + continue; + } + + $exts[] = substr($pattern, 2); + } + + if (!$exts) { + continue; + } + + $mt = strtolower((string) $node['type']); + $new[$mt] = array_merge($new[$mt] ?? [], $exts); + foreach ($node->alias as $alias) { + $mt = strtolower((string) $alias['type']); + $new[$mt] = array_merge($new[$mt] ?? [], $exts); + } +} + +// load current map +$data = file_get_contents($output = __DIR__.'/../../MimeTypes.php'); +$current = []; +$pre = ''; +$post = ''; +foreach (explode("\n", $data) as $line) { + if (!preg_match("{^ '([^']+/[^']+)' => \['(.+)'\],$}", $line, $matches)) { + if (!$current) { + $pre .= $line."\n"; + } else { + $post .= $line."\n"; + } + continue; + } + $current[$matches[1]] = explode("', '", $matches[2]); +} + +// we merge the 2 maps (we never remove old mime types) +$map = array_replace_recursive($current, $new); +ksort($map); + +$data = $pre; +foreach ($map as $mimeType => $exts) { + $data .= sprintf(" '%s' => ['%s'],\n", $mimeType, implode("', '", array_unique($exts))); +} +$data .= $post; + +// reverse map +// we prefill the extensions with some preferences for content-types +$exts = [ + 'aif' => ['audio/x-aiff'], + 'aiff' => ['audio/x-aiff'], + 'aps' => ['application/postscript'], + 'avi' => ['video/avi'], + 'bmp' => ['image/bmp'], + 'bz2' => ['application/x-bz2'], + 'css' => ['text/css'], + 'csv' => ['text/csv'], + 'dmg' => ['application/x-apple-diskimage'], + 'doc' => ['application/msword'], + 'docx' => ['application/vnd.openxmlformats-officedocument.wordprocessingml.document'], + 'eml' => ['message/rfc822'], + 'exe' => ['application/x-ms-dos-executable'], + 'flv' => ['video/x-flv'], + 'gif' => ['image/gif'], + 'gz' => ['application/x-gzip'], + 'hqx' => ['application/stuffit'], + 'htm' => ['text/html'], + 'html' => ['text/html'], + 'jar' => ['application/x-java-archive'], + 'jpeg' => ['image/jpeg'], + 'jpg' => ['image/jpeg'], + 'js' => ['text/javascript'], + 'm3u' => ['audio/x-mpegurl'], + 'm4a' => ['audio/mp4'], + 'mdb' => ['application/x-msaccess'], + 'mid' => ['audio/midi'], + 'midi' => ['audio/midi'], + 'mov' => ['video/quicktime'], + 'mp3' => ['audio/mpeg'], + 'mp4' => ['video/mp4'], + 'mpeg' => ['video/mpeg'], + 'mpg' => ['video/mpeg'], + 'ogg' => ['audio/ogg'], + 'pdf' => ['application/pdf'], + 'php' => ['application/x-php'], + 'php3' => ['application/x-php'], + 'php4' => ['application/x-php'], + 'php5' => ['application/x-php'], + 'png' => ['image/png'], + 'ppt' => ['application/vnd.ms-powerpoint'], + 'pptx' => ['application/vnd.openxmlformats-officedocument.presentationml.presentation'], + 'ps' => ['application/postscript'], + 'rar' => ['application/x-rar-compressed'], + 'rtf' => ['application/rtf'], + 'sit' => ['application/x-stuffit'], + 'svg' => ['image/svg+xml'], + 'tar' => ['application/x-tar'], + 'tif' => ['image/tiff'], + 'tiff' => ['image/tiff'], + 'ttf' => ['application/x-font-truetype'], + 'txt' => ['text/plain'], + 'vcf' => ['text/x-vcard'], + 'wav' => ['audio/wav'], + 'wma' => ['audio/x-ms-wma'], + 'wmv' => ['audio/x-ms-wmv'], + 'xls' => ['application/vnd.ms-excel'], + 'xlsx' => ['application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'], + 'xml' => ['application/xml'], + 'zip' => ['application/zip'], +]; +foreach ($map as $mimeType => $extensions) { + foreach ($extensions as $extension) { + $exts[$extension][] = $mimeType; + } +} +ksort($exts); + +$updated = ''; +$state = 0; +foreach (explode("\n", $data) as $line) { + if (!preg_match("{^ '([^'/]+)' => \['(.+)'\],$}", $line, $matches)) { + if (1 === $state) { + $state = 2; + foreach ($exts as $ext => $mimeTypes) { + $updated .= sprintf(" '%s' => ['%s'],\n", $ext, implode("', '", array_unique($mimeTypes))); + } + } + $updated .= $line."\n"; + continue; + } + $state = 1; +} + +$updated = preg_replace('{Updated from upstream on .+?\.}', 'Updated from upstream on '.date('Y-m-d'), $updated, -1); + +file_put_contents($output, rtrim($updated, "\n")."\n"); + +echo "Done.\n"; diff --git a/vendor/symfony/mime/Tests/AbstractMimeTypeGuesserTest.php b/vendor/symfony/mime/Tests/AbstractMimeTypeGuesserTest.php new file mode 100644 index 0000000000000000000000000000000000000000..3ac9382f84bc6ff2efdfb443f9420b4bf83705d9 --- /dev/null +++ b/vendor/symfony/mime/Tests/AbstractMimeTypeGuesserTest.php @@ -0,0 +1,102 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime\Tests; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Mime\MimeTypeGuesserInterface; + +abstract class AbstractMimeTypeGuesserTest extends TestCase +{ + public static function tearDownAfterClass(): void + { + $path = __DIR__.'/Fixtures/mimetypes/to_delete'; + if (file_exists($path)) { + @chmod($path, 0666); + @unlink($path); + } + } + + abstract protected function getGuesser(): MimeTypeGuesserInterface; + + public function testGuessImageWithoutExtension() + { + if (!$this->getGuesser()->isGuesserSupported()) { + $this->markTestSkipped('Guesser is not supported'); + } + + $this->assertEquals('image/gif', $this->getGuesser()->guessMimeType(__DIR__.'/Fixtures/mimetypes/test')); + } + + public function testGuessImageWithDirectory() + { + if (!$this->getGuesser()->isGuesserSupported()) { + $this->markTestSkipped('Guesser is not supported'); + } + + $this->expectException('\InvalidArgumentException'); + $this->getGuesser()->guessMimeType(__DIR__.'/Fixtures/mimetypes/directory'); + } + + public function testGuessImageWithKnownExtension() + { + if (!$this->getGuesser()->isGuesserSupported()) { + $this->markTestSkipped('Guesser is not supported'); + } + + $this->assertEquals('image/gif', $this->getGuesser()->guessMimeType(__DIR__.'/Fixtures/mimetypes/test.gif')); + } + + public function testGuessFileWithUnknownExtension() + { + if (!$this->getGuesser()->isGuesserSupported()) { + $this->markTestSkipped('Guesser is not supported'); + } + + $this->assertEquals('application/octet-stream', $this->getGuesser()->guessMimeType(__DIR__.'/Fixtures/mimetypes/.unknownextension')); + } + + public function testGuessWithIncorrectPath() + { + if (!$this->getGuesser()->isGuesserSupported()) { + $this->markTestSkipped('Guesser is not supported'); + } + + $this->expectException('\InvalidArgumentException'); + $this->getGuesser()->guessMimeType(__DIR__.'/Fixtures/mimetypes/not_here'); + } + + public function testGuessWithNonReadablePath() + { + if (!$this->getGuesser()->isGuesserSupported()) { + $this->markTestSkipped('Guesser is not supported'); + } + + if ('\\' === \DIRECTORY_SEPARATOR) { + $this->markTestSkipped('Can not verify chmod operations on Windows'); + } + + if (!getenv('USER') || 'root' === getenv('USER')) { + $this->markTestSkipped('This test will fail if run under superuser'); + } + + $path = __DIR__.'/Fixtures/mimetypes/to_delete'; + touch($path); + @chmod($path, 0333); + + if ('0333' == substr(sprintf('%o', fileperms($path)), -4)) { + $this->expectException('\InvalidArgumentException'); + $this->getGuesser()->guessMimeType($path); + } else { + $this->markTestSkipped('Can not verify chmod operations, change of file permissions failed'); + } + } +} diff --git a/vendor/symfony/mime/Tests/AddressTest.php b/vendor/symfony/mime/Tests/AddressTest.php new file mode 100644 index 0000000000000000000000000000000000000000..dd7d3cebf67caddf8bcf53ad570a468054dad9cb --- /dev/null +++ b/vendor/symfony/mime/Tests/AddressTest.php @@ -0,0 +1,61 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime\Tests; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Mime\Address; +use Symfony\Component\Mime\NamedAddress; + +class AddressTest extends TestCase +{ + public function testConstructor() + { + $a = new Address('fabien@symfonï.com'); + $this->assertEquals('fabien@symfonï.com', $a->getAddress()); + $this->assertEquals('fabien@xn--symfon-nwa.com', $a->toString()); + $this->assertEquals('fabien@xn--symfon-nwa.com', $a->getEncodedAddress()); + } + + public function testConstructorWithInvalidAddress() + { + $this->expectException(\InvalidArgumentException::class); + new Address('fab pot@symfony.com'); + } + + public function testCreate() + { + $this->assertSame($a = new Address('fabien@symfony.com'), Address::create($a)); + $this->assertSame($b = new NamedAddress('helene@symfony.com', 'Helene'), Address::create($b)); + $this->assertEquals($a, Address::create('fabien@symfony.com')); + } + + public function testCreateWrongArg() + { + $this->expectException(\InvalidArgumentException::class); + Address::create(new \stdClass()); + } + + public function testCreateArray() + { + $fabien = new Address('fabien@symfony.com'); + $helene = new NamedAddress('helene@symfony.com', 'Helene'); + $this->assertSame([$fabien, $helene], Address::createArray([$fabien, $helene])); + + $this->assertEquals([$fabien], Address::createArray(['fabien@symfony.com'])); + } + + public function testCreateArrayWrongArg() + { + $this->expectException(\InvalidArgumentException::class); + Address::createArray([new \stdClass()]); + } +} diff --git a/vendor/symfony/mime/Tests/CharacterStreamTest.php b/vendor/symfony/mime/Tests/CharacterStreamTest.php new file mode 100644 index 0000000000000000000000000000000000000000..62f4dc6fe83263d22095a42bc1730f101bba0b52 --- /dev/null +++ b/vendor/symfony/mime/Tests/CharacterStreamTest.php @@ -0,0 +1,87 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime\Tests; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Mime\CharacterStream; + +class CharacterStreamTest extends TestCase +{ + public function testReadCharactersAreInTact() + { + $stream = new CharacterStream(pack('C*', 0xD0, 0x94, 0xD0, 0xB6, 0xD0, 0xBE)); + $stream->write(pack('C*', + 0xD0, 0xBB, + 0xD1, 0x8E, + 0xD0, 0xB1, + 0xD1, 0x8B, + 0xD1, 0x85 + )); + $this->assertSame(pack('C*', 0xD0, 0x94), $stream->read(1)); + $this->assertSame(pack('C*', 0xD0, 0xB6, 0xD0, 0xBE), $stream->read(2)); + $this->assertSame(pack('C*', 0xD0, 0xBB), $stream->read(1)); + $this->assertSame(pack('C*', 0xD1, 0x8E, 0xD0, 0xB1, 0xD1, 0x8B), $stream->read(3)); + $this->assertSame(pack('C*', 0xD1, 0x85), $stream->read(1)); + $this->assertNull($stream->read(1)); + } + + public function testCharactersCanBeReadAsByteArrays() + { + $stream = new CharacterStream(pack('C*', 0xD0, 0x94, 0xD0, 0xB6, 0xD0, 0xBE)); + $stream->write(pack('C*', + 0xD0, 0xBB, + 0xD1, 0x8E, + 0xD0, 0xB1, + 0xD1, 0x8B, + 0xD1, 0x85 + )); + $this->assertEquals([0xD0, 0x94], $stream->readBytes(1)); + $this->assertEquals([0xD0, 0xB6, 0xD0, 0xBE], $stream->readBytes(2)); + $this->assertEquals([0xD0, 0xBB], $stream->readBytes(1)); + $this->assertEquals([0xD1, 0x8E, 0xD0, 0xB1, 0xD1, 0x8B], $stream->readBytes(3)); + $this->assertEquals([0xD1, 0x85], $stream->readBytes(1)); + $this->assertNull($stream->readBytes(1)); + } + + public function testRequestingLargeCharCountPastEndOfStream() + { + $stream = new CharacterStream(pack('C*', 0xD0, 0x94, 0xD0, 0xB6, 0xD0, 0xBE)); + $this->assertSame(pack('C*', 0xD0, 0x94, 0xD0, 0xB6, 0xD0, 0xBE), $stream->read(100)); + $this->assertNull($stream->read(1)); + } + + public function testRequestingByteArrayCountPastEndOfStream() + { + $stream = new CharacterStream(pack('C*', 0xD0, 0x94, 0xD0, 0xB6, 0xD0, 0xBE)); + $this->assertEquals([0xD0, 0x94, 0xD0, 0xB6, 0xD0, 0xBE], $stream->readBytes(100)); + $this->assertNull($stream->readBytes(1)); + } + + public function testPointerOffsetCanBeSet() + { + $stream = new CharacterStream(pack('C*', 0xD0, 0x94, 0xD0, 0xB6, 0xD0, 0xBE)); + $this->assertSame(pack('C*', 0xD0, 0x94), $stream->read(1)); + $stream->setPointer(0); + $this->assertSame(pack('C*', 0xD0, 0x94), $stream->read(1)); + $stream->setPointer(2); + $this->assertSame(pack('C*', 0xD0, 0xBE), $stream->read(1)); + } + + public function testAlgorithmWithFixedWidthCharsets() + { + $stream = new CharacterStream(pack('C*', 0xD1, 0x8D, 0xD0, 0xBB, 0xD0, 0xB0)); + $this->assertSame(pack('C*', 0xD1, 0x8D), $stream->read(1)); + $this->assertSame(pack('C*', 0xD0, 0xBB), $stream->read(1)); + $this->assertSame(pack('C*', 0xD0, 0xB0), $stream->read(1)); + $this->assertNull($stream->read(1)); + } +} diff --git a/vendor/symfony/mime/Tests/DependencyInjection/AddMimeTypeGuesserPassTest.php b/vendor/symfony/mime/Tests/DependencyInjection/AddMimeTypeGuesserPassTest.php new file mode 100644 index 0000000000000000000000000000000000000000..cf40a4675f117bdd5c3bf9d6c1f1fcf5c83f304e --- /dev/null +++ b/vendor/symfony/mime/Tests/DependencyInjection/AddMimeTypeGuesserPassTest.php @@ -0,0 +1,42 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime\Tests\DependencyInjection; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Definition; +use Symfony\Component\DependencyInjection\Reference; +use Symfony\Component\Mime\DependencyInjection\AddMimeTypeGuesserPass; +use Symfony\Component\Mime\FileinfoMimeTypeGuesser; +use Symfony\Component\Mime\MimeTypes; + +class AddMimeTypeGuesserPassTest extends TestCase +{ + public function testTags() + { + $container = new ContainerBuilder(); + $container->addCompilerPass(new AddMimeTypeGuesserPass()); + + $definition = new Definition(FileinfoMimeTypeGuesser::class); + $definition->addArgument('/path/to/magic/file'); + $definition->addTag('mime.mime_type_guesser'); + $container->setDefinition('some_mime_type_guesser', $definition->setPublic(true)); + $container->register('mime_types', MimeTypes::class)->setPublic(true); + $container->compile(); + + $router = $container->getDefinition('mime_types'); + $calls = $router->getMethodCalls(); + $this->assertCount(1, $calls); + $this->assertEquals('registerGuesser', $calls[0][0]); + $this->assertEquals(new Reference('some_mime_type_guesser'), $calls[0][1][0]); + } +} diff --git a/vendor/symfony/mime/Tests/EmailTest.php b/vendor/symfony/mime/Tests/EmailTest.php new file mode 100644 index 0000000000000000000000000000000000000000..764f66b079480936960d04a060337bfacc258f7b --- /dev/null +++ b/vendor/symfony/mime/Tests/EmailTest.php @@ -0,0 +1,389 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime\Tests; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Mime\Address; +use Symfony\Component\Mime\Email; +use Symfony\Component\Mime\NamedAddress; +use Symfony\Component\Mime\Part\DataPart; +use Symfony\Component\Mime\Part\Multipart\AlternativePart; +use Symfony\Component\Mime\Part\Multipart\MixedPart; +use Symfony\Component\Mime\Part\Multipart\RelatedPart; +use Symfony\Component\Mime\Part\TextPart; + +class EmailTest extends TestCase +{ + public function testSubject() + { + $e = new Email(); + $e->subject('Subject'); + $this->assertEquals('Subject', $e->getSubject()); + } + + public function testDate() + { + $e = new Email(); + $e->date($d = new \DateTimeImmutable()); + $this->assertSame($d, $e->getDate()); + } + + public function testReturnPath() + { + $e = new Email(); + $e->returnPath('fabien@symfony.com'); + $this->assertEquals(new Address('fabien@symfony.com'), $e->getReturnPath()); + } + + public function testSender() + { + $e = new Email(); + $e->sender('fabien@symfony.com'); + $this->assertEquals(new Address('fabien@symfony.com'), $e->getSender()); + + $e->sender($fabien = new Address('fabien@symfony.com')); + $this->assertSame($fabien, $e->getSender()); + } + + public function testFrom() + { + $e = new Email(); + $helene = new Address('helene@symfony.com'); + $thomas = new NamedAddress('thomas@symfony.com', 'Thomas'); + $caramel = new Address('caramel@symfony.com'); + + $this->assertSame($e, $e->from('fabien@symfony.com', $helene, $thomas)); + $v = $e->getFrom(); + $this->assertCount(3, $v); + $this->assertEquals(new Address('fabien@symfony.com'), $v[0]); + $this->assertSame($helene, $v[1]); + $this->assertSame($thomas, $v[2]); + + $this->assertSame($e, $e->addFrom('lucas@symfony.com', $caramel)); + $v = $e->getFrom(); + $this->assertCount(5, $v); + $this->assertEquals(new Address('fabien@symfony.com'), $v[0]); + $this->assertSame($helene, $v[1]); + $this->assertSame($thomas, $v[2]); + $this->assertEquals(new Address('lucas@symfony.com'), $v[3]); + $this->assertSame($caramel, $v[4]); + + $e = new Email(); + $e->addFrom('lucas@symfony.com', $caramel); + $this->assertCount(2, $e->getFrom()); + + $e = new Email(); + $e->from('lucas@symfony.com'); + $e->from($caramel); + $this->assertSame([$caramel], $e->getFrom()); + } + + public function testReplyTo() + { + $e = new Email(); + $helene = new Address('helene@symfony.com'); + $thomas = new NamedAddress('thomas@symfony.com', 'Thomas'); + $caramel = new Address('caramel@symfony.com'); + + $this->assertSame($e, $e->replyTo('fabien@symfony.com', $helene, $thomas)); + $v = $e->getReplyTo(); + $this->assertCount(3, $v); + $this->assertEquals(new Address('fabien@symfony.com'), $v[0]); + $this->assertSame($helene, $v[1]); + $this->assertSame($thomas, $v[2]); + + $this->assertSame($e, $e->addReplyTo('lucas@symfony.com', $caramel)); + $v = $e->getReplyTo(); + $this->assertCount(5, $v); + $this->assertEquals(new Address('fabien@symfony.com'), $v[0]); + $this->assertSame($helene, $v[1]); + $this->assertSame($thomas, $v[2]); + $this->assertEquals(new Address('lucas@symfony.com'), $v[3]); + $this->assertSame($caramel, $v[4]); + + $e = new Email(); + $e->addReplyTo('lucas@symfony.com', $caramel); + $this->assertCount(2, $e->getReplyTo()); + + $e = new Email(); + $e->replyTo('lucas@symfony.com'); + $e->replyTo($caramel); + $this->assertSame([$caramel], $e->getReplyTo()); + } + + public function testTo() + { + $e = new Email(); + $helene = new Address('helene@symfony.com'); + $thomas = new NamedAddress('thomas@symfony.com', 'Thomas'); + $caramel = new Address('caramel@symfony.com'); + + $this->assertSame($e, $e->to('fabien@symfony.com', $helene, $thomas)); + $v = $e->getTo(); + $this->assertCount(3, $v); + $this->assertEquals(new Address('fabien@symfony.com'), $v[0]); + $this->assertSame($helene, $v[1]); + $this->assertSame($thomas, $v[2]); + + $this->assertSame($e, $e->addTo('lucas@symfony.com', $caramel)); + $v = $e->getTo(); + $this->assertCount(5, $v); + $this->assertEquals(new Address('fabien@symfony.com'), $v[0]); + $this->assertSame($helene, $v[1]); + $this->assertSame($thomas, $v[2]); + $this->assertEquals(new Address('lucas@symfony.com'), $v[3]); + $this->assertSame($caramel, $v[4]); + + $e = new Email(); + $e->addTo('lucas@symfony.com', $caramel); + $this->assertCount(2, $e->getTo()); + + $e = new Email(); + $e->to('lucas@symfony.com'); + $e->to($caramel); + $this->assertSame([$caramel], $e->getTo()); + } + + public function testCc() + { + $e = new Email(); + $helene = new Address('helene@symfony.com'); + $thomas = new NamedAddress('thomas@symfony.com', 'Thomas'); + $caramel = new Address('caramel@symfony.com'); + + $this->assertSame($e, $e->cc('fabien@symfony.com', $helene, $thomas)); + $v = $e->getCc(); + $this->assertCount(3, $v); + $this->assertEquals(new Address('fabien@symfony.com'), $v[0]); + $this->assertSame($helene, $v[1]); + $this->assertSame($thomas, $v[2]); + + $this->assertSame($e, $e->addCc('lucas@symfony.com', $caramel)); + $v = $e->getCc(); + $this->assertCount(5, $v); + $this->assertEquals(new Address('fabien@symfony.com'), $v[0]); + $this->assertSame($helene, $v[1]); + $this->assertSame($thomas, $v[2]); + $this->assertEquals(new Address('lucas@symfony.com'), $v[3]); + $this->assertSame($caramel, $v[4]); + + $e = new Email(); + $e->addCc('lucas@symfony.com', $caramel); + $this->assertCount(2, $e->getCc()); + + $e = new Email(); + $e->cc('lucas@symfony.com'); + $e->cc($caramel); + $this->assertSame([$caramel], $e->getCc()); + } + + public function testBcc() + { + $e = new Email(); + $helene = new Address('helene@symfony.com'); + $thomas = new NamedAddress('thomas@symfony.com', 'Thomas'); + $caramel = new Address('caramel@symfony.com'); + + $this->assertSame($e, $e->bcc('fabien@symfony.com', $helene, $thomas)); + $v = $e->getBcc(); + $this->assertCount(3, $v); + $this->assertEquals(new Address('fabien@symfony.com'), $v[0]); + $this->assertSame($helene, $v[1]); + $this->assertSame($thomas, $v[2]); + + $this->assertSame($e, $e->addBcc('lucas@symfony.com', $caramel)); + $v = $e->getBcc(); + $this->assertCount(5, $v); + $this->assertEquals(new Address('fabien@symfony.com'), $v[0]); + $this->assertSame($helene, $v[1]); + $this->assertSame($thomas, $v[2]); + $this->assertEquals(new Address('lucas@symfony.com'), $v[3]); + $this->assertSame($caramel, $v[4]); + + $e = new Email(); + $e->addBcc('lucas@symfony.com', $caramel); + $this->assertCount(2, $e->getBcc()); + + $e = new Email(); + $e->bcc('lucas@symfony.com'); + $e->bcc($caramel); + $this->assertSame([$caramel], $e->getBcc()); + } + + public function testPriority() + { + $e = new Email(); + $this->assertEquals(3, $e->getPriority()); + + $e->priority(1); + $this->assertEquals(1, $e->getPriority()); + $e->priority(10); + $this->assertEquals(5, $e->getPriority()); + $e->priority(-10); + $this->assertEquals(1, $e->getPriority()); + } + + public function testGenerateBodyThrowsWhenEmptyBody() + { + $this->expectException(\LogicException::class); + (new Email())->getBody(); + } + + public function testGetBody() + { + $e = new Email(); + $e->setBody($text = new TextPart('text content')); + $this->assertEquals($text, $e->getBody()); + } + + public function testGenerateBody() + { + $text = new TextPart('text content'); + $html = new TextPart('html content', 'utf-8', 'html'); + $att = new DataPart($file = fopen(__DIR__.'/Fixtures/mimetypes/test', 'r')); + $img = new DataPart($image = fopen(__DIR__.'/Fixtures/mimetypes/test.gif', 'r'), 'test.gif'); + + $e = new Email(); + $e->text('text content'); + $this->assertEquals($text, $e->getBody()); + $this->assertEquals('text content', $e->getTextBody()); + + $e = new Email(); + $e->html('html content'); + $this->assertEquals($html, $e->getBody()); + $this->assertEquals('html content', $e->getHtmlBody()); + + $e = new Email(); + $e->html('html content'); + $e->text('text content'); + $this->assertEquals(new AlternativePart($text, $html), $e->getBody()); + + $e = new Email(); + $e->html('html content', 'iso-8859-1'); + $e->text('text content', 'iso-8859-1'); + $this->assertEquals('iso-8859-1', $e->getTextCharset()); + $this->assertEquals('iso-8859-1', $e->getHtmlCharset()); + $this->assertEquals(new AlternativePart(new TextPart('text content', 'iso-8859-1'), new TextPart('html content', 'iso-8859-1', 'html')), $e->getBody()); + + $e = new Email(); + $e->attach($file); + $e->text('text content'); + $this->assertEquals(new MixedPart($text, $att), $e->getBody()); + + $e = new Email(); + $e->attach($file); + $e->html('html content'); + $this->assertEquals(new MixedPart($html, $att), $e->getBody()); + + $e = new Email(); + $e->attach($file); + $this->assertEquals(new MixedPart($att), $e->getBody()); + + $e = new Email(); + $e->html('html content'); + $e->text('text content'); + $e->attach($file); + $this->assertEquals(new MixedPart(new AlternativePart($text, $html), $att), $e->getBody()); + + $e = new Email(); + $e->html('html content'); + $e->text('text content'); + $e->attach($file); + $e->attach($image, 'test.gif'); + $this->assertEquals(new MixedPart(new AlternativePart($text, $html), $att, $img), $e->getBody()); + + $e = new Email(); + $e->text('text content'); + $e->attach($file); + $e->attach($image, 'test.gif'); + $this->assertEquals(new MixedPart($text, $att, $img), $e->getBody()); + + $e = new Email(); + $e->html($content = 'html content <img src="test.gif">'); + $e->text('text content'); + $e->attach($file); + $e->attach($image, 'test.gif'); + $fullhtml = new TextPart($content, 'utf-8', 'html'); + $this->assertEquals(new MixedPart(new AlternativePart($text, $fullhtml), $att, $img), $e->getBody()); + + $e = new Email(); + $e->html($content = 'html content <img src="cid:test.gif">'); + $e->text('text content'); + $e->attach($file); + $e->attach($image, 'test.gif'); + $fullhtml = new TextPart($content, 'utf-8', 'html'); + $inlinedimg = (new DataPart($image, 'test.gif'))->asInline(); + $body = $e->getBody(); + $this->assertInstanceOf(MixedPart::class, $body); + $this->assertCount(2, $related = $body->getParts()); + $this->assertInstanceOf(RelatedPart::class, $related[0]); + $this->assertEquals($att, $related[1]); + $this->assertCount(2, $parts = $related[0]->getParts()); + $this->assertInstanceOf(AlternativePart::class, $parts[0]); + $generatedHtml = $parts[0]->getParts()[1]; + $this->assertStringContainsString('cid:'.$parts[1]->getContentId(), $generatedHtml->getBody()); + + $content = 'html content <img src="cid:test.gif">'; + $r = fopen('php://memory', 'r+', false); + fwrite($r, $content); + rewind($r); + + $e = new Email(); + $e->html($r); + // embedding the same image twice results in one image only in the email + $e->embed($image, 'test.gif'); + $e->embed($image, 'test.gif'); + $body = $e->getBody(); + $this->assertInstanceOf(RelatedPart::class, $body); + // 2 parts only, not 3 (text + embedded image once) + $this->assertCount(2, $parts = $body->getParts()); + $this->assertStringMatchesFormat('html content <img src=3D"cid:%s@symfony">', $parts[0]->bodyToString()); + } + + public function testAttachments() + { + $contents = file_get_contents($name = __DIR__.'/Fixtures/mimetypes/test', 'r'); + $att = new DataPart($file = fopen($name, 'r'), 'test'); + $inline = (new DataPart($contents, 'test'))->asInline(); + $e = new Email(); + $e->attach($file, 'test'); + $e->embed($contents, 'test'); + $this->assertEquals([$att, $inline], $e->getAttachments()); + + $att = DataPart::fromPath($name, 'test'); + $inline = DataPart::fromPath($name, 'test')->asInline(); + $e = new Email(); + $e->attachFromPath($name); + $e->embedFromPath($name); + $this->assertEquals([$att->bodyToString(), $inline->bodyToString()], array_map(function (DataPart $a) { return $a->bodyToString(); }, $e->getAttachments())); + $this->assertEquals([$att->getPreparedHeaders(), $inline->getPreparedHeaders()], array_map(function (DataPart $a) { return $a->getPreparedHeaders(); }, $e->getAttachments())); + } + + public function testSerialize() + { + $r = fopen('php://memory', 'r+', false); + fwrite($r, 'Text content'); + rewind($r); + + $e = new Email(); + $e->from('fabien@symfony.com'); + $e->text($r); + $e->html($r); + $contents = file_get_contents($name = __DIR__.'/Fixtures/mimetypes/test', 'r'); + $file = fopen($name, 'r'); + $e->attach($file, 'test'); + $expected = clone $e; + $n = unserialize(serialize($e)); + $this->assertEquals($expected->getHeaders(), $n->getHeaders()); + $this->assertEquals($e->getBody(), $n->getBody()); + } +} diff --git a/vendor/symfony/mime/Tests/Encoder/Base64EncoderTest.php b/vendor/symfony/mime/Tests/Encoder/Base64EncoderTest.php new file mode 100644 index 0000000000000000000000000000000000000000..a90fbb70fcbdbf43b70d7aacf0b615bb95f092dc --- /dev/null +++ b/vendor/symfony/mime/Tests/Encoder/Base64EncoderTest.php @@ -0,0 +1,158 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime\Tests\Encoder; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Mime\Encoder\Base64Encoder; + +class Base64EncoderTest extends TestCase +{ + /* + There's really no point in testing the entire base64 encoding to the + level QP encoding has been tested. base64_encode() has been in PHP for + years. + */ + + public function testInputOutputRatioIs3to4Bytes() + { + /* + RFC 2045, 6.8 + + The encoding process represents 24-bit groups of input bits as output + strings of 4 encoded characters. Proceeding from left to right, a + 24-bit input group is formed by concatenating 3 8bit input groups. + These 24 bits are then treated as 4 concatenated 6-bit groups, each + of which is translated into a single digit in the base64 alphabet. + */ + + $encoder = new Base64Encoder(); + $this->assertEquals('MTIz', $encoder->encodeString('123'), '3 bytes of input should yield 4 bytes of output'); + $this->assertEquals('MTIzNDU2', $encoder->encodeString('123456'), '6 bytes in input should yield 8 bytes of output'); + $this->assertEquals('MTIzNDU2Nzg5', $encoder->encodeString('123456789'), '%s: 9 bytes in input should yield 12 bytes of output'); + } + + public function testPadLength() + { + /* + RFC 2045, 6.8 + + Special processing is performed if fewer than 24 bits are available + at the end of the data being encoded. A full encoding quantum is + always completed at the end of a body. When fewer than 24 input bits + are available in an input group, zero bits are added (on the right) + to form an integral number of 6-bit groups. Padding at the end of + the data is performed using the "=" character. Since all base64 + input is an integral number of octets, only the following cases can + arise: (1) the final quantum of encoding input is an integral + multiple of 24 bits; here, the final unit of encoded output will be + an integral multiple of 4 characters with no "=" padding, (2) the + final quantum of encoding input is exactly 8 bits; here, the final + unit of encoded output will be two characters followed by two "=" + padding characters, or (3) the final quantum of encoding input is + exactly 16 bits; here, the final unit of encoded output will be three + characters followed by one "=" padding character. + */ + + $encoder = new Base64Encoder(); + for ($i = 0; $i < 30; ++$i) { + $input = pack('C', random_int(0, 255)); + $this->assertRegExp('~^[a-zA-Z0-9/\+]{2}==$~', $encoder->encodeString($input), 'A single byte should have 2 bytes of padding'); + } + + for ($i = 0; $i < 30; ++$i) { + $input = pack('C*', random_int(0, 255), random_int(0, 255)); + $this->assertRegExp('~^[a-zA-Z0-9/\+]{3}=$~', $encoder->encodeString($input), 'Two bytes should have 1 byte of padding'); + } + + for ($i = 0; $i < 30; ++$i) { + $input = pack('C*', random_int(0, 255), random_int(0, 255), random_int(0, 255)); + $this->assertRegExp('~^[a-zA-Z0-9/\+]{4}$~', $encoder->encodeString($input), 'Three bytes should have no padding'); + } + } + + public function testMaximumLineLengthIs76Characters() + { + /* + The encoded output stream must be represented in lines of no more + than 76 characters each. All line breaks or other characters not + found in Table 1 must be ignored by decoding software. + */ + + $input = + 'abcdefghijklmnopqrstuvwxyz'. + 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'. + '1234567890'. + 'abcdefghijklmnopqrstuvwxyz'. + 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'. + '1234567890'. + 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'; + + $output = + 'YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXpBQk'.//38 + 'NERUZHSElKS0xNTk9QUVJTVFVWV1hZWjEyMzQ1'."\r\n".//76 * + 'Njc4OTBhYmNkZWZnaGlqa2xtbm9wcXJzdHV2d3'.//38 + 'h5ekFCQ0RFRkdISUpLTE1OT1BRUlNUVVZXWFla'."\r\n".//76 * + 'MTIzNDU2Nzg5MEFCQ0RFRkdISUpLTE1OT1BRUl'.//38 + 'NUVVZXWFla'; //48 + + $encoder = new Base64Encoder(); + $this->assertEquals($output, $encoder->encodeString($input), 'Lines should be no more than 76 characters'); + } + + public function testMaximumLineLengthCanBeSpecified() + { + $input = + 'abcdefghijklmnopqrstuvwxyz'. + 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'. + '1234567890'. + 'abcdefghijklmnopqrstuvwxyz'. + 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'. + '1234567890'. + 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'; + + $output = + 'YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXpBQk'.//38 + 'NERUZHSElKS0'."\r\n".//50 * + 'xNTk9QUVJTVFVWV1hZWjEyMzQ1Njc4OTBhYmNk'.//38 + 'ZWZnaGlqa2xt'."\r\n".//50 * + 'bm9wcXJzdHV2d3h5ekFCQ0RFRkdISUpLTE1OT1'.//38 + 'BRUlNUVVZXWF'."\r\n".//50 * + 'laMTIzNDU2Nzg5MEFCQ0RFRkdISUpLTE1OT1BR'.//38 + 'UlNUVVZXWFla'; //50 * + + $encoder = new Base64Encoder(); + $this->assertEquals($output, $encoder->encodeString($input, 'utf-8', 0, 50), 'Lines should be no more than 100 characters'); + } + + public function testFirstLineLengthCanBeDifferent() + { + $input = + 'abcdefghijklmnopqrstuvwxyz'. + 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'. + '1234567890'. + 'abcdefghijklmnopqrstuvwxyz'. + 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'. + '1234567890'. + 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'; + + $output = + 'YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXpBQk'.//38 + 'NERUZHSElKS0xNTk9QU'."\r\n".//57 * + 'VJTVFVWV1hZWjEyMzQ1Njc4OTBhYmNkZWZnaGl'.//38 + 'qa2xtbm9wcXJzdHV2d3h5ekFCQ0RFRkdISUpLT'."\r\n".//76 * + 'E1OT1BRUlNUVVZXWFlaMTIzNDU2Nzg5MEFCQ0R'.//38 + 'FRkdISUpLTE1OT1BRUlNUVVZXWFla'; //67 + + $encoder = new Base64Encoder(); + $this->assertEquals($output, $encoder->encodeString($input, 'utf-8', 19), 'First line offset is 19 so first line should be 57 chars long'); + } +} diff --git a/vendor/symfony/mime/Tests/Encoder/Base64MimeHeaderEncoderTest.php b/vendor/symfony/mime/Tests/Encoder/Base64MimeHeaderEncoderTest.php new file mode 100644 index 0000000000000000000000000000000000000000..34bfe0d47c96099508d1135d285e0b6644053761 --- /dev/null +++ b/vendor/symfony/mime/Tests/Encoder/Base64MimeHeaderEncoderTest.php @@ -0,0 +1,23 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime\Tests\Encoder; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Mime\Encoder\Base64MimeHeaderEncoder; + +class Base64MimeHeaderEncoderTest extends TestCase +{ + public function testNameIsB() + { + $this->assertEquals('B', (new Base64MimeHeaderEncoder())->getName()); + } +} diff --git a/vendor/symfony/mime/Tests/Encoder/QpEncoderTest.php b/vendor/symfony/mime/Tests/Encoder/QpEncoderTest.php new file mode 100644 index 0000000000000000000000000000000000000000..bf08b2f095573eb96960d505be4fb388e1872495 --- /dev/null +++ b/vendor/symfony/mime/Tests/Encoder/QpEncoderTest.php @@ -0,0 +1,213 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime\Tests\Encoder; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Mime\Encoder\QpEncoder; + +class QpEncoderTest extends TestCase +{ + /* -- RFC 2045, 6.7 -- + (1) (General 8bit representation) Any octet, except a CR or + LF that is part of a CRLF line break of the canonical + (standard) form of the data being encoded, may be + represented by an "=" followed by a two digit + hexadecimal representation of the octet's value. The + digits of the hexadecimal alphabet, for this purpose, + are "0123456789ABCDEF". Uppercase letters must be + used; lowercase letters are not allowed. Thus, for + example, the decimal value 12 (US-ASCII form feed) can + be represented by "=0C", and the decimal value 61 (US- + ASCII EQUAL SIGN) can be represented by "=3D". This + rule must be followed except when the following rules + allow an alternative encoding. + */ + + public function testPermittedCharactersAreNotEncoded() + { + /* -- RFC 2045, 6.7 -- + (2) (Literal representation) Octets with decimal values of + 33 through 60 inclusive, and 62 through 126, inclusive, + MAY be represented as the US-ASCII characters which + correspond to those octets (EXCLAMATION POINT through + LESS THAN, and GREATER THAN through TILDE, + respectively). + */ + + $encoder = new QpEncoder(); + foreach (array_merge(range(33, 60), range(62, 126)) as $ordinal) { + $char = \chr($ordinal); + $this->assertSame($char, $encoder->encodeString($char)); + } + } + + public function testWhiteSpaceAtLineEndingIsEncoded() + { + /* -- RFC 2045, 6.7 -- + (3) (White Space) Octets with values of 9 and 32 MAY be + represented as US-ASCII TAB (HT) and SPACE characters, + respectively, but MUST NOT be so represented at the end + of an encoded line. Any TAB (HT) or SPACE characters + on an encoded line MUST thus be followed on that line + by a printable character. In particular, an "=" at the + end of an encoded line, indicating a soft line break + (see rule #5) may follow one or more TAB (HT) or SPACE + characters. It follows that an octet with decimal + value 9 or 32 appearing at the end of an encoded line + must be represented according to Rule #1. This rule is + necessary because some MTAs (Message Transport Agents, + programs which transport messages from one user to + another, or perform a portion of such transfers) are + known to pad lines of text with SPACEs, and others are + known to remove "white space" characters from the end + of a line. Therefore, when decoding a Quoted-Printable + body, any trailing white space on a line must be + deleted, as it will necessarily have been added by + intermediate transport agents. + */ + + $encoder = new QpEncoder(); + + $HT = \chr(0x09); // 9 + $SPACE = \chr(0x20); // 32 + + // HT + $string = 'a'.$HT.$HT."\r\n".'b'; + $this->assertEquals('a'.$HT.'=09'."\r\n".'b', $encoder->encodeString($string)); + + // SPACE + $string = 'a'.$SPACE.$SPACE."\r\n".'b'; + $this->assertEquals('a'.$SPACE.'=20'."\r\n".'b', $encoder->encodeString($string)); + } + + public function testCRLFIsLeftAlone() + { + /* + (4) (Line Breaks) A line break in a text body, represented + as a CRLF sequence in the text canonical form, must be + represented by a (RFC 822) line break, which is also a + CRLF sequence, in the Quoted-Printable encoding. Since + the canonical representation of media types other than + text do not generally include the representation of + line breaks as CRLF sequences, no hard line breaks + (i.e. line breaks that are intended to be meaningful + and to be displayed to the user) can occur in the + quoted-printable encoding of such types. Sequences + like "=0D", "=0A", "=0A=0D" and "=0D=0A" will routinely + appear in non-text data represented in quoted- + printable, of course. + + Note that many implementations may elect to encode the + local representation of various content types directly + rather than converting to canonical form first, + encoding, and then converting back to local + representation. In particular, this may apply to plain + text material on systems that use newline conventions + other than a CRLF terminator sequence. Such an + implementation optimization is permissible, but only + when the combined canonicalization-encoding step is + equivalent to performing the three steps separately. + */ + + $encoder = new QpEncoder(); + $string = 'a'."\r\n".'b'."\r\n".'c'."\r\n"; + $this->assertEquals($string, $encoder->encodeString($string)); + } + + public function testLinesLongerThan76CharactersAreSoftBroken() + { + /* + (5) (Soft Line Breaks) The Quoted-Printable encoding + REQUIRES that encoded lines be no more than 76 + characters long. If longer lines are to be encoded + with the Quoted-Printable encoding, "soft" line breaks + must be used. An equal sign as the last character on a + encoded line indicates such a non-significant ("soft") + line break in the encoded text. + */ + + $encoder = new QpEncoder(); + $input = str_repeat('a', 140); + $output = ''; + for ($i = 0; $i < 140; ++$i) { + // we read 4 chars at a time (max is 75) + if (18 * 4 /* 72 */ == $i) { + $output .= "=\r\n"; + } + $output .= 'a'; + } + $this->assertEquals($output, $encoder->encodeString($input)); + } + + public function testMaxLineLengthCanBeSpecified() + { + $encoder = new QpEncoder(); + $input = str_repeat('a', 100); + $output = ''; + for ($i = 0; $i < 100; ++$i) { + // we read 4 chars at a time (max is 53) + if (13 * 4 /* 52 */ == $i) { + $output .= "=\r\n"; + } + $output .= 'a'; + } + $this->assertEquals($output, $encoder->encodeString($input, 'utf-8', 0, 54)); + } + + public function testBytesBelowPermittedRangeAreEncoded() + { + // According to Rule (1 & 2) + $encoder = new QpEncoder(); + foreach (range(0, 32) as $ordinal) { + $char = \chr($ordinal); + $this->assertEquals(sprintf('=%02X', $ordinal), $encoder->encodeString($char)); + } + } + + public function testDecimalByte61IsEncoded() + { + // According to Rule (1 & 2) + $encoder = new QpEncoder(); + $this->assertEquals('=3D', $encoder->encodeString('=')); + } + + public function testBytesAbovePermittedRangeAreEncoded() + { + // According to Rule (1 & 2) + $encoder = new QpEncoder(); + foreach (range(127, 255) as $ordinal) { + $this->assertSame(sprintf('=%02X', $ordinal), $encoder->encodeString(\chr($ordinal), 'iso-8859-1')); + } + } + + public function testFirstLineLengthCanBeDifferent() + { + $encoder = new QpEncoder(); + $input = str_repeat('a', 140); + $output = ''; + for ($i = 0; $i < 140; ++$i) { + // we read 4 chars at a time (max is 54 for the first line and 75 for the second one) + if (13 * 4 == $i || 13 * 4 + 18 * 4 == $i) { + $output .= "=\r\n"; + } + $output .= 'a'; + } + $this->assertEquals($output, $encoder->encodeString($input, 'utf-8', 22), 'First line should start at offset 22 so can only have max length 54'); + } + + public function testTextIsPreWrapped() + { + $encoder = new QpEncoder(); + $input = str_repeat('a', 70)."\r\n".str_repeat('a', 70)."\r\n".str_repeat('a', 70); + $this->assertEquals($input, $encoder->encodeString($input)); + } +} diff --git a/vendor/symfony/mime/Tests/Encoder/QpMimeHeaderEncoderTest.php b/vendor/symfony/mime/Tests/Encoder/QpMimeHeaderEncoderTest.php new file mode 100644 index 0000000000000000000000000000000000000000..f075452cbb1d4ed9e4a76d0754a4d532dc55e5be --- /dev/null +++ b/vendor/symfony/mime/Tests/Encoder/QpMimeHeaderEncoderTest.php @@ -0,0 +1,139 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime\Tests\Encoder; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Mime\Encoder\QpMimeHeaderEncoder; + +class QpMimeHeaderEncoderTest extends TestCase +{ + public function testNameIsQ() + { + $encoder = new QpMimeHeaderEncoder(); + $this->assertEquals('Q', $encoder->getName()); + } + + public function testSpaceAndTabNeverAppear() + { + /* -- RFC 2047, 4. + Only a subset of the printable ASCII characters may be used in + 'encoded-text'. Space and tab characters are not allowed, so that + the beginning and end of an 'encoded-word' are obvious. + */ + + $encoder = new QpMimeHeaderEncoder(); + $this->assertNotRegExp('~[ \t]~', $encoder->encodeString("a \t b"), 'encoded-words in headers cannot contain LWSP as per RFC 2047.'); + } + + public function testSpaceIsRepresentedByUnderscore() + { + /* -- RFC 2047, 4.2. + (2) The 8-bit hexadecimal value 20 (e.g., ISO-8859-1 SPACE) may be + represented as "_" (underscore, ASCII 95.). (This character may + not pass through some internetwork mail gateways, but its use + will greatly enhance readability of "Q" encoded data with mail + readers that do not support this encoding.) Note that the "_" + always represents hexadecimal 20, even if the SPACE character + occupies a different code position in the character set in use. + */ + $encoder = new QpMimeHeaderEncoder(); + $this->assertEquals('a_b', $encoder->encodeString('a b'), 'Spaces can be represented by more readable underscores as per RFC 2047.'); + } + + public function testEqualsAndQuestionAndUnderscoreAreEncoded() + { + /* -- RFC 2047, 4.2. + (3) 8-bit values which correspond to printable ASCII characters other + than "=", "?", and "_" (underscore), MAY be represented as those + characters. (But see section 5 for restrictions.) In + particular, SPACE and TAB MUST NOT be represented as themselves + within encoded words. + */ + $encoder = new QpMimeHeaderEncoder(); + $this->assertEquals('=3D=3F=5F', $encoder->encodeString('=?_'), 'Chars =, ? and _ (underscore) may not appear as per RFC 2047.'); + } + + public function testParensAndQuotesAreEncoded() + { + /* -- RFC 2047, 5 (2). + A "Q"-encoded 'encoded-word' which appears in a 'comment' MUST NOT + contain the characters "(", ")" or " + */ + + $encoder = new QpMimeHeaderEncoder(); + $this->assertEquals('=28=22=29', $encoder->encodeString('(")'), 'Chars (, " (DQUOTE) and ) may not appear as per RFC 2047.'); + } + + public function testOnlyCharactersAllowedInPhrasesAreUsed() + { + /* -- RFC 2047, 5. + (3) As a replacement for a 'word' entity within a 'phrase', for example, + one that precedes an address in a From, To, or Cc header. The ABNF + definition for 'phrase' from RFC 822 thus becomes: + + phrase = 1*( encoded-word / word ) + + In this case the set of characters that may be used in a "Q"-encoded + 'encoded-word' is restricted to: <upper and lower case ASCII + letters, decimal digits, "!", "*", "+", "-", "/", "=", and "_" + (underscore, ASCII 95.)>. An 'encoded-word' that appears within a + 'phrase' MUST be separated from any adjacent 'word', 'text' or + 'special' by 'linear-white-space'. + */ + + $allowedBytes = array_merge( + range(\ord('a'), \ord('z')), range(\ord('A'), \ord('Z')), + range(\ord('0'), \ord('9')), + [\ord('!'), \ord('*'), \ord('+'), \ord('-'), \ord('/')] + ); + $encoder = new QpMimeHeaderEncoder(); + foreach (range(0x00, 0xFF) as $byte) { + $char = pack('C', $byte); + $encodedChar = $encoder->encodeString($char, 'iso-8859-1'); + if (\in_array($byte, $allowedBytes)) { + $this->assertEquals($char, $encodedChar, 'Character '.$char.' should not be encoded.'); + } elseif (0x20 == $byte) { + // special case + $this->assertEquals('_', $encodedChar, 'Space character should be replaced.'); + } else { + $this->assertEquals(sprintf('=%02X', $byte), $encodedChar, 'Byte '.$byte.' should be encoded.'); + } + } + } + + public function testEqualsNeverAppearsAtEndOfLine() + { + /* -- RFC 2047, 5 (3). + The 'encoded-text' in an 'encoded-word' must be self-contained; + 'encoded-text' MUST NOT be continued from one 'encoded-word' to + another. This implies that the 'encoded-text' portion of a "B" + 'encoded-word' will be a multiple of 4 characters long; for a "Q" + 'encoded-word', any "=" character that appears in the 'encoded-text' + portion will be followed by two hexadecimal characters. + */ + + $input = str_repeat('a', 140); + + $output = ''; + $seq = 0; + for (; $seq < 140; ++$seq) { + // compute the end of line (multiple of 4 chars) + if (18 * 4 === $seq) { + $output .= "\r\n"; // =\r\n + } + $output .= 'a'; + } + + $encoder = new QpMimeHeaderEncoder(); + $this->assertEquals($output, $encoder->encodeString($input)); + } +} diff --git a/vendor/symfony/mime/Tests/Encoder/Rfc2231EncoderTest.php b/vendor/symfony/mime/Tests/Encoder/Rfc2231EncoderTest.php new file mode 100644 index 0000000000000000000000000000000000000000..edcb15fcec371133896f740d0068aa73666d3ddc --- /dev/null +++ b/vendor/symfony/mime/Tests/Encoder/Rfc2231EncoderTest.php @@ -0,0 +1,129 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime\Tests\Encoder; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Mime\Encoder\Rfc2231Encoder; + +class Rfc2231EncoderTest extends TestCase +{ + private $rfc2045Token = '/^[\x21\x23-\x27\x2A\x2B\x2D\x2E\x30-\x39\x41-\x5A\x5E-\x7E]+$/D'; + + /* -- + This algorithm is described in RFC 2231, but is barely touched upon except + for mentioning bytes can be represented as their octet values (e.g. %20 for + the SPACE character). + + The tests here focus on how to use that representation to always generate text + which matches RFC 2045's definition of "token". + */ + + public function testEncodingAsciiCharactersProducesValidToken() + { + $string = ''; + foreach (range(0x00, 0x7F) as $octet) { + $char = pack('C', $octet); + $string .= $char; + } + $encoder = new Rfc2231Encoder(); + $encoded = $encoder->encodeString($string); + + foreach (explode("\r\n", $encoded) as $line) { + $this->assertRegExp($this->rfc2045Token, $line, 'Encoder should always return a valid RFC 2045 token.'); + } + } + + public function testEncodingNonAsciiCharactersProducesValidToken() + { + $string = ''; + foreach (range(0x80, 0xFF) as $octet) { + $char = pack('C', $octet); + $string .= $char; + } + $encoder = new Rfc2231Encoder(); + $encoded = $encoder->encodeString($string); + + foreach (explode("\r\n", $encoded) as $line) { + $this->assertRegExp($this->rfc2045Token, $line, 'Encoder should always return a valid RFC 2045 token.'); + } + } + + public function testMaximumLineLengthCanBeSet() + { + $string = ''; + for ($x = 0; $x < 200; ++$x) { + $char = 'a'; + $string .= $char; + } + $encoder = new Rfc2231Encoder(); + $encoded = $encoder->encodeString($string, 'utf-8', 0, 75); + + // 72 here and not 75 as we read 4 chars at a time + $this->assertEquals( + str_repeat('a', 72)."\r\n". + str_repeat('a', 72)."\r\n". + str_repeat('a', 56), + $encoded, + 'Lines should be wrapped at each 72 characters' + ); + } + + public function testFirstLineCanHaveShorterLength() + { + $string = ''; + for ($x = 0; $x < 200; ++$x) { + $char = 'a'; + $string .= $char; + } + $encoder = new Rfc2231Encoder(); + $encoded = $encoder->encodeString($string, 'utf-8', 24, 72); + + $this->assertEquals( + str_repeat('a', 48)."\r\n". + str_repeat('a', 72)."\r\n". + str_repeat('a', 72)."\r\n". + str_repeat('a', 8), + $encoded, + 'First line should be 24 bytes shorter than the others.' + ); + } + + public function testEncodingAndDecodingSamples() + { + $dir = realpath(__DIR__.'/../Fixtures/samples/charsets'); + $sampleFp = opendir($dir); + while (false !== $encoding = readdir($sampleFp)) { + if ('.' == substr($encoding, 0, 1)) { + continue; + } + + $encoder = new Rfc2231Encoder(); + if (is_dir($dir.'/'.$encoding)) { + $fileFp = opendir($dir.'/'.$encoding); + while (false !== $sampleFile = readdir($fileFp)) { + if ('.' == substr($sampleFile, 0, 1)) { + continue; + } + + $text = file_get_contents($dir.'/'.$encoding.'/'.$sampleFile); + $encodedText = $encoder->encodeString($text, $encoding); + $this->assertEquals( + urldecode(implode('', explode("\r\n", $encodedText))), $text, + 'Encoded string should decode back to original string for sample '.$dir.'/'.$encoding.'/'.$sampleFile + ); + } + closedir($fileFp); + } + } + closedir($sampleFp); + } +} diff --git a/vendor/symfony/mime/Tests/FileBinaryMimeTypeGuesserTest.php b/vendor/symfony/mime/Tests/FileBinaryMimeTypeGuesserTest.php new file mode 100644 index 0000000000000000000000000000000000000000..0742732895e524cb7d1db39364ae417e8377e71a --- /dev/null +++ b/vendor/symfony/mime/Tests/FileBinaryMimeTypeGuesserTest.php @@ -0,0 +1,23 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime\Tests; + +use Symfony\Component\Mime\FileBinaryMimeTypeGuesser; +use Symfony\Component\Mime\MimeTypeGuesserInterface; + +class FileBinaryMimeTypeGuesserTest extends AbstractMimeTypeGuesserTest +{ + protected function getGuesser(): MimeTypeGuesserInterface + { + return new FileBinaryMimeTypeGuesser(); + } +} diff --git a/vendor/symfony/mime/Tests/FileinfoMimeTypeGuesserTest.php b/vendor/symfony/mime/Tests/FileinfoMimeTypeGuesserTest.php new file mode 100644 index 0000000000000000000000000000000000000000..d2e6930a4b9c383d95ac759c1de5105c170b3988 --- /dev/null +++ b/vendor/symfony/mime/Tests/FileinfoMimeTypeGuesserTest.php @@ -0,0 +1,26 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime\Tests; + +use Symfony\Component\Mime\FileinfoMimeTypeGuesser; +use Symfony\Component\Mime\MimeTypeGuesserInterface; + +/** + * @requires extension fileinfo + */ +class FileinfoMimeTypeGuesserTest extends AbstractMimeTypeGuesserTest +{ + protected function getGuesser(): MimeTypeGuesserInterface + { + return new FileinfoMimeTypeGuesser(); + } +} diff --git a/vendor/symfony/mime/Tests/Fixtures/mimetypes/.unknownextension b/vendor/symfony/mime/Tests/Fixtures/mimetypes/.unknownextension new file mode 100644 index 0000000000000000000000000000000000000000..4d1ae35ba2c8ec712fa2a379db44ad639ca277bd --- /dev/null +++ b/vendor/symfony/mime/Tests/Fixtures/mimetypes/.unknownextension @@ -0,0 +1 @@ +f \ No newline at end of file diff --git a/vendor/symfony/http-kernel/Tests/Fixtures/BaseBundle/Resources/hide.txt b/vendor/symfony/mime/Tests/Fixtures/mimetypes/directory/.empty similarity index 100% rename from vendor/symfony/http-kernel/Tests/Fixtures/BaseBundle/Resources/hide.txt rename to vendor/symfony/mime/Tests/Fixtures/mimetypes/directory/.empty diff --git a/vendor/symfony/http-kernel/Tests/Fixtures/Bundle1Bundle/Resources/foo.txt b/vendor/symfony/mime/Tests/Fixtures/mimetypes/other-file.example similarity index 100% rename from vendor/symfony/http-kernel/Tests/Fixtures/Bundle1Bundle/Resources/foo.txt rename to vendor/symfony/mime/Tests/Fixtures/mimetypes/other-file.example diff --git a/vendor/symfony/mime/Tests/Fixtures/mimetypes/test b/vendor/symfony/mime/Tests/Fixtures/mimetypes/test new file mode 100644 index 0000000000000000000000000000000000000000..b636f4b8df536b0a85e7cea1a6cf3f0bd3179b96 Binary files /dev/null and b/vendor/symfony/mime/Tests/Fixtures/mimetypes/test differ diff --git a/vendor/symfony/mime/Tests/Fixtures/mimetypes/test.gif b/vendor/symfony/mime/Tests/Fixtures/mimetypes/test.gif new file mode 100644 index 0000000000000000000000000000000000000000..b636f4b8df536b0a85e7cea1a6cf3f0bd3179b96 Binary files /dev/null and b/vendor/symfony/mime/Tests/Fixtures/mimetypes/test.gif differ diff --git a/vendor/symfony/mime/Tests/Fixtures/samples/charsets/iso-2022-jp/one.txt b/vendor/symfony/mime/Tests/Fixtures/samples/charsets/iso-2022-jp/one.txt new file mode 100644 index 0000000000000000000000000000000000000000..c2923deb983a0fb8bd031720089f456f0594398a --- /dev/null +++ b/vendor/symfony/mime/Tests/Fixtures/samples/charsets/iso-2022-jp/one.txt @@ -0,0 +1,11 @@ +ISO-2022-JPã¯ã€ã‚¤ãƒ³ã‚¿ãƒ¼ãƒãƒƒãƒˆä¸Š(特ã«é›»åメール)ãªã©ã§ä½¿ã‚ã‚Œã‚‹æ—¥æœ¬ã®æ–‡å—ç”¨ã®æ–‡å—符å·åŒ–æ–¹å¼ã€‚ISO/IEC 2022ã®ã‚¨ã‚¹ã‚±ãƒ¼ãƒ—シーケンスを利用ã—ã¦æ–‡å—集åˆã‚’切り替ãˆã‚‹7ビットã®ã‚³ãƒ¼ãƒ‰ã§ã‚ã‚‹ã“ã¨ã‚’特徴ã¨ã™ã‚‹ (アナウンス機能ã®ã‚¨ã‚¹ã‚±ãƒ¼ãƒ—シーケンスã¯çœç•¥ã•れる)。俗ã«ã€ŒJISコードã€ã¨å‘¼ã°ã‚Œã‚‹ã“ã¨ã‚‚ã‚る。 + +æ¦‚è¦ +日本語表記ã¸ã®åˆ©ç”¨ãŒæƒ³å®šã•れã¦ã„ã‚‹æ–‡å—コードã§ã‚ã‚Šã€æ—¥æœ¬èªžã®åˆ©ç”¨ã•れるãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã«ãŠã„ã¦ã€æ—¥æœ¬ã®è¦æ ¼ã‚’応用ã—ãŸã‚‚ã®ã§ã‚る。ã¾ãŸæ–‡å—集åˆã¨ã—ã¦ã¯ã€æ—¥æœ¬èªžã§ç”¨ã„られる漢å—ã€ã²ã‚‰ãŒãªã€ã‚«ã‚¿ã‚«ãƒŠã¯ã‚‚ã¡ã‚ã‚“ã€ãƒ©ãƒ†ãƒ³æ–‡å—ã€ã‚®ãƒªã‚·ã‚¢æ–‡å—ã€ã‚リル文å—ãªã©ã‚‚å«ã‚“ã§ãŠã‚Šã€å¦è¡“や産æ¥ã®åˆ†é‡Žã§ã®åˆ©ç”¨ã‚‚考慮ãŸã‚‚ã®ã¨ãªã£ã¦ã„ã‚‹ã€‚è¦æ ¼åã«ã€ISOã®æ—¥æœ¬èªžã®è¨€èªžã‚³ãƒ¼ãƒ‰ã§ã‚ã‚‹jaã§ã¯ãªãã€å›½ãƒ»åœ°åŸŸåコードã®JPãŒç¤ºã•れã¦ã„るゆãˆã‚“ã§ã‚る。 +æ–‡å—集åˆã¨ã—ã¦JIS X 0201ã®C0集åˆï¼ˆåˆ¶å¾¡æ–‡å—)ã€JIS X 0201ã®ãƒ©ãƒ†ãƒ³æ–‡å—集åˆã€ISO 646ã®å›½éš›åŸºæº–版図形文å—ã€JIS X 0208ã®1978年版(JIS C 6226-1978)ã¨1983å¹´ãŠã‚ˆã³1990年版ãŒåˆ©ç”¨ã§ãる。JIS X 0201ã®ç‰‡ä»®åæ–‡å—集åˆã¯åˆ©ç”¨ã§ããªã„。1986年以é™ã€æ—¥æœ¬ã®é›»åメールã§ç”¨ã„られã¦ããŸJUNETã‚³ãƒ¼ãƒ‰ã‚’ã€æ‘井純・Mark Crispin・Erik van der PoelãŒ1993å¹´ã«RFC化ã—ãŸã‚‚ã®(RFC 1468)。後ã«JIS X 0208:1997ã®é™„属書2ã¨ã—ã¦JISã«è¦å®šã•れãŸã€‚MIMEã«ãŠã‘ã‚‹æ–‡å—符å·åŒ–æ–¹å¼ã®è˜åˆ¥ç”¨ã®åå‰ã¨ã—㦠IANA ã«ç™»éŒ²ã•れã¦ã„る。 +ãªãŠã€ç¬¦å·åŒ–ã®ä»•様ã«ã¤ã„ã¦ã¯ISO/IEC 2022#ISO-2022-JPã‚‚å‚照。 + +ISO-2022-JPã¨éžæ¨™æº–的拡張使用 +「JISコードã€ï¼ˆã¾ãŸã¯ã€ŒISO-2022-JPã€ï¼‰ã¨ã„ã†ã‚³ãƒ¼ãƒ‰åã®è¦å®šä¸‹ã§ã¯ã€ãã®ä»•様通りã®ä½¿ç”¨ãŒæ±‚ã‚られる。ã—ã‹ã—ã€Windows OS上ã§ã¯ã€å®Ÿéš›ã«ã¯CP932コード (Microsoftã«ã‚ˆã‚‹Shift JISã‚’æ‹¡å¼µã—ãŸäºœç¨®ã€‚ISO-2022-JPè¦å®šå¤–æ–‡å—ãŒè¿½åŠ ã•れã¦ã„る。)ã«ã‚ˆã‚‹ç‹¬è‡ªæ‹¡å¼µï¼ˆã®æ–‡å—)をæ–りãªã使ã†ã‚¢ãƒ—リケーションãŒå¤šã„。ã“ã®ä¾‹ã¨ã—ã¦Internet Explorerã‚„Outlook ExpressãŒã‚る。ã¾ãŸã€EmEditorã€ç§€ä¸¸ã‚¨ãƒ‡ã‚£ã‚¿ã‚„Thunderbirdã®ã‚ˆã†ãªMicrosoft社以外ã®Windowsアプリケーションã§ã‚‚åŒæ§˜ã®å ´åˆãŒã‚る。ã“ã®å ´åˆã€ISO-2022-JPã®ç¯„å›²å¤–ã®æ–‡å—を使ã£ã¦ã—ã¾ã†ã¨ã€ç•°ãªã‚‹è£½å“é–“ã§ã¯æœªå®šç¾©ä¸æ˜Žæ–‡å—ã¨ã—ã¦èªè˜ã•れるã‹ã€ã‚‚ã—ãã¯æ–‡å—化ã‘ã‚’èµ·ã“ã™åŽŸå› ã¨ãªã‚‹ã€‚ãã®ãŸã‚ã€Windows用ã®é›»åメールクライアントã§ã‚ã£ã¦ã‚‚ç‹¬è‡ªæ‹¡å¼µã®æ–‡å—を使用ã™ã‚‹ã¨è¦å‘Šã‚’出ã—ãŸã‚Šã€ã‚ãˆã¦ä½¿ãˆãªã„よã†ã«åˆ¶é™ã—ã¦ã„ã‚‹ã‚‚ã®ã‚‚å˜åœ¨ã™ã‚‹ã€‚ã•らã«ã¯ISO-2022-JPã®ç¯„囲内ã§ã‚ã£ã¦ã‚‚CP932ã¯éžæ¨™æº–æ–‡å—(FULLWIDTH TILDEç‰ï¼‰ã‚’æŒã¤ã®ã§æ–‡å—化ã‘ã®åŽŸå› ã«ãªã‚Šå¾—る。 +ã¾ãŸã€ç¬¦å·åŒ–æ–¹å¼åã‚’ISO-2022-JPã¨ã—ã¦ã„ã‚‹ã®ã«ã€æ–‡å—集åˆã¨ã—ã¦ã¯JIS X 0212 (ã„ã‚ゆる補助漢å—) ã‚„JIS X 0201ã®ç‰‡ä»®åæ–‡å—é›†åˆ (ã„ã‚ゆるåŠè§’カナ) をも符å·åŒ–ã—ã¦ã„る例ãŒã‚ã‚‹ãŒã€ISO-2022-JPã§ã¯ã“ã‚Œã‚‰ã®æ–‡å—を許容ã—ã¦ã„ãªã„。ã“れらã®ç¬¦å·åŒ–ã¯ç‹¬è‡ªæ‹¡å¼µã®å®Ÿè£…ã§ã‚りã€ä¸ã«ã¯ISO/IEC 2022ã®ä»•æ§˜ã«æº–æ‹ ã™ã‚‰ã—ã¦ã„ãªã„ã‚‚ã®ã‚‚ã‚ã‚‹[2]。従ã£ã¦å—ä¿¡å´ã®é›»åメールクライアントãŒã“れらã®ç‹¬è‡ªæ‹¡å¼µã«å¯¾å¿œã—ã¦ã„ãªã„å ´åˆã€ãã®æ–‡å—ã‚ã‚‹ã„ã¯ãã®æ–‡å—ã‚’å«ã‚€è¡Œã€æ™‚ã«ã¯ãƒ†ã‚ã‚¹ãƒˆå…¨ä½“ãŒæ–‡å—化ã‘ã™ã‚‹ã“ã¨ãŒã‚る。 + diff --git a/vendor/symfony/mime/Tests/Fixtures/samples/charsets/iso-8859-1/one.txt b/vendor/symfony/mime/Tests/Fixtures/samples/charsets/iso-8859-1/one.txt new file mode 100644 index 0000000000000000000000000000000000000000..3101178af2d73a0e8688b8d9c35da2b1a70208f6 --- /dev/null +++ b/vendor/symfony/mime/Tests/Fixtures/samples/charsets/iso-8859-1/one.txt @@ -0,0 +1,19 @@ +Op mat eraus hinnen beschte, rou zënne schaddreg ké. Ké sin Eisen Kaffi prächteg, den haut esou Fielse wa, Well zielen d'Welt am dir. Aus grousse rëschten d'Stroos do, as dat Kléder gewëss d'Kà chen. Schied gehéiert d'Vioule net hu, rou ke zënter Säiten d'Hierz. Ze eise Fletschen mat, gei as gréng d'Lëtzebuerger. Wäit räich no mat. + +Säiten d'Liewen aus en. Un gëtt bléit lossen wee, da wéi alle weisen Kolrettchen. Et deser d'Pan d'Kirmes vun, en wuel Benn rëschten méi. En get drem ménger beschte, da wär Stad welle. Nun Dach d'Pied do, mä gét ruffen gehéiert. Ze onser ugedon fir, d'Liewen Plett'len ech no, si Räis wielen bereet wat. Iwer spilt fir jo. + +An hin däischter Margréitchen, eng ke Frot brommt, vu den Räis néierens. Da hir Hunn Frot nozegon, rout Fläiß Himmel zum si, net gutt Kaffi Gesträich fu. Vill lait Gaart sou wa, Land Mamm Schuebersonndeg rei do. Gei geet Minutt en, gei d'Leit beschte Kolrettchen et, Mamm fergiess un hun. + +Et gutt Heck kommen oft, Lann rëscht rei um, Hunn rëscht schéinste ke der. En lait zielen schnéiwäiss hir, fu rou botze éiweg Minutt, rem fest gudden schaddreg en. Noper bereet Margréitchen mat op, dem denkt d'Leit d'Vioule no, oft ké Himmel Hämmel. En denkt blénken Fréijor net, Gart Schiet d'Natur no wou. No hin Ierd Frot d'Kirmes. Hire aremt un rou, ké den éiweg wielen Milliounen. + +Mir si Hunn Blénkeg. Ké get ston derfir d'Kà chen. Haut d'Pan fu ons, dé frou löschteg d'Meereische rei. Sou op wuel Léift. Stret schlon grousse gin hu. Mä denkt d'Leit hinnen net, ké gét haut fort rëscht. + +Koum d'Pan hannendrun ass ké, ké den brét Kaffi geplot. Schéi Hären d'Pied fu gét, do d'Mier néierens bei. Rëm päift Hämmel am, wee Engel beschéngt mä. Brommt klinzecht der ke, wa rout jeitzt dén. Get Zalot d'Vioule däischter da, jo fir Bänk päift duerch, bei d'Beem schéinen Plett'len jo. Den haut Faarwen ze, eng en Biereg Kirmesdag, um sin alles Faarwen d'Vioule. + +Eng Hunn Schied et, wat wa Frot fest gebotzt. Bei jo bleiwe ruffen Klarinett. Un Feld klinzecht gét, rifft Margréitchen rem ke. Mir dé Noper duurch gewëss, ston sech kille sin en. Gei Stret d'Wise um, Haus Gart wee as. Monn ménger an blo, wat da Gart gefällt Hämmelsbrot. + +Brommt geplot och ze, dat wa Räis Well Kaffi. Do get spilt prächteg, as wär kille bleiwe gewalteg. Onser frësch Margréitchen rem ke, blo en huet ugedon. Onser Hemecht wär de, hu eraus d'Sonn dat, eise deser hannendrun da och. + +As durch Himmel hun, no fest iw'rem schéinste mir, Hunn séngt Hierz ke zum. Séngt iw'rem d'Natur zum an. Ke wär gutt Grénge. Kënnt gudden prächteg mä rei. Dé dir Blénkeg Klarinett Kolrettchen, da fort muerges d'Kanner wou, main Feld ruffen vu wéi. Da gin esou Zalot gewalteg, gét vill Hemecht blénken dé. + +Haut gréng nun et, nei vu Bass gréng d'Gaassen. Fest d'Beem uechter si gin. Oft vu sinn wellen kréien. Et ass lait Zalot schéinen. \ No newline at end of file diff --git a/vendor/symfony/mime/Tests/Fixtures/samples/charsets/utf-8/one.txt b/vendor/symfony/mime/Tests/Fixtures/samples/charsets/utf-8/one.txt new file mode 100644 index 0000000000000000000000000000000000000000..26c94d5d231cb1f5718d6d1df8253f361000e2d3 --- /dev/null +++ b/vendor/symfony/mime/Tests/Fixtures/samples/charsets/utf-8/one.txt @@ -0,0 +1,22 @@ +Код одно гринÑпана руководишь на. Его вы Ð·Ð½Ð°Ð½Ð¸Ñ Ð´Ð²Ð¸Ð¶ÐµÐ½Ð¸Ðµ. Ты две начать +одиночку, Ñказать оÑнователь удовольÑтвием но миф. Бы какие ÑиÑтема тем. +ПолноÑтью иÑпользует три мы, человек клоунов те наÑ, бы давать творчеÑкую +ÑзотеричеÑÐºÐ°Ñ ÑˆÐµÑ„. + +Мог не помнить никакого ÑÑкономленного, две либо какие пишите бы. Должен +компанию кто те, Ñтот заключалаÑÑŒ проектировщик не ты. Глупые периоды ты +длÑ. Вам который хороший он. Те любых ÐºÑ€ÐµÐ¼Ð½Ð¸Ñ ÐºÐ¾Ð½Ñ†ÐµÐ½Ñ‚Ñ€Ð¸Ñ€ÑƒÑŽÑ‚ÑÑ Ð¼Ð¾Ð³, +Ñобирать принадлежите без вы. + +ДжоÑла меньше хорошего вы миф, за тем году разработки. Даже управлÑющим +руководители был не. Три коде выпуÑкать заботитьÑÑ Ð½Ñƒ. То его ÑиÑтема +удовольÑтвием безоÑтановочно, или ты главной процеÑÑорах. Мы без джоÑл +Ð·Ð½Ð°Ð½Ð¸Ñ Ð¿Ð¾Ð»ÑƒÑ‡Ð°Ñ‚, Ñтатьи оÑтальные мы ещё. + +Ðих руÑÑком каÑаетÑÑ Ð¿Ð¾Ñкольку по, образование должником +ÑиÑтематизированный ну мои. Прийти кандидата универÑитет но наÑ, Ð´Ð»Ñ Ð±Ñ‹ +должны никакого, биг многие причин Ð¸Ð½Ñ‚ÐµÑ€Ð²ÑŒÑŽÐ¸Ñ€Ð¾Ð²Ð°Ð½Ð¸Ñ Ð·Ð°. + +Тем до плиту почему. Вот учёт такие одного бы, об биг разным внешних +промежуток. Ð’Ð°Ñ Ð´Ð¾ какому возможноÑтей безответÑтвенный, были погодите бы +его, по них глупые долгий количеÑтва. diff --git a/vendor/symfony/mime/Tests/Fixtures/samples/charsets/utf-8/three.txt b/vendor/symfony/mime/Tests/Fixtures/samples/charsets/utf-8/three.txt new file mode 100644 index 0000000000000000000000000000000000000000..c81ccd598b6077fe92c78afa7aee238f2f4cf0ea --- /dev/null +++ b/vendor/symfony/mime/Tests/Fixtures/samples/charsets/utf-8/three.txt @@ -0,0 +1,45 @@ +Αν ήδη διάβασε γλιτώσει μεταγλωτίσει, αυτήν θυμάμαι μου μα. Την κατάσταση χÏησιμοποίησΠνα! Τα διαφοÏά φαινόμενο διολισθήσεις πες, υψηλότεÏη Ï€Ïοκαλείς πεÏισσότεÏες όχι κι. Με ελÎγχου γίνεται σας, μικÏής δημιουÏγοÏν τη του. Τις τα γÏάψει εικόνες απαÏάδεκτη? + +Îα ότι Ï€Ïώτοι απαÏαίτητο. Άμεση πετάνε κακόκεφος τον ÏŽÏ‚, να χώÏου πιθανότητες του. Το μÎχÏι οÏίστε λιγότεÏους σας. Πω ναί φυσικά εικόνες. + +Μου οι κώδικα αποκλειστικοÏÏ‚, λες το μάλλον συνεχώς. ÎÎου σημεία απίστευτα σας μα. ΧÏόνου μεταγλωτιστής σε νÎα, τη τις πιάνει μποÏοÏσες Ï€ÏογÏαμματιστÎÏ‚. Των κάνε βγαίνει εντυπωσιακό τα? ΚÏατάει τεσσαÏών δυστυχώς της κι, ήδη υψηλότεÏη εξακολουθεί τα? + +ÎÏα πετάνε μποÏοÏσε λιγότεÏους αν, τα απαÏάδεκτη συγχωνευτεί Ïοή. Τη ÎγÏαψες συνηθίζουν σαν. Όλα με υλικό στήλες χειÏότεÏα. Ανώδυνη δουλÎψει επί ως, αν διαδίκτυο εσωτεÏικών παÏάγοντες από. ΚεντÏικό επιτυχία πες το. + +Πω ναι λÎει τελειώσει, Îξι ως ÎÏγων τελειώσει. Με αÏχεία βουτήξουν ανταγωνιστής ÏŽÏα, Ï€Î¿Î»Ï Î³Ïαφικά σελίδων τα στη. ÎŒÏο οÎλεγχος δημιουÏγοÏν δε, ας θÎλεις ελÎγχου συντακτικό ÏŒÏο! Της θυμάμαι επιδιόÏθωση τα. Για μποÏοÏσε πεÏισσότεÏο αν, μÎγιστη σημαίνει αποφάσισε τα του, άτομο αποτελÎσει τι στα. + +Τι στην αφήσεις διοίκηση στη. Τα εσφαλμÎνη δημιουÏγια επιχείÏιση Îξι! Βήμα μαγικά εκτελÎσει ανά τη. Όλη αφήσεις συνεχώς εμποÏικά αν, το λες κόλπα επιτυχία. Ότι οι ζώνη κειμÎνων. ÎŒÏο κι Ïωτάει γÏαμμής πελάτες, τελειώσει διολισθήσεις καθυστεÏοÏσε αν εγώ? Τι πετοÏν διοίκηση Ï€Ïοβλήματα ήδη. + +Τη γλιτώσει Î±Ï€Î¿Î¸Î·ÎºÎµÏ…Ï„Î¹ÎºÎ¿Ï Î¼Î¹Î±. Πω Îξι δημιουÏγια πιθανότητες, ως Ï€Îντε ελÎγχους εκτελείται λες. Πως εÏωτήσεις διοικητικό συγκεντÏωμÎνοι οι, ας συνεχώς διοικητικό αποστηθίσει σαν. Δε Ï€Ïώτες συνεχώς διολισθήσεις Îχω, από τι κανÎνας βουτήξουν, γειτονιάς Ï€Ïοσεκτικά ανταγωνιστής κι σαν. + +ΔημιουÏγια συνηθίζουν κλπ τι? Όχι ποσοστό διακοπής κι. Κλπ φακÎλους δεδομÎνη εξοÏγιστικά θα? Υποψήφιο καθοÏίζουν με όλη, στα πήÏε Ï€Ïοσοχή εταιÏείες πω, ÏŽÏ‚ τον συνάδελφος διοικητικό δημιουÏγήσεις! ΔοÏλευε επιτίθενται σας θα, με Îνας παÏαγωγικής Îνα, να ναι σημεία μÎγιστη απαÏάδεκτη? + +Σας τεσσαÏών συνεντεÏξης τη, αÏπάζεις σίγουÏος μη για', επί τοπικÎÏ‚ εντολÎÏ‚ ακοÏσει θα? Ως δυστυχής μεταγλωτιστής όλη, να την είχαν σφάλμα απαÏαίτητο! Μην ÏŽÏ‚ άτομο διοÏθώσει χÏησιμοποιοÏνταν. Δεν τα κόλπα πετάξαμε, μη που άγχος Ï…ÏŒÏκη άμεση, Î±Ï†Î¿Ï Î´Ï…ÏƒÏ„Ï…Ï‡ÏŽÏ‚ διακόψουμε ÏŒÏο αν! Όλη μαγικά πετάνε επιδιοÏθώσεις δε, Ïοή φυσικά αποτελÎσει πω. + +ΆπειÏα παÏαπάνω φαινόμενο πω ÏŽÏα, σαν πόÏτες κÏατήσουν συνηθίζουν ως. Κι ÏŽÏα Ï„ÏÎξει είχαμε εφαÏμογή. Απλό σχεδιαστής μεταγλωτιστής ας επί, τις τα όταν ÎγÏαψες γÏαμμής? Όλα κάνεις συνάδελφος εÏγαζόμενοι θα, χαÏÏ„Î¹Î¿Ï Ï‡Î±Î¼Î·Î»ÏŒÏ‚ τα Ïοή. Ως ναι ÏŒÏοφο ÎÏθει, μην πελάτες αποφάσισε μεταφÏαστής με, να βιαστικά εκδόσεις αναζήτησης λες. Των φταίει εκθÎσεις Ï€Ïοσπαθήσεις οι, σπίτι αποστηθίσει ας λες? + +ÎÏ‚ που υπηÏεσία απαÏαίτητο δημιουÏγείς. Μη άÏα χαÏά καθώς νÏχτας, πω ματ μπουν είχαν. Άμεση δημιουÏγείς ÏŽÏ‚ Ïοή, γÏάψει γÏαμμής σίγουÏος στα τι! Αν Î±Ï†Î¿Ï Ï€Ïώτοι εÏγαζόμενων ναί. + +Άμεση διοÏθώσεις με δÏο? Έχουν παÏάδειγμα των θα, μου ÎÏθει θυμάμαι πεÏισσότεÏο το. Ότι θα Î±Ï†Î¿Ï Ï‡Ïειάζονται πεÏισσότεÏες. Σαν συνεχώς πεÏίπου οι. + +ÎÏ‚ Ï€Ïώτης πετάξαμε λες, ÏŒÏο κι Ï€Ïώτες ζητήσεις δυστυχής. Ανά χÏόνου διακοπή επιχειÏηματίες ας, ÏŽÏ‚ μόλις άτομο χειÏότεÏα ÏŒÏο, κÏατάει σχεδιαστής Ï€Ïοσπαθήσεις νÎο το. Πουλάς Ï€ÏοσθÎσει όλη πω, Ï„Ïπου χαÏακτηÏιστικό εγώ σε, πω πιο δοÏλευε αναζήτησης? ΑναφοÏά δίνοντας σαν μη, μάθε δεδομÎνη εσωτεÏικών με ναι, αναφÎÏονται πεÏιβάλλοντος ÏŽÏα αν. Και λÎει απόλαυσε τα, που το ÏŒÏοφο Ï€ÏοσπαθοÏν? + +Πάντα χÏόνου χÏήματα ναι το, σαν σωστά θυμάμαι σκεφτείς τα. Μα αποτελÎσει ανεπιθÏμητη την, πιο το Ï„Îτοιο ατόμου, τη των Ï„Ïόπο εÏγαλείων επιδιόÏθωσης. ΠεÏιβάλλον παÏαγωγικής σου κι, κλπ οι Ï„Ïπου κακόκεφους αποστηθίσει, δε των πλÎον Ï„Ïόποι. Πιθανότητες χαÏακτηÏιστικών σας κι, γÏαφικά δημιουÏγήσεις μια οι, πω πολλοί εξαÏτάται Ï€Ïοσεκτικά εδώ. Σταματάς παÏάγοντες για' ÏŽÏ‚, στις Ïωτάει το ναι! ΚαÏÎκλα ζητήσεις συνδυασμοÏÏ‚ τη ήδη! + +Για μαγικά συνεχώς ακοÏσει το. Σταματάς Ï€Ïοϊόντα βουτήξουν ÏŽÏ‚ Ïοή. Είχαν Ï€Ïώτες οι ναι, μα λες αποστηθίσει ανακαλÏπτεις. ÎŒÏοφο άλγεβÏα παÏαπάνω εδώ τη, Ï€Ïόσληψη λαμβάνουν καταλάθος ήδη ας? Ως και εισαγωγή κÏατήσουν, Îνας κακόκεφους κι μας, όχι κώδικάς παίξουν πω. Πω νÎα κÏατάει εκφÏάσουν, τότε τελικών τη όχι, ας της Ï„ÏÎξει αλλάζοντας αποκλειστικοÏÏ‚. + +Ένας βιβλίο σε άÏα, ναι ως γÏάψει ταξινομεί διοÏθώσεις! Εδώ να γεγονός συγγÏαφείς, ÏŽÏ‚ ήδη διακόψουμε επιχειÏηματίες? Ότι πακÎτων εσφαλμÎνη κι, θα ÏŒÏο κόλπα παÏαγωγικής? Αν Îχω κεντÏικό υψηλότεÏη, κι δεν ίδιο πετάνε παÏατηÏοÏμενη! Που λοιπόν σημαντικό μα, Ï€Ïοκαλείς χειÏοκÏοτήματα ως όλα, μα επί κόλπα άγχος γÏαμμÎÏ‚! Δε σου κάνεις βουτήξουν, μη ÎÏγων επενδυτής χÏησιμοποίησΠστα, ως του Ï€Ïώτες διάσημα σημαντικό. + +Βιβλίο τεÏάστιο Ï€ÏοκÏπτουν σαν το, σαν Ï„Ïόπο επιδιόÏθωση ας. Είχαν Ï€Ïοσοχή Ï€Ïοσπάθεια κι ματ, εδώ ως Îτσι σελίδων συζήτηση. Και στην βγαίνει εσφαλμÎνη με, δυστυχής παÏάδειγμα δε μας, από σε Ï…ÏŒÏκη επιδιόÏθωσης. ÎÎα πω νÎου πιθανό, στήλες συγγÏαφείς μπαίνοντας μα για', το Ïωτήσει κακόκεφους της? Μου σε αÏÎσει συγγÏαφής συγχωνευτεί, μη μου Ï…ÏŒÏκη ξÎχασε διακοπής! ÎÏ‚ επί αποφάσισε αποκλειστικοÏÏ‚ χÏησιμοποιώντας, χÏήματα σελίδων ταξινομεί ναι με. + +Μη ανά γÏαμμή απόλαυσε, πω ναι μάτσο διασφαλίζεται. Τη Îξι μόλις εÏγάστηκε δημιουÏγοÏν, Îκδοση αναφοÏά δυσκολότεÏο οι νÎο. Σας ως μποÏοÏσε παÏάδειγμα, αν ότι δοÏλευε μποÏοÏσε αποκλειστικοÏÏ‚, πιο λÎει βουτήξουν διοÏθώσει ως. Έχω τελευταία κακόκεφους ας, όσο εÏγαζόμενων δημιουÏγήσεις τα. + +Του αν δουλÎψει μποÏοÏσε, πετοÏν χαμηλός εδώ ας? ΚÏκλο Ï„Ïπους με που, δεν σε Îχουν συνεχώς χειÏότεÏα, τις τι απαÏάδεκτη συνηθίζουν? Θα μην τους αυτήν, τη Îνα πήÏε πακÎτων, κι Ï€ÏοκÏπτουν πεÏιβάλλον πως. Μα για δουλÎψει απόλαυσε εφαμοÏγής, ÏŽÏ‚ εδώ σημαίνει μποÏοÏσες, άμεση ακοÏσει Ï€Ïοσοχή τη εδώ? + +Στα δώσε αθόÏυβες λιγότεÏους οι, δε αναγκάζονται αποκλειστικοÏÏ‚ όλα! Ας μπουν διοικητικό μια, πάντα ελÎγχου διοÏθώσεις ÏŽÏ‚ τον. Ότι πήÏε κανόνα μα. Που άτομα κάνεις δημιουÏγίες τα, οι μας Î±Ï†Î¿Ï ÎºÏŒÎ»Ï€Î± Ï€ÏογÏαμματιστής, Î±Ï†Î¿Ï Ï‰Ïαίο Ï€ÏοκÏπτουν στα ως. ΘÎμα χÏησιμοποιήσει αν όλα, του τα άλγεβÏα σελίδων. Τα ότι ανώδυνη δυστυχώς συνδυασμοÏÏ‚, μας οι πάντα γνωÏίζουμε ανταγωνιστής, όχι τα δοκιμάσεις σχεδιαστής! Στην συνεντεÏξης επιδιόÏθωση πιο τα, μα από πουλάς πεÏιβάλλον παÏαγωγικής. + +Έχουν μεταγλωτίσει σε σας, σε πάντα Ï€Ïώτης μειώσει των, γÏάψει Ïουτίνα δυσκολότεÏο ήδη μα? Ταξινομεί διοÏθώσεις να μας. Θα της Ï€ÏοσπαθοÏν πεÏιεχόμενα, δε Îχω τοπικÎÏ‚ στÎλνοντάς. Ανά δε αλφα άμεση, κάποιο Ïωτάει γνωÏίζουμε πω στη, φÏάση μαγικά συνÎχεια δε δÏο! Αν είχαμε μειώσει Ïοή, μας μετÏάει καθυστεÏοÏσε επιδιοÏθώσεις μη. Χάος Ï…ÏŒÏκη κεντÏικό Îχω σε, ανά πεÏίπου αναγκάζονται πω. + +Όσο επιστÏÎφουν χÏονοδιαγÏάμματα μη. Πως ωÏαίο κακόκεφος διαχειÏιστής ως, τις να διακοπής αναζήτησης. Κάποιο ποσοστό ταξινομεί επί τη? Μάθε άμεση αλλάζοντας δÏο με, μου νÎου πάντα να. + +Πω του δυστυχώς πιθανότητες. Κι Ïωτάει υψηλότεÏη δημιουÏγια ότι, πω εισαγωγή τελευταία απομόνωση ναι. Των ζητήσεις γνωÏίζουμε ÏŽÏ‚? Για' μη παÏαδοτÎου αναφÎÏονται! Ύψος παÏαγωγικά Ïοή ως, φυσικά διάβασε εικόνες όσο σε? Δεν Ï…ÏŒÏκη διοÏθώσεις επεξεÏγασία θα, ως μÎση σÏστημα χÏησιμοποιήσει τις. \ No newline at end of file diff --git a/vendor/symfony/mime/Tests/Fixtures/samples/charsets/utf-8/two.txt b/vendor/symfony/mime/Tests/Fixtures/samples/charsets/utf-8/two.txt new file mode 100644 index 0000000000000000000000000000000000000000..2443fc4d88e6ab9795ded0bab336b6c2d86f0286 --- /dev/null +++ b/vendor/symfony/mime/Tests/Fixtures/samples/charsets/utf-8/two.txt @@ -0,0 +1,3 @@ +रखति आवशà¥à¤¯à¤•त पà¥à¤°à¥‡à¤°à¤¨à¤¾ मà¥à¤–à¥à¤¯à¤¤à¤¹ हिंदी किà¤à¤²à¥‹à¤— असकà¥à¤·à¤® कारà¥à¤¯à¤²à¤¯ करते विवरण किके मानसिक दिनांक पà¥à¤°à¥à¤µ संसाध à¤à¤µà¤®à¥ कà¥à¤¶à¤²à¤¤à¤¾ अमितकà¥à¤®à¤¾à¤° पà¥à¤°à¥‹à¤¤à¥à¤¸à¤¾à¤¹à¤¿à¤¤ जनित देखने उदेशीत विकसित बलवान बà¥à¤°à¥Œà¤¶à¤° किà¤à¤²à¥‹à¤— विशà¥à¤²à¥‡à¤·à¤£ लोगो कैसे जागरà¥à¤• पà¥à¤°à¤µà¥à¤°à¥à¤¤à¤¿ पà¥à¤°à¥‹à¤¤à¥à¤¸à¤¾à¤¹à¤¿à¤¤ सदसà¥à¤¯ आवशà¥à¤¯à¤•त पà¥à¤°à¤¸à¤¾à¤°à¤¨ उपलबà¥à¤§à¤¤à¤¾ अथवा हिंदी जनित दरà¥à¤¶à¤¾à¤¤à¤¾ यनà¥à¤¤à¥à¤°à¤¾à¤²à¤¯ बलवान अतित सहयोग शà¥à¤°à¥à¤†à¤¤ सà¤à¥€à¤•à¥à¤› माहितीवानीजà¥à¤¯ लिये खरिदे है।अà¤à¥€ à¤à¤•तà¥à¤°à¤¿à¤¤ समà¥à¤ªà¤°à¥à¤• रिती मà¥à¤¶à¥à¤•िल पà¥à¤°à¤¾à¤¥à¤®à¤¿à¤• à¤à¥‡à¤¦à¤¨à¤•à¥à¤·à¤®à¤¤à¤¾ विशà¥à¤µ उनà¥à¤¹à¥‡ गटको दà¥à¤µà¤¾à¤°à¤¾ तकरीबन + +विशà¥à¤µ दà¥à¤µà¤¾à¤°à¤¾ वà¥à¤¯à¤¾à¤–à¥à¤¯à¤¾ सके। आजपर वातावरण वà¥à¤¯à¤¾à¤–à¥à¤¯à¤¾à¤¨ पहोच। हमारी कीसे पà¥à¤°à¤¾à¤¥à¤®à¤¿à¤• विचारशिलता पà¥à¤°à¥à¤µ करती कमà¥à¤ªà¥à¤¯à¥à¤Ÿà¤° à¤à¥‡à¤¦à¤¨à¤•à¥à¤·à¤®à¤¤à¤¾ लिये बलवान औरà¥à¥ªà¥«à¥¦ यायेका वारà¥à¤¤à¤¾à¤²à¤¾à¤ª सà¥à¤šà¤¨à¤¾ à¤à¤¾à¤°à¤¤ शà¥à¤°à¥à¤†à¤¤ लाà¤à¤¾à¤¨à¥à¤µà¤¿à¤¤ पढाठसंसà¥à¤¥à¤¾ वरà¥à¤£à¤¿à¤¤ मारà¥à¤—दरà¥à¤¶à¤¨ चà¥à¤¨à¤¨à¥‡ \ No newline at end of file diff --git a/vendor/symfony/mime/Tests/Header/DateHeaderTest.php b/vendor/symfony/mime/Tests/Header/DateHeaderTest.php new file mode 100644 index 0000000000000000000000000000000000000000..4fc92b96aecf96240d138a328ae8dba960b7d359 --- /dev/null +++ b/vendor/symfony/mime/Tests/Header/DateHeaderTest.php @@ -0,0 +1,80 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime\Tests\Header; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Mime\Header\DateHeader; + +class DateHeaderTest extends TestCase +{ + /* -- + The following tests refer to RFC 2822, section 3.6.1 and 3.3. + */ + + public function testGetDateTime() + { + $header = new DateHeader('Date', $dateTime = new \DateTimeImmutable()); + $this->assertSame($dateTime, $header->getDateTime()); + } + + public function testDateTimeCanBeSetBySetter() + { + $header = new DateHeader('Date', new \DateTimeImmutable()); + $header->setDateTime($dateTime = new \DateTimeImmutable()); + $this->assertSame($dateTime, $header->getDateTime()); + } + + public function testDateTimeIsConvertedToImmutable() + { + $dateTime = new \DateTime(); + $header = new DateHeader('Date', $dateTime); + $this->assertInstanceOf('DateTimeImmutable', $header->getDateTime()); + $this->assertEquals($dateTime->getTimestamp(), $header->getDateTime()->getTimestamp()); + $this->assertEquals($dateTime->getTimezone(), $header->getDateTime()->getTimezone()); + } + + public function testDateTimeIsImmutable() + { + $header = new DateHeader('Date', $dateTime = new \DateTime('2000-01-01 12:00:00 Europe/Berlin')); + $dateTime->setDate(2002, 2, 2); + $this->assertEquals('Sat, 01 Jan 2000 12:00:00 +0100', $header->getDateTime()->format('r')); + $this->assertEquals('Sat, 01 Jan 2000 12:00:00 +0100', $header->getBodyAsString()); + } + + public function testDateTimeIsConvertedToRfc2822Date() + { + $header = new DateHeader('Date', $dateTime = new \DateTimeImmutable('2000-01-01 12:00:00 Europe/Berlin')); + $header->setDateTime($dateTime); + $this->assertEquals('Sat, 01 Jan 2000 12:00:00 +0100', $header->getBodyAsString()); + } + + public function testSetBody() + { + $header = new DateHeader('Date', $dateTime = new \DateTimeImmutable()); + $header->setBody($dateTime); + $this->assertEquals($dateTime->format('r'), $header->getBodyAsString()); + } + + public function testGetBody() + { + $header = new DateHeader('Date', $dateTime = new \DateTimeImmutable()); + $header->setDateTime($dateTime); + $this->assertEquals($dateTime, $header->getBody()); + } + + public function testToString() + { + $header = new DateHeader('Date', $dateTime = new \DateTimeImmutable('2000-01-01 12:00:00 Europe/Berlin')); + $header->setDateTime($dateTime); + $this->assertEquals('Date: Sat, 01 Jan 2000 12:00:00 +0100', $header->toString()); + } +} diff --git a/vendor/symfony/mime/Tests/Header/HeadersTest.php b/vendor/symfony/mime/Tests/Header/HeadersTest.php new file mode 100644 index 0000000000000000000000000000000000000000..3568c9a6e45d60ecd62566612eadea834ab497f7 --- /dev/null +++ b/vendor/symfony/mime/Tests/Header/HeadersTest.php @@ -0,0 +1,245 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime\Tests\Header; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Mime\Address; +use Symfony\Component\Mime\Header\Headers; +use Symfony\Component\Mime\Header\IdentificationHeader; +use Symfony\Component\Mime\Header\MailboxListHeader; +use Symfony\Component\Mime\Header\UnstructuredHeader; + +class HeadersTest extends TestCase +{ + public function testAddMailboxListHeaderDelegatesToFactory() + { + $headers = new Headers(); + $headers->addMailboxListHeader('From', ['person@domain']); + $this->assertNotNull($headers->get('From')); + } + + public function testAddDateHeaderDelegatesToFactory() + { + $dateTime = new \DateTimeImmutable(); + $headers = new Headers(); + $headers->addDateHeader('Date', $dateTime); + $this->assertNotNull($headers->get('Date')); + } + + public function testAddTextHeaderDelegatesToFactory() + { + $headers = new Headers(); + $headers->addTextHeader('Subject', 'some text'); + $this->assertNotNull($headers->get('Subject')); + } + + public function testAddParameterizedHeaderDelegatesToFactory() + { + $headers = new Headers(); + $headers->addParameterizedHeader('Content-Type', 'text/plain', ['charset' => 'utf-8']); + $this->assertNotNull($headers->get('Content-Type')); + } + + public function testAddIdHeaderDelegatesToFactory() + { + $headers = new Headers(); + $headers->addIdHeader('Message-ID', 'some@id'); + $this->assertNotNull($headers->get('Message-ID')); + } + + public function testAddPathHeaderDelegatesToFactory() + { + $headers = new Headers(); + $headers->addPathHeader('Return-Path', 'some@path'); + $this->assertNotNull($headers->get('Return-Path')); + } + + public function testHasReturnsFalseWhenNoHeaders() + { + $headers = new Headers(); + $this->assertFalse($headers->has('Some-Header')); + } + + public function testAddedMailboxListHeaderIsSeenByHas() + { + $headers = new Headers(); + $headers->addMailboxListHeader('From', ['person@domain']); + $this->assertTrue($headers->has('From')); + } + + public function testAddedDateHeaderIsSeenByHas() + { + $dateTime = new \DateTimeImmutable(); + $headers = new Headers(); + $headers->addDateHeader('Date', $dateTime); + $this->assertTrue($headers->has('Date')); + } + + public function testAddedTextHeaderIsSeenByHas() + { + $headers = new Headers(); + $headers->addTextHeader('Subject', 'some text'); + $this->assertTrue($headers->has('Subject')); + } + + public function testAddedParameterizedHeaderIsSeenByHas() + { + $headers = new Headers(); + $headers->addParameterizedHeader('Content-Type', 'text/plain', ['charset' => 'utf-8']); + $this->assertTrue($headers->has('Content-Type')); + } + + public function testAddedIdHeaderIsSeenByHas() + { + $headers = new Headers(); + $headers->addIdHeader('Message-ID', 'some@id'); + $this->assertTrue($headers->has('Message-ID')); + } + + public function testAddedPathHeaderIsSeenByHas() + { + $headers = new Headers(); + $headers->addPathHeader('Return-Path', 'some@path'); + $this->assertTrue($headers->has('Return-Path')); + } + + public function testNewlySetHeaderIsSeenByHas() + { + $headers = new Headers(); + $headers->add(new UnstructuredHeader('X-Foo', 'bar')); + $this->assertTrue($headers->has('X-Foo')); + } + + public function testHasCanDistinguishMultipleHeaders() + { + $headers = new Headers(); + $headers->addTextHeader('X-Test', 'some@id'); + $headers->addTextHeader('X-Test', 'other@id'); + $this->assertTrue($headers->has('X-Test')); + } + + public function testGet() + { + $header = new IdentificationHeader('Message-ID', 'some@id'); + $headers = new Headers(); + $headers->addIdHeader('Message-ID', 'some@id'); + $this->assertEquals($header->toString(), $headers->get('Message-ID')->toString()); + } + + public function testGetReturnsNullIfHeaderNotSet() + { + $headers = new Headers(); + $this->assertNull($headers->get('Message-ID')); + } + + public function testAllReturnsAllHeadersMatchingName() + { + $header0 = new UnstructuredHeader('X-Test', 'some@id'); + $header1 = new UnstructuredHeader('X-Test', 'other@id'); + $header2 = new UnstructuredHeader('X-Test', 'more@id'); + $headers = new Headers(); + $headers->addTextHeader('X-Test', 'some@id'); + $headers->addTextHeader('X-Test', 'other@id'); + $headers->addTextHeader('X-Test', 'more@id'); + $this->assertEquals([$header0, $header1, $header2], iterator_to_array($headers->all('X-Test'))); + } + + public function testAllReturnsAllHeadersIfNoArguments() + { + $header0 = new IdentificationHeader('Message-ID', 'some@id'); + $header1 = new UnstructuredHeader('Subject', 'thing'); + $header2 = new MailboxListHeader('To', [new Address('person@example.org')]); + $headers = new Headers(); + $headers->addIdHeader('Message-ID', 'some@id'); + $headers->addTextHeader('Subject', 'thing'); + $headers->addMailboxListHeader('To', [new Address('person@example.org')]); + $this->assertEquals(['message-id' => $header0, 'subject' => $header1, 'to' => $header2], iterator_to_array($headers->all())); + } + + public function testAllReturnsEmptyArrayIfNoneSet() + { + $headers = new Headers(); + $this->assertEquals([], iterator_to_array($headers->all('Received'))); + } + + public function testRemoveRemovesAllHeadersWithName() + { + $header0 = new UnstructuredHeader('X-Test', 'some@id'); + $header1 = new UnstructuredHeader('X-Test', 'other@id'); + $headers = new Headers(); + $headers->addIdHeader('X-Test', 'some@id'); + $headers->addIdHeader('X-Test', 'other@id'); + $headers->remove('X-Test'); + $this->assertFalse($headers->has('X-Test')); + $this->assertFalse($headers->has('X-Test')); + } + + public function testHasIsNotCaseSensitive() + { + $header = new IdentificationHeader('Message-ID', 'some@id'); + $headers = new Headers(); + $headers->addIdHeader('Message-ID', 'some@id'); + $this->assertTrue($headers->has('message-id')); + } + + public function testGetIsNotCaseSensitive() + { + $header = new IdentificationHeader('Message-ID', 'some@id'); + $headers = new Headers(); + $headers->addIdHeader('Message-ID', 'some@id'); + $this->assertEquals($header, $headers->get('message-id')); + } + + public function testAllIsNotCaseSensitive() + { + $header = new IdentificationHeader('Message-ID', 'some@id'); + $headers = new Headers(); + $headers->addIdHeader('Message-ID', 'some@id'); + $this->assertEquals([$header], iterator_to_array($headers->all('message-id'))); + } + + public function testRemoveIsNotCaseSensitive() + { + $header = new IdentificationHeader('Message-ID', 'some@id'); + $headers = new Headers(); + $headers->addIdHeader('Message-ID', 'some@id'); + $headers->remove('message-id'); + $this->assertFalse($headers->has('Message-ID')); + } + + public function testToStringJoinsHeadersTogether() + { + $headers = new Headers(); + $headers->addTextHeader('Foo', 'bar'); + $headers->addTextHeader('Zip', 'buttons'); + $this->assertEquals("Foo: bar\r\nZip: buttons\r\n", $headers->toString()); + } + + public function testHeadersWithoutBodiesAreNotDisplayed() + { + $headers = new Headers(); + $headers->addTextHeader('Foo', 'bar'); + $headers->addTextHeader('Zip', ''); + $this->assertEquals("Foo: bar\r\n", $headers->toString()); + } + + public function testToArray() + { + $headers = new Headers(); + $headers->addIdHeader('Message-ID', 'some@id'); + $headers->addTextHeader('Foo', str_repeat('a', 60).pack('C', 0x8F)); + $this->assertEquals([ + 'Message-ID: <some@id>', + "Foo: =?utf-8?Q?aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa?=\r\n =?utf-8?Q?aaaa?=", + ], $headers->toArray()); + } +} diff --git a/vendor/symfony/mime/Tests/Header/IdentificationHeaderTest.php b/vendor/symfony/mime/Tests/Header/IdentificationHeaderTest.php new file mode 100644 index 0000000000000000000000000000000000000000..b7f0095d3a164fb64821637039df219a6c6f91c8 --- /dev/null +++ b/vendor/symfony/mime/Tests/Header/IdentificationHeaderTest.php @@ -0,0 +1,173 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime\Tests\Header; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Mime\Header\IdentificationHeader; + +class IdentificationHeaderTest extends TestCase +{ + public function testValueMatchesMsgIdSpec() + { + /* -- RFC 2822, 3.6.4. + message-id = "Message-ID:" msg-id CRLF + + in-reply-to = "In-Reply-To:" 1*msg-id CRLF + + references = "References:" 1*msg-id CRLF + + msg-id = [CFWS] "<" id-left "@" id-right ">" [CFWS] + + id-left = dot-atom-text / no-fold-quote / obs-id-left + + id-right = dot-atom-text / no-fold-literal / obs-id-right + + no-fold-quote = DQUOTE *(qtext / quoted-pair) DQUOTE + + no-fold-literal = "[" *(dtext / quoted-pair) "]" + */ + + $header = new IdentificationHeader('Message-ID', 'id-left@id-right'); + $this->assertEquals('<id-left@id-right>', $header->getBodyAsString()); + } + + public function testIdCanBeRetrievedVerbatim() + { + $header = new IdentificationHeader('Message-ID', 'id-left@id-right'); + $this->assertEquals('id-left@id-right', $header->getId()); + } + + public function testMultipleIdsCanBeSet() + { + $header = new IdentificationHeader('References', 'c@d'); + $header->setIds(['a@b', 'x@y']); + $this->assertEquals(['a@b', 'x@y'], $header->getIds()); + } + + public function testSettingMultipleIdsProducesAListValue() + { + /* -- RFC 2822, 3.6.4. + The "References:" and "In-Reply-To:" field each contain one or more + unique message identifiers, optionally separated by CFWS. + + .. SNIP .. + + in-reply-to = "In-Reply-To:" 1*msg-id CRLF + + references = "References:" 1*msg-id CRLF + */ + + $header = new IdentificationHeader('References', ['a@b', 'x@y']); + $this->assertEquals('<a@b> <x@y>', $header->getBodyAsString()); + } + + public function testIdLeftCanBeQuoted() + { + /* -- RFC 2822, 3.6.4. + id-left = dot-atom-text / no-fold-quote / obs-id-left + */ + + $header = new IdentificationHeader('References', '"ab"@c'); + $this->assertEquals('"ab"@c', $header->getId()); + $this->assertEquals('<"ab"@c>', $header->getBodyAsString()); + } + + public function testIdLeftCanContainAnglesAsQuotedPairs() + { + /* -- RFC 2822, 3.6.4. + no-fold-quote = DQUOTE *(qtext / quoted-pair) DQUOTE + */ + + $header = new IdentificationHeader('References', '"a\\<\\>b"@c'); + $this->assertEquals('"a\\<\\>b"@c', $header->getId()); + $this->assertEquals('<"a\\<\\>b"@c>', $header->getBodyAsString()); + } + + public function testIdLeftCanBeDotAtom() + { + $header = new IdentificationHeader('References', 'a.b+&%$.c@d'); + $this->assertEquals('a.b+&%$.c@d', $header->getId()); + $this->assertEquals('<a.b+&%$.c@d>', $header->getBodyAsString()); + } + + public function testInvalidIdLeftThrowsException() + { + $this->expectException('Exception'); + $this->expectExceptionMessage('Email "a b c@d" does not comply with addr-spec of RFC 2822.'); + $header = new IdentificationHeader('References', 'a b c@d'); + } + + public function testIdRightCanBeDotAtom() + { + /* -- RFC 2822, 3.6.4. + id-right = dot-atom-text / no-fold-literal / obs-id-right + */ + + $header = new IdentificationHeader('References', 'a@b.c+&%$.d'); + $this->assertEquals('a@b.c+&%$.d', $header->getId()); + $this->assertEquals('<a@b.c+&%$.d>', $header->getBodyAsString()); + } + + public function testIdRightCanBeLiteral() + { + /* -- RFC 2822, 3.6.4. + no-fold-literal = "[" *(dtext / quoted-pair) "]" + */ + + $header = new IdentificationHeader('References', 'a@[1.2.3.4]'); + $this->assertEquals('a@[1.2.3.4]', $header->getId()); + $this->assertEquals('<a@[1.2.3.4]>', $header->getBodyAsString()); + } + + public function testIdRigthIsIdnEncoded() + { + $header = new IdentificationHeader('References', 'a@ä'); + $this->assertEquals('a@ä', $header->getId()); + $this->assertEquals('<a@xn--4ca>', $header->getBodyAsString()); + } + + public function testInvalidIdRightThrowsException() + { + $this->expectException('Exception'); + $this->expectExceptionMessage('Email "a@b c d" does not comply with addr-spec of RFC 2822.'); + $header = new IdentificationHeader('References', 'a@b c d'); + } + + public function testMissingAtSignThrowsException() + { + $this->expectException('Exception'); + $this->expectExceptionMessage('Email "abc" does not comply with addr-spec of RFC 2822.'); + /* -- RFC 2822, 3.6.4. + msg-id = [CFWS] "<" id-left "@" id-right ">" [CFWS] + */ + $header = new IdentificationHeader('References', 'abc'); + } + + public function testSetBody() + { + $header = new IdentificationHeader('Message-ID', 'c@d'); + $header->setBody('a@b'); + $this->assertEquals(['a@b'], $header->getIds()); + } + + public function testGetBody() + { + $header = new IdentificationHeader('Message-ID', 'a@b'); + $this->assertEquals(['a@b'], $header->getBody()); + } + + public function testStringValue() + { + $header = new IdentificationHeader('References', ['a@b', 'x@y']); + $this->assertEquals('References: <a@b> <x@y>', $header->toString()); + } +} diff --git a/vendor/symfony/mime/Tests/Header/MailboxHeaderTest.php b/vendor/symfony/mime/Tests/Header/MailboxHeaderTest.php new file mode 100644 index 0000000000000000000000000000000000000000..72f22ff980260162cf0e2de76e614ad65fb581e3 --- /dev/null +++ b/vendor/symfony/mime/Tests/Header/MailboxHeaderTest.php @@ -0,0 +1,77 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime\Tests\Header; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Mime\Address; +use Symfony\Component\Mime\Header\MailboxHeader; +use Symfony\Component\Mime\NamedAddress; + +class MailboxHeaderTest extends TestCase +{ + public function testConstructor() + { + $header = new MailboxHeader('Sender', $address = new Address('fabien@symfony.com')); + $this->assertEquals($address, $header->getAddress()); + $this->assertEquals($address, $header->getBody()); + } + + public function testAddress() + { + $header = new MailboxHeader('Sender', new Address('fabien@symfony.com')); + $header->setBody($address = new Address('helene@symfony.com')); + $this->assertEquals($address, $header->getAddress()); + $this->assertEquals($address, $header->getBody()); + $header->setAddress($address = new Address('thomas@symfony.com')); + $this->assertEquals($address, $header->getAddress()); + $this->assertEquals($address, $header->getBody()); + } + + public function testgetBodyAsString() + { + $header = new MailboxHeader('Sender', new Address('fabien@symfony.com')); + $this->assertEquals('fabien@symfony.com', $header->getBodyAsString()); + + $header->setAddress(new Address('fabien@sïmfony.com')); + $this->assertEquals('fabien@xn--smfony-iwa.com', $header->getBodyAsString()); + + $header = new MailboxHeader('Sender', new NamedAddress('fabien@symfony.com', 'Fabien Potencier')); + $this->assertEquals('Fabien Potencier <fabien@symfony.com>', $header->getBodyAsString()); + + $header = new MailboxHeader('Sender', new NamedAddress('fabien@symfony.com', 'Fabien Potencier, "from Symfony"')); + $this->assertEquals('"Fabien Potencier, \"from Symfony\"" <fabien@symfony.com>', $header->getBodyAsString()); + + $header = new MailboxHeader('From', new NamedAddress('fabien@symfony.com', 'Fabien Potencier, \\escaped\\')); + $this->assertEquals('"Fabien Potencier, \\\\escaped\\\\" <fabien@symfony.com>', $header->getBodyAsString()); + + $name = 'P'.pack('C', 0x8F).'tencier'; + $header = new MailboxHeader('Sender', new NamedAddress('fabien@symfony.com', 'Fabien '.$name)); + $header->setCharset('iso-8859-1'); + $this->assertEquals('Fabien =?'.$header->getCharset().'?Q?P=8Ftencier?= <fabien@symfony.com>', $header->getBodyAsString()); + } + + public function testUtf8CharsInLocalPartThrows() + { + $this->expectException('Symfony\Component\Mime\Exception\AddressEncoderException'); + $header = new MailboxHeader('Sender', new Address('fabïen@symfony.com')); + $header->getBodyAsString(); + } + + public function testToString() + { + $header = new MailboxHeader('Sender', new Address('fabien@symfony.com')); + $this->assertEquals('Sender: fabien@symfony.com', $header->toString()); + + $header = new MailboxHeader('Sender', new NamedAddress('fabien@symfony.com', 'Fabien Potencier')); + $this->assertEquals('Sender: Fabien Potencier <fabien@symfony.com>', $header->toString()); + } +} diff --git a/vendor/symfony/mime/Tests/Header/MailboxListHeaderTest.php b/vendor/symfony/mime/Tests/Header/MailboxListHeaderTest.php new file mode 100644 index 0000000000000000000000000000000000000000..2eee1cfa8663ad1a9e6bd6096eb1393f9fed70dc --- /dev/null +++ b/vendor/symfony/mime/Tests/Header/MailboxListHeaderTest.php @@ -0,0 +1,131 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime\Tests\Header; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Mime\Address; +use Symfony\Component\Mime\Header\MailboxListHeader; +use Symfony\Component\Mime\NamedAddress; + +class MailboxListHeaderTest extends TestCase +{ + // RFC 2822, 3.6.2 for all tests + + public function testMailboxIsSetForAddress() + { + $header = new MailboxListHeader('From', [new Address('chris@swiftmailer.org')]); + $this->assertEquals(['chris@swiftmailer.org'], $header->getAddressStrings()); + } + + public function testMailboxIsRenderedForNameAddress() + { + $header = new MailboxListHeader('From', [new NamedAddress('chris@swiftmailer.org', 'Chris Corbyn')]); + $this->assertEquals(['Chris Corbyn <chris@swiftmailer.org>'], $header->getAddressStrings()); + } + + public function testAddressCanBeReturnedForAddress() + { + $header = new MailboxListHeader('From', $addresses = [new Address('chris@swiftmailer.org')]); + $this->assertEquals($addresses, $header->getAddresses()); + } + + public function testQuotesInNameAreQuoted() + { + $header = new MailboxListHeader('From', [new NamedAddress('chris@swiftmailer.org', 'Chris Corbyn, "DHE"')]); + $this->assertEquals(['"Chris Corbyn, \"DHE\"" <chris@swiftmailer.org>'], $header->getAddressStrings()); + } + + public function testEscapeCharsInNameAreQuoted() + { + $header = new MailboxListHeader('From', [new NamedAddress('chris@swiftmailer.org', 'Chris Corbyn, \\escaped\\')]); + $this->assertEquals(['"Chris Corbyn, \\\\escaped\\\\" <chris@swiftmailer.org>'], $header->getAddressStrings()); + } + + public function testUtf8CharsInDomainAreIdnEncoded() + { + $header = new MailboxListHeader('From', [new NamedAddress('chris@swïftmailer.org', 'Chris Corbyn')]); + $this->assertEquals(['Chris Corbyn <chris@xn--swftmailer-78a.org>'], $header->getAddressStrings()); + } + + public function testUtf8CharsInLocalPartThrows() + { + $this->expectException('Symfony\Component\Mime\Exception\AddressEncoderException'); + $header = new MailboxListHeader('From', [new NamedAddress('chrïs@swiftmailer.org', 'Chris Corbyn')]); + $header->getAddressStrings(); + } + + public function testGetMailboxesReturnsNameValuePairs() + { + $header = new MailboxListHeader('From', $addresses = [new NamedAddress('chris@swiftmailer.org', 'Chris Corbyn, DHE')]); + $this->assertEquals($addresses, $header->getAddresses()); + } + + public function testMultipleAddressesAsMailboxStrings() + { + $header = new MailboxListHeader('From', [new Address('chris@swiftmailer.org'), new Address('mark@swiftmailer.org')]); + $this->assertEquals(['chris@swiftmailer.org', 'mark@swiftmailer.org'], $header->getAddressStrings()); + } + + public function testNameIsEncodedIfNonAscii() + { + $name = 'C'.pack('C', 0x8F).'rbyn'; + $header = new MailboxListHeader('From', [new NamedAddress('chris@swiftmailer.org', 'Chris '.$name)]); + $header->setCharset('iso-8859-1'); + $addresses = $header->getAddressStrings(); + $this->assertEquals('Chris =?'.$header->getCharset().'?Q?C=8Frbyn?= <chris@swiftmailer.org>', array_shift($addresses)); + } + + public function testEncodingLineLengthCalculations() + { + /* -- RFC 2047, 2. + An 'encoded-word' may not be more than 75 characters long, including + 'charset', 'encoding', 'encoded-text', and delimiters. + */ + + $name = 'C'.pack('C', 0x8F).'rbyn'; + $header = new MailboxListHeader('From', [new NamedAddress('chris@swiftmailer.org', 'Chris '.$name)]); + $header->setCharset('iso-8859-1'); + $addresses = $header->getAddressStrings(); + $this->assertEquals('Chris =?'.$header->getCharset().'?Q?C=8Frbyn?= <chris@swiftmailer.org>', array_shift($addresses)); + } + + public function testGetValueReturnsMailboxStringValue() + { + $header = new MailboxListHeader('From', [new NamedAddress('chris@swiftmailer.org', 'Chris Corbyn')]); + $this->assertEquals('Chris Corbyn <chris@swiftmailer.org>', $header->getBodyAsString()); + } + + public function testGetValueReturnsMailboxStringValueForMultipleMailboxes() + { + $header = new MailboxListHeader('From', [new NamedAddress('chris@swiftmailer.org', 'Chris Corbyn'), new NamedAddress('mark@swiftmailer.org', 'Mark Corbyn')]); + $this->assertEquals('Chris Corbyn <chris@swiftmailer.org>, Mark Corbyn <mark@swiftmailer.org>', $header->getBodyAsString()); + } + + public function testSetBody() + { + $header = new MailboxListHeader('From', []); + $header->setBody($addresses = [new Address('chris@swiftmailer.org')]); + $this->assertEquals($addresses, $header->getAddresses()); + } + + public function testGetBody() + { + $header = new MailboxListHeader('From', $addresses = [new Address('chris@swiftmailer.org')]); + $this->assertEquals($addresses, $header->getBody()); + } + + public function testToString() + { + $header = new MailboxListHeader('From', [new NamedAddress('chris@example.org', 'Chris Corbyn'), new NamedAddress('mark@example.org', 'Mark Corbyn')]); + $this->assertEquals('From: Chris Corbyn <chris@example.org>, Mark Corbyn <mark@example.org>', $header->toString()); + } +} diff --git a/vendor/symfony/mime/Tests/Header/ParameterizedHeaderTest.php b/vendor/symfony/mime/Tests/Header/ParameterizedHeaderTest.php new file mode 100644 index 0000000000000000000000000000000000000000..e41d03857df08fc069386dfb83b7d07769c77e49 --- /dev/null +++ b/vendor/symfony/mime/Tests/Header/ParameterizedHeaderTest.php @@ -0,0 +1,295 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime\Tests\Header; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Mime\Header\ParameterizedHeader; + +class ParameterizedHeaderTest extends TestCase +{ + private $charset = 'utf-8'; + private $lang = 'en-us'; + + public function testValueIsReturnedVerbatim() + { + $header = new ParameterizedHeader('Content-Type', 'text/plain'); + $this->assertEquals('text/plain', $header->getValue()); + } + + public function testParametersAreAppended() + { + /* -- RFC 2045, 5.1 + parameter := attribute "=" value + + attribute := token + ; Matching of attributes + ; is ALWAYS case-insensitive. + + value := token / quoted-string + + token := 1*<any (US-ASCII) CHAR except SPACE, CTLs, + or tspecials> + + tspecials := "(" / ")" / "<" / ">" / "@" / + "," / ";" / ":" / "\" / <"> + "/" / "[" / "]" / "?" / "=" + ; Must be in quoted-string, + ; to use within parameter values + */ + + $header = new ParameterizedHeader('Content-Type', 'text/plain'); + $header->setParameters(['charset' => 'utf-8']); + $this->assertEquals('text/plain; charset=utf-8', $header->getBodyAsString()); + } + + public function testSpaceInParamResultsInQuotedString() + { + $header = new ParameterizedHeader('Content-Type', 'attachment'); + $header->setParameters(['filename' => 'my file.txt']); + $this->assertEquals('attachment; filename="my file.txt"', $header->getBodyAsString()); + } + + public function testLongParamsAreBrokenIntoMultipleAttributeStrings() + { + /* -- RFC 2231, 3. + The asterisk character ("*") followed + by a decimal count is employed to indicate that multiple parameters + are being used to encapsulate a single parameter value. The count + starts at 0 and increments by 1 for each subsequent section of the + parameter value. Decimal values are used and neither leading zeroes + nor gaps in the sequence are allowed. + + The original parameter value is recovered by concatenating the + various sections of the parameter, in order. For example, the + content-type field + + Content-Type: message/external-body; access-type=URL; + URL*0="ftp://"; + URL*1="cs.utk.edu/pub/moore/bulk-mailer/bulk-mailer.tar" + + is semantically identical to + + Content-Type: message/external-body; access-type=URL; + URL="ftp://cs.utk.edu/pub/moore/bulk-mailer/bulk-mailer.tar" + + Note that quotes around parameter values are part of the value + syntax; they are NOT part of the value itself. Furthermore, it is + explicitly permitted to have a mixture of quoted and unquoted + continuation fields. + */ + + $value = str_repeat('a', 180); + + $header = new ParameterizedHeader('Content-Disposition', 'attachment'); + $header->setParameters(['filename' => $value]); + $this->assertEquals( + 'attachment; '. + 'filename*0*=utf-8\'\''.str_repeat('a', 60).";\r\n ". + 'filename*1*='.str_repeat('a', 60).";\r\n ". + 'filename*2*='.str_repeat('a', 60), + $header->getBodyAsString() + ); + } + + public function testEncodedParamDataIncludesCharsetAndLanguage() + { + /* -- RFC 2231, 4. + Asterisks ("*") are reused to provide the indicator that language and + character set information is present and encoding is being used. A + single quote ("'") is used to delimit the character set and language + information at the beginning of the parameter value. Percent signs + ("%") are used as the encoding flag, which agrees with RFC 2047. + + Specifically, an asterisk at the end of a parameter name acts as an + indicator that character set and language information may appear at + the beginning of the parameter value. A single quote is used to + separate the character set, language, and actual value information in + the parameter value string, and an percent sign is used to flag + octets encoded in hexadecimal. For example: + + Content-Type: application/x-stuff; + title*=us-ascii'en-us'This%20is%20%2A%2A%2Afun%2A%2A%2A + + Note that it is perfectly permissible to leave either the character + set or language field blank. Note also that the single quote + delimiters MUST be present even when one of the field values is + omitted. + */ + + $value = str_repeat('a', 20).pack('C', 0x8F).str_repeat('a', 10); + $header = new ParameterizedHeader('Content-Disposition', 'attachment'); + $header->setCharset('iso-8859-1'); + $header->setValue('attachment'); + $header->setParameters(['filename' => $value]); + $header->setLanguage($this->lang); + $this->assertEquals( + 'attachment; filename*='.$header->getCharset()."'".$this->lang."'". + str_repeat('a', 20).'%8F'.str_repeat('a', 10), + $header->getBodyAsString() + ); + } + + public function testMultipleEncodedParamLinesAreFormattedCorrectly() + { + /* -- RFC 2231, 4.1. + Character set and language information may be combined with the + parameter continuation mechanism. For example: + + Content-Type: application/x-stuff + title*0*=us-ascii'en'This%20is%20even%20more%20 + title*1*=%2A%2A%2Afun%2A%2A%2A%20 + title*2="isn't it!" + + Note that: + + (1) Language and character set information only appear at + the beginning of a given parameter value. + + (2) Continuations do not provide a facility for using more + than one character set or language in the same + parameter value. + + (3) A value presented using multiple continuations may + contain a mixture of encoded and unencoded segments. + + (4) The first segment of a continuation MUST be encoded if + language and character set information are given. + + (5) If the first segment of a continued parameter value is + encoded the language and character set field delimiters + MUST be present even when the fields are left blank. + */ + + $value = str_repeat('a', 20).pack('C', 0x8F).str_repeat('a', 60); + $header = new ParameterizedHeader('Content-Disposition', 'attachment'); + $header->setValue('attachment'); + $header->setCharset('utf-6'); + $header->setParameters(['filename' => $value]); + $header->setLanguage($this->lang); + $this->assertEquals( + 'attachment; filename*0*='.$header->getCharset()."'".$this->lang."'". + str_repeat('a', 20).'%8F'.str_repeat('a', 23).";\r\n ". + 'filename*1*='.str_repeat('a', 37), + $header->getBodyAsString() + ); + } + + public function testToString() + { + $header = new ParameterizedHeader('Content-Type', 'text/html'); + $header->setParameters(['charset' => 'utf-8']); + $this->assertEquals('Content-Type: text/html; charset=utf-8', $header->toString()); + } + + public function testValueCanBeEncodedIfNonAscii() + { + $value = 'fo'.pack('C', 0x8F).'bar'; + $header = new ParameterizedHeader('X-Foo', $value); + $header->setCharset('iso-8859-1'); + $header->setParameters(['lookslike' => 'foobar']); + $this->assertEquals('X-Foo: =?'.$header->getCharset().'?Q?fo=8Fbar?=; lookslike=foobar', $header->toString()); + } + + public function testValueAndParamCanBeEncodedIfNonAscii() + { + $value = 'fo'.pack('C', 0x8F).'bar'; + $header = new ParameterizedHeader('X-Foo', $value); + $header->setCharset('iso-8859-1'); + $header->setParameters(['says' => $value]); + $this->assertEquals('X-Foo: =?'.$header->getCharset().'?Q?fo=8Fbar?=; says*='.$header->getCharset()."''fo%8Fbar", $header->toString()); + } + + public function testParamsAreEncodedIfNonAscii() + { + $value = 'fo'.pack('C', 0x8F).'bar'; + $header = new ParameterizedHeader('X-Foo', 'bar'); + $header->setCharset('iso-8859-1'); + $header->setParameters(['says' => $value]); + $this->assertEquals('X-Foo: bar; says*='.$header->getCharset()."''fo%8Fbar", $header->toString()); + } + + public function testParamsAreEncodedWithLegacyEncodingEnabled() + { + $value = 'fo'.pack('C', 0x8F).'bar'; + $header = new ParameterizedHeader('Content-Type', 'bar'); + $header->setCharset('iso-8859-1'); + $header->setParameters(['says' => $value]); + $this->assertEquals('Content-Type: bar; says="=?'.$header->getCharset().'?Q?fo=8Fbar?="', $header->toString()); + } + + public function testLanguageInformationAppearsInEncodedWords() + { + /* -- RFC 2231, 5. + 5. Language specification in Encoded Words + + RFC 2047 provides support for non-US-ASCII character sets in RFC 822 + message header comments, phrases, and any unstructured text field. + This is done by defining an encoded word construct which can appear + in any of these places. Given that these are fields intended for + display, it is sometimes necessary to associate language information + with encoded words as well as just the character set. This + specification extends the definition of an encoded word to allow the + inclusion of such information. This is simply done by suffixing the + character set specification with an asterisk followed by the language + tag. For example: + + From: =?US-ASCII*EN?Q?Keith_Moore?= <moore@cs.utk.edu> + + -- RFC 2047, 5. Use of encoded-words in message headers + ... + + An 'encoded-word' MUST NOT be used in parameter of a MIME + Content-Type or Content-Disposition field, or in any structured + field body except within a 'comment' or 'phrase'. + + -- RFC 2047, Appendix - changes since RFC 1522 + ... + + clarify that encoded-words are allowed in '*text' fields in both + RFC822 headers and MIME body part headers, but NOT as parameter + values. + */ + + $value = 'fo'.pack('C', 0x8F).'bar'; + $header = new ParameterizedHeader('X-Foo', $value); + $header->setCharset('iso-8859-1'); + $header->setLanguage('en'); + $header->setParameters(['says' => $value]); + $this->assertEquals('X-Foo: =?'.$header->getCharset().'*en?Q?fo=8Fbar?=; says*='.$header->getCharset()."'en'fo%8Fbar", $header->toString()); + } + + public function testSetBody() + { + $header = new ParameterizedHeader('Content-Type', 'text/html'); + $header->setBody('text/plain'); + $this->assertEquals('text/plain', $header->getValue()); + } + + public function testGetBody() + { + $header = new ParameterizedHeader('Content-Type', 'text/plain'); + $this->assertEquals('text/plain', $header->getBody()); + } + + public function testSetParameter() + { + $header = new ParameterizedHeader('Content-Type', 'text/html'); + $header->setParameters(['charset' => 'utf-8', 'delsp' => 'yes']); + $header->setParameter('delsp', 'no'); + $this->assertEquals(['charset' => 'utf-8', 'delsp' => 'no'], $header->getParameters()); + } + + public function testGetParameter() + { + $header = new ParameterizedHeader('Content-Type', 'text/html'); + $header->setParameters(['charset' => 'utf-8', 'delsp' => 'yes']); + $this->assertEquals('utf-8', $header->getParameter('charset')); + } +} diff --git a/vendor/symfony/mime/Tests/Header/PathHeaderTest.php b/vendor/symfony/mime/Tests/Header/PathHeaderTest.php new file mode 100644 index 0000000000000000000000000000000000000000..6bc029aee4cea3b9fba67ec879f424d80a7ff6f1 --- /dev/null +++ b/vendor/symfony/mime/Tests/Header/PathHeaderTest.php @@ -0,0 +1,77 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime\Tests\Header; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Mime\Address; +use Symfony\Component\Mime\Header\PathHeader; + +class PathHeaderTest extends TestCase +{ + public function testSingleAddressCanBeSetAndFetched() + { + $header = new PathHeader('Return-Path', $address = new Address('chris@swiftmailer.org')); + $this->assertEquals($address, $header->getAddress()); + } + + public function testAddressMustComplyWithRfc2822() + { + $this->expectException('Exception'); + $header = new PathHeader('Return-Path', new Address('chr is@swiftmailer.org')); + } + + public function testValueIsAngleAddrWithValidAddress() + { + /* -- RFC 2822, 3.6.7. + + return = "Return-Path:" path CRLF + + path = ([CFWS] "<" ([CFWS] / addr-spec) ">" [CFWS]) / + obs-path + */ + + $header = new PathHeader('Return-Path', new Address('chris@swiftmailer.org')); + $this->assertEquals('<chris@swiftmailer.org>', $header->getBodyAsString()); + } + + public function testAddressIsIdnEncoded() + { + $header = new PathHeader('Return-Path', new Address('chris@swïftmailer.org')); + $this->assertEquals('<chris@xn--swftmailer-78a.org>', $header->getBodyAsString()); + } + + public function testAddressMustBeEncodable() + { + $this->expectException('Symfony\Component\Mime\Exception\AddressEncoderException'); + $header = new PathHeader('Return-Path', new Address('chrïs@swiftmailer.org')); + $header->getBodyAsString(); + } + + public function testSetBody() + { + $header = new PathHeader('Return-Path', new Address('foo@example.com')); + $header->setBody($address = new Address('foo@bar.tld')); + $this->assertEquals($address, $header->getAddress()); + } + + public function testGetBody() + { + $header = new PathHeader('Return-Path', $address = new Address('foo@bar.tld')); + $this->assertEquals($address, $header->getBody()); + } + + public function testToString() + { + $header = new PathHeader('Return-Path', new Address('chris@swiftmailer.org')); + $this->assertEquals('Return-Path: <chris@swiftmailer.org>', $header->toString()); + } +} diff --git a/vendor/symfony/mime/Tests/Header/UnstructuredHeaderTest.php b/vendor/symfony/mime/Tests/Header/UnstructuredHeaderTest.php new file mode 100644 index 0000000000000000000000000000000000000000..3e065bf268a795552f720eb2d168e6eaa7bd0672 --- /dev/null +++ b/vendor/symfony/mime/Tests/Header/UnstructuredHeaderTest.php @@ -0,0 +1,247 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime\Tests\Header; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Mime\Header\UnstructuredHeader; + +class UnstructuredHeaderTest extends TestCase +{ + private $charset = 'utf-8'; + + public function testGetNameReturnsNameVerbatim() + { + $header = new UnstructuredHeader('Subject', ''); + $this->assertEquals('Subject', $header->getName()); + } + + public function testGetValueReturnsValueVerbatim() + { + $header = new UnstructuredHeader('Subject', 'Test'); + $this->assertEquals('Test', $header->getValue()); + } + + public function testBasicStructureIsKeyValuePair() + { + /* -- RFC 2822, 2.2 + Header fields are lines composed of a field name, followed by a colon + (":"), followed by a field body, and terminated by CRLF. + */ + $header = new UnstructuredHeader('Subject', 'Test'); + $this->assertEquals('Subject: Test', $header->toString()); + } + + public function testLongHeadersAreFoldedAtWordBoundary() + { + /* -- RFC 2822, 2.2.3 + Each header field is logically a single line of characters comprising + the field name, the colon, and the field body. For convenience + however, and to deal with the 998/78 character limitations per line, + the field body portion of a header field can be split into a multiple + line representation; this is called "folding". The general rule is + that wherever this standard allows for folding white space (not + simply WSP characters), a CRLF may be inserted before any WSP. + */ + + $value = 'The quick brown fox jumped over the fence, he was a very very '. + 'scary brown fox with a bushy tail'; + $header = new UnstructuredHeader('X-Custom-Header', $value); + /* + X-Custom-Header: The quick brown fox jumped over the fence, he was a very very + scary brown fox with a bushy tail + */ + $this->assertEquals( + 'X-Custom-Header: The quick brown fox jumped over the fence, he was a'. + ' very'."\r\n".//Folding + ' very scary brown fox with a bushy tail', + $header->toString(), '%s: The header should have been folded at 76th char' + ); + } + + public function testPrintableAsciiOnlyAppearsInHeaders() + { + /* -- RFC 2822, 2.2. + A field name MUST be composed of printable US-ASCII characters (i.e., + characters that have values between 33 and 126, inclusive), except + colon. A field body may be composed of any US-ASCII characters, + except for CR and LF. + */ + + $nonAsciiChar = pack('C', 0x8F); + $header = new UnstructuredHeader('X-Test', $nonAsciiChar); + $this->assertRegExp('~^[^:\x00-\x20\x80-\xFF]+: [^\x80-\xFF\r\n]+$~s', $header->toString()); + } + + public function testEncodedWordsFollowGeneralStructure() + { + /* -- RFC 2047, 1. + Generally, an "encoded-word" is a sequence of printable ASCII + characters that begins with "=?", ends with "?=", and has two "?"s in + between. + */ + + $nonAsciiChar = pack('C', 0x8F); + $header = new UnstructuredHeader('X-Test', $nonAsciiChar); + $this->assertRegExp('~^X-Test: \=?.*?\?.*?\?.*?\?=$~s', $header->toString()); + } + + public function testEncodedWordIncludesCharsetAndEncodingMethodAndText() + { + /* -- RFC 2047, 2. + An 'encoded-word' is defined by the following ABNF grammar. The + notation of RFC 822 is used, with the exception that white space + characters MUST NOT appear between components of an 'encoded-word'. + + encoded-word = "=?" charset "?" encoding "?" encoded-text "?=" + */ + + $nonAsciiChar = pack('C', 0x8F); + $header = new UnstructuredHeader('X-Test', $nonAsciiChar); + $header->setCharset('iso-8859-1'); + $this->assertEquals('X-Test: =?'.$header->getCharset().'?Q?=8F?=', $header->toString()); + } + + public function testEncodedWordsAreUsedToEncodedNonPrintableAscii() + { + // SPACE and TAB permitted + $nonPrintableBytes = array_merge(range(0x00, 0x08), range(0x10, 0x19), [0x7F]); + foreach ($nonPrintableBytes as $byte) { + $char = pack('C', $byte); + $encodedChar = sprintf('=%02X', $byte); + $header = new UnstructuredHeader('X-A', $char); + $header->setCharset('iso-8859-1'); + $this->assertEquals('X-A: =?'.$header->getCharset().'?Q?'.$encodedChar.'?=', $header->toString(), 'Non-printable ascii should be encoded'); + } + } + + public function testEncodedWordsAreUsedToEncode8BitOctets() + { + foreach (range(0x80, 0xFF) as $byte) { + $char = pack('C', $byte); + $encodedChar = sprintf('=%02X', $byte); + $header = new UnstructuredHeader('X-A', $char); + $header->setCharset('iso-8859-1'); + $this->assertEquals('X-A: =?'.$header->getCharset().'?Q?'.$encodedChar.'?=', $header->toString(), '8-bit octets should be encoded'); + } + } + + public function testEncodedWordsAreNoMoreThan75CharsPerLine() + { + /* -- RFC 2047, 2. + An 'encoded-word' may not be more than 75 characters long, including + 'charset', 'encoding', 'encoded-text', and delimiters. + + ... SNIP ... + + While there is no limit to the length of a multiple-line header + field, each line of a header field that contains one or more + 'encoded-word's is limited to 76 characters. + */ + + $nonAsciiChar = pack('C', 0x8F); + + //Note that multi-line headers begin with LWSP which makes 75 + 1 = 76 + //Note also that =?utf-8?q??= is 12 chars which makes 75 - 12 = 63 + + //* X-Test: is 8 chars + $header = new UnstructuredHeader('X-Test', $nonAsciiChar); + $header->setCharset('iso-8859-1'); + $this->assertEquals('X-Test: =?'.$header->getCharset().'?Q?=8F?=', $header->toString()); + } + + public function testFWSPIsUsedWhenEncoderReturnsMultipleLines() + { + /* --RFC 2047, 2. + If it is desirable to encode more text than will fit in an 'encoded-word' of + 75 characters, multiple 'encoded-word's (separated by CRLF SPACE) may + be used. + */ + + // Note that multi-line headers begin with LWSP which makes 75 + 1 = 76 + // Note also that =?utf-8?q??= is 12 chars which makes 75 - 12 = 63 + + //* X-Test: is 8 chars + $header = new UnstructuredHeader('X-Test', pack('C', 0x8F).'line_one_here'."\r\n".'line_two_here'); + $header->setCharset('iso-8859-1'); + $this->assertEquals('X-Test: =?'.$header->getCharset().'?Q?=8Fline=5Fone=5Fhere?='."\r\n".' =?'.$header->getCharset().'?Q?line=5Ftwo=5Fhere?=', $header->toString()); + } + + public function testAdjacentWordsAreEncodedTogether() + { + /* -- RFC 2047, 5 (1) + Ordinary ASCII text and 'encoded-word's may appear together in the + same header field. However, an 'encoded-word' that appears in a + header field defined as '*text' MUST be separated from any adjacent + 'encoded-word' or 'text' by 'linear-white-space'. + + -- RFC 2047, 2. + IMPORTANT: 'encoded-word's are designed to be recognized as 'atom's + by an RFC 822 parser. As a consequence, unencoded white space + characters (such as SPACE and HTAB) are FORBIDDEN within an + 'encoded-word'. + */ + + // It would be valid to encode all words needed, however it's probably + // easiest to encode the longest amount required at a time + + $word = 'w'.pack('C', 0x8F).'rd'; + $text = 'start '.$word.' '.$word.' then '.$word; + // 'start', ' word word', ' and end', ' word' + + $header = new UnstructuredHeader('X-Test', $text); + $header->setCharset('iso-8859-1'); + $this->assertEquals('X-Test: start =?'.$header->getCharset().'?Q?'. + 'w=8Frd_w=8Frd?= then =?'.$header->getCharset().'?Q?'. + 'w=8Frd?=', $header->toString(), + 'Adjacent encoded words should appear grouped with WSP encoded' + ); + } + + public function testLanguageInformationAppearsInEncodedWords() + { + /* -- RFC 2231, 5. + 5. Language specification in Encoded Words + + RFC 2047 provides support for non-US-ASCII character sets in RFC 822 + message header comments, phrases, and any unstructured text field. + This is done by defining an encoded word construct which can appear + in any of these places. Given that these are fields intended for + display, it is sometimes necessary to associate language information + with encoded words as well as just the character set. This + specification extends the definition of an encoded word to allow the + inclusion of such information. This is simply done by suffixing the + character set specification with an asterisk followed by the language + tag. For example: + + From: =?US-ASCII*EN?Q?Keith_Moore?= <moore@cs.utk.edu> + */ + + $value = 'fo'.pack('C', 0x8F).'bar'; + $header = new UnstructuredHeader('Subject', $value); + $header->setLanguage('en'); + $header->setCharset('iso-8859-1'); + $this->assertEquals('Subject: =?iso-8859-1*en?Q?fo=8Fbar?=', $header->toString()); + } + + public function testSetBody() + { + $header = new UnstructuredHeader('X-Test', ''); + $header->setBody('test'); + $this->assertEquals('test', $header->getValue()); + } + + public function testGetBody() + { + $header = new UnstructuredHeader('Subject', 'test'); + $this->assertEquals('test', $header->getBody()); + } +} diff --git a/vendor/symfony/mime/Tests/MessageConverterTest.php b/vendor/symfony/mime/Tests/MessageConverterTest.php new file mode 100644 index 0000000000000000000000000000000000000000..6a780862463776be8bc25cb90819eed1604ad9eb --- /dev/null +++ b/vendor/symfony/mime/Tests/MessageConverterTest.php @@ -0,0 +1,81 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime\Tests; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Mime\Email; +use Symfony\Component\Mime\Message; +use Symfony\Component\Mime\MessageConverter; + +class MessageConverterTest extends TestCase +{ + public function testToEmail() + { + $file = file_get_contents(__DIR__.'/Fixtures/mimetypes/test.gif'); + $email = (new Email())->from('fabien@symfony.com'); + $this->assertSame($email, MessageConverter::toEmail($email)); + + $this->assertConversion((clone $email)->text('text content')); + $this->assertConversion((clone $email)->html('HTML content <img src="cid:test.jpg" />')); + $this->assertConversion((clone $email) + ->text('text content') + ->html('HTML content <img src="cid:test.jpg" />') + ); + $this->assertConversion((clone $email) + ->text('text content') + ->html('HTML content <img src="cid:test.jpg" />') + ->embed($file, 'test.jpg', 'image/gif') + ); + $this->assertConversion((clone $email) + ->text('text content') + ->html('HTML content <img src="cid:test.jpg" />') + ->attach($file, 'test_attached.jpg', 'image/gif') + ); + $this->assertConversion((clone $email) + ->text('text content') + ->html('HTML content <img src="cid:test.jpg" />') + ->embed($file, 'test.jpg', 'image/gif') + ->attach($file, 'test_attached.jpg', 'image/gif') + ); + $this->assertConversion((clone $email) + ->text('text content') + ->attach($file, 'test_attached.jpg', 'image/gif') + ); + $this->assertConversion((clone $email) + ->html('HTML content <img src="cid:test.jpg" />') + ->attach($file, 'test_attached.jpg', 'image/gif') + ); + $this->assertConversion((clone $email) + ->html('HTML content <img src="cid:test.jpg" />') + ->embed($file, 'test.jpg', 'image/gif') + ); + $this->assertConversion((clone $email) + ->text('text content') + ->embed($file, 'test_attached.jpg', 'image/gif') + ); + } + + private function assertConversion(Email $expected) + { + $r = new \ReflectionMethod($expected, 'generateBody'); + $r->setAccessible(true); + + $message = new Message($expected->getHeaders(), $r->invoke($expected)); + $converted = MessageConverter::toEmail($message); + if ($expected->getHtmlBody()) { + $this->assertStringMatchesFormat(str_replace('cid:test.jpg', 'cid:%s', $expected->getHtmlBody()), $converted->getHtmlBody()); + $expected->html('HTML content'); + $converted->html('HTML content'); + } + $this->assertEquals($expected, $converted); + } +} diff --git a/vendor/symfony/mime/Tests/MessageTest.php b/vendor/symfony/mime/Tests/MessageTest.php new file mode 100644 index 0000000000000000000000000000000000000000..cc806b919e3f9cae5f7194de387f37251a20766f --- /dev/null +++ b/vendor/symfony/mime/Tests/MessageTest.php @@ -0,0 +1,151 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime\Tests; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Mime\Address; +use Symfony\Component\Mime\Header\Headers; +use Symfony\Component\Mime\Header\MailboxListHeader; +use Symfony\Component\Mime\Header\UnstructuredHeader; +use Symfony\Component\Mime\Message; +use Symfony\Component\Mime\NamedAddress; +use Symfony\Component\Mime\Part\TextPart; + +class MessageTest extends TestCase +{ + public function testConstruct() + { + $m = new Message(); + $this->assertNull($m->getBody()); + $this->assertEquals(new Headers(), $m->getHeaders()); + + $m = new Message($h = (new Headers())->addDateHeader('Date', new \DateTime()), $b = new TextPart('content')); + $this->assertSame($b, $m->getBody()); + $this->assertEquals($h, $m->getHeaders()); + + $m = new Message(); + $m->setBody($b); + $m->setHeaders($h); + $this->assertSame($b, $m->getBody()); + $this->assertSame($h, $m->getHeaders()); + } + + public function testGetPreparedHeadersThrowsWhenNoFrom() + { + $this->expectException(\LogicException::class); + (new Message())->getPreparedHeaders(); + } + + public function testGetPreparedHeadersCloneHeaders() + { + $message = new Message(); + $message->getHeaders()->addMailboxListHeader('From', ['fabien@symfony.com']); + $this->assertNotSame($message->getPreparedHeaders(), $message->getHeaders()); + } + + public function testGetPreparedHeadersSetRequiredHeaders() + { + $message = new Message(); + $message->getHeaders()->addMailboxListHeader('From', ['fabien@symfony.com']); + $headers = $message->getPreparedHeaders(); + $this->assertTrue($headers->has('MIME-Version')); + $this->assertTrue($headers->has('Message-ID')); + $this->assertTrue($headers->has('Date')); + $this->assertFalse($headers->has('Bcc')); + } + + public function testGetPreparedHeaders() + { + $message = new Message(); + $message->getHeaders()->addMailboxListHeader('From', ['fabien@symfony.com']); + $h = $message->getPreparedHeaders(); + $this->assertCount(4, iterator_to_array($h->all())); + $this->assertEquals(new MailboxListHeader('From', [new Address('fabien@symfony.com')]), $h->get('From')); + $this->assertEquals(new UnstructuredHeader('MIME-Version', '1.0'), $h->get('mime-version')); + $this->assertTrue($h->has('Message-Id')); + $this->assertTrue($h->has('Date')); + + $message = new Message(); + $message->getHeaders()->addMailboxListHeader('From', ['fabien@symfony.com']); + $message->getHeaders()->addDateHeader('Date', $n = new \DateTimeImmutable()); + $this->assertEquals($n, $message->getPreparedHeaders()->get('Date')->getDateTime()); + + $message = new Message(); + $message->getHeaders()->addMailboxListHeader('From', ['fabien@symfony.com']); + $message->getHeaders()->addMailboxListHeader('Bcc', ['fabien@symfony.com']); + $this->assertNull($message->getPreparedHeaders()->get('Bcc')); + } + + public function testGetPreparedHeadersWithNoFrom() + { + $this->expectException(\LogicException::class); + (new Message())->getPreparedHeaders(); + } + + public function testGetPreparedHeadersWithNamedFrom() + { + $message = new Message(); + $message->getHeaders()->addMailboxListHeader('From', [new NamedAddress('fabien@symfony.com', 'Fabien')]); + $h = $message->getPreparedHeaders(); + $this->assertEquals(new MailboxListHeader('From', [new NamedAddress('fabien@symfony.com', 'Fabien')]), $h->get('From')); + $this->assertTrue($h->has('Message-Id')); + } + + public function testGetPreparedHeadersHasSenderWhenNeeded() + { + $message = new Message(); + $message->getHeaders()->addMailboxListHeader('From', ['fabien@symfony.com']); + $this->assertNull($message->getPreparedHeaders()->get('Sender')); + + $message = new Message(); + $message->getHeaders()->addMailboxListHeader('From', ['fabien@symfony.com', 'lucas@symfony.com']); + $this->assertEquals('fabien@symfony.com', $message->getPreparedHeaders()->get('Sender')->getAddress()->getAddress()); + + $message = new Message(); + $message->getHeaders()->addMailboxListHeader('From', ['fabien@symfony.com', 'lucas@symfony.com']); + $message->getHeaders()->addMailboxHeader('Sender', 'thomas@symfony.com'); + $this->assertEquals('thomas@symfony.com', $message->getPreparedHeaders()->get('Sender')->getAddress()->getAddress()); + } + + public function testToString() + { + $message = new Message(); + $message->getHeaders()->addMailboxListHeader('From', ['fabien@symfony.com']); + $expected = <<<EOF +From: fabien@symfony.com +MIME-Version: 1.0 +Date: %s +Message-ID: <%s@symfony.com> +Content-Type: text/plain; charset=utf-8 +Content-Transfer-Encoding: quoted-printable + + +EOF; + $this->assertStringMatchesFormat($expected, str_replace("\r\n", "\n", $message->toString())); + $this->assertStringMatchesFormat($expected, str_replace("\r\n", "\n", implode('', iterator_to_array($message->toIterable(), false)))); + + $message = new Message(null, new TextPart('content')); + $message->getHeaders()->addMailboxListHeader('From', ['fabien@symfony.com']); + $expected = <<<EOF +From: fabien@symfony.com +MIME-Version: 1.0 +Date: %s +Message-ID: <%s@symfony.com> +Content-Type: text/plain; charset=utf-8 +Content-Transfer-Encoding: quoted-printable + +content +EOF; + $this->assertStringMatchesFormat($expected, str_replace("\r\n", "\n", $message->toString())); + $this->assertStringMatchesFormat($expected, str_replace("\r\n", "\n", implode('', iterator_to_array($message->toIterable(), false)))); + } +} diff --git a/vendor/symfony/mime/Tests/MimeTypesTest.php b/vendor/symfony/mime/Tests/MimeTypesTest.php new file mode 100644 index 0000000000000000000000000000000000000000..c5ff262b80ffabfe367b4dee9b565661427dda86 --- /dev/null +++ b/vendor/symfony/mime/Tests/MimeTypesTest.php @@ -0,0 +1,61 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime\Tests; + +use Symfony\Component\Mime\Exception\RuntimeException; +use Symfony\Component\Mime\MimeTypeGuesserInterface; +use Symfony\Component\Mime\MimeTypes; + +/** + * @requires extension fileinfo + */ +class MimeTypesTest extends AbstractMimeTypeGuesserTest +{ + protected function getGuesser(): MimeTypeGuesserInterface + { + return new MimeTypes(); + } + + public function testUnsupportedGuesser() + { + $guesser = $this->getGuesser(); + $guesser->registerGuesser(new class() implements MimeTypeGuesserInterface { + public function isGuesserSupported(): bool + { + return false; + } + + public function guessMimeType(string $mimeType): ?string + { + throw new RuntimeException('Should never be called.'); + } + }); + $this->assertEquals('image/gif', $guesser->guessMimeType(__DIR__.'/Fixtures/mimetypes/test')); + } + + public function testGetExtensions() + { + $mt = new MimeTypes(); + $this->assertSame(['mbox'], $mt->getExtensions('application/mbox')); + $this->assertSame(['ai', 'eps', 'ps'], $mt->getExtensions('application/postscript')); + $this->assertSame([], $mt->getExtensions('application/whatever-symfony')); + } + + public function testGetMimeTypes() + { + $mt = new MimeTypes(); + $this->assertSame(['application/mbox'], $mt->getMimeTypes('mbox')); + $this->assertContains('application/postscript', $mt->getMimeTypes('ai')); + $this->assertContains('application/postscript', $mt->getMimeTypes('ps')); + $this->assertSame([], $mt->getMimeTypes('symfony')); + } +} diff --git a/vendor/symfony/mime/Tests/NamedAddressTest.php b/vendor/symfony/mime/Tests/NamedAddressTest.php new file mode 100644 index 0000000000000000000000000000000000000000..b793cbbaf843dccb4c9daf251a6175e30ae81d02 --- /dev/null +++ b/vendor/symfony/mime/Tests/NamedAddressTest.php @@ -0,0 +1,42 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime\Tests; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Mime\NamedAddress; + +class NamedAddressTest extends TestCase +{ + public function testConstructor() + { + $a = new NamedAddress('fabien@symfonï.com', 'Fabien'); + $this->assertEquals('Fabien', $a->getName()); + $this->assertEquals('fabien@symfonï.com', $a->getAddress()); + $this->assertEquals('Fabien <fabien@xn--symfon-nwa.com>', $a->toString()); + $this->assertEquals('fabien@xn--symfon-nwa.com', $a->getEncodedAddress()); + } + + public function nameEmptyDataProvider(): array + { + return [[''], [' '], [" \r\n "]]; + } + + /** + * @dataProvider nameEmptyDataProvider + */ + public function testNameEmpty(string $name) + { + $mail = 'mail@example.org'; + + $this->assertSame($mail, (new NamedAddress($mail, $name))->getEncodedNamedAddress()); + } +} diff --git a/vendor/symfony/mime/Tests/Part/DataPartTest.php b/vendor/symfony/mime/Tests/Part/DataPartTest.php new file mode 100644 index 0000000000000000000000000000000000000000..d8a08a24303c24c7241c37150cb3949717ecc7c4 --- /dev/null +++ b/vendor/symfony/mime/Tests/Part/DataPartTest.php @@ -0,0 +1,149 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime\Tests\Part; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Mime\Header\Headers; +use Symfony\Component\Mime\Header\IdentificationHeader; +use Symfony\Component\Mime\Header\ParameterizedHeader; +use Symfony\Component\Mime\Header\UnstructuredHeader; +use Symfony\Component\Mime\Part\DataPart; + +class DataPartTest extends TestCase +{ + public function testConstructor() + { + $p = new DataPart('content'); + $this->assertEquals('content', $p->getBody()); + $this->assertEquals(base64_encode('content'), $p->bodyToString()); + $this->assertEquals(base64_encode('content'), implode('', iterator_to_array($p->bodyToIterable()))); + // bodyToIterable() can be called several times + $this->assertEquals(base64_encode('content'), implode('', iterator_to_array($p->bodyToIterable()))); + $this->assertEquals('application', $p->getMediaType()); + $this->assertEquals('octet-stream', $p->getMediaSubType()); + + $p = new DataPart('content', null, 'text/html'); + $this->assertEquals('text', $p->getMediaType()); + $this->assertEquals('html', $p->getMediaSubType()); + } + + public function testConstructorWithResource() + { + $f = fopen('php://memory', 'r+', false); + fwrite($f, 'content'); + rewind($f); + $p = new DataPart($f); + $this->assertEquals('content', $p->getBody()); + $this->assertEquals(base64_encode('content'), $p->bodyToString()); + $this->assertEquals(base64_encode('content'), implode('', iterator_to_array($p->bodyToIterable()))); + fclose($f); + } + + public function testConstructorWithNonStringOrResource() + { + $this->expectException(\TypeError::class); + new DataPart(new \stdClass()); + } + + public function testHeaders() + { + $p = new DataPart('content'); + $this->assertEquals(new Headers( + new ParameterizedHeader('Content-Type', 'application/octet-stream'), + new UnstructuredHeader('Content-Transfer-Encoding', 'base64'), + new ParameterizedHeader('Content-Disposition', 'attachment') + ), $p->getPreparedHeaders()); + + $p = new DataPart('content', 'photo.jpg', 'text/html'); + $this->assertEquals(new Headers( + new ParameterizedHeader('Content-Type', 'text/html', ['name' => 'photo.jpg']), + new UnstructuredHeader('Content-Transfer-Encoding', 'base64'), + new ParameterizedHeader('Content-Disposition', 'attachment', ['name' => 'photo.jpg', 'filename' => 'photo.jpg']) + ), $p->getPreparedHeaders()); + } + + public function testAsInline() + { + $p = new DataPart('content', 'photo.jpg', 'text/html'); + $p->asInline(); + $this->assertEquals(new Headers( + new ParameterizedHeader('Content-Type', 'text/html', ['name' => 'photo.jpg']), + new UnstructuredHeader('Content-Transfer-Encoding', 'base64'), + new ParameterizedHeader('Content-Disposition', 'inline', ['name' => 'photo.jpg', 'filename' => 'photo.jpg']) + ), $p->getPreparedHeaders()); + } + + public function testAsInlineWithCID() + { + $p = new DataPart('content', 'photo.jpg', 'text/html'); + $p->asInline(); + $cid = $p->getContentId(); + $this->assertEquals(new Headers( + new ParameterizedHeader('Content-Type', 'text/html', ['name' => 'photo.jpg']), + new UnstructuredHeader('Content-Transfer-Encoding', 'base64'), + new ParameterizedHeader('Content-Disposition', 'inline', ['name' => 'photo.jpg', 'filename' => 'photo.jpg']), + new IdentificationHeader('Content-ID', $cid) + ), $p->getPreparedHeaders()); + } + + public function testFromPath() + { + $p = DataPart::fromPath($file = __DIR__.'/../Fixtures/mimetypes/test.gif'); + $content = file_get_contents($file); + $this->assertEquals($content, $p->getBody()); + $this->assertEquals(base64_encode($content), $p->bodyToString()); + $this->assertEquals(base64_encode($content), implode('', iterator_to_array($p->bodyToIterable()))); + $this->assertEquals('image', $p->getMediaType()); + $this->assertEquals('gif', $p->getMediaSubType()); + $this->assertEquals(new Headers( + new ParameterizedHeader('Content-Type', 'image/gif', ['name' => 'test.gif']), + new UnstructuredHeader('Content-Transfer-Encoding', 'base64'), + new ParameterizedHeader('Content-Disposition', 'attachment', ['name' => 'test.gif', 'filename' => 'test.gif']) + ), $p->getPreparedHeaders()); + } + + public function testFromPathWithMeta() + { + $p = DataPart::fromPath($file = __DIR__.'/../Fixtures/mimetypes/test.gif', 'photo.gif', 'image/jpeg'); + $content = file_get_contents($file); + $this->assertEquals($content, $p->getBody()); + $this->assertEquals(base64_encode($content), $p->bodyToString()); + $this->assertEquals(base64_encode($content), implode('', iterator_to_array($p->bodyToIterable()))); + $this->assertEquals('image', $p->getMediaType()); + $this->assertEquals('jpeg', $p->getMediaSubType()); + $this->assertEquals(new Headers( + new ParameterizedHeader('Content-Type', 'image/jpeg', ['name' => 'photo.gif']), + new UnstructuredHeader('Content-Transfer-Encoding', 'base64'), + new ParameterizedHeader('Content-Disposition', 'attachment', ['name' => 'photo.gif', 'filename' => 'photo.gif']) + ), $p->getPreparedHeaders()); + } + + public function testHasContentId() + { + $p = new DataPart('content'); + $this->assertFalse($p->hasContentId()); + $p->getContentId(); + $this->assertTrue($p->hasContentId()); + } + + public function testSerialize() + { + $r = fopen('php://memory', 'r+', false); + fwrite($r, 'Text content'); + rewind($r); + + $p = new DataPart($r); + $p->getHeaders()->addTextHeader('foo', 'bar'); + $expected = clone $p; + $this->assertEquals($expected->toString(), unserialize(serialize($p))->toString()); + } +} diff --git a/vendor/symfony/mime/Tests/Part/MessagePartTest.php b/vendor/symfony/mime/Tests/Part/MessagePartTest.php new file mode 100644 index 0000000000000000000000000000000000000000..21a4eb03b129203ed33969aa27da5694b6c2a61b --- /dev/null +++ b/vendor/symfony/mime/Tests/Part/MessagePartTest.php @@ -0,0 +1,42 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime\Tests\Part; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Mime\Email; +use Symfony\Component\Mime\Header\Headers; +use Symfony\Component\Mime\Header\ParameterizedHeader; +use Symfony\Component\Mime\Header\UnstructuredHeader; +use Symfony\Component\Mime\Part\MessagePart; + +class MessagePartTest extends TestCase +{ + public function testConstructor() + { + $p = new MessagePart((new Email())->from('fabien@symfony.com')->text('content')); + $this->assertStringContainsString('content', $p->getBody()); + $this->assertStringContainsString('content', $p->bodyToString()); + $this->assertStringContainsString('content', implode('', iterator_to_array($p->bodyToIterable()))); + $this->assertEquals('message', $p->getMediaType()); + $this->assertEquals('rfc822', $p->getMediaSubType()); + } + + public function testHeaders() + { + $p = new MessagePart((new Email())->from('fabien@symfony.com')->text('content')->subject('Subject')); + $this->assertEquals(new Headers( + new ParameterizedHeader('Content-Type', 'message/rfc822', ['name' => 'Subject.eml']), + new UnstructuredHeader('Content-Transfer-Encoding', 'base64'), + new ParameterizedHeader('Content-Disposition', 'attachment', ['name' => 'Subject.eml', 'filename' => 'Subject.eml']) + ), $p->getPreparedHeaders()); + } +} diff --git a/vendor/symfony/mime/Tests/Part/Multipart/AlternativePartTest.php b/vendor/symfony/mime/Tests/Part/Multipart/AlternativePartTest.php new file mode 100644 index 0000000000000000000000000000000000000000..2dbc1315ef1b4f5c286d36db29d05d4032b98f6f --- /dev/null +++ b/vendor/symfony/mime/Tests/Part/Multipart/AlternativePartTest.php @@ -0,0 +1,25 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime\Tests\Part\Multipart; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Mime\Part\Multipart\AlternativePart; + +class AlternativePartTest extends TestCase +{ + public function testConstructor() + { + $a = new AlternativePart(); + $this->assertEquals('multipart', $a->getMediaType()); + $this->assertEquals('alternative', $a->getMediaSubtype()); + } +} diff --git a/vendor/symfony/mime/Tests/Part/Multipart/DigestPartTest.php b/vendor/symfony/mime/Tests/Part/Multipart/DigestPartTest.php new file mode 100644 index 0000000000000000000000000000000000000000..82738efbc5cbe76d471b64f3352efd86608d93eb --- /dev/null +++ b/vendor/symfony/mime/Tests/Part/Multipart/DigestPartTest.php @@ -0,0 +1,28 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime\Tests\Part\Multipart; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Mime\Message; +use Symfony\Component\Mime\Part\MessagePart; +use Symfony\Component\Mime\Part\Multipart\DigestPart; + +class DigestPartTest extends TestCase +{ + public function testConstructor() + { + $r = new DigestPart($a = new MessagePart(new Message()), $b = new MessagePart(new Message())); + $this->assertEquals('multipart', $r->getMediaType()); + $this->assertEquals('digest', $r->getMediaSubtype()); + $this->assertEquals([$a, $b], $r->getParts()); + } +} diff --git a/vendor/symfony/mime/Tests/Part/Multipart/FormDataPartTest.php b/vendor/symfony/mime/Tests/Part/Multipart/FormDataPartTest.php new file mode 100644 index 0000000000000000000000000000000000000000..71a03e6863d8a451fdffb84bf3ccd79998399423 --- /dev/null +++ b/vendor/symfony/mime/Tests/Part/Multipart/FormDataPartTest.php @@ -0,0 +1,66 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime\Tests\Part\Multipart; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Mime\Part\DataPart; +use Symfony\Component\Mime\Part\Multipart\FormDataPart; +use Symfony\Component\Mime\Part\TextPart; + +class FormDataPartTest extends TestCase +{ + public function testConstructor() + { + $r = new \ReflectionProperty(TextPart::class, 'encoding'); + $r->setAccessible(true); + + $b = new TextPart('content'); + $c = DataPart::fromPath($file = __DIR__.'/../../Fixtures/mimetypes/test.gif'); + $f = new FormDataPart([ + 'foo' => $content = 'very very long content that will not be cut even if the length is way more than 76 characters, ok?', + 'bar' => clone $b, + 'baz' => clone $c, + ]); + $this->assertEquals('multipart', $f->getMediaType()); + $this->assertEquals('form-data', $f->getMediaSubtype()); + $t = new TextPart($content, 'utf-8', 'plain', '8bit'); + $t->setDisposition('form-data'); + $t->setName('foo'); + $t->getHeaders()->setMaxLineLength(PHP_INT_MAX); + $b->setDisposition('form-data'); + $b->setName('bar'); + $b->getHeaders()->setMaxLineLength(PHP_INT_MAX); + $r->setValue($b, '8bit'); + $c->setDisposition('form-data'); + $c->setName('baz'); + $c->getHeaders()->setMaxLineLength(PHP_INT_MAX); + $r->setValue($c, '8bit'); + $this->assertEquals([$t, $b, $c], $f->getParts()); + } + + public function testToString() + { + $p = DataPart::fromPath($file = __DIR__.'/../../Fixtures/mimetypes/test.gif'); + $this->assertEquals(base64_encode(file_get_contents($file)), $p->bodyToString()); + } + + public function testContentLineLength() + { + $f = new FormDataPart([ + 'foo' => new DataPart($foo = str_repeat('foo', 1000), 'foo.txt', 'text/plain'), + 'bar' => $bar = str_repeat('bar', 1000), + ]); + $parts = $f->getParts(); + $this->assertEquals($foo, $parts[0]->bodyToString()); + $this->assertEquals($bar, $parts[1]->bodyToString()); + } +} diff --git a/vendor/symfony/mime/Tests/Part/Multipart/MixedPartTest.php b/vendor/symfony/mime/Tests/Part/Multipart/MixedPartTest.php new file mode 100644 index 0000000000000000000000000000000000000000..3ff02ee6cacd5ae91aceccf108ef03e7ff3aa7eb --- /dev/null +++ b/vendor/symfony/mime/Tests/Part/Multipart/MixedPartTest.php @@ -0,0 +1,25 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime\Tests\Part\Multipart; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Mime\Part\Multipart\MixedPart; + +class MixedPartTest extends TestCase +{ + public function testConstructor() + { + $a = new MixedPart(); + $this->assertEquals('multipart', $a->getMediaType()); + $this->assertEquals('mixed', $a->getMediaSubtype()); + } +} diff --git a/vendor/symfony/mime/Tests/Part/Multipart/RelatedPartTest.php b/vendor/symfony/mime/Tests/Part/Multipart/RelatedPartTest.php new file mode 100644 index 0000000000000000000000000000000000000000..2a5a7bed97cd4cb748f78f3fdf39b310343ba0fd --- /dev/null +++ b/vendor/symfony/mime/Tests/Part/Multipart/RelatedPartTest.php @@ -0,0 +1,30 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime\Tests\Part\Multipart; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Mime\Part\Multipart\RelatedPart; +use Symfony\Component\Mime\Part\TextPart; + +class RelatedPartTest extends TestCase +{ + public function testConstructor() + { + $r = new RelatedPart($a = new TextPart('content'), $b = new TextPart('HTML content', 'utf-8', 'html'), $c = new TextPart('HTML content again', 'utf-8', 'html')); + $this->assertEquals('multipart', $r->getMediaType()); + $this->assertEquals('related', $r->getMediaSubtype()); + $this->assertEquals([$a, $b, $c], $r->getParts()); + $this->assertFalse($a->getHeaders()->has('Content-ID')); + $this->assertTrue($b->getHeaders()->has('Content-ID')); + $this->assertTrue($c->getHeaders()->has('Content-ID')); + } +} diff --git a/vendor/symfony/mime/Tests/Part/TextPartTest.php b/vendor/symfony/mime/Tests/Part/TextPartTest.php new file mode 100644 index 0000000000000000000000000000000000000000..c3818b883d46540fbda79a6f5f5845c10c0a1bad --- /dev/null +++ b/vendor/symfony/mime/Tests/Part/TextPartTest.php @@ -0,0 +1,92 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime\Tests\Part; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Mime\Header\Headers; +use Symfony\Component\Mime\Header\ParameterizedHeader; +use Symfony\Component\Mime\Header\UnstructuredHeader; +use Symfony\Component\Mime\Part\TextPart; + +class TextPartTest extends TestCase +{ + public function testConstructor() + { + $p = new TextPart('content'); + $this->assertEquals('content', $p->getBody()); + $this->assertEquals('content', $p->bodyToString()); + $this->assertEquals('content', implode('', iterator_to_array($p->bodyToIterable()))); + // bodyToIterable() can be called several times + $this->assertEquals('content', implode('', iterator_to_array($p->bodyToIterable()))); + $this->assertEquals('text', $p->getMediaType()); + $this->assertEquals('plain', $p->getMediaSubType()); + + $p = new TextPart('content', null, 'html'); + $this->assertEquals('html', $p->getMediaSubType()); + } + + public function testConstructorWithResource() + { + $f = fopen('php://memory', 'r+', false); + fwrite($f, 'content'); + rewind($f); + $p = new TextPart($f); + $this->assertEquals('content', $p->getBody()); + $this->assertEquals('content', $p->bodyToString()); + $this->assertEquals('content', implode('', iterator_to_array($p->bodyToIterable()))); + fclose($f); + } + + public function testConstructorWithNonStringOrResource() + { + $this->expectException(\TypeError::class); + new TextPart(new \stdClass()); + } + + public function testHeaders() + { + $p = new TextPart('content'); + $this->assertEquals(new Headers( + new ParameterizedHeader('Content-Type', 'text/plain', ['charset' => 'utf-8']), + new UnstructuredHeader('Content-Transfer-Encoding', 'quoted-printable') + ), $p->getPreparedHeaders()); + + $p = new TextPart('content', 'iso-8859-1'); + $this->assertEquals(new Headers( + new ParameterizedHeader('Content-Type', 'text/plain', ['charset' => 'iso-8859-1']), + new UnstructuredHeader('Content-Transfer-Encoding', 'quoted-printable') + ), $p->getPreparedHeaders()); + } + + public function testEncoding() + { + $p = new TextPart('content', 'utf-8', 'plain', 'base64'); + $this->assertEquals(base64_encode('content'), $p->bodyToString()); + $this->assertEquals(base64_encode('content'), implode('', iterator_to_array($p->bodyToIterable()))); + $this->assertEquals(new Headers( + new ParameterizedHeader('Content-Type', 'text/plain', ['charset' => 'utf-8']), + new UnstructuredHeader('Content-Transfer-Encoding', 'base64') + ), $p->getPreparedHeaders()); + } + + public function testSerialize() + { + $r = fopen('php://memory', 'r+', false); + fwrite($r, 'Text content'); + rewind($r); + + $p = new TextPart($r); + $p->getHeaders()->addTextHeader('foo', 'bar'); + $expected = clone $p; + $this->assertEquals($expected->toString(), unserialize(serialize($p))->toString()); + } +} diff --git a/vendor/symfony/mime/Tests/RawMessageTest.php b/vendor/symfony/mime/Tests/RawMessageTest.php new file mode 100644 index 0000000000000000000000000000000000000000..5d1588bff00fa66d617c91e9eace4d5918fd45c9 --- /dev/null +++ b/vendor/symfony/mime/Tests/RawMessageTest.php @@ -0,0 +1,35 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Mime\Tests; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Mime\RawMessage; + +class RawMessageTest extends TestCase +{ + public function testToString() + { + $message = new RawMessage('string'); + $this->assertEquals('string', $message->toString()); + $this->assertEquals('string', implode('', iterator_to_array($message->toIterable()))); + // calling methods more than once work + $this->assertEquals('string', $message->toString()); + $this->assertEquals('string', implode('', iterator_to_array($message->toIterable()))); + + $message = new RawMessage(new \ArrayObject(['some', ' ', 'string'])); + $this->assertEquals('some string', $message->toString()); + $this->assertEquals('some string', implode('', iterator_to_array($message->toIterable()))); + // calling methods more than once work + $this->assertEquals('some string', $message->toString()); + $this->assertEquals('some string', implode('', iterator_to_array($message->toIterable()))); + } +} diff --git a/vendor/symfony/mime/composer.json b/vendor/symfony/mime/composer.json new file mode 100644 index 0000000000000000000000000000000000000000..0697e5609930c87c5814c5a195512f5c6896776d --- /dev/null +++ b/vendor/symfony/mime/composer.json @@ -0,0 +1,39 @@ +{ + "name": "symfony/mime", + "type": "library", + "description": "A library to manipulate MIME messages", + "keywords": ["mime", "mime-type"], + "homepage": "https://symfony.com", + "license": "MIT", + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "require": { + "php": "^7.1.3", + "symfony/polyfill-intl-idn": "^1.10", + "symfony/polyfill-mbstring": "^1.0" + }, + "require-dev": { + "egulias/email-validator": "^2.1.10", + "symfony/dependency-injection": "~3.4|^4.1" + }, + "autoload": { + "psr-4": { "Symfony\\Component\\Mime\\": "" }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "minimum-stability": "dev", + "extra": { + "branch-alias": { + "dev-master": "4.3-dev" + } + } +} diff --git a/vendor/symfony/mime/phpunit.xml.dist b/vendor/symfony/mime/phpunit.xml.dist new file mode 100644 index 0000000000000000000000000000000000000000..a1c68d0e5f37155e4cc9cf9756d19c9dd41f0020 --- /dev/null +++ b/vendor/symfony/mime/phpunit.xml.dist @@ -0,0 +1,31 @@ +<?xml version="1.0" encoding="UTF-8"?> + +<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/5.2/phpunit.xsd" + backupGlobals="false" + colors="true" + bootstrap="vendor/autoload.php" + failOnRisky="true" + failOnWarning="true" +> + <php> + <ini name="error_reporting" value="-1" /> + </php> + + <testsuites> + <testsuite name="Symfony MIME Component Test Suite"> + <directory>./Tests/</directory> + </testsuite> + </testsuites> + + <filter> + <whitelist> + <directory>./</directory> + <exclude> + <directory>./Resources</directory> + <directory>./Tests</directory> + <directory>./vendor</directory> + </exclude> + </whitelist> + </filter> +</phpunit> diff --git a/vendor/symfony/polyfill-ctype/Ctype.php b/vendor/symfony/polyfill-ctype/Ctype.php new file mode 100644 index 0000000000000000000000000000000000000000..58414dc73bd45b931b73a05a040d9ca23a61acf6 --- /dev/null +++ b/vendor/symfony/polyfill-ctype/Ctype.php @@ -0,0 +1,227 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Polyfill\Ctype; + +/** + * Ctype implementation through regex. + * + * @internal + * + * @author Gert de Pagter <BackEndTea@gmail.com> + */ +final class Ctype +{ + /** + * Returns TRUE if every character in text is either a letter or a digit, FALSE otherwise. + * + * @see https://php.net/ctype-alnum + * + * @param string|int $text + * + * @return bool + */ + public static function ctype_alnum($text) + { + $text = self::convert_int_to_char_for_ctype($text); + + return \is_string($text) && '' !== $text && !preg_match('/[^A-Za-z0-9]/', $text); + } + + /** + * Returns TRUE if every character in text is a letter, FALSE otherwise. + * + * @see https://php.net/ctype-alpha + * + * @param string|int $text + * + * @return bool + */ + public static function ctype_alpha($text) + { + $text = self::convert_int_to_char_for_ctype($text); + + return \is_string($text) && '' !== $text && !preg_match('/[^A-Za-z]/', $text); + } + + /** + * Returns TRUE if every character in text is a control character from the current locale, FALSE otherwise. + * + * @see https://php.net/ctype-cntrl + * + * @param string|int $text + * + * @return bool + */ + public static function ctype_cntrl($text) + { + $text = self::convert_int_to_char_for_ctype($text); + + return \is_string($text) && '' !== $text && !preg_match('/[^\x00-\x1f\x7f]/', $text); + } + + /** + * Returns TRUE if every character in the string text is a decimal digit, FALSE otherwise. + * + * @see https://php.net/ctype-digit + * + * @param string|int $text + * + * @return bool + */ + public static function ctype_digit($text) + { + $text = self::convert_int_to_char_for_ctype($text); + + return \is_string($text) && '' !== $text && !preg_match('/[^0-9]/', $text); + } + + /** + * Returns TRUE if every character in text is printable and actually creates visible output (no white space), FALSE otherwise. + * + * @see https://php.net/ctype-graph + * + * @param string|int $text + * + * @return bool + */ + public static function ctype_graph($text) + { + $text = self::convert_int_to_char_for_ctype($text); + + return \is_string($text) && '' !== $text && !preg_match('/[^!-~]/', $text); + } + + /** + * Returns TRUE if every character in text is a lowercase letter. + * + * @see https://php.net/ctype-lower + * + * @param string|int $text + * + * @return bool + */ + public static function ctype_lower($text) + { + $text = self::convert_int_to_char_for_ctype($text); + + return \is_string($text) && '' !== $text && !preg_match('/[^a-z]/', $text); + } + + /** + * Returns TRUE if every character in text will actually create output (including blanks). Returns FALSE if text contains control characters or characters that do not have any output or control function at all. + * + * @see https://php.net/ctype-print + * + * @param string|int $text + * + * @return bool + */ + public static function ctype_print($text) + { + $text = self::convert_int_to_char_for_ctype($text); + + return \is_string($text) && '' !== $text && !preg_match('/[^ -~]/', $text); + } + + /** + * Returns TRUE if every character in text is printable, but neither letter, digit or blank, FALSE otherwise. + * + * @see https://php.net/ctype-punct + * + * @param string|int $text + * + * @return bool + */ + public static function ctype_punct($text) + { + $text = self::convert_int_to_char_for_ctype($text); + + return \is_string($text) && '' !== $text && !preg_match('/[^!-\/\:-@\[-`\{-~]/', $text); + } + + /** + * Returns TRUE if every character in text creates some sort of white space, FALSE otherwise. Besides the blank character this also includes tab, vertical tab, line feed, carriage return and form feed characters. + * + * @see https://php.net/ctype-space + * + * @param string|int $text + * + * @return bool + */ + public static function ctype_space($text) + { + $text = self::convert_int_to_char_for_ctype($text); + + return \is_string($text) && '' !== $text && !preg_match('/[^\s]/', $text); + } + + /** + * Returns TRUE if every character in text is an uppercase letter. + * + * @see https://php.net/ctype-upper + * + * @param string|int $text + * + * @return bool + */ + public static function ctype_upper($text) + { + $text = self::convert_int_to_char_for_ctype($text); + + return \is_string($text) && '' !== $text && !preg_match('/[^A-Z]/', $text); + } + + /** + * Returns TRUE if every character in text is a hexadecimal 'digit', that is a decimal digit or a character from [A-Fa-f] , FALSE otherwise. + * + * @see https://php.net/ctype-xdigit + * + * @param string|int $text + * + * @return bool + */ + public static function ctype_xdigit($text) + { + $text = self::convert_int_to_char_for_ctype($text); + + return \is_string($text) && '' !== $text && !preg_match('/[^A-Fa-f0-9]/', $text); + } + + /** + * Converts integers to their char versions according to normal ctype behaviour, if needed. + * + * If an integer between -128 and 255 inclusive is provided, + * it is interpreted as the ASCII value of a single character + * (negative values have 256 added in order to allow characters in the Extended ASCII range). + * Any other integer is interpreted as a string containing the decimal digits of the integer. + * + * @param string|int $int + * + * @return mixed + */ + private static function convert_int_to_char_for_ctype($int) + { + if (!\is_int($int)) { + return $int; + } + + if ($int < -128 || $int > 255) { + return (string) $int; + } + + if ($int < 0) { + $int += 256; + } + + return \chr($int); + } +} diff --git a/vendor/symfony/polyfill-ctype/LICENSE b/vendor/symfony/polyfill-ctype/LICENSE new file mode 100644 index 0000000000000000000000000000000000000000..3f853aaf35fe186d4016761eb6e8a403de3e6e0d --- /dev/null +++ b/vendor/symfony/polyfill-ctype/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2018-2019 Fabien Potencier + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/vendor/symfony/polyfill-ctype/README.md b/vendor/symfony/polyfill-ctype/README.md new file mode 100644 index 0000000000000000000000000000000000000000..8add1ab0096e7e7ca60829b87266d2c5a884ac26 --- /dev/null +++ b/vendor/symfony/polyfill-ctype/README.md @@ -0,0 +1,12 @@ +Symfony Polyfill / Ctype +======================== + +This component provides `ctype_*` functions to users who run php versions without the ctype extension. + +More information can be found in the +[main Polyfill README](https://github.com/symfony/polyfill/blob/master/README.md). + +License +======= + +This library is released under the [MIT license](LICENSE). diff --git a/vendor/symfony/polyfill-ctype/bootstrap.php b/vendor/symfony/polyfill-ctype/bootstrap.php new file mode 100644 index 0000000000000000000000000000000000000000..14d1d0faa37151ccb47e6067f6d3e96b8207db48 --- /dev/null +++ b/vendor/symfony/polyfill-ctype/bootstrap.php @@ -0,0 +1,26 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use Symfony\Polyfill\Ctype as p; + +if (!function_exists('ctype_alnum')) { + function ctype_alnum($text) { return p\Ctype::ctype_alnum($text); } + function ctype_alpha($text) { return p\Ctype::ctype_alpha($text); } + function ctype_cntrl($text) { return p\Ctype::ctype_cntrl($text); } + function ctype_digit($text) { return p\Ctype::ctype_digit($text); } + function ctype_graph($text) { return p\Ctype::ctype_graph($text); } + function ctype_lower($text) { return p\Ctype::ctype_lower($text); } + function ctype_print($text) { return p\Ctype::ctype_print($text); } + function ctype_punct($text) { return p\Ctype::ctype_punct($text); } + function ctype_space($text) { return p\Ctype::ctype_space($text); } + function ctype_upper($text) { return p\Ctype::ctype_upper($text); } + function ctype_xdigit($text) { return p\Ctype::ctype_xdigit($text); } +} diff --git a/vendor/symfony/polyfill-ctype/composer.json b/vendor/symfony/polyfill-ctype/composer.json new file mode 100644 index 0000000000000000000000000000000000000000..090f923ef1dcb151a058806d94a8c658e4889136 --- /dev/null +++ b/vendor/symfony/polyfill-ctype/composer.json @@ -0,0 +1,34 @@ +{ + "name": "symfony/polyfill-ctype", + "type": "library", + "description": "Symfony polyfill for ctype functions", + "keywords": ["polyfill", "compatibility", "portable", "ctype"], + "homepage": "https://symfony.com", + "license": "MIT", + "authors": [ + { + "name": "Gert de Pagter", + "email": "BackEndTea@gmail.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "require": { + "php": ">=5.3.3" + }, + "autoload": { + "psr-4": { "Symfony\\Polyfill\\Ctype\\": "" }, + "files": [ "bootstrap.php" ] + }, + "suggest": { + "ext-ctype": "For best performance" + }, + "minimum-stability": "dev", + "extra": { + "branch-alias": { + "dev-master": "1.12-dev" + } + } +} diff --git a/vendor/symfony/polyfill-intl-idn/Idn.php b/vendor/symfony/polyfill-intl-idn/Idn.php new file mode 100644 index 0000000000000000000000000000000000000000..adb718d29652ecc3897c8dbb7d502462ea32a8c4 --- /dev/null +++ b/vendor/symfony/polyfill-intl-idn/Idn.php @@ -0,0 +1,283 @@ +<?php + +/* + * Copyright (c) 2014 TrueServer B.V. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is furnished + * to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + * + * Originally forked from + * https://github.com/true/php-punycode/blob/v2.1.1/src/Punycode.php + */ + +namespace Symfony\Polyfill\Intl\Idn; + +/** + * Partial intl implementation in pure PHP. + * + * Implemented: + * - idn_to_ascii - Convert domain name to IDNA ASCII form + * - idn_to_utf8 - Convert domain name from IDNA ASCII to Unicode + * + * @author Renan Gonçalves <renan.saddam@gmail.com> + * @author Sebastian Kroczek <sk@xbug.de> + * @author Dmitry Lukashin <dmitry@lukashin.ru> + * @author Laurent Bassin <laurent@bassin.info> + * + * @internal + */ +final class Idn +{ + const INTL_IDNA_VARIANT_2003 = 0; + const INTL_IDNA_VARIANT_UTS46 = 1; + + private static $encodeTable = array( + 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', + 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', + 'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', + ); + + private static $decodeTable = array( + 'a' => 0, 'b' => 1, 'c' => 2, 'd' => 3, 'e' => 4, 'f' => 5, + 'g' => 6, 'h' => 7, 'i' => 8, 'j' => 9, 'k' => 10, 'l' => 11, + 'm' => 12, 'n' => 13, 'o' => 14, 'p' => 15, 'q' => 16, 'r' => 17, + 's' => 18, 't' => 19, 'u' => 20, 'v' => 21, 'w' => 22, 'x' => 23, + 'y' => 24, 'z' => 25, '0' => 26, '1' => 27, '2' => 28, '3' => 29, + '4' => 30, '5' => 31, '6' => 32, '7' => 33, '8' => 34, '9' => 35, + ); + + public static function idn_to_ascii($domain, $options, $variant, &$idna_info = array()) + { + if (\PHP_VERSION_ID >= 70200 && self::INTL_IDNA_VARIANT_2003 === $variant) { + @trigger_error('idn_to_ascii(): INTL_IDNA_VARIANT_2003 is deprecated', E_USER_DEPRECATED); + } + + if (self::INTL_IDNA_VARIANT_UTS46 === $variant) { + $domain = mb_strtolower($domain, 'utf-8'); + } + + $parts = explode('.', $domain); + + foreach ($parts as $i => &$part) { + if ('' === $part && \count($parts) > 1 + $i) { + return false; + } + if (false === $part = self::encodePart($part)) { + return false; + } + } + + $output = implode('.', $parts); + + $idna_info = array( + 'result' => \strlen($output) > 255 ? false : $output, + 'isTransitionalDifferent' => false, + 'errors' => 0, + ); + + return $idna_info['result']; + } + + public static function idn_to_utf8($domain, $options, $variant, &$idna_info = array()) + { + if (\PHP_VERSION_ID >= 70200 && self::INTL_IDNA_VARIANT_2003 === $variant) { + @trigger_error('idn_to_utf8(): INTL_IDNA_VARIANT_2003 is deprecated', E_USER_DEPRECATED); + } + + $parts = explode('.', $domain); + + foreach ($parts as &$part) { + $length = \strlen($part); + if ($length < 1 || 63 < $length) { + continue; + } + if (0 !== strpos($part, 'xn--')) { + continue; + } + + $part = substr($part, 4); + $part = self::decodePart($part); + } + + $output = implode('.', $parts); + + $idna_info = array( + 'result' => \strlen($output) > 255 ? false : $output, + 'isTransitionalDifferent' => false, + 'errors' => 0, + ); + + return $idna_info['result']; + } + + private static function encodePart($input) + { + $codePoints = self::listCodePoints($input); + + $n = 128; + $bias = 72; + $delta = 0; + $h = $b = \count($codePoints['basic']); + + $output = ''; + foreach ($codePoints['basic'] as $code) { + $output .= mb_chr($code, 'utf-8'); + } + if ($input === $output) { + return $output; + } + if ($b > 0) { + $output .= '-'; + } + + $codePoints['nonBasic'] = array_unique($codePoints['nonBasic']); + sort($codePoints['nonBasic']); + + $i = 0; + $length = mb_strlen($input, 'utf-8'); + while ($h < $length) { + $m = $codePoints['nonBasic'][$i++]; + $delta += ($m - $n) * ($h + 1); + $n = $m; + + foreach ($codePoints['all'] as $c) { + if ($c < $n || $c < 128) { + ++$delta; + } + if ($c === $n) { + $q = $delta; + for ($k = 36;; $k += 36) { + $t = self::calculateThreshold($k, $bias); + if ($q < $t) { + break; + } + + $code = $t + (($q - $t) % (36 - $t)); + $output .= self::$encodeTable[$code]; + + $q = ($q - $t) / (36 - $t); + } + + $output .= self::$encodeTable[$q]; + $bias = self::adapt($delta, $h + 1, ($h === $b)); + $delta = 0; + ++$h; + } + } + + ++$delta; + ++$n; + } + + $output = 'xn--'.$output; + + return \strlen($output) < 1 || 63 < \strlen($output) ? false : strtolower($output); + } + + private static function listCodePoints($input) + { + $codePoints = array( + 'all' => array(), + 'basic' => array(), + 'nonBasic' => array(), + ); + + $length = mb_strlen($input, 'utf-8'); + for ($i = 0; $i < $length; ++$i) { + $char = mb_substr($input, $i, 1, 'utf-8'); + $code = mb_ord($char, 'utf-8'); + if ($code < 128) { + $codePoints['all'][] = $codePoints['basic'][] = $code; + } else { + $codePoints['all'][] = $codePoints['nonBasic'][] = $code; + } + } + + return $codePoints; + } + + private static function calculateThreshold($k, $bias) + { + if ($k <= $bias + 1) { + return 1; + } + if ($k >= $bias + 26) { + return 26; + } + + return $k - $bias; + } + + private static function adapt($delta, $numPoints, $firstTime) + { + $delta = (int) ($firstTime ? $delta / 700 : $delta / 2); + $delta += (int) ($delta / $numPoints); + + $k = 0; + while ($delta > 35 * 13) { + $delta = (int) ($delta / 35); + $k = $k + 36; + } + + return $k + (int) (36 * $delta / ($delta + 38)); + } + + private static function decodePart($input) + { + $n = 128; + $i = 0; + $bias = 72; + $output = ''; + + $pos = strrpos($input, '-'); + if (false !== $pos) { + $output = substr($input, 0, $pos++); + } else { + $pos = 0; + } + + $outputLength = \strlen($output); + $inputLength = \strlen($input); + + while ($pos < $inputLength) { + $oldi = $i; + $w = 1; + + for ($k = 36;; $k += 36) { + $digit = self::$decodeTable[$input[$pos++]]; + $i += $digit * $w; + $t = self::calculateThreshold($k, $bias); + + if ($digit < $t) { + break; + } + + $w *= 36 - $t; + } + + $bias = self::adapt($i - $oldi, ++$outputLength, 0 === $oldi); + $n = $n + (int) ($i / $outputLength); + $i = $i % $outputLength; + $output = mb_substr($output, 0, $i, 'utf-8').mb_chr($n, 'utf-8').mb_substr($output, $i, $outputLength - 1, 'utf-8'); + + ++$i; + } + + return $output; + } +} diff --git a/vendor/symfony/polyfill-intl-idn/LICENSE b/vendor/symfony/polyfill-intl-idn/LICENSE new file mode 100644 index 0000000000000000000000000000000000000000..3f853aaf35fe186d4016761eb6e8a403de3e6e0d --- /dev/null +++ b/vendor/symfony/polyfill-intl-idn/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2018-2019 Fabien Potencier + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/vendor/symfony/polyfill-intl-idn/README.md b/vendor/symfony/polyfill-intl-idn/README.md new file mode 100644 index 0000000000000000000000000000000000000000..5fd8c6e97834a0bcbbaad627e34b8e35307a1de8 --- /dev/null +++ b/vendor/symfony/polyfill-intl-idn/README.md @@ -0,0 +1,12 @@ +Symfony Polyfill / Intl: Idn +============================ + +This component provides `idn_to_ascii` and `idn_to_utf8` functions to users who run php versions without the intl extension. + +More information can be found in the +[main Polyfill README](https://github.com/symfony/polyfill/blob/master/README.md). + +License +======= + +This library is released under the [MIT license](LICENSE). diff --git a/vendor/symfony/polyfill-intl-idn/bootstrap.php b/vendor/symfony/polyfill-intl-idn/bootstrap.php new file mode 100644 index 0000000000000000000000000000000000000000..c6e3921d764c903257ed9cde7000e1751f5537c0 --- /dev/null +++ b/vendor/symfony/polyfill-intl-idn/bootstrap.php @@ -0,0 +1,59 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use Symfony\Polyfill\Intl\Idn as p; + +if (!function_exists('idn_to_ascii')) { + define('U_IDNA_PROHIBITED_ERROR', 66560); + define('U_IDNA_ERROR_START', 66560); + define('U_IDNA_UNASSIGNED_ERROR', 66561); + define('U_IDNA_CHECK_BIDI_ERROR', 66562); + define('U_IDNA_STD3_ASCII_RULES_ERROR', 66563); + define('U_IDNA_ACE_PREFIX_ERROR', 66564); + define('U_IDNA_VERIFICATION_ERROR', 66565); + define('U_IDNA_LABEL_TOO_LONG_ERROR', 66566); + define('U_IDNA_ZERO_LENGTH_LABEL_ERROR', 66567); + define('U_IDNA_DOMAIN_NAME_TOO_LONG_ERROR', 66568); + define('U_IDNA_ERROR_LIMIT', 66569); + define('U_STRINGPREP_PROHIBITED_ERROR', 66560); + define('U_STRINGPREP_UNASSIGNED_ERROR', 66561); + define('U_STRINGPREP_CHECK_BIDI_ERROR', 66562); + define('IDNA_DEFAULT', 0); + define('IDNA_ALLOW_UNASSIGNED', 1); + define('IDNA_USE_STD3_RULES', 2); + define('IDNA_CHECK_BIDI', 4); + define('IDNA_CHECK_CONTEXTJ', 8); + define('IDNA_NONTRANSITIONAL_TO_ASCII', 16); + define('IDNA_NONTRANSITIONAL_TO_UNICODE', 32); + define('INTL_IDNA_VARIANT_2003', 0); + define('INTL_IDNA_VARIANT_UTS46', 1); + define('IDNA_ERROR_EMPTY_LABEL', 1); + define('IDNA_ERROR_LABEL_TOO_LONG', 2); + define('IDNA_ERROR_DOMAIN_NAME_TOO_LONG', 4); + define('IDNA_ERROR_LEADING_HYPHEN', 8); + define('IDNA_ERROR_TRAILING_HYPHEN', 16); + define('IDNA_ERROR_HYPHEN_3_4', 32); + define('IDNA_ERROR_LEADING_COMBINING_MARK', 64); + define('IDNA_ERROR_DISALLOWED', 128); + define('IDNA_ERROR_PUNYCODE', 256); + define('IDNA_ERROR_LABEL_HAS_DOT', 512); + define('IDNA_ERROR_INVALID_ACE_LABEL', 1024); + define('IDNA_ERROR_BIDI', 2048); + define('IDNA_ERROR_CONTEXTJ', 4096); + + if (PHP_VERSION_ID < 70400) { + function idn_to_ascii($domain, $options = IDNA_DEFAULT, $variant = INTL_IDNA_VARIANT_2003, &$idna_info = array()) { return p\Idn::idn_to_ascii($domain, $options, $variant, $idna_info); } + function idn_to_utf8($domain, $options = IDNA_DEFAULT, $variant = INTL_IDNA_VARIANT_2003, &$idna_info = array()) { return p\Idn::idn_to_utf8($domain, $options, $variant, $idna_info); } + } else { + function idn_to_ascii($domain, $options = IDNA_DEFAULT, $variant = INTL_IDNA_VARIANT_UTS46, &$idna_info = array()) { return p\Idn::idn_to_ascii($domain, $options, $variant, $idna_info); } + function idn_to_utf8($domain, $options = IDNA_DEFAULT, $variant = INTL_IDNA_VARIANT_UTS46, &$idna_info = array()) { return p\Idn::idn_to_utf8($domain, $options, $variant, $idna_info); } + } +} diff --git a/vendor/symfony/polyfill-intl-idn/composer.json b/vendor/symfony/polyfill-intl-idn/composer.json new file mode 100644 index 0000000000000000000000000000000000000000..d2e3f4b19740e7ba388beea3b52217206b553580 --- /dev/null +++ b/vendor/symfony/polyfill-intl-idn/composer.json @@ -0,0 +1,36 @@ +{ + "name": "symfony/polyfill-intl-idn", + "type": "library", + "description": "Symfony polyfill for intl's idn_to_ascii and idn_to_utf8 functions", + "keywords": ["polyfill", "shim", "compatibility", "portable", "intl", "idn"], + "homepage": "https://symfony.com", + "license": "MIT", + "authors": [ + { + "name": "Laurent Bassin", + "email": "laurent@bassin.info" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "require": { + "php": ">=5.3.3", + "symfony/polyfill-mbstring": "^1.3", + "symfony/polyfill-php72": "^1.9" + }, + "autoload": { + "psr-4": { "Symfony\\Polyfill\\Intl\\Idn\\": "" }, + "files": [ "bootstrap.php" ] + }, + "suggest": { + "ext-intl": "For best performance" + }, + "minimum-stability": "dev", + "extra": { + "branch-alias": { + "dev-master": "1.12-dev" + } + } +} diff --git a/vendor/symfony/polyfill-mbstring/LICENSE b/vendor/symfony/polyfill-mbstring/LICENSE index 24fa32c2e9b27aef3eac523f0042b8ab9ba81944..4cd8bdd3007da4d62985ec9e5ca81a1e18ae34d1 100644 --- a/vendor/symfony/polyfill-mbstring/LICENSE +++ b/vendor/symfony/polyfill-mbstring/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2015-2018 Fabien Potencier +Copyright (c) 2015-2019 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/vendor/symfony/polyfill-mbstring/Mbstring.php b/vendor/symfony/polyfill-mbstring/Mbstring.php index 67cf9ab8bd0c48b94e2f2b966597e1f511435280..1fc4feea72cd8ba056ebb794a97a5a6254be08c7 100644 --- a/vendor/symfony/polyfill-mbstring/Mbstring.php +++ b/vendor/symfony/polyfill-mbstring/Mbstring.php @@ -35,6 +35,7 @@ namespace Symfony\Polyfill\Mbstring; * - mb_strlen - Get string length * - mb_strpos - Find position of first occurrence of string in a string * - mb_strrpos - Find position of last occurrence of a string in a string + * - mb_str_split - Convert a string to an array * - mb_strtolower - Make a string lowercase * - mb_strtoupper - Make a string uppercase * - mb_substitute_character - Set/Get substitution character @@ -44,7 +45,7 @@ namespace Symfony\Polyfill\Mbstring; * - mb_strrchr - Finds the last occurrence of a character in a string within another * - mb_strrichr - Finds the last occurrence of a character in a string within another, case insensitive * - mb_strripos - Finds position of last occurrence of a string within another, case insensitive - * - mb_strstr - Finds first occurrence of a string within anothers + * - mb_strstr - Finds first occurrence of a string within another * - mb_strwidth - Return width of string * - mb_substr_count - Count the number of substring occurrences * @@ -72,13 +73,13 @@ final class Mbstring private static $language = 'neutral'; private static $internalEncoding = 'UTF-8'; private static $caseFold = array( - array('µ','Å¿',"\xCD\x85",'Ï‚',"\xCF\x90","\xCF\x91","\xCF\x95","\xCF\x96","\xCF\xB0","\xCF\xB1","\xCF\xB5","\xE1\xBA\x9B","\xE1\xBE\xBE"), - array('μ','s','ι', 'σ','β', 'θ', 'φ', 'Ï€', 'κ', 'Ï', 'ε', "\xE1\xB9\xA1",'ι'), + array('µ', 'Å¿', "\xCD\x85", 'Ï‚', "\xCF\x90", "\xCF\x91", "\xCF\x95", "\xCF\x96", "\xCF\xB0", "\xCF\xB1", "\xCF\xB5", "\xE1\xBA\x9B", "\xE1\xBE\xBE"), + array('μ', 's', 'ι', 'σ', 'β', 'θ', 'φ', 'Ï€', 'κ', 'Ï', 'ε', "\xE1\xB9\xA1", 'ι'), ); public static function mb_convert_encoding($s, $toEncoding, $fromEncoding = null) { - if (is_array($fromEncoding) || false !== strpos($fromEncoding, ',')) { + if (\is_array($fromEncoding) || false !== strpos($fromEncoding, ',')) { $fromEncoding = self::mb_detect_encoding($s, $fromEncoding); } else { $fromEncoding = self::getEncoding($fromEncoding); @@ -140,17 +141,19 @@ final class Mbstring public static function mb_decode_numericentity($s, $convmap, $encoding = null) { - if (null !== $s && !is_scalar($s) && !(is_object($s) && method_exists($s, '__toString'))) { - trigger_error('mb_decode_numericentity() expects parameter 1 to be string, '.gettype($s).' given', E_USER_WARNING); + if (null !== $s && !\is_scalar($s) && !(\is_object($s) && \method_exists($s, '__toString'))) { + trigger_error('mb_decode_numericentity() expects parameter 1 to be string, '.\gettype($s).' given', E_USER_WARNING); + return null; } - if (!is_array($convmap) || !$convmap) { + if (!\is_array($convmap) || !$convmap) { return false; } - if (null !== $encoding && !is_scalar($encoding)) { - trigger_error('mb_decode_numericentity() expects parameter 3 to be string, '.gettype($s).' given', E_USER_WARNING); + if (null !== $encoding && !\is_scalar($encoding)) { + trigger_error('mb_decode_numericentity() expects parameter 3 to be string, '.\gettype($s).' given', E_USER_WARNING); + return ''; // Instead of null (cf. mb_encode_numericentity). } @@ -170,7 +173,7 @@ final class Mbstring $s = iconv($encoding, 'UTF-8//IGNORE', $s); } - $cnt = floor(count($convmap) / 4) * 4; + $cnt = floor(\count($convmap) / 4) * 4; for ($i = 0; $i < $cnt; $i += 4) { // collector_decode_htmlnumericentity ignores $convmap[$i + 3] @@ -185,6 +188,7 @@ final class Mbstring return Mbstring::mb_chr($c - $convmap[$i + 2]); } } + return $m[0]; }, $s); @@ -197,22 +201,25 @@ final class Mbstring public static function mb_encode_numericentity($s, $convmap, $encoding = null, $is_hex = false) { - if (null !== $s && !is_scalar($s) && !(is_object($s) && method_exists($s, '__toString'))) { - trigger_error('mb_encode_numericentity() expects parameter 1 to be string, '.gettype($s).' given', E_USER_WARNING); + if (null !== $s && !\is_scalar($s) && !(\is_object($s) && \method_exists($s, '__toString'))) { + trigger_error('mb_encode_numericentity() expects parameter 1 to be string, '.\gettype($s).' given', E_USER_WARNING); + return null; } - if (!is_array($convmap) || !$convmap) { + if (!\is_array($convmap) || !$convmap) { return false; } - if (null !== $encoding && !is_scalar($encoding)) { - trigger_error('mb_encode_numericentity() expects parameter 3 to be string, '.gettype($s).' given', E_USER_WARNING); + if (null !== $encoding && !\is_scalar($encoding)) { + trigger_error('mb_encode_numericentity() expects parameter 3 to be string, '.\gettype($s).' given', E_USER_WARNING); + return null; // Instead of '' (cf. mb_decode_numericentity). } - if (null !== $is_hex && !is_scalar($is_hex)) { - trigger_error('mb_encode_numericentity() expects parameter 4 to be boolean, '.gettype($s).' given', E_USER_WARNING); + if (null !== $is_hex && !\is_scalar($is_hex)) { + trigger_error('mb_encode_numericentity() expects parameter 4 to be boolean, '.\gettype($s).' given', E_USER_WARNING); + return null; } @@ -234,9 +241,9 @@ final class Mbstring static $ulenMask = array("\xC0" => 2, "\xD0" => 2, "\xE0" => 3, "\xF0" => 4); - $cnt = floor(count($convmap) / 4) * 4; + $cnt = floor(\count($convmap) / 4) * 4; $i = 0; - $len = strlen($s); + $len = \strlen($s); $result = ''; while ($i < $len) { @@ -281,8 +288,11 @@ final class Mbstring } if (MB_CASE_TITLE == $mode) { - $s = preg_replace_callback('/\b\p{Ll}/u', array(__CLASS__, 'title_case_upper'), $s); - $s = preg_replace_callback('/\B[\p{Lu}\p{Lt}]+/u', array(__CLASS__, 'title_case_lower'), $s); + static $titleRegexp = null; + if (null === $titleRegexp) { + $titleRegexp = self::getData('titleCaseRegexp'); + } + $s = preg_replace_callback($titleRegexp, array(__CLASS__, 'title_case'), $s); } else { if (MB_CASE_UPPER == $mode) { static $upper = null; @@ -305,7 +315,7 @@ final class Mbstring static $ulenMask = array("\xC0" => 2, "\xD0" => 2, "\xE0" => 3, "\xF0" => 4); $i = 0; - $len = strlen($s); + $len = \strlen($s); while ($i < $len) { $ulen = $s[$i] < "\x80" ? 1 : $ulenMask[$s[$i] & "\xF0"]; @@ -314,7 +324,7 @@ final class Mbstring if (isset($map[$uchr])) { $uchr = $map[$uchr]; - $nlen = strlen($uchr); + $nlen = \strlen($uchr); if ($nlen == $ulen) { $nlen = $i; @@ -324,7 +334,7 @@ final class Mbstring } else { $s = substr_replace($s, $uchr, $i - $ulen, $ulen); $len += $nlen - $ulen; - $i += $nlen - $ulen; + $i += $nlen - $ulen; } } } @@ -404,7 +414,7 @@ final class Mbstring if (null === $encodingList) { $encodingList = self::$encodingList; } else { - if (!is_array($encodingList)) { + if (!\is_array($encodingList)) { $encodingList = array_map('trim', explode(',', $encodingList)); } $encodingList = array_map('strtoupper', $encodingList); @@ -441,7 +451,7 @@ final class Mbstring return self::$encodingList; } - if (!is_array($encodingList)) { + if (!\is_array($encodingList)) { $encodingList = array_map('trim', explode(',', $encodingList)); } $encodingList = array_map('strtoupper', $encodingList); @@ -452,6 +462,7 @@ final class Mbstring if (strncmp($enc, 'ISO-8859-', 9)) { return false; } + // no break case 'ASCII': case 'UTF8': case 'UTF-8': @@ -467,7 +478,7 @@ final class Mbstring { $encoding = self::getEncoding($encoding); if ('CP850' === $encoding || 'ASCII' === $encoding) { - return strlen($s); + return \strlen($s); } return @iconv_strlen($s, $encoding); @@ -513,6 +524,34 @@ final class Mbstring return false !== $pos ? $offset + $pos : false; } + public static function mb_str_split($string, $split_length = 1, $encoding = null) + { + if (null !== $string && !\is_scalar($string) && !(\is_object($string) && \method_exists($string, '__toString'))) { + trigger_error('mb_str_split() expects parameter 1 to be string, '.\gettype($string).' given', E_USER_WARNING); + + return null; + } + + if ($split_length < 1) { + trigger_error('The length of each segment must be greater than zero', E_USER_WARNING); + + return false; + } + + if (null === $encoding) { + $encoding = mb_internal_encoding(); + } + + $result = array(); + $length = mb_strlen($string, $encoding); + + for ($i = 0; $i < $length; $i += $split_length) { + $result[] = mb_substr($string, $i, $split_length, $encoding); + } + + return $result; + } + public static function mb_strtolower($s, $encoding = null) { return self::mb_convert_case($s, MB_CASE_LOWER, $encoding); @@ -536,7 +575,7 @@ final class Mbstring { $encoding = self::getEncoding($encoding); if ('CP850' === $encoding || 'ASCII' === $encoding) { - return substr($s, $start, null === $length ? 2147483647 : $length); + return (string) substr($s, $start, null === $length ? 2147483647 : $length); } if ($start < 0) { @@ -679,13 +718,13 @@ final class Mbstring public static function mb_chr($code, $encoding = null) { if (0x80 > $code %= 0x200000) { - $s = chr($code); + $s = \chr($code); } elseif (0x800 > $code) { - $s = chr(0xC0 | $code >> 6).chr(0x80 | $code & 0x3F); + $s = \chr(0xC0 | $code >> 6).\chr(0x80 | $code & 0x3F); } elseif (0x10000 > $code) { - $s = chr(0xE0 | $code >> 12).chr(0x80 | $code >> 6 & 0x3F).chr(0x80 | $code & 0x3F); + $s = \chr(0xE0 | $code >> 12).\chr(0x80 | $code >> 6 & 0x3F).\chr(0x80 | $code & 0x3F); } else { - $s = chr(0xF0 | $code >> 18).chr(0x80 | $code >> 12 & 0x3F).chr(0x80 | $code >> 6 & 0x3F).chr(0x80 | $code & 0x3F); + $s = \chr(0xF0 | $code >> 18).\chr(0x80 | $code >> 12 & 0x3F).\chr(0x80 | $code >> 6 & 0x3F).\chr(0x80 | $code & 0x3F); } if ('UTF-8' !== $encoding = self::getEncoding($encoding)) { @@ -701,6 +740,10 @@ final class Mbstring $s = mb_convert_encoding($s, 'UTF-8', $encoding); } + if (1 === \strlen($s)) { + return \ord($s); + } + $code = ($s = unpack('C*', substr($s, 0, 4))) ? $s[1] : 0; if (0xF0 <= $code) { return (($code - 0xF0) << 18) + (($s[2] - 0x80) << 12) + (($s[3] - 0x80) << 6) + $s[4] - 0x80; @@ -735,7 +778,7 @@ final class Mbstring while (isset($m[$i])) { if (0x80 > $m[$i]) { - $entities .= chr($m[$i++]); + $entities .= \chr($m[$i++]); continue; } if (0xF0 <= $m[$i]) { @@ -752,14 +795,9 @@ final class Mbstring return $entities; } - private static function title_case_lower(array $s) - { - return self::mb_convert_case($s[0], MB_CASE_LOWER, 'UTF-8'); - } - - private static function title_case_upper(array $s) + private static function title_case(array $s) { - return self::mb_convert_case($s[0], MB_CASE_UPPER, 'UTF-8'); + return self::mb_convert_case($s[1], MB_CASE_UPPER, 'UTF-8').self::mb_convert_case($s[2], MB_CASE_LOWER, 'UTF-8'); } private static function getData($file) diff --git a/vendor/symfony/polyfill-mbstring/Resources/unidata/lowerCase.php b/vendor/symfony/polyfill-mbstring/Resources/unidata/lowerCase.php index 3ca16416a82580b15bd446ba5cf75dc3d87fa922..e6fbfa64e6215a3e572d3d99f794cc6a85ea8af8 100644 --- a/vendor/symfony/polyfill-mbstring/Resources/unidata/lowerCase.php +++ b/vendor/symfony/polyfill-mbstring/Resources/unidata/lowerCase.php @@ -1,6 +1,6 @@ <?php -static $data = array ( +return array( 'A' => 'a', 'B' => 'b', 'C' => 'c', @@ -1094,8 +1094,3 @@ static $data = array ( 'ð‘¢¾' => '𑣞', '𑢿' => '𑣟', ); - -$result =& $data; -unset($data); - -return $result; diff --git a/vendor/symfony/polyfill-mbstring/Resources/unidata/titleCaseRegexp.php b/vendor/symfony/polyfill-mbstring/Resources/unidata/titleCaseRegexp.php new file mode 100644 index 0000000000000000000000000000000000000000..2a8f6e73b99301469991b2bb835324b39d96cd60 --- /dev/null +++ b/vendor/symfony/polyfill-mbstring/Resources/unidata/titleCaseRegexp.php @@ -0,0 +1,5 @@ +<?php + +// from Case_Ignorable in https://unicode.org/Public/UNIDATA/DerivedCoreProperties.txt + +return '/(?<![\x{0027}\x{002E}\x{003A}\x{005E}\x{0060}\x{00A8}\x{00AD}\x{00AF}\x{00B4}\x{00B7}\x{00B8}\x{02B0}-\x{02C1}\x{02C2}-\x{02C5}\x{02C6}-\x{02D1}\x{02D2}-\x{02DF}\x{02E0}-\x{02E4}\x{02E5}-\x{02EB}\x{02EC}\x{02ED}\x{02EE}\x{02EF}-\x{02FF}\x{0300}-\x{036F}\x{0374}\x{0375}\x{037A}\x{0384}-\x{0385}\x{0387}\x{0483}-\x{0487}\x{0488}-\x{0489}\x{0559}\x{0591}-\x{05BD}\x{05BF}\x{05C1}-\x{05C2}\x{05C4}-\x{05C5}\x{05C7}\x{05F4}\x{0600}-\x{0605}\x{0610}-\x{061A}\x{061C}\x{0640}\x{064B}-\x{065F}\x{0670}\x{06D6}-\x{06DC}\x{06DD}\x{06DF}-\x{06E4}\x{06E5}-\x{06E6}\x{06E7}-\x{06E8}\x{06EA}-\x{06ED}\x{070F}\x{0711}\x{0730}-\x{074A}\x{07A6}-\x{07B0}\x{07EB}-\x{07F3}\x{07F4}-\x{07F5}\x{07FA}\x{07FD}\x{0816}-\x{0819}\x{081A}\x{081B}-\x{0823}\x{0824}\x{0825}-\x{0827}\x{0828}\x{0829}-\x{082D}\x{0859}-\x{085B}\x{08D3}-\x{08E1}\x{08E2}\x{08E3}-\x{0902}\x{093A}\x{093C}\x{0941}-\x{0948}\x{094D}\x{0951}-\x{0957}\x{0962}-\x{0963}\x{0971}\x{0981}\x{09BC}\x{09C1}-\x{09C4}\x{09CD}\x{09E2}-\x{09E3}\x{09FE}\x{0A01}-\x{0A02}\x{0A3C}\x{0A41}-\x{0A42}\x{0A47}-\x{0A48}\x{0A4B}-\x{0A4D}\x{0A51}\x{0A70}-\x{0A71}\x{0A75}\x{0A81}-\x{0A82}\x{0ABC}\x{0AC1}-\x{0AC5}\x{0AC7}-\x{0AC8}\x{0ACD}\x{0AE2}-\x{0AE3}\x{0AFA}-\x{0AFF}\x{0B01}\x{0B3C}\x{0B3F}\x{0B41}-\x{0B44}\x{0B4D}\x{0B56}\x{0B62}-\x{0B63}\x{0B82}\x{0BC0}\x{0BCD}\x{0C00}\x{0C04}\x{0C3E}-\x{0C40}\x{0C46}-\x{0C48}\x{0C4A}-\x{0C4D}\x{0C55}-\x{0C56}\x{0C62}-\x{0C63}\x{0C81}\x{0CBC}\x{0CBF}\x{0CC6}\x{0CCC}-\x{0CCD}\x{0CE2}-\x{0CE3}\x{0D00}-\x{0D01}\x{0D3B}-\x{0D3C}\x{0D41}-\x{0D44}\x{0D4D}\x{0D62}-\x{0D63}\x{0DCA}\x{0DD2}-\x{0DD4}\x{0DD6}\x{0E31}\x{0E34}-\x{0E3A}\x{0E46}\x{0E47}-\x{0E4E}\x{0EB1}\x{0EB4}-\x{0EB9}\x{0EBB}-\x{0EBC}\x{0EC6}\x{0EC8}-\x{0ECD}\x{0F18}-\x{0F19}\x{0F35}\x{0F37}\x{0F39}\x{0F71}-\x{0F7E}\x{0F80}-\x{0F84}\x{0F86}-\x{0F87}\x{0F8D}-\x{0F97}\x{0F99}-\x{0FBC}\x{0FC6}\x{102D}-\x{1030}\x{1032}-\x{1037}\x{1039}-\x{103A}\x{103D}-\x{103E}\x{1058}-\x{1059}\x{105E}-\x{1060}\x{1071}-\x{1074}\x{1082}\x{1085}-\x{1086}\x{108D}\x{109D}\x{10FC}\x{135D}-\x{135F}\x{1712}-\x{1714}\x{1732}-\x{1734}\x{1752}-\x{1753}\x{1772}-\x{1773}\x{17B4}-\x{17B5}\x{17B7}-\x{17BD}\x{17C6}\x{17C9}-\x{17D3}\x{17D7}\x{17DD}\x{180B}-\x{180D}\x{180E}\x{1843}\x{1885}-\x{1886}\x{18A9}\x{1920}-\x{1922}\x{1927}-\x{1928}\x{1932}\x{1939}-\x{193B}\x{1A17}-\x{1A18}\x{1A1B}\x{1A56}\x{1A58}-\x{1A5E}\x{1A60}\x{1A62}\x{1A65}-\x{1A6C}\x{1A73}-\x{1A7C}\x{1A7F}\x{1AA7}\x{1AB0}-\x{1ABD}\x{1ABE}\x{1B00}-\x{1B03}\x{1B34}\x{1B36}-\x{1B3A}\x{1B3C}\x{1B42}\x{1B6B}-\x{1B73}\x{1B80}-\x{1B81}\x{1BA2}-\x{1BA5}\x{1BA8}-\x{1BA9}\x{1BAB}-\x{1BAD}\x{1BE6}\x{1BE8}-\x{1BE9}\x{1BED}\x{1BEF}-\x{1BF1}\x{1C2C}-\x{1C33}\x{1C36}-\x{1C37}\x{1C78}-\x{1C7D}\x{1CD0}-\x{1CD2}\x{1CD4}-\x{1CE0}\x{1CE2}-\x{1CE8}\x{1CED}\x{1CF4}\x{1CF8}-\x{1CF9}\x{1D2C}-\x{1D6A}\x{1D78}\x{1D9B}-\x{1DBF}\x{1DC0}-\x{1DF9}\x{1DFB}-\x{1DFF}\x{1FBD}\x{1FBF}-\x{1FC1}\x{1FCD}-\x{1FCF}\x{1FDD}-\x{1FDF}\x{1FED}-\x{1FEF}\x{1FFD}-\x{1FFE}\x{200B}-\x{200F}\x{2018}\x{2019}\x{2024}\x{2027}\x{202A}-\x{202E}\x{2060}-\x{2064}\x{2066}-\x{206F}\x{2071}\x{207F}\x{2090}-\x{209C}\x{20D0}-\x{20DC}\x{20DD}-\x{20E0}\x{20E1}\x{20E2}-\x{20E4}\x{20E5}-\x{20F0}\x{2C7C}-\x{2C7D}\x{2CEF}-\x{2CF1}\x{2D6F}\x{2D7F}\x{2DE0}-\x{2DFF}\x{2E2F}\x{3005}\x{302A}-\x{302D}\x{3031}-\x{3035}\x{303B}\x{3099}-\x{309A}\x{309B}-\x{309C}\x{309D}-\x{309E}\x{30FC}-\x{30FE}\x{A015}\x{A4F8}-\x{A4FD}\x{A60C}\x{A66F}\x{A670}-\x{A672}\x{A674}-\x{A67D}\x{A67F}\x{A69C}-\x{A69D}\x{A69E}-\x{A69F}\x{A6F0}-\x{A6F1}\x{A700}-\x{A716}\x{A717}-\x{A71F}\x{A720}-\x{A721}\x{A770}\x{A788}\x{A789}-\x{A78A}\x{A7F8}-\x{A7F9}\x{A802}\x{A806}\x{A80B}\x{A825}-\x{A826}\x{A8C4}-\x{A8C5}\x{A8E0}-\x{A8F1}\x{A8FF}\x{A926}-\x{A92D}\x{A947}-\x{A951}\x{A980}-\x{A982}\x{A9B3}\x{A9B6}-\x{A9B9}\x{A9BC}\x{A9CF}\x{A9E5}\x{A9E6}\x{AA29}-\x{AA2E}\x{AA31}-\x{AA32}\x{AA35}-\x{AA36}\x{AA43}\x{AA4C}\x{AA70}\x{AA7C}\x{AAB0}\x{AAB2}-\x{AAB4}\x{AAB7}-\x{AAB8}\x{AABE}-\x{AABF}\x{AAC1}\x{AADD}\x{AAEC}-\x{AAED}\x{AAF3}-\x{AAF4}\x{AAF6}\x{AB5B}\x{AB5C}-\x{AB5F}\x{ABE5}\x{ABE8}\x{ABED}\x{FB1E}\x{FBB2}-\x{FBC1}\x{FE00}-\x{FE0F}\x{FE13}\x{FE20}-\x{FE2F}\x{FE52}\x{FE55}\x{FEFF}\x{FF07}\x{FF0E}\x{FF1A}\x{FF3E}\x{FF40}\x{FF70}\x{FF9E}-\x{FF9F}\x{FFE3}\x{FFF9}-\x{FFFB}\x{101FD}\x{102E0}\x{10376}-\x{1037A}\x{10A01}-\x{10A03}\x{10A05}-\x{10A06}\x{10A0C}-\x{10A0F}\x{10A38}-\x{10A3A}\x{10A3F}\x{10AE5}-\x{10AE6}\x{10D24}-\x{10D27}\x{10F46}-\x{10F50}\x{11001}\x{11038}-\x{11046}\x{1107F}-\x{11081}\x{110B3}-\x{110B6}\x{110B9}-\x{110BA}\x{110BD}\x{110CD}\x{11100}-\x{11102}\x{11127}-\x{1112B}\x{1112D}-\x{11134}\x{11173}\x{11180}-\x{11181}\x{111B6}-\x{111BE}\x{111C9}-\x{111CC}\x{1122F}-\x{11231}\x{11234}\x{11236}-\x{11237}\x{1123E}\x{112DF}\x{112E3}-\x{112EA}\x{11300}-\x{11301}\x{1133B}-\x{1133C}\x{11340}\x{11366}-\x{1136C}\x{11370}-\x{11374}\x{11438}-\x{1143F}\x{11442}-\x{11444}\x{11446}\x{1145E}\x{114B3}-\x{114B8}\x{114BA}\x{114BF}-\x{114C0}\x{114C2}-\x{114C3}\x{115B2}-\x{115B5}\x{115BC}-\x{115BD}\x{115BF}-\x{115C0}\x{115DC}-\x{115DD}\x{11633}-\x{1163A}\x{1163D}\x{1163F}-\x{11640}\x{116AB}\x{116AD}\x{116B0}-\x{116B5}\x{116B7}\x{1171D}-\x{1171F}\x{11722}-\x{11725}\x{11727}-\x{1172B}\x{1182F}-\x{11837}\x{11839}-\x{1183A}\x{11A01}-\x{11A0A}\x{11A33}-\x{11A38}\x{11A3B}-\x{11A3E}\x{11A47}\x{11A51}-\x{11A56}\x{11A59}-\x{11A5B}\x{11A8A}-\x{11A96}\x{11A98}-\x{11A99}\x{11C30}-\x{11C36}\x{11C38}-\x{11C3D}\x{11C3F}\x{11C92}-\x{11CA7}\x{11CAA}-\x{11CB0}\x{11CB2}-\x{11CB3}\x{11CB5}-\x{11CB6}\x{11D31}-\x{11D36}\x{11D3A}\x{11D3C}-\x{11D3D}\x{11D3F}-\x{11D45}\x{11D47}\x{11D90}-\x{11D91}\x{11D95}\x{11D97}\x{11EF3}-\x{11EF4}\x{16AF0}-\x{16AF4}\x{16B30}-\x{16B36}\x{16B40}-\x{16B43}\x{16F8F}-\x{16F92}\x{16F93}-\x{16F9F}\x{16FE0}-\x{16FE1}\x{1BC9D}-\x{1BC9E}\x{1BCA0}-\x{1BCA3}\x{1D167}-\x{1D169}\x{1D173}-\x{1D17A}\x{1D17B}-\x{1D182}\x{1D185}-\x{1D18B}\x{1D1AA}-\x{1D1AD}\x{1D242}-\x{1D244}\x{1DA00}-\x{1DA36}\x{1DA3B}-\x{1DA6C}\x{1DA75}\x{1DA84}\x{1DA9B}-\x{1DA9F}\x{1DAA1}-\x{1DAAF}\x{1E000}-\x{1E006}\x{1E008}-\x{1E018}\x{1E01B}-\x{1E021}\x{1E023}-\x{1E024}\x{1E026}-\x{1E02A}\x{1E8D0}-\x{1E8D6}\x{1E944}-\x{1E94A}\x{1F3FB}-\x{1F3FF}\x{E0001}\x{E0020}-\x{E007F}\x{E0100}-\x{E01EF}])(\pL)(\pL*+)/u'; diff --git a/vendor/symfony/polyfill-mbstring/Resources/unidata/upperCase.php b/vendor/symfony/polyfill-mbstring/Resources/unidata/upperCase.php index ec9422121cae73c8baa8d0cfc695897a5c091961..b8103b2e808dd0a670c04868f20edcc969ea7e70 100644 --- a/vendor/symfony/polyfill-mbstring/Resources/unidata/upperCase.php +++ b/vendor/symfony/polyfill-mbstring/Resources/unidata/upperCase.php @@ -1,6 +1,6 @@ <?php -static $data = array ( +return array( 'a' => 'A', 'b' => 'B', 'c' => 'C', @@ -1102,8 +1102,3 @@ static $data = array ( '𑣞' => 'ð‘¢¾', '𑣟' => '𑢿', ); - -$result =& $data; -unset($data); - -return $result; diff --git a/vendor/symfony/polyfill-mbstring/bootstrap.php b/vendor/symfony/polyfill-mbstring/bootstrap.php index 2fdcc5a6f69ceb58f3e948cac4d99bb20edb4fbf..204a41ba271e343369ecf9a63d617aae7f5271bc 100644 --- a/vendor/symfony/polyfill-mbstring/bootstrap.php +++ b/vendor/symfony/polyfill-mbstring/bootstrap.php @@ -56,3 +56,7 @@ if (!function_exists('mb_chr')) { function mb_chr($code, $enc = null) { return p\Mbstring::mb_chr($code, $enc); } function mb_scrub($s, $enc = null) { $enc = null === $enc ? mb_internal_encoding() : $enc; return mb_convert_encoding($s, $enc, $enc); } } + +if (!function_exists('mb_str_split')) { + function mb_str_split($string, $split_length = 1, $encoding = null) { return p\Mbstring::mb_str_split($string, $split_length, $encoding); } +} diff --git a/vendor/symfony/polyfill-mbstring/composer.json b/vendor/symfony/polyfill-mbstring/composer.json index 4febcdd5c0051eb3b0dc1cd71114f7b27eee0e16..308f009a10a0dab6632cc54d286a0c115295df2f 100644 --- a/vendor/symfony/polyfill-mbstring/composer.json +++ b/vendor/symfony/polyfill-mbstring/composer.json @@ -28,7 +28,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-master": "1.7-dev" + "dev-master": "1.12-dev" } } } diff --git a/vendor/symfony/polyfill-php70/Php70.php b/vendor/symfony/polyfill-php70/Php70.php deleted file mode 100644 index 8e7845066399b456741bba723f56ecfeb99ccae8..0000000000000000000000000000000000000000 --- a/vendor/symfony/polyfill-php70/Php70.php +++ /dev/null @@ -1,74 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Polyfill\Php70; - -/** - * @author Nicolas Grekas <p@tchwork.com> - * - * @internal - */ -final class Php70 -{ - public static function intdiv($dividend, $divisor) - { - $dividend = self::intArg($dividend, __FUNCTION__, 1); - $divisor = self::intArg($divisor, __FUNCTION__, 2); - - if (0 === $divisor) { - throw new \DivisionByZeroError('Division by zero'); - } - if (-1 === $divisor && ~PHP_INT_MAX === $dividend) { - throw new \ArithmeticError('Division of PHP_INT_MIN by -1 is not an integer'); - } - - return ($dividend - ($dividend % $divisor)) / $divisor; - } - - public static function preg_replace_callback_array(array $patterns, $subject, $limit = -1, &$count = 0) - { - $count = 0; - $result = (string) $subject; - if (0 === $limit = self::intArg($limit, __FUNCTION__, 3)) { - return $result; - } - - foreach ($patterns as $pattern => $callback) { - $result = preg_replace_callback($pattern, $callback, $result, $limit, $c); - $count += $c; - } - - return $result; - } - - public static function error_clear_last() - { - static $handler; - if (!$handler) { - $handler = function() { return false; }; - } - set_error_handler($handler); - @trigger_error(''); - restore_error_handler(); - } - - public static function intArg($value, $caller, $pos) - { - if (is_int($value)) { - return $value; - } - if (!is_numeric($value) || PHP_INT_MAX <= ($value += 0) || ~PHP_INT_MAX >= $value) { - throw new \TypeError(sprintf('%s() expects parameter %d to be integer, %s given', $caller, $pos, gettype($value))); - } - - return (int) $value; - } -} diff --git a/vendor/symfony/polyfill-php70/README.md b/vendor/symfony/polyfill-php70/README.md deleted file mode 100644 index 04988c6f93571afa9b2d2a32e8701043441ce26c..0000000000000000000000000000000000000000 --- a/vendor/symfony/polyfill-php70/README.md +++ /dev/null @@ -1,28 +0,0 @@ -Symfony Polyfill / Php70 -======================== - -This component provides features unavailable in releases prior to PHP 7.0: - -- [`intdiv`](http://php.net/intdiv) -- [`preg_replace_callback_array`](http://php.net/preg_replace_callback_array) -- [`error_clear_last`](http://php.net/error_clear_last) -- `random_bytes` and `random_int` (from [paragonie/random_compat](https://github.com/paragonie/random_compat)) -- [`*Error` throwable classes](http://php.net/Error) -- [`PHP_INT_MIN`](http://php.net/manual/en/reserved.constants.php#constant.php-int-min) -- `SessionUpdateTimestampHandlerInterface` - -More information can be found in the -[main Polyfill README](https://github.com/symfony/polyfill/blob/master/README.md). - -Compatibility notes -=================== - -To write portable code between PHP5 and PHP7, some care must be taken: -- `\*Error` exceptions must be caught before `\Exception`; -- after calling `error_clear_last()`, the result of `$e = error_get_last()` must be - verified using `isset($e['message'][0])` instead of `null !== $e`. - -License -======= - -This library is released under the [MIT license](LICENSE). diff --git a/vendor/symfony/polyfill-php70/Resources/stubs/ArithmeticError.php b/vendor/symfony/polyfill-php70/Resources/stubs/ArithmeticError.php deleted file mode 100644 index 68191244625989ccc21e579a4b321b5e79d6660c..0000000000000000000000000000000000000000 --- a/vendor/symfony/polyfill-php70/Resources/stubs/ArithmeticError.php +++ /dev/null @@ -1,5 +0,0 @@ -<?php - -class ArithmeticError extends Error -{ -} diff --git a/vendor/symfony/polyfill-php70/Resources/stubs/AssertionError.php b/vendor/symfony/polyfill-php70/Resources/stubs/AssertionError.php deleted file mode 100644 index acb125080f798881790a72e505a9bf6d5aee5800..0000000000000000000000000000000000000000 --- a/vendor/symfony/polyfill-php70/Resources/stubs/AssertionError.php +++ /dev/null @@ -1,5 +0,0 @@ -<?php - -class AssertionError extends Error -{ -} diff --git a/vendor/symfony/polyfill-php70/Resources/stubs/DivisionByZeroError.php b/vendor/symfony/polyfill-php70/Resources/stubs/DivisionByZeroError.php deleted file mode 100644 index c99278b31d71290acf06f01c9dbe814756c5d68f..0000000000000000000000000000000000000000 --- a/vendor/symfony/polyfill-php70/Resources/stubs/DivisionByZeroError.php +++ /dev/null @@ -1,5 +0,0 @@ -<?php - -class DivisionByZeroError extends Error -{ -} diff --git a/vendor/symfony/polyfill-php70/Resources/stubs/Error.php b/vendor/symfony/polyfill-php70/Resources/stubs/Error.php deleted file mode 100644 index 405847fb891b72772f66dcca131cfece6709b1f2..0000000000000000000000000000000000000000 --- a/vendor/symfony/polyfill-php70/Resources/stubs/Error.php +++ /dev/null @@ -1,5 +0,0 @@ -<?php - -class Error extends Exception -{ -} diff --git a/vendor/symfony/polyfill-php70/Resources/stubs/ParseError.php b/vendor/symfony/polyfill-php70/Resources/stubs/ParseError.php deleted file mode 100644 index 2dd447dd4314a6da483be9763cf9ab99aa2787a5..0000000000000000000000000000000000000000 --- a/vendor/symfony/polyfill-php70/Resources/stubs/ParseError.php +++ /dev/null @@ -1,5 +0,0 @@ -<?php - -class ParseError extends Error -{ -} diff --git a/vendor/symfony/polyfill-php70/Resources/stubs/SessionUpdateTimestampHandlerInterface.php b/vendor/symfony/polyfill-php70/Resources/stubs/SessionUpdateTimestampHandlerInterface.php deleted file mode 100644 index 0cc02c8f92c35687fac53151d6eb6729bada1779..0000000000000000000000000000000000000000 --- a/vendor/symfony/polyfill-php70/Resources/stubs/SessionUpdateTimestampHandlerInterface.php +++ /dev/null @@ -1,23 +0,0 @@ -<?php - -interface SessionUpdateTimestampHandlerInterface -{ - /** - * Checks if a session identifier already exists or not. - * - * @param string $key - * - * @return bool - */ - public function validateId($key); - - /** - * Updates the timestamp of a session when its data didn't change. - * - * @param string $key - * @param string $val - * - * @return bool - */ - public function updateTimestamp($key, $val); -} diff --git a/vendor/symfony/polyfill-php70/Resources/stubs/TypeError.php b/vendor/symfony/polyfill-php70/Resources/stubs/TypeError.php deleted file mode 100644 index 2bed1b48317528da308a71512e4191c8d3c33f0b..0000000000000000000000000000000000000000 --- a/vendor/symfony/polyfill-php70/Resources/stubs/TypeError.php +++ /dev/null @@ -1,5 +0,0 @@ -<?php - -class TypeError extends Error -{ -} diff --git a/vendor/symfony/polyfill-php70/bootstrap.php b/vendor/symfony/polyfill-php70/bootstrap.php deleted file mode 100644 index 445c39839c4f7dd4bcc4e942dd17f18d6fe36199..0000000000000000000000000000000000000000 --- a/vendor/symfony/polyfill-php70/bootstrap.php +++ /dev/null @@ -1,27 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -use Symfony\Polyfill\Php70 as p; - -if (PHP_VERSION_ID < 70000) { - if (!defined('PHP_INT_MIN')) { - define('PHP_INT_MIN', ~PHP_INT_MAX); - } - if (!function_exists('intdiv')) { - function intdiv($dividend, $divisor) { return p\Php70::intdiv($dividend, $divisor); } - } - if (!function_exists('preg_replace_callback_array')) { - function preg_replace_callback_array(array $patterns, $subject, $limit = -1, &$count = 0) { return p\Php70::preg_replace_callback_array($patterns, $subject, $limit, $count); } - } - if (!function_exists('error_clear_last')) { - function error_clear_last() { return p\Php70::error_clear_last(); } - } -} diff --git a/vendor/symfony/polyfill-php72/LICENSE b/vendor/symfony/polyfill-php72/LICENSE new file mode 100644 index 0000000000000000000000000000000000000000..4cd8bdd3007da4d62985ec9e5ca81a1e18ae34d1 --- /dev/null +++ b/vendor/symfony/polyfill-php72/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2015-2019 Fabien Potencier + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/vendor/symfony/polyfill-php72/Php72.php b/vendor/symfony/polyfill-php72/Php72.php new file mode 100644 index 0000000000000000000000000000000000000000..d531e8441bff9f706fe9de1a0a76f27201b7fbe8 --- /dev/null +++ b/vendor/symfony/polyfill-php72/Php72.php @@ -0,0 +1,216 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Polyfill\Php72; + +/** + * @author Nicolas Grekas <p@tchwork.com> + * @author Dariusz RumiÅ„ski <dariusz.ruminski@gmail.com> + * + * @internal + */ +final class Php72 +{ + private static $hashMask; + + public static function utf8_encode($s) + { + $s .= $s; + $len = \strlen($s); + + for ($i = $len >> 1, $j = 0; $i < $len; ++$i, ++$j) { + switch (true) { + case $s[$i] < "\x80": $s[$j] = $s[$i]; break; + case $s[$i] < "\xC0": $s[$j] = "\xC2"; $s[++$j] = $s[$i]; break; + default: $s[$j] = "\xC3"; $s[++$j] = \chr(\ord($s[$i]) - 64); break; + } + } + + return substr($s, 0, $j); + } + + public static function utf8_decode($s) + { + $s = (string) $s; + $len = \strlen($s); + + for ($i = 0, $j = 0; $i < $len; ++$i, ++$j) { + switch ($s[$i] & "\xF0") { + case "\xC0": + case "\xD0": + $c = (\ord($s[$i] & "\x1F") << 6) | \ord($s[++$i] & "\x3F"); + $s[$j] = $c < 256 ? \chr($c) : '?'; + break; + + case "\xF0": + ++$i; + // no break + + case "\xE0": + $s[$j] = '?'; + $i += 2; + break; + + default: + $s[$j] = $s[$i]; + } + } + + return substr($s, 0, $j); + } + + public static function php_os_family() + { + if ('\\' === \DIRECTORY_SEPARATOR) { + return 'Windows'; + } + + $map = array( + 'Darwin' => 'Darwin', + 'DragonFly' => 'BSD', + 'FreeBSD' => 'BSD', + 'NetBSD' => 'BSD', + 'OpenBSD' => 'BSD', + 'Linux' => 'Linux', + 'SunOS' => 'Solaris', + ); + + return isset($map[PHP_OS]) ? $map[PHP_OS] : 'Unknown'; + } + + public static function spl_object_id($object) + { + if (null === self::$hashMask) { + self::initHashMask(); + } + if (null === $hash = spl_object_hash($object)) { + return; + } + + return self::$hashMask ^ hexdec(substr($hash, 16 - \PHP_INT_SIZE, \PHP_INT_SIZE)); + } + + public static function sapi_windows_vt100_support($stream, $enable = null) + { + if (!\is_resource($stream)) { + trigger_error('sapi_windows_vt100_support() expects parameter 1 to be resource, '.\gettype($stream).' given', E_USER_WARNING); + + return false; + } + + $meta = stream_get_meta_data($stream); + + if ('STDIO' !== $meta['stream_type']) { + trigger_error('sapi_windows_vt100_support() was not able to analyze the specified stream', E_USER_WARNING); + + return false; + } + + // We cannot actually disable vt100 support if it is set + if (false === $enable || !self::stream_isatty($stream)) { + return false; + } + + // The native function does not apply to stdin + $meta = array_map('strtolower', $meta); + $stdin = 'php://stdin' === $meta['uri'] || 'php://fd/0' === $meta['uri']; + + return !$stdin + && (false !== getenv('ANSICON') + || 'ON' === getenv('ConEmuANSI') + || 'xterm' === getenv('TERM') + || 'Hyper' === getenv('TERM_PROGRAM')); + } + + public static function stream_isatty($stream) + { + if (!\is_resource($stream)) { + trigger_error('stream_isatty() expects parameter 1 to be resource, '.\gettype($stream).' given', E_USER_WARNING); + + return false; + } + + if ('\\' === \DIRECTORY_SEPARATOR) { + $stat = @fstat($stream); + // Check if formatted mode is S_IFCHR + return $stat ? 0020000 === ($stat['mode'] & 0170000) : false; + } + + return \function_exists('posix_isatty') && @posix_isatty($stream); + } + + private static function initHashMask() + { + $obj = (object) array(); + self::$hashMask = -1; + + // check if we are nested in an output buffering handler to prevent a fatal error with ob_start() below + $obFuncs = array('ob_clean', 'ob_end_clean', 'ob_flush', 'ob_end_flush', 'ob_get_contents', 'ob_get_flush'); + foreach (debug_backtrace(\PHP_VERSION_ID >= 50400 ? DEBUG_BACKTRACE_IGNORE_ARGS : false) as $frame) { + if (isset($frame['function'][0]) && !isset($frame['class']) && 'o' === $frame['function'][0] && \in_array($frame['function'], $obFuncs)) { + $frame['line'] = 0; + break; + } + } + if (!empty($frame['line'])) { + ob_start(); + debug_zval_dump($obj); + self::$hashMask = (int) substr(ob_get_clean(), 17); + } + + self::$hashMask ^= hexdec(substr(spl_object_hash($obj), 16 - \PHP_INT_SIZE, \PHP_INT_SIZE)); + } + + public static function mb_chr($code, $encoding = null) + { + if (0x80 > $code %= 0x200000) { + $s = \chr($code); + } elseif (0x800 > $code) { + $s = \chr(0xC0 | $code >> 6).\chr(0x80 | $code & 0x3F); + } elseif (0x10000 > $code) { + $s = \chr(0xE0 | $code >> 12).\chr(0x80 | $code >> 6 & 0x3F).\chr(0x80 | $code & 0x3F); + } else { + $s = \chr(0xF0 | $code >> 18).\chr(0x80 | $code >> 12 & 0x3F).\chr(0x80 | $code >> 6 & 0x3F).\chr(0x80 | $code & 0x3F); + } + + if ('UTF-8' !== $encoding) { + $s = mb_convert_encoding($s, $encoding, 'UTF-8'); + } + + return $s; + } + + public static function mb_ord($s, $encoding = null) + { + if (null == $encoding) { + $s = mb_convert_encoding($s, 'UTF-8'); + } elseif ('UTF-8' !== $encoding) { + $s = mb_convert_encoding($s, 'UTF-8', $encoding); + } + + if (1 === \strlen($s)) { + return \ord($s); + } + + $code = ($s = unpack('C*', substr($s, 0, 4))) ? $s[1] : 0; + if (0xF0 <= $code) { + return (($code - 0xF0) << 18) + (($s[2] - 0x80) << 12) + (($s[3] - 0x80) << 6) + $s[4] - 0x80; + } + if (0xE0 <= $code) { + return (($code - 0xE0) << 12) + (($s[2] - 0x80) << 6) + $s[3] - 0x80; + } + if (0xC0 <= $code) { + return (($code - 0xC0) << 6) + $s[2] - 0x80; + } + + return $code; + } +} diff --git a/vendor/symfony/polyfill-php72/README.md b/vendor/symfony/polyfill-php72/README.md new file mode 100644 index 0000000000000000000000000000000000000000..82c45f7a58609564f91c44767789c3ee0664991c --- /dev/null +++ b/vendor/symfony/polyfill-php72/README.md @@ -0,0 +1,27 @@ +Symfony Polyfill / Php72 +======================== + +This component provides functions added to PHP 7.2 core: + +- [`spl_object_id`](https://php.net/spl_object_id) +- [`stream_isatty`](https://php.net/stream_isatty) + +On Windows only: + +- [`sapi_windows_vt100_support`](https://php.net/sapi_windows_vt100_support) + +Moved to core since 7.2 (was in the optional XML extension earlier): + +- [`utf8_encode`](https://php.net/utf8_encode) +- [`utf8_decode`](https://php.net/utf8_decode) + +Also, it provides a constant added to PHP 7.2: +- [`PHP_OS_FAMILY`](http://php.net/manual/en/reserved.constants.php#constant.php-os-family) + +More information can be found in the +[main Polyfill README](https://github.com/symfony/polyfill/blob/master/README.md). + +License +======= + +This library is released under the [MIT license](LICENSE). diff --git a/vendor/symfony/polyfill-php72/bootstrap.php b/vendor/symfony/polyfill-php72/bootstrap.php new file mode 100644 index 0000000000000000000000000000000000000000..519056de4aa1ec2b25b06b77b4dad800720c5016 --- /dev/null +++ b/vendor/symfony/polyfill-php72/bootstrap.php @@ -0,0 +1,36 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use Symfony\Polyfill\Php72 as p; + +if (PHP_VERSION_ID < 70200) { + if ('\\' === DIRECTORY_SEPARATOR && !function_exists('sapi_windows_vt100_support')) { + function sapi_windows_vt100_support($stream, $enable = null) { return p\Php72::sapi_windows_vt100_support($stream, $enable); } + } + if (!function_exists('stream_isatty')) { + function stream_isatty($stream) { return p\Php72::stream_isatty($stream); } + } + if (!function_exists('utf8_encode')) { + function utf8_encode($s) { return p\Php72::utf8_encode($s); } + function utf8_decode($s) { return p\Php72::utf8_decode($s); } + } + if (!function_exists('spl_object_id')) { + function spl_object_id($s) { return p\Php72::spl_object_id($s); } + } + if (!defined('PHP_OS_FAMILY')) { + define('PHP_OS_FAMILY', p\Php72::php_os_family()); + } + if (!function_exists('mb_chr')) { + function mb_ord($s, $enc = null) { return p\Php72::mb_ord($s, $enc); } + function mb_chr($code, $enc = null) { return p\Php72::mb_chr($code, $enc); } + function mb_scrub($s, $enc = null) { $enc = null === $enc ? mb_internal_encoding() : $enc; return mb_convert_encoding($s, $enc, $enc); } + } +} diff --git a/vendor/symfony/polyfill-php72/composer.json b/vendor/symfony/polyfill-php72/composer.json new file mode 100644 index 0000000000000000000000000000000000000000..5cfcbb757868847c87b6cd7c7c38dbfb9db5e766 --- /dev/null +++ b/vendor/symfony/polyfill-php72/composer.json @@ -0,0 +1,31 @@ +{ + "name": "symfony/polyfill-php72", + "type": "library", + "description": "Symfony polyfill backporting some PHP 7.2+ features to lower PHP versions", + "keywords": ["polyfill", "shim", "compatibility", "portable"], + "homepage": "https://symfony.com", + "license": "MIT", + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "require": { + "php": ">=5.3.3" + }, + "autoload": { + "psr-4": { "Symfony\\Polyfill\\Php72\\": "" }, + "files": [ "bootstrap.php" ] + }, + "minimum-stability": "dev", + "extra": { + "branch-alias": { + "dev-master": "1.12-dev" + } + } +} diff --git a/vendor/symfony/polyfill-php73/LICENSE b/vendor/symfony/polyfill-php73/LICENSE new file mode 100644 index 0000000000000000000000000000000000000000..3f853aaf35fe186d4016761eb6e8a403de3e6e0d --- /dev/null +++ b/vendor/symfony/polyfill-php73/LICENSE @@ -0,0 +1,19 @@ +Copyright (c) 2018-2019 Fabien Potencier + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is furnished +to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/vendor/symfony/polyfill-php73/Php73.php b/vendor/symfony/polyfill-php73/Php73.php new file mode 100644 index 0000000000000000000000000000000000000000..7c99d1972a05af1f980fab27c1f5078fd33cf14b --- /dev/null +++ b/vendor/symfony/polyfill-php73/Php73.php @@ -0,0 +1,43 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Polyfill\Php73; + +/** + * @author Gabriel Caruso <carusogabriel34@gmail.com> + * @author Ion Bazan <ion.bazan@gmail.com> + * + * @internal + */ +final class Php73 +{ + public static $startAt = 1533462603; + + /** + * @param bool $asNum + * + * @return array|float|int + */ + public static function hrtime($asNum = false) + { + $ns = microtime(false); + $s = substr($ns, 11) - self::$startAt; + $ns = 1E9 * (float) $ns; + + if ($asNum) { + $ns += $s * 1E9; + + return \PHP_INT_SIZE === 4 ? $ns : (int) $ns; + } + + return array($s, (int) $ns); + } +} diff --git a/vendor/symfony/polyfill-php73/README.md b/vendor/symfony/polyfill-php73/README.md new file mode 100644 index 0000000000000000000000000000000000000000..b3ebbce511bcd3840e6565753a9854b6f459cefe --- /dev/null +++ b/vendor/symfony/polyfill-php73/README.md @@ -0,0 +1,18 @@ +Symfony Polyfill / Php73 +======================== + +This component provides functions added to PHP 7.3 core: + +- [`array_key_first`](https://php.net/array_key_first) +- [`array_key_last`](https://php.net/array_key_last) +- [`hrtime`](https://php.net/function.hrtime) +- [`is_countable`](https://php.net/is_countable) +- [`JsonException`](https://php.net/JsonException) + +More information can be found in the +[main Polyfill README](https://github.com/symfony/polyfill/blob/master/README.md). + +License +======= + +This library is released under the [MIT license](LICENSE). diff --git a/vendor/symfony/http-kernel/Tests/Fixtures/ExtensionLoadedBundle/ExtensionLoadedBundle.php b/vendor/symfony/polyfill-php73/Resources/stubs/JsonException.php similarity index 58% rename from vendor/symfony/http-kernel/Tests/Fixtures/ExtensionLoadedBundle/ExtensionLoadedBundle.php rename to vendor/symfony/polyfill-php73/Resources/stubs/JsonException.php index 3af81cb07396dc00669251e7ec6890d9cc124b60..673d100224854a8d9c0dc429cf4dfd5b3bef0726 100644 --- a/vendor/symfony/http-kernel/Tests/Fixtures/ExtensionLoadedBundle/ExtensionLoadedBundle.php +++ b/vendor/symfony/polyfill-php73/Resources/stubs/JsonException.php @@ -9,10 +9,6 @@ * file that was distributed with this source code. */ -namespace Symfony\Component\HttpKernel\Tests\Fixtures\ExtensionLoadedBundle; - -use Symfony\Component\HttpKernel\Bundle\Bundle; - -class ExtensionLoadedBundle extends Bundle +class JsonException extends Exception { } diff --git a/vendor/symfony/polyfill-php73/bootstrap.php b/vendor/symfony/polyfill-php73/bootstrap.php new file mode 100644 index 0000000000000000000000000000000000000000..4c3f44f6bf8247cadfc4a8cea9b67f20d857fc81 --- /dev/null +++ b/vendor/symfony/polyfill-php73/bootstrap.php @@ -0,0 +1,32 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use Symfony\Polyfill\Php73 as p; + +if (PHP_VERSION_ID < 70300) { + if (!function_exists('is_countable')) { + function is_countable($var) { return is_array($var) || $var instanceof Countable || $var instanceof ResourceBundle || $var instanceof SimpleXmlElement; } + } + + if (!function_exists('hrtime')) { + require_once __DIR__.'/Php73.php'; + p\Php73::$startAt = (int) microtime(true); + function hrtime($asNum = false) { return p\Php73::hrtime($asNum); } + } + + if (!function_exists('array_key_first')) { + function array_key_first(array $array) { foreach ($array as $key => $value) { return $key; } } + } + + if (!function_exists('array_key_last')) { + function array_key_last(array $array) { end($array); return key($array); } + } +} diff --git a/vendor/symfony/polyfill-php70/composer.json b/vendor/symfony/polyfill-php73/composer.json similarity index 70% rename from vendor/symfony/polyfill-php70/composer.json rename to vendor/symfony/polyfill-php73/composer.json index 88ff357a56b0591146dad2233ef4717de236c275..92808af8f983e10a5ca63298add09ceffa195593 100644 --- a/vendor/symfony/polyfill-php70/composer.json +++ b/vendor/symfony/polyfill-php73/composer.json @@ -1,7 +1,7 @@ { - "name": "symfony/polyfill-php70", + "name": "symfony/polyfill-php73", "type": "library", - "description": "Symfony polyfill backporting some PHP 7.0+ features to lower PHP versions", + "description": "Symfony polyfill backporting some PHP 7.3+ features to lower PHP versions", "keywords": ["polyfill", "shim", "compatibility", "portable"], "homepage": "https://symfony.com", "license": "MIT", @@ -16,18 +16,17 @@ } ], "require": { - "php": ">=5.3.3", - "paragonie/random_compat": "~1.0|~2.0" + "php": ">=5.3.3" }, "autoload": { - "psr-4": { "Symfony\\Polyfill\\Php70\\": "" }, + "psr-4": { "Symfony\\Polyfill\\Php73\\": "" }, "files": [ "bootstrap.php" ], "classmap": [ "Resources/stubs" ] }, "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-master": "1.7-dev" + "dev-master": "1.12-dev" } } } diff --git a/vendor/symfony/routing/Annotation/Route.php b/vendor/symfony/routing/Annotation/Route.php index 5b3cbeaab1848223d9f179095e2e26b3c45abb13..4d5f6181155912f9ae0abbef45b78824204e14fb 100644 --- a/vendor/symfony/routing/Annotation/Route.php +++ b/vendor/symfony/routing/Annotation/Route.php @@ -22,14 +22,18 @@ namespace Symfony\Component\Routing\Annotation; class Route { private $path; + private $localizedPaths = []; private $name; - private $requirements = array(); - private $options = array(); - private $defaults = array(); + private $requirements = []; + private $options = []; + private $defaults = []; private $host; - private $methods = array(); - private $schemes = array(); + private $methods = []; + private $schemes = []; private $condition; + private $locale; + private $format; + private $utf8; /** * @param array $data An array of key/value parameters @@ -38,15 +42,39 @@ class Route */ public function __construct(array $data) { + if (isset($data['localized_paths'])) { + throw new \BadMethodCallException(sprintf('Unknown property "localized_paths" on annotation "%s".', \get_class($this))); + } + if (isset($data['value'])) { - $data['path'] = $data['value']; + $data[\is_array($data['value']) ? 'localized_paths' : 'path'] = $data['value']; unset($data['value']); } + if (isset($data['path']) && \is_array($data['path'])) { + $data['localized_paths'] = $data['path']; + unset($data['path']); + } + + if (isset($data['locale'])) { + $data['defaults']['_locale'] = $data['locale']; + unset($data['locale']); + } + + if (isset($data['format'])) { + $data['defaults']['_format'] = $data['format']; + unset($data['format']); + } + + if (isset($data['utf8'])) { + $data['options']['utf8'] = filter_var($data['utf8'], FILTER_VALIDATE_BOOLEAN) ?: false; + unset($data['utf8']); + } + foreach ($data as $key => $value) { $method = 'set'.str_replace('_', '', $key); if (!method_exists($this, $method)) { - throw new \BadMethodCallException(sprintf('Unknown property "%s" on annotation "%s".', $key, get_class($this))); + throw new \BadMethodCallException(sprintf('Unknown property "%s" on annotation "%s".', $key, \get_class($this))); } $this->$method($value); } @@ -62,6 +90,16 @@ class Route return $this->path; } + public function setLocalizedPaths(array $localizedPaths) + { + $this->localizedPaths = $localizedPaths; + } + + public function getLocalizedPaths(): array + { + return $this->localizedPaths; + } + public function setHost($pattern) { $this->host = $pattern; @@ -114,7 +152,7 @@ class Route public function setSchemes($schemes) { - $this->schemes = is_array($schemes) ? $schemes : array($schemes); + $this->schemes = \is_array($schemes) ? $schemes : [$schemes]; } public function getSchemes() @@ -124,7 +162,7 @@ class Route public function setMethods($methods) { - $this->methods = is_array($methods) ? $methods : array($methods); + $this->methods = \is_array($methods) ? $methods : [$methods]; } public function getMethods() diff --git a/vendor/symfony/routing/CHANGELOG.md b/vendor/symfony/routing/CHANGELOG.md index e278f8b1e593688f4e7a5b5e546c69bb90b03b3e..5f133efd6ef9cb23ebd828635fdecc1e67497282 100644 --- a/vendor/symfony/routing/CHANGELOG.md +++ b/vendor/symfony/routing/CHANGELOG.md @@ -1,6 +1,30 @@ CHANGELOG ========= +4.3.0 +----- + + * added `CompiledUrlMatcher` and `CompiledUrlMatcherDumper` + * added `CompiledUrlGenerator` and `CompiledUrlGeneratorDumper` + * deprecated `PhpGeneratorDumper` and `PhpMatcherDumper` + * deprecated `generator_base_class`, `generator_cache_class`, `matcher_base_class` and `matcher_cache_class` router options + * `Serializable` implementing methods for `Route` and `CompiledRoute` are marked as `@internal` and `@final`. + Instead of overwriting them, use `__serialize` and `__unserialize` as extension points which are forward compatible + with the new serialization methods in PHP 7.4. + * exposed `utf8` Route option, defaults "locale" and "format" in configuration loaders and configurators + * added support for invokable service route loaders + +4.2.0 +----- + + * added fallback to cultureless locale for internationalized routes + +4.0.0 +----- + + * dropped support for using UTF-8 route patterns without using the `utf8` option + * dropped support for using UTF-8 route requirements without using the `utf8` option + 3.4.0 ----- @@ -41,7 +65,7 @@ CHANGELOG Before: ```php - $router->generate('blog_show', array('slug' => 'my-blog-post'), true); + $router->generate('blog_show', ['slug' => 'my-blog-post'], true); ``` After: @@ -49,7 +73,7 @@ CHANGELOG ```php use Symfony\Component\Routing\Generator\UrlGeneratorInterface; - $router->generate('blog_show', array('slug' => 'my-blog-post'), UrlGeneratorInterface::ABSOLUTE_URL); + $router->generate('blog_show', ['slug' => 'my-blog-post'], UrlGeneratorInterface::ABSOLUTE_URL); ``` 2.5.0 @@ -57,7 +81,7 @@ CHANGELOG * [DEPRECATION] The `ApacheMatcherDumper` and `ApacheUrlMatcher` were deprecated and will be removed in Symfony 3.0, since the performance gains were minimal and - it's hard to replicate the behaviour of PHP implementation. + it's hard to replicate the behavior of PHP implementation. 2.3.0 ----- @@ -114,7 +138,7 @@ CHANGELOG ```php $route = new Route(); $route->setPath('/article/{id}'); - $route->setMethods(array('POST', 'PUT')); + $route->setMethods(['POST', 'PUT']); $route->setSchemes('https'); ``` @@ -169,10 +193,10 @@ CHANGELOG used with a single parameter. The other params `$prefix`, `$default`, `$requirements` and `$options` will still work, but have been deprecated. The `addPrefix` method should be used for this use-case instead. - Before: `$parentCollection->addCollection($collection, '/prefix', array(...), array(...))` + Before: `$parentCollection->addCollection($collection, '/prefix', [...], [...])` After: ```php - $collection->addPrefix('/prefix', array(...), array(...)); + $collection->addPrefix('/prefix', [...], [...]); $parentCollection->addCollection($collection); ``` * added support for the method default argument values when defining a @Route @@ -197,7 +221,7 @@ CHANGELOG (only relevant if you implemented your own RouteCompiler). * Added possibility to generate relative paths and network paths in the UrlGenerator, e.g. "../parent-file" and "//example.com/dir/file". The third parameter in - `UrlGeneratorInterface::generate($name, $parameters = array(), $referenceType = self::ABSOLUTE_PATH)` + `UrlGeneratorInterface::generate($name, $parameters = [], $referenceType = self::ABSOLUTE_PATH)` now accepts more values and you should use the constants defined in `UrlGeneratorInterface` for claritiy. The old method calls with a Boolean parameter will continue to work because they equal the signature using the constants. diff --git a/vendor/symfony/routing/CompiledRoute.php b/vendor/symfony/routing/CompiledRoute.php index 8ecf5153ce2f73d2a368d6a9ac19df889c7dc7a7..87278e702a899127cd44c77f1330cd31af2c5c99 100644 --- a/vendor/symfony/routing/CompiledRoute.php +++ b/vendor/symfony/routing/CompiledRoute.php @@ -37,9 +37,9 @@ class CompiledRoute implements \Serializable * @param array $hostVariables An array of host variables * @param array $variables An array of variables (variables defined in the path and in the host patterns) */ - public function __construct($staticPrefix, $regex, array $tokens, array $pathVariables, $hostRegex = null, array $hostTokens = array(), array $hostVariables = array(), array $variables = array()) + public function __construct(string $staticPrefix, string $regex, array $tokens, array $pathVariables, string $hostRegex = null, array $hostTokens = [], array $hostVariables = [], array $variables = []) { - $this->staticPrefix = (string) $staticPrefix; + $this->staticPrefix = $staticPrefix; $this->regex = $regex; $this->tokens = $tokens; $this->pathVariables = $pathVariables; @@ -49,12 +49,9 @@ class CompiledRoute implements \Serializable $this->variables = $variables; } - /** - * {@inheritdoc} - */ - public function serialize() + public function __serialize(): array { - return serialize(array( + return [ 'vars' => $this->variables, 'path_prefix' => $this->staticPrefix, 'path_regex' => $this->regex, @@ -63,20 +60,20 @@ class CompiledRoute implements \Serializable 'host_regex' => $this->hostRegex, 'host_tokens' => $this->hostTokens, 'host_vars' => $this->hostVariables, - )); + ]; } /** - * {@inheritdoc} + * @internal since Symfony 4.3 + * @final since Symfony 4.3 */ - public function unserialize($serialized) + public function serialize() { - if (\PHP_VERSION_ID >= 70000) { - $data = unserialize($serialized, array('allowed_classes' => false)); - } else { - $data = unserialize($serialized); - } + return serialize($this->__serialize()); + } + public function __unserialize(array $data): void + { $this->variables = $data['vars']; $this->staticPrefix = $data['path_prefix']; $this->regex = $data['path_regex']; @@ -87,6 +84,15 @@ class CompiledRoute implements \Serializable $this->hostVariables = $data['host_vars']; } + /** + * @internal since Symfony 4.3 + * @final since Symfony 4.3 + */ + public function unserialize($serialized) + { + $this->__unserialize(unserialize($serialized, ['allowed_classes' => false])); + } + /** * Returns the static prefix. * diff --git a/vendor/symfony/routing/DependencyInjection/RoutingResolverPass.php b/vendor/symfony/routing/DependencyInjection/RoutingResolverPass.php index 4af0a5a28668b82b798605eb8df6cb5556d89351..7068825fef7a1c5c4268f9cd44ffb9ee44114340 100644 --- a/vendor/symfony/routing/DependencyInjection/RoutingResolverPass.php +++ b/vendor/symfony/routing/DependencyInjection/RoutingResolverPass.php @@ -11,10 +11,10 @@ namespace Symfony\Component\Routing\DependencyInjection; -use Symfony\Component\DependencyInjection\Reference; -use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; use Symfony\Component\DependencyInjection\Compiler\PriorityTaggedServiceTrait; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Reference; /** * Adds tagged routing.loader services to routing.resolver service. @@ -28,7 +28,7 @@ class RoutingResolverPass implements CompilerPassInterface private $resolverServiceId; private $loaderTag; - public function __construct($resolverServiceId = 'routing.resolver', $loaderTag = 'routing.loader') + public function __construct(string $resolverServiceId = 'routing.resolver', string $loaderTag = 'routing.loader') { $this->resolverServiceId = $resolverServiceId; $this->loaderTag = $loaderTag; @@ -43,7 +43,7 @@ class RoutingResolverPass implements CompilerPassInterface $definition = $container->getDefinition($this->resolverServiceId); foreach ($this->findAndSortTaggedServices($this->loaderTag, $container) as $id) { - $definition->addMethodCall('addLoader', array(new Reference($id))); + $definition->addMethodCall('addLoader', [new Reference($id)]); } } } diff --git a/vendor/symfony/routing/Exception/ExceptionInterface.php b/vendor/symfony/routing/Exception/ExceptionInterface.php index db7636211fe42dd0948fc88bf684d8874e6efbcb..22e72b16bdbd456243f517ad9eb8bc1ae5647cb8 100644 --- a/vendor/symfony/routing/Exception/ExceptionInterface.php +++ b/vendor/symfony/routing/Exception/ExceptionInterface.php @@ -16,6 +16,6 @@ namespace Symfony\Component\Routing\Exception; * * @author Alexandre Salomé <alexandre.salome@gmail.com> */ -interface ExceptionInterface +interface ExceptionInterface extends \Throwable { } diff --git a/vendor/symfony/routing/Exception/MethodNotAllowedException.php b/vendor/symfony/routing/Exception/MethodNotAllowedException.php index 712412fecec589af8d009dd32e88e672dd879bed..e129ec8bf2178ce938f37852b6d3e5ab40f80cc7 100644 --- a/vendor/symfony/routing/Exception/MethodNotAllowedException.php +++ b/vendor/symfony/routing/Exception/MethodNotAllowedException.php @@ -20,9 +20,9 @@ namespace Symfony\Component\Routing\Exception; */ class MethodNotAllowedException extends \RuntimeException implements ExceptionInterface { - protected $allowedMethods = array(); + protected $allowedMethods = []; - public function __construct(array $allowedMethods, $message = null, $code = 0, \Exception $previous = null) + public function __construct(array $allowedMethods, string $message = null, int $code = 0, \Exception $previous = null) { $this->allowedMethods = array_map('strtoupper', $allowedMethods); diff --git a/vendor/symfony/routing/Generator/CompiledUrlGenerator.php b/vendor/symfony/routing/Generator/CompiledUrlGenerator.php new file mode 100644 index 0000000000000000000000000000000000000000..41cd5893ae2f385cd01dac4fe3bdbe065688fa3d --- /dev/null +++ b/vendor/symfony/routing/Generator/CompiledUrlGenerator.php @@ -0,0 +1,58 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Generator; + +use Psr\Log\LoggerInterface; +use Symfony\Component\Routing\Exception\RouteNotFoundException; +use Symfony\Component\Routing\RequestContext; + +/** + * Generates URLs based on rules dumped by CompiledUrlGeneratorDumper. + */ +class CompiledUrlGenerator extends UrlGenerator +{ + private $compiledRoutes = []; + private $defaultLocale; + + public function __construct(array $compiledRoutes, RequestContext $context, LoggerInterface $logger = null, string $defaultLocale = null) + { + $this->compiledRoutes = $compiledRoutes; + $this->context = $context; + $this->logger = $logger; + $this->defaultLocale = $defaultLocale; + } + + public function generate($name, $parameters = [], $referenceType = self::ABSOLUTE_PATH) + { + $locale = $parameters['_locale'] + ?? $this->context->getParameter('_locale') + ?: $this->defaultLocale; + + if (null !== $locale) { + do { + if (($this->compiledRoutes[$name.'.'.$locale][1]['_canonical_route'] ?? null) === $name) { + unset($parameters['_locale']); + $name .= '.'.$locale; + break; + } + } while (false !== $locale = strstr($locale, '_', true)); + } + + if (!isset($this->compiledRoutes[$name])) { + throw new RouteNotFoundException(sprintf('Unable to generate a URL for the named route "%s" as such route does not exist.', $name)); + } + + list($variables, $defaults, $requirements, $tokens, $hostTokens, $requiredSchemes) = $this->compiledRoutes[$name]; + + return $this->doGenerate($variables, $defaults, $requirements, $tokens, $parameters, $name, $referenceType, $hostTokens, $requiredSchemes); + } +} diff --git a/vendor/symfony/routing/Generator/ConfigurableRequirementsInterface.php b/vendor/symfony/routing/Generator/ConfigurableRequirementsInterface.php index dc97b7e724f7fe0df86b8354d7d2f3cdbfd57fa8..2e5dc5325bddf6c670c6f19242fab05836b711e1 100644 --- a/vendor/symfony/routing/Generator/ConfigurableRequirementsInterface.php +++ b/vendor/symfony/routing/Generator/ConfigurableRequirementsInterface.php @@ -20,7 +20,7 @@ namespace Symfony\Component\Routing\Generator; * The possible configurations and use-cases: * - setStrictRequirements(true): Throw an exception for mismatching requirements. This * is mostly useful in development environment. - * - setStrictRequirements(false): Don't throw an exception but return null as URL for + * - setStrictRequirements(false): Don't throw an exception but return an empty string as URL for * mismatching requirements and log the problem. Useful when you cannot control all * params because they come from third party libs but don't want to have a 404 in * production environment. It should log the mismatch so one can review it. diff --git a/vendor/symfony/routing/Generator/Dumper/CompiledUrlGeneratorDumper.php b/vendor/symfony/routing/Generator/Dumper/CompiledUrlGeneratorDumper.php new file mode 100644 index 0000000000000000000000000000000000000000..e90a40a26f0fcc67325cfb78c8345cc65a8eeb06 --- /dev/null +++ b/vendor/symfony/routing/Generator/Dumper/CompiledUrlGeneratorDumper.php @@ -0,0 +1,73 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Generator\Dumper; + +use Symfony\Component\Routing\Matcher\Dumper\CompiledUrlMatcherDumper; + +/** + * CompiledUrlGeneratorDumper creates a PHP array to be used with CompiledUrlGenerator. + * + * @author Fabien Potencier <fabien@symfony.com> + * @author Tobias Schultze <http://tobion.de> + * @author Nicolas Grekas <p@tchwork.com> + */ +class CompiledUrlGeneratorDumper extends GeneratorDumper +{ + public function getCompiledRoutes(): array + { + $compiledRoutes = []; + foreach ($this->getRoutes()->all() as $name => $route) { + $compiledRoute = $route->compile(); + + $compiledRoutes[$name] = [ + $compiledRoute->getVariables(), + $route->getDefaults(), + $route->getRequirements(), + $compiledRoute->getTokens(), + $compiledRoute->getHostTokens(), + $route->getSchemes(), + ]; + } + + return $compiledRoutes; + } + + /** + * {@inheritdoc} + */ + public function dump(array $options = []) + { + return <<<EOF +<?php + +// This file has been auto-generated by the Symfony Routing Component. + +return [{$this->generateDeclaredRoutes()} +]; + +EOF; + } + + /** + * Generates PHP code representing an array of defined routes + * together with the routes properties (e.g. requirements). + */ + private function generateDeclaredRoutes(): string + { + $routes = ''; + foreach ($this->getCompiledRoutes() as $name => $properties) { + $routes .= sprintf("\n '%s' => %s,", $name, CompiledUrlMatcherDumper::export($properties)); + } + + return $routes; + } +} diff --git a/vendor/symfony/routing/Generator/Dumper/GeneratorDumperInterface.php b/vendor/symfony/routing/Generator/Dumper/GeneratorDumperInterface.php index fed34723927735b7ef9a3b902807dd71defdb830..096519aa1a72f1a7db90ce97e11463c1bf386515 100644 --- a/vendor/symfony/routing/Generator/Dumper/GeneratorDumperInterface.php +++ b/vendor/symfony/routing/Generator/Dumper/GeneratorDumperInterface.php @@ -28,7 +28,7 @@ interface GeneratorDumperInterface * * @return string Executable code */ - public function dump(array $options = array()); + public function dump(array $options = []); /** * Gets the routes to dump. diff --git a/vendor/symfony/routing/Generator/Dumper/PhpGeneratorDumper.php b/vendor/symfony/routing/Generator/Dumper/PhpGeneratorDumper.php index 60bdf1da3522c19ab982401e59cf5f54f63cc64e..3869ffda4eebe4434d5c7ced0212a361e7771532 100644 --- a/vendor/symfony/routing/Generator/Dumper/PhpGeneratorDumper.php +++ b/vendor/symfony/routing/Generator/Dumper/PhpGeneratorDumper.php @@ -11,11 +11,17 @@ namespace Symfony\Component\Routing\Generator\Dumper; +@trigger_error(sprintf('The "%s" class is deprecated since Symfony 4.3, use "CompiledUrlGeneratorDumper" instead.', PhpGeneratorDumper::class), E_USER_DEPRECATED); + +use Symfony\Component\Routing\Matcher\Dumper\CompiledUrlMatcherDumper; + /** * PhpGeneratorDumper creates a PHP class able to generate URLs for a given set of routes. * * @author Fabien Potencier <fabien@symfony.com> * @author Tobias Schultze <http://tobion.de> + * + * @deprecated since Symfony 4.3, use CompiledUrlGeneratorDumper instead. */ class PhpGeneratorDumper extends GeneratorDumper { @@ -31,12 +37,12 @@ class PhpGeneratorDumper extends GeneratorDumper * * @return string A PHP class representing the generator class */ - public function dump(array $options = array()) + public function dump(array $options = []) { - $options = array_merge(array( + $options = array_merge([ 'class' => 'ProjectUrlGenerator', 'base_class' => 'Symfony\\Component\\Routing\\Generator\\UrlGenerator', - ), $options); + ], $options); return <<<EOF <?php @@ -52,11 +58,13 @@ use Psr\Log\LoggerInterface; class {$options['class']} extends {$options['base_class']} { private static \$declaredRoutes; + private \$defaultLocale; - public function __construct(RequestContext \$context, LoggerInterface \$logger = null) + public function __construct(RequestContext \$context, LoggerInterface \$logger = null, string \$defaultLocale = null) { \$this->context = \$context; \$this->logger = \$logger; + \$this->defaultLocale = \$defaultLocale; if (null === self::\$declaredRoutes) { self::\$declaredRoutes = {$this->generateDeclaredRoutes()}; } @@ -76,11 +84,11 @@ EOF; */ private function generateDeclaredRoutes() { - $routes = "array(\n"; + $routes = "[\n"; foreach ($this->getRoutes()->all() as $name => $route) { $compiledRoute = $route->compile(); - $properties = array(); + $properties = []; $properties[] = $compiledRoute->getVariables(); $properties[] = $route->getDefaults(); $properties[] = $route->getRequirements(); @@ -88,9 +96,9 @@ EOF; $properties[] = $compiledRoute->getHostTokens(); $properties[] = $route->getSchemes(); - $routes .= sprintf(" '%s' => %s,\n", $name, str_replace("\n", '', var_export($properties, true))); + $routes .= sprintf(" '%s' => %s,\n", $name, CompiledUrlMatcherDumper::export($properties)); } - $routes .= ' )'; + $routes .= ' ]'; return $routes; } @@ -103,8 +111,22 @@ EOF; private function generateGenerateMethod() { return <<<'EOF' - public function generate($name, $parameters = array(), $referenceType = self::ABSOLUTE_PATH) + public function generate($name, $parameters = [], $referenceType = self::ABSOLUTE_PATH) { + $locale = $parameters['_locale'] + ?? $this->context->getParameter('_locale') + ?: $this->defaultLocale; + + if (null !== $locale && null !== $name) { + do { + if ((self::$declaredRoutes[$name.'.'.$locale][1]['_canonical_route'] ?? null) === $name) { + unset($parameters['_locale']); + $name .= '.'.$locale; + break; + } + } while (false !== $locale = strstr($locale, '_', true)); + } + if (!isset(self::$declaredRoutes[$name])) { throw new RouteNotFoundException(sprintf('Unable to generate a URL for the named route "%s" as such route does not exist.', $name)); } diff --git a/vendor/symfony/routing/Generator/UrlGenerator.php b/vendor/symfony/routing/Generator/UrlGenerator.php index 02a59a9253976bc9ff42de15c00bf1ac77471d10..8be593bf98b6f93c5f3ca478522f11cae5583101 100644 --- a/vendor/symfony/routing/Generator/UrlGenerator.php +++ b/vendor/symfony/routing/Generator/UrlGenerator.php @@ -11,12 +11,12 @@ namespace Symfony\Component\Routing\Generator; -use Symfony\Component\Routing\RouteCollection; -use Symfony\Component\Routing\RequestContext; +use Psr\Log\LoggerInterface; use Symfony\Component\Routing\Exception\InvalidParameterException; -use Symfony\Component\Routing\Exception\RouteNotFoundException; use Symfony\Component\Routing\Exception\MissingMandatoryParametersException; -use Psr\Log\LoggerInterface; +use Symfony\Component\Routing\Exception\RouteNotFoundException; +use Symfony\Component\Routing\RequestContext; +use Symfony\Component\Routing\RouteCollection; /** * UrlGenerator can generate a URL or a path for any route in the RouteCollection @@ -27,6 +27,20 @@ use Psr\Log\LoggerInterface; */ class UrlGenerator implements UrlGeneratorInterface, ConfigurableRequirementsInterface { + private const QUERY_FRAGMENT_DECODED = [ + // RFC 3986 explicitly allows those in the query/fragment to reference other URIs unencoded + '%2F' => '/', + '%3F' => '?', + // reserved chars that have no special meaning for HTTP URIs in a query or fragment + // this excludes esp. "&", "=" and also "+" because PHP would treat it as a space (form-encoded) + '%40' => '@', + '%3A' => ':', + '%21' => '!', + '%3B' => ';', + '%2C' => ',', + '%2A' => '*', + ]; + protected $routes; protected $context; @@ -37,6 +51,8 @@ class UrlGenerator implements UrlGeneratorInterface, ConfigurableRequirementsInt protected $logger; + private $defaultLocale; + /** * This array defines the characters (besides alphanumeric ones) that will not be percent-encoded in the path segment of the generated URL. * @@ -45,7 +61,7 @@ class UrlGenerator implements UrlGeneratorInterface, ConfigurableRequirementsInt * "?" and "#" (would be interpreted wrongly as query and fragment identifier), * "'" and """ (are used as delimiters in HTML). */ - protected $decodedChars = array( + protected $decodedChars = [ // the slash can be used to designate a hierarchical structure and we want allow using it with this meaning // some webservers don't allow the slash in encoded form in the path for security reasons anyway // see http://stackoverflow.com/questions/4069002/http-400-if-2f-part-of-get-url-in-jboss @@ -63,13 +79,14 @@ class UrlGenerator implements UrlGeneratorInterface, ConfigurableRequirementsInt '%21' => '!', '%2A' => '*', '%7C' => '|', - ); + ]; - public function __construct(RouteCollection $routes, RequestContext $context, LoggerInterface $logger = null) + public function __construct(RouteCollection $routes, RequestContext $context, LoggerInterface $logger = null, string $defaultLocale = null) { $this->routes = $routes; $this->context = $context; $this->logger = $logger; + $this->defaultLocale = $defaultLocale; } /** @@ -107,9 +124,23 @@ class UrlGenerator implements UrlGeneratorInterface, ConfigurableRequirementsInt /** * {@inheritdoc} */ - public function generate($name, $parameters = array(), $referenceType = self::ABSOLUTE_PATH) + public function generate($name, $parameters = [], $referenceType = self::ABSOLUTE_PATH) { - if (null === $route = $this->routes->get($name)) { + $route = null; + $locale = $parameters['_locale'] + ?? $this->context->getParameter('_locale') + ?: $this->defaultLocale; + + if (null !== $locale) { + do { + if (null !== ($route = $this->routes->get($name.'.'.$locale)) && $route->getDefault('_canonical_route') === $name) { + unset($parameters['_locale']); + break; + } + } while (false !== $locale = strstr($locale, '_', true)); + } + + if (null === $route = $route ?? $this->routes->get($name)) { throw new RouteNotFoundException(sprintf('Unable to generate a URL for the named route "%s" as such route does not exist.', $name)); } @@ -123,8 +154,10 @@ class UrlGenerator implements UrlGeneratorInterface, ConfigurableRequirementsInt * @throws MissingMandatoryParametersException When some parameters are missing that are mandatory for the route * @throws InvalidParameterException When a parameter value for a placeholder is not correct because * it does not match the requirement + * + * @return string */ - protected function doGenerate($variables, $defaults, $requirements, $tokens, $parameters, $name, $referenceType, $hostTokens, array $requiredSchemes = array()) + protected function doGenerate($variables, $defaults, $requirements, $tokens, $parameters, $name, $referenceType, $hostTokens, array $requiredSchemes = []) { $variables = array_flip($variables); $mergedParams = array_replace($defaults, $this->context->getParameters(), $parameters); @@ -139,21 +172,25 @@ class UrlGenerator implements UrlGeneratorInterface, ConfigurableRequirementsInt $message = 'Parameter "{parameter}" for route "{route}" must match "{expected}" ("{given}" given) to generate a corresponding URL.'; foreach ($tokens as $token) { if ('variable' === $token[0]) { - if (!$optional || !array_key_exists($token[3], $defaults) || null !== $mergedParams[$token[3]] && (string) $mergedParams[$token[3]] !== (string) $defaults[$token[3]]) { - // check requirement - if (null !== $this->strictRequirements && !preg_match('#^'.$token[2].'$#'.(empty($token[4]) ? '' : 'u'), $mergedParams[$token[3]])) { + $varName = $token[3]; + // variable is not important by default + $important = $token[5] ?? false; + + if (!$optional || $important || !\array_key_exists($varName, $defaults) || (null !== $mergedParams[$varName] && (string) $mergedParams[$varName] !== (string) $defaults[$varName])) { + // check requirement (while ignoring look-around patterns) + if (null !== $this->strictRequirements && !preg_match('#^'.preg_replace('/\(\?(?:=|<=|!|<!)((?:[^()\\\\]+|\\\\.|\((?1)\))*)\)/', '', $token[2]).'$#i'.(empty($token[4]) ? '' : 'u'), $mergedParams[$token[3]])) { if ($this->strictRequirements) { - throw new InvalidParameterException(strtr($message, array('{parameter}' => $token[3], '{route}' => $name, '{expected}' => $token[2], '{given}' => $mergedParams[$token[3]]))); + throw new InvalidParameterException(strtr($message, ['{parameter}' => $varName, '{route}' => $name, '{expected}' => $token[2], '{given}' => $mergedParams[$varName]])); } if ($this->logger) { - $this->logger->error($message, array('parameter' => $token[3], 'route' => $name, 'expected' => $token[2], 'given' => $mergedParams[$token[3]])); + $this->logger->error($message, ['parameter' => $varName, 'route' => $name, 'expected' => $token[2], 'given' => $mergedParams[$varName]]); } - return; + return ''; } - $url = $token[1].$mergedParams[$token[3]].$url; + $url = $token[1].$mergedParams[$varName].$url; $optional = false; } } else { @@ -173,7 +210,7 @@ class UrlGenerator implements UrlGeneratorInterface, ConfigurableRequirementsInt // the path segments "." and ".." are interpreted as relative reference when resolving a URI; see http://tools.ietf.org/html/rfc3986#section-3.3 // so we need to encode them as they are not used for this purpose here // otherwise we would generate a URI that, when followed by a user agent (e.g. browser), does not match this route - $url = strtr($url, array('/../' => '/%2E%2E/', '/./' => '/%2E/')); + $url = strtr($url, ['/../' => '/%2E%2E/', '/./' => '/%2E/']); if ('/..' === substr($url, -3)) { $url = substr($url, 0, -2).'%2E%2E'; } elseif ('/.' === substr($url, -2)) { @@ -185,7 +222,7 @@ class UrlGenerator implements UrlGeneratorInterface, ConfigurableRequirementsInt $scheme = $this->context->getScheme(); if ($requiredSchemes) { - if (!in_array($scheme, $requiredSchemes, true)) { + if (!\in_array($scheme, $requiredSchemes, true)) { $referenceType = self::ABSOLUTE_URL; $scheme = current($requiredSchemes); } @@ -195,16 +232,17 @@ class UrlGenerator implements UrlGeneratorInterface, ConfigurableRequirementsInt $routeHost = ''; foreach ($hostTokens as $token) { if ('variable' === $token[0]) { - if (null !== $this->strictRequirements && !preg_match('#^'.$token[2].'$#i'.(empty($token[4]) ? '' : 'u'), $mergedParams[$token[3]])) { + // check requirement (while ignoring look-around patterns) + if (null !== $this->strictRequirements && !preg_match('#^'.preg_replace('/\(\?(?:=|<=|!|<!)((?:[^()\\\\]+|\\\\.|\((?1)\))*)\)/', '', $token[2]).'$#i'.(empty($token[4]) ? '' : 'u'), $mergedParams[$token[3]])) { if ($this->strictRequirements) { - throw new InvalidParameterException(strtr($message, array('{parameter}' => $token[3], '{route}' => $name, '{expected}' => $token[2], '{given}' => $mergedParams[$token[3]]))); + throw new InvalidParameterException(strtr($message, ['{parameter}' => $token[3], '{route}' => $name, '{expected}' => $token[2], '{given}' => $mergedParams[$token[3]]])); } if ($this->logger) { - $this->logger->error($message, array('parameter' => $token[3], 'route' => $name, 'expected' => $token[2], 'given' => $mergedParams[$token[3]])); + $this->logger->error($message, ['parameter' => $token[3], 'route' => $name, 'expected' => $token[2], 'given' => $mergedParams[$token[3]]]); } - return; + return ''; } $routeHost = $token[1].$mergedParams[$token[3]].$routeHost; @@ -221,16 +259,18 @@ class UrlGenerator implements UrlGeneratorInterface, ConfigurableRequirementsInt } } - if ((self::ABSOLUTE_URL === $referenceType || self::NETWORK_PATH === $referenceType) && !empty($host)) { - $port = ''; - if ('http' === $scheme && 80 != $this->context->getHttpPort()) { - $port = ':'.$this->context->getHttpPort(); - } elseif ('https' === $scheme && 443 != $this->context->getHttpsPort()) { - $port = ':'.$this->context->getHttpsPort(); - } + if (self::ABSOLUTE_URL === $referenceType || self::NETWORK_PATH === $referenceType) { + if ('' !== $host || ('' !== $scheme && 'http' !== $scheme && 'https' !== $scheme)) { + $port = ''; + if ('http' === $scheme && 80 !== $this->context->getHttpPort()) { + $port = ':'.$this->context->getHttpPort(); + } elseif ('https' === $scheme && 443 !== $this->context->getHttpsPort()) { + $port = ':'.$this->context->getHttpsPort(); + } - $schemeAuthority = self::NETWORK_PATH === $referenceType ? '//' : "$scheme://"; - $schemeAuthority .= $host.$port; + $schemeAuthority = self::NETWORK_PATH === $referenceType || '' === $scheme ? '//' : "$scheme://"; + $schemeAuthority .= $host.$port; + } } if (self::RELATIVE_PATH === $referenceType) { @@ -245,10 +285,7 @@ class UrlGenerator implements UrlGeneratorInterface, ConfigurableRequirementsInt }); // extract fragment - $fragment = ''; - if (isset($defaults['_fragment'])) { - $fragment = $defaults['_fragment']; - } + $fragment = $defaults['_fragment'] ?? ''; if (isset($extra['_fragment'])) { $fragment = $extra['_fragment']; @@ -256,13 +293,11 @@ class UrlGenerator implements UrlGeneratorInterface, ConfigurableRequirementsInt } if ($extra && $query = http_build_query($extra, '', '&', PHP_QUERY_RFC3986)) { - // "/" and "?" can be left decoded for better user experience, see - // http://tools.ietf.org/html/rfc3986#section-3.4 - $url .= '?'.strtr($query, array('%2F' => '/')); + $url .= '?'.strtr($query, self::QUERY_FRAGMENT_DECODED); } if ('' !== $fragment) { - $url .= '#'.strtr(rawurlencode($fragment), array('%2F' => '/', '%3F' => '?')); + $url .= '#'.strtr(rawurlencode($fragment), self::QUERY_FRAGMENT_DECODED); } return $url; @@ -308,7 +343,7 @@ class UrlGenerator implements UrlGeneratorInterface, ConfigurableRequirementsInt } $targetDirs[] = $targetFile; - $path = str_repeat('../', count($sourceDirs)).implode('/', $targetDirs); + $path = str_repeat('../', \count($sourceDirs)).implode('/', $targetDirs); // A reference to the same base directory or an empty subdirectory must be prefixed with "./". // This also applies to a segment with a colon character (e.g., "file:colon") that cannot be used diff --git a/vendor/symfony/routing/Generator/UrlGeneratorInterface.php b/vendor/symfony/routing/Generator/UrlGeneratorInterface.php index d6e7938e5ba065f64718806f0522d9aafbc372c2..64714d354dba2f1f56e4b8d71ecff150aa2067e3 100644 --- a/vendor/symfony/routing/Generator/UrlGeneratorInterface.php +++ b/vendor/symfony/routing/Generator/UrlGeneratorInterface.php @@ -71,9 +71,9 @@ interface UrlGeneratorInterface extends RequestContextAwareInterface * * The special parameter _fragment will be used as the document fragment suffixed to the final URL. * - * @param string $name The name of the route - * @param mixed $parameters An array of parameters - * @param int $referenceType The type of reference to be generated (one of the constants) + * @param string $name The name of the route + * @param mixed[] $parameters An array of parameters + * @param int $referenceType The type of reference to be generated (one of the constants) * * @return string The generated URL * @@ -82,5 +82,5 @@ interface UrlGeneratorInterface extends RequestContextAwareInterface * @throws InvalidParameterException When a parameter value for a placeholder is not correct because * it does not match the requirement */ - public function generate($name, $parameters = array(), $referenceType = self::ABSOLUTE_PATH); + public function generate($name, $parameters = [], $referenceType = self::ABSOLUTE_PATH); } diff --git a/vendor/symfony/routing/LICENSE b/vendor/symfony/routing/LICENSE index 21d7fb9e2f29b50caca3a76f0647e94e2cc8ddc1..a677f43763ca467472898351b328aee41e2edd7c 100644 --- a/vendor/symfony/routing/LICENSE +++ b/vendor/symfony/routing/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-2018 Fabien Potencier +Copyright (c) 2004-2019 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/vendor/symfony/routing/Loader/AnnotationClassLoader.php b/vendor/symfony/routing/Loader/AnnotationClassLoader.php index 2fe6fb596e42a4ac7fbc37cebd94bccbf0b6eaeb..6390a79f581187a6278217c48481b6f669fa4c95 100644 --- a/vendor/symfony/routing/Loader/AnnotationClassLoader.php +++ b/vendor/symfony/routing/Loader/AnnotationClassLoader.php @@ -12,11 +12,12 @@ namespace Symfony\Component\Routing\Loader; use Doctrine\Common\Annotations\Reader; +use Symfony\Component\Config\Loader\LoaderInterface; +use Symfony\Component\Config\Loader\LoaderResolverInterface; use Symfony\Component\Config\Resource\FileResource; +use Symfony\Component\Routing\Annotation\Route as RouteAnnotation; use Symfony\Component\Routing\Route; use Symfony\Component\Routing\RouteCollection; -use Symfony\Component\Config\Loader\LoaderInterface; -use Symfony\Component\Config\Loader\LoaderResolverInterface; /** * AnnotationClassLoader loads routing information from a PHP class and its methods. @@ -32,7 +33,6 @@ use Symfony\Component\Config\Loader\LoaderResolverInterface; * recognizes several parameters: requirements, options, defaults, schemes, * methods, host, and name. The name parameter is mandatory. * Here is an example of how you should be able to use it: - * * /** * * @Route("/Blog") * * / @@ -44,7 +44,6 @@ use Symfony\Component\Config\Loader\LoaderResolverInterface; * public function index() * { * } - * * /** * * @Route("/{id}", name="blog_post", requirements = {"id" = "\d+"}) * * / @@ -119,15 +118,22 @@ abstract class AnnotationClassLoader implements LoaderInterface } } - if (0 === $collection->count() && $class->hasMethod('__invoke') && $annot = $this->reader->getClassAnnotation($class, $this->routeAnnotationClass)) { - $globals['path'] = ''; - $globals['name'] = ''; - $this->addRoute($collection, $annot, $globals, $class, $class->getMethod('__invoke')); + if (0 === $collection->count() && $class->hasMethod('__invoke')) { + $globals = $this->resetGlobals(); + foreach ($this->reader->getClassAnnotations($class) as $annot) { + if ($annot instanceof $this->routeAnnotationClass) { + $this->addRoute($collection, $annot, $globals, $class, $class->getMethod('__invoke')); + } + } } return $collection; } + /** + * @param RouteAnnotation $annot or an object that exposes a similar interface + * @param array $globals + */ protected function addRoute(RouteCollection $collection, $annot, $globals, \ReflectionClass $class, \ReflectionMethod $method) { $name = $annot->getName(); @@ -136,13 +142,16 @@ abstract class AnnotationClassLoader implements LoaderInterface } $name = $globals['name'].$name; - $defaults = array_replace($globals['defaults'], $annot->getDefaults()); - foreach ($method->getParameters() as $param) { - if (false !== strpos($globals['path'].$annot->getPath(), sprintf('{%s}', $param->getName())) && !isset($defaults[$param->getName()]) && $param->isDefaultValueAvailable()) { - $defaults[$param->getName()] = $param->getDefaultValue(); + $requirements = $annot->getRequirements(); + + foreach ($requirements as $placeholder => $requirement) { + if (\is_int($placeholder)) { + @trigger_error(sprintf('A placeholder name must be a string (%d given). Did you forget to specify the placeholder key for the requirement "%s" of route "%s" in "%s::%s()"?', $placeholder, $requirement, $name, $class->getName(), $method->getName()), E_USER_DEPRECATED); } } - $requirements = array_replace($globals['requirements'], $annot->getRequirements()); + + $defaults = array_replace($globals['defaults'], $annot->getDefaults()); + $requirements = array_replace($globals['requirements'], $requirements); $options = array_replace($globals['options'], $annot->getOptions()); $schemes = array_merge($globals['schemes'], $annot->getSchemes()); $methods = array_merge($globals['methods'], $annot->getMethods()); @@ -157,11 +166,57 @@ abstract class AnnotationClassLoader implements LoaderInterface $condition = $globals['condition']; } - $route = $this->createRoute($globals['path'].$annot->getPath(), $defaults, $requirements, $options, $host, $schemes, $methods, $condition); + $path = $annot->getLocalizedPaths() ?: $annot->getPath(); + $prefix = $globals['localized_paths'] ?: $globals['path']; + $paths = []; - $this->configureRoute($route, $class, $method, $annot); + if (\is_array($path)) { + if (!\is_array($prefix)) { + foreach ($path as $locale => $localePath) { + $paths[$locale] = $prefix.$localePath; + } + } elseif ($missing = array_diff_key($prefix, $path)) { + throw new \LogicException(sprintf('Route to "%s" is missing paths for locale(s) "%s".', $class->name.'::'.$method->name, implode('", "', array_keys($missing)))); + } else { + foreach ($path as $locale => $localePath) { + if (!isset($prefix[$locale])) { + throw new \LogicException(sprintf('Route to "%s" with locale "%s" is missing a corresponding prefix in class "%s".', $method->name, $locale, $class->name)); + } + + $paths[$locale] = $prefix[$locale].$localePath; + } + } + } elseif (\is_array($prefix)) { + foreach ($prefix as $locale => $localePrefix) { + $paths[$locale] = $localePrefix.$path; + } + } else { + $paths[] = $prefix.$path; + } - $collection->add($name, $route); + foreach ($method->getParameters() as $param) { + if (isset($defaults[$param->name]) || !$param->isDefaultValueAvailable()) { + continue; + } + foreach ($paths as $locale => $path) { + if (preg_match(sprintf('/\{%s(?:<.*?>)?\}/', preg_quote($param->name)), $path)) { + $defaults[$param->name] = $param->getDefaultValue(); + break; + } + } + } + + foreach ($paths as $locale => $path) { + $route = $this->createRoute($path, $defaults, $requirements, $options, $host, $schemes, $methods, $condition); + $this->configureRoute($route, $class, $method, $annot); + if (0 !== $locale) { + $route->setDefault('_locale', $locale); + $route->setDefault('_canonical_route', $name); + $collection->add($name.'.'.$locale, $route); + } else { + $collection->add($name, $route); + } + } } /** @@ -169,7 +224,7 @@ abstract class AnnotationClassLoader implements LoaderInterface */ public function supports($resource, $type = null) { - return is_string($resource) && preg_match('/^(?:\\\\?[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)+$/', $resource) && (!$type || 'annotation' === $type); + return \is_string($resource) && preg_match('/^(?:\\\\?[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*)+$/', $resource) && (!$type || 'annotation' === $type); } /** @@ -189,14 +244,12 @@ abstract class AnnotationClassLoader implements LoaderInterface /** * Gets the default route name for a class method. * - * @param \ReflectionClass $class - * @param \ReflectionMethod $method - * * @return string */ protected function getDefaultRouteName(\ReflectionClass $class, \ReflectionMethod $method) { - $name = strtolower(str_replace('\\', '_', $class->name).'_'.$method->name); + $name = str_replace('\\', '_', $class->name).'_'.$method->name; + $name = \function_exists('mb_strtolower') && preg_match('//u', $name) ? mb_strtolower($name, 'UTF-8') : strtolower($name); if ($this->defaultRouteIndex > 0) { $name .= '_'.$this->defaultRouteIndex; } @@ -207,17 +260,7 @@ abstract class AnnotationClassLoader implements LoaderInterface protected function getGlobals(\ReflectionClass $class) { - $globals = array( - 'path' => '', - 'requirements' => array(), - 'options' => array(), - 'defaults' => array(), - 'schemes' => array(), - 'methods' => array(), - 'host' => '', - 'condition' => '', - 'name' => '', - ); + $globals = $this->resetGlobals(); if ($annot = $this->reader->getClassAnnotation($class, $this->routeAnnotationClass)) { if (null !== $annot->getName()) { @@ -228,6 +271,8 @@ abstract class AnnotationClassLoader implements LoaderInterface $globals['path'] = $annot->getPath(); } + $globals['localized_paths'] = $annot->getLocalizedPaths(); + if (null !== $annot->getRequirements()) { $globals['requirements'] = $annot->getRequirements(); } @@ -255,11 +300,33 @@ abstract class AnnotationClassLoader implements LoaderInterface if (null !== $annot->getCondition()) { $globals['condition'] = $annot->getCondition(); } + + foreach ($globals['requirements'] as $placeholder => $requirement) { + if (\is_int($placeholder)) { + @trigger_error(sprintf('A placeholder name must be a string (%d given). Did you forget to specify the placeholder key for the requirement "%s" in "%s"?', $placeholder, $requirement, $class->getName()), E_USER_DEPRECATED); + } + } } return $globals; } + private function resetGlobals() + { + return [ + 'path' => null, + 'localized_paths' => [], + 'requirements' => [], + 'options' => [], + 'defaults' => [], + 'schemes' => [], + 'methods' => [], + 'host' => '', + 'condition' => '', + 'name' => '', + ]; + } + protected function createRoute($path, $defaults, $requirements, $options, $host, $schemes, $methods, $condition) { return new Route($path, $defaults, $requirements, $options, $host, $schemes, $methods, $condition); diff --git a/vendor/symfony/routing/Loader/AnnotationDirectoryLoader.php b/vendor/symfony/routing/Loader/AnnotationDirectoryLoader.php index 4574a0201c0c39d9ce74e99ccc82c0dbf50f9e6a..3fb70ea20b4338e77139681564fa27134b120fdc 100644 --- a/vendor/symfony/routing/Loader/AnnotationDirectoryLoader.php +++ b/vendor/symfony/routing/Loader/AnnotationDirectoryLoader.php @@ -11,8 +11,8 @@ namespace Symfony\Component\Routing\Loader; -use Symfony\Component\Routing\RouteCollection; use Symfony\Component\Config\Resource\DirectoryResource; +use Symfony\Component\Routing\RouteCollection; /** * AnnotationDirectoryLoader loads routing information from annotations set @@ -80,7 +80,7 @@ class AnnotationDirectoryLoader extends AnnotationFileLoader return true; } - if ($type || !is_string($resource)) { + if ($type || !\is_string($resource)) { return false; } diff --git a/vendor/symfony/routing/Loader/AnnotationFileLoader.php b/vendor/symfony/routing/Loader/AnnotationFileLoader.php index cf9f0704c498771c71ea66c73fdb0c8292eb3342..eafd614d4ffd224814c9fc51eb32dcfc3c6f5d21 100644 --- a/vendor/symfony/routing/Loader/AnnotationFileLoader.php +++ b/vendor/symfony/routing/Loader/AnnotationFileLoader.php @@ -11,10 +11,10 @@ namespace Symfony\Component\Routing\Loader; -use Symfony\Component\Routing\RouteCollection; -use Symfony\Component\Config\Resource\FileResource; -use Symfony\Component\Config\Loader\FileLoader; use Symfony\Component\Config\FileLocatorInterface; +use Symfony\Component\Config\Loader\FileLoader; +use Symfony\Component\Config\Resource\FileResource; +use Symfony\Component\Routing\RouteCollection; /** * AnnotationFileLoader loads routing information from annotations set @@ -31,8 +31,8 @@ class AnnotationFileLoader extends FileLoader */ public function __construct(FileLocatorInterface $locator, AnnotationClassLoader $loader) { - if (!function_exists('token_get_all')) { - throw new \RuntimeException('The Tokenizer extension is required for the routing annotation loaders.'); + if (!\function_exists('token_get_all')) { + throw new \LogicException('The Tokenizer extension is required for the routing annotation loaders.'); } parent::__construct($locator); @@ -46,7 +46,7 @@ class AnnotationFileLoader extends FileLoader * @param string $file A PHP file path * @param string|null $type The resource type * - * @return RouteCollection A RouteCollection instance + * @return RouteCollection|null A RouteCollection instance * * @throws \InvalidArgumentException When the file does not exist or its routes cannot be parsed */ @@ -56,13 +56,16 @@ class AnnotationFileLoader extends FileLoader $collection = new RouteCollection(); if ($class = $this->findClass($path)) { + $refl = new \ReflectionClass($class); + if ($refl->isAbstract()) { + return null; + } + $collection->addResource(new FileResource($path)); $collection->addCollection($this->loader->load($class, $type)); } - if (\PHP_VERSION_ID >= 70000) { - // PHP 7 memory manager will not release after token_get_all(), see https://bugs.php.net/70098 - gc_mem_caches(); - } + + gc_mem_caches(); return $collection; } @@ -72,7 +75,7 @@ class AnnotationFileLoader extends FileLoader */ public function supports($resource, $type = null) { - return is_string($resource) && 'php' === pathinfo($resource, PATHINFO_EXTENSION) && (!$type || 'annotation' === $type); + return \is_string($resource) && 'php' === pathinfo($resource, PATHINFO_EXTENSION) && (!$type || 'annotation' === $type); } /** @@ -88,7 +91,7 @@ class AnnotationFileLoader extends FileLoader $namespace = false; $tokens = token_get_all(file_get_contents($file)); - if (1 === count($tokens) && T_INLINE_HTML === $tokens[0][0]) { + if (1 === \count($tokens) && T_INLINE_HTML === $tokens[0][0]) { throw new \InvalidArgumentException(sprintf('The file "%s" does not contain PHP code. Did you forgot to add the "<?php" start tag at the beginning of the file?', $file)); } @@ -105,7 +108,7 @@ class AnnotationFileLoader extends FileLoader if (true === $namespace && T_STRING === $token[0]) { $namespace = $token[1]; - while (isset($tokens[++$i][1]) && in_array($tokens[$i][0], array(T_NS_SEPARATOR, T_STRING))) { + while (isset($tokens[++$i][1]) && \in_array($tokens[$i][0], [T_NS_SEPARATOR, T_STRING])) { $namespace .= $tokens[$i][1]; } $token = $tokens[$i]; @@ -122,7 +125,7 @@ class AnnotationFileLoader extends FileLoader if (T_DOUBLE_COLON === $tokens[$j][0] || T_NEW === $tokens[$j][0]) { $skipClassToken = true; break; - } elseif (!in_array($tokens[$j][0], array(T_WHITESPACE, T_DOC_COMMENT, T_COMMENT))) { + } elseif (!\in_array($tokens[$j][0], [T_WHITESPACE, T_DOC_COMMENT, T_COMMENT])) { break; } } diff --git a/vendor/symfony/routing/Loader/Configurator/CollectionConfigurator.php b/vendor/symfony/routing/Loader/Configurator/CollectionConfigurator.php index 38d86cb895cb4e3914754a4a84f53be364558c18..e1de75e01de52ce0b80a591346b430d890602ffc 100644 --- a/vendor/symfony/routing/Loader/Configurator/CollectionConfigurator.php +++ b/vendor/symfony/routing/Loader/Configurator/CollectionConfigurator.php @@ -23,34 +23,26 @@ class CollectionConfigurator use Traits\RouteTrait; private $parent; + private $parentConfigurator; + private $parentPrefixes; - public function __construct(RouteCollection $parent, $name) + public function __construct(RouteCollection $parent, string $name, self $parentConfigurator = null, array $parentPrefixes = null) { $this->parent = $parent; $this->name = $name; $this->collection = new RouteCollection(); $this->route = new Route(''); + $this->parentConfigurator = $parentConfigurator; // for GC control + $this->parentPrefixes = $parentPrefixes; } public function __destruct() { - $this->collection->addPrefix(rtrim($this->route->getPath(), '/')); - $this->parent->addCollection($this->collection); - } + if (null === $this->prefixes) { + $this->collection->addPrefix($this->route->getPath()); + } - /** - * Adds a route. - * - * @param string $name - * @param string $path - * - * @return RouteConfigurator - */ - final public function add($name, $path) - { - $this->collection->add($this->name.$name, $route = clone $this->route); - - return new RouteConfigurator($this->collection, $route->setPath($path), $this->name); + $this->parent->addCollection($this->collection); } /** @@ -60,20 +52,44 @@ class CollectionConfigurator */ final public function collection($name = '') { - return new self($this->collection, $this->name.$name); + return new self($this->collection, $this->name.$name, $this, $this->prefixes); } /** * Sets the prefix to add to the path of all child routes. * - * @param string $prefix + * @param string|array $prefix the prefix, or the localized prefixes * * @return $this */ final public function prefix($prefix) { - $this->route->setPath($prefix); + if (\is_array($prefix)) { + if (null === $this->parentPrefixes) { + // no-op + } elseif ($missing = array_diff_key($this->parentPrefixes, $prefix)) { + throw new \LogicException(sprintf('Collection "%s" is missing prefixes for locale(s) "%s".', $this->name, implode('", "', array_keys($missing)))); + } else { + foreach ($prefix as $locale => $localePrefix) { + if (!isset($this->parentPrefixes[$locale])) { + throw new \LogicException(sprintf('Collection "%s" with locale "%s" is missing a corresponding prefix in its parent collection.', $this->name, $locale)); + } + + $prefix[$locale] = $this->parentPrefixes[$locale].$localePrefix; + } + } + $this->prefixes = $prefix; + $this->route->setPath('/'); + } else { + $this->prefixes = null; + $this->route->setPath($prefix); + } return $this; } + + private function createRoute($path): Route + { + return (clone $this->route)->setPath($path); + } } diff --git a/vendor/symfony/routing/Loader/Configurator/ImportConfigurator.php b/vendor/symfony/routing/Loader/Configurator/ImportConfigurator.php index d0a3c373ff23a1385fdd548e22bc4739b5b7131c..92e7efde4600b0e25b61ab23d7feacc1e93984a1 100644 --- a/vendor/symfony/routing/Loader/Configurator/ImportConfigurator.php +++ b/vendor/symfony/routing/Loader/Configurator/ImportConfigurator.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Routing\Loader\Configurator; +use Symfony\Component\Routing\Route; use Symfony\Component\Routing\RouteCollection; /** @@ -36,13 +37,56 @@ class ImportConfigurator /** * Sets the prefix to add to the path of all child routes. * - * @param string $prefix + * @param string|array $prefix the prefix, or the localized prefixes * * @return $this */ - final public function prefix($prefix) + final public function prefix($prefix, bool $trailingSlashOnRoot = true) { - $this->route->addPrefix($prefix); + if (!\is_array($prefix)) { + $this->route->addPrefix($prefix); + if (!$trailingSlashOnRoot) { + $rootPath = (new Route(trim(trim($prefix), '/').'/'))->getPath(); + foreach ($this->route->all() as $route) { + if ($route->getPath() === $rootPath) { + $route->setPath(rtrim($rootPath, '/')); + } + } + } + } else { + foreach ($prefix as $locale => $localePrefix) { + $prefix[$locale] = trim(trim($localePrefix), '/'); + } + foreach ($this->route->all() as $name => $route) { + if (null === $locale = $route->getDefault('_locale')) { + $this->route->remove($name); + foreach ($prefix as $locale => $localePrefix) { + $localizedRoute = clone $route; + $localizedRoute->setDefault('_locale', $locale); + $localizedRoute->setDefault('_canonical_route', $name); + $localizedRoute->setPath($localePrefix.(!$trailingSlashOnRoot && '/' === $route->getPath() ? '' : $route->getPath())); + $this->route->add($name.'.'.$locale, $localizedRoute); + } + } elseif (!isset($prefix[$locale])) { + throw new \InvalidArgumentException(sprintf('Route "%s" with locale "%s" is missing a corresponding prefix in its parent collection.', $name, $locale)); + } else { + $route->setPath($prefix[$locale].(!$trailingSlashOnRoot && '/' === $route->getPath() ? '' : $route->getPath())); + $this->route->add($name, $route); + } + } + } + + return $this; + } + + /** + * Sets the prefix to add to the name of all child routes. + * + * @return $this + */ + final public function namePrefix(string $namePrefix) + { + $this->route->addNamePrefix($namePrefix); return $this; } diff --git a/vendor/symfony/routing/Loader/Configurator/RouteConfigurator.php b/vendor/symfony/routing/Loader/Configurator/RouteConfigurator.php index b8d87025435e063c36be1e5cebfe2fbe751dee22..e700f8de7c13b6656745de9471e445b0c5471af4 100644 --- a/vendor/symfony/routing/Loader/Configurator/RouteConfigurator.php +++ b/vendor/symfony/routing/Loader/Configurator/RouteConfigurator.php @@ -11,7 +11,6 @@ namespace Symfony\Component\Routing\Loader\Configurator; -use Symfony\Component\Routing\Route; use Symfony\Component\Routing\RouteCollection; /** @@ -22,10 +21,14 @@ class RouteConfigurator use Traits\AddTrait; use Traits\RouteTrait; - public function __construct(RouteCollection $collection, Route $route, $name = '') + private $parentConfigurator; + + public function __construct(RouteCollection $collection, $route, string $name = '', CollectionConfigurator $parentConfigurator = null, array $prefixes = null) { $this->collection = $collection; $this->route = $route; $this->name = $name; + $this->parentConfigurator = $parentConfigurator; // for GC control + $this->prefixes = $prefixes; } } diff --git a/vendor/symfony/routing/Loader/Configurator/RoutingConfigurator.php b/vendor/symfony/routing/Loader/Configurator/RoutingConfigurator.php index 4591a86ba5cf956d7b64d8a5ade90c4e6db7780b..a315cfb4ad07ee43a430087287a44336817e1287 100644 --- a/vendor/symfony/routing/Loader/Configurator/RoutingConfigurator.php +++ b/vendor/symfony/routing/Loader/Configurator/RoutingConfigurator.php @@ -25,7 +25,7 @@ class RoutingConfigurator private $path; private $file; - public function __construct(RouteCollection $collection, PhpFileLoader $loader, $path, $file) + public function __construct(RouteCollection $collection, PhpFileLoader $loader, string $path, string $file) { $this->collection = $collection; $this->loader = $loader; @@ -38,10 +38,18 @@ class RoutingConfigurator */ final public function import($resource, $type = null, $ignoreErrors = false) { - $this->loader->setCurrentDir(dirname($this->path)); - $subCollection = $this->loader->import($resource, $type, $ignoreErrors, $this->file); - - return new ImportConfigurator($this->collection, $subCollection); + $this->loader->setCurrentDir(\dirname($this->path)); + $imported = $this->loader->import($resource, $type, $ignoreErrors, $this->file); + if (!\is_array($imported)) { + return new ImportConfigurator($this->collection, $imported); + } + + $mergedCollection = new RouteCollection(); + foreach ($imported as $subCollection) { + $mergedCollection->addCollection($subCollection); + } + + return new ImportConfigurator($this->collection, $mergedCollection); } /** diff --git a/vendor/symfony/routing/Loader/Configurator/Traits/AddTrait.php b/vendor/symfony/routing/Loader/Configurator/Traits/AddTrait.php index 7171fd241f6d05f11dce527a0e2ac3e4761d00f2..45642d2fec0cdfba9ee4ff96eece088ef7f08ab1 100644 --- a/vendor/symfony/routing/Loader/Configurator/Traits/AddTrait.php +++ b/vendor/symfony/routing/Loader/Configurator/Traits/AddTrait.php @@ -11,6 +11,7 @@ namespace Symfony\Component\Routing\Loader\Configurator\Traits; +use Symfony\Component\Routing\Loader\Configurator\CollectionConfigurator; use Symfony\Component\Routing\Loader\Configurator\RouteConfigurator; use Symfony\Component\Routing\Route; use Symfony\Component\Routing\RouteCollection; @@ -24,31 +25,66 @@ trait AddTrait private $name = ''; + private $prefixes; + /** * Adds a route. * - * @param string $name - * @param string $path - * - * @return RouteConfigurator + * @param string|array $path the path, or the localized paths of the route */ - final public function add($name, $path) + final public function add(string $name, $path): RouteConfigurator { - $this->collection->add($this->name.$name, $route = new Route($path)); + $paths = []; + $parentConfigurator = $this instanceof CollectionConfigurator ? $this : ($this instanceof RouteConfigurator ? $this->parentConfigurator : null); + + if (\is_array($path)) { + if (null === $this->prefixes) { + $paths = $path; + } elseif ($missing = array_diff_key($this->prefixes, $path)) { + throw new \LogicException(sprintf('Route "%s" is missing routes for locale(s) "%s".', $name, implode('", "', array_keys($missing)))); + } else { + foreach ($path as $locale => $localePath) { + if (!isset($this->prefixes[$locale])) { + throw new \LogicException(sprintf('Route "%s" with locale "%s" is missing a corresponding prefix in its parent collection.', $name, $locale)); + } + + $paths[$locale] = $this->prefixes[$locale].$localePath; + } + } + } elseif (null !== $this->prefixes) { + foreach ($this->prefixes as $locale => $prefix) { + $paths[$locale] = $prefix.$path; + } + } else { + $this->collection->add($this->name.$name, $route = $this->createRoute($path)); + + return new RouteConfigurator($this->collection, $route, $this->name, $parentConfigurator, $this->prefixes); + } + + $routes = new RouteCollection(); - return new RouteConfigurator($this->collection, $route); + foreach ($paths as $locale => $path) { + $routes->add($name.'.'.$locale, $route = $this->createRoute($path)); + $this->collection->add($this->name.$name.'.'.$locale, $route); + $route->setDefault('_locale', $locale); + $route->setDefault('_canonical_route', $this->name.$name); + } + + return new RouteConfigurator($this->collection, $routes, $this->name, $parentConfigurator, $this->prefixes); } /** * Adds a route. * - * @param string $name - * @param string $path - * - * @return RouteConfigurator + * @param string|array $path the path, or the localized paths of the route */ - final public function __invoke($name, $path) + final public function __invoke(string $name, $path): RouteConfigurator { return $this->add($name, $path); } + + private function createRoute($path): Route + { + return new Route($path); + } } diff --git a/vendor/symfony/routing/Loader/Configurator/Traits/RouteTrait.php b/vendor/symfony/routing/Loader/Configurator/Traits/RouteTrait.php index 4d2e255b14076549d3a7b44bf41c7adb599b48cd..92c4d2ffdcccf7e6247682f78b10607747e7b03e 100644 --- a/vendor/symfony/routing/Loader/Configurator/Traits/RouteTrait.php +++ b/vendor/symfony/routing/Loader/Configurator/Traits/RouteTrait.php @@ -58,13 +58,23 @@ trait RouteTrait } /** - * Sets the condition. + * Whether paths should accept utf8 encoding. * - * @param string $condition + * @return $this + */ + final public function utf8(bool $utf8 = true) + { + $this->route->addOptions(['utf8' => $utf8]); + + return $this; + } + + /** + * Sets the condition. * * @return $this */ - final public function condition($condition) + final public function condition(string $condition) { $this->route->setCondition($condition); @@ -74,11 +84,9 @@ trait RouteTrait /** * Sets the pattern for the host. * - * @param string $pattern - * * @return $this */ - final public function host($pattern) + final public function host(string $pattern) { $this->route->setHost($pattern); @@ -124,7 +132,31 @@ trait RouteTrait */ final public function controller($controller) { - $this->route->addDefaults(array('_controller' => $controller)); + $this->route->addDefaults(['_controller' => $controller]); + + return $this; + } + + /** + * Adds the "_locale" entry to defaults. + * + * @return $this + */ + final public function locale(string $locale) + { + $this->route->addDefaults(['_locale' => $locale]); + + return $this; + } + + /** + * Adds the "_format" entry to defaults. + * + * @return $this + */ + final public function format(string $format) + { + $this->route->addDefaults(['_format' => $format]); return $this; } diff --git a/vendor/symfony/routing/Loader/DependencyInjection/ServiceRouterLoader.php b/vendor/symfony/routing/Loader/DependencyInjection/ServiceRouterLoader.php index 6c1621635b943862c9838371460d1bfc89eb2452..0276719c10e8e9abba45c4094df15ec31d80e1fa 100644 --- a/vendor/symfony/routing/Loader/DependencyInjection/ServiceRouterLoader.php +++ b/vendor/symfony/routing/Loader/DependencyInjection/ServiceRouterLoader.php @@ -17,8 +17,6 @@ use Symfony\Component\Routing\Loader\ObjectRouteLoader; /** * A route loader that executes a service to load the routes. * - * This depends on the DependencyInjection component. - * * @author Ryan Weaver <ryan@knpuniversity.com> */ class ServiceRouterLoader extends ObjectRouteLoader diff --git a/vendor/symfony/routing/Loader/DirectoryLoader.php b/vendor/symfony/routing/Loader/DirectoryLoader.php index 4bb5b31b60a824343abc54590699a92911af0f09..08e833e0a1ea5278e13e42d23fd673158f896b5f 100644 --- a/vendor/symfony/routing/Loader/DirectoryLoader.php +++ b/vendor/symfony/routing/Loader/DirectoryLoader.php @@ -12,8 +12,8 @@ namespace Symfony\Component\Routing\Loader; use Symfony\Component\Config\Loader\FileLoader; -use Symfony\Component\Routing\RouteCollection; use Symfony\Component\Config\Resource\DirectoryResource; +use Symfony\Component\Routing\RouteCollection; class DirectoryLoader extends FileLoader { diff --git a/vendor/symfony/routing/Loader/GlobFileLoader.php b/vendor/symfony/routing/Loader/GlobFileLoader.php new file mode 100644 index 0000000000000000000000000000000000000000..03ee341b98250790edd80f2ac5bb3b415cf3a9dc --- /dev/null +++ b/vendor/symfony/routing/Loader/GlobFileLoader.php @@ -0,0 +1,47 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Loader; + +use Symfony\Component\Config\Loader\FileLoader; +use Symfony\Component\Routing\RouteCollection; + +/** + * GlobFileLoader loads files from a glob pattern. + * + * @author Nicolas Grekas <p@tchwork.com> + */ +class GlobFileLoader extends FileLoader +{ + /** + * {@inheritdoc} + */ + public function load($resource, $type = null) + { + $collection = new RouteCollection(); + + foreach ($this->glob($resource, false, $globResource) as $path => $info) { + $collection->addCollection($this->import($path)); + } + + $collection->addResource($globResource); + + return $collection; + } + + /** + * {@inheritdoc} + */ + public function supports($resource, $type = null) + { + return 'glob' === $type; + } +} diff --git a/vendor/symfony/routing/Loader/ObjectRouteLoader.php b/vendor/symfony/routing/Loader/ObjectRouteLoader.php index 0899a818129be5008111eff3b8c7d2d4b69395df..8f0680f02aa5cf8f3936f69ac8aaac005550f810 100644 --- a/vendor/symfony/routing/Loader/ObjectRouteLoader.php +++ b/vendor/symfony/routing/Loader/ObjectRouteLoader.php @@ -37,37 +37,42 @@ abstract class ObjectRouteLoader extends Loader /** * Calls the service that will load the routes. * - * @param mixed $resource Some value that will resolve to a callable + * @param string $resource Some value that will resolve to a callable * @param string|null $type The resource type * * @return RouteCollection */ public function load($resource, $type = null) { - $parts = explode(':', $resource); - if (2 != count($parts)) { - throw new \InvalidArgumentException(sprintf('Invalid resource "%s" passed to the "service" route loader: use the format "service_name:methodName"', $resource)); + if (!preg_match('/^[^\:]+(?:::?(?:[^\:]+))?$/', $resource)) { + throw new \InvalidArgumentException(sprintf('Invalid resource "%s" passed to the "service" route loader: use the format "service::method" or "service" if your service has an "__invoke" method.', $resource)); } + if (1 === substr_count($resource, ':')) { + $resource = str_replace(':', '::', $resource); + @trigger_error(sprintf('Referencing service route loaders with a single colon is deprecated since Symfony 4.1. Use %s instead.', $resource), E_USER_DEPRECATED); + } + + $parts = explode('::', $resource); $serviceString = $parts[0]; - $method = $parts[1]; + $method = $parts[1] ?? '__invoke'; $loaderObject = $this->getServiceObject($serviceString); - if (!is_object($loaderObject)) { - throw new \LogicException(sprintf('%s:getServiceObject() must return an object: %s returned', get_class($this), gettype($loaderObject))); + if (!\is_object($loaderObject)) { + throw new \LogicException(sprintf('%s:getServiceObject() must return an object: %s returned', \get_class($this), \gettype($loaderObject))); } - if (!method_exists($loaderObject, $method)) { - throw new \BadMethodCallException(sprintf('Method "%s" not found on "%s" when importing routing resource "%s"', $method, get_class($loaderObject), $resource)); + if (!\is_callable([$loaderObject, $method])) { + throw new \BadMethodCallException(sprintf('Method "%s" not found on "%s" when importing routing resource "%s"', $method, \get_class($loaderObject), $resource)); } - $routeCollection = call_user_func(array($loaderObject, $method), $this); + $routeCollection = $loaderObject->$method($this); if (!$routeCollection instanceof RouteCollection) { - $type = is_object($routeCollection) ? get_class($routeCollection) : gettype($routeCollection); + $type = \is_object($routeCollection) ? \get_class($routeCollection) : \gettype($routeCollection); - throw new \LogicException(sprintf('The %s::%s method must return a RouteCollection: %s returned', get_class($loaderObject), $method, $type)); + throw new \LogicException(sprintf('The %s::%s method must return a RouteCollection: %s returned', \get_class($loaderObject), $method, $type)); } // make the service file tracked so that if it changes, the cache rebuilds diff --git a/vendor/symfony/routing/Loader/PhpFileLoader.php b/vendor/symfony/routing/Loader/PhpFileLoader.php index 3fcd692f92562f931bc0c329c67cb1ab3c7fc2b7..a5cf95156401249963306c33c658989c33dfe12c 100644 --- a/vendor/symfony/routing/Loader/PhpFileLoader.php +++ b/vendor/symfony/routing/Loader/PhpFileLoader.php @@ -36,19 +36,19 @@ class PhpFileLoader extends FileLoader public function load($file, $type = null) { $path = $this->locator->locate($file); - $this->setCurrentDir(dirname($path)); + $this->setCurrentDir(\dirname($path)); // the closure forbids access to the private scope in the included file $loader = $this; - $load = \Closure::bind(function ($file) use ($loader) { + $load = \Closure::bind(static function ($file) use ($loader) { return include $file; }, null, ProtectedPhpFileLoader::class); $result = $load($path); - if ($result instanceof \Closure) { + if (\is_object($result) && \is_callable($result)) { $collection = new RouteCollection(); - $result(new RoutingConfigurator($collection, $this, $path, $file), $this); + $result(new RoutingConfigurator($collection, $this, $path, $file)); } else { $collection = $result; } @@ -63,7 +63,7 @@ class PhpFileLoader extends FileLoader */ public function supports($resource, $type = null) { - return is_string($resource) && 'php' === pathinfo($resource, PATHINFO_EXTENSION) && (!$type || 'php' === $type); + return \is_string($resource) && 'php' === pathinfo($resource, PATHINFO_EXTENSION) && (!$type || 'php' === $type); } } diff --git a/vendor/symfony/routing/Loader/XmlFileLoader.php b/vendor/symfony/routing/Loader/XmlFileLoader.php index 3a77890703ce290e50011976c5036e9b84c95412..ed4faf3915b72ddb748f7c4f40c35341f47b9d01 100644 --- a/vendor/symfony/routing/Loader/XmlFileLoader.php +++ b/vendor/symfony/routing/Loader/XmlFileLoader.php @@ -11,11 +11,11 @@ namespace Symfony\Component\Routing\Loader; -use Symfony\Component\Routing\RouteCollection; -use Symfony\Component\Routing\Route; -use Symfony\Component\Config\Resource\FileResource; use Symfony\Component\Config\Loader\FileLoader; +use Symfony\Component\Config\Resource\FileResource; use Symfony\Component\Config\Util\XmlUtils; +use Symfony\Component\Routing\Route; +use Symfony\Component\Routing\RouteCollection; /** * XmlFileLoader loads XML routing files. @@ -93,7 +93,7 @@ class XmlFileLoader extends FileLoader */ public function supports($resource, $type = null) { - return is_string($resource) && 'xml' === pathinfo($resource, PATHINFO_EXTENSION) && (!$type || 'xml' === $type); + return \is_string($resource) && 'xml' === pathinfo($resource, PATHINFO_EXTENSION) && (!$type || 'xml' === $type); } /** @@ -107,17 +107,34 @@ class XmlFileLoader extends FileLoader */ protected function parseRoute(RouteCollection $collection, \DOMElement $node, $path) { - if ('' === ($id = $node->getAttribute('id')) || !$node->hasAttribute('path')) { - throw new \InvalidArgumentException(sprintf('The <route> element in file "%s" must have an "id" and a "path" attribute.', $path)); + if ('' === $id = $node->getAttribute('id')) { + throw new \InvalidArgumentException(sprintf('The <route> element in file "%s" must have an "id" attribute.', $path)); } $schemes = preg_split('/[\s,\|]++/', $node->getAttribute('schemes'), -1, PREG_SPLIT_NO_EMPTY); $methods = preg_split('/[\s,\|]++/', $node->getAttribute('methods'), -1, PREG_SPLIT_NO_EMPTY); - list($defaults, $requirements, $options, $condition) = $this->parseConfigs($node, $path); + list($defaults, $requirements, $options, $condition, $paths) = $this->parseConfigs($node, $path); - $route = new Route($node->getAttribute('path'), $defaults, $requirements, $options, $node->getAttribute('host'), $schemes, $methods, $condition); - $collection->add($id, $route); + if (!$paths && '' === $node->getAttribute('path')) { + throw new \InvalidArgumentException(sprintf('The <route> element in file "%s" must have a "path" attribute or <path> child nodes.', $path)); + } + + if ($paths && '' !== $node->getAttribute('path')) { + throw new \InvalidArgumentException(sprintf('The <route> element in file "%s" must not have both a "path" attribute and <path> child nodes.', $path)); + } + + if (!$paths) { + $route = new Route($node->getAttribute('path'), $defaults, $requirements, $options, $node->getAttribute('host'), $schemes, $methods, $condition); + $collection->add($id, $route); + } else { + foreach ($paths as $locale => $p) { + $defaults['_locale'] = $locale; + $defaults['_canonical_route'] = $id; + $route = new Route($p, $defaults, $requirements, $options, $node->getAttribute('host'), $schemes, $methods, $condition); + $collection->add($id.'.'.$locale, $route); + } + } } /** @@ -141,31 +158,80 @@ class XmlFileLoader extends FileLoader $host = $node->hasAttribute('host') ? $node->getAttribute('host') : null; $schemes = $node->hasAttribute('schemes') ? preg_split('/[\s,\|]++/', $node->getAttribute('schemes'), -1, PREG_SPLIT_NO_EMPTY) : null; $methods = $node->hasAttribute('methods') ? preg_split('/[\s,\|]++/', $node->getAttribute('methods'), -1, PREG_SPLIT_NO_EMPTY) : null; + $trailingSlashOnRoot = $node->hasAttribute('trailing-slash-on-root') ? XmlUtils::phpize($node->getAttribute('trailing-slash-on-root')) : true; - list($defaults, $requirements, $options, $condition) = $this->parseConfigs($node, $path); - - $this->setCurrentDir(dirname($path)); + list($defaults, $requirements, $options, $condition, /* $paths */, $prefixes) = $this->parseConfigs($node, $path); - $subCollection = $this->import($resource, ('' !== $type ? $type : null), false, $file); - /* @var $subCollection RouteCollection */ - $subCollection->addPrefix($prefix); - if (null !== $host) { - $subCollection->setHost($host); - } - if (null !== $condition) { - $subCollection->setCondition($condition); + if ('' !== $prefix && $prefixes) { + throw new \InvalidArgumentException(sprintf('The <route> element in file "%s" must not have both a "prefix" attribute and <prefix> child nodes.', $path)); } - if (null !== $schemes) { - $subCollection->setSchemes($schemes); - } - if (null !== $methods) { - $subCollection->setMethods($methods); + + $this->setCurrentDir(\dirname($path)); + + /** @var RouteCollection[] $imported */ + $imported = $this->import($resource, ('' !== $type ? $type : null), false, $file); + + if (!\is_array($imported)) { + $imported = [$imported]; } - $subCollection->addDefaults($defaults); - $subCollection->addRequirements($requirements); - $subCollection->addOptions($options); - $collection->addCollection($subCollection); + foreach ($imported as $subCollection) { + /* @var $subCollection RouteCollection */ + if ('' !== $prefix || !$prefixes) { + $subCollection->addPrefix($prefix); + if (!$trailingSlashOnRoot) { + $rootPath = (new Route(trim(trim($prefix), '/').'/'))->getPath(); + foreach ($subCollection->all() as $route) { + if ($route->getPath() === $rootPath) { + $route->setPath(rtrim($rootPath, '/')); + } + } + } + } else { + foreach ($prefixes as $locale => $localePrefix) { + $prefixes[$locale] = trim(trim($localePrefix), '/'); + } + foreach ($subCollection->all() as $name => $route) { + if (null === $locale = $route->getDefault('_locale')) { + $subCollection->remove($name); + foreach ($prefixes as $locale => $localePrefix) { + $localizedRoute = clone $route; + $localizedRoute->setPath($localePrefix.(!$trailingSlashOnRoot && '/' === $route->getPath() ? '' : $route->getPath())); + $localizedRoute->setDefault('_locale', $locale); + $localizedRoute->setDefault('_canonical_route', $name); + $subCollection->add($name.'.'.$locale, $localizedRoute); + } + } elseif (!isset($prefixes[$locale])) { + throw new \InvalidArgumentException(sprintf('Route "%s" with locale "%s" is missing a corresponding prefix when imported in "%s".', $name, $locale, $path)); + } else { + $route->setPath($prefixes[$locale].(!$trailingSlashOnRoot && '/' === $route->getPath() ? '' : $route->getPath())); + $subCollection->add($name, $route); + } + } + } + + if (null !== $host) { + $subCollection->setHost($host); + } + if (null !== $condition) { + $subCollection->setCondition($condition); + } + if (null !== $schemes) { + $subCollection->setSchemes($schemes); + } + if (null !== $methods) { + $subCollection->setMethods($methods); + } + $subCollection->addDefaults($defaults); + $subCollection->addRequirements($requirements); + $subCollection->addOptions($options); + + if ($namePrefix = $node->getAttribute('name-prefix')) { + $subCollection->addNamePrefix($namePrefix); + } + + $collection->addCollection($subCollection); + } } /** @@ -196,17 +262,26 @@ class XmlFileLoader extends FileLoader */ private function parseConfigs(\DOMElement $node, $path) { - $defaults = array(); - $requirements = array(); - $options = array(); + $defaults = []; + $requirements = []; + $options = []; $condition = null; + $prefixes = []; + $paths = []; + /** @var \DOMElement $n */ foreach ($node->getElementsByTagNameNS(self::NAMESPACE_URI, '*') as $n) { if ($node !== $n->parentNode) { continue; } switch ($n->localName) { + case 'path': + $paths[$n->getAttribute('locale')] = trim($n->textContent); + break; + case 'prefix': + $prefixes[$n->getAttribute('locale')] = trim($n->textContent); + break; case 'default': if ($this->isElementValueNull($n)) { $defaults[$n->getAttribute('key')] = null; @@ -219,7 +294,7 @@ class XmlFileLoader extends FileLoader $requirements[$n->getAttribute('key')] = trim($n->textContent); break; case 'option': - $options[$n->getAttribute('key')] = trim($n->textContent); + $options[$n->getAttribute('key')] = XmlUtils::phpize(trim($n->textContent)); break; case 'condition': $condition = trim($n->textContent); @@ -238,8 +313,17 @@ class XmlFileLoader extends FileLoader $defaults['_controller'] = $controller; } + if ($node->hasAttribute('locale')) { + $defaults['_locale'] = $node->getAttribute('locale'); + } + if ($node->hasAttribute('format')) { + $defaults['_format'] = $node->getAttribute('format'); + } + if ($node->hasAttribute('utf8')) { + $options['utf8'] = XmlUtils::phpize($node->getAttribute('utf8')); + } - return array($defaults, $requirements, $options, $condition); + return [$defaults, $requirements, $options, $condition, $paths, $prefixes]; } /** @@ -253,7 +337,7 @@ class XmlFileLoader extends FileLoader private function parseDefaultsConfig(\DOMElement $element, $path) { if ($this->isElementValueNull($element)) { - return; + return null; } // Check for existing element nodes in the default element. There can @@ -290,7 +374,7 @@ class XmlFileLoader extends FileLoader private function parseDefaultNode(\DOMElement $node, $path) { if ($this->isElementValueNull($node)) { - return; + return null; } switch ($node->localName) { @@ -303,7 +387,7 @@ class XmlFileLoader extends FileLoader case 'string': return trim($node->nodeValue); case 'list': - $list = array(); + $list = []; foreach ($node->childNodes as $element) { if (!$element instanceof \DOMElement) { @@ -319,7 +403,7 @@ class XmlFileLoader extends FileLoader return $list; case 'map': - $map = array(); + $map = []; foreach ($node->childNodes as $element) { if (!$element instanceof \DOMElement) { diff --git a/vendor/symfony/routing/Loader/YamlFileLoader.php b/vendor/symfony/routing/Loader/YamlFileLoader.php index 037d581d05eab1420e45c346fef8a264acac78e2..15c223ecadcf4c6a899e86006e8ec59a5d4eae38 100644 --- a/vendor/symfony/routing/Loader/YamlFileLoader.php +++ b/vendor/symfony/routing/Loader/YamlFileLoader.php @@ -11,12 +11,13 @@ namespace Symfony\Component\Routing\Loader; -use Symfony\Component\Routing\RouteCollection; -use Symfony\Component\Routing\Route; +use Symfony\Component\Config\Loader\FileLoader; use Symfony\Component\Config\Resource\FileResource; +use Symfony\Component\Routing\Route; +use Symfony\Component\Routing\RouteCollection; use Symfony\Component\Yaml\Exception\ParseException; use Symfony\Component\Yaml\Parser as YamlParser; -use Symfony\Component\Config\Loader\FileLoader; +use Symfony\Component\Yaml\Yaml; /** * YamlFileLoader loads Yaml routing files. @@ -26,9 +27,9 @@ use Symfony\Component\Config\Loader\FileLoader; */ class YamlFileLoader extends FileLoader { - private static $availableKeys = array( - 'resource', 'type', 'prefix', 'path', 'host', 'schemes', 'methods', 'defaults', 'requirements', 'options', 'condition', 'controller', - ); + private static $availableKeys = [ + 'resource', 'type', 'prefix', 'path', 'host', 'schemes', 'methods', 'defaults', 'requirements', 'options', 'condition', 'controller', 'name_prefix', 'trailing_slash_on_root', 'locale', 'format', 'utf8', + ]; private $yamlParser; /** @@ -57,18 +58,10 @@ class YamlFileLoader extends FileLoader $this->yamlParser = new YamlParser(); } - $prevErrorHandler = set_error_handler(function ($level, $message, $script, $line) use ($file, &$prevErrorHandler) { - $message = E_USER_DEPRECATED === $level ? preg_replace('/ on line \d+/', ' in "'.$file.'"$0', $message) : $message; - - return $prevErrorHandler ? $prevErrorHandler($level, $message, $script, $line) : false; - }); - try { - $parsedConfig = $this->yamlParser->parseFile($path); + $parsedConfig = $this->yamlParser->parseFile($path, Yaml::PARSE_CONSTANT); } catch (ParseException $e) { throw new \InvalidArgumentException(sprintf('The file "%s" does not contain valid YAML.', $path), 0, $e); - } finally { - restore_error_handler(); } $collection = new RouteCollection(); @@ -80,7 +73,7 @@ class YamlFileLoader extends FileLoader } // not an array - if (!is_array($parsedConfig)) { + if (!\is_array($parsedConfig)) { throw new \InvalidArgumentException(sprintf('The file "%s" must contain a YAML array.', $path)); } @@ -102,7 +95,7 @@ class YamlFileLoader extends FileLoader */ public function supports($resource, $type = null) { - return is_string($resource) && in_array(pathinfo($resource, PATHINFO_EXTENSION), array('yml', 'yaml'), true) && (!$type || 'yaml' === $type); + return \is_string($resource) && \in_array(pathinfo($resource, PATHINFO_EXTENSION), ['yml', 'yaml'], true) && (!$type || 'yaml' === $type); } /** @@ -115,21 +108,47 @@ class YamlFileLoader extends FileLoader */ protected function parseRoute(RouteCollection $collection, $name, array $config, $path) { - $defaults = isset($config['defaults']) ? $config['defaults'] : array(); - $requirements = isset($config['requirements']) ? $config['requirements'] : array(); - $options = isset($config['options']) ? $config['options'] : array(); + $defaults = isset($config['defaults']) ? $config['defaults'] : []; + $requirements = isset($config['requirements']) ? $config['requirements'] : []; + $options = isset($config['options']) ? $config['options'] : []; $host = isset($config['host']) ? $config['host'] : ''; - $schemes = isset($config['schemes']) ? $config['schemes'] : array(); - $methods = isset($config['methods']) ? $config['methods'] : array(); + $schemes = isset($config['schemes']) ? $config['schemes'] : []; + $methods = isset($config['methods']) ? $config['methods'] : []; $condition = isset($config['condition']) ? $config['condition'] : null; + foreach ($requirements as $placeholder => $requirement) { + if (\is_int($placeholder)) { + @trigger_error(sprintf('A placeholder name must be a string (%d given). Did you forget to specify the placeholder key for the requirement "%s" of route "%s" in "%s"?', $placeholder, $requirement, $name, $path), E_USER_DEPRECATED); + } + } + if (isset($config['controller'])) { $defaults['_controller'] = $config['controller']; } + if (isset($config['locale'])) { + $defaults['_locale'] = $config['locale']; + } + if (isset($config['format'])) { + $defaults['_format'] = $config['format']; + } + if (isset($config['utf8'])) { + $options['utf8'] = $config['utf8']; + } - $route = new Route($config['path'], $defaults, $requirements, $options, $host, $schemes, $methods, $condition); + if (\is_array($config['path'])) { + $route = new Route('', $defaults, $requirements, $options, $host, $schemes, $methods, $condition); - $collection->add($name, $route); + foreach ($config['path'] as $locale => $path) { + $localizedRoute = clone $route; + $localizedRoute->setDefault('_locale', $locale); + $localizedRoute->setDefault('_canonical_route', $name); + $localizedRoute->setPath($path); + $collection->add($name.'.'.$locale, $localizedRoute); + } + } else { + $route = new Route($config['path'], $defaults, $requirements, $options, $host, $schemes, $methods, $condition); + $collection->add($name, $route); + } } /** @@ -144,40 +163,93 @@ class YamlFileLoader extends FileLoader { $type = isset($config['type']) ? $config['type'] : null; $prefix = isset($config['prefix']) ? $config['prefix'] : ''; - $defaults = isset($config['defaults']) ? $config['defaults'] : array(); - $requirements = isset($config['requirements']) ? $config['requirements'] : array(); - $options = isset($config['options']) ? $config['options'] : array(); + $defaults = isset($config['defaults']) ? $config['defaults'] : []; + $requirements = isset($config['requirements']) ? $config['requirements'] : []; + $options = isset($config['options']) ? $config['options'] : []; $host = isset($config['host']) ? $config['host'] : null; $condition = isset($config['condition']) ? $config['condition'] : null; $schemes = isset($config['schemes']) ? $config['schemes'] : null; $methods = isset($config['methods']) ? $config['methods'] : null; + $trailingSlashOnRoot = $config['trailing_slash_on_root'] ?? true; if (isset($config['controller'])) { $defaults['_controller'] = $config['controller']; } - - $this->setCurrentDir(dirname($path)); - - $subCollection = $this->import($config['resource'], $type, false, $file); - /* @var $subCollection RouteCollection */ - $subCollection->addPrefix($prefix); - if (null !== $host) { - $subCollection->setHost($host); + if (isset($config['locale'])) { + $defaults['_locale'] = $config['locale']; } - if (null !== $condition) { - $subCollection->setCondition($condition); + if (isset($config['format'])) { + $defaults['_format'] = $config['format']; } - if (null !== $schemes) { - $subCollection->setSchemes($schemes); + if (isset($config['utf8'])) { + $options['utf8'] = $config['utf8']; } - if (null !== $methods) { - $subCollection->setMethods($methods); + + $this->setCurrentDir(\dirname($path)); + + $imported = $this->import($config['resource'], $type, false, $file); + + if (!\is_array($imported)) { + $imported = [$imported]; } - $subCollection->addDefaults($defaults); - $subCollection->addRequirements($requirements); - $subCollection->addOptions($options); - $collection->addCollection($subCollection); + foreach ($imported as $subCollection) { + /* @var $subCollection RouteCollection */ + if (!\is_array($prefix)) { + $subCollection->addPrefix($prefix); + if (!$trailingSlashOnRoot) { + $rootPath = (new Route(trim(trim($prefix), '/').'/'))->getPath(); + foreach ($subCollection->all() as $route) { + if ($route->getPath() === $rootPath) { + $route->setPath(rtrim($rootPath, '/')); + } + } + } + } else { + foreach ($prefix as $locale => $localePrefix) { + $prefix[$locale] = trim(trim($localePrefix), '/'); + } + foreach ($subCollection->all() as $name => $route) { + if (null === $locale = $route->getDefault('_locale')) { + $subCollection->remove($name); + foreach ($prefix as $locale => $localePrefix) { + $localizedRoute = clone $route; + $localizedRoute->setDefault('_locale', $locale); + $localizedRoute->setDefault('_canonical_route', $name); + $localizedRoute->setPath($localePrefix.(!$trailingSlashOnRoot && '/' === $route->getPath() ? '' : $route->getPath())); + $subCollection->add($name.'.'.$locale, $localizedRoute); + } + } elseif (!isset($prefix[$locale])) { + throw new \InvalidArgumentException(sprintf('Route "%s" with locale "%s" is missing a corresponding prefix when imported in "%s".', $name, $locale, $file)); + } else { + $route->setPath($prefix[$locale].(!$trailingSlashOnRoot && '/' === $route->getPath() ? '' : $route->getPath())); + $subCollection->add($name, $route); + } + } + } + + if (null !== $host) { + $subCollection->setHost($host); + } + if (null !== $condition) { + $subCollection->setCondition($condition); + } + if (null !== $schemes) { + $subCollection->setSchemes($schemes); + } + if (null !== $methods) { + $subCollection->setMethods($methods); + } + $subCollection->addDefaults($defaults); + $subCollection->addRequirements($requirements); + $subCollection->addOptions($options); + + if (isset($config['name_prefix'])) { + $subCollection->addNamePrefix($config['name_prefix']); + } + + $collection->addCollection($subCollection); + } } /** @@ -192,32 +264,20 @@ class YamlFileLoader extends FileLoader */ protected function validate($config, $name, $path) { - if (!is_array($config)) { + if (!\is_array($config)) { throw new \InvalidArgumentException(sprintf('The definition of "%s" in "%s" must be a YAML array.', $name, $path)); } if ($extraKeys = array_diff(array_keys($config), self::$availableKeys)) { - throw new \InvalidArgumentException(sprintf( - 'The routing file "%s" contains unsupported keys for "%s": "%s". Expected one of: "%s".', - $path, $name, implode('", "', $extraKeys), implode('", "', self::$availableKeys) - )); + throw new \InvalidArgumentException(sprintf('The routing file "%s" contains unsupported keys for "%s": "%s". Expected one of: "%s".', $path, $name, implode('", "', $extraKeys), implode('", "', self::$availableKeys))); } if (isset($config['resource']) && isset($config['path'])) { - throw new \InvalidArgumentException(sprintf( - 'The routing file "%s" must not specify both the "resource" key and the "path" key for "%s". Choose between an import and a route definition.', - $path, $name - )); + throw new \InvalidArgumentException(sprintf('The routing file "%s" must not specify both the "resource" key and the "path" key for "%s". Choose between an import and a route definition.', $path, $name)); } if (!isset($config['resource']) && isset($config['type'])) { - throw new \InvalidArgumentException(sprintf( - 'The "type" key for the route definition "%s" in "%s" is unsupported. It is only available for imports in combination with the "resource" key.', - $name, $path - )); + throw new \InvalidArgumentException(sprintf('The "type" key for the route definition "%s" in "%s" is unsupported. It is only available for imports in combination with the "resource" key.', $name, $path)); } if (!isset($config['resource']) && !isset($config['path'])) { - throw new \InvalidArgumentException(sprintf( - 'You must define a "path" for the route "%s" in file "%s".', - $name, $path - )); + throw new \InvalidArgumentException(sprintf('You must define a "path" for the route "%s" in file "%s".', $name, $path)); } if (isset($config['controller']) && isset($config['defaults']['_controller'])) { throw new \InvalidArgumentException(sprintf('The routing file "%s" must not specify both the "controller" key and the defaults key "_controller" for "%s".', $path, $name)); diff --git a/vendor/symfony/routing/Loader/schema/routing/routing-1.0.xsd b/vendor/symfony/routing/Loader/schema/routing/routing-1.0.xsd index a97111aaa55e32353d714b2f56f5df74122ee813..ebf6632a57269d1a75ef3a95b2903c28f54a98c2 100644 --- a/vendor/symfony/routing/Loader/schema/routing/routing-1.0.xsd +++ b/vendor/symfony/routing/Loader/schema/routing/routing-1.0.xsd @@ -24,6 +24,14 @@ </xsd:choice> </xsd:complexType> + <xsd:complexType name="localized-path"> + <xsd:simpleContent> + <xsd:extension base="xsd:string"> + <xsd:attribute name="locale" type="xsd:string" use="required" /> + </xsd:extension> + </xsd:simpleContent> + </xsd:complexType> + <xsd:group name="configs"> <xsd:choice> <xsd:element name="default" nillable="true" type="default" /> @@ -34,26 +42,38 @@ </xsd:group> <xsd:complexType name="route"> - <xsd:group ref="configs" minOccurs="0" maxOccurs="unbounded" /> - + <xsd:sequence> + <xsd:group ref="configs" minOccurs="0" maxOccurs="unbounded" /> + <xsd:element name="path" type="localized-path" minOccurs="0" maxOccurs="unbounded" /> + </xsd:sequence> <xsd:attribute name="id" type="xsd:string" use="required" /> - <xsd:attribute name="path" type="xsd:string" use="required" /> + <xsd:attribute name="path" type="xsd:string" /> <xsd:attribute name="host" type="xsd:string" /> <xsd:attribute name="schemes" type="xsd:string" /> <xsd:attribute name="methods" type="xsd:string" /> <xsd:attribute name="controller" type="xsd:string" /> + <xsd:attribute name="locale" type="xsd:string" /> + <xsd:attribute name="format" type="xsd:string" /> + <xsd:attribute name="utf8" type="xsd:boolean" /> </xsd:complexType> <xsd:complexType name="import"> - <xsd:group ref="configs" minOccurs="0" maxOccurs="unbounded" /> - + <xsd:sequence maxOccurs="unbounded" minOccurs="0"> + <xsd:group ref="configs" minOccurs="0" maxOccurs="unbounded" /> + <xsd:element name="prefix" type="localized-path" minOccurs="0" maxOccurs="unbounded" /> + </xsd:sequence> <xsd:attribute name="resource" type="xsd:string" use="required" /> <xsd:attribute name="type" type="xsd:string" /> <xsd:attribute name="prefix" type="xsd:string" /> + <xsd:attribute name="name-prefix" type="xsd:string" /> <xsd:attribute name="host" type="xsd:string" /> <xsd:attribute name="schemes" type="xsd:string" /> <xsd:attribute name="methods" type="xsd:string" /> <xsd:attribute name="controller" type="xsd:string" /> + <xsd:attribute name="locale" type="xsd:string" /> + <xsd:attribute name="format" type="xsd:string" /> + <xsd:attribute name="trailing-slash-on-root" type="xsd:boolean" /> + <xsd:attribute name="utf8" type="xsd:boolean" /> </xsd:complexType> <xsd:complexType name="default" mixed="true"> diff --git a/vendor/symfony/routing/Matcher/CompiledUrlMatcher.php b/vendor/symfony/routing/Matcher/CompiledUrlMatcher.php new file mode 100644 index 0000000000000000000000000000000000000000..e15cda77865853e360b6da35c8f7c85fde8ffd2f --- /dev/null +++ b/vendor/symfony/routing/Matcher/CompiledUrlMatcher.php @@ -0,0 +1,31 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Matcher; + +use Symfony\Component\Routing\Matcher\Dumper\CompiledUrlMatcherTrait; +use Symfony\Component\Routing\RequestContext; + +/** + * Matches URLs based on rules dumped by CompiledUrlMatcherDumper. + * + * @author Nicolas Grekas <p@tchwork.com> + */ +class CompiledUrlMatcher extends UrlMatcher +{ + use CompiledUrlMatcherTrait; + + public function __construct(array $compiledRoutes, RequestContext $context) + { + $this->context = $context; + list($this->matchHost, $this->staticRoutes, $this->regexpList, $this->dynamicRoutes, $this->checkCondition) = $compiledRoutes; + } +} diff --git a/vendor/symfony/routing/Matcher/Dumper/CompiledUrlMatcherDumper.php b/vendor/symfony/routing/Matcher/Dumper/CompiledUrlMatcherDumper.php new file mode 100644 index 0000000000000000000000000000000000000000..ab67e6885ac924534d2eb8e8441996877981ee8b --- /dev/null +++ b/vendor/symfony/routing/Matcher/Dumper/CompiledUrlMatcherDumper.php @@ -0,0 +1,501 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Matcher\Dumper; + +use Symfony\Component\ExpressionLanguage\ExpressionFunctionProviderInterface; +use Symfony\Component\ExpressionLanguage\ExpressionLanguage; +use Symfony\Component\Routing\Route; +use Symfony\Component\Routing\RouteCollection; + +/** + * CompiledUrlMatcherDumper creates PHP arrays to be used with CompiledUrlMatcher. + * + * @author Fabien Potencier <fabien@symfony.com> + * @author Tobias Schultze <http://tobion.de> + * @author Arnaud Le Blanc <arnaud.lb@gmail.com> + * @author Nicolas Grekas <p@tchwork.com> + */ +class CompiledUrlMatcherDumper extends MatcherDumper +{ + private $expressionLanguage; + private $signalingException; + + /** + * @var ExpressionFunctionProviderInterface[] + */ + private $expressionLanguageProviders = []; + + /** + * {@inheritdoc} + */ + public function dump(array $options = []) + { + return <<<EOF +<?php + +/** + * This file has been auto-generated + * by the Symfony Routing Component. + */ + +return [ +{$this->generateCompiledRoutes()}]; + +EOF; + } + + public function addExpressionLanguageProvider(ExpressionFunctionProviderInterface $provider) + { + $this->expressionLanguageProviders[] = $provider; + } + + /** + * Generates the arrays for CompiledUrlMatcher's constructor. + */ + public function getCompiledRoutes(bool $forDump = false): array + { + // Group hosts by same-suffix, re-order when possible + $matchHost = false; + $routes = new StaticPrefixCollection(); + foreach ($this->getRoutes()->all() as $name => $route) { + if ($host = $route->getHost()) { + $matchHost = true; + $host = '/'.strtr(strrev($host), '}.{', '(/)'); + } + + $routes->addRoute($host ?: '/(.*)', [$name, $route]); + } + + if ($matchHost) { + $compiledRoutes = [true]; + $routes = $routes->populateCollection(new RouteCollection()); + } else { + $compiledRoutes = [false]; + $routes = $this->getRoutes(); + } + + list($staticRoutes, $dynamicRoutes) = $this->groupStaticRoutes($routes); + + $conditions = [null]; + $compiledRoutes[] = $this->compileStaticRoutes($staticRoutes, $conditions); + $chunkLimit = \count($dynamicRoutes); + + while (true) { + try { + $this->signalingException = new \RuntimeException('Compilation failed: regular expression is too large'); + $compiledRoutes = array_merge($compiledRoutes, $this->compileDynamicRoutes($dynamicRoutes, $matchHost, $chunkLimit, $conditions)); + + break; + } catch (\Exception $e) { + if (1 < $chunkLimit && $this->signalingException === $e) { + $chunkLimit = 1 + ($chunkLimit >> 1); + continue; + } + throw $e; + } + } + + if ($forDump) { + $compiledRoutes[2] = $compiledRoutes[4]; + } + unset($conditions[0]); + + if ($conditions) { + foreach ($conditions as $expression => $condition) { + $conditions[$expression] = "case {$condition}: return {$expression};"; + } + + $checkConditionCode = <<<EOF + static function (\$condition, \$context, \$request) { // \$checkCondition + switch (\$condition) { +{$this->indent(implode("\n", $conditions), 3)} + } + } +EOF; + $compiledRoutes[4] = $forDump ? $checkConditionCode .= ",\n" : eval('return '.$checkConditionCode.';'); + } else { + $compiledRoutes[4] = $forDump ? " null, // \$checkCondition\n" : null; + } + + return $compiledRoutes; + } + + private function generateCompiledRoutes(): string + { + list($matchHost, $staticRoutes, $regexpCode, $dynamicRoutes, $checkConditionCode) = $this->getCompiledRoutes(true); + + $code = self::export($matchHost).', // $matchHost'."\n"; + + $code .= '[ // $staticRoutes'."\n"; + foreach ($staticRoutes as $path => $routes) { + $code .= sprintf(" %s => [\n", self::export($path)); + foreach ($routes as $route) { + $code .= sprintf(" [%s, %s, %s, %s, %s, %s, %s],\n", ...array_map([__CLASS__, 'export'], $route)); + } + $code .= " ],\n"; + } + $code .= "],\n"; + + $code .= sprintf("[ // \$regexpList%s\n],\n", $regexpCode); + + $code .= '[ // $dynamicRoutes'."\n"; + foreach ($dynamicRoutes as $path => $routes) { + $code .= sprintf(" %s => [\n", self::export($path)); + foreach ($routes as $route) { + $code .= sprintf(" [%s, %s, %s, %s, %s, %s, %s],\n", ...array_map([__CLASS__, 'export'], $route)); + } + $code .= " ],\n"; + } + $code .= "],\n"; + $code = preg_replace('/ => \[\n (\[.+?),\n \],/', ' => [$1],', $code); + + return $this->indent($code, 1).$checkConditionCode; + } + + /** + * Splits static routes from dynamic routes, so that they can be matched first, using a simple switch. + */ + private function groupStaticRoutes(RouteCollection $collection): array + { + $staticRoutes = $dynamicRegex = []; + $dynamicRoutes = new RouteCollection(); + + foreach ($collection->all() as $name => $route) { + $compiledRoute = $route->compile(); + $staticPrefix = rtrim($compiledRoute->getStaticPrefix(), '/'); + $hostRegex = $compiledRoute->getHostRegex(); + $regex = $compiledRoute->getRegex(); + if ($hasTrailingSlash = '/' !== $route->getPath()) { + $pos = strrpos($regex, '$'); + $hasTrailingSlash = '/' === $regex[$pos - 1]; + $regex = substr_replace($regex, '/?$', $pos - $hasTrailingSlash, 1 + $hasTrailingSlash); + } + + if (!$compiledRoute->getPathVariables()) { + $host = !$compiledRoute->getHostVariables() ? $route->getHost() : ''; + $url = $route->getPath(); + if ($hasTrailingSlash) { + $url = substr($url, 0, -1); + } + foreach ($dynamicRegex as list($hostRx, $rx, $prefix)) { + if (('' === $prefix || 0 === strpos($url, $prefix)) && (preg_match($rx, $url) || preg_match($rx, $url.'/')) && (!$host || !$hostRx || preg_match($hostRx, $host))) { + $dynamicRegex[] = [$hostRegex, $regex, $staticPrefix]; + $dynamicRoutes->add($name, $route); + continue 2; + } + } + + $staticRoutes[$url][$name] = [$route, $hasTrailingSlash]; + } else { + $dynamicRegex[] = [$hostRegex, $regex, $staticPrefix]; + $dynamicRoutes->add($name, $route); + } + } + + return [$staticRoutes, $dynamicRoutes]; + } + + /** + * Compiles static routes in a switch statement. + * + * Condition-less paths are put in a static array in the switch's default, with generic matching logic. + * Paths that can match two or more routes, or have user-specified conditions are put in separate switch's cases. + * + * @throws \LogicException + */ + private function compileStaticRoutes(array $staticRoutes, array &$conditions): array + { + if (!$staticRoutes) { + return []; + } + $compiledRoutes = []; + + foreach ($staticRoutes as $url => $routes) { + $compiledRoutes[$url] = []; + foreach ($routes as $name => list($route, $hasTrailingSlash)) { + $compiledRoutes[$url][] = $this->compileRoute($route, $name, (!$route->compile()->getHostVariables() ? $route->getHost() : $route->compile()->getHostRegex()) ?: null, $hasTrailingSlash, false, $conditions); + } + } + + return $compiledRoutes; + } + + /** + * Compiles a regular expression followed by a switch statement to match dynamic routes. + * + * The regular expression matches both the host and the pathinfo at the same time. For stellar performance, + * it is built as a tree of patterns, with re-ordering logic to group same-prefix routes together when possible. + * + * Patterns are named so that we know which one matched (https://pcre.org/current/doc/html/pcre2syntax.html#SEC23). + * This name is used to "switch" to the additional logic required to match the final route. + * + * Condition-less paths are put in a static array in the switch's default, with generic matching logic. + * Paths that can match two or more routes, or have user-specified conditions are put in separate switch's cases. + * + * Last but not least: + * - Because it is not possibe to mix unicode/non-unicode patterns in a single regexp, several of them can be generated. + * - The same regexp can be used several times when the logic in the switch rejects the match. When this happens, the + * matching-but-failing subpattern is blacklisted by replacing its name by "(*F)", which forces a failure-to-match. + * To ease this backlisting operation, the name of subpatterns is also the string offset where the replacement should occur. + */ + private function compileDynamicRoutes(RouteCollection $collection, bool $matchHost, int $chunkLimit, array &$conditions): array + { + if (!$collection->all()) { + return [[], [], '']; + } + $regexpList = []; + $code = ''; + $state = (object) [ + 'regexMark' => 0, + 'regex' => [], + 'routes' => [], + 'mark' => 0, + 'markTail' => 0, + 'hostVars' => [], + 'vars' => [], + ]; + $state->getVars = static function ($m) use ($state) { + if ('_route' === $m[1]) { + return '?:'; + } + + $state->vars[] = $m[1]; + + return ''; + }; + + $chunkSize = 0; + $prev = null; + $perModifiers = []; + foreach ($collection->all() as $name => $route) { + preg_match('#[a-zA-Z]*$#', $route->compile()->getRegex(), $rx); + if ($chunkLimit < ++$chunkSize || $prev !== $rx[0] && $route->compile()->getPathVariables()) { + $chunkSize = 1; + $routes = new RouteCollection(); + $perModifiers[] = [$rx[0], $routes]; + $prev = $rx[0]; + } + $routes->add($name, $route); + } + + foreach ($perModifiers as list($modifiers, $routes)) { + $prev = false; + $perHost = []; + foreach ($routes->all() as $name => $route) { + $regex = $route->compile()->getHostRegex(); + if ($prev !== $regex) { + $routes = new RouteCollection(); + $perHost[] = [$regex, $routes]; + $prev = $regex; + } + $routes->add($name, $route); + } + $prev = false; + $rx = '{^(?'; + $code .= "\n {$state->mark} => ".self::export($rx); + $startingMark = $state->mark; + $state->mark += \strlen($rx); + $state->regex = $rx; + + foreach ($perHost as list($hostRegex, $routes)) { + if ($matchHost) { + if ($hostRegex) { + preg_match('#^.\^(.*)\$.[a-zA-Z]*$#', $hostRegex, $rx); + $state->vars = []; + $hostRegex = '(?i:'.preg_replace_callback('#\?P<([^>]++)>#', $state->getVars, $rx[1]).')\.'; + $state->hostVars = $state->vars; + } else { + $hostRegex = '(?:(?:[^./]*+\.)++)'; + $state->hostVars = []; + } + $state->mark += \strlen($rx = ($prev ? ')' : '')."|{$hostRegex}(?"); + $code .= "\n .".self::export($rx); + $state->regex .= $rx; + $prev = true; + } + + $tree = new StaticPrefixCollection(); + foreach ($routes->all() as $name => $route) { + preg_match('#^.\^(.*)\$.[a-zA-Z]*$#', $route->compile()->getRegex(), $rx); + + $state->vars = []; + $regex = preg_replace_callback('#\?P<([^>]++)>#', $state->getVars, $rx[1]); + if ($hasTrailingSlash = '/' !== $regex && '/' === $regex[-1]) { + $regex = substr($regex, 0, -1); + } + $hasTrailingVar = (bool) preg_match('#\{\w+\}/?$#', $route->getPath()); + + $tree->addRoute($regex, [$name, $regex, $state->vars, $route, $hasTrailingSlash, $hasTrailingVar]); + } + + $code .= $this->compileStaticPrefixCollection($tree, $state, 0, $conditions); + } + if ($matchHost) { + $code .= "\n .')'"; + $state->regex .= ')'; + } + $rx = ")/?$}{$modifiers}"; + $code .= "\n .'{$rx}',"; + $state->regex .= $rx; + $state->markTail = 0; + + // if the regex is too large, throw a signaling exception to recompute with smaller chunk size + set_error_handler(function ($type, $message) { throw false !== strpos($message, $this->signalingException->getMessage()) ? $this->signalingException : new \ErrorException($message); }); + try { + preg_match($state->regex, ''); + } finally { + restore_error_handler(); + } + + $regexpList[$startingMark] = $state->regex; + } + + $state->routes[$state->mark][] = [null, null, null, null, false, false, 0]; + unset($state->getVars); + + return [$regexpList, $state->routes, $code]; + } + + /** + * Compiles a regexp tree of subpatterns that matches nested same-prefix routes. + * + * @param \stdClass $state A simple state object that keeps track of the progress of the compilation, + * and gathers the generated switch's "case" and "default" statements + */ + private function compileStaticPrefixCollection(StaticPrefixCollection $tree, \stdClass $state, int $prefixLen, array &$conditions): string + { + $code = ''; + $prevRegex = null; + $routes = $tree->getRoutes(); + + foreach ($routes as $i => $route) { + if ($route instanceof StaticPrefixCollection) { + $prevRegex = null; + $prefix = substr($route->getPrefix(), $prefixLen); + $state->mark += \strlen($rx = "|{$prefix}(?"); + $code .= "\n .".self::export($rx); + $state->regex .= $rx; + $code .= $this->indent($this->compileStaticPrefixCollection($route, $state, $prefixLen + \strlen($prefix), $conditions)); + $code .= "\n .')'"; + $state->regex .= ')'; + ++$state->markTail; + continue; + } + + list($name, $regex, $vars, $route, $hasTrailingSlash, $hasTrailingVar) = $route; + $compiledRoute = $route->compile(); + $vars = array_merge($state->hostVars, $vars); + + if ($compiledRoute->getRegex() === $prevRegex) { + $state->routes[$state->mark][] = $this->compileRoute($route, $name, $vars, $hasTrailingSlash, $hasTrailingVar, $conditions); + continue; + } + + $state->mark += 3 + $state->markTail + \strlen($regex) - $prefixLen; + $state->markTail = 2 + \strlen($state->mark); + $rx = sprintf('|%s(*:%s)', substr($regex, $prefixLen), $state->mark); + $code .= "\n .".self::export($rx); + $state->regex .= $rx; + + $prevRegex = $compiledRoute->getRegex(); + $state->routes[$state->mark] = [$this->compileRoute($route, $name, $vars, $hasTrailingSlash, $hasTrailingVar, $conditions)]; + } + + return $code; + } + + /** + * Compiles a single Route to PHP code used to match it against the path info. + */ + private function compileRoute(Route $route, string $name, $vars, bool $hasTrailingSlash, bool $hasTrailingVar, array &$conditions): array + { + $defaults = $route->getDefaults(); + + if (isset($defaults['_canonical_route'])) { + $name = $defaults['_canonical_route']; + unset($defaults['_canonical_route']); + } + + if ($condition = $route->getCondition()) { + $condition = $this->getExpressionLanguage()->compile($condition, ['context', 'request']); + $condition = $conditions[$condition] ?? $conditions[$condition] = (false !== strpos($condition, '$request') ? 1 : -1) * \count($conditions); + } else { + $condition = null; + } + + return [ + ['_route' => $name] + $defaults, + $vars, + array_flip($route->getMethods()) ?: null, + array_flip($route->getSchemes()) ?: null, + $hasTrailingSlash, + $hasTrailingVar, + $condition, + ]; + } + + private function getExpressionLanguage() + { + if (null === $this->expressionLanguage) { + if (!class_exists('Symfony\Component\ExpressionLanguage\ExpressionLanguage')) { + throw new \LogicException('Unable to use expressions as the Symfony ExpressionLanguage component is not installed.'); + } + $this->expressionLanguage = new ExpressionLanguage(null, $this->expressionLanguageProviders); + } + + return $this->expressionLanguage; + } + + private function indent($code, $level = 1) + { + return preg_replace('/^./m', str_repeat(' ', $level).'$0', $code); + } + + /** + * @internal + */ + public static function export($value): string + { + if (null === $value) { + return 'null'; + } + if (!\is_array($value)) { + if (\is_object($value)) { + throw new \InvalidArgumentException('Symfony\Component\Routing\Route cannot contain objects.'); + } + + return str_replace("\n", '\'."\n".\'', var_export($value, true)); + } + if (!$value) { + return '[]'; + } + + $i = 0; + $export = '['; + + foreach ($value as $k => $v) { + if ($i === $k) { + ++$i; + } else { + $export .= self::export($k).' => '; + + if (\is_int($k) && $i < $k) { + $i = 1 + $k; + } + } + + $export .= self::export($v).', '; + } + + return substr_replace($export, ']', -2); + } +} diff --git a/vendor/symfony/routing/Matcher/Dumper/CompiledUrlMatcherTrait.php b/vendor/symfony/routing/Matcher/Dumper/CompiledUrlMatcherTrait.php new file mode 100644 index 0000000000000000000000000000000000000000..0528a7b213c61408d0db5cd6c3d16489bdf0463e --- /dev/null +++ b/vendor/symfony/routing/Matcher/Dumper/CompiledUrlMatcherTrait.php @@ -0,0 +1,187 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Matcher\Dumper; + +use Symfony\Component\Routing\Exception\MethodNotAllowedException; +use Symfony\Component\Routing\Exception\NoConfigurationException; +use Symfony\Component\Routing\Exception\ResourceNotFoundException; +use Symfony\Component\Routing\Matcher\RedirectableUrlMatcherInterface; +use Symfony\Component\Routing\RequestContext; + +/** + * @author Nicolas Grekas <p@tchwork.com> + * + * @internal + * + * @property RequestContext $context + */ +trait CompiledUrlMatcherTrait +{ + private $matchHost = false; + private $staticRoutes = []; + private $regexpList = []; + private $dynamicRoutes = []; + private $checkCondition; + + public function match($pathinfo) + { + $allow = $allowSchemes = []; + if ($ret = $this->doMatch($pathinfo, $allow, $allowSchemes)) { + return $ret; + } + if ($allow) { + throw new MethodNotAllowedException(array_keys($allow)); + } + if (!$this instanceof RedirectableUrlMatcherInterface) { + throw new ResourceNotFoundException(sprintf('No routes found for "%s".', $pathinfo)); + } + if (!\in_array($this->context->getMethod(), ['HEAD', 'GET'], true)) { + // no-op + } elseif ($allowSchemes) { + redirect_scheme: + $scheme = $this->context->getScheme(); + $this->context->setScheme(key($allowSchemes)); + try { + if ($ret = $this->doMatch($pathinfo)) { + return $this->redirect($pathinfo, $ret['_route'], $this->context->getScheme()) + $ret; + } + } finally { + $this->context->setScheme($scheme); + } + } elseif ('/' !== $trimmedPathinfo = rtrim($pathinfo, '/') ?: '/') { + $pathinfo = $trimmedPathinfo === $pathinfo ? $pathinfo.'/' : $trimmedPathinfo; + if ($ret = $this->doMatch($pathinfo, $allow, $allowSchemes)) { + return $this->redirect($pathinfo, $ret['_route']) + $ret; + } + if ($allowSchemes) { + goto redirect_scheme; + } + } + + throw new ResourceNotFoundException(sprintf('No routes found for "%s".', $pathinfo)); + } + + private function doMatch(string $pathinfo, array &$allow = [], array &$allowSchemes = []): array + { + $allow = $allowSchemes = []; + $pathinfo = rawurldecode($pathinfo) ?: '/'; + $trimmedPathinfo = rtrim($pathinfo, '/') ?: '/'; + $context = $this->context; + $requestMethod = $canonicalMethod = $context->getMethod(); + + if ($this->matchHost) { + $host = strtolower($context->getHost()); + } + + if ('HEAD' === $requestMethod) { + $canonicalMethod = 'GET'; + } + $supportsRedirections = 'GET' === $canonicalMethod && $this instanceof RedirectableUrlMatcherInterface; + + foreach ($this->staticRoutes[$trimmedPathinfo] ?? [] as list($ret, $requiredHost, $requiredMethods, $requiredSchemes, $hasTrailingSlash, , $condition)) { + if ($condition && !($this->checkCondition)($condition, $context, 0 < $condition ? $request ?? $request = $this->request ?: $this->createRequest($pathinfo) : null)) { + continue; + } + + if ($requiredHost) { + if ('#' !== $requiredHost[0] ? $requiredHost !== $host : !preg_match($requiredHost, $host, $hostMatches)) { + continue; + } + if ('#' === $requiredHost[0] && $hostMatches) { + $hostMatches['_route'] = $ret['_route']; + $ret = $this->mergeDefaults($hostMatches, $ret); + } + } + + if ('/' !== $pathinfo && $hasTrailingSlash === ($trimmedPathinfo === $pathinfo)) { + if ($supportsRedirections && (!$requiredMethods || isset($requiredMethods['GET']))) { + return $allow = $allowSchemes = []; + } + continue; + } + + $hasRequiredScheme = !$requiredSchemes || isset($requiredSchemes[$context->getScheme()]); + if ($hasRequiredScheme && $requiredMethods && !isset($requiredMethods[$canonicalMethod]) && !isset($requiredMethods[$requestMethod])) { + $allow += $requiredMethods; + continue; + } + + if (!$hasRequiredScheme) { + $allowSchemes += $requiredSchemes; + continue; + } + + return $ret; + } + + $matchedPathinfo = $this->matchHost ? $host.'.'.$pathinfo : $pathinfo; + + foreach ($this->regexpList as $offset => $regex) { + while (preg_match($regex, $matchedPathinfo, $matches)) { + foreach ($this->dynamicRoutes[$m = (int) $matches['MARK']] as list($ret, $vars, $requiredMethods, $requiredSchemes, $hasTrailingSlash, $hasTrailingVar, $condition)) { + if (null !== $condition) { + if (0 === $condition) { // marks the last route in the regexp + continue 3; + } + if (!($this->checkCondition)($condition, $context, 0 < $condition ? $request ?? $request = $this->request ?: $this->createRequest($pathinfo) : null)) { + continue; + } + } + + $hasTrailingVar = $trimmedPathinfo !== $pathinfo && $hasTrailingVar; + + if ($hasTrailingVar && ($hasTrailingSlash || (null === $n = $matches[\count($vars)] ?? null) || '/' !== ($n[-1] ?? '/')) && preg_match($regex, $this->matchHost ? $host.'.'.$trimmedPathinfo : $trimmedPathinfo, $n) && $m === (int) $n['MARK']) { + if ($hasTrailingSlash) { + $matches = $n; + } else { + $hasTrailingVar = false; + } + } + + if ('/' !== $pathinfo && !$hasTrailingVar && $hasTrailingSlash === ($trimmedPathinfo === $pathinfo)) { + if ($supportsRedirections && (!$requiredMethods || isset($requiredMethods['GET']))) { + return $allow = $allowSchemes = []; + } + continue; + } + + foreach ($vars as $i => $v) { + if (isset($matches[1 + $i])) { + $ret[$v] = $matches[1 + $i]; + } + } + + if ($requiredSchemes && !isset($requiredSchemes[$context->getScheme()])) { + $allowSchemes += $requiredSchemes; + continue; + } + + if ($requiredMethods && !isset($requiredMethods[$canonicalMethod]) && !isset($requiredMethods[$requestMethod])) { + $allow += $requiredMethods; + continue; + } + + return $ret; + } + + $regex = substr_replace($regex, 'F', $m - $offset, 1 + \strlen($m)); + $offset += \strlen($m); + } + } + + if ('/' === $pathinfo && !$allow && !$allowSchemes) { + throw new NoConfigurationException(); + } + + return []; + } +} diff --git a/vendor/symfony/routing/Matcher/Dumper/DumperCollection.php b/vendor/symfony/routing/Matcher/Dumper/DumperCollection.php deleted file mode 100644 index 6916297b8c1747bc4c33c0cb14e7f3c76c575f68..0000000000000000000000000000000000000000 --- a/vendor/symfony/routing/Matcher/Dumper/DumperCollection.php +++ /dev/null @@ -1,159 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Matcher\Dumper; - -/** - * Collection of routes. - * - * @author Arnaud Le Blanc <arnaud.lb@gmail.com> - * - * @internal - */ -class DumperCollection implements \IteratorAggregate -{ - /** - * @var DumperCollection|null - */ - private $parent; - - /** - * @var DumperCollection[]|DumperRoute[] - */ - private $children = array(); - - /** - * @var array - */ - private $attributes = array(); - - /** - * Returns the children routes and collections. - * - * @return self[]|DumperRoute[] - */ - public function all() - { - return $this->children; - } - - /** - * Adds a route or collection. - * - * @param DumperRoute|DumperCollection The route or collection - */ - public function add($child) - { - if ($child instanceof self) { - $child->setParent($this); - } - $this->children[] = $child; - } - - /** - * Sets children. - * - * @param array $children The children - */ - public function setAll(array $children) - { - foreach ($children as $child) { - if ($child instanceof self) { - $child->setParent($this); - } - } - $this->children = $children; - } - - /** - * Returns an iterator over the children. - * - * @return \Iterator|DumperCollection[]|DumperRoute[] The iterator - */ - public function getIterator() - { - return new \ArrayIterator($this->children); - } - - /** - * Returns the root of the collection. - * - * @return self The root collection - */ - public function getRoot() - { - return (null !== $this->parent) ? $this->parent->getRoot() : $this; - } - - /** - * Returns the parent collection. - * - * @return self|null The parent collection or null if the collection has no parent - */ - protected function getParent() - { - return $this->parent; - } - - /** - * Sets the parent collection. - */ - protected function setParent(DumperCollection $parent) - { - $this->parent = $parent; - } - - /** - * Returns true if the attribute is defined. - * - * @param string $name The attribute name - * - * @return bool true if the attribute is defined, false otherwise - */ - public function hasAttribute($name) - { - return array_key_exists($name, $this->attributes); - } - - /** - * Returns an attribute by name. - * - * @param string $name The attribute name - * @param mixed $default Default value is the attribute doesn't exist - * - * @return mixed The attribute value - */ - public function getAttribute($name, $default = null) - { - return $this->hasAttribute($name) ? $this->attributes[$name] : $default; - } - - /** - * Sets an attribute by name. - * - * @param string $name The attribute name - * @param mixed $value The attribute value - */ - public function setAttribute($name, $value) - { - $this->attributes[$name] = $value; - } - - /** - * Sets multiple attributes. - * - * @param array $attributes The attributes - */ - public function setAttributes($attributes) - { - $this->attributes = $attributes; - } -} diff --git a/vendor/symfony/routing/Matcher/Dumper/DumperRoute.php b/vendor/symfony/routing/Matcher/Dumper/DumperRoute.php deleted file mode 100644 index c71989a3a1532cb9b4e8b711464970e7bb5bfd8f..0000000000000000000000000000000000000000 --- a/vendor/symfony/routing/Matcher/Dumper/DumperRoute.php +++ /dev/null @@ -1,57 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Matcher\Dumper; - -use Symfony\Component\Routing\Route; - -/** - * Container for a Route. - * - * @author Arnaud Le Blanc <arnaud.lb@gmail.com> - * - * @internal - */ -class DumperRoute -{ - private $name; - private $route; - - /** - * @param string $name The route name - * @param Route $route The route - */ - public function __construct($name, Route $route) - { - $this->name = $name; - $this->route = $route; - } - - /** - * Returns the route name. - * - * @return string The route name - */ - public function getName() - { - return $this->name; - } - - /** - * Returns the route. - * - * @return Route The route - */ - public function getRoute() - { - return $this->route; - } -} diff --git a/vendor/symfony/routing/Matcher/Dumper/MatcherDumperInterface.php b/vendor/symfony/routing/Matcher/Dumper/MatcherDumperInterface.php index 5e7c134b9f394752d3c6d4dd4b1911f2c47db36b..2a25293aa3e5cc52b580202cabd2653c7e8e6962 100644 --- a/vendor/symfony/routing/Matcher/Dumper/MatcherDumperInterface.php +++ b/vendor/symfony/routing/Matcher/Dumper/MatcherDumperInterface.php @@ -28,7 +28,7 @@ interface MatcherDumperInterface * * @return string Executable code */ - public function dump(array $options = array()); + public function dump(array $options = []); /** * Gets the routes to dump. diff --git a/vendor/symfony/routing/Matcher/Dumper/PhpMatcherDumper.php b/vendor/symfony/routing/Matcher/Dumper/PhpMatcherDumper.php index acb9eddb34de852580bd95462cec71ff70f9d3e4..ee505e1641446ce3ff08951c61c66c8983646847 100644 --- a/vendor/symfony/routing/Matcher/Dumper/PhpMatcherDumper.php +++ b/vendor/symfony/routing/Matcher/Dumper/PhpMatcherDumper.php @@ -11,10 +11,7 @@ namespace Symfony\Component\Routing\Matcher\Dumper; -use Symfony\Component\Routing\Route; -use Symfony\Component\Routing\RouteCollection; -use Symfony\Component\ExpressionLanguage\ExpressionLanguage; -use Symfony\Component\ExpressionLanguage\ExpressionFunctionProviderInterface; +@trigger_error(sprintf('The "%s" class is deprecated since Symfony 4.3, use "CompiledUrlMatcherDumper" instead.', PhpMatcherDumper::class), E_USER_DEPRECATED); /** * PhpMatcherDumper creates a PHP class able to match URLs for a given set of routes. @@ -22,16 +19,12 @@ use Symfony\Component\ExpressionLanguage\ExpressionFunctionProviderInterface; * @author Fabien Potencier <fabien@symfony.com> * @author Tobias Schultze <http://tobion.de> * @author Arnaud Le Blanc <arnaud.lb@gmail.com> + * @author Nicolas Grekas <p@tchwork.com> + * + * @deprecated since Symfony 4.3, use CompiledUrlMatcherDumper instead. */ -class PhpMatcherDumper extends MatcherDumper +class PhpMatcherDumper extends CompiledUrlMatcherDumper { - private $expressionLanguage; - - /** - * @var ExpressionFunctionProviderInterface[] - */ - private $expressionLanguageProviders = array(); - /** * Dumps a set of routes to a PHP class. * @@ -44,22 +37,24 @@ class PhpMatcherDumper extends MatcherDumper * * @return string A PHP class representing the matcher class */ - public function dump(array $options = array()) + public function dump(array $options = []) { - $options = array_replace(array( + $options = array_replace([ 'class' => 'ProjectUrlMatcher', 'base_class' => 'Symfony\\Component\\Routing\\Matcher\\UrlMatcher', - ), $options); + ], $options); - // trailing slash support is only enabled if we know how to redirect the user - $interfaces = class_implements($options['base_class']); - $supportsRedirections = isset($interfaces['Symfony\\Component\\Routing\\Matcher\\RedirectableUrlMatcherInterface']); + $code = parent::dump(); + $code = preg_replace('#\n ([^ ].*?) // \$(\w++)$#m', "\n \$this->$2 = $1", $code); + $code = str_replace(",\n $", ";\n $", $code); + $code = substr($code, strpos($code, '$this') - 4, -5).";\n"; + $code = preg_replace('/^ \$this->\w++ = (?:null|false|\[\n \]);\n/m', '', $code); + $code = str_replace("\n ", "\n ", "\n".$code); return <<<EOF <?php -use Symfony\Component\Routing\Exception\MethodNotAllowedException; -use Symfony\Component\Routing\Exception\ResourceNotFoundException; +use Symfony\Component\Routing\Matcher\Dumper\CompiledUrlMatcherTrait; use Symfony\Component\Routing\RequestContext; /** @@ -68,374 +63,13 @@ use Symfony\Component\Routing\RequestContext; */ class {$options['class']} extends {$options['base_class']} { + use CompiledUrlMatcherTrait; + public function __construct(RequestContext \$context) { - \$this->context = \$context; - } - -{$this->generateMatchMethod($supportsRedirections)} + \$this->context = \$context;{$code} } } EOF; } - - public function addExpressionLanguageProvider(ExpressionFunctionProviderInterface $provider) - { - $this->expressionLanguageProviders[] = $provider; - } - - /** - * Generates the code for the match method implementing UrlMatcherInterface. - * - * @param bool $supportsRedirections Whether redirections are supported by the base class - * - * @return string Match method as PHP code - */ - private function generateMatchMethod($supportsRedirections) - { - $code = rtrim($this->compileRoutes($this->getRoutes(), $supportsRedirections), "\n"); - - return <<<EOF - public function match(\$rawPathinfo) - { - \$allow = array(); - \$pathinfo = rawurldecode(\$rawPathinfo); - \$trimmedPathinfo = rtrim(\$pathinfo, '/'); - \$context = \$this->context; - \$request = \$this->request; - \$requestMethod = \$canonicalMethod = \$context->getMethod(); - \$scheme = \$context->getScheme(); - - if ('HEAD' === \$requestMethod) { - \$canonicalMethod = 'GET'; - } - - -$code - - throw 0 < count(\$allow) ? new MethodNotAllowedException(array_unique(\$allow)) : new ResourceNotFoundException(); - } -EOF; - } - - /** - * Generates PHP code to match a RouteCollection with all its routes. - * - * @param RouteCollection $routes A RouteCollection instance - * @param bool $supportsRedirections Whether redirections are supported by the base class - * - * @return string PHP code - */ - private function compileRoutes(RouteCollection $routes, $supportsRedirections) - { - $fetchedHost = false; - $groups = $this->groupRoutesByHostRegex($routes); - $code = ''; - - foreach ($groups as $collection) { - if (null !== $regex = $collection->getAttribute('host_regex')) { - if (!$fetchedHost) { - $code .= " \$host = \$context->getHost();\n\n"; - $fetchedHost = true; - } - - $code .= sprintf(" if (preg_match(%s, \$host, \$hostMatches)) {\n", var_export($regex, true)); - } - - $tree = $this->buildStaticPrefixCollection($collection); - $groupCode = $this->compileStaticPrefixRoutes($tree, $supportsRedirections); - - if (null !== $regex) { - // apply extra indention at each line (except empty ones) - $groupCode = preg_replace('/^.{2,}$/m', ' $0', $groupCode); - $code .= $groupCode; - $code .= " }\n\n"; - } else { - $code .= $groupCode; - } - } - - if ('' === $code) { - $code .= " if ('/' === \$pathinfo) {\n"; - $code .= " throw new Symfony\Component\Routing\Exception\NoConfigurationException();\n"; - $code .= " }\n"; - } - - return $code; - } - - private function buildStaticPrefixCollection(DumperCollection $collection) - { - $prefixCollection = new StaticPrefixCollection(); - - foreach ($collection as $dumperRoute) { - $prefix = $dumperRoute->getRoute()->compile()->getStaticPrefix(); - $prefixCollection->addRoute($prefix, $dumperRoute); - } - - $prefixCollection->optimizeGroups(); - - return $prefixCollection; - } - - /** - * Generates PHP code to match a tree of routes. - * - * @param StaticPrefixCollection $collection A StaticPrefixCollection instance - * @param bool $supportsRedirections Whether redirections are supported by the base class - * @param string $ifOrElseIf either "if" or "elseif" to influence chaining - * - * @return string PHP code - */ - private function compileStaticPrefixRoutes(StaticPrefixCollection $collection, $supportsRedirections, $ifOrElseIf = 'if') - { - $code = ''; - $prefix = $collection->getPrefix(); - - if (!empty($prefix) && '/' !== $prefix) { - $code .= sprintf(" %s (0 === strpos(\$pathinfo, %s)) {\n", $ifOrElseIf, var_export($prefix, true)); - } - - $ifOrElseIf = 'if'; - - foreach ($collection->getItems() as $route) { - if ($route instanceof StaticPrefixCollection) { - $code .= $this->compileStaticPrefixRoutes($route, $supportsRedirections, $ifOrElseIf); - $ifOrElseIf = 'elseif'; - } else { - $code .= $this->compileRoute($route[1]->getRoute(), $route[1]->getName(), $supportsRedirections, $prefix)."\n"; - $ifOrElseIf = 'if'; - } - } - - if (!empty($prefix) && '/' !== $prefix) { - $code .= " }\n\n"; - // apply extra indention at each line (except empty ones) - $code = preg_replace('/^.{2,}$/m', ' $0', $code); - } - - return $code; - } - - /** - * Compiles a single Route to PHP code used to match it against the path info. - * - * @param Route $route A Route instance - * @param string $name The name of the Route - * @param bool $supportsRedirections Whether redirections are supported by the base class - * @param string|null $parentPrefix The prefix of the parent collection used to optimize the code - * - * @return string PHP code - * - * @throws \LogicException - */ - private function compileRoute(Route $route, $name, $supportsRedirections, $parentPrefix = null) - { - $code = ''; - $compiledRoute = $route->compile(); - $conditions = array(); - $hasTrailingSlash = false; - $matches = false; - $hostMatches = false; - $methods = $route->getMethods(); - - $supportsTrailingSlash = $supportsRedirections && (!$methods || in_array('HEAD', $methods) || in_array('GET', $methods)); - $regex = $compiledRoute->getRegex(); - - if (!count($compiledRoute->getPathVariables()) && false !== preg_match('#^(.)\^(?P<url>.*?)\$\1#'.('u' === substr($regex, -1) ? 'u' : ''), $regex, $m)) { - if ($supportsTrailingSlash && '/' === substr($m['url'], -1)) { - $conditions[] = sprintf('%s === $trimmedPathinfo', var_export(rtrim(str_replace('\\', '', $m['url']), '/'), true)); - $hasTrailingSlash = true; - } else { - $conditions[] = sprintf('%s === $pathinfo', var_export(str_replace('\\', '', $m['url']), true)); - } - } else { - if ($compiledRoute->getStaticPrefix() && $compiledRoute->getStaticPrefix() !== $parentPrefix) { - $conditions[] = sprintf('0 === strpos($pathinfo, %s)', var_export($compiledRoute->getStaticPrefix(), true)); - } - - if ($supportsTrailingSlash && $pos = strpos($regex, '/$')) { - $regex = substr($regex, 0, $pos).'/?$'.substr($regex, $pos + 2); - $hasTrailingSlash = true; - } - $conditions[] = sprintf('preg_match(%s, $pathinfo, $matches)', var_export($regex, true)); - - $matches = true; - } - - if ($compiledRoute->getHostVariables()) { - $hostMatches = true; - } - - if ($route->getCondition()) { - $conditions[] = $this->getExpressionLanguage()->compile($route->getCondition(), array('context', 'request')); - } - - $conditions = implode(' && ', $conditions); - - $code .= <<<EOF - // $name - if ($conditions) { - -EOF; - - $gotoname = 'not_'.preg_replace('/[^A-Za-z0-9_]/', '', $name); - - if ($methods) { - if (1 === count($methods)) { - if ('HEAD' === $methods[0]) { - $code .= <<<EOF - if ('HEAD' !== \$requestMethod) { - \$allow[] = 'HEAD'; - goto $gotoname; - } - - -EOF; - } else { - $code .= <<<EOF - if ('$methods[0]' !== \$canonicalMethod) { - \$allow[] = '$methods[0]'; - goto $gotoname; - } - - -EOF; - } - } else { - $methodVariable = 'requestMethod'; - - if (in_array('GET', $methods)) { - // Since we treat HEAD requests like GET requests we don't need to match it. - $methodVariable = 'canonicalMethod'; - $methods = array_values(array_filter($methods, function ($method) { return 'HEAD' !== $method; })); - } - - if (1 === count($methods)) { - $code .= <<<EOF - if ('$methods[0]' !== \$$methodVariable) { - \$allow[] = '$methods[0]'; - goto $gotoname; - } - - -EOF; - } else { - $methods = implode("', '", $methods); - $code .= <<<EOF - if (!in_array(\$$methodVariable, array('$methods'))) { - \$allow = array_merge(\$allow, array('$methods')); - goto $gotoname; - } - - -EOF; - } - } - } - - // the offset where the return value is appended below, with indendation - $retOffset = 12 + strlen($code); - - // optimize parameters array - if ($matches || $hostMatches) { - $vars = array(); - if ($hostMatches) { - $vars[] = '$hostMatches'; - } - if ($matches) { - $vars[] = '$matches'; - } - $vars[] = "array('_route' => '$name')"; - - $code .= sprintf( - " \$ret = \$this->mergeDefaults(array_replace(%s), %s);\n", - implode(', ', $vars), - str_replace("\n", '', var_export($route->getDefaults(), true)) - ); - } elseif ($route->getDefaults()) { - $code .= sprintf(" \$ret = %s;\n", str_replace("\n", '', var_export(array_replace($route->getDefaults(), array('_route' => $name)), true))); - } else { - $code .= sprintf(" \$ret = array('_route' => '%s');\n", $name); - } - - if ($hasTrailingSlash) { - $code .= <<<EOF - if (substr(\$pathinfo, -1) !== '/') { - return array_replace(\$ret, \$this->redirect(\$rawPathinfo.'/', '$name')); - } - - -EOF; - } - - if ($schemes = $route->getSchemes()) { - if (!$supportsRedirections) { - throw new \LogicException('The "schemes" requirement is only supported for URL matchers that implement RedirectableUrlMatcherInterface.'); - } - $schemes = str_replace("\n", '', var_export(array_flip($schemes), true)); - $code .= <<<EOF - \$requiredSchemes = $schemes; - if (!isset(\$requiredSchemes[\$scheme])) { - return array_replace(\$ret, \$this->redirect(\$rawPathinfo, '$name', key(\$requiredSchemes))); - } - - -EOF; - } - - if ($hasTrailingSlash || $schemes) { - $code .= " return \$ret;\n"; - } else { - $code = substr_replace($code, 'return', $retOffset, 6); - } - $code .= " }\n"; - - if ($methods) { - $code .= " $gotoname:\n"; - } - - return $code; - } - - /** - * Groups consecutive routes having the same host regex. - * - * The result is a collection of collections of routes having the same host regex. - * - * @param RouteCollection $routes A flat RouteCollection - * - * @return DumperCollection A collection with routes grouped by host regex in sub-collections - */ - private function groupRoutesByHostRegex(RouteCollection $routes) - { - $groups = new DumperCollection(); - $currentGroup = new DumperCollection(); - $currentGroup->setAttribute('host_regex', null); - $groups->add($currentGroup); - - foreach ($routes as $name => $route) { - $hostRegex = $route->compile()->getHostRegex(); - if ($currentGroup->getAttribute('host_regex') !== $hostRegex) { - $currentGroup = new DumperCollection(); - $currentGroup->setAttribute('host_regex', $hostRegex); - $groups->add($currentGroup); - } - $currentGroup->add(new DumperRoute($name, $route)); - } - - return $groups; - } - - private function getExpressionLanguage() - { - if (null === $this->expressionLanguage) { - if (!class_exists('Symfony\Component\ExpressionLanguage\ExpressionLanguage')) { - throw new \RuntimeException('Unable to use expressions as the Symfony ExpressionLanguage component is not installed.'); - } - $this->expressionLanguage = new ExpressionLanguage(null, $this->expressionLanguageProviders); - } - - return $this->expressionLanguage; - } } diff --git a/vendor/symfony/routing/Matcher/Dumper/StaticPrefixCollection.php b/vendor/symfony/routing/Matcher/Dumper/StaticPrefixCollection.php index 73658086189a07fe2fcc8b2a593e6ed27ecdd210..65b6c0718b3161a8da7b637e4d12725452d0f3e8 100644 --- a/vendor/symfony/routing/Matcher/Dumper/StaticPrefixCollection.php +++ b/vendor/symfony/routing/Matcher/Dumper/StaticPrefixCollection.php @@ -11,44 +11,49 @@ namespace Symfony\Component\Routing\Matcher\Dumper; +use Symfony\Component\Routing\RouteCollection; + /** * Prefix tree of routes preserving routes order. * * @author Frank de Jonge <info@frankdejonge.nl> + * @author Nicolas Grekas <p@tchwork.com> * * @internal */ class StaticPrefixCollection { + private $prefix; + /** - * @var string + * @var string[] */ - private $prefix; + private $staticPrefixes = []; /** - * @var array[]|StaticPrefixCollection[] + * @var string[] */ - private $items = array(); + private $prefixes = []; /** - * @var int + * @var array[]|self[] */ - private $matchStart = 0; + private $items = []; - public function __construct($prefix = '') + public function __construct(string $prefix = '/') { $this->prefix = $prefix; } - public function getPrefix() + public function getPrefix(): string { return $this->prefix; } /** - * @return mixed[]|StaticPrefixCollection[] + * @return array[]|self[] */ - public function getItems() + public function getRoutes(): array { return $this->items; } @@ -56,183 +61,142 @@ class StaticPrefixCollection /** * Adds a route to a group. * - * @param string $prefix - * @param mixed $route + * @param array|self $route */ - public function addRoute($prefix, $route) + public function addRoute(string $prefix, $route) { - $prefix = '/' === $prefix ? $prefix : rtrim($prefix, '/'); - $this->guardAgainstAddingNotAcceptedRoutes($prefix); + list($prefix, $staticPrefix) = $this->getCommonPrefix($prefix, $prefix); - if ($this->prefix === $prefix) { - // When a prefix is exactly the same as the base we move up the match start position. - // This is needed because otherwise routes that come afterwards have higher precedence - // than a possible regular expression, which goes against the input order sorting. - $this->items[] = array($prefix, $route); - $this->matchStart = count($this->items); + for ($i = \count($this->items) - 1; 0 <= $i; --$i) { + $item = $this->items[$i]; - return; - } + list($commonPrefix, $commonStaticPrefix) = $this->getCommonPrefix($prefix, $this->prefixes[$i]); - foreach ($this->items as $i => $item) { - if ($i < $this->matchStart) { - continue; - } + if ($this->prefix === $commonPrefix) { + // the new route and a previous one have no common prefix, let's see if they are exclusive to each others - if ($item instanceof self && $item->accepts($prefix)) { - $item->addRoute($prefix, $route); + if ($this->prefix !== $staticPrefix && $this->prefix !== $this->staticPrefixes[$i]) { + // the new route and the previous one have exclusive static prefixes + continue; + } - return; - } + if ($this->prefix === $staticPrefix && $this->prefix === $this->staticPrefixes[$i]) { + // the new route and the previous one have no static prefix + break; + } - $group = $this->groupWithItem($item, $prefix, $route); + if ($this->prefixes[$i] !== $this->staticPrefixes[$i] && $this->prefix === $this->staticPrefixes[$i]) { + // the previous route is non-static and has no static prefix + break; + } - if ($group instanceof self) { - $this->items[$i] = $group; + if ($prefix !== $staticPrefix && $this->prefix === $staticPrefix) { + // the new route is non-static and has no static prefix + break; + } - return; + continue; } - } - - // No optimised case was found, in this case we simple add the route for possible - // grouping when new routes are added. - $this->items[] = array($prefix, $route); - } - /** - * Tries to combine a route with another route or group. - * - * @param StaticPrefixCollection|array $item - * @param string $prefix - * @param mixed $route - * - * @return null|StaticPrefixCollection - */ - private function groupWithItem($item, $prefix, $route) - { - $itemPrefix = $item instanceof self ? $item->prefix : $item[0]; - $commonPrefix = $this->detectCommonPrefix($prefix, $itemPrefix); + if ($item instanceof self && $this->prefixes[$i] === $commonPrefix) { + // the new route is a child of a previous one, let's nest it + $item->addRoute($prefix, $route); + } else { + // the new route and a previous one have a common prefix, let's merge them + $child = new self($commonPrefix); + list($child->prefixes[0], $child->staticPrefixes[0]) = $child->getCommonPrefix($this->prefixes[$i], $this->prefixes[$i]); + list($child->prefixes[1], $child->staticPrefixes[1]) = $child->getCommonPrefix($prefix, $prefix); + $child->items = [$this->items[$i], $route]; + + $this->staticPrefixes[$i] = $commonStaticPrefix; + $this->prefixes[$i] = $commonPrefix; + $this->items[$i] = $child; + } - if (!$commonPrefix) { return; } - $child = new self($commonPrefix); - - if ($item instanceof self) { - $child->items = array($item); - } else { - $child->addRoute($item[0], $item[1]); - } - - $child->addRoute($prefix, $route); - - return $child; - } - - /** - * Checks whether a prefix can be contained within the group. - * - * @param string $prefix - * - * @return bool Whether a prefix could belong in a given group - */ - private function accepts($prefix) - { - return '' === $this->prefix || 0 === strpos($prefix, $this->prefix); + // No optimised case was found, in this case we simple add the route for possible + // grouping when new routes are added. + $this->staticPrefixes[] = $staticPrefix; + $this->prefixes[] = $prefix; + $this->items[] = $route; } /** - * Detects whether there's a common prefix relative to the group prefix and returns it. - * - * @param string $prefix - * @param string $anotherPrefix - * - * @return false|string A common prefix, longer than the base/group prefix, or false when none available + * Linearizes back a set of nested routes into a collection. */ - private function detectCommonPrefix($prefix, $anotherPrefix) + public function populateCollection(RouteCollection $routes): RouteCollection { - $baseLength = strlen($this->prefix); - $commonLength = $baseLength; - $end = min(strlen($prefix), strlen($anotherPrefix)); - - for ($i = $baseLength; $i <= $end; ++$i) { - if (substr($prefix, 0, $i) !== substr($anotherPrefix, 0, $i)) { - break; + foreach ($this->items as $route) { + if ($route instanceof self) { + $route->populateCollection($routes); + } else { + $routes->add(...$route); } - - $commonLength = $i; } - $commonPrefix = rtrim(substr($prefix, 0, $commonLength), '/'); - - if (strlen($commonPrefix) > $baseLength) { - return $commonPrefix; - } - - return false; + return $routes; } /** - * Optimizes the tree by inlining items from groups with less than 3 items. + * Gets the full and static common prefixes between two route patterns. + * + * The static prefix stops at last at the first opening bracket. */ - public function optimizeGroups() + private function getCommonPrefix(string $prefix, string $anotherPrefix): array { - $index = -1; - - while (isset($this->items[++$index])) { - $item = $this->items[$index]; - - if ($item instanceof self) { - $item->optimizeGroups(); - - // When a group contains only two items there's no reason to optimize because at minimum - // the amount of prefix check is 2. In this case inline the group. - if ($item->shouldBeInlined()) { - array_splice($this->items, $index, 1, $item->items); - - // Lower index to pass through the same index again after optimizing. - // The first item of the replacements might be a group needing optimization. - --$index; + $baseLength = \strlen($this->prefix); + $end = min(\strlen($prefix), \strlen($anotherPrefix)); + $staticLength = null; + set_error_handler([__CLASS__, 'handleError']); + + for ($i = $baseLength; $i < $end && $prefix[$i] === $anotherPrefix[$i]; ++$i) { + if ('(' === $prefix[$i]) { + $staticLength = $staticLength ?? $i; + for ($j = 1 + $i, $n = 1; $j < $end && 0 < $n; ++$j) { + if ($prefix[$j] !== $anotherPrefix[$j]) { + break 2; + } + if ('(' === $prefix[$j]) { + ++$n; + } elseif (')' === $prefix[$j]) { + --$n; + } elseif ('\\' === $prefix[$j] && (++$j === $end || $prefix[$j] !== $anotherPrefix[$j])) { + --$j; + break; + } } + if (0 < $n) { + break; + } + if (('?' === ($prefix[$j] ?? '') || '?' === ($anotherPrefix[$j] ?? '')) && ($prefix[$j] ?? '') !== ($anotherPrefix[$j] ?? '')) { + break; + } + $subPattern = substr($prefix, $i, $j - $i); + if ($prefix !== $anotherPrefix && !preg_match('/^\(\[[^\]]++\]\+\+\)$/', $subPattern) && !preg_match('{(?<!'.$subPattern.')}', '')) { + // sub-patterns of variable length are not considered as common prefixes because their greediness would break in-order matching + break; + } + $i = $j - 1; + } elseif ('\\' === $prefix[$i] && (++$i === $end || $prefix[$i] !== $anotherPrefix[$i])) { + --$i; + break; } } - } - - private function shouldBeInlined() - { - if (count($this->items) >= 3) { - return false; - } - - foreach ($this->items as $item) { - if ($item instanceof self) { - return true; - } - } - - foreach ($this->items as $item) { - if (is_array($item) && $item[0] === $this->prefix) { - return false; - } + restore_error_handler(); + if ($i < $end && 0b10 === (\ord($prefix[$i]) >> 6) && preg_match('//u', $prefix.' '.$anotherPrefix)) { + do { + // Prevent cutting in the middle of an UTF-8 characters + --$i; + } while (0b10 === (\ord($prefix[$i]) >> 6)); } - return true; + return [substr($prefix, 0, $i), substr($prefix, 0, $staticLength ?? $i)]; } - /** - * Guards against adding incompatible prefixes in a group. - * - * @param string $prefix - * - * @throws \LogicException when a prefix does not belong in a group - */ - private function guardAgainstAddingNotAcceptedRoutes($prefix) + public static function handleError($type, $msg) { - if (!$this->accepts($prefix)) { - $message = sprintf('Could not add route with prefix %s to collection with prefix %s', $prefix, $this->prefix); - - throw new \LogicException($message); - } + return false !== strpos($msg, 'Compilation failed: lookbehind assertion is not fixed length'); } } diff --git a/vendor/symfony/routing/Matcher/RedirectableUrlMatcher.php b/vendor/symfony/routing/Matcher/RedirectableUrlMatcher.php index 3770a9c24c5e5fe2ec48da714067d72f0097f722..eb7bec7f344221bc6cd525f92b02ffb088ae746f 100644 --- a/vendor/symfony/routing/Matcher/RedirectableUrlMatcher.php +++ b/vendor/symfony/routing/Matcher/RedirectableUrlMatcher.php @@ -11,8 +11,8 @@ namespace Symfony\Component\Routing\Matcher; +use Symfony\Component\Routing\Exception\ExceptionInterface; use Symfony\Component\Routing\Exception\ResourceNotFoundException; -use Symfony\Component\Routing\Route; /** * @author Fabien Potencier <fabien@symfony.com> @@ -25,41 +25,40 @@ abstract class RedirectableUrlMatcher extends UrlMatcher implements Redirectable public function match($pathinfo) { try { - $parameters = parent::match($pathinfo); + return parent::match($pathinfo); } catch (ResourceNotFoundException $e) { - if ('/' === substr($pathinfo, -1) || !in_array($this->context->getMethod(), array('HEAD', 'GET'))) { + if (!\in_array($this->context->getMethod(), ['HEAD', 'GET'], true)) { throw $e; } - try { - $parameters = parent::match($pathinfo.'/'); + if ($this->allowSchemes) { + redirect_scheme: + $scheme = $this->context->getScheme(); + $this->context->setScheme(current($this->allowSchemes)); + try { + $ret = parent::match($pathinfo); - return array_replace($parameters, $this->redirect($pathinfo.'/', isset($parameters['_route']) ? $parameters['_route'] : null)); - } catch (ResourceNotFoundException $e2) { + return $this->redirect($pathinfo, $ret['_route'] ?? null, $this->context->getScheme()) + $ret; + } catch (ExceptionInterface $e2) { + throw $e; + } finally { + $this->context->setScheme($scheme); + } + } elseif ('/' === $trimmedPathinfo = rtrim($pathinfo, '/') ?: '/') { throw $e; - } - } - - return $parameters; - } - - /** - * {@inheritdoc} - */ - protected function handleRouteRequirements($pathinfo, $name, Route $route) - { - // expression condition - if ($route->getCondition() && !$this->getExpressionLanguage()->evaluate($route->getCondition(), array('context' => $this->context, 'request' => $this->request ?: $this->createRequest($pathinfo)))) { - return array(self::REQUIREMENT_MISMATCH, null); - } + } else { + try { + $pathinfo = $trimmedPathinfo === $pathinfo ? $pathinfo.'/' : $trimmedPathinfo; + $ret = parent::match($pathinfo); - // check HTTP scheme requirement - $scheme = $this->context->getScheme(); - $schemes = $route->getSchemes(); - if ($schemes && !$route->hasScheme($scheme)) { - return array(self::ROUTE_MATCH, $this->redirect($pathinfo, $name, current($schemes))); + return $this->redirect($pathinfo, $ret['_route'] ?? null) + $ret; + } catch (ExceptionInterface $e2) { + if ($this->allowSchemes) { + goto redirect_scheme; + } + throw $e; + } + } } - - return array(self::REQUIREMENT_MATCH, null); } } diff --git a/vendor/symfony/routing/Matcher/RequestMatcherInterface.php b/vendor/symfony/routing/Matcher/RequestMatcherInterface.php index 1eef778a56bc01ac322c6090cca30dca6a0f000d..0c193ff2d1f067bb6227460eaab8a9e9074b0207 100644 --- a/vendor/symfony/routing/Matcher/RequestMatcherInterface.php +++ b/vendor/symfony/routing/Matcher/RequestMatcherInterface.php @@ -12,9 +12,9 @@ namespace Symfony\Component\Routing\Matcher; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\Routing\Exception\MethodNotAllowedException; use Symfony\Component\Routing\Exception\NoConfigurationException; use Symfony\Component\Routing\Exception\ResourceNotFoundException; -use Symfony\Component\Routing\Exception\MethodNotAllowedException; /** * RequestMatcherInterface is the interface that all request matcher classes must implement. diff --git a/vendor/symfony/routing/Matcher/TraceableUrlMatcher.php b/vendor/symfony/routing/Matcher/TraceableUrlMatcher.php index 9085be04248861d88b81918e6b491ba83d743747..fb035d1e8777e4db8d24e0d9fa3c44214d76da46 100644 --- a/vendor/symfony/routing/Matcher/TraceableUrlMatcher.php +++ b/vendor/symfony/routing/Matcher/TraceableUrlMatcher.php @@ -31,7 +31,7 @@ class TraceableUrlMatcher extends UrlMatcher public function getTraces($pathinfo) { - $this->traces = array(); + $this->traces = []; try { $this->match($pathinfo); @@ -52,12 +52,32 @@ class TraceableUrlMatcher extends UrlMatcher protected function matchCollection($pathinfo, RouteCollection $routes) { + // HEAD and GET are equivalent as per RFC + if ('HEAD' === $method = $this->context->getMethod()) { + $method = 'GET'; + } + $supportsTrailingSlash = 'GET' === $method && $this instanceof RedirectableUrlMatcherInterface; + $trimmedPathinfo = rtrim($pathinfo, '/') ?: '/'; + foreach ($routes as $name => $route) { $compiledRoute = $route->compile(); + $staticPrefix = rtrim($compiledRoute->getStaticPrefix(), '/'); + $requiredMethods = $route->getMethods(); - if (!preg_match($compiledRoute->getRegex(), $pathinfo, $matches)) { + // check the static prefix of the URL first. Only use the more expensive preg_match when it matches + if ('' !== $staticPrefix && 0 !== strpos($trimmedPathinfo, $staticPrefix)) { + $this->addTrace(sprintf('Path "%s" does not match', $route->getPath()), self::ROUTE_DOES_NOT_MATCH, $name, $route); + continue; + } + $regex = $compiledRoute->getRegex(); + + $pos = strrpos($regex, '$'); + $hasTrailingSlash = '/' === $regex[$pos - 1]; + $regex = substr_replace($regex, '/?$', $pos - $hasTrailingSlash, 1 + $hasTrailingSlash); + + if (!preg_match($regex, $pathinfo, $matches)) { // does it match without any requirements? - $r = new Route($route->getPath(), $route->getDefaults(), array(), $route->getOptions()); + $r = new Route($route->getPath(), $route->getDefaults(), [], $route->getOptions()); $cr = $r->compile(); if (!preg_match($cr->getRegex(), $pathinfo)) { $this->addTrace(sprintf('Path "%s" does not match', $route->getPath()), self::ROUTE_DOES_NOT_MATCH, $name, $route); @@ -66,10 +86,10 @@ class TraceableUrlMatcher extends UrlMatcher } foreach ($route->getRequirements() as $n => $regex) { - $r = new Route($route->getPath(), $route->getDefaults(), array($n => $regex), $route->getOptions()); + $r = new Route($route->getPath(), $route->getDefaults(), [$n => $regex], $route->getOptions()); $cr = $r->compile(); - if (in_array($n, $cr->getVariables()) && !preg_match($cr->getRegex(), $pathinfo)) { + if (\in_array($n, $cr->getVariables()) && !preg_match($cr->getRegex(), $pathinfo)) { $this->addTrace(sprintf('Requirement for "%s" does not match (%s)', $n, $regex), self::ROUTE_ALMOST_MATCHES, $name, $route); continue 2; @@ -79,63 +99,66 @@ class TraceableUrlMatcher extends UrlMatcher continue; } - // check host requirement - $hostMatches = array(); + $hasTrailingVar = $trimmedPathinfo !== $pathinfo && preg_match('#\{\w+\}/?$#', $route->getPath()); + + if ($hasTrailingVar && ($hasTrailingSlash || (null === $m = $matches[\count($compiledRoute->getPathVariables())] ?? null) || '/' !== ($m[-1] ?? '/')) && preg_match($regex, $trimmedPathinfo, $m)) { + if ($hasTrailingSlash) { + $matches = $m; + } else { + $hasTrailingVar = false; + } + } + + $hostMatches = []; if ($compiledRoute->getHostRegex() && !preg_match($compiledRoute->getHostRegex(), $this->context->getHost(), $hostMatches)) { $this->addTrace(sprintf('Host "%s" does not match the requirement ("%s")', $this->context->getHost(), $route->getHost()), self::ROUTE_ALMOST_MATCHES, $name, $route); - continue; } - // check HTTP method requirement - if ($requiredMethods = $route->getMethods()) { - // HEAD and GET are equivalent as per RFC - if ('HEAD' === $method = $this->context->getMethod()) { - $method = 'GET'; - } - - if (!in_array($method, $requiredMethods)) { - $this->allow = array_merge($this->allow, $requiredMethods); + $status = $this->handleRouteRequirements($pathinfo, $name, $route); - $this->addTrace(sprintf('Method "%s" does not match any of the required methods (%s)', $this->context->getMethod(), implode(', ', $requiredMethods)), self::ROUTE_ALMOST_MATCHES, $name, $route); - - continue; - } + if (self::REQUIREMENT_MISMATCH === $status[0]) { + $this->addTrace(sprintf('Condition "%s" does not evaluate to "true"', $route->getCondition()), self::ROUTE_ALMOST_MATCHES, $name, $route); + continue; } - // check condition - if ($condition = $route->getCondition()) { - if (!$this->getExpressionLanguage()->evaluate($condition, array('context' => $this->context, 'request' => $this->request ?: $this->createRequest($pathinfo)))) { - $this->addTrace(sprintf('Condition "%s" does not evaluate to "true"', $condition), self::ROUTE_ALMOST_MATCHES, $name, $route); + if ('/' !== $pathinfo && !$hasTrailingVar && $hasTrailingSlash === ($trimmedPathinfo === $pathinfo)) { + if ($supportsTrailingSlash && (!$requiredMethods || \in_array('GET', $requiredMethods))) { + $this->addTrace('Route matches!', self::ROUTE_MATCHES, $name, $route); - continue; + return $this->allow = $this->allowSchemes = []; } + $this->addTrace(sprintf('Path "%s" does not match', $route->getPath()), self::ROUTE_DOES_NOT_MATCH, $name, $route); + continue; } - // check HTTP scheme requirement - if ($requiredSchemes = $route->getSchemes()) { - $scheme = $this->context->getScheme(); - - if (!$route->hasScheme($scheme)) { - $this->addTrace(sprintf('Scheme "%s" does not match any of the required schemes (%s); the user will be redirected to first required scheme', $scheme, implode(', ', $requiredSchemes)), self::ROUTE_ALMOST_MATCHES, $name, $route); + if ($route->getSchemes() && !$route->hasScheme($this->context->getScheme())) { + $this->allowSchemes = array_merge($this->allowSchemes, $route->getSchemes()); + $this->addTrace(sprintf('Scheme "%s" does not match any of the required schemes (%s)', $this->context->getScheme(), implode(', ', $route->getSchemes())), self::ROUTE_ALMOST_MATCHES, $name, $route); + continue; + } - return true; - } + if ($requiredMethods && !\in_array($method, $requiredMethods)) { + $this->allow = array_merge($this->allow, $requiredMethods); + $this->addTrace(sprintf('Method "%s" does not match any of the required methods (%s)', $this->context->getMethod(), implode(', ', $requiredMethods)), self::ROUTE_ALMOST_MATCHES, $name, $route); + continue; } $this->addTrace('Route matches!', self::ROUTE_MATCHES, $name, $route); - return true; + return $this->getAttributes($route, $name, array_replace($matches, $hostMatches, isset($status[1]) ? $status[1] : [])); } + + return []; } private function addTrace($log, $level = self::ROUTE_DOES_NOT_MATCH, $name = null, $route = null) { - $this->traces[] = array( + $this->traces[] = [ 'log' => $log, 'name' => $name, 'level' => $level, 'path' => null !== $route ? $route->getPath() : null, - ); + ]; } } diff --git a/vendor/symfony/routing/Matcher/UrlMatcher.php b/vendor/symfony/routing/Matcher/UrlMatcher.php index 3cba7e66f86061a3a6460a85da03866e055bc897..dca1d6366fa025ae46eaac8ed0cf970d416c592a 100644 --- a/vendor/symfony/routing/Matcher/UrlMatcher.php +++ b/vendor/symfony/routing/Matcher/UrlMatcher.php @@ -11,15 +11,15 @@ namespace Symfony\Component\Routing\Matcher; +use Symfony\Component\ExpressionLanguage\ExpressionFunctionProviderInterface; +use Symfony\Component\ExpressionLanguage\ExpressionLanguage; +use Symfony\Component\HttpFoundation\Request; use Symfony\Component\Routing\Exception\MethodNotAllowedException; use Symfony\Component\Routing\Exception\NoConfigurationException; use Symfony\Component\Routing\Exception\ResourceNotFoundException; -use Symfony\Component\Routing\RouteCollection; use Symfony\Component\Routing\RequestContext; use Symfony\Component\Routing\Route; -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\ExpressionLanguage\ExpressionLanguage; -use Symfony\Component\ExpressionLanguage\ExpressionFunctionProviderInterface; +use Symfony\Component\Routing\RouteCollection; /** * UrlMatcher matches URL based on a set of routes. @@ -32,8 +32,21 @@ class UrlMatcher implements UrlMatcherInterface, RequestMatcherInterface const REQUIREMENT_MISMATCH = 1; const ROUTE_MATCH = 2; + /** @var RequestContext */ protected $context; - protected $allow = array(); + + /** + * Collects HTTP methods that would be allowed for the request. + */ + protected $allow = []; + + /** + * Collects URI schemes that would be allowed for the request. + * + * @internal + */ + protected $allowSchemes = []; + protected $routes; protected $request; protected $expressionLanguage; @@ -41,7 +54,7 @@ class UrlMatcher implements UrlMatcherInterface, RequestMatcherInterface /** * @var ExpressionFunctionProviderInterface[] */ - protected $expressionLanguageProviders = array(); + protected $expressionLanguageProviders = []; public function __construct(RouteCollection $routes, RequestContext $context) { @@ -70,17 +83,17 @@ class UrlMatcher implements UrlMatcherInterface, RequestMatcherInterface */ public function match($pathinfo) { - $this->allow = array(); + $this->allow = $this->allowSchemes = []; - if ($ret = $this->matchCollection(rawurldecode($pathinfo), $this->routes)) { + if ($ret = $this->matchCollection(rawurldecode($pathinfo) ?: '/', $this->routes)) { return $ret; } - if (0 === count($this->routes) && '/' === $pathinfo) { + if ('/' === $pathinfo && !$this->allow && !$this->allowSchemes) { throw new NoConfigurationException(); } - throw 0 < count($this->allow) + throw 0 < \count($this->allow) ? new MethodNotAllowedException(array_unique($this->allow)) : new ResourceNotFoundException(sprintf('No routes found for "%s".', $pathinfo)); } @@ -118,45 +131,74 @@ class UrlMatcher implements UrlMatcherInterface, RequestMatcherInterface */ protected function matchCollection($pathinfo, RouteCollection $routes) { + // HEAD and GET are equivalent as per RFC + if ('HEAD' === $method = $this->context->getMethod()) { + $method = 'GET'; + } + $supportsTrailingSlash = 'GET' === $method && $this instanceof RedirectableUrlMatcherInterface; + $trimmedPathinfo = rtrim($pathinfo, '/') ?: '/'; + foreach ($routes as $name => $route) { $compiledRoute = $route->compile(); + $staticPrefix = rtrim($compiledRoute->getStaticPrefix(), '/'); + $requiredMethods = $route->getMethods(); // check the static prefix of the URL first. Only use the more expensive preg_match when it matches - if ('' !== $compiledRoute->getStaticPrefix() && 0 !== strpos($pathinfo, $compiledRoute->getStaticPrefix())) { + if ('' !== $staticPrefix && 0 !== strpos($trimmedPathinfo, $staticPrefix)) { continue; } + $regex = $compiledRoute->getRegex(); - if (!preg_match($compiledRoute->getRegex(), $pathinfo, $matches)) { + $pos = strrpos($regex, '$'); + $hasTrailingSlash = '/' === $regex[$pos - 1]; + $regex = substr_replace($regex, '/?$', $pos - $hasTrailingSlash, 1 + $hasTrailingSlash); + + if (!preg_match($regex, $pathinfo, $matches)) { continue; } - $hostMatches = array(); + $hasTrailingVar = $trimmedPathinfo !== $pathinfo && preg_match('#\{\w+\}/?$#', $route->getPath()); + + if ($hasTrailingVar && ($hasTrailingSlash || (null === $m = $matches[\count($compiledRoute->getPathVariables())] ?? null) || '/' !== ($m[-1] ?? '/')) && preg_match($regex, $trimmedPathinfo, $m)) { + if ($hasTrailingSlash) { + $matches = $m; + } else { + $hasTrailingVar = false; + } + } + + $hostMatches = []; if ($compiledRoute->getHostRegex() && !preg_match($compiledRoute->getHostRegex(), $this->context->getHost(), $hostMatches)) { continue; } - // check HTTP method requirement - if ($requiredMethods = $route->getMethods()) { - // HEAD and GET are equivalent as per RFC - if ('HEAD' === $method = $this->context->getMethod()) { - $method = 'GET'; - } + $status = $this->handleRouteRequirements($pathinfo, $name, $route); - if (!in_array($method, $requiredMethods)) { - $this->allow = array_merge($this->allow, $requiredMethods); + if (self::REQUIREMENT_MISMATCH === $status[0]) { + continue; + } - continue; + if ('/' !== $pathinfo && !$hasTrailingVar && $hasTrailingSlash === ($trimmedPathinfo === $pathinfo)) { + if ($supportsTrailingSlash && (!$requiredMethods || \in_array('GET', $requiredMethods))) { + return $this->allow = $this->allowSchemes = []; } + continue; } - $status = $this->handleRouteRequirements($pathinfo, $name, $route); + if ($route->getSchemes() && !$route->hasScheme($this->context->getScheme())) { + $this->allowSchemes = array_merge($this->allowSchemes, $route->getSchemes()); + continue; + } - if (self::REQUIREMENT_MISMATCH === $status[0]) { + if ($requiredMethods && !\in_array($method, $requiredMethods)) { + $this->allow = array_merge($this->allow, $requiredMethods); continue; } - return $this->getAttributes($route, $name, array_replace($matches, $hostMatches, isset($status[1]) ? $status[1] : array())); + return $this->getAttributes($route, $name, array_replace($matches, $hostMatches, isset($status[1]) ? $status[1] : [])); } + + return []; } /** @@ -174,9 +216,14 @@ class UrlMatcher implements UrlMatcherInterface, RequestMatcherInterface */ protected function getAttributes(Route $route, $name, array $attributes) { + $defaults = $route->getDefaults(); + if (isset($defaults['_canonical_route'])) { + $name = $defaults['_canonical_route']; + unset($defaults['_canonical_route']); + } $attributes['_route'] = $name; - return $this->mergeDefaults($attributes, $route->getDefaults()); + return $this->mergeDefaults($attributes, $defaults); } /** @@ -191,15 +238,11 @@ class UrlMatcher implements UrlMatcherInterface, RequestMatcherInterface protected function handleRouteRequirements($pathinfo, $name, Route $route) { // expression condition - if ($route->getCondition() && !$this->getExpressionLanguage()->evaluate($route->getCondition(), array('context' => $this->context, 'request' => $this->request ?: $this->createRequest($pathinfo)))) { - return array(self::REQUIREMENT_MISMATCH, null); + if ($route->getCondition() && !$this->getExpressionLanguage()->evaluate($route->getCondition(), ['context' => $this->context, 'request' => $this->request ?: $this->createRequest($pathinfo)])) { + return [self::REQUIREMENT_MISMATCH, null]; } - // check HTTP scheme requirement - $scheme = $this->context->getScheme(); - $status = $route->getSchemes() && !$route->hasScheme($scheme) ? self::REQUIREMENT_MISMATCH : self::REQUIREMENT_MATCH; - - return array($status, null); + return [self::REQUIREMENT_MATCH, null]; } /** @@ -213,7 +256,7 @@ class UrlMatcher implements UrlMatcherInterface, RequestMatcherInterface protected function mergeDefaults($params, $defaults) { foreach ($params as $key => $value) { - if (!is_int($key)) { + if (!\is_int($key) && null !== $value) { $defaults[$key] = $value; } } @@ -225,7 +268,7 @@ class UrlMatcher implements UrlMatcherInterface, RequestMatcherInterface { if (null === $this->expressionLanguage) { if (!class_exists('Symfony\Component\ExpressionLanguage\ExpressionLanguage')) { - throw new \RuntimeException('Unable to use expressions as the Symfony ExpressionLanguage component is not installed.'); + throw new \LogicException('Unable to use expressions as the Symfony ExpressionLanguage component is not installed.'); } $this->expressionLanguage = new ExpressionLanguage(null, $this->expressionLanguageProviders); } @@ -242,9 +285,9 @@ class UrlMatcher implements UrlMatcherInterface, RequestMatcherInterface return null; } - return Request::create($this->context->getScheme().'://'.$this->context->getHost().$this->context->getBaseUrl().$pathinfo, $this->context->getMethod(), $this->context->getParameters(), array(), array(), array( + return Request::create($this->context->getScheme().'://'.$this->context->getHost().$this->context->getBaseUrl().$pathinfo, $this->context->getMethod(), $this->context->getParameters(), [], [], [ 'SCRIPT_FILENAME' => $this->context->getBaseUrl(), 'SCRIPT_NAME' => $this->context->getBaseUrl(), - )); + ]); } } diff --git a/vendor/symfony/routing/Matcher/UrlMatcherInterface.php b/vendor/symfony/routing/Matcher/UrlMatcherInterface.php index 2c7c3135bc66f0a8642b137690d3ab0ed6f3d8f4..17f1f97b3b4775d4f1f391edc6df0a3488d3ae35 100644 --- a/vendor/symfony/routing/Matcher/UrlMatcherInterface.php +++ b/vendor/symfony/routing/Matcher/UrlMatcherInterface.php @@ -11,10 +11,10 @@ namespace Symfony\Component\Routing\Matcher; +use Symfony\Component\Routing\Exception\MethodNotAllowedException; use Symfony\Component\Routing\Exception\NoConfigurationException; -use Symfony\Component\Routing\RequestContextAwareInterface; use Symfony\Component\Routing\Exception\ResourceNotFoundException; -use Symfony\Component\Routing\Exception\MethodNotAllowedException; +use Symfony\Component\Routing\RequestContextAwareInterface; /** * UrlMatcherInterface is the interface that all URL matcher classes must implement. diff --git a/vendor/symfony/routing/RequestContext.php b/vendor/symfony/routing/RequestContext.php index d62a7766ef85956ad7f4ca59c2cfd4ce32841854..591dd15938695f4d3a3d321d37046dc563eb92c7 100644 --- a/vendor/symfony/routing/RequestContext.php +++ b/vendor/symfony/routing/RequestContext.php @@ -31,19 +31,9 @@ class RequestContext private $httpPort; private $httpsPort; private $queryString; - private $parameters = array(); + private $parameters = []; - /** - * @param string $baseUrl The base URL - * @param string $method The HTTP method - * @param string $host The HTTP host name - * @param string $scheme The HTTP scheme - * @param int $httpPort The HTTP port - * @param int $httpsPort The HTTPS port - * @param string $path The path - * @param string $queryString The query string - */ - public function __construct($baseUrl = '', $method = 'GET', $host = 'localhost', $scheme = 'http', $httpPort = 80, $httpsPort = 443, $path = '/', $queryString = '') + public function __construct(string $baseUrl = '', string $method = 'GET', string $host = 'localhost', string $scheme = 'http', int $httpPort = 80, int $httpsPort = 443, string $path = '/', string $queryString = '') { $this->setBaseUrl($baseUrl); $this->setMethod($method); @@ -316,7 +306,7 @@ class RequestContext */ public function hasParameter($name) { - return array_key_exists($name, $this->parameters); + return \array_key_exists($name, $this->parameters); } /** diff --git a/vendor/symfony/routing/Route.php b/vendor/symfony/routing/Route.php index cd50ac8276f60014dffd747bcfc1d0919bdf448b..90d8e617c4e9723fd5087ecce7d7ce4f8477cd68 100644 --- a/vendor/symfony/routing/Route.php +++ b/vendor/symfony/routing/Route.php @@ -21,15 +21,15 @@ class Route implements \Serializable { private $path = '/'; private $host = ''; - private $schemes = array(); - private $methods = array(); - private $defaults = array(); - private $requirements = array(); - private $options = array(); + private $schemes = []; + private $methods = []; + private $defaults = []; + private $requirements = []; + private $options = []; private $condition = ''; /** - * @var null|CompiledRoute + * @var CompiledRoute|null */ private $compiled; @@ -50,11 +50,11 @@ class Route implements \Serializable * @param string|string[] $methods A required HTTP method or an array of restricted methods * @param string $condition A condition that should evaluate to true for the route to match */ - public function __construct($path, array $defaults = array(), array $requirements = array(), array $options = array(), $host = '', $schemes = array(), $methods = array(), $condition = '') + public function __construct(string $path, array $defaults = [], array $requirements = [], array $options = [], ?string $host = '', $schemes = [], $methods = [], ?string $condition = '') { $this->setPath($path); - $this->setDefaults($defaults); - $this->setRequirements($requirements); + $this->addDefaults($defaults); + $this->addRequirements($requirements); $this->setOptions($options); $this->setHost($host); $this->setSchemes($schemes); @@ -62,12 +62,9 @@ class Route implements \Serializable $this->setCondition($condition); } - /** - * {@inheritdoc} - */ - public function serialize() + public function __serialize(): array { - return serialize(array( + return [ 'path' => $this->path, 'host' => $this->host, 'defaults' => $this->defaults, @@ -77,15 +74,20 @@ class Route implements \Serializable 'methods' => $this->methods, 'condition' => $this->condition, 'compiled' => $this->compiled, - )); + ]; } /** - * {@inheritdoc} + * @internal since Symfony 4.3 + * @final since Symfony 4.3 */ - public function unserialize($serialized) + public function serialize() + { + return serialize($this->__serialize()); + } + + public function __unserialize(array $data): void { - $data = unserialize($serialized); $this->path = $data['path']; $this->host = $data['host']; $this->defaults = $data['defaults']; @@ -102,6 +104,15 @@ class Route implements \Serializable } } + /** + * @internal since Symfony 4.3 + * @final since Symfony 4.3 + */ + public function unserialize($serialized) + { + $this->__unserialize(unserialize($serialized)); + } + /** * Returns the pattern for the path. * @@ -123,6 +134,19 @@ class Route implements \Serializable */ public function setPath($pattern) { + if (false !== strpbrk($pattern, '?<')) { + $pattern = preg_replace_callback('#\{(\w++)(<.*?>)?(\?[^\}]*+)?\}#', function ($m) { + if (isset($m[3][0])) { + $this->setDefault($m[1], '?' !== $m[3] ? substr($m[3], 1) : null); + } + if (isset($m[2][0])) { + $this->setRequirement($m[1], substr($m[2], 1, -1)); + } + + return '{'.$m[1].'}'; + }, $pattern); + } + // A pattern must start with a slash and must not have multiple slashes at the beginning because the // generated path for this route would be confused with a network path, e.g. '//domain.com/path'. $this->path = '/'.ltrim(trim($pattern), '/'); @@ -196,7 +220,7 @@ class Route implements \Serializable */ public function hasScheme($scheme) { - return in_array(strtolower($scheme), $this->schemes, true); + return \in_array(strtolower($scheme), $this->schemes, true); } /** @@ -249,9 +273,9 @@ class Route implements \Serializable */ public function setOptions(array $options) { - $this->options = array( + $this->options = [ 'compiler_class' => 'Symfony\\Component\\Routing\\RouteCompiler', - ); + ]; return $this->addOptions($options); } @@ -314,7 +338,7 @@ class Route implements \Serializable */ public function hasOption($name) { - return array_key_exists($name, $this->options); + return \array_key_exists($name, $this->options); } /** @@ -338,7 +362,7 @@ class Route implements \Serializable */ public function setDefaults(array $defaults) { - $this->defaults = array(); + $this->defaults = []; return $this->addDefaults($defaults); } @@ -383,7 +407,7 @@ class Route implements \Serializable */ public function hasDefault($name) { - return array_key_exists($name, $this->defaults); + return \array_key_exists($name, $this->defaults); } /** @@ -423,7 +447,7 @@ class Route implements \Serializable */ public function setRequirements(array $requirements) { - $this->requirements = array(); + $this->requirements = []; return $this->addRequirements($requirements); } @@ -468,7 +492,7 @@ class Route implements \Serializable */ public function hasRequirement($key) { - return array_key_exists($key, $this->requirements); + return \array_key_exists($key, $this->requirements); } /** @@ -537,7 +561,7 @@ class Route implements \Serializable private function sanitizeRequirement($key, $regex) { - if (!is_string($regex)) { + if (!\is_string($regex)) { throw new \InvalidArgumentException(sprintf('Routing requirement for "%s" must be a string.', $key)); } diff --git a/vendor/symfony/routing/RouteCollection.php b/vendor/symfony/routing/RouteCollection.php index feabf234bc6d4fd6c41d6b97dd667bafbae59e57..6c642300a96d3d3f30b751b3e3855f82ff55f978 100644 --- a/vendor/symfony/routing/RouteCollection.php +++ b/vendor/symfony/routing/RouteCollection.php @@ -28,12 +28,12 @@ class RouteCollection implements \IteratorAggregate, \Countable /** * @var Route[] */ - private $routes = array(); + private $routes = []; /** * @var array */ - private $resources = array(); + private $resources = []; public function __clone() { @@ -63,7 +63,7 @@ class RouteCollection implements \IteratorAggregate, \Countable */ public function count() { - return count($this->routes); + return \count($this->routes); } /** @@ -117,7 +117,7 @@ class RouteCollection implements \IteratorAggregate, \Countable * Adds a route collection at the end of the current set by appending all * routes of the added collection. */ - public function addCollection(RouteCollection $collection) + public function addCollection(self $collection) { // we need to remove all routes with the same names first because just replacing them // would not place the new route at the end of the merged array @@ -138,7 +138,7 @@ class RouteCollection implements \IteratorAggregate, \Countable * @param array $defaults An array of default values * @param array $requirements An array of requirements */ - public function addPrefix($prefix, array $defaults = array(), array $requirements = array()) + public function addPrefix($prefix, array $defaults = [], array $requirements = []) { $prefix = trim(trim($prefix), '/'); @@ -153,6 +153,23 @@ class RouteCollection implements \IteratorAggregate, \Countable } } + /** + * Adds a prefix to the name of all the routes within in the collection. + */ + public function addNamePrefix(string $prefix) + { + $prefixedRoutes = []; + + foreach ($this->routes as $name => $route) { + $prefixedRoutes[$prefix.$name] = $route; + if (null !== $name = $route->getDefault('_canonical_route')) { + $route->setDefault('_canonical_route', $prefix.$name); + } + } + + $this->routes = $prefixedRoutes; + } + /** * Sets the host pattern on all routes. * @@ -160,7 +177,7 @@ class RouteCollection implements \IteratorAggregate, \Countable * @param array $defaults An array of default values * @param array $requirements An array of requirements */ - public function setHost($pattern, array $defaults = array(), array $requirements = array()) + public function setHost($pattern, array $defaults = [], array $requirements = []) { foreach ($this->routes as $route) { $route->setHost($pattern); diff --git a/vendor/symfony/routing/RouteCollectionBuilder.php b/vendor/symfony/routing/RouteCollectionBuilder.php index e8a9a165d6734611ac6328566cba52522fc27d4d..d1b1cdf5c8817b88aee52b6f6f51a7990f3d1167 100644 --- a/vendor/symfony/routing/RouteCollectionBuilder.php +++ b/vendor/symfony/routing/RouteCollectionBuilder.php @@ -11,7 +11,7 @@ namespace Symfony\Component\Routing; -use Symfony\Component\Config\Exception\FileLoaderLoadException; +use Symfony\Component\Config\Exception\LoaderLoadException; use Symfony\Component\Config\Loader\LoaderInterface; use Symfony\Component\Config\Resource\ResourceInterface; @@ -25,18 +25,18 @@ class RouteCollectionBuilder /** * @var Route[]|RouteCollectionBuilder[] */ - private $routes = array(); + private $routes = []; private $loader; - private $defaults = array(); + private $defaults = []; private $prefix; private $host; private $condition; - private $requirements = array(); - private $options = array(); + private $requirements = []; + private $options = []; private $schemes; private $methods; - private $resources = array(); + private $resources = []; public function __construct(LoaderInterface $loader = null) { @@ -46,7 +46,7 @@ class RouteCollectionBuilder /** * Import an external routing resource and returns the RouteCollectionBuilder. * - * $routes->import('blog.yml', '/blog'); + * $routes->import('blog.yml', '/blog'); * * @param mixed $resource * @param string|null $prefix @@ -54,11 +54,11 @@ class RouteCollectionBuilder * * @return self * - * @throws FileLoaderLoadException + * @throws LoaderLoadException */ public function import($resource, $prefix = '/', $type = null) { - /** @var RouteCollection[] $collection */ + /** @var RouteCollection[] $collections */ $collections = $this->load($resource, $type); // create a builder from the RouteCollection @@ -118,7 +118,7 @@ class RouteCollectionBuilder * @param string $prefix * @param RouteCollectionBuilder $builder */ - public function mount($prefix, RouteCollectionBuilder $builder) + public function mount($prefix, self $builder) { $builder->prefix = trim(trim($prefix), '/'); $this->routes[] = $builder; @@ -127,7 +127,6 @@ class RouteCollectionBuilder /** * Adds a Route object to the builder. * - * @param Route $route * @param string|null $name * * @return $this @@ -251,11 +250,9 @@ class RouteCollectionBuilder /** * Adds a resource for this collection. * - * @param ResourceInterface $resource - * * @return $this */ - private function addResource(ResourceInterface $resource) + private function addResource(ResourceInterface $resource): self { $this->resources[] = $resource; @@ -326,15 +323,13 @@ class RouteCollectionBuilder /** * Generates a route name based on details of this route. - * - * @return string */ - private function generateRouteName(Route $route) + private function generateRouteName(Route $route): string { $methods = implode('_', $route->getMethods()).'_'; $routeName = $methods.$route->getPath(); - $routeName = str_replace(array('/', ':', '|', '-'), '_', $routeName); + $routeName = str_replace(['/', ':', '|', '-'], '_', $routeName); $routeName = preg_replace('/[^a-z0-9A-Z_.]+/', '', $routeName); // Collapse consecutive underscores down into a single underscore. @@ -351,9 +346,9 @@ class RouteCollectionBuilder * * @return RouteCollection[] * - * @throws FileLoaderLoadException If no loader is found + * @throws LoaderLoadException If no loader is found */ - private function load($resource, $type = null) + private function load($resource, string $type = null): array { if (null === $this->loader) { throw new \BadMethodCallException('Cannot import other routing resources: you must pass a LoaderInterface when constructing RouteCollectionBuilder.'); @@ -362,19 +357,19 @@ class RouteCollectionBuilder if ($this->loader->supports($resource, $type)) { $collections = $this->loader->load($resource, $type); - return is_array($collections) ? $collections : array($collections); + return \is_array($collections) ? $collections : [$collections]; } if (null === $resolver = $this->loader->getResolver()) { - throw new FileLoaderLoadException($resource, null, null, null, $type); + throw new LoaderLoadException($resource, null, null, null, $type); } if (false === $loader = $resolver->resolve($resource, $type)) { - throw new FileLoaderLoadException($resource, null, null, null, $type); + throw new LoaderLoadException($resource, null, null, null, $type); } $collections = $loader->load($resource, $type); - return is_array($collections) ? $collections : array($collections); + return \is_array($collections) ? $collections : [$collections]; } } diff --git a/vendor/symfony/routing/RouteCompiler.php b/vendor/symfony/routing/RouteCompiler.php index 9b5526f31c09301b84cc0bbd382eded56988fbcf..cfea64276954fa4c24af3aa38d1875b09e19d545 100644 --- a/vendor/symfony/routing/RouteCompiler.php +++ b/vendor/symfony/routing/RouteCompiler.php @@ -46,10 +46,10 @@ class RouteCompiler implements RouteCompilerInterface */ public static function compile(Route $route) { - $hostVariables = array(); - $variables = array(); + $hostVariables = []; + $variables = []; $hostRegex = null; - $hostTokens = array(); + $hostTokens = []; if ('' !== $host = $route->getHost()) { $result = self::compilePattern($route, $host, true); @@ -94,17 +94,16 @@ class RouteCompiler implements RouteCompilerInterface private static function compilePattern(Route $route, $pattern, $isHost) { - $tokens = array(); - $variables = array(); - $matches = array(); + $tokens = []; + $variables = []; + $matches = []; $pos = 0; $defaultSeparator = $isHost ? '.' : '/'; $useUtf8 = preg_match('//u', $pattern); $needsUtf8 = $route->getOption('utf8'); if (!$needsUtf8 && $useUtf8 && preg_match('/[\x80-\xFF]/', $pattern)) { - $needsUtf8 = true; - @trigger_error(sprintf('Using UTF-8 route patterns without setting the "utf8" option is deprecated since Symfony 3.2 and will throw a LogicException in 4.0. Turn on the "utf8" route option for pattern "%s".', $pattern), E_USER_DEPRECATED); + throw new \LogicException(sprintf('Cannot use UTF-8 route patterns without setting the "utf8" option for route "%s".', $route->getPath())); } if (!$useUtf8 && $needsUtf8) { throw new \LogicException(sprintf('Cannot mix UTF-8 requirements with non-UTF-8 pattern "%s".', $pattern)); @@ -112,14 +111,15 @@ class RouteCompiler implements RouteCompilerInterface // Match all variables enclosed in "{}" and iterate over them. But we only want to match the innermost variable // in case of nested "{}", e.g. {foo{bar}}. This in ensured because \w does not match "{" or "}" itself. - preg_match_all('#\{\w+\}#', $pattern, $matches, PREG_OFFSET_CAPTURE | PREG_SET_ORDER); + preg_match_all('#\{(!)?(\w+)\}#', $pattern, $matches, PREG_OFFSET_CAPTURE | PREG_SET_ORDER); foreach ($matches as $match) { - $varName = substr($match[0][0], 1, -1); + $important = $match[1][1] >= 0; + $varName = $match[2][0]; // get all static text preceding the current variable $precedingText = substr($pattern, $pos, $match[0][1] - $pos); - $pos = $match[0][1] + strlen($match[0][0]); + $pos = $match[0][1] + \strlen($match[0][0]); - if (!strlen($precedingText)) { + if (!\strlen($precedingText)) { $precedingChar = ''; } elseif ($useUtf8) { preg_match('/.$/u', $precedingText, $precedingChar); @@ -134,18 +134,18 @@ class RouteCompiler implements RouteCompilerInterface if (preg_match('/^\d/', $varName)) { throw new \DomainException(sprintf('Variable name "%s" cannot start with a digit in route pattern "%s". Please use a different name.', $varName, $pattern)); } - if (in_array($varName, $variables)) { + if (\in_array($varName, $variables)) { throw new \LogicException(sprintf('Route pattern "%s" cannot reference variable name "%s" more than once.', $pattern, $varName)); } - if (strlen($varName) > self::VARIABLE_MAXIMUM_LENGTH) { + if (\strlen($varName) > self::VARIABLE_MAXIMUM_LENGTH) { throw new \DomainException(sprintf('Variable name "%s" cannot be longer than %s characters in route pattern "%s". Please use a shorter name.', $varName, self::VARIABLE_MAXIMUM_LENGTH, $pattern)); } if ($isSeparator && $precedingText !== $precedingChar) { - $tokens[] = array('text', substr($precedingText, 0, -strlen($precedingChar))); - } elseif (!$isSeparator && strlen($precedingText) > 0) { - $tokens[] = array('text', $precedingText); + $tokens[] = ['text', substr($precedingText, 0, -\strlen($precedingChar))]; + } elseif (!$isSeparator && \strlen($precedingText) > 0) { + $tokens[] = ['text', $precedingText]; } $regexp = $route->getRequirement($varName); @@ -154,7 +154,7 @@ class RouteCompiler implements RouteCompilerInterface // Find the next static character after the variable that functions as a separator. By default, this separator and '/' // are disallowed for the variable. This default requirement makes sure that optional variables can be matched at all // and that the generating-matching-combination of URLs unambiguous, i.e. the params used for generating the URL are - // the same that will be matched. Example: new Route('/{page}.{_format}', array('_format' => 'html')) + // the same that will be matched. Example: new Route('/{page}.{_format}', ['_format' => 'html']) // If {page} would also match the separating dot, {_format} would never match as {page} will eagerly consume everything. // Also even if {_format} was not optional the requirement prevents that {page} matches something that was originally // part of {_format} when generating the URL, e.g. _format = 'mobile.html'. @@ -176,28 +176,35 @@ class RouteCompiler implements RouteCompilerInterface if (!preg_match('//u', $regexp)) { $useUtf8 = false; } elseif (!$needsUtf8 && preg_match('/[\x80-\xFF]|(?<!\\\\)\\\\(?:\\\\\\\\)*+(?-i:X|[pP][\{CLMNPSZ]|x\{[A-Fa-f0-9]{3})/', $regexp)) { - $needsUtf8 = true; - @trigger_error(sprintf('Using UTF-8 route requirements without setting the "utf8" option is deprecated since Symfony 3.2 and will throw a LogicException in 4.0. Turn on the "utf8" route option for variable "%s" in pattern "%s".', $varName, $pattern), E_USER_DEPRECATED); + throw new \LogicException(sprintf('Cannot use UTF-8 route requirements without setting the "utf8" option for variable "%s" in pattern "%s".', $varName, $pattern)); } if (!$useUtf8 && $needsUtf8) { throw new \LogicException(sprintf('Cannot mix UTF-8 requirement with non-UTF-8 charset for variable "%s" in pattern "%s".', $varName, $pattern)); } + $regexp = self::transformCapturingGroupsToNonCapturings($regexp); } - $tokens[] = array('variable', $isSeparator ? $precedingChar : '', $regexp, $varName); + if ($important) { + $token = ['variable', $isSeparator ? $precedingChar : '', $regexp, $varName, false, true]; + } else { + $token = ['variable', $isSeparator ? $precedingChar : '', $regexp, $varName]; + } + + $tokens[] = $token; $variables[] = $varName; } - if ($pos < strlen($pattern)) { - $tokens[] = array('text', substr($pattern, $pos)); + if ($pos < \strlen($pattern)) { + $tokens[] = ['text', substr($pattern, $pos)]; } // find the first optional token $firstOptional = PHP_INT_MAX; if (!$isHost) { - for ($i = count($tokens) - 1; $i >= 0; --$i) { + for ($i = \count($tokens) - 1; $i >= 0; --$i) { $token = $tokens[$i]; - if ('variable' === $token[0] && $route->hasDefault($token[3])) { + // variable is optional when it is not important and has a default value + if ('variable' === $token[0] && !($token[5] ?? false) && $route->hasDefault($token[3])) { $firstOptional = $i; } else { break; @@ -207,35 +214,33 @@ class RouteCompiler implements RouteCompilerInterface // compute the matching regexp $regexp = ''; - for ($i = 0, $nbToken = count($tokens); $i < $nbToken; ++$i) { + for ($i = 0, $nbToken = \count($tokens); $i < $nbToken; ++$i) { $regexp .= self::computeRegexp($tokens, $i, $firstOptional); } - $regexp = self::REGEX_DELIMITER.'^'.$regexp.'$'.self::REGEX_DELIMITER.'s'.($isHost ? 'i' : ''); + $regexp = self::REGEX_DELIMITER.'^'.$regexp.'$'.self::REGEX_DELIMITER.'sD'.($isHost ? 'i' : ''); // enable Utf8 matching if really required if ($needsUtf8) { $regexp .= 'u'; - for ($i = 0, $nbToken = count($tokens); $i < $nbToken; ++$i) { + for ($i = 0, $nbToken = \count($tokens); $i < $nbToken; ++$i) { if ('variable' === $tokens[$i][0]) { - $tokens[$i][] = true; + $tokens[$i][4] = true; } } } - return array( + return [ 'staticPrefix' => self::determineStaticPrefix($route, $tokens), 'regex' => $regexp, 'tokens' => array_reverse($tokens), 'variables' => $variables, - ); + ]; } /** * Determines the longest static prefix possible for a route. - * - * @return string The leading static part of a route's path */ - private static function determineStaticPrefix(Route $route, array $tokens) + private static function determineStaticPrefix(Route $route, array $tokens): string { if ('text' !== $tokens[0][0]) { return ($route->hasDefault($tokens[0][3]) || '/' === $tokens[0][1]) ? '' : $tokens[0][1]; @@ -251,14 +256,9 @@ class RouteCompiler implements RouteCompilerInterface } /** - * Returns the next static character in the Route pattern that will serve as a separator. - * - * @param string $pattern The route pattern - * @param bool $useUtf8 Whether the character is encoded in UTF-8 or not - * - * @return string The next static character that functions as separator (or empty string when none available) + * Returns the next static character in the Route pattern that will serve as a separator (or the empty string when none available). */ - private static function findNextSeparator($pattern, $useUtf8) + private static function findNextSeparator(string $pattern, bool $useUtf8): string { if ('' == $pattern) { // return empty string if pattern is empty or false (false which can be returned by substr) @@ -284,7 +284,7 @@ class RouteCompiler implements RouteCompilerInterface * * @return string The regexp pattern for a single token */ - private static function computeRegexp(array $tokens, $index, $firstOptional) + private static function computeRegexp(array $tokens, int $index, int $firstOptional): string { $token = $tokens[$index]; if ('text' === $token[0]) { @@ -302,7 +302,7 @@ class RouteCompiler implements RouteCompilerInterface // "?:" means it is non-capturing, i.e. the portion of the subject string that // matched the optional subpattern is not passed back. $regexp = "(?:$regexp"; - $nbTokens = count($tokens); + $nbTokens = \count($tokens); if ($nbTokens - 1 == $index) { // Close the optional subpatterns $regexp .= str_repeat(')?', $nbTokens - $firstOptional - (0 === $firstOptional ? 1 : 0)); @@ -313,4 +313,25 @@ class RouteCompiler implements RouteCompilerInterface } } } + + private static function transformCapturingGroupsToNonCapturings(string $regexp): string + { + for ($i = 0; $i < \strlen($regexp); ++$i) { + if ('\\' === $regexp[$i]) { + ++$i; + continue; + } + if ('(' !== $regexp[$i] || !isset($regexp[$i + 2])) { + continue; + } + if ('*' === $regexp[++$i] || '?' === $regexp[$i]) { + ++$i; + continue; + } + $regexp = substr_replace($regexp, '?:', $i, 0); + ++$i; + } + + return $regexp; + } } diff --git a/vendor/symfony/routing/Router.php b/vendor/symfony/routing/Router.php index 0de921853f8757876d385c517370375060328381..5f8d9ffb159dd3555833928a3cd588e2d3323ae3 100644 --- a/vendor/symfony/routing/Router.php +++ b/vendor/symfony/routing/Router.php @@ -11,19 +11,28 @@ namespace Symfony\Component\Routing; -use Symfony\Component\Config\Loader\LoaderInterface; -use Symfony\Component\Config\ConfigCacheInterface; -use Symfony\Component\Config\ConfigCacheFactoryInterface; -use Symfony\Component\Config\ConfigCacheFactory; use Psr\Log\LoggerInterface; +use Symfony\Bundle\FrameworkBundle\Routing\RedirectableUrlMatcher; +use Symfony\Component\Config\ConfigCacheFactory; +use Symfony\Component\Config\ConfigCacheFactoryInterface; +use Symfony\Component\Config\ConfigCacheInterface; +use Symfony\Component\Config\Loader\LoaderInterface; +use Symfony\Component\ExpressionLanguage\ExpressionFunctionProviderInterface; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\Routing\Generator\CompiledUrlGenerator; use Symfony\Component\Routing\Generator\ConfigurableRequirementsInterface; -use Symfony\Component\Routing\Generator\UrlGeneratorInterface; +use Symfony\Component\Routing\Generator\Dumper\CompiledUrlGeneratorDumper; use Symfony\Component\Routing\Generator\Dumper\GeneratorDumperInterface; +use Symfony\Component\Routing\Generator\Dumper\PhpGeneratorDumper; +use Symfony\Component\Routing\Generator\UrlGenerator; +use Symfony\Component\Routing\Generator\UrlGeneratorInterface; +use Symfony\Component\Routing\Matcher\CompiledUrlMatcher; +use Symfony\Component\Routing\Matcher\Dumper\CompiledUrlMatcherDumper; +use Symfony\Component\Routing\Matcher\Dumper\MatcherDumperInterface; +use Symfony\Component\Routing\Matcher\Dumper\PhpMatcherDumper; use Symfony\Component\Routing\Matcher\RequestMatcherInterface; +use Symfony\Component\Routing\Matcher\UrlMatcher; use Symfony\Component\Routing\Matcher\UrlMatcherInterface; -use Symfony\Component\Routing\Matcher\Dumper\MatcherDumperInterface; -use Symfony\Component\HttpFoundation\Request; -use Symfony\Component\ExpressionLanguage\ExpressionFunctionProviderInterface; /** * The Router class is an example of the integration of all pieces of the @@ -66,13 +75,18 @@ class Router implements RouterInterface, RequestMatcherInterface /** * @var array */ - protected $options = array(); + protected $options = []; /** * @var LoggerInterface|null */ protected $logger; + /** + * @var string|null + */ + protected $defaultLocale; + /** * @var ConfigCacheFactoryInterface|null */ @@ -81,7 +95,7 @@ class Router implements RouterInterface, RequestMatcherInterface /** * @var ExpressionFunctionProviderInterface[] */ - private $expressionLanguageProviders = array(); + private $expressionLanguageProviders = []; /** * @param LoaderInterface $loader A LoaderInterface instance @@ -90,13 +104,14 @@ class Router implements RouterInterface, RequestMatcherInterface * @param RequestContext $context The context * @param LoggerInterface $logger A logger instance */ - public function __construct(LoaderInterface $loader, $resource, array $options = array(), RequestContext $context = null, LoggerInterface $logger = null) + public function __construct(LoaderInterface $loader, $resource, array $options = [], RequestContext $context = null, LoggerInterface $logger = null, string $defaultLocale = null) { $this->loader = $loader; $this->resource = $resource; $this->logger = $logger; $this->context = $context ?: new RequestContext(); $this->setOptions($options); + $this->defaultLocale = $defaultLocale; } /** @@ -107,13 +122,9 @@ class Router implements RouterInterface, RequestMatcherInterface * * cache_dir: The cache directory (or null to disable caching) * * debug: Whether to enable debugging or not (false by default) * * generator_class: The name of a UrlGeneratorInterface implementation - * * generator_base_class: The base class for the dumped generator class - * * generator_cache_class: The class name for the dumped generator class * * generator_dumper_class: The name of a GeneratorDumperInterface implementation * * matcher_class: The name of a UrlMatcherInterface implementation - * * matcher_base_class: The base class for the dumped matcher class - * * matcher_dumper_class: The class name for the dumped matcher class - * * matcher_cache_class: The name of a MatcherDumperInterface implementation + * * matcher_dumper_class: The name of a MatcherDumperInterface implementation * * resource_type: Type hint for the main resource (optional) * * strict_requirements: Configure strict requirement checking for generators * implementing ConfigurableRequirementsInterface (default is true) @@ -124,25 +135,26 @@ class Router implements RouterInterface, RequestMatcherInterface */ public function setOptions(array $options) { - $this->options = array( + $this->options = [ 'cache_dir' => null, 'debug' => false, - 'generator_class' => 'Symfony\\Component\\Routing\\Generator\\UrlGenerator', - 'generator_base_class' => 'Symfony\\Component\\Routing\\Generator\\UrlGenerator', - 'generator_dumper_class' => 'Symfony\\Component\\Routing\\Generator\\Dumper\\PhpGeneratorDumper', - 'generator_cache_class' => 'ProjectUrlGenerator', - 'matcher_class' => 'Symfony\\Component\\Routing\\Matcher\\UrlMatcher', - 'matcher_base_class' => 'Symfony\\Component\\Routing\\Matcher\\UrlMatcher', - 'matcher_dumper_class' => 'Symfony\\Component\\Routing\\Matcher\\Dumper\\PhpMatcherDumper', - 'matcher_cache_class' => 'ProjectUrlMatcher', + 'generator_class' => CompiledUrlGenerator::class, + 'generator_base_class' => UrlGenerator::class, // deprecated + 'generator_dumper_class' => CompiledUrlGeneratorDumper::class, + 'generator_cache_class' => 'UrlGenerator', // deprecated + 'matcher_class' => CompiledUrlMatcher::class, + 'matcher_base_class' => UrlMatcher::class, // deprecated + 'matcher_dumper_class' => CompiledUrlMatcherDumper::class, + 'matcher_cache_class' => 'UrlMatcher', // deprecated 'resource_type' => null, 'strict_requirements' => true, - ); + ]; // check option names and live merge, if errors are encountered Exception will be thrown - $invalid = array(); + $invalid = []; foreach ($options as $key => $value) { - if (array_key_exists($key, $this->options)) { + $this->checkDeprecatedOption($key); + if (\array_key_exists($key, $this->options)) { $this->options[$key] = $value; } else { $invalid[] = $key; @@ -164,10 +176,12 @@ class Router implements RouterInterface, RequestMatcherInterface */ public function setOption($key, $value) { - if (!array_key_exists($key, $this->options)) { + if (!\array_key_exists($key, $this->options)) { throw new \InvalidArgumentException(sprintf('The Router does not support the "%s" option.', $key)); } + $this->checkDeprecatedOption($key); + $this->options[$key] = $value; } @@ -182,10 +196,12 @@ class Router implements RouterInterface, RequestMatcherInterface */ public function getOption($key) { - if (!array_key_exists($key, $this->options)) { + if (!\array_key_exists($key, $this->options)) { throw new \InvalidArgumentException(sprintf('The Router does not support the "%s" option.', $key)); } + $this->checkDeprecatedOption($key); + return $this->options[$key]; } @@ -235,7 +251,7 @@ class Router implements RouterInterface, RequestMatcherInterface /** * {@inheritdoc} */ - public function generate($name, $parameters = array(), $referenceType = self::ABSOLUTE_PATH) + public function generate($name, $parameters = [], $referenceType = self::ABSOLUTE_PATH) { return $this->getGenerator()->generate($name, $parameters, $referenceType); } @@ -263,9 +279,9 @@ class Router implements RouterInterface, RequestMatcherInterface } /** - * Gets the UrlMatcher instance associated with this Router. + * Gets the UrlMatcher or RequestMatcher instance associated with this Router. * - * @return UrlMatcherInterface A UrlMatcherInterface instance + * @return UrlMatcherInterface|RequestMatcherInterface */ public function getMatcher() { @@ -273,8 +289,14 @@ class Router implements RouterInterface, RequestMatcherInterface return $this->matcher; } + $compiled = is_a($this->options['matcher_class'], CompiledUrlMatcher::class, true) && (UrlMatcher::class === $this->options['matcher_base_class'] || RedirectableUrlMatcher::class === $this->options['matcher_base_class']); + if (null === $this->options['cache_dir'] || null === $this->options['matcher_cache_class']) { - $this->matcher = new $this->options['matcher_class']($this->getRouteCollection(), $this->context); + $routes = $this->getRouteCollection(); + if ($compiled) { + $routes = (new CompiledUrlMatcherDumper($routes))->getCompiledRoutes(); + } + $this->matcher = new $this->options['matcher_class']($routes, $this->context); if (method_exists($this->matcher, 'addExpressionLanguageProvider')) { foreach ($this->expressionLanguageProviders as $provider) { $this->matcher->addExpressionLanguageProvider($provider); @@ -293,16 +315,22 @@ class Router implements RouterInterface, RequestMatcherInterface } } - $options = array( + $options = [ 'class' => $this->options['matcher_cache_class'], 'base_class' => $this->options['matcher_base_class'], - ); + ]; $cache->write($dumper->dump($options), $this->getRouteCollection()->getResources()); } ); - require_once $cache->getPath(); + if ($compiled) { + return $this->matcher = new $this->options['matcher_class'](require $cache->getPath(), $this->context); + } + + if (!class_exists($this->options['matcher_cache_class'], false)) { + require_once $cache->getPath(); + } return $this->matcher = new $this->options['matcher_cache_class']($this->context); } @@ -318,25 +346,37 @@ class Router implements RouterInterface, RequestMatcherInterface return $this->generator; } + $compiled = is_a($this->options['generator_class'], CompiledUrlGenerator::class, true) && UrlGenerator::class === $this->options['generator_base_class']; + if (null === $this->options['cache_dir'] || null === $this->options['generator_cache_class']) { - $this->generator = new $this->options['generator_class']($this->getRouteCollection(), $this->context, $this->logger); + $routes = $this->getRouteCollection(); + if ($compiled) { + $routes = (new CompiledUrlGeneratorDumper($routes))->getCompiledRoutes(); + } + $this->generator = new $this->options['generator_class']($routes, $this->context, $this->logger, $this->defaultLocale); } else { $cache = $this->getConfigCacheFactory()->cache($this->options['cache_dir'].'/'.$this->options['generator_cache_class'].'.php', function (ConfigCacheInterface $cache) { $dumper = $this->getGeneratorDumperInstance(); - $options = array( + $options = [ 'class' => $this->options['generator_cache_class'], 'base_class' => $this->options['generator_base_class'], - ); + ]; $cache->write($dumper->dump($options), $this->getRouteCollection()->getResources()); } ); - require_once $cache->getPath(); + if ($compiled) { + $this->generator = new $this->options['generator_class'](require $cache->getPath(), $this->context, $this->logger); + } else { + if (!class_exists($this->options['generator_cache_class'], false)) { + require_once $cache->getPath(); + } - $this->generator = new $this->options['generator_cache_class']($this->context, $this->logger); + $this->generator = new $this->options['generator_cache_class']($this->context, $this->logger, $this->defaultLocale); + } } if ($this->generator instanceof ConfigurableRequirementsInterface) { @@ -356,6 +396,11 @@ class Router implements RouterInterface, RequestMatcherInterface */ protected function getGeneratorDumperInstance() { + // For BC, fallback to PhpGeneratorDumper if the UrlGenerator and UrlGeneratorDumper are not consistent with each other + if (is_a($this->options['generator_class'], CompiledUrlGenerator::class, true) !== is_a($this->options['generator_dumper_class'], CompiledUrlGeneratorDumper::class, true)) { + return new PhpGeneratorDumper($this->getRouteCollection()); + } + return new $this->options['generator_dumper_class']($this->getRouteCollection()); } @@ -364,6 +409,11 @@ class Router implements RouterInterface, RequestMatcherInterface */ protected function getMatcherDumperInstance() { + // For BC, fallback to PhpMatcherDumper if the UrlMatcher and UrlMatcherDumper are not consistent with each other + if (is_a($this->options['matcher_class'], CompiledUrlMatcher::class, true) !== is_a($this->options['matcher_dumper_class'], CompiledUrlMatcherDumper::class, true)) { + return new PhpMatcherDumper($this->getRouteCollection()); + } + return new $this->options['matcher_dumper_class']($this->getRouteCollection()); } @@ -371,7 +421,7 @@ class Router implements RouterInterface, RequestMatcherInterface * Provides the ConfigCache factory implementation, falling back to a * default implementation if necessary. * - * @return ConfigCacheFactoryInterface $configCacheFactory + * @return ConfigCacheFactoryInterface */ private function getConfigCacheFactory() { @@ -381,4 +431,15 @@ class Router implements RouterInterface, RequestMatcherInterface return $this->configCacheFactory; } + + private function checkDeprecatedOption($key) + { + switch ($key) { + case 'generator_base_class': + case 'generator_cache_class': + case 'matcher_base_class': + case 'matcher_cache_class': + @trigger_error(sprintf('Option "%s" given to router %s is deprecated since Symfony 4.3.', $key, static::class), E_USER_DEPRECATED); + } + } } diff --git a/vendor/symfony/routing/RouterInterface.php b/vendor/symfony/routing/RouterInterface.php index a10ae34e07451b6a16949e030922c8ff005cd741..8a3e33dc22436b1810742853d907f8b821f29fb4 100644 --- a/vendor/symfony/routing/RouterInterface.php +++ b/vendor/symfony/routing/RouterInterface.php @@ -26,6 +26,9 @@ interface RouterInterface extends UrlMatcherInterface, UrlGeneratorInterface /** * Gets the RouteCollection instance associated with this Router. * + * WARNING: This method should never be used at runtime as it is SLOW. + * You might use it in a cache warmer though. + * * @return RouteCollection A RouteCollection instance */ public function getRouteCollection(); diff --git a/vendor/symfony/routing/Tests/Annotation/RouteTest.php b/vendor/symfony/routing/Tests/Annotation/RouteTest.php index 9af22f29f802f354607e7a5663839199d998c881..58c59dcbbfa151e3de4236cfdccf336a11d7c4d9 100644 --- a/vendor/symfony/routing/Tests/Annotation/RouteTest.php +++ b/vendor/symfony/routing/Tests/Annotation/RouteTest.php @@ -16,12 +16,16 @@ use Symfony\Component\Routing\Annotation\Route; class RouteTest extends TestCase { - /** - * @expectedException \BadMethodCallException - */ public function testInvalidRouteParameter() { - $route = new Route(array('foo' => 'bar')); + $this->expectException('BadMethodCallException'); + $route = new Route(['foo' => 'bar']); + } + + public function testTryingToSetLocalesDirectly() + { + $this->expectException('BadMethodCallException'); + $route = new Route(['locales' => ['nl' => 'bar']]); } /** @@ -29,22 +33,23 @@ class RouteTest extends TestCase */ public function testRouteParameters($parameter, $value, $getter) { - $route = new Route(array($parameter => $value)); + $route = new Route([$parameter => $value]); $this->assertEquals($route->$getter(), $value); } public function getValidParameters() { - return array( - array('value', '/Blog', 'getPath'), - array('requirements', array('locale' => 'en'), 'getRequirements'), - array('options', array('compiler_class' => 'RouteCompiler'), 'getOptions'), - array('name', 'blog_index', 'getName'), - array('defaults', array('_controller' => 'MyBlogBundle:Blog:index'), 'getDefaults'), - array('schemes', array('https'), 'getSchemes'), - array('methods', array('GET', 'POST'), 'getMethods'), - array('host', '{locale}.example.com', 'getHost'), - array('condition', 'context.getMethod() == "GET"', 'getCondition'), - ); + return [ + ['value', '/Blog', 'getPath'], + ['requirements', ['locale' => 'en'], 'getRequirements'], + ['options', ['compiler_class' => 'RouteCompiler'], 'getOptions'], + ['name', 'blog_index', 'getName'], + ['defaults', ['_controller' => 'MyBlogBundle:Blog:index'], 'getDefaults'], + ['schemes', ['https'], 'getSchemes'], + ['methods', ['GET', 'POST'], 'getMethods'], + ['host', '{locale}.example.com', 'getHost'], + ['condition', 'context.getMethod() == "GET"', 'getCondition'], + ['value', ['nl' => '/hier', 'en' => '/here'], 'getLocalizedPaths'], + ]; } } diff --git a/vendor/symfony/routing/Tests/CompiledRouteTest.php b/vendor/symfony/routing/Tests/CompiledRouteTest.php index 5bec7bbd7c86397d190d392bc91a4cd150f1320e..9c9f4f286203f42141567496310ca19a12909cc1 100644 --- a/vendor/symfony/routing/Tests/CompiledRouteTest.php +++ b/vendor/symfony/routing/Tests/CompiledRouteTest.php @@ -18,10 +18,10 @@ class CompiledRouteTest extends TestCase { public function testAccessors() { - $compiled = new CompiledRoute('prefix', 'regex', array('tokens'), array(), null, array(), array(), array('variables')); + $compiled = new CompiledRoute('prefix', 'regex', ['tokens'], [], null, [], [], ['variables']); $this->assertEquals('prefix', $compiled->getStaticPrefix(), '__construct() takes a static prefix as its second argument'); $this->assertEquals('regex', $compiled->getRegex(), '__construct() takes a regexp as its third argument'); - $this->assertEquals(array('tokens'), $compiled->getTokens(), '__construct() takes an array of tokens as its fourth argument'); - $this->assertEquals(array('variables'), $compiled->getVariables(), '__construct() takes an array of variables as its ninth argument'); + $this->assertEquals(['tokens'], $compiled->getTokens(), '__construct() takes an array of tokens as its fourth argument'); + $this->assertEquals(['variables'], $compiled->getVariables(), '__construct() takes an array of variables as its ninth argument'); } } diff --git a/vendor/symfony/routing/Tests/DependencyInjection/RoutingResolverPassTest.php b/vendor/symfony/routing/Tests/DependencyInjection/RoutingResolverPassTest.php index 97a34c969c2fee8f9f4c574a253d82f1663b0d6e..30c7516e59711d2485fa529f4d4197673677316d 100644 --- a/vendor/symfony/routing/Tests/DependencyInjection/RoutingResolverPassTest.php +++ b/vendor/symfony/routing/Tests/DependencyInjection/RoutingResolverPassTest.php @@ -29,7 +29,7 @@ class RoutingResolverPassTest extends TestCase (new RoutingResolverPass())->process($container); $this->assertEquals( - array(array('addLoader', array(new Reference('loader1'))), array('addLoader', array(new Reference('loader2')))), + [['addLoader', [new Reference('loader1')]], ['addLoader', [new Reference('loader2')]]], $container->getDefinition('routing.resolver')->getMethodCalls() ); } diff --git a/vendor/symfony/routing/Tests/Fixtures/AnnotatedClasses/AbstractClass.php b/vendor/symfony/routing/Tests/Fixtures/AnnotatedClasses/AbstractClass.php index 56bcab2a91d4fb565b5af5ea0d4c9c9d2dbbcc30..bd7ea962c144c9bc10d884a83bf7c3e0562782df 100644 --- a/vendor/symfony/routing/Tests/Fixtures/AnnotatedClasses/AbstractClass.php +++ b/vendor/symfony/routing/Tests/Fixtures/AnnotatedClasses/AbstractClass.php @@ -13,4 +13,9 @@ namespace Symfony\Component\Routing\Tests\Fixtures\AnnotatedClasses; abstract class AbstractClass { + abstract public function abstractRouteAction(); + + public function routeAction($arg1, $arg2 = 'defaultValue2', $arg3 = 'defaultValue3') + { + } } diff --git a/vendor/symfony/routing/Tests/Fixtures/AnnotatedClasses/EncodingClass.php b/vendor/symfony/routing/Tests/Fixtures/AnnotatedClasses/EncodingClass.php new file mode 100644 index 0000000000000000000000000000000000000000..dac72e3ddcfca1f9c842b0008074f81ccdb4a286 --- /dev/null +++ b/vendor/symfony/routing/Tests/Fixtures/AnnotatedClasses/EncodingClass.php @@ -0,0 +1,10 @@ +<?php + +namespace Symfony\Component\Routing\Tests\Fixtures\AnnotatedClasses; + +class EncodingClass +{ + public function routeÀction() + { + } +} diff --git a/vendor/symfony/routing/Tests/Fixtures/AnnotationFixtures/AbstractClassController.php b/vendor/symfony/routing/Tests/Fixtures/AnnotationFixtures/AbstractClassController.php new file mode 100644 index 0000000000000000000000000000000000000000..50576bcf1027e7dede4ac3a69148bdce413ec9d1 --- /dev/null +++ b/vendor/symfony/routing/Tests/Fixtures/AnnotationFixtures/AbstractClassController.php @@ -0,0 +1,7 @@ +<?php + +namespace Symfony\Component\Routing\Tests\Fixtures\AnnotationFixtures; + +abstract class AbstractClassController +{ +} diff --git a/vendor/symfony/routing/Tests/Fixtures/AnnotationFixtures/ActionPathController.php b/vendor/symfony/routing/Tests/Fixtures/AnnotationFixtures/ActionPathController.php new file mode 100644 index 0000000000000000000000000000000000000000..b96c4d658e740d741f8a97da739c31b448381d27 --- /dev/null +++ b/vendor/symfony/routing/Tests/Fixtures/AnnotationFixtures/ActionPathController.php @@ -0,0 +1,15 @@ +<?php + +namespace Symfony\Component\Routing\Tests\Fixtures\AnnotationFixtures; + +use Symfony\Component\Routing\Annotation\Route; + +class ActionPathController +{ + /** + * @Route("/path", name="action") + */ + public function action() + { + } +} diff --git a/vendor/symfony/routing/Tests/Fixtures/AnnotationFixtures/DefaultValueController.php b/vendor/symfony/routing/Tests/Fixtures/AnnotationFixtures/DefaultValueController.php new file mode 100644 index 0000000000000000000000000000000000000000..f7e38c290d2e788a8a7e7fccd6f138f231c300b2 --- /dev/null +++ b/vendor/symfony/routing/Tests/Fixtures/AnnotationFixtures/DefaultValueController.php @@ -0,0 +1,23 @@ +<?php + +namespace Symfony\Component\Routing\Tests\Fixtures\AnnotationFixtures; + +use Symfony\Component\Routing\Annotation\Route; + +class DefaultValueController +{ + /** + * @Route("/{default}/path", name="action") + */ + public function action($default = 'value') + { + } + + /** + * @Route("/hello/{name<\w+>}", name="hello_without_default") + * @Route("/hello/{name<\w+>?Symfony}", name="hello_with_default") + */ + public function hello(string $name = 'World') + { + } +} diff --git a/vendor/symfony/routing/Tests/Fixtures/AnnotationFixtures/ExplicitLocalizedActionPathController.php b/vendor/symfony/routing/Tests/Fixtures/AnnotationFixtures/ExplicitLocalizedActionPathController.php new file mode 100644 index 0000000000000000000000000000000000000000..e832c6b37740a4fa50865446dc8fca5d4e69dd0f --- /dev/null +++ b/vendor/symfony/routing/Tests/Fixtures/AnnotationFixtures/ExplicitLocalizedActionPathController.php @@ -0,0 +1,15 @@ +<?php + +namespace Symfony\Component\Routing\Tests\Fixtures\AnnotationFixtures; + +use Symfony\Component\Routing\Annotation\Route; + +class ExplicitLocalizedActionPathController +{ + /** + * @Route(path={"en": "/path", "nl": "/pad"}, name="action") + */ + public function action() + { + } +} diff --git a/vendor/symfony/routing/Tests/Fixtures/AnnotationFixtures/GlobalDefaultsClass.php b/vendor/symfony/routing/Tests/Fixtures/AnnotationFixtures/GlobalDefaultsClass.php new file mode 100644 index 0000000000000000000000000000000000000000..a4acb310c2a80691bb782a516a474dc3ab214cfd --- /dev/null +++ b/vendor/symfony/routing/Tests/Fixtures/AnnotationFixtures/GlobalDefaultsClass.php @@ -0,0 +1,34 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Tests\Fixtures\AnnotationFixtures; + +use Symfony\Component\Routing\Annotation\Route; + +/** + * @Route("/defaults", locale="g_locale", format="g_format") + */ +class GlobalDefaultsClass +{ + /** + * @Route("/specific-locale", name="specific_locale", locale="s_locale") + */ + public function locale() + { + } + + /** + * @Route("/specific-format", name="specific_format", format="s_format") + */ + public function format() + { + } +} diff --git a/vendor/symfony/routing/Tests/Fixtures/AnnotationFixtures/InvokableController.php b/vendor/symfony/routing/Tests/Fixtures/AnnotationFixtures/InvokableController.php new file mode 100644 index 0000000000000000000000000000000000000000..c70793a81d7a83af934fcea12d458e4bc7d8627a --- /dev/null +++ b/vendor/symfony/routing/Tests/Fixtures/AnnotationFixtures/InvokableController.php @@ -0,0 +1,15 @@ +<?php + +namespace Symfony\Component\Routing\Tests\Fixtures\AnnotationFixtures; + +use Symfony\Component\Routing\Annotation\Route; + +/** + * @Route("/here", name="lol", methods={"GET", "POST"}, schemes={"https"}) + */ +class InvokableController +{ + public function __invoke() + { + } +} diff --git a/vendor/symfony/routing/Tests/Fixtures/AnnotationFixtures/InvokableLocalizedController.php b/vendor/symfony/routing/Tests/Fixtures/AnnotationFixtures/InvokableLocalizedController.php new file mode 100644 index 0000000000000000000000000000000000000000..d9633b9f384422e45f2f83dad8fc884861e3f6c3 --- /dev/null +++ b/vendor/symfony/routing/Tests/Fixtures/AnnotationFixtures/InvokableLocalizedController.php @@ -0,0 +1,15 @@ +<?php + +namespace Symfony\Component\Routing\Tests\Fixtures\AnnotationFixtures; + +use Symfony\Component\Routing\Annotation\Route; + +/** + * @Route(path={"nl": "/hier", "en": "/here"}, name="action") + */ +class InvokableLocalizedController +{ + public function __invoke() + { + } +} diff --git a/vendor/symfony/routing/Tests/Fixtures/AnnotationFixtures/LocalizedActionPathController.php b/vendor/symfony/routing/Tests/Fixtures/AnnotationFixtures/LocalizedActionPathController.php new file mode 100644 index 0000000000000000000000000000000000000000..be6a35669029ef3b42c12c34d6f5c74c0c5fe25d --- /dev/null +++ b/vendor/symfony/routing/Tests/Fixtures/AnnotationFixtures/LocalizedActionPathController.php @@ -0,0 +1,15 @@ +<?php + +namespace Symfony\Component\Routing\Tests\Fixtures\AnnotationFixtures; + +use Symfony\Component\Routing\Annotation\Route; + +class LocalizedActionPathController +{ + /** + * @Route(path={"en": "/path", "nl": "/pad"}, name="action") + */ + public function action() + { + } +} diff --git a/vendor/symfony/routing/Tests/Fixtures/AnnotationFixtures/LocalizedMethodActionControllers.php b/vendor/symfony/routing/Tests/Fixtures/AnnotationFixtures/LocalizedMethodActionControllers.php new file mode 100644 index 0000000000000000000000000000000000000000..cadf3d1b1e304e9ac8a10ce3a93492bce59f5faf --- /dev/null +++ b/vendor/symfony/routing/Tests/Fixtures/AnnotationFixtures/LocalizedMethodActionControllers.php @@ -0,0 +1,25 @@ +<?php + +namespace Symfony\Component\Routing\Tests\Fixtures\AnnotationFixtures; + +use Symfony\Component\Routing\Annotation\Route; + +/** + * @Route(path={"en": "/the/path", "nl": "/het/pad"}) + */ +class LocalizedMethodActionControllers +{ + /** + * @Route(name="post", methods={"POST"}) + */ + public function post() + { + } + + /** + * @Route(name="put", methods={"PUT"}) + */ + public function put() + { + } +} diff --git a/vendor/symfony/routing/Tests/Fixtures/AnnotationFixtures/LocalizedPrefixLocalizedActionController.php b/vendor/symfony/routing/Tests/Fixtures/AnnotationFixtures/LocalizedPrefixLocalizedActionController.php new file mode 100644 index 0000000000000000000000000000000000000000..68f51b4821b103c24ba48b281ca3133f0b819f6f --- /dev/null +++ b/vendor/symfony/routing/Tests/Fixtures/AnnotationFixtures/LocalizedPrefixLocalizedActionController.php @@ -0,0 +1,18 @@ +<?php + +namespace Symfony\Component\Routing\Tests\Fixtures\AnnotationFixtures; + +use Symfony\Component\Routing\Annotation\Route; + +/** + * @Route(path={"nl": "/nl", "en": "/en"}) + */ +class LocalizedPrefixLocalizedActionController +{ + /** + * @Route(path={"nl": "/actie", "en": "/action"}, name="action") + */ + public function action() + { + } +} diff --git a/vendor/symfony/routing/Tests/Fixtures/AnnotationFixtures/LocalizedPrefixMissingLocaleActionController.php b/vendor/symfony/routing/Tests/Fixtures/AnnotationFixtures/LocalizedPrefixMissingLocaleActionController.php new file mode 100644 index 0000000000000000000000000000000000000000..a06e44e8492b3951a237164ba54c207a9c6f9358 --- /dev/null +++ b/vendor/symfony/routing/Tests/Fixtures/AnnotationFixtures/LocalizedPrefixMissingLocaleActionController.php @@ -0,0 +1,18 @@ +<?php + +namespace Symfony\Component\Routing\Tests\Fixtures\AnnotationFixtures; + +use Symfony\Component\Routing\Annotation\Route; + +/** + * @Route(path={"nl": "/nl"}) + */ +class LocalizedPrefixMissingLocaleActionController +{ + /** + * @Route(path={"nl": "/actie", "en": "/action"}, name="action") + */ + public function action() + { + } +} diff --git a/vendor/symfony/routing/Tests/Fixtures/AnnotationFixtures/LocalizedPrefixMissingRouteLocaleActionController.php b/vendor/symfony/routing/Tests/Fixtures/AnnotationFixtures/LocalizedPrefixMissingRouteLocaleActionController.php new file mode 100644 index 0000000000000000000000000000000000000000..8c9d96bcd410c744744dce39cce97df8cc371875 --- /dev/null +++ b/vendor/symfony/routing/Tests/Fixtures/AnnotationFixtures/LocalizedPrefixMissingRouteLocaleActionController.php @@ -0,0 +1,18 @@ +<?php + +namespace Symfony\Component\Routing\Tests\Fixtures\AnnotationFixtures; + +use Symfony\Component\Routing\Annotation\Route; + +/** + * @Route(path={"nl": "/nl", "en": "/en"}) + */ +class LocalizedPrefixMissingRouteLocaleActionController +{ + /** + * @Route(path={"nl": "/actie"}, name="action") + */ + public function action() + { + } +} diff --git a/vendor/symfony/routing/Tests/Fixtures/AnnotationFixtures/LocalizedPrefixWithRouteWithoutLocale.php b/vendor/symfony/routing/Tests/Fixtures/AnnotationFixtures/LocalizedPrefixWithRouteWithoutLocale.php new file mode 100644 index 0000000000000000000000000000000000000000..91dceb3319864e4d50f76d4cc3c47dbf365d72aa --- /dev/null +++ b/vendor/symfony/routing/Tests/Fixtures/AnnotationFixtures/LocalizedPrefixWithRouteWithoutLocale.php @@ -0,0 +1,18 @@ +<?php + +namespace Symfony\Component\Routing\Tests\Fixtures\AnnotationFixtures; + +use Symfony\Component\Routing\Annotation\Route; + +/** + * @Route(path={"en": "/en", "nl": "/nl"}) + */ +class LocalizedPrefixWithRouteWithoutLocale +{ + /** + * @Route("/suffix", name="action") + */ + public function action() + { + } +} diff --git a/vendor/symfony/routing/Tests/Fixtures/AnnotationFixtures/MethodActionControllers.php b/vendor/symfony/routing/Tests/Fixtures/AnnotationFixtures/MethodActionControllers.php new file mode 100644 index 0000000000000000000000000000000000000000..9350f3a914d8c283418a8c886fed2b0ef4d1d25a --- /dev/null +++ b/vendor/symfony/routing/Tests/Fixtures/AnnotationFixtures/MethodActionControllers.php @@ -0,0 +1,25 @@ +<?php + +namespace Symfony\Component\Routing\Tests\Fixtures\AnnotationFixtures; + +use Symfony\Component\Routing\Annotation\Route; + +/** + * @Route("/the/path") + */ +class MethodActionControllers +{ + /** + * @Route(name="post", methods={"POST"}) + */ + public function post() + { + } + + /** + * @Route(name="put", methods={"PUT"}) + */ + public function put() + { + } +} diff --git a/vendor/symfony/routing/Tests/Fixtures/AnnotationFixtures/MissingRouteNameController.php b/vendor/symfony/routing/Tests/Fixtures/AnnotationFixtures/MissingRouteNameController.php new file mode 100644 index 0000000000000000000000000000000000000000..7a4afb1e7347a59ac5ae14bbde606d5df7a1aa74 --- /dev/null +++ b/vendor/symfony/routing/Tests/Fixtures/AnnotationFixtures/MissingRouteNameController.php @@ -0,0 +1,15 @@ +<?php + +namespace Symfony\Component\Routing\Tests\Fixtures\AnnotationFixtures; + +use Symfony\Component\Routing\Annotation\Route; + +class MissingRouteNameController +{ + /** + * @Route("/path") + */ + public function action() + { + } +} diff --git a/vendor/symfony/routing/Tests/Fixtures/AnnotationFixtures/NothingButNameController.php b/vendor/symfony/routing/Tests/Fixtures/AnnotationFixtures/NothingButNameController.php new file mode 100644 index 0000000000000000000000000000000000000000..5aa1b07c77c177a9ba65af3b2b582b4c4c056644 --- /dev/null +++ b/vendor/symfony/routing/Tests/Fixtures/AnnotationFixtures/NothingButNameController.php @@ -0,0 +1,15 @@ +<?php + +namespace Symfony\Component\Routing\Tests\Fixtures\AnnotationFixtures; + +use Symfony\Component\Routing\Annotation\Route; + +class NothingButNameController +{ + /** + * @Route(name="action") + */ + public function action() + { + } +} diff --git a/vendor/symfony/routing/Tests/Fixtures/AnnotationFixtures/PrefixedActionLocalizedRouteController.php b/vendor/symfony/routing/Tests/Fixtures/AnnotationFixtures/PrefixedActionLocalizedRouteController.php new file mode 100644 index 0000000000000000000000000000000000000000..0b07d63df6ce53786689a20fe5f37c48ff96642c --- /dev/null +++ b/vendor/symfony/routing/Tests/Fixtures/AnnotationFixtures/PrefixedActionLocalizedRouteController.php @@ -0,0 +1,18 @@ +<?php + +namespace Symfony\Component\Routing\Tests\Fixtures\AnnotationFixtures; + +use Symfony\Component\Routing\Annotation\Route; + +/** + * @Route("/prefix") + */ +class PrefixedActionLocalizedRouteController +{ + /** + * @Route(path={"en": "/path", "nl": "/pad"}, name="action") + */ + public function action() + { + } +} diff --git a/vendor/symfony/routing/Tests/Fixtures/AnnotationFixtures/PrefixedActionPathController.php b/vendor/symfony/routing/Tests/Fixtures/AnnotationFixtures/PrefixedActionPathController.php new file mode 100644 index 0000000000000000000000000000000000000000..04c1d044b29c7d8e57a0ff1820993bdc7aea27f9 --- /dev/null +++ b/vendor/symfony/routing/Tests/Fixtures/AnnotationFixtures/PrefixedActionPathController.php @@ -0,0 +1,18 @@ +<?php + +namespace Symfony\Component\Routing\Tests\Fixtures\AnnotationFixtures; + +use Symfony\Component\Routing\Annotation\Route; + +/** + * @Route("/prefix", host="frankdejonge.nl", condition="lol=fun") + */ +class PrefixedActionPathController +{ + /** + * @Route("/path", name="action") + */ + public function action() + { + } +} diff --git a/vendor/symfony/routing/Tests/Fixtures/AnnotationFixtures/RequirementsWithoutPlaceholderNameController.php b/vendor/symfony/routing/Tests/Fixtures/AnnotationFixtures/RequirementsWithoutPlaceholderNameController.php new file mode 100644 index 0000000000000000000000000000000000000000..301f9691d138b7be7cdd0ad4fbf5430ef10fdc58 --- /dev/null +++ b/vendor/symfony/routing/Tests/Fixtures/AnnotationFixtures/RequirementsWithoutPlaceholderNameController.php @@ -0,0 +1,27 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Tests\Fixtures\AnnotationFixtures; + +use Symfony\Component\Routing\Annotation\Route; + +/** + * @Route("/", requirements={"foo", "\d+"}) + */ +class RequirementsWithoutPlaceholderNameController +{ + /** + * @Route("/{foo}", name="foo", requirements={"foo", "\d+"}) + */ + public function foo() + { + } +} diff --git a/vendor/symfony/routing/Tests/Fixtures/AnnotationFixtures/RouteWithPrefixController.php b/vendor/symfony/routing/Tests/Fixtures/AnnotationFixtures/RouteWithPrefixController.php new file mode 100644 index 0000000000000000000000000000000000000000..a98a527ad34a392a2c12baa5d28d4086995d8233 --- /dev/null +++ b/vendor/symfony/routing/Tests/Fixtures/AnnotationFixtures/RouteWithPrefixController.php @@ -0,0 +1,18 @@ +<?php + +namespace Symfony\Component\Routing\Tests\Fixtures\AnnotationFixtures; + +use Symfony\Component\Routing\Annotation\Route; + +/** + * @Route("/prefix") + */ +class RouteWithPrefixController +{ + /** + * @Route("/path", name="action") + */ + public function action() + { + } +} diff --git a/vendor/symfony/routing/Tests/Fixtures/AnnotationFixtures/Utf8ActionControllers.php b/vendor/symfony/routing/Tests/Fixtures/AnnotationFixtures/Utf8ActionControllers.php new file mode 100644 index 0000000000000000000000000000000000000000..ea5505f779efb0e76def7ef66723c1427dda0eea --- /dev/null +++ b/vendor/symfony/routing/Tests/Fixtures/AnnotationFixtures/Utf8ActionControllers.php @@ -0,0 +1,25 @@ +<?php + +namespace Symfony\Component\Routing\Tests\Fixtures\AnnotationFixtures; + +use Symfony\Component\Routing\Annotation\Route; + +/** + * @Route("/test", utf8=true) + */ +class Utf8ActionControllers +{ + /** + * @Route(name="one") + */ + public function one() + { + } + + /** + * @Route(name="two", utf8=false) + */ + public function two() + { + } +} diff --git a/vendor/symfony/routing/Tests/Fixtures/CustomRouteCompiler.php b/vendor/symfony/routing/Tests/Fixtures/CustomRouteCompiler.php index c2e2afd9afcd967c6a5dffaae111a704a6c67d6a..22b942d7bc871be44339393416d9e0a6415088b9 100644 --- a/vendor/symfony/routing/Tests/Fixtures/CustomRouteCompiler.php +++ b/vendor/symfony/routing/Tests/Fixtures/CustomRouteCompiler.php @@ -21,6 +21,6 @@ class CustomRouteCompiler extends RouteCompiler */ public static function compile(Route $route) { - return new CustomCompiledRoute('', '', array(), array()); + return new CustomCompiledRoute('', '', [], []); } } diff --git a/vendor/symfony/routing/Tests/Fixtures/CustomXmlFileLoader.php b/vendor/symfony/routing/Tests/Fixtures/CustomXmlFileLoader.php index 9fd5754a160a41e7b0fe775a9561d7a363416b5e..b7a02b60b0ae1ab9822a3ef6e700fbefe40de6e8 100644 --- a/vendor/symfony/routing/Tests/Fixtures/CustomXmlFileLoader.php +++ b/vendor/symfony/routing/Tests/Fixtures/CustomXmlFileLoader.php @@ -11,8 +11,8 @@ namespace Symfony\Component\Routing\Tests\Fixtures; -use Symfony\Component\Routing\Loader\XmlFileLoader; use Symfony\Component\Config\Util\XmlUtils; +use Symfony\Component\Routing\Loader\XmlFileLoader; /** * XmlFileLoader with schema validation turned off. diff --git a/vendor/symfony/routing/Tests/Fixtures/RedirectableUrlMatcher.php b/vendor/symfony/routing/Tests/Fixtures/RedirectableUrlMatcher.php index 15937bcf02d16ebe7041163e2d8fd40b7efd7835..79ae1cce54ca9290e62c278ca80368a1451755ce 100644 --- a/vendor/symfony/routing/Tests/Fixtures/RedirectableUrlMatcher.php +++ b/vendor/symfony/routing/Tests/Fixtures/RedirectableUrlMatcher.php @@ -11,8 +11,8 @@ namespace Symfony\Component\Routing\Tests\Fixtures; -use Symfony\Component\Routing\Matcher\UrlMatcher; use Symfony\Component\Routing\Matcher\RedirectableUrlMatcherInterface; +use Symfony\Component\Routing\Matcher\UrlMatcher; /** * @author Fabien Potencier <fabien@symfony.com> @@ -21,10 +21,10 @@ class RedirectableUrlMatcher extends UrlMatcher implements RedirectableUrlMatche { public function redirect($path, $route, $scheme = null) { - return array( + return [ '_controller' => 'Some controller reference...', 'path' => $path, 'scheme' => $scheme, - ); + ]; } } diff --git a/vendor/symfony/routing/Tests/Fixtures/controller/import__controller.xml b/vendor/symfony/routing/Tests/Fixtures/controller/import__controller.xml index bbe727d41be36a17263472fde2a1d86c378a133c..5c62914f90d2e24d1722f9cb40b114b4ead9b9fe 100644 --- a/vendor/symfony/routing/Tests/Fixtures/controller/import__controller.xml +++ b/vendor/symfony/routing/Tests/Fixtures/controller/import__controller.xml @@ -2,7 +2,7 @@ <routes xmlns="http://symfony.com/schema/routing" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://symfony.com/schema/routing - http://symfony.com/schema/routing/routing-1.0.xsd"> + https://symfony.com/schema/routing/routing-1.0.xsd"> <import resource="routing.xml"> <default key="_controller">FrameworkBundle:Template:template</default> diff --git a/vendor/symfony/routing/Tests/Fixtures/controller/import_controller.xml b/vendor/symfony/routing/Tests/Fixtures/controller/import_controller.xml index 378b9ca18fa43b0c6c269bea96a19d4edc5fed3e..8f52c4ec1479e36067672dd91465e2e0c6054081 100644 --- a/vendor/symfony/routing/Tests/Fixtures/controller/import_controller.xml +++ b/vendor/symfony/routing/Tests/Fixtures/controller/import_controller.xml @@ -2,7 +2,7 @@ <routes xmlns="http://symfony.com/schema/routing" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://symfony.com/schema/routing - http://symfony.com/schema/routing/routing-1.0.xsd"> + https://symfony.com/schema/routing/routing-1.0.xsd"> <import resource="routing.xml" controller="FrameworkBundle:Template:template" /> </routes> diff --git a/vendor/symfony/routing/Tests/Fixtures/controller/import_override_defaults.xml b/vendor/symfony/routing/Tests/Fixtures/controller/import_override_defaults.xml index e3c755a40a81c3e6e8d60c004d3b0faa5d2fa1e8..e092500fbd675a9ca796f6f5d25dc242fe484def 100644 --- a/vendor/symfony/routing/Tests/Fixtures/controller/import_override_defaults.xml +++ b/vendor/symfony/routing/Tests/Fixtures/controller/import_override_defaults.xml @@ -2,7 +2,7 @@ <routes xmlns="http://symfony.com/schema/routing" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://symfony.com/schema/routing - http://symfony.com/schema/routing/routing-1.0.xsd"> + https://symfony.com/schema/routing/routing-1.0.xsd"> <import resource="routing.xml" controller="FrameworkBundle:Template:template"> <default key="_controller">AppBundle:Blog:index</default> diff --git a/vendor/symfony/routing/Tests/Fixtures/controller/override_defaults.xml b/vendor/symfony/routing/Tests/Fixtures/controller/override_defaults.xml index f47c57b3085a1c52d73c4f13593bfcffe6ecf81f..f665ddbbcb1a960ab205565fc8af6a150dfe0ae4 100644 --- a/vendor/symfony/routing/Tests/Fixtures/controller/override_defaults.xml +++ b/vendor/symfony/routing/Tests/Fixtures/controller/override_defaults.xml @@ -2,7 +2,7 @@ <routes xmlns="http://symfony.com/schema/routing" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://symfony.com/schema/routing - http://symfony.com/schema/routing/routing-1.0.xsd"> + https://symfony.com/schema/routing/routing-1.0.xsd"> <route id="app_blog" path="/blog" controller="AppBundle:Homepage:show"> <default key="_controller">AppBundle:Blog:index</default> diff --git a/vendor/symfony/routing/Tests/Fixtures/controller/routing.xml b/vendor/symfony/routing/Tests/Fixtures/controller/routing.xml index 6420138a650724e3d8d238e00876a7ae03ee0628..f35e3e0a87b3e70b44d666aec2b3fee77bb9bcf1 100644 --- a/vendor/symfony/routing/Tests/Fixtures/controller/routing.xml +++ b/vendor/symfony/routing/Tests/Fixtures/controller/routing.xml @@ -2,7 +2,7 @@ <routes xmlns="http://symfony.com/schema/routing" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://symfony.com/schema/routing - http://symfony.com/schema/routing/routing-1.0.xsd"> + https://symfony.com/schema/routing/routing-1.0.xsd"> <route id="app_homepage" path="/" controller="AppBundle:Homepage:show" /> diff --git a/vendor/symfony/routing/Tests/Fixtures/defaults.php b/vendor/symfony/routing/Tests/Fixtures/defaults.php new file mode 100644 index 0000000000000000000000000000000000000000..200b568b17a7adb495f54280bafb98b86b053f2e --- /dev/null +++ b/vendor/symfony/routing/Tests/Fixtures/defaults.php @@ -0,0 +1,10 @@ +<?php + +namespace Symfony\Component\Routing\Loader\Configurator; + +return function (RoutingConfigurator $routes) { + $routes->add('defaults', '/defaults') + ->locale('en') + ->format('html') + ; +}; diff --git a/vendor/symfony/routing/Tests/Fixtures/defaults.xml b/vendor/symfony/routing/Tests/Fixtures/defaults.xml new file mode 100644 index 0000000000000000000000000000000000000000..dfa9153a86b11a081b905fba8ace3643c0ef370e --- /dev/null +++ b/vendor/symfony/routing/Tests/Fixtures/defaults.xml @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<routes xmlns="http://symfony.com/schema/routing" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://symfony.com/schema/routing + https://symfony.com/schema/routing/routing-1.0.xsd"> + + <route id="defaults" path="/defaults" locale="en" format="html" /> +</routes> diff --git a/vendor/symfony/routing/Tests/Fixtures/defaults.yml b/vendor/symfony/routing/Tests/Fixtures/defaults.yml new file mode 100644 index 0000000000000000000000000000000000000000..a563ae084b7c26bf302acc4c1a21e98cb89ba049 --- /dev/null +++ b/vendor/symfony/routing/Tests/Fixtures/defaults.yml @@ -0,0 +1,4 @@ +defaults: + path: /defaults + locale: en + format: html diff --git a/vendor/symfony/routing/Tests/Fixtures/dumper/compiled_url_matcher0.php b/vendor/symfony/routing/Tests/Fixtures/dumper/compiled_url_matcher0.php new file mode 100644 index 0000000000000000000000000000000000000000..550288cb1fdf07b0bc87460af16b624995e47f28 --- /dev/null +++ b/vendor/symfony/routing/Tests/Fixtures/dumper/compiled_url_matcher0.php @@ -0,0 +1,17 @@ +<?php + +/** + * This file has been auto-generated + * by the Symfony Routing Component. + */ + +return [ + false, // $matchHost + [ // $staticRoutes + ], + [ // $regexpList + ], + [ // $dynamicRoutes + ], + null, // $checkCondition +]; diff --git a/vendor/symfony/routing/Tests/Fixtures/dumper/compiled_url_matcher1.php b/vendor/symfony/routing/Tests/Fixtures/dumper/compiled_url_matcher1.php new file mode 100644 index 0000000000000000000000000000000000000000..7811f150a8ad71da7f0fa9929ef4754d4f540f20 --- /dev/null +++ b/vendor/symfony/routing/Tests/Fixtures/dumper/compiled_url_matcher1.php @@ -0,0 +1,108 @@ +<?php + +/** + * This file has been auto-generated + * by the Symfony Routing Component. + */ + +return [ + true, // $matchHost + [ // $staticRoutes + '/test/baz' => [[['_route' => 'baz'], null, null, null, false, false, null]], + '/test/baz.html' => [[['_route' => 'baz2'], null, null, null, false, false, null]], + '/test/baz3' => [[['_route' => 'baz3'], null, null, null, true, false, null]], + '/foofoo' => [[['_route' => 'foofoo', 'def' => 'test'], null, null, null, false, false, null]], + '/spa ce' => [[['_route' => 'space'], null, null, null, false, false, null]], + '/multi/new' => [[['_route' => 'overridden2'], null, null, null, false, false, null]], + '/multi/hey' => [[['_route' => 'hey'], null, null, null, true, false, null]], + '/ababa' => [[['_route' => 'ababa'], null, null, null, false, false, null]], + '/route1' => [[['_route' => 'route1'], 'a.example.com', null, null, false, false, null]], + '/c2/route2' => [[['_route' => 'route2'], 'a.example.com', null, null, false, false, null]], + '/route4' => [[['_route' => 'route4'], 'a.example.com', null, null, false, false, null]], + '/c2/route3' => [[['_route' => 'route3'], 'b.example.com', null, null, false, false, null]], + '/route5' => [[['_route' => 'route5'], 'c.example.com', null, null, false, false, null]], + '/route6' => [[['_route' => 'route6'], null, null, null, false, false, null]], + '/route11' => [[['_route' => 'route11'], '#^(?P<var1>[^\\.]++)\\.example\\.com$#sDi', null, null, false, false, null]], + '/route12' => [[['_route' => 'route12', 'var1' => 'val'], '#^(?P<var1>[^\\.]++)\\.example\\.com$#sDi', null, null, false, false, null]], + '/route17' => [[['_route' => 'route17'], null, null, null, false, false, null]], + ], + [ // $regexpList + 0 => '{^(?' + .'|(?:(?:[^./]*+\\.)++)(?' + .'|/foo/(baz|symfony)(*:47)' + .'|/bar(?' + .'|/([^/]++)(*:70)' + .'|head/([^/]++)(*:90)' + .')' + .'|/test/([^/]++)(?' + .'|(*:115)' + .')' + .'|/([\']+)(*:131)' + .'|/a/(?' + .'|b\'b/([^/]++)(?' + .'|(*:160)' + .'|(*:168)' + .')' + .'|(.*)(*:181)' + .'|b\'b/([^/]++)(?' + .'|(*:204)' + .'|(*:212)' + .')' + .')' + .'|/multi/hello(?:/([^/]++))?(*:248)' + .'|/([^/]++)/b/([^/]++)(?' + .'|(*:279)' + .'|(*:287)' + .')' + .'|/aba/([^/]++)(*:309)' + .')|(?i:([^\\.]++)\\.example\\.com)\\.(?' + .'|/route1(?' + .'|3/([^/]++)(*:371)' + .'|4/([^/]++)(*:389)' + .')' + .')|(?i:c\\.example\\.com)\\.(?' + .'|/route15/([^/]++)(*:441)' + .')|(?:(?:[^./]*+\\.)++)(?' + .'|/route16/([^/]++)(*:489)' + .'|/a/(?' + .'|a\\.\\.\\.(*:510)' + .'|b/(?' + .'|([^/]++)(*:531)' + .'|c/([^/]++)(*:549)' + .')' + .')' + .')' + .')/?$}sD', + ], + [ // $dynamicRoutes + 47 => [[['_route' => 'foo', 'def' => 'test'], ['bar'], null, null, false, true, null]], + 70 => [[['_route' => 'bar'], ['foo'], ['GET' => 0, 'HEAD' => 1], null, false, true, null]], + 90 => [[['_route' => 'barhead'], ['foo'], ['GET' => 0], null, false, true, null]], + 115 => [ + [['_route' => 'baz4'], ['foo'], null, null, true, true, null], + [['_route' => 'baz5'], ['foo'], ['POST' => 0], null, true, true, null], + [['_route' => 'baz.baz6'], ['foo'], ['PUT' => 0], null, true, true, null], + ], + 131 => [[['_route' => 'quoter'], ['quoter'], null, null, false, true, null]], + 160 => [[['_route' => 'foo1'], ['foo'], ['PUT' => 0], null, false, true, null]], + 168 => [[['_route' => 'bar1'], ['bar'], null, null, false, true, null]], + 181 => [[['_route' => 'overridden'], ['var'], null, null, false, true, null]], + 204 => [[['_route' => 'foo2'], ['foo1'], null, null, false, true, null]], + 212 => [[['_route' => 'bar2'], ['bar1'], null, null, false, true, null]], + 248 => [[['_route' => 'helloWorld', 'who' => 'World!'], ['who'], null, null, false, true, null]], + 279 => [[['_route' => 'foo3'], ['_locale', 'foo'], null, null, false, true, null]], + 287 => [[['_route' => 'bar3'], ['_locale', 'bar'], null, null, false, true, null]], + 309 => [[['_route' => 'foo4'], ['foo'], null, null, false, true, null]], + 371 => [[['_route' => 'route13'], ['var1', 'name'], null, null, false, true, null]], + 389 => [[['_route' => 'route14', 'var1' => 'val'], ['var1', 'name'], null, null, false, true, null]], + 441 => [[['_route' => 'route15'], ['name'], null, null, false, true, null]], + 489 => [[['_route' => 'route16', 'var1' => 'val'], ['name'], null, null, false, true, null]], + 510 => [[['_route' => 'a'], [], null, null, false, false, null]], + 531 => [[['_route' => 'b'], ['var'], null, null, false, true, null]], + 549 => [ + [['_route' => 'c'], ['var'], null, null, false, true, null], + [null, null, null, null, false, false, 0], + ], + ], + null, // $checkCondition +]; diff --git a/vendor/symfony/routing/Tests/Fixtures/dumper/compiled_url_matcher10.php b/vendor/symfony/routing/Tests/Fixtures/dumper/compiled_url_matcher10.php new file mode 100644 index 0000000000000000000000000000000000000000..c1822190edea85c1389c50497727d97227f8bcaa --- /dev/null +++ b/vendor/symfony/routing/Tests/Fixtures/dumper/compiled_url_matcher10.php @@ -0,0 +1,2774 @@ +<?php + +/** + * This file has been auto-generated + * by the Symfony Routing Component. + */ + +return [ + false, // $matchHost + [ // $staticRoutes + ], + [ // $regexpList + 0 => '{^(?' + .'|/c(?' + .'|f(?' + .'|cd20/([^/]++)/([^/]++)/([^/]++)/cfcd20(*:54)' + .'|e(?' + .'|cdb/([^/]++)/([^/]++)/([^/]++)/cfecdb(*:102)' + .'|e39/([^/]++)/([^/]++)/([^/]++)/cfee39(*:147)' + .')' + .'|a086/([^/]++)/([^/]++)/([^/]++)/cfa086(*:194)' + .'|004f/([^/]++)/([^/]++)/([^/]++)/cf004f(*:240)' + .')' + .'|4(?' + .'|ca42/([^/]++)/([^/]++)/([^/]++)/c4ca42(*:291)' + .'|5147/([^/]++)/([^/]++)/([^/]++)/c45147(*:337)' + .'|1000/([^/]++)/([^/]++)/([^/]++)/c41000(*:383)' + .')' + .'|8(?' + .'|1e72/([^/]++)/([^/]++)/([^/]++)/c81e72(*:434)' + .'|ffe9/([^/]++)/([^/]++)/([^/]++)/c8ffe9(*:480)' + .'|6a7e/([^/]++)/([^/]++)/([^/]++)/c86a7e(*:526)' + .')' + .'|9(?' + .'|f0f8/([^/]++)/([^/]++)/([^/]++)/c9f0f8(*:577)' + .'|e107/([^/]++)/([^/]++)/([^/]++)/c9e107(*:623)' + .')' + .'|2(?' + .'|0(?' + .'|ad4/([^/]++)/([^/]++)/([^/]++)/c20ad4(*:677)' + .'|3d8/([^/]++)/([^/]++)/([^/]++)/c203d8(*:722)' + .')' + .'|4cd7/([^/]++)/([^/]++)/([^/]++)/c24cd7(*:769)' + .')' + .'|5(?' + .'|1ce4/([^/]++)/([^/]++)/([^/]++)/c51ce4(*:820)' + .'|2f1b/([^/]++)/([^/]++)/([^/]++)/c52f1b(*:866)' + .'|ff25/([^/]++)/([^/]++)/([^/]++)/c5ff25(*:912)' + .')' + .'|7(?' + .'|4d97/([^/]++)/([^/]++)/([^/]++)/c74d97(*:963)' + .'|e124/([^/]++)/([^/]++)/([^/]++)/c7e124(*:1009)' + .')' + .'|16a53/([^/]++)/([^/]++)/([^/]++)/c16a53(*:1058)' + .'|0(?' + .'|c7c7/([^/]++)/([^/]++)/([^/]++)/c0c7c7(*:1109)' + .'|e190/([^/]++)/([^/]++)/([^/]++)/c0e190(*:1156)' + .'|42f4/([^/]++)/([^/]++)/([^/]++)/c042f4(*:1203)' + .'|58f5/([^/]++)/([^/]++)/([^/]++)/c058f5(*:1250)' + .')' + .'|e(?' + .'|debb/([^/]++)/([^/]++)/([^/]++)/cedebb(*:1302)' + .'|e631/([^/]++)/([^/]++)/([^/]++)/cee631(*:1349)' + .')' + .'|a(?' + .'|46c1/([^/]++)/([^/]++)/([^/]++)/ca46c1(*:1401)' + .'|f1a3/([^/]++)/([^/]++)/([^/]++)/caf1a3(*:1448)' + .')' + .'|b70ab/([^/]++)/([^/]++)/([^/]++)/cb70ab(*:1497)' + .'|d0069/([^/]++)/([^/]++)/([^/]++)/cd0069(*:1545)' + .'|3(?' + .'|e878/([^/]++)/([^/]++)/([^/]++)/c3e878(*:1596)' + .'|c59e/([^/]++)/([^/]++)/([^/]++)/c3c59e(*:1643)' + .')' + .')' + .'|/e(?' + .'|c(?' + .'|cbc8/([^/]++)/([^/]++)/([^/]++)/eccbc8(*:1701)' + .'|8(?' + .'|956/([^/]++)/([^/]++)/([^/]++)/ec8956(*:1751)' + .'|ce6/([^/]++)/([^/]++)/([^/]++)/ec8ce6(*:1797)' + .')' + .'|5dec/([^/]++)/([^/]++)/([^/]++)/ec5dec(*:1845)' + .')' + .'|4(?' + .'|da3b/([^/]++)/([^/]++)/([^/]++)/e4da3b(*:1897)' + .'|a622/([^/]++)/([^/]++)/([^/]++)/e4a622(*:1944)' + .'|6de7/([^/]++)/([^/]++)/([^/]++)/e46de7(*:1991)' + .'|4fea/([^/]++)/([^/]++)/([^/]++)/e44fea(*:2038)' + .')' + .'|3(?' + .'|6985/([^/]++)/([^/]++)/([^/]++)/e36985(*:2090)' + .'|796a/([^/]++)/([^/]++)/([^/]++)/e3796a(*:2137)' + .')' + .'|a(?' + .'|5d2f/([^/]++)/([^/]++)/([^/]++)/ea5d2f(*:2189)' + .'|e27d/([^/]++)/([^/]++)/([^/]++)/eae27d(*:2236)' + .')' + .'|2(?' + .'|c(?' + .'|420/([^/]++)/([^/]++)/([^/]++)/e2c420(*:2291)' + .'|0be/([^/]++)/([^/]++)/([^/]++)/e2c0be(*:2337)' + .')' + .'|ef52/([^/]++)/([^/]++)/([^/]++)/e2ef52(*:2385)' + .')' + .'|d(?' + .'|3d2c/([^/]++)/([^/]++)/([^/]++)/ed3d2c(*:2437)' + .'|a80a/([^/]++)/([^/]++)/([^/]++)/eda80a(*:2484)' + .'|dea8/([^/]++)/([^/]++)/([^/]++)/eddea8(*:2531)' + .')' + .'|b(?' + .'|16(?' + .'|0d/([^/]++)/([^/]++)/([^/]++)/eb160d(*:2586)' + .'|37/([^/]++)/([^/]++)/([^/]++)/eb1637(*:2631)' + .')' + .'|a0dc/([^/]++)/([^/]++)/([^/]++)/eba0dc(*:2679)' + .')' + .'|0(?' + .'|0da0/([^/]++)/([^/]++)/([^/]++)/e00da0(*:2731)' + .'|c641/([^/]++)/([^/]++)/([^/]++)/e0c641(*:2778)' + .')' + .'|e(?' + .'|cca5/([^/]++)/([^/]++)/([^/]++)/eecca5(*:2830)' + .'|d5af/([^/]++)/([^/]++)/([^/]++)/eed5af(*:2877)' + .')' + .'|96ed4/([^/]++)/([^/]++)/([^/]++)/e96ed4(*:2926)' + .'|1(?' + .'|6542/([^/]++)/([^/]++)/([^/]++)/e16542(*:2977)' + .'|e32e/([^/]++)/([^/]++)/([^/]++)/e1e32e(*:3024)' + .')' + .'|56954/([^/]++)/([^/]++)/([^/]++)/e56954(*:3073)' + .'|f(?' + .'|0d39/([^/]++)/([^/]++)/([^/]++)/ef0d39(*:3124)' + .'|e937/([^/]++)/([^/]++)/([^/]++)/efe937(*:3171)' + .'|575e/([^/]++)/([^/]++)/([^/]++)/ef575e(*:3218)' + .')' + .'|7b24b/([^/]++)/([^/]++)/([^/]++)/e7b24b(*:3267)' + .'|836d8/([^/]++)/([^/]++)/([^/]++)/e836d8(*:3315)' + .')' + .'|/a(?' + .'|8(?' + .'|7ff6/([^/]++)/([^/]++)/([^/]++)/a87ff6(*:3372)' + .'|baa5/([^/]++)/([^/]++)/([^/]++)/a8baa5(*:3419)' + .'|f15e/([^/]++)/([^/]++)/([^/]++)/a8f15e(*:3466)' + .'|c88a/([^/]++)/([^/]++)/([^/]++)/a8c88a(*:3513)' + .'|abb4/([^/]++)/([^/]++)/([^/]++)/a8abb4(*:3560)' + .')' + .'|a(?' + .'|b323/([^/]++)/([^/]++)/([^/]++)/aab323(*:3612)' + .'|942a/([^/]++)/([^/]++)/([^/]++)/aa942a(*:3659)' + .')' + .'|5(?' + .'|bfc9/([^/]++)/([^/]++)/([^/]++)/a5bfc9(*:3711)' + .'|771b/([^/]++)/([^/]++)/([^/]++)/a5771b(*:3758)' + .'|e001/([^/]++)/([^/]++)/([^/]++)/a5e001(*:3805)' + .'|97e5/([^/]++)/([^/]++)/([^/]++)/a597e5(*:3852)' + .'|16a8/([^/]++)/([^/]++)/([^/]++)/a516a8(*:3899)' + .')' + .'|1d0c6/([^/]++)/([^/]++)/([^/]++)/a1d0c6(*:3948)' + .'|6(?' + .'|84ec/([^/]++)/([^/]++)/([^/]++)/a684ec(*:3999)' + .'|6658/([^/]++)/([^/]++)/([^/]++)/a66658(*:4046)' + .')' + .'|3(?' + .'|f390/([^/]++)/([^/]++)/([^/]++)/a3f390(*:4098)' + .'|c65c/([^/]++)/([^/]++)/([^/]++)/a3c65c(*:4145)' + .')' + .'|d(?' + .'|61ab/([^/]++)/([^/]++)/([^/]++)/ad61ab(*:4197)' + .'|13a2/([^/]++)/([^/]++)/([^/]++)/ad13a2(*:4244)' + .'|972f/([^/]++)/([^/]++)/([^/]++)/ad972f(*:4291)' + .')' + .'|c(?' + .'|627a/([^/]++)/([^/]++)/([^/]++)/ac627a(*:4343)' + .'|1dd2/([^/]++)/([^/]++)/([^/]++)/ac1dd2(*:4390)' + .')' + .'|9(?' + .'|7da6/([^/]++)/([^/]++)/([^/]++)/a97da6(*:4442)' + .'|6b65/([^/]++)/([^/]++)/([^/]++)/a96b65(*:4489)' + .')' + .'|0(?' + .'|a080/([^/]++)/([^/]++)/([^/]++)/a0a080(*:4541)' + .'|2ffd/([^/]++)/([^/]++)/([^/]++)/a02ffd(*:4588)' + .'|1a03/([^/]++)/([^/]++)/([^/]++)/a01a03(*:4635)' + .')' + .'|4(?' + .'|a042/([^/]++)/([^/]++)/([^/]++)/a4a042(*:4687)' + .'|f236/([^/]++)/([^/]++)/([^/]++)/a4f236(*:4734)' + .'|9e94/([^/]++)/([^/]++)/([^/]++)/a49e94(*:4781)' + .')' + .'|2557a/([^/]++)/([^/]++)/([^/]++)/a2557a(*:4830)' + .'|b817c/([^/]++)/([^/]++)/([^/]++)/ab817c(*:4878)' + .')' + .'|/1(?' + .'|6(?' + .'|7909/([^/]++)/([^/]++)/([^/]++)/167909(*:4935)' + .'|a5cd/([^/]++)/([^/]++)/([^/]++)/16a5cd(*:4982)' + .'|51cf/([^/]++)/([^/]++)/([^/]++)/1651cf(*:5029)' + .')' + .'|f(?' + .'|0e3d/([^/]++)/([^/]++)/([^/]++)/1f0e3d(*:5081)' + .'|f(?' + .'|1de/([^/]++)/([^/]++)/([^/]++)/1ff1de(*:5131)' + .'|8a7/([^/]++)/([^/]++)/([^/]++)/1ff8a7(*:5177)' + .')' + .')' + .'|8(?' + .'|2be0/([^/]++)/([^/]++)/([^/]++)/182be0(*:5230)' + .'|d804/([^/]++)/([^/]++)/([^/]++)/18d804(*:5277)' + .'|9977/([^/]++)/([^/]++)/([^/]++)/189977(*:5324)' + .')' + .'|c(?' + .'|383c/([^/]++)/([^/]++)/([^/]++)/1c383c(*:5376)' + .'|9ac0/([^/]++)/([^/]++)/([^/]++)/1c9ac0(*:5423)' + .')' + .'|9(?' + .'|ca14/([^/]++)/([^/]++)/([^/]++)/19ca14(*:5475)' + .'|f3cd/([^/]++)/([^/]++)/([^/]++)/19f3cd(*:5522)' + .')' + .'|7(?' + .'|e621/([^/]++)/([^/]++)/([^/]++)/17e621(*:5574)' + .'|0000/([^/]++)/([^/]++)/([^/]++)/170000(*:5621)' + .'|d63b/([^/]++)/([^/]++)/([^/]++)/17d63b(*:5668)' + .')' + .'|4(?' + .'|bfa6/([^/]++)/([^/]++)/([^/]++)/14bfa6(*:5720)' + .'|0f69/([^/]++)/([^/]++)/([^/]++)/140f69(*:5767)' + .'|9e96/([^/]++)/([^/]++)/([^/]++)/149e96(*:5814)' + .'|2949/([^/]++)/([^/]++)/([^/]++)/142949(*:5861)' + .')' + .'|a(?' + .'|fa34/([^/]++)/([^/]++)/([^/]++)/1afa34(*:5913)' + .'|5b1e/([^/]++)/([^/]++)/([^/]++)/1a5b1e(*:5960)' + .')' + .'|3(?' + .'|8(?' + .'|597/([^/]++)/([^/]++)/([^/]++)/138597(*:6015)' + .'|bb0/([^/]++)/([^/]++)/([^/]++)/138bb0(*:6061)' + .')' + .'|f(?' + .'|e9d/([^/]++)/([^/]++)/([^/]++)/13fe9d(*:6112)' + .'|989/([^/]++)/([^/]++)/([^/]++)/13f989(*:6158)' + .'|3cf/([^/]++)/([^/]++)/([^/]++)/13f3cf(*:6204)' + .')' + .')' + .'|d7f7a/([^/]++)/([^/]++)/([^/]++)/1d7f7a(*:6254)' + .'|5(?' + .'|34b7/([^/]++)/([^/]++)/([^/]++)/1534b7(*:6305)' + .'|8f30/([^/]++)/([^/]++)/([^/]++)/158f30(*:6352)' + .'|4384/([^/]++)/([^/]++)/([^/]++)/154384(*:6399)' + .'|d4e8/([^/]++)/([^/]++)/([^/]++)/15d4e8(*:6446)' + .')' + .'|1(?' + .'|5f89/([^/]++)/([^/]++)/([^/]++)/115f89(*:6498)' + .'|b984/([^/]++)/([^/]++)/([^/]++)/11b984(*:6545)' + .')' + .'|068c6/([^/]++)/([^/]++)/([^/]++)/1068c6(*:6594)' + .'|be3bc/([^/]++)/([^/]++)/([^/]++)/1be3bc(*:6642)' + .')' + .'|/8(?' + .'|f(?' + .'|1(?' + .'|4e4/([^/]++)/([^/]++)/([^/]++)/8f14e4(*:6702)' + .'|21c/([^/]++)/([^/]++)/([^/]++)/8f121c(*:6748)' + .')' + .'|8551/([^/]++)/([^/]++)/([^/]++)/8f8551(*:6796)' + .'|5329/([^/]++)/([^/]++)/([^/]++)/8f5329(*:6843)' + .'|e009/([^/]++)/([^/]++)/([^/]++)/8fe009(*:6890)' + .')' + .'|e(?' + .'|296a/([^/]++)/([^/]++)/([^/]++)/8e296a(*:6942)' + .'|98d8/([^/]++)/([^/]++)/([^/]++)/8e98d8(*:6989)' + .'|fb10/([^/]++)/([^/]++)/([^/]++)/8efb10(*:7036)' + .'|6b42/([^/]++)/([^/]++)/([^/]++)/8e6b42(*:7083)' + .')' + .'|61398/([^/]++)/([^/]++)/([^/]++)/861398(*:7132)' + .'|1(?' + .'|2b4b/([^/]++)/([^/]++)/([^/]++)/812b4b(*:7183)' + .'|9f46/([^/]++)/([^/]++)/([^/]++)/819f46(*:7230)' + .'|6b11/([^/]++)/([^/]++)/([^/]++)/816b11(*:7277)' + .')' + .'|d(?' + .'|5e95/([^/]++)/([^/]++)/([^/]++)/8d5e95(*:7329)' + .'|3bba/([^/]++)/([^/]++)/([^/]++)/8d3bba(*:7376)' + .'|d48d/([^/]++)/([^/]++)/([^/]++)/8dd48d(*:7423)' + .'|7d8e/([^/]++)/([^/]++)/([^/]++)/8d7d8e(*:7470)' + .')' + .'|2(?' + .'|aa4b/([^/]++)/([^/]++)/([^/]++)/82aa4b(*:7522)' + .'|1(?' + .'|612/([^/]++)/([^/]++)/([^/]++)/821612(*:7572)' + .'|fa7/([^/]++)/([^/]++)/([^/]++)/821fa7(*:7618)' + .')' + .'|cec9/([^/]++)/([^/]++)/([^/]++)/82cec9(*:7666)' + .')' + .'|5(?' + .'|d8ce/([^/]++)/([^/]++)/([^/]++)/85d8ce(*:7718)' + .'|4d(?' + .'|6f/([^/]++)/([^/]++)/([^/]++)/854d6f(*:7768)' + .'|9f/([^/]++)/([^/]++)/([^/]++)/854d9f(*:7813)' + .')' + .')' + .'|4d9ee/([^/]++)/([^/]++)/([^/]++)/84d9ee(*:7863)' + .'|c(?' + .'|19f5/([^/]++)/([^/]++)/([^/]++)/8c19f5(*:7914)' + .'|b22b/([^/]++)/([^/]++)/([^/]++)/8cb22b(*:7961)' + .')' + .'|39ab4/([^/]++)/([^/]++)/([^/]++)/839ab4(*:8010)' + .'|9f0fd/([^/]++)/([^/]++)/([^/]++)/89f0fd(*:8058)' + .'|bf121/([^/]++)/([^/]++)/([^/]++)/8bf121(*:8106)' + .'|77a9b/([^/]++)/([^/]++)/([^/]++)/877a9b(*:8154)' + .')' + .'|/4(?' + .'|5(?' + .'|c48c/([^/]++)/([^/]++)/([^/]++)/45c48c(*:8211)' + .'|fbc6/([^/]++)/([^/]++)/([^/]++)/45fbc6(*:8258)' + .')' + .'|e732c/([^/]++)/([^/]++)/([^/]++)/4e732c(*:8307)' + .'|4f683/([^/]++)/([^/]++)/([^/]++)/44f683(*:8355)' + .'|3(?' + .'|ec51/([^/]++)/([^/]++)/([^/]++)/43ec51(*:8406)' + .'|2aca/([^/]++)/([^/]++)/([^/]++)/432aca(*:8453)' + .')' + .'|c5(?' + .'|6ff/([^/]++)/([^/]++)/([^/]++)/4c56ff(*:8505)' + .'|bde/([^/]++)/([^/]++)/([^/]++)/4c5bde(*:8551)' + .')' + .'|2(?' + .'|a0e1/([^/]++)/([^/]++)/([^/]++)/42a0e1(*:8603)' + .'|e7aa/([^/]++)/([^/]++)/([^/]++)/42e7aa(*:8650)' + .'|998c/([^/]++)/([^/]++)/([^/]++)/42998c(*:8697)' + .'|8fca/([^/]++)/([^/]++)/([^/]++)/428fca(*:8744)' + .')' + .'|7(?' + .'|d1e9/([^/]++)/([^/]++)/([^/]++)/47d1e9(*:8796)' + .'|34ba/([^/]++)/([^/]++)/([^/]++)/4734ba(*:8843)' + .')' + .'|6ba9f/([^/]++)/([^/]++)/([^/]++)/46ba9f(*:8892)' + .'|8aedb/([^/]++)/([^/]++)/([^/]++)/48aedb(*:8940)' + .'|9(?' + .'|182f/([^/]++)/([^/]++)/([^/]++)/49182f(*:8991)' + .'|6e05/([^/]++)/([^/]++)/([^/]++)/496e05(*:9038)' + .'|ae49/([^/]++)/([^/]++)/([^/]++)/49ae49(*:9085)' + .')' + .'|0008b/([^/]++)/([^/]++)/([^/]++)/40008b(*:9134)' + .'|1(?' + .'|f1f1/([^/]++)/([^/]++)/([^/]++)/41f1f1(*:9185)' + .'|ae36/([^/]++)/([^/]++)/([^/]++)/41ae36(*:9232)' + .')' + .'|f(?' + .'|6ffe/([^/]++)/([^/]++)/([^/]++)/4f6ffe(*:9284)' + .'|4adc/([^/]++)/([^/]++)/([^/]++)/4f4adc(*:9331)' + .')' + .')' + .'|/d(?' + .'|3(?' + .'|d944/([^/]++)/([^/]++)/([^/]++)/d3d944(*:9389)' + .'|9577/([^/]++)/([^/]++)/([^/]++)/d39577(*:9436)' + .'|4ab1/([^/]++)/([^/]++)/([^/]++)/d34ab1(*:9483)' + .')' + .'|6(?' + .'|7d8a/([^/]++)/([^/]++)/([^/]++)/d67d8a(*:9535)' + .'|4592/([^/]++)/([^/]++)/([^/]++)/d64592(*:9582)' + .'|baf6/([^/]++)/([^/]++)/([^/]++)/d6baf6(*:9629)' + .'|1e4b/([^/]++)/([^/]++)/([^/]++)/d61e4b(*:9676)' + .')' + .'|9(?' + .'|d4f4/([^/]++)/([^/]++)/([^/]++)/d9d4f4(*:9728)' + .'|6409/([^/]++)/([^/]++)/([^/]++)/d96409(*:9775)' + .'|47bf/([^/]++)/([^/]++)/([^/]++)/d947bf(*:9822)' + .'|fc5b/([^/]++)/([^/]++)/([^/]++)/d9fc5b(*:9869)' + .')' + .'|8(?' + .'|2c8d/([^/]++)/([^/]++)/([^/]++)/d82c8d(*:9921)' + .'|1f9c/([^/]++)/([^/]++)/([^/]++)/d81f9c(*:9968)' + .')' + .'|2(?' + .'|ddea/([^/]++)/([^/]++)/([^/]++)/d2ddea(*:10020)' + .'|96c1/([^/]++)/([^/]++)/([^/]++)/d296c1(*:10068)' + .')' + .'|0(?' + .'|9bf4/([^/]++)/([^/]++)/([^/]++)/d09bf4(*:10121)' + .'|7e70/([^/]++)/([^/]++)/([^/]++)/d07e70(*:10169)' + .')' + .'|1(?' + .'|f(?' + .'|e17/([^/]++)/([^/]++)/([^/]++)/d1fe17(*:10225)' + .'|491/([^/]++)/([^/]++)/([^/]++)/d1f491(*:10272)' + .'|255/([^/]++)/([^/]++)/([^/]++)/d1f255(*:10319)' + .')' + .'|c38a/([^/]++)/([^/]++)/([^/]++)/d1c38a(*:10368)' + .'|8f65/([^/]++)/([^/]++)/([^/]++)/d18f65(*:10416)' + .')' + .'|a4fb5/([^/]++)/([^/]++)/([^/]++)/da4fb5(*:10466)' + .'|b8e1a/([^/]++)/([^/]++)/([^/]++)/db8e1a(*:10515)' + .'|709f3/([^/]++)/([^/]++)/([^/]++)/d709f3(*:10564)' + .'|c(?' + .'|912a/([^/]++)/([^/]++)/([^/]++)/dc912a(*:10616)' + .'|6a64/([^/]++)/([^/]++)/([^/]++)/dc6a64(*:10664)' + .')' + .'|db306/([^/]++)/([^/]++)/([^/]++)/ddb306(*:10714)' + .')' + .'|/6(?' + .'|5(?' + .'|12bd/([^/]++)/([^/]++)/([^/]++)/6512bd(*:10772)' + .'|b9ee/([^/]++)/([^/]++)/([^/]++)/65b9ee(*:10820)' + .'|ded5/([^/]++)/([^/]++)/([^/]++)/65ded5(*:10868)' + .')' + .'|f(?' + .'|4922/([^/]++)/([^/]++)/([^/]++)/6f4922(*:10921)' + .'|3ef7/([^/]++)/([^/]++)/([^/]++)/6f3ef7(*:10969)' + .'|aa80/([^/]++)/([^/]++)/([^/]++)/6faa80(*:11017)' + .')' + .'|e(?' + .'|a(?' + .'|9ab/([^/]++)/([^/]++)/([^/]++)/6ea9ab(*:11073)' + .'|2ef/([^/]++)/([^/]++)/([^/]++)/6ea2ef(*:11120)' + .')' + .'|cbdd/([^/]++)/([^/]++)/([^/]++)/6ecbdd(*:11169)' + .')' + .'|3(?' + .'|64d3/([^/]++)/([^/]++)/([^/]++)/6364d3(*:11222)' + .'|dc7e/([^/]++)/([^/]++)/([^/]++)/63dc7e(*:11270)' + .'|923f/([^/]++)/([^/]++)/([^/]++)/63923f(*:11318)' + .')' + .'|c(?' + .'|8349/([^/]++)/([^/]++)/([^/]++)/6c8349(*:11371)' + .'|4b76/([^/]++)/([^/]++)/([^/]++)/6c4b76(*:11419)' + .'|dd60/([^/]++)/([^/]++)/([^/]++)/6cdd60(*:11467)' + .'|9882/([^/]++)/([^/]++)/([^/]++)/6c9882(*:11515)' + .'|524f/([^/]++)/([^/]++)/([^/]++)/6c524f(*:11563)' + .')' + .'|7(?' + .'|c6a1/([^/]++)/([^/]++)/([^/]++)/67c6a1(*:11616)' + .'|f7fb/([^/]++)/([^/]++)/([^/]++)/67f7fb(*:11664)' + .')' + .'|42e92/([^/]++)/([^/]++)/([^/]++)/642e92(*:11714)' + .'|6(?' + .'|f041/([^/]++)/([^/]++)/([^/]++)/66f041(*:11766)' + .'|808e/([^/]++)/([^/]++)/([^/]++)/66808e(*:11814)' + .'|3682/([^/]++)/([^/]++)/([^/]++)/663682(*:11862)' + .')' + .'|8(?' + .'|d30a/([^/]++)/([^/]++)/([^/]++)/68d30a(*:11915)' + .'|8396/([^/]++)/([^/]++)/([^/]++)/688396(*:11963)' + .'|5545/([^/]++)/([^/]++)/([^/]++)/685545(*:12011)' + .'|ce19/([^/]++)/([^/]++)/([^/]++)/68ce19(*:12059)' + .')' + .'|9(?' + .'|74ce/([^/]++)/([^/]++)/([^/]++)/6974ce(*:12112)' + .'|8d51/([^/]++)/([^/]++)/([^/]++)/698d51(*:12160)' + .'|adc1/([^/]++)/([^/]++)/([^/]++)/69adc1(*:12208)' + .'|cb3e/([^/]++)/([^/]++)/([^/]++)/69cb3e(*:12256)' + .')' + .'|da(?' + .'|900/([^/]++)/([^/]++)/([^/]++)/6da900(*:12309)' + .'|37d/([^/]++)/([^/]++)/([^/]++)/6da37d(*:12356)' + .')' + .'|21bf6/([^/]++)/([^/]++)/([^/]++)/621bf6(*:12406)' + .'|a9aed/([^/]++)/([^/]++)/([^/]++)/6a9aed(*:12455)' + .')' + .'|/9(?' + .'|b(?' + .'|f31c/([^/]++)/([^/]++)/([^/]++)/9bf31c(*:12513)' + .'|8619/([^/]++)/([^/]++)/([^/]++)/9b8619(*:12561)' + .'|04d1/([^/]++)/([^/]++)/([^/]++)/9b04d1(*:12609)' + .'|e40c/([^/]++)/([^/]++)/([^/]++)/9be40c(*:12657)' + .'|70e8/([^/]++)/([^/]++)/([^/]++)/9b70e8(*:12705)' + .')' + .'|8(?' + .'|f137/([^/]++)/([^/]++)/([^/]++)/98f137(*:12758)' + .'|dce8/([^/]++)/([^/]++)/([^/]++)/98dce8(*:12806)' + .'|72ed/([^/]++)/([^/]++)/([^/]++)/9872ed(*:12854)' + .'|b297/([^/]++)/([^/]++)/([^/]++)/98b297(*:12902)' + .')' + .'|a(?' + .'|1158/([^/]++)/([^/]++)/([^/]++)/9a1158(*:12955)' + .'|9687/([^/]++)/([^/]++)/([^/]++)/9a9687(*:13003)' + .')' + .'|f(?' + .'|6140/([^/]++)/([^/]++)/([^/]++)/9f6140(*:13056)' + .'|c3d7/([^/]++)/([^/]++)/([^/]++)/9fc3d7(*:13104)' + .'|d818/([^/]++)/([^/]++)/([^/]++)/9fd818(*:13152)' + .')' + .'|7(?' + .'|78d5/([^/]++)/([^/]++)/([^/]++)/9778d5(*:13205)' + .'|6652/([^/]++)/([^/]++)/([^/]++)/976652(*:13253)' + .'|9d47/([^/]++)/([^/]++)/([^/]++)/979d47(*:13301)' + .')' + .'|3db85/([^/]++)/([^/]++)/([^/]++)/93db85(*:13351)' + .'|2c(?' + .'|c22/([^/]++)/([^/]++)/([^/]++)/92cc22(*:13403)' + .'|8c9/([^/]++)/([^/]++)/([^/]++)/92c8c9(*:13450)' + .')' + .'|03ce9/([^/]++)/([^/]++)/([^/]++)/903ce9(*:13500)' + .'|6da2f/([^/]++)/([^/]++)/([^/]++)/96da2f(*:13549)' + .'|d(?' + .'|cb88/([^/]++)/([^/]++)/([^/]++)/9dcb88(*:13601)' + .'|fcd5/([^/]++)/([^/]++)/([^/]++)/9dfcd5(*:13649)' + .'|e6d1/([^/]++)/([^/]++)/([^/]++)/9de6d1(*:13697)' + .')' + .'|c(?' + .'|fdf1/([^/]++)/([^/]++)/([^/]++)/9cfdf1(*:13750)' + .'|838d/([^/]++)/([^/]++)/([^/]++)/9c838d(*:13798)' + .')' + .'|18(?' + .'|890/([^/]++)/([^/]++)/([^/]++)/918890(*:13851)' + .'|317/([^/]++)/([^/]++)/([^/]++)/918317(*:13898)' + .')' + .'|4(?' + .'|f6d7/([^/]++)/([^/]++)/([^/]++)/94f6d7(*:13951)' + .'|1e1a/([^/]++)/([^/]++)/([^/]++)/941e1a(*:13999)' + .'|31c8/([^/]++)/([^/]++)/([^/]++)/9431c8(*:14047)' + .'|61cc/([^/]++)/([^/]++)/([^/]++)/9461cc(*:14095)' + .')' + .'|50a41/([^/]++)/([^/]++)/([^/]++)/950a41(*:14145)' + .')' + .'|/7(?' + .'|0(?' + .'|efdf/([^/]++)/([^/]++)/([^/]++)/70efdf(*:14203)' + .'|5f21/([^/]++)/([^/]++)/([^/]++)/705f21(*:14251)' + .'|c639/([^/]++)/([^/]++)/([^/]++)/70c639(*:14299)' + .')' + .'|2b32a/([^/]++)/([^/]++)/([^/]++)/72b32a(*:14349)' + .'|f(?' + .'|39f8/([^/]++)/([^/]++)/([^/]++)/7f39f8(*:14401)' + .'|6ffa/([^/]++)/([^/]++)/([^/]++)/7f6ffa(*:14449)' + .'|1(?' + .'|de2/([^/]++)/([^/]++)/([^/]++)/7f1de2(*:14500)' + .'|00b/([^/]++)/([^/]++)/([^/]++)/7f100b(*:14547)' + .')' + .'|e1f8/([^/]++)/([^/]++)/([^/]++)/7fe1f8(*:14596)' + .')' + .'|3(?' + .'|5b90/([^/]++)/([^/]++)/([^/]++)/735b90(*:14649)' + .'|278a/([^/]++)/([^/]++)/([^/]++)/73278a(*:14697)' + .'|80ad/([^/]++)/([^/]++)/([^/]++)/7380ad(*:14745)' + .')' + .'|cbbc4/([^/]++)/([^/]++)/([^/]++)/7cbbc4(*:14795)' + .'|6(?' + .'|4796/([^/]++)/([^/]++)/([^/]++)/764796(*:14847)' + .'|dc61/([^/]++)/([^/]++)/([^/]++)/76dc61(*:14895)' + .')' + .'|e(?' + .'|f605/([^/]++)/([^/]++)/([^/]++)/7ef605(*:14948)' + .'|7757/([^/]++)/([^/]++)/([^/]++)/7e7757(*:14996)' + .'|a(?' + .'|be3/([^/]++)/([^/]++)/([^/]++)/7eabe3(*:15047)' + .'|cb5/([^/]++)/([^/]++)/([^/]++)/7eacb5(*:15094)' + .')' + .')' + .'|5(?' + .'|7b50/([^/]++)/([^/]++)/([^/]++)/757b50(*:15148)' + .'|8874/([^/]++)/([^/]++)/([^/]++)/758874(*:15196)' + .'|fc09/([^/]++)/([^/]++)/([^/]++)/75fc09(*:15244)' + .')' + .'|4(?' + .'|db12/([^/]++)/([^/]++)/([^/]++)/74db12(*:15297)' + .'|071a/([^/]++)/([^/]++)/([^/]++)/74071a(*:15345)' + .')' + .'|a614f/([^/]++)/([^/]++)/([^/]++)/7a614f(*:15395)' + .'|d04bb/([^/]++)/([^/]++)/([^/]++)/7d04bb(*:15444)' + .')' + .'|/3(?' + .'|c(?' + .'|59dc/([^/]++)/([^/]++)/([^/]++)/3c59dc(*:15502)' + .'|ec07/([^/]++)/([^/]++)/([^/]++)/3cec07(*:15550)' + .'|7781/([^/]++)/([^/]++)/([^/]++)/3c7781(*:15598)' + .'|f166/([^/]++)/([^/]++)/([^/]++)/3cf166(*:15646)' + .')' + .'|7(?' + .'|693c/([^/]++)/([^/]++)/([^/]++)/37693c(*:15699)' + .'|a749/([^/]++)/([^/]++)/([^/]++)/37a749(*:15747)' + .'|bc2f/([^/]++)/([^/]++)/([^/]++)/37bc2f(*:15795)' + .'|1bce/([^/]++)/([^/]++)/([^/]++)/371bce(*:15843)' + .')' + .'|3(?' + .'|e75f/([^/]++)/([^/]++)/([^/]++)/33e75f(*:15896)' + .'|5f53/([^/]++)/([^/]++)/([^/]++)/335f53(*:15944)' + .')' + .'|4(?' + .'|1(?' + .'|73c/([^/]++)/([^/]++)/([^/]++)/34173c(*:16000)' + .'|6a7/([^/]++)/([^/]++)/([^/]++)/3416a7(*:16047)' + .')' + .'|ed06/([^/]++)/([^/]++)/([^/]++)/34ed06(*:16096)' + .')' + .'|2(?' + .'|95c7/([^/]++)/([^/]++)/([^/]++)/3295c7(*:16149)' + .'|bb90/([^/]++)/([^/]++)/([^/]++)/32bb90(*:16197)' + .'|0722/([^/]++)/([^/]++)/([^/]++)/320722(*:16245)' + .')' + .'|5(?' + .'|f4a8/([^/]++)/([^/]++)/([^/]++)/35f4a8(*:16298)' + .'|7a6f/([^/]++)/([^/]++)/([^/]++)/357a6f(*:16346)' + .'|2fe2/([^/]++)/([^/]++)/([^/]++)/352fe2(*:16394)' + .'|0510/([^/]++)/([^/]++)/([^/]++)/350510(*:16442)' + .')' + .'|ef815/([^/]++)/([^/]++)/([^/]++)/3ef815(*:16492)' + .'|8(?' + .'|b3ef/([^/]++)/([^/]++)/([^/]++)/38b3ef(*:16544)' + .'|af86/([^/]++)/([^/]++)/([^/]++)/38af86(*:16592)' + .'|db3a/([^/]++)/([^/]++)/([^/]++)/38db3a(*:16640)' + .')' + .'|d(?' + .'|ef18/([^/]++)/([^/]++)/([^/]++)/3def18(*:16693)' + .'|d48a/([^/]++)/([^/]++)/([^/]++)/3dd48a(*:16741)' + .')' + .'|9(?' + .'|88c7/([^/]++)/([^/]++)/([^/]++)/3988c7(*:16794)' + .'|0597/([^/]++)/([^/]++)/([^/]++)/390597(*:16842)' + .'|461a/([^/]++)/([^/]++)/([^/]++)/39461a(*:16890)' + .')' + .'|6(?' + .'|3663/([^/]++)/([^/]++)/([^/]++)/363663(*:16943)' + .'|44a6/([^/]++)/([^/]++)/([^/]++)/3644a6(*:16991)' + .'|660e/([^/]++)/([^/]++)/([^/]++)/36660e(*:17039)' + .')' + .'|1(?' + .'|fefc/([^/]++)/([^/]++)/([^/]++)/31fefc(*:17092)' + .'|0dcb/([^/]++)/([^/]++)/([^/]++)/310dcb(*:17140)' + .')' + .'|b8a61/([^/]++)/([^/]++)/([^/]++)/3b8a61(*:17190)' + .'|fe94a/([^/]++)/([^/]++)/([^/]++)/3fe94a(*:17239)' + .'|ad7c2/([^/]++)/([^/]++)/([^/]++)/3ad7c2(*:17288)' + .')' + .'|/b(?' + .'|6(?' + .'|d767/([^/]++)/([^/]++)/([^/]++)/b6d767(*:17346)' + .'|f047/([^/]++)/([^/]++)/([^/]++)/b6f047(*:17394)' + .')' + .'|53(?' + .'|b3a/([^/]++)/([^/]++)/([^/]++)/b53b3a(*:17447)' + .'|4ba/([^/]++)/([^/]++)/([^/]++)/b534ba(*:17494)' + .')' + .'|3(?' + .'|e3e3/([^/]++)/([^/]++)/([^/]++)/b3e3e3(*:17547)' + .'|967a/([^/]++)/([^/]++)/([^/]++)/b3967a(*:17595)' + .')' + .'|7(?' + .'|3ce3/([^/]++)/([^/]++)/([^/]++)/b73ce3(*:17648)' + .'|b16e/([^/]++)/([^/]++)/([^/]++)/b7b16e(*:17696)' + .')' + .'|d(?' + .'|4c9a/([^/]++)/([^/]++)/([^/]++)/bd4c9a(*:17749)' + .'|686f/([^/]++)/([^/]++)/([^/]++)/bd686f(*:17797)' + .')' + .'|f8229/([^/]++)/([^/]++)/([^/]++)/bf8229(*:17847)' + .'|1(?' + .'|d10e/([^/]++)/([^/]++)/([^/]++)/b1d10e(*:17899)' + .'|a59b/([^/]++)/([^/]++)/([^/]++)/b1a59b(*:17947)' + .')' + .'|c(?' + .'|be33/([^/]++)/([^/]++)/([^/]++)/bcbe33(*:18000)' + .'|6dc4/([^/]++)/([^/]++)/([^/]++)/bc6dc4(*:18048)' + .'|a82e/([^/]++)/([^/]++)/([^/]++)/bca82e(*:18096)' + .')' + .'|e(?' + .'|83ab/([^/]++)/([^/]++)/([^/]++)/be83ab(*:18149)' + .'|ed13/([^/]++)/([^/]++)/([^/]++)/beed13(*:18197)' + .')' + .'|2eb73/([^/]++)/([^/]++)/([^/]++)/b2eb73(*:18247)' + .'|83aac/([^/]++)/([^/]++)/([^/]++)/b83aac(*:18296)' + .'|ac916/([^/]++)/([^/]++)/([^/]++)/bac916(*:18345)' + .'|b(?' + .'|f94b/([^/]++)/([^/]++)/([^/]++)/bbf94b(*:18397)' + .'|cbff/([^/]++)/([^/]++)/([^/]++)/bbcbff(*:18445)' + .')' + .'|9228e/([^/]++)/([^/]++)/([^/]++)/b9228e(*:18495)' + .')' + .'|/0(?' + .'|2(?' + .'|e74f/([^/]++)/([^/]++)/([^/]++)/02e74f(*:18553)' + .'|522a/([^/]++)/([^/]++)/([^/]++)/02522a(*:18601)' + .'|66e3/([^/]++)/([^/]++)/([^/]++)/0266e3(*:18649)' + .')' + .'|9(?' + .'|3f65/([^/]++)/([^/]++)/([^/]++)/093f65(*:18702)' + .'|1d58/([^/]++)/([^/]++)/([^/]++)/091d58(*:18750)' + .')' + .'|7(?' + .'|2b03/([^/]++)/([^/]++)/([^/]++)/072b03(*:18803)' + .'|e1cd/([^/]++)/([^/]++)/([^/]++)/07e1cd(*:18851)' + .'|7(?' + .'|7d5/([^/]++)/([^/]++)/([^/]++)/0777d5(*:18902)' + .'|e29/([^/]++)/([^/]++)/([^/]++)/077e29(*:18949)' + .')' + .'|cdfd/([^/]++)/([^/]++)/([^/]++)/07cdfd(*:18998)' + .')' + .'|3(?' + .'|afdb/([^/]++)/([^/]++)/([^/]++)/03afdb(*:19051)' + .'|36dc/([^/]++)/([^/]++)/([^/]++)/0336dc(*:19099)' + .'|c6b0/([^/]++)/([^/]++)/([^/]++)/03c6b0(*:19147)' + .'|53ab/([^/]++)/([^/]++)/([^/]++)/0353ab(*:19195)' + .')' + .'|6(?' + .'|9059/([^/]++)/([^/]++)/([^/]++)/069059(*:19248)' + .'|4096/([^/]++)/([^/]++)/([^/]++)/064096(*:19296)' + .'|0ad9/([^/]++)/([^/]++)/([^/]++)/060ad9(*:19344)' + .'|138b/([^/]++)/([^/]++)/([^/]++)/06138b(*:19392)' + .'|eb61/([^/]++)/([^/]++)/([^/]++)/06eb61(*:19440)' + .')' + .'|1(?' + .'|3(?' + .'|d40/([^/]++)/([^/]++)/([^/]++)/013d40(*:19496)' + .'|86b/([^/]++)/([^/]++)/([^/]++)/01386b(*:19543)' + .')' + .'|161a/([^/]++)/([^/]++)/([^/]++)/01161a(*:19592)' + .'|9d38/([^/]++)/([^/]++)/([^/]++)/019d38(*:19640)' + .')' + .'|f(?' + .'|28b5/([^/]++)/([^/]++)/([^/]++)/0f28b5(*:19693)' + .'|49c8/([^/]++)/([^/]++)/([^/]++)/0f49c8(*:19741)' + .')' + .'|a(?' + .'|09c8/([^/]++)/([^/]++)/([^/]++)/0a09c8(*:19794)' + .'|a188/([^/]++)/([^/]++)/([^/]++)/0aa188(*:19842)' + .')' + .'|0(?' + .'|6f52/([^/]++)/([^/]++)/([^/]++)/006f52(*:19895)' + .'|4114/([^/]++)/([^/]++)/([^/]++)/004114(*:19943)' + .'|ec53/([^/]++)/([^/]++)/([^/]++)/00ec53(*:19991)' + .')' + .'|4(?' + .'|5117/([^/]++)/([^/]++)/([^/]++)/045117(*:20044)' + .'|0259/([^/]++)/([^/]++)/([^/]++)/040259(*:20092)' + .')' + .'|84b6f/([^/]++)/([^/]++)/([^/]++)/084b6f(*:20142)' + .'|e(?' + .'|6597/([^/]++)/([^/]++)/([^/]++)/0e6597(*:20194)' + .'|0193/([^/]++)/([^/]++)/([^/]++)/0e0193(*:20242)' + .')' + .'|bb4ae/([^/]++)/([^/]++)/([^/]++)/0bb4ae(*:20292)' + .'|5(?' + .'|049e/([^/]++)/([^/]++)/([^/]++)/05049e(*:20344)' + .'|84ce/([^/]++)/([^/]++)/([^/]++)/0584ce(*:20392)' + .'|f971/([^/]++)/([^/]++)/([^/]++)/05f971(*:20440)' + .')' + .'|c74b7/([^/]++)/([^/]++)/([^/]++)/0c74b7(*:20490)' + .'|d(?' + .'|0fd7/([^/]++)/([^/]++)/([^/]++)/0d0fd7(*:20542)' + .'|eb1c/([^/]++)/([^/]++)/([^/]++)/0deb1c(*:20590)' + .')' + .')' + .'|/f(?' + .'|7(?' + .'|1(?' + .'|771/([^/]++)/([^/]++)/([^/]++)/f71771(*:20652)' + .'|849/([^/]++)/([^/]++)/([^/]++)/f71849(*:20699)' + .')' + .'|e6c8/([^/]++)/([^/]++)/([^/]++)/f7e6c8(*:20748)' + .'|6640/([^/]++)/([^/]++)/([^/]++)/f76640(*:20796)' + .'|3b76/([^/]++)/([^/]++)/([^/]++)/f73b76(*:20844)' + .'|4909/([^/]++)/([^/]++)/([^/]++)/f74909(*:20892)' + .'|70b6/([^/]++)/([^/]++)/([^/]++)/f770b6(*:20940)' + .')' + .'|4(?' + .'|57c5/([^/]++)/([^/]++)/([^/]++)/f457c5(*:20993)' + .'|b9ec/([^/]++)/([^/]++)/([^/]++)/f4b9ec(*:21041)' + .'|f6dc/([^/]++)/([^/]++)/([^/]++)/f4f6dc(*:21089)' + .')' + .'|c(?' + .'|490c/([^/]++)/([^/]++)/([^/]++)/fc490c(*:21142)' + .'|2213/([^/]++)/([^/]++)/([^/]++)/fc2213(*:21190)' + .'|cb60/([^/]++)/([^/]++)/([^/]++)/fccb60(*:21238)' + .')' + .'|b(?' + .'|d793/([^/]++)/([^/]++)/([^/]++)/fbd793(*:21291)' + .'|7b9f/([^/]++)/([^/]++)/([^/]++)/fb7b9f(*:21339)' + .')' + .'|0(?' + .'|33ab/([^/]++)/([^/]++)/([^/]++)/f033ab(*:21392)' + .'|935e/([^/]++)/([^/]++)/([^/]++)/f0935e(*:21440)' + .')' + .'|e(?' + .'|9fc2/([^/]++)/([^/]++)/([^/]++)/fe9fc2(*:21493)' + .'|131d/([^/]++)/([^/]++)/([^/]++)/fe131d(*:21541)' + .'|73f6/([^/]++)/([^/]++)/([^/]++)/fe73f6(*:21589)' + .')' + .'|8(?' + .'|9913/([^/]++)/([^/]++)/([^/]++)/f89913(*:21642)' + .'|c1f2/([^/]++)/([^/]++)/([^/]++)/f8c1f2(*:21690)' + .'|5454/([^/]++)/([^/]++)/([^/]++)/f85454(*:21738)' + .')' + .'|2(?' + .'|2170/([^/]++)/([^/]++)/([^/]++)/f22170(*:21791)' + .'|fc99/([^/]++)/([^/]++)/([^/]++)/f2fc99(*:21839)' + .')' + .'|a(?' + .'|7cdf/([^/]++)/([^/]++)/([^/]++)/fa7cdf(*:21892)' + .'|a9af/([^/]++)/([^/]++)/([^/]++)/faa9af(*:21940)' + .')' + .'|340f1/([^/]++)/([^/]++)/([^/]++)/f340f1(*:21990)' + .'|9(?' + .'|0f2a/([^/]++)/([^/]++)/([^/]++)/f90f2a(*:22042)' + .'|b902/([^/]++)/([^/]++)/([^/]++)/f9b902(*:22090)' + .')' + .'|fd52f/([^/]++)/([^/]++)/([^/]++)/ffd52f(*:22140)' + .'|61d69/([^/]++)/([^/]++)/([^/]++)/f61d69(*:22189)' + .'|5f859/([^/]++)/([^/]++)/([^/]++)/f5f859(*:22238)' + .'|1b6f2/([^/]++)/([^/]++)/([^/]++)/f1b6f2(*:22287)' + .')' + .'|/2(?' + .'|8(?' + .'|3802/([^/]++)/([^/]++)/([^/]++)/283802(*:22345)' + .'|dd2c/([^/]++)/([^/]++)/([^/]++)/28dd2c(*:22393)' + .'|9dff/([^/]++)/([^/]++)/([^/]++)/289dff(*:22441)' + .'|f0b8/([^/]++)/([^/]++)/([^/]++)/28f0b8(*:22489)' + .')' + .'|a(?' + .'|38a4/([^/]++)/([^/]++)/([^/]++)/2a38a4(*:22542)' + .'|79ea/([^/]++)/([^/]++)/([^/]++)/2a79ea(*:22590)' + .')' + .'|6(?' + .'|657d/([^/]++)/([^/]++)/([^/]++)/26657d(*:22643)' + .'|e359/([^/]++)/([^/]++)/([^/]++)/26e359(*:22691)' + .'|3373/([^/]++)/([^/]++)/([^/]++)/263373(*:22739)' + .')' + .'|7(?' + .'|23d0/([^/]++)/([^/]++)/([^/]++)/2723d0(*:22792)' + .'|4ad4/([^/]++)/([^/]++)/([^/]++)/274ad4(*:22840)' + .')' + .'|b(?' + .'|4492/([^/]++)/([^/]++)/([^/]++)/2b4492(*:22893)' + .'|24d4/([^/]++)/([^/]++)/([^/]++)/2b24d4(*:22941)' + .')' + .'|0(?' + .'|2cb9/([^/]++)/([^/]++)/([^/]++)/202cb9(*:22994)' + .'|f075/([^/]++)/([^/]++)/([^/]++)/20f075(*:23042)' + .'|50e0/([^/]++)/([^/]++)/([^/]++)/2050e0(*:23090)' + .')' + .'|f(?' + .'|2b26/([^/]++)/([^/]++)/([^/]++)/2f2b26(*:23143)' + .'|5570/([^/]++)/([^/]++)/([^/]++)/2f5570(*:23191)' + .')' + .'|4(?' + .'|b16f/([^/]++)/([^/]++)/([^/]++)/24b16f(*:23244)' + .'|8e84/([^/]++)/([^/]++)/([^/]++)/248e84(*:23292)' + .'|21fc/([^/]++)/([^/]++)/([^/]++)/2421fc(*:23340)' + .')' + .'|5(?' + .'|b282/([^/]++)/([^/]++)/([^/]++)/25b282(*:23393)' + .'|0cf8/([^/]++)/([^/]++)/([^/]++)/250cf8(*:23441)' + .'|ddc0/([^/]++)/([^/]++)/([^/]++)/25ddc0(*:23489)' + .')' + .'|18a0a/([^/]++)/([^/]++)/([^/]++)/218a0a(*:23539)' + .')' + .'|/5(?' + .'|4229a/([^/]++)/([^/]++)/([^/]++)/54229a(*:23594)' + .'|f(?' + .'|93f9/([^/]++)/([^/]++)/([^/]++)/5f93f9(*:23646)' + .'|d0b3/([^/]++)/([^/]++)/([^/]++)/5fd0b3(*:23694)' + .')' + .'|ef(?' + .'|0(?' + .'|59/([^/]++)/([^/]++)/([^/]++)/5ef059(*:23750)' + .'|b4/([^/]++)/([^/]++)/([^/]++)/5ef0b4(*:23796)' + .')' + .'|698/([^/]++)/([^/]++)/([^/]++)/5ef698(*:23844)' + .')' + .'|8(?' + .'|78a7/([^/]++)/([^/]++)/([^/]++)/5878a7(*:23897)' + .'|a2fc/([^/]++)/([^/]++)/([^/]++)/58a2fc(*:23945)' + .'|238e/([^/]++)/([^/]++)/([^/]++)/58238e(*:23993)' + .')' + .'|7(?' + .'|aeee/([^/]++)/([^/]++)/([^/]++)/57aeee(*:24046)' + .'|7(?' + .'|ef1/([^/]++)/([^/]++)/([^/]++)/577ef1(*:24097)' + .'|bcc/([^/]++)/([^/]++)/([^/]++)/577bcc(*:24144)' + .')' + .'|37c6/([^/]++)/([^/]++)/([^/]++)/5737c6(*:24193)' + .')' + .'|3(?' + .'|9fd5/([^/]++)/([^/]++)/([^/]++)/539fd5(*:24246)' + .'|c3bc/([^/]++)/([^/]++)/([^/]++)/53c3bc(*:24294)' + .')' + .'|5(?' + .'|5d67/([^/]++)/([^/]++)/([^/]++)/555d67(*:24347)' + .'|0a14/([^/]++)/([^/]++)/([^/]++)/550a14(*:24395)' + .'|9cb9/([^/]++)/([^/]++)/([^/]++)/559cb9(*:24443)' + .'|a7cf/([^/]++)/([^/]++)/([^/]++)/55a7cf(*:24491)' + .')' + .'|02e4a/([^/]++)/([^/]++)/([^/]++)/502e4a(*:24541)' + .'|b8add/([^/]++)/([^/]++)/([^/]++)/5b8add(*:24590)' + .'|2720e/([^/]++)/([^/]++)/([^/]++)/52720e(*:24639)' + .'|a4b25/([^/]++)/([^/]++)/([^/]++)/5a4b25(*:24688)' + .'|1d92b/([^/]++)/([^/]++)/([^/]++)/51d92b(*:24737)' + .'|98b3e/([^/]++)/([^/]++)/([^/]++)/598b3e(*:24786)' + .')' + .')/?$}sD', + 24786 => '{^(?' + .'|/5(?' + .'|b69b9/([^/]++)/([^/]++)/([^/]++)/5b69b9(*:24837)' + .'|9(?' + .'|b90e/([^/]++)/([^/]++)/([^/]++)/59b90e(*:24889)' + .'|c330/([^/]++)/([^/]++)/([^/]++)/59c330(*:24937)' + .')' + .'|3(?' + .'|fde9/([^/]++)/([^/]++)/([^/]++)/53fde9(*:24990)' + .'|e3a7/([^/]++)/([^/]++)/([^/]++)/53e3a7(*:25038)' + .')' + .'|e(?' + .'|a164/([^/]++)/([^/]++)/([^/]++)/5ea164(*:25091)' + .'|3881/([^/]++)/([^/]++)/([^/]++)/5e3881(*:25139)' + .'|9f92/([^/]++)/([^/]++)/([^/]++)/5e9f92(*:25187)' + .'|c91a/([^/]++)/([^/]++)/([^/]++)/5ec91a(*:25235)' + .')' + .'|7(?' + .'|3703/([^/]++)/([^/]++)/([^/]++)/573703(*:25288)' + .'|51ec/([^/]++)/([^/]++)/([^/]++)/5751ec(*:25336)' + .'|05e1/([^/]++)/([^/]++)/([^/]++)/5705e1(*:25384)' + .')' + .'|8(?' + .'|ae74/([^/]++)/([^/]++)/([^/]++)/58ae74(*:25437)' + .'|d4d1/([^/]++)/([^/]++)/([^/]++)/58d4d1(*:25485)' + .'|07a6/([^/]++)/([^/]++)/([^/]++)/5807a6(*:25533)' + .'|e4d4/([^/]++)/([^/]++)/([^/]++)/58e4d4(*:25581)' + .')' + .'|d(?' + .'|44ee/([^/]++)/([^/]++)/([^/]++)/5d44ee(*:25634)' + .'|d9db/([^/]++)/([^/]++)/([^/]++)/5dd9db(*:25682)' + .')' + .'|5(?' + .'|b37c/([^/]++)/([^/]++)/([^/]++)/55b37c(*:25735)' + .'|743c/([^/]++)/([^/]++)/([^/]++)/55743c(*:25783)' + .'|6f39/([^/]++)/([^/]++)/([^/]++)/556f39(*:25831)' + .')' + .'|c(?' + .'|0492/([^/]++)/([^/]++)/([^/]++)/5c0492(*:25884)' + .'|572e/([^/]++)/([^/]++)/([^/]++)/5c572e(*:25932)' + .'|9362/([^/]++)/([^/]++)/([^/]++)/5c9362(*:25980)' + .')' + .'|4(?' + .'|8731/([^/]++)/([^/]++)/([^/]++)/548731(*:26033)' + .'|a367/([^/]++)/([^/]++)/([^/]++)/54a367(*:26081)' + .')' + .'|0(?' + .'|0e75/([^/]++)/([^/]++)/([^/]++)/500e75(*:26134)' + .'|c3d7/([^/]++)/([^/]++)/([^/]++)/50c3d7(*:26182)' + .')' + .'|f(?' + .'|2c22/([^/]++)/([^/]++)/([^/]++)/5f2c22(*:26235)' + .'|0f5e/([^/]++)/([^/]++)/([^/]++)/5f0f5e(*:26283)' + .')' + .'|1ef18/([^/]++)/([^/]++)/([^/]++)/51ef18(*:26333)' + .')' + .'|/b(?' + .'|5(?' + .'|b41f/([^/]++)/([^/]++)/([^/]++)/b5b41f(*:26391)' + .'|dc4e/([^/]++)/([^/]++)/([^/]++)/b5dc4e(*:26439)' + .'|6a18/([^/]++)/([^/]++)/([^/]++)/b56a18(*:26487)' + .'|5ec2/([^/]++)/([^/]++)/([^/]++)/b55ec2(*:26535)' + .')' + .'|337e8/([^/]++)/([^/]++)/([^/]++)/b337e8(*:26585)' + .'|a(?' + .'|2fd3/([^/]++)/([^/]++)/([^/]++)/ba2fd3(*:26637)' + .'|3866/([^/]++)/([^/]++)/([^/]++)/ba3866(*:26685)' + .')' + .'|2(?' + .'|eeb7/([^/]++)/([^/]++)/([^/]++)/b2eeb7(*:26738)' + .'|f627/([^/]++)/([^/]++)/([^/]++)/b2f627(*:26786)' + .')' + .'|7(?' + .'|3dfe/([^/]++)/([^/]++)/([^/]++)/b73dfe(*:26839)' + .'|bb35/([^/]++)/([^/]++)/([^/]++)/b7bb35(*:26887)' + .'|ee6f/([^/]++)/([^/]++)/([^/]++)/b7ee6f(*:26935)' + .'|892f/([^/]++)/([^/]++)/([^/]++)/b7892f(*:26983)' + .'|0683/([^/]++)/([^/]++)/([^/]++)/b70683(*:27031)' + .')' + .'|4(?' + .'|288d/([^/]++)/([^/]++)/([^/]++)/b4288d(*:27084)' + .'|a528/([^/]++)/([^/]++)/([^/]++)/b4a528(*:27132)' + .')' + .'|e(?' + .'|3159/([^/]++)/([^/]++)/([^/]++)/be3159(*:27185)' + .'|b22f/([^/]++)/([^/]++)/([^/]++)/beb22f(*:27233)' + .'|a595/([^/]++)/([^/]++)/([^/]++)/bea595(*:27281)' + .')' + .'|1(?' + .'|eec3/([^/]++)/([^/]++)/([^/]++)/b1eec3(*:27334)' + .'|37fd/([^/]++)/([^/]++)/([^/]++)/b137fd(*:27382)' + .')' + .'|0(?' + .'|56eb/([^/]++)/([^/]++)/([^/]++)/b056eb(*:27435)' + .'|b183/([^/]++)/([^/]++)/([^/]++)/b0b183(*:27483)' + .')' + .'|f6276/([^/]++)/([^/]++)/([^/]++)/bf6276(*:27533)' + .'|6(?' + .'|edc1/([^/]++)/([^/]++)/([^/]++)/b6edc1(*:27585)' + .'|a108/([^/]++)/([^/]++)/([^/]++)/b6a108(*:27633)' + .')' + .'|86e8d/([^/]++)/([^/]++)/([^/]++)/b86e8d(*:27683)' + .')' + .'|/2(?' + .'|8(?' + .'|5e19/([^/]++)/([^/]++)/([^/]++)/285e19(*:27741)' + .'|2(?' + .'|3f4/([^/]++)/([^/]++)/([^/]++)/2823f4(*:27792)' + .'|67a/([^/]++)/([^/]++)/([^/]++)/28267a(*:27839)' + .')' + .'|8cc0/([^/]++)/([^/]++)/([^/]++)/288cc0(*:27888)' + .'|7e03/([^/]++)/([^/]++)/([^/]++)/287e03(*:27936)' + .')' + .'|d(?' + .'|6cc4/([^/]++)/([^/]++)/([^/]++)/2d6cc4(*:27989)' + .'|ea61/([^/]++)/([^/]++)/([^/]++)/2dea61(*:28037)' + .'|ace7/([^/]++)/([^/]++)/([^/]++)/2dace7(*:28085)' + .')' + .'|b(?' + .'|8a61/([^/]++)/([^/]++)/([^/]++)/2b8a61(*:28138)' + .'|b232/([^/]++)/([^/]++)/([^/]++)/2bb232(*:28186)' + .'|a596/([^/]++)/([^/]++)/([^/]++)/2ba596(*:28234)' + .'|cab9/([^/]++)/([^/]++)/([^/]++)/2bcab9(*:28282)' + .')' + .'|9(?' + .'|8f95/([^/]++)/([^/]++)/([^/]++)/298f95(*:28335)' + .'|1597/([^/]++)/([^/]++)/([^/]++)/291597(*:28383)' + .')' + .'|58be1/([^/]++)/([^/]++)/([^/]++)/258be1(*:28433)' + .'|3(?' + .'|3509/([^/]++)/([^/]++)/([^/]++)/233509(*:28485)' + .'|ce18/([^/]++)/([^/]++)/([^/]++)/23ce18(*:28533)' + .')' + .'|6(?' + .'|dd0d/([^/]++)/([^/]++)/([^/]++)/26dd0d(*:28586)' + .'|408f/([^/]++)/([^/]++)/([^/]++)/26408f(*:28634)' + .')' + .'|f(?' + .'|37d1/([^/]++)/([^/]++)/([^/]++)/2f37d1(*:28687)' + .'|885d/([^/]++)/([^/]++)/([^/]++)/2f885d(*:28735)' + .')' + .'|2(?' + .'|91d2/([^/]++)/([^/]++)/([^/]++)/2291d2(*:28788)' + .'|ac3c/([^/]++)/([^/]++)/([^/]++)/22ac3c(*:28836)' + .'|fb0c/([^/]++)/([^/]++)/([^/]++)/22fb0c(*:28884)' + .')' + .'|4(?' + .'|6819/([^/]++)/([^/]++)/([^/]++)/246819(*:28937)' + .'|896e/([^/]++)/([^/]++)/([^/]++)/24896e(*:28985)' + .')' + .'|a(?' + .'|fe45/([^/]++)/([^/]++)/([^/]++)/2afe45(*:29038)' + .'|084e/([^/]++)/([^/]++)/([^/]++)/2a084e(*:29086)' + .'|9d12/([^/]++)/([^/]++)/([^/]++)/2a9d12(*:29134)' + .'|b564/([^/]++)/([^/]++)/([^/]++)/2ab564(*:29182)' + .')' + .'|1(?' + .'|7eed/([^/]++)/([^/]++)/([^/]++)/217eed(*:29235)' + .'|0f76/([^/]++)/([^/]++)/([^/]++)/210f76(*:29283)' + .')' + .'|e65f2/([^/]++)/([^/]++)/([^/]++)/2e65f2(*:29333)' + .'|ca65f/([^/]++)/([^/]++)/([^/]++)/2ca65f(*:29382)' + .'|0aee3/([^/]++)/([^/]++)/([^/]++)/20aee3(*:29431)' + .')' + .'|/e(?' + .'|8(?' + .'|c065/([^/]++)/([^/]++)/([^/]++)/e8c065(*:29489)' + .'|20a4/([^/]++)/([^/]++)/([^/]++)/e820a4(*:29537)' + .')' + .'|2(?' + .'|230b/([^/]++)/([^/]++)/([^/]++)/e2230b(*:29590)' + .'|a2dc/([^/]++)/([^/]++)/([^/]++)/e2a2dc(*:29638)' + .'|05ee/([^/]++)/([^/]++)/([^/]++)/e205ee(*:29686)' + .')' + .'|b(?' + .'|d962/([^/]++)/([^/]++)/([^/]++)/ebd962(*:29739)' + .'|6fdc/([^/]++)/([^/]++)/([^/]++)/eb6fdc(*:29787)' + .')' + .'|d(?' + .'|265b/([^/]++)/([^/]++)/([^/]++)/ed265b(*:29840)' + .'|fbe1/([^/]++)/([^/]++)/([^/]++)/edfbe1(*:29888)' + .'|e7e2/([^/]++)/([^/]++)/([^/]++)/ede7e2(*:29936)' + .')' + .'|6(?' + .'|b4b2/([^/]++)/([^/]++)/([^/]++)/e6b4b2(*:29989)' + .'|cb2a/([^/]++)/([^/]++)/([^/]++)/e6cb2a(*:30037)' + .')' + .'|5(?' + .'|f6ad/([^/]++)/([^/]++)/([^/]++)/e5f6ad(*:30090)' + .'|55eb/([^/]++)/([^/]++)/([^/]++)/e555eb(*:30138)' + .'|841d/([^/]++)/([^/]++)/([^/]++)/e5841d(*:30186)' + .'|7c6b/([^/]++)/([^/]++)/([^/]++)/e57c6b(*:30234)' + .')' + .'|aae33/([^/]++)/([^/]++)/([^/]++)/eaae33(*:30284)' + .'|4(?' + .'|bb4c/([^/]++)/([^/]++)/([^/]++)/e4bb4c(*:30336)' + .'|9b8b/([^/]++)/([^/]++)/([^/]++)/e49b8b(*:30384)' + .')' + .'|7(?' + .'|0611/([^/]++)/([^/]++)/([^/]++)/e70611(*:30437)' + .'|f8a7/([^/]++)/([^/]++)/([^/]++)/e7f8a7(*:30485)' + .'|44f9/([^/]++)/([^/]++)/([^/]++)/e744f9(*:30533)' + .')' + .'|9(?' + .'|95f9/([^/]++)/([^/]++)/([^/]++)/e995f9(*:30586)' + .'|4550/([^/]++)/([^/]++)/([^/]++)/e94550(*:30634)' + .'|7ee2/([^/]++)/([^/]++)/([^/]++)/e97ee2(*:30682)' + .')' + .'|e(?' + .'|fc9e/([^/]++)/([^/]++)/([^/]++)/eefc9e(*:30735)' + .'|b69a/([^/]++)/([^/]++)/([^/]++)/eeb69a(*:30783)' + .')' + .'|0(?' + .'|7413/([^/]++)/([^/]++)/([^/]++)/e07413(*:30836)' + .'|cf1f/([^/]++)/([^/]++)/([^/]++)/e0cf1f(*:30884)' + .'|ec45/([^/]++)/([^/]++)/([^/]++)/e0ec45(*:30932)' + .')' + .'|f4e3b/([^/]++)/([^/]++)/([^/]++)/ef4e3b(*:30982)' + .'|c5aa0/([^/]++)/([^/]++)/([^/]++)/ec5aa0(*:31031)' + .')' + .'|/f(?' + .'|f(?' + .'|4d5f/([^/]++)/([^/]++)/([^/]++)/ff4d5f(*:31089)' + .'|eabd/([^/]++)/([^/]++)/([^/]++)/ffeabd(*:31137)' + .')' + .'|3(?' + .'|f27a/([^/]++)/([^/]++)/([^/]++)/f3f27a(*:31190)' + .'|8762/([^/]++)/([^/]++)/([^/]++)/f38762(*:31238)' + .')' + .'|4(?' + .'|be00/([^/]++)/([^/]++)/([^/]++)/f4be00(*:31291)' + .'|5526/([^/]++)/([^/]++)/([^/]++)/f45526(*:31339)' + .'|7d0a/([^/]++)/([^/]++)/([^/]++)/f47d0a(*:31387)' + .')' + .'|0(?' + .'|e52b/([^/]++)/([^/]++)/([^/]++)/f0e52b(*:31440)' + .'|adc8/([^/]++)/([^/]++)/([^/]++)/f0adc8(*:31488)' + .')' + .'|de926/([^/]++)/([^/]++)/([^/]++)/fde926(*:31538)' + .'|5(?' + .'|deae/([^/]++)/([^/]++)/([^/]++)/f5deae(*:31590)' + .'|7a2f/([^/]++)/([^/]++)/([^/]++)/f57a2f(*:31638)' + .')' + .'|7(?' + .'|6a89/([^/]++)/([^/]++)/([^/]++)/f76a89(*:31691)' + .'|9921/([^/]++)/([^/]++)/([^/]++)/f79921(*:31739)' + .'|e905/([^/]++)/([^/]++)/([^/]++)/f7e905(*:31787)' + .')' + .'|2(?' + .'|9c21/([^/]++)/([^/]++)/([^/]++)/f29c21(*:31840)' + .'|201f/([^/]++)/([^/]++)/([^/]++)/f2201f(*:31888)' + .')' + .'|a(?' + .'|e0b2/([^/]++)/([^/]++)/([^/]++)/fae0b2(*:31941)' + .'|14d4/([^/]++)/([^/]++)/([^/]++)/fa14d4(*:31989)' + .'|3a3c/([^/]++)/([^/]++)/([^/]++)/fa3a3c(*:32037)' + .'|83a1/([^/]++)/([^/]++)/([^/]++)/fa83a1(*:32085)' + .')' + .'|c(?' + .'|cb3c/([^/]++)/([^/]++)/([^/]++)/fccb3c(*:32138)' + .'|8001/([^/]++)/([^/]++)/([^/]++)/fc8001(*:32186)' + .'|3cf4/([^/]++)/([^/]++)/([^/]++)/fc3cf4(*:32234)' + .'|4930/([^/]++)/([^/]++)/([^/]++)/fc4930(*:32282)' + .')' + .'|64eac/([^/]++)/([^/]++)/([^/]++)/f64eac(*:32332)' + .'|b8970/([^/]++)/([^/]++)/([^/]++)/fb8970(*:32381)' + .'|1c159/([^/]++)/([^/]++)/([^/]++)/f1c159(*:32430)' + .'|9(?' + .'|028f/([^/]++)/([^/]++)/([^/]++)/f9028f(*:32482)' + .'|a40a/([^/]++)/([^/]++)/([^/]++)/f9a40a(*:32530)' + .')' + .'|e(?' + .'|8c15/([^/]++)/([^/]++)/([^/]++)/fe8c15(*:32583)' + .'|c8d4/([^/]++)/([^/]++)/([^/]++)/fec8d4(*:32631)' + .'|7ee8/([^/]++)/([^/]++)/([^/]++)/fe7ee8(*:32679)' + .')' + .')' + .'|/3(?' + .'|8(?' + .'|9(?' + .'|bc7/([^/]++)/([^/]++)/([^/]++)/389bc7(*:32741)' + .'|13e/([^/]++)/([^/]++)/([^/]++)/38913e(*:32788)' + .')' + .'|71bd/([^/]++)/([^/]++)/([^/]++)/3871bd(*:32837)' + .')' + .'|d(?' + .'|c487/([^/]++)/([^/]++)/([^/]++)/3dc487(*:32890)' + .'|2d8c/([^/]++)/([^/]++)/([^/]++)/3d2d8c(*:32938)' + .'|8e28/([^/]++)/([^/]++)/([^/]++)/3d8e28(*:32986)' + .'|f1d4/([^/]++)/([^/]++)/([^/]++)/3df1d4(*:33034)' + .')' + .'|7f0e8/([^/]++)/([^/]++)/([^/]++)/37f0e8(*:33084)' + .'|3(?' + .'|e807/([^/]++)/([^/]++)/([^/]++)/33e807(*:33136)' + .'|28bd/([^/]++)/([^/]++)/([^/]++)/3328bd(*:33184)' + .')' + .'|a(?' + .'|0(?' + .'|772/([^/]++)/([^/]++)/([^/]++)/3a0772(*:33240)' + .'|66b/([^/]++)/([^/]++)/([^/]++)/3a066b(*:33287)' + .')' + .'|835d/([^/]++)/([^/]++)/([^/]++)/3a835d(*:33336)' + .')' + .'|0(?' + .'|bb38/([^/]++)/([^/]++)/([^/]++)/30bb38(*:33389)' + .'|3ed4/([^/]++)/([^/]++)/([^/]++)/303ed4(*:33437)' + .'|ef30/([^/]++)/([^/]++)/([^/]++)/30ef30(*:33485)' + .'|1ad0/([^/]++)/([^/]++)/([^/]++)/301ad0(*:33533)' + .')' + .'|4(?' + .'|9389/([^/]++)/([^/]++)/([^/]++)/349389(*:33586)' + .'|35c3/([^/]++)/([^/]++)/([^/]++)/3435c3(*:33634)' + .')' + .'|62(?' + .'|1f1/([^/]++)/([^/]++)/([^/]++)/3621f1(*:33687)' + .'|e80/([^/]++)/([^/]++)/([^/]++)/362e80(*:33734)' + .')' + .'|5(?' + .'|cf86/([^/]++)/([^/]++)/([^/]++)/35cf86(*:33787)' + .'|2407/([^/]++)/([^/]++)/([^/]++)/352407(*:33835)' + .')' + .'|2b30a/([^/]++)/([^/]++)/([^/]++)/32b30a(*:33885)' + .'|1839b/([^/]++)/([^/]++)/([^/]++)/31839b(*:33934)' + .'|b(?' + .'|5dca/([^/]++)/([^/]++)/([^/]++)/3b5dca(*:33986)' + .'|3dba/([^/]++)/([^/]++)/([^/]++)/3b3dba(*:34034)' + .')' + .'|e89eb/([^/]++)/([^/]++)/([^/]++)/3e89eb(*:34084)' + .'|cef96/([^/]++)/([^/]++)/([^/]++)/3cef96(*:34133)' + .')' + .'|/0(?' + .'|8(?' + .'|7408/([^/]++)/([^/]++)/([^/]++)/087408(*:34191)' + .'|b255/([^/]++)/([^/]++)/([^/]++)/08b255(*:34239)' + .'|c543/([^/]++)/([^/]++)/([^/]++)/08c543(*:34287)' + .'|d986/([^/]++)/([^/]++)/([^/]++)/08d986(*:34335)' + .'|419b/([^/]++)/([^/]++)/([^/]++)/08419b(*:34383)' + .')' + .'|7(?' + .'|563a/([^/]++)/([^/]++)/([^/]++)/07563a(*:34436)' + .'|6a0c/([^/]++)/([^/]++)/([^/]++)/076a0c(*:34484)' + .'|a96b/([^/]++)/([^/]++)/([^/]++)/07a96b(*:34532)' + .'|c580/([^/]++)/([^/]++)/([^/]++)/07c580(*:34580)' + .'|8719/([^/]++)/([^/]++)/([^/]++)/078719(*:34628)' + .')' + .'|f(?' + .'|cbc6/([^/]++)/([^/]++)/([^/]++)/0fcbc6(*:34681)' + .'|9661/([^/]++)/([^/]++)/([^/]++)/0f9661(*:34729)' + .'|f(?' + .'|39b/([^/]++)/([^/]++)/([^/]++)/0ff39b(*:34780)' + .'|803/([^/]++)/([^/]++)/([^/]++)/0ff803(*:34827)' + .')' + .'|840b/([^/]++)/([^/]++)/([^/]++)/0f840b(*:34876)' + .')' + .'|1(?' + .'|f78b/([^/]++)/([^/]++)/([^/]++)/01f78b(*:34929)' + .'|3a00/([^/]++)/([^/]++)/([^/]++)/013a00(*:34977)' + .'|8825/([^/]++)/([^/]++)/([^/]++)/018825(*:35025)' + .')' + .'|6(?' + .'|9(?' + .'|d3b/([^/]++)/([^/]++)/([^/]++)/069d3b(*:35081)' + .'|97f/([^/]++)/([^/]++)/([^/]++)/06997f(*:35128)' + .')' + .'|1412/([^/]++)/([^/]++)/([^/]++)/061412(*:35177)' + .')' + .'|4(?' + .'|ecb1/([^/]++)/([^/]++)/([^/]++)/04ecb1(*:35230)' + .'|3c3d/([^/]++)/([^/]++)/([^/]++)/043c3d(*:35278)' + .')' + .'|0ac8e/([^/]++)/([^/]++)/([^/]++)/00ac8e(*:35328)' + .'|5(?' + .'|1e4e/([^/]++)/([^/]++)/([^/]++)/051e4e(*:35380)' + .'|37fb/([^/]++)/([^/]++)/([^/]++)/0537fb(*:35428)' + .')' + .'|d(?' + .'|7de1/([^/]++)/([^/]++)/([^/]++)/0d7de1(*:35481)' + .'|3180/([^/]++)/([^/]++)/([^/]++)/0d3180(*:35529)' + .'|0871/([^/]++)/([^/]++)/([^/]++)/0d0871(*:35577)' + .')' + .'|cb929/([^/]++)/([^/]++)/([^/]++)/0cb929(*:35627)' + .'|2(?' + .'|a32a/([^/]++)/([^/]++)/([^/]++)/02a32a(*:35679)' + .'|4d7f/([^/]++)/([^/]++)/([^/]++)/024d7f(*:35727)' + .')' + .'|efe32/([^/]++)/([^/]++)/([^/]++)/0efe32(*:35777)' + .'|a113e/([^/]++)/([^/]++)/([^/]++)/0a113e(*:35826)' + .'|b8aff/([^/]++)/([^/]++)/([^/]++)/0b8aff(*:35875)' + .')' + .'|/a(?' + .'|7(?' + .'|6088/([^/]++)/([^/]++)/([^/]++)/a76088(*:35933)' + .'|aeed/([^/]++)/([^/]++)/([^/]++)/a7aeed(*:35981)' + .'|33fa/([^/]++)/([^/]++)/([^/]++)/a733fa(*:36029)' + .')' + .'|9a(?' + .'|665/([^/]++)/([^/]++)/([^/]++)/a9a665(*:36082)' + .'|1d5/([^/]++)/([^/]++)/([^/]++)/a9a1d5(*:36129)' + .')' + .'|8(?' + .'|6c45/([^/]++)/([^/]++)/([^/]++)/a86c45(*:36182)' + .'|849b/([^/]++)/([^/]++)/([^/]++)/a8849b(*:36230)' + .'|e(?' + .'|864/([^/]++)/([^/]++)/([^/]++)/a8e864(*:36281)' + .'|cba/([^/]++)/([^/]++)/([^/]++)/a8ecba(*:36328)' + .')' + .')' + .'|c(?' + .'|c3e0/([^/]++)/([^/]++)/([^/]++)/acc3e0(*:36382)' + .'|f4b8/([^/]++)/([^/]++)/([^/]++)/acf4b8(*:36430)' + .')' + .'|b(?' + .'|d815/([^/]++)/([^/]++)/([^/]++)/abd815(*:36483)' + .'|233b/([^/]++)/([^/]++)/([^/]++)/ab233b(*:36531)' + .'|a3b6/([^/]++)/([^/]++)/([^/]++)/aba3b6(*:36579)' + .'|88b1/([^/]++)/([^/]++)/([^/]++)/ab88b1(*:36627)' + .')' + .'|5(?' + .'|3240/([^/]++)/([^/]++)/([^/]++)/a53240(*:36680)' + .'|cdd4/([^/]++)/([^/]++)/([^/]++)/a5cdd4(*:36728)' + .')' + .'|f(?' + .'|d(?' + .'|483/([^/]++)/([^/]++)/([^/]++)/afd483(*:36784)' + .'|a33/([^/]++)/([^/]++)/([^/]++)/afda33(*:36831)' + .')' + .'|f162/([^/]++)/([^/]++)/([^/]++)/aff162(*:36880)' + .')' + .'|e(?' + .'|0eb3/([^/]++)/([^/]++)/([^/]++)/ae0eb3(*:36933)' + .'|b313/([^/]++)/([^/]++)/([^/]++)/aeb313(*:36981)' + .')' + .'|1(?' + .'|d33d/([^/]++)/([^/]++)/([^/]++)/a1d33d(*:37034)' + .'|140a/([^/]++)/([^/]++)/([^/]++)/a1140a(*:37082)' + .')' + .'|ddfa9/([^/]++)/([^/]++)/([^/]++)/addfa9(*:37132)' + .'|6(?' + .'|7f09/([^/]++)/([^/]++)/([^/]++)/a67f09(*:37184)' + .'|4c94/([^/]++)/([^/]++)/([^/]++)/a64c94(*:37232)' + .')' + .'|a169b/([^/]++)/([^/]++)/([^/]++)/aa169b(*:37282)' + .'|4300b/([^/]++)/([^/]++)/([^/]++)/a4300b(*:37331)' + .'|3d68b/([^/]++)/([^/]++)/([^/]++)/a3d68b(*:37380)' + .')' + .'|/1(?' + .'|0(?' + .'|a(?' + .'|7cd/([^/]++)/([^/]++)/([^/]++)/10a7cd(*:37441)' + .'|5ab/([^/]++)/([^/]++)/([^/]++)/10a5ab(*:37488)' + .')' + .'|9a0c/([^/]++)/([^/]++)/([^/]++)/109a0c(*:37537)' + .')' + .'|3f320/([^/]++)/([^/]++)/([^/]++)/13f320(*:37587)' + .'|6(?' + .'|c222/([^/]++)/([^/]++)/([^/]++)/16c222(*:37639)' + .'|8908/([^/]++)/([^/]++)/([^/]++)/168908(*:37687)' + .')' + .'|5(?' + .'|de21/([^/]++)/([^/]++)/([^/]++)/15de21(*:37740)' + .'|95af/([^/]++)/([^/]++)/([^/]++)/1595af(*:37788)' + .')' + .'|1(?' + .'|b921/([^/]++)/([^/]++)/([^/]++)/11b921(*:37841)' + .'|4193/([^/]++)/([^/]++)/([^/]++)/114193(*:37889)' + .')' + .'|bb91f/([^/]++)/([^/]++)/([^/]++)/1bb91f(*:37939)' + .'|7(?' + .'|28ef/([^/]++)/([^/]++)/([^/]++)/1728ef(*:37991)' + .'|c276/([^/]++)/([^/]++)/([^/]++)/17c276(*:38039)' + .'|0c94/([^/]++)/([^/]++)/([^/]++)/170c94(*:38087)' + .')' + .'|85(?' + .'|c29/([^/]++)/([^/]++)/([^/]++)/185c29(*:38140)' + .'|e65/([^/]++)/([^/]++)/([^/]++)/185e65(*:38187)' + .')' + .'|9(?' + .'|2fc0/([^/]++)/([^/]++)/([^/]++)/192fc0(*:38240)' + .'|b(?' + .'|c91/([^/]++)/([^/]++)/([^/]++)/19bc91(*:38291)' + .'|650/([^/]++)/([^/]++)/([^/]++)/19b650(*:38338)' + .')' + .'|05ae/([^/]++)/([^/]++)/([^/]++)/1905ae(*:38387)' + .')' + .'|e(?' + .'|cfb4/([^/]++)/([^/]++)/([^/]++)/1ecfb4(*:38440)' + .'|fa39/([^/]++)/([^/]++)/([^/]++)/1efa39(*:38488)' + .'|056d/([^/]++)/([^/]++)/([^/]++)/1e056d(*:38536)' + .')' + .'|aa48f/([^/]++)/([^/]++)/([^/]++)/1aa48f(*:38586)' + .'|f(?' + .'|c214/([^/]++)/([^/]++)/([^/]++)/1fc214(*:38638)' + .'|5089/([^/]++)/([^/]++)/([^/]++)/1f5089(*:38686)' + .'|4477/([^/]++)/([^/]++)/([^/]++)/1f4477(*:38734)' + .')' + .'|c(?' + .'|c363/([^/]++)/([^/]++)/([^/]++)/1cc363(*:38787)' + .'|1d4d/([^/]++)/([^/]++)/([^/]++)/1c1d4d(*:38835)' + .'|e927/([^/]++)/([^/]++)/([^/]++)/1ce927(*:38883)' + .')' + .')' + .'|/6(?' + .'|3(?' + .'|538f/([^/]++)/([^/]++)/([^/]++)/63538f(*:38942)' + .'|2cee/([^/]++)/([^/]++)/([^/]++)/632cee(*:38990)' + .'|95eb/([^/]++)/([^/]++)/([^/]++)/6395eb(*:39038)' + .')' + .'|9(?' + .'|421f/([^/]++)/([^/]++)/([^/]++)/69421f(*:39091)' + .'|2f93/([^/]++)/([^/]++)/([^/]++)/692f93(*:39139)' + .')' + .'|5658f/([^/]++)/([^/]++)/([^/]++)/65658f(*:39189)' + .'|4(?' + .'|7bba/([^/]++)/([^/]++)/([^/]++)/647bba(*:39241)' + .'|223c/([^/]++)/([^/]++)/([^/]++)/64223c(*:39289)' + .')' + .'|e(?' + .'|2713/([^/]++)/([^/]++)/([^/]++)/6e2713(*:39342)' + .'|0721/([^/]++)/([^/]++)/([^/]++)/6e0721(*:39390)' + .'|7b33/([^/]++)/([^/]++)/([^/]++)/6e7b33(*:39438)' + .')' + .'|0(?' + .'|5ff7/([^/]++)/([^/]++)/([^/]++)/605ff7(*:39491)' + .'|8159/([^/]++)/([^/]++)/([^/]++)/608159(*:39539)' + .')' + .'|a(?' + .'|ca97/([^/]++)/([^/]++)/([^/]++)/6aca97(*:39592)' + .'|10bb/([^/]++)/([^/]++)/([^/]++)/6a10bb(*:39640)' + .'|ab12/([^/]++)/([^/]++)/([^/]++)/6aab12(*:39688)' + .')' + .'|7(?' + .'|66aa/([^/]++)/([^/]++)/([^/]++)/6766aa(*:39741)' + .'|e103/([^/]++)/([^/]++)/([^/]++)/67e103(*:39789)' + .'|d(?' + .'|96d/([^/]++)/([^/]++)/([^/]++)/67d96d(*:39840)' + .'|16d/([^/]++)/([^/]++)/([^/]++)/67d16d(*:39887)' + .')' + .'|0e8a/([^/]++)/([^/]++)/([^/]++)/670e8a(*:39936)' + .'|7e09/([^/]++)/([^/]++)/([^/]++)/677e09(*:39984)' + .')' + .'|8(?' + .'|264b/([^/]++)/([^/]++)/([^/]++)/68264b(*:40037)' + .'|053a/([^/]++)/([^/]++)/([^/]++)/68053a(*:40085)' + .')' + .'|c(?' + .'|2979/([^/]++)/([^/]++)/([^/]++)/6c2979(*:40138)' + .'|d67d/([^/]++)/([^/]++)/([^/]++)/6cd67d(*:40186)' + .'|3cf7/([^/]++)/([^/]++)/([^/]++)/6c3cf7(*:40234)' + .'|fe0e/([^/]++)/([^/]++)/([^/]++)/6cfe0e(*:40282)' + .')' + .'|bc24f/([^/]++)/([^/]++)/([^/]++)/6bc24f(*:40332)' + .'|f2268/([^/]++)/([^/]++)/([^/]++)/6f2268(*:40381)' + .'|1b4a6/([^/]++)/([^/]++)/([^/]++)/61b4a6(*:40430)' + .'|21461/([^/]++)/([^/]++)/([^/]++)/621461(*:40479)' + .'|d0f84/([^/]++)/([^/]++)/([^/]++)/6d0f84(*:40528)' + .'|60229/([^/]++)/([^/]++)/([^/]++)/660229(*:40577)' + .')' + .'|/c(?' + .'|f(?' + .'|6735/([^/]++)/([^/]++)/([^/]++)/cf6735(*:40635)' + .'|bce4/([^/]++)/([^/]++)/([^/]++)/cfbce4(*:40683)' + .')' + .'|3(?' + .'|99(?' + .'|86/([^/]++)/([^/]++)/([^/]++)/c39986(*:40739)' + .'|2e/([^/]++)/([^/]++)/([^/]++)/c3992e(*:40785)' + .')' + .'|61bc/([^/]++)/([^/]++)/([^/]++)/c361bc(*:40834)' + .'|2d9b/([^/]++)/([^/]++)/([^/]++)/c32d9b(*:40882)' + .')' + .'|75b6f/([^/]++)/([^/]++)/([^/]++)/c75b6f(*:40932)' + .'|c(?' + .'|b(?' + .'|1d4/([^/]++)/([^/]++)/([^/]++)/ccb1d4(*:40987)' + .'|098/([^/]++)/([^/]++)/([^/]++)/ccb098(*:41034)' + .')' + .'|c0aa/([^/]++)/([^/]++)/([^/]++)/ccc0aa(*:41083)' + .'|1aa4/([^/]++)/([^/]++)/([^/]++)/cc1aa4(*:41131)' + .')' + .'|b(?' + .'|cb58/([^/]++)/([^/]++)/([^/]++)/cbcb58(*:41184)' + .'|b6a3/([^/]++)/([^/]++)/([^/]++)/cbb6a3(*:41232)' + .')' + .'|9892a/([^/]++)/([^/]++)/([^/]++)/c9892a(*:41282)' + .'|6e19e/([^/]++)/([^/]++)/([^/]++)/c6e19e(*:41331)' + .'|dc0d6/([^/]++)/([^/]++)/([^/]++)/cdc0d6(*:41380)' + .'|5ab0b/([^/]++)/([^/]++)/([^/]++)/c5ab0b(*:41429)' + .'|a(?' + .'|9c26/([^/]++)/([^/]++)/([^/]++)/ca9c26(*:41481)' + .'|8155/([^/]++)/([^/]++)/([^/]++)/ca8155(*:41529)' + .'|7591/([^/]++)/([^/]++)/([^/]++)/ca7591(*:41577)' + .')' + .'|0(?' + .'|6d06/([^/]++)/([^/]++)/([^/]++)/c06d06(*:41630)' + .'|f168/([^/]++)/([^/]++)/([^/]++)/c0f168(*:41678)' + .')' + .'|8(?' + .'|ed21/([^/]++)/([^/]++)/([^/]++)/c8ed21(*:41731)' + .'|fbbc/([^/]++)/([^/]++)/([^/]++)/c8fbbc(*:41779)' + .'|c41c/([^/]++)/([^/]++)/([^/]++)/c8c41c(*:41827)' + .')' + .'|15da1/([^/]++)/([^/]++)/([^/]++)/c15da1(*:41877)' + .'|2(?' + .'|626d/([^/]++)/([^/]++)/([^/]++)/c2626d(*:41929)' + .'|aee8/([^/]++)/([^/]++)/([^/]++)/c2aee8(*:41977)' + .'|2abf/([^/]++)/([^/]++)/([^/]++)/c22abf(*:42025)' + .')' + .'|e78d1/([^/]++)/([^/]++)/([^/]++)/ce78d1(*:42075)' + .'|4(?' + .'|015b/([^/]++)/([^/]++)/([^/]++)/c4015b(*:42127)' + .'|b31c/([^/]++)/([^/]++)/([^/]++)/c4b31c(*:42175)' + .')' + .')' + .'|/8(?' + .'|5(?' + .'|422a/([^/]++)/([^/]++)/([^/]++)/85422a(*:42234)' + .'|1ddf/([^/]++)/([^/]++)/([^/]++)/851ddf(*:42282)' + .'|fc37/([^/]++)/([^/]++)/([^/]++)/85fc37(*:42330)' + .')' + .'|1(?' + .'|4481/([^/]++)/([^/]++)/([^/]++)/814481(*:42383)' + .'|e74d/([^/]++)/([^/]++)/([^/]++)/81e74d(*:42431)' + .')' + .'|d(?' + .'|3(?' + .'|420/([^/]++)/([^/]++)/([^/]++)/8d3420(*:42487)' + .'|17b/([^/]++)/([^/]++)/([^/]++)/8d317b(*:42534)' + .')' + .'|f707/([^/]++)/([^/]++)/([^/]++)/8df707(*:42583)' + .'|6dc3/([^/]++)/([^/]++)/([^/]++)/8d6dc3(*:42631)' + .')' + .'|e(?' + .'|efcf/([^/]++)/([^/]++)/([^/]++)/8eefcf(*:42684)' + .'|bda5/([^/]++)/([^/]++)/([^/]++)/8ebda5(*:42732)' + .'|82ab/([^/]++)/([^/]++)/([^/]++)/8e82ab(*:42780)' + .')' + .'|b(?' + .'|16eb/([^/]++)/([^/]++)/([^/]++)/8b16eb(*:42833)' + .'|6dd7/([^/]++)/([^/]++)/([^/]++)/8b6dd7(*:42881)' + .'|5040/([^/]++)/([^/]++)/([^/]++)/8b5040(*:42929)' + .')' + .'|c(?' + .'|7bbb/([^/]++)/([^/]++)/([^/]++)/8c7bbb(*:42982)' + .'|6744/([^/]++)/([^/]++)/([^/]++)/8c6744(*:43030)' + .'|235f/([^/]++)/([^/]++)/([^/]++)/8c235f(*:43078)' + .')' + .'|8(?' + .'|4d24/([^/]++)/([^/]++)/([^/]++)/884d24(*:43131)' + .'|ae63/([^/]++)/([^/]++)/([^/]++)/88ae63(*:43179)' + .')' + .'|7(?' + .'|5715/([^/]++)/([^/]++)/([^/]++)/875715(*:43232)' + .'|2488/([^/]++)/([^/]++)/([^/]++)/872488(*:43280)' + .')' + .'|4(?' + .'|1172/([^/]++)/([^/]++)/([^/]++)/841172(*:43333)' + .'|6c26/([^/]++)/([^/]++)/([^/]++)/846c26(*:43381)' + .'|f7e6/([^/]++)/([^/]++)/([^/]++)/84f7e6(*:43429)' + .'|7cc5/([^/]++)/([^/]++)/([^/]++)/847cc5(*:43477)' + .')' + .'|f(?' + .'|ecb2/([^/]++)/([^/]++)/([^/]++)/8fecb2(*:43530)' + .'|7d80/([^/]++)/([^/]++)/([^/]++)/8f7d80(*:43578)' + .'|468c/([^/]++)/([^/]++)/([^/]++)/8f468c(*:43626)' + .')' + .'|a0e11/([^/]++)/([^/]++)/([^/]++)/8a0e11(*:43676)' + .'|2(?' + .'|f2b3/([^/]++)/([^/]++)/([^/]++)/82f2b3(*:43728)' + .'|489c/([^/]++)/([^/]++)/([^/]++)/82489c(*:43776)' + .')' + .'|6(?' + .'|b122/([^/]++)/([^/]++)/([^/]++)/86b122(*:43829)' + .'|0320/([^/]++)/([^/]++)/([^/]++)/860320(*:43877)' + .')' + .'|9(?' + .'|2c91/([^/]++)/([^/]++)/([^/]++)/892c91(*:43930)' + .'|fcd0/([^/]++)/([^/]++)/([^/]++)/89fcd0(*:43978)' + .')' + .'|065d0/([^/]++)/([^/]++)/([^/]++)/8065d0(*:44028)' + .')' + .'|/d(?' + .'|6(?' + .'|4a34/([^/]++)/([^/]++)/([^/]++)/d64a34(*:44086)' + .'|c651/([^/]++)/([^/]++)/([^/]++)/d6c651(*:44134)' + .')' + .'|f(?' + .'|877f/([^/]++)/([^/]++)/([^/]++)/df877f(*:44187)' + .'|263d/([^/]++)/([^/]++)/([^/]++)/df263d(*:44235)' + .'|7f28/([^/]++)/([^/]++)/([^/]++)/df7f28(*:44283)' + .'|6d23/([^/]++)/([^/]++)/([^/]++)/df6d23(*:44331)' + .')' + .'|b(?' + .'|85e2/([^/]++)/([^/]++)/([^/]++)/db85e2(*:44384)' + .'|e272/([^/]++)/([^/]++)/([^/]++)/dbe272(*:44432)' + .')' + .'|d(?' + .'|45(?' + .'|85/([^/]++)/([^/]++)/([^/]++)/dd4585(*:44488)' + .'|04/([^/]++)/([^/]++)/([^/]++)/dd4504(*:44534)' + .')' + .'|8eb9/([^/]++)/([^/]++)/([^/]++)/dd8eb9(*:44583)' + .')' + .'|a(?' + .'|ca41/([^/]++)/([^/]++)/([^/]++)/daca41(*:44636)' + .'|8ce5/([^/]++)/([^/]++)/([^/]++)/da8ce5(*:44684)' + .'|0d11/([^/]++)/([^/]++)/([^/]++)/da0d11(*:44732)' + .')' + .'|4(?' + .'|90d7/([^/]++)/([^/]++)/([^/]++)/d490d7(*:44785)' + .'|c2e4/([^/]++)/([^/]++)/([^/]++)/d4c2e4(*:44833)' + .')' + .'|8(?' + .'|6ea6/([^/]++)/([^/]++)/([^/]++)/d86ea6(*:44886)' + .'|40cc/([^/]++)/([^/]++)/([^/]++)/d840cc(*:44934)' + .')' + .'|c(?' + .'|82d6/([^/]++)/([^/]++)/([^/]++)/dc82d6(*:44987)' + .'|6a70/([^/]++)/([^/]++)/([^/]++)/dc6a70(*:45035)' + .'|5689/([^/]++)/([^/]++)/([^/]++)/dc5689(*:45083)' + .')' + .'|7(?' + .'|a728/([^/]++)/([^/]++)/([^/]++)/d7a728(*:45136)' + .'|0732/([^/]++)/([^/]++)/([^/]++)/d70732(*:45184)' + .'|9aac/([^/]++)/([^/]++)/([^/]++)/d79aac(*:45232)' + .')' + .'|14220/([^/]++)/([^/]++)/([^/]++)/d14220(*:45282)' + .'|5(?' + .'|cfea/([^/]++)/([^/]++)/([^/]++)/d5cfea(*:45334)' + .'|8072/([^/]++)/([^/]++)/([^/]++)/d58072(*:45382)' + .'|54f7/([^/]++)/([^/]++)/([^/]++)/d554f7(*:45430)' + .'|16b1/([^/]++)/([^/]++)/([^/]++)/d516b1(*:45478)' + .'|6b9f/([^/]++)/([^/]++)/([^/]++)/d56b9f(*:45526)' + .')' + .'|045c5/([^/]++)/([^/]++)/([^/]++)/d045c5(*:45576)' + .'|2(?' + .'|ed45/([^/]++)/([^/]++)/([^/]++)/d2ed45(*:45628)' + .'|40e3/([^/]++)/([^/]++)/([^/]++)/d240e3(*:45676)' + .')' + .'|93ed5/([^/]++)/([^/]++)/([^/]++)/d93ed5(*:45726)' + .')' + .'|/7(?' + .'|b(?' + .'|cdf7/([^/]++)/([^/]++)/([^/]++)/7bcdf7(*:45784)' + .'|13b2/([^/]++)/([^/]++)/([^/]++)/7b13b2(*:45832)' + .')' + .'|dcd34/([^/]++)/([^/]++)/([^/]++)/7dcd34(*:45882)' + .'|f(?' + .'|24d2/([^/]++)/([^/]++)/([^/]++)/7f24d2(*:45934)' + .'|5d04/([^/]++)/([^/]++)/([^/]++)/7f5d04(*:45982)' + .'|1171/([^/]++)/([^/]++)/([^/]++)/7f1171(*:46030)' + .'|a732/([^/]++)/([^/]++)/([^/]++)/7fa732(*:46078)' + .')' + .'|6(?' + .'|6ebc/([^/]++)/([^/]++)/([^/]++)/766ebc(*:46131)' + .'|34ea/([^/]++)/([^/]++)/([^/]++)/7634ea(*:46179)' + .')' + .'|750ca/([^/]++)/([^/]++)/([^/]++)/7750ca(*:46229)' + .'|1(?' + .'|a(?' + .'|3cb/([^/]++)/([^/]++)/([^/]++)/71a3cb(*:46284)' + .'|d16/([^/]++)/([^/]++)/([^/]++)/71ad16(*:46331)' + .')' + .'|43d7/([^/]++)/([^/]++)/([^/]++)/7143d7(*:46380)' + .')' + .'|88d98/([^/]++)/([^/]++)/([^/]++)/788d98(*:46430)' + .'|2(?' + .'|da7f/([^/]++)/([^/]++)/([^/]++)/72da7f(*:46482)' + .'|50eb/([^/]++)/([^/]++)/([^/]++)/7250eb(*:46530)' + .')' + .'|c(?' + .'|590f/([^/]++)/([^/]++)/([^/]++)/7c590f(*:46583)' + .'|e328/([^/]++)/([^/]++)/([^/]++)/7ce328(*:46631)' + .')' + .'|a5392/([^/]++)/([^/]++)/([^/]++)/7a5392(*:46681)' + .'|95c7a/([^/]++)/([^/]++)/([^/]++)/795c7a(*:46730)' + .'|504ad/([^/]++)/([^/]++)/([^/]++)/7504ad(*:46779)' + .'|04afe/([^/]++)/([^/]++)/([^/]++)/704afe(*:46828)' + .'|4bba2/([^/]++)/([^/]++)/([^/]++)/74bba2(*:46877)' + .')' + .'|/9(?' + .'|b(?' + .'|72e3/([^/]++)/([^/]++)/([^/]++)/9b72e3(*:46935)' + .'|698e/([^/]++)/([^/]++)/([^/]++)/9b698e(*:46983)' + .')' + .'|7e852/([^/]++)/([^/]++)/([^/]++)/97e852(*:47033)' + .'|4c7bb/([^/]++)/([^/]++)/([^/]++)/94c7bb(*:47082)' + .'|9(?' + .'|c5e0/([^/]++)/([^/]++)/([^/]++)/99c5e0(*:47134)' + .'|6a7f/([^/]++)/([^/]++)/([^/]++)/996a7f(*:47182)' + .'|bcfc/([^/]++)/([^/]++)/([^/]++)/99bcfc(*:47230)' + .'|0827/([^/]++)/([^/]++)/([^/]++)/990827(*:47278)' + .')' + .'|a(?' + .'|d6aa/([^/]++)/([^/]++)/([^/]++)/9ad6aa(*:47331)' + .'|b0d8/([^/]++)/([^/]++)/([^/]++)/9ab0d8(*:47379)' + .')' + .'|c(?' + .'|f81d/([^/]++)/([^/]++)/([^/]++)/9cf81d(*:47432)' + .'|c138/([^/]++)/([^/]++)/([^/]++)/9cc138(*:47480)' + .'|82c7/([^/]++)/([^/]++)/([^/]++)/9c82c7(*:47528)' + .'|0180/([^/]++)/([^/]++)/([^/]++)/9c0180(*:47576)' + .')' + .'|f(?' + .'|396f/([^/]++)/([^/]++)/([^/]++)/9f396f(*:47629)' + .'|e859/([^/]++)/([^/]++)/([^/]++)/9fe859(*:47677)' + .'|53d8/([^/]++)/([^/]++)/([^/]++)/9f53d8(*:47725)' + .')' + .'|12d2b/([^/]++)/([^/]++)/([^/]++)/912d2b(*:47775)' + .'|59a55/([^/]++)/([^/]++)/([^/]++)/959a55(*:47824)' + .'|6(?' + .'|ea64/([^/]++)/([^/]++)/([^/]++)/96ea64(*:47876)' + .'|b9bf/([^/]++)/([^/]++)/([^/]++)/96b9bf(*:47924)' + .')' + .'|e3cfc/([^/]++)/([^/]++)/([^/]++)/9e3cfc(*:47974)' + .'|2(?' + .'|fb0c/([^/]++)/([^/]++)/([^/]++)/92fb0c(*:48026)' + .'|262b/([^/]++)/([^/]++)/([^/]++)/92262b(*:48074)' + .'|32fe/([^/]++)/([^/]++)/([^/]++)/9232fe(*:48122)' + .'|977a/([^/]++)/([^/]++)/([^/]++)/92977a(*:48170)' + .')' + .'|8d6f5/([^/]++)/([^/]++)/([^/]++)/98d6f5(*:48220)' + .'|0794e/([^/]++)/([^/]++)/([^/]++)/90794e(*:48269)' + .'|34815/([^/]++)/([^/]++)/([^/]++)/934815(*:48318)' + .')' + .'|/4(?' + .'|e(?' + .'|4b5f/([^/]++)/([^/]++)/([^/]++)/4e4b5f(*:48376)' + .'|a06f/([^/]++)/([^/]++)/([^/]++)/4ea06f(*:48424)' + .'|0(?' + .'|928/([^/]++)/([^/]++)/([^/]++)/4e0928(*:48475)' + .'|cb6/([^/]++)/([^/]++)/([^/]++)/4e0cb6(*:48522)' + .')' + .')' + .'|6922a/([^/]++)/([^/]++)/([^/]++)/46922a(*:48573)' + .'|4(?' + .'|c4c1/([^/]++)/([^/]++)/([^/]++)/44c4c1(*:48625)' + .'|3cb0/([^/]++)/([^/]++)/([^/]++)/443cb0(*:48673)' + .')' + .'|8ab2f/([^/]++)/([^/]++)/([^/]++)/48ab2f(*:48723)' + .'|5(?' + .'|645a/([^/]++)/([^/]++)/([^/]++)/45645a(*:48775)' + .'|58db/([^/]++)/([^/]++)/([^/]++)/4558db(*:48823)' + .')' + .'|2e77b/([^/]++)/([^/]++)/([^/]++)/42e77b(*:48873)' + .'|c27ce/([^/]++)/([^/]++)/([^/]++)/4c27ce(*:48922)' + .'|f(?' + .'|fce0/([^/]++)/([^/]++)/([^/]++)/4ffce0(*:48974)' + .'|ac9b/([^/]++)/([^/]++)/([^/]++)/4fac9b(*:49022)' + .')' + .'|a47d2/([^/]++)/([^/]++)/([^/]++)/4a47d2(*:49072)' + .'|70e7a/([^/]++)/([^/]++)/([^/]++)/470e7a(*:49121)' + .'|b(?' + .'|0(?' + .'|4a6/([^/]++)/([^/]++)/([^/]++)/4b04a6(*:49176)' + .'|a59/([^/]++)/([^/]++)/([^/]++)/4b0a59(*:49223)' + .'|250/([^/]++)/([^/]++)/([^/]++)/4b0250(*:49270)' + .')' + .'|6538/([^/]++)/([^/]++)/([^/]++)/4b6538(*:49319)' + .')' + .'|3(?' + .'|f(?' + .'|a7f/([^/]++)/([^/]++)/([^/]++)/43fa7f(*:49375)' + .'|eae/([^/]++)/([^/]++)/([^/]++)/43feae(*:49422)' + .')' + .'|0c36/([^/]++)/([^/]++)/([^/]++)/430c36(*:49471)' + .'|7d7d/([^/]++)/([^/]++)/([^/]++)/437d7d(*:49519)' + .'|1135/([^/]++)/([^/]++)/([^/]++)/431135(*:49567)' + .')' + .'|d(?' + .'|5b99/([^/]++)/([^/]++)/([^/]++)/4d5b99(*:49620)' + .'|aa3d/([^/]++)/([^/]++)/([^/]++)/4daa3d(*:49668)' + .')' + .'|9c9ad/([^/]++)/([^/]++)/([^/]++)/49c9ad(*:49718)' + .')' + .')/?$}sD', + ], + [ // $dynamicRoutes + 54 => [[['_route' => '_0'], ['a', 'b', 'c'], null, null, false, false, null]], + 102 => [[['_route' => '_190'], ['a', 'b', 'c'], null, null, false, false, null]], + 147 => [[['_route' => '_478'], ['a', 'b', 'c'], null, null, false, false, null]], + 194 => [[['_route' => '_259'], ['a', 'b', 'c'], null, null, false, false, null]], + 240 => [[['_route' => '_368'], ['a', 'b', 'c'], null, null, false, false, null]], + 291 => [[['_route' => '_1'], ['a', 'b', 'c'], null, null, false, false, null]], + 337 => [[['_route' => '_116'], ['a', 'b', 'c'], null, null, false, false, null]], + 383 => [[['_route' => '_490'], ['a', 'b', 'c'], null, null, false, false, null]], + 434 => [[['_route' => '_2'], ['a', 'b', 'c'], null, null, false, false, null]], + 480 => [[['_route' => '_124'], ['a', 'b', 'c'], null, null, false, false, null]], + 526 => [[['_route' => '_389'], ['a', 'b', 'c'], null, null, false, false, null]], + 577 => [[['_route' => '_8'], ['a', 'b', 'c'], null, null, false, false, null]], + 623 => [[['_route' => '_104'], ['a', 'b', 'c'], null, null, false, false, null]], + 677 => [[['_route' => '_12'], ['a', 'b', 'c'], null, null, false, false, null]], + 722 => [[['_route' => '_442'], ['a', 'b', 'c'], null, null, false, false, null]], + 769 => [[['_route' => '_253'], ['a', 'b', 'c'], null, null, false, false, null]], + 820 => [[['_route' => '_13'], ['a', 'b', 'c'], null, null, false, false, null]], + 866 => [[['_route' => '_254'], ['a', 'b', 'c'], null, null, false, false, null]], + 912 => [[['_route' => '_347'], ['a', 'b', 'c'], null, null, false, false, null]], + 963 => [[['_route' => '_16'], ['a', 'b', 'c'], null, null, false, false, null]], + 1009 => [[['_route' => '_87'], ['a', 'b', 'c'], null, null, false, false, null]], + 1058 => [[['_route' => '_31'], ['a', 'b', 'c'], null, null, false, false, null]], + 1109 => [[['_route' => '_50'], ['a', 'b', 'c'], null, null, false, false, null]], + 1156 => [[['_route' => '_219'], ['a', 'b', 'c'], null, null, false, false, null]], + 1203 => [[['_route' => '_332'], ['a', 'b', 'c'], null, null, false, false, null]], + 1250 => [[['_route' => '_359'], ['a', 'b', 'c'], null, null, false, false, null]], + 1302 => [[['_route' => '_183'], ['a', 'b', 'c'], null, null, false, false, null]], + 1349 => [[['_route' => '_500'], ['a', 'b', 'c'], null, null, false, false, null]], + 1401 => [[['_route' => '_214'], ['a', 'b', 'c'], null, null, false, false, null]], + 1448 => [[['_route' => '_321'], ['a', 'b', 'c'], null, null, false, false, null]], + 1497 => [[['_route' => '_243'], ['a', 'b', 'c'], null, null, false, false, null]], + 1545 => [[['_route' => '_328'], ['a', 'b', 'c'], null, null, false, false, null]], + 1596 => [[['_route' => '_362'], ['a', 'b', 'c'], null, null, false, false, null]], + 1643 => [[['_route' => '_488'], ['a', 'b', 'c'], null, null, false, false, null]], + 1701 => [[['_route' => '_3'], ['a', 'b', 'c'], null, null, false, false, null]], + 1751 => [[['_route' => '_102'], ['a', 'b', 'c'], null, null, false, false, null]], + 1797 => [[['_route' => '_220'], ['a', 'b', 'c'], null, null, false, false, null]], + 1845 => [[['_route' => '_127'], ['a', 'b', 'c'], null, null, false, false, null]], + 1897 => [[['_route' => '_5'], ['a', 'b', 'c'], null, null, false, false, null]], + 1944 => [[['_route' => '_242'], ['a', 'b', 'c'], null, null, false, false, null]], + 1991 => [[['_route' => '_397'], ['a', 'b', 'c'], null, null, false, false, null]], + 2038 => [[['_route' => '_454'], ['a', 'b', 'c'], null, null, false, false, null]], + 2090 => [[['_route' => '_34'], ['a', 'b', 'c'], null, null, false, false, null]], + 2137 => [[['_route' => '_281'], ['a', 'b', 'c'], null, null, false, false, null]], + 2189 => [[['_route' => '_64'], ['a', 'b', 'c'], null, null, false, false, null]], + 2236 => [[['_route' => '_205'], ['a', 'b', 'c'], null, null, false, false, null]], + 2291 => [[['_route' => '_71'], ['a', 'b', 'c'], null, null, false, false, null]], + 2337 => [[['_route' => '_203'], ['a', 'b', 'c'], null, null, false, false, null]], + 2385 => [[['_route' => '_97'], ['a', 'b', 'c'], null, null, false, false, null]], + 2437 => [[['_route' => '_98'], ['a', 'b', 'c'], null, null, false, false, null]], + 2484 => [[['_route' => '_267'], ['a', 'b', 'c'], null, null, false, false, null]], + 2531 => [[['_route' => '_309'], ['a', 'b', 'c'], null, null, false, false, null]], + 2586 => [[['_route' => '_117'], ['a', 'b', 'c'], null, null, false, false, null]], + 2631 => [[['_route' => '_211'], ['a', 'b', 'c'], null, null, false, false, null]], + 2679 => [[['_route' => '_484'], ['a', 'b', 'c'], null, null, false, false, null]], + 2731 => [[['_route' => '_139'], ['a', 'b', 'c'], null, null, false, false, null]], + 2778 => [[['_route' => '_421'], ['a', 'b', 'c'], null, null, false, false, null]], + 2830 => [[['_route' => '_185'], ['a', 'b', 'c'], null, null, false, false, null]], + 2877 => [[['_route' => '_439'], ['a', 'b', 'c'], null, null, false, false, null]], + 2926 => [[['_route' => '_218'], ['a', 'b', 'c'], null, null, false, false, null]], + 2977 => [[['_route' => '_233'], ['a', 'b', 'c'], null, null, false, false, null]], + 3024 => [[['_route' => '_483'], ['a', 'b', 'c'], null, null, false, false, null]], + 3073 => [[['_route' => '_265'], ['a', 'b', 'c'], null, null, false, false, null]], + 3124 => [[['_route' => '_299'], ['a', 'b', 'c'], null, null, false, false, null]], + 3171 => [[['_route' => '_351'], ['a', 'b', 'c'], null, null, false, false, null]], + 3218 => [[['_route' => '_472'], ['a', 'b', 'c'], null, null, false, false, null]], + 3267 => [[['_route' => '_360'], ['a', 'b', 'c'], null, null, false, false, null]], + 3315 => [[['_route' => '_466'], ['a', 'b', 'c'], null, null, false, false, null]], + 3372 => [[['_route' => '_4'], ['a', 'b', 'c'], null, null, false, false, null]], + 3419 => [[['_route' => '_142'], ['a', 'b', 'c'], null, null, false, false, null]], + 3466 => [[['_route' => '_151'], ['a', 'b', 'c'], null, null, false, false, null]], + 3513 => [[['_route' => '_308'], ['a', 'b', 'c'], null, null, false, false, null]], + 3560 => [[['_route' => '_440'], ['a', 'b', 'c'], null, null, false, false, null]], + 3612 => [[['_route' => '_14'], ['a', 'b', 'c'], null, null, false, false, null]], + 3659 => [[['_route' => '_358'], ['a', 'b', 'c'], null, null, false, false, null]], + 3711 => [[['_route' => '_37'], ['a', 'b', 'c'], null, null, false, false, null]], + 3758 => [[['_route' => '_38'], ['a', 'b', 'c'], null, null, false, false, null]], + 3805 => [[['_route' => '_146'], ['a', 'b', 'c'], null, null, false, false, null]], + 3852 => [[['_route' => '_194'], ['a', 'b', 'c'], null, null, false, false, null]], + 3899 => [[['_route' => '_487'], ['a', 'b', 'c'], null, null, false, false, null]], + 3948 => [[['_route' => '_42'], ['a', 'b', 'c'], null, null, false, false, null]], + 3999 => [[['_route' => '_54'], ['a', 'b', 'c'], null, null, false, false, null]], + 4046 => [[['_route' => '_326'], ['a', 'b', 'c'], null, null, false, false, null]], + 4098 => [[['_route' => '_68'], ['a', 'b', 'c'], null, null, false, false, null]], + 4145 => [[['_route' => '_108'], ['a', 'b', 'c'], null, null, false, false, null]], + 4197 => [[['_route' => '_74'], ['a', 'b', 'c'], null, null, false, false, null]], + 4244 => [[['_route' => '_315'], ['a', 'b', 'c'], null, null, false, false, null]], + 4291 => [[['_route' => '_374'], ['a', 'b', 'c'], null, null, false, false, null]], + 4343 => [[['_route' => '_99'], ['a', 'b', 'c'], null, null, false, false, null]], + 4390 => [[['_route' => '_238'], ['a', 'b', 'c'], null, null, false, false, null]], + 4442 => [[['_route' => '_107'], ['a', 'b', 'c'], null, null, false, false, null]], + 4489 => [[['_route' => '_409'], ['a', 'b', 'c'], null, null, false, false, null]], + 4541 => [[['_route' => '_122'], ['a', 'b', 'c'], null, null, false, false, null]], + 4588 => [[['_route' => '_379'], ['a', 'b', 'c'], null, null, false, false, null]], + 4635 => [[['_route' => '_390'], ['a', 'b', 'c'], null, null, false, false, null]], + 4687 => [[['_route' => '_171'], ['a', 'b', 'c'], null, null, false, false, null]], + 4734 => [[['_route' => '_260'], ['a', 'b', 'c'], null, null, false, false, null]], + 4781 => [[['_route' => '_434'], ['a', 'b', 'c'], null, null, false, false, null]], + 4830 => [[['_route' => '_189'], ['a', 'b', 'c'], null, null, false, false, null]], + 4878 => [[['_route' => '_467'], ['a', 'b', 'c'], null, null, false, false, null]], + 4935 => [[['_route' => '_6'], ['a', 'b', 'c'], null, null, false, false, null]], + 4982 => [[['_route' => '_286'], ['a', 'b', 'c'], null, null, false, false, null]], + 5029 => [[['_route' => '_438'], ['a', 'b', 'c'], null, null, false, false, null]], + 5081 => [[['_route' => '_19'], ['a', 'b', 'c'], null, null, false, false, null]], + 5131 => [[['_route' => '_24'], ['a', 'b', 'c'], null, null, false, false, null]], + 5177 => [[['_route' => '_172'], ['a', 'b', 'c'], null, null, false, false, null]], + 5230 => [[['_route' => '_33'], ['a', 'b', 'c'], null, null, false, false, null]], + 5277 => [[['_route' => '_400'], ['a', 'b', 'c'], null, null, false, false, null]], + 5324 => [[['_route' => '_427'], ['a', 'b', 'c'], null, null, false, false, null]], + 5376 => [[['_route' => '_35'], ['a', 'b', 'c'], null, null, false, false, null]], + 5423 => [[['_route' => '_156'], ['a', 'b', 'c'], null, null, false, false, null]], + 5475 => [[['_route' => '_36'], ['a', 'b', 'c'], null, null, false, false, null]], + 5522 => [[['_route' => '_251'], ['a', 'b', 'c'], null, null, false, false, null]], + 5574 => [[['_route' => '_43'], ['a', 'b', 'c'], null, null, false, false, null]], + 5621 => [[['_route' => '_292'], ['a', 'b', 'c'], null, null, false, false, null]], + 5668 => [[['_route' => '_411'], ['a', 'b', 'c'], null, null, false, false, null]], + 5720 => [[['_route' => '_69'], ['a', 'b', 'c'], null, null, false, false, null]], + 5767 => [[['_route' => '_159'], ['a', 'b', 'c'], null, null, false, false, null]], + 5814 => [[['_route' => '_170'], ['a', 'b', 'c'], null, null, false, false, null]], + 5861 => [[['_route' => '_376'], ['a', 'b', 'c'], null, null, false, false, null]], + 5913 => [[['_route' => '_131'], ['a', 'b', 'c'], null, null, false, false, null]], + 5960 => [[['_route' => '_446'], ['a', 'b', 'c'], null, null, false, false, null]], + 6015 => [[['_route' => '_140'], ['a', 'b', 'c'], null, null, false, false, null]], + 6061 => [[['_route' => '_353'], ['a', 'b', 'c'], null, null, false, false, null]], + 6112 => [[['_route' => '_224'], ['a', 'b', 'c'], null, null, false, false, null]], + 6158 => [[['_route' => '_346'], ['a', 'b', 'c'], null, null, false, false, null]], + 6204 => [[['_route' => '_443'], ['a', 'b', 'c'], null, null, false, false, null]], + 6254 => [[['_route' => '_154'], ['a', 'b', 'c'], null, null, false, false, null]], + 6305 => [[['_route' => '_212'], ['a', 'b', 'c'], null, null, false, false, null]], + 6352 => [[['_route' => '_313'], ['a', 'b', 'c'], null, null, false, false, null]], + 6399 => [[['_route' => '_395'], ['a', 'b', 'c'], null, null, false, false, null]], + 6446 => [[['_route' => '_441'], ['a', 'b', 'c'], null, null, false, false, null]], + 6498 => [[['_route' => '_223'], ['a', 'b', 'c'], null, null, false, false, null]], + 6545 => [[['_route' => '_303'], ['a', 'b', 'c'], null, null, false, false, null]], + 6594 => [[['_route' => '_410'], ['a', 'b', 'c'], null, null, false, false, null]], + 6642 => [[['_route' => '_494'], ['a', 'b', 'c'], null, null, false, false, null]], + 6702 => [[['_route' => '_7'], ['a', 'b', 'c'], null, null, false, false, null]], + 6748 => [[['_route' => '_268'], ['a', 'b', 'c'], null, null, false, false, null]], + 6796 => [[['_route' => '_178'], ['a', 'b', 'c'], null, null, false, false, null]], + 6843 => [[['_route' => '_179'], ['a', 'b', 'c'], null, null, false, false, null]], + 6890 => [[['_route' => '_416'], ['a', 'b', 'c'], null, null, false, false, null]], + 6942 => [[['_route' => '_25'], ['a', 'b', 'c'], null, null, false, false, null]], + 6989 => [[['_route' => '_307'], ['a', 'b', 'c'], null, null, false, false, null]], + 7036 => [[['_route' => '_387'], ['a', 'b', 'c'], null, null, false, false, null]], + 7083 => [[['_route' => '_471'], ['a', 'b', 'c'], null, null, false, false, null]], + 7132 => [[['_route' => '_90'], ['a', 'b', 'c'], null, null, false, false, null]], + 7183 => [[['_route' => '_95'], ['a', 'b', 'c'], null, null, false, false, null]], + 7230 => [[['_route' => '_338'], ['a', 'b', 'c'], null, null, false, false, null]], + 7277 => [[['_route' => '_401'], ['a', 'b', 'c'], null, null, false, false, null]], + 7329 => [[['_route' => '_147'], ['a', 'b', 'c'], null, null, false, false, null]], + 7376 => [[['_route' => '_319'], ['a', 'b', 'c'], null, null, false, false, null]], + 7423 => [[['_route' => '_354'], ['a', 'b', 'c'], null, null, false, false, null]], + 7470 => [[['_route' => '_428'], ['a', 'b', 'c'], null, null, false, false, null]], + 7522 => [[['_route' => '_162'], ['a', 'b', 'c'], null, null, false, false, null]], + 7572 => [[['_route' => '_175'], ['a', 'b', 'c'], null, null, false, false, null]], + 7618 => [[['_route' => '_455'], ['a', 'b', 'c'], null, null, false, false, null]], + 7666 => [[['_route' => '_355'], ['a', 'b', 'c'], null, null, false, false, null]], + 7718 => [[['_route' => '_197'], ['a', 'b', 'c'], null, null, false, false, null]], + 7768 => [[['_route' => '_202'], ['a', 'b', 'c'], null, null, false, false, null]], + 7813 => [[['_route' => '_489'], ['a', 'b', 'c'], null, null, false, false, null]], + 7863 => [[['_route' => '_199'], ['a', 'b', 'c'], null, null, false, false, null]], + 7914 => [[['_route' => '_263'], ['a', 'b', 'c'], null, null, false, false, null]], + 7961 => [[['_route' => '_406'], ['a', 'b', 'c'], null, null, false, false, null]], + 8010 => [[['_route' => '_289'], ['a', 'b', 'c'], null, null, false, false, null]], + 8058 => [[['_route' => '_325'], ['a', 'b', 'c'], null, null, false, false, null]], + 8106 => [[['_route' => '_378'], ['a', 'b', 'c'], null, null, false, false, null]], + 8154 => [[['_route' => '_468'], ['a', 'b', 'c'], null, null, false, false, null]], + 8211 => [[['_route' => '_9'], ['a', 'b', 'c'], null, null, false, false, null]], + 8258 => [[['_route' => '_216'], ['a', 'b', 'c'], null, null, false, false, null]], + 8307 => [[['_route' => '_26'], ['a', 'b', 'c'], null, null, false, false, null]], + 8355 => [[['_route' => '_62'], ['a', 'b', 'c'], null, null, false, false, null]], + 8406 => [[['_route' => '_81'], ['a', 'b', 'c'], null, null, false, false, null]], + 8453 => [[['_route' => '_318'], ['a', 'b', 'c'], null, null, false, false, null]], + 8505 => [[['_route' => '_121'], ['a', 'b', 'c'], null, null, false, false, null]], + 8551 => [[['_route' => '_182'], ['a', 'b', 'c'], null, null, false, false, null]], + 8603 => [[['_route' => '_136'], ['a', 'b', 'c'], null, null, false, false, null]], + 8650 => [[['_route' => '_415'], ['a', 'b', 'c'], null, null, false, false, null]], + 8697 => [[['_route' => '_457'], ['a', 'b', 'c'], null, null, false, false, null]], + 8744 => [[['_route' => '_463'], ['a', 'b', 'c'], null, null, false, false, null]], + 8796 => [[['_route' => '_148'], ['a', 'b', 'c'], null, null, false, false, null]], + 8843 => [[['_route' => '_273'], ['a', 'b', 'c'], null, null, false, false, null]], + 8892 => [[['_route' => '_284'], ['a', 'b', 'c'], null, null, false, false, null]], + 8940 => [[['_route' => '_288'], ['a', 'b', 'c'], null, null, false, false, null]], + 8991 => [[['_route' => '_295'], ['a', 'b', 'c'], null, null, false, false, null]], + 9038 => [[['_route' => '_305'], ['a', 'b', 'c'], null, null, false, false, null]], + 9085 => [[['_route' => '_453'], ['a', 'b', 'c'], null, null, false, false, null]], + 9134 => [[['_route' => '_340'], ['a', 'b', 'c'], null, null, false, false, null]], + 9185 => [[['_route' => '_371'], ['a', 'b', 'c'], null, null, false, false, null]], + 9232 => [[['_route' => '_417'], ['a', 'b', 'c'], null, null, false, false, null]], + 9284 => [[['_route' => '_382'], ['a', 'b', 'c'], null, null, false, false, null]], + 9331 => [[['_route' => '_404'], ['a', 'b', 'c'], null, null, false, false, null]], + 9389 => [[['_route' => '_10'], ['a', 'b', 'c'], null, null, false, false, null]], + 9436 => [[['_route' => '_279'], ['a', 'b', 'c'], null, null, false, false, null]], + 9483 => [[['_route' => '_377'], ['a', 'b', 'c'], null, null, false, false, null]], + 9535 => [[['_route' => '_39'], ['a', 'b', 'c'], null, null, false, false, null]], + 9582 => [[['_route' => '_40'], ['a', 'b', 'c'], null, null, false, false, null]], + 9629 => [[['_route' => '_264'], ['a', 'b', 'c'], null, null, false, false, null]], + 9676 => [[['_route' => '_449'], ['a', 'b', 'c'], null, null, false, false, null]], + 9728 => [[['_route' => '_46'], ['a', 'b', 'c'], null, null, false, false, null]], + 9775 => [[['_route' => '_257'], ['a', 'b', 'c'], null, null, false, false, null]], + 9822 => [[['_route' => '_274'], ['a', 'b', 'c'], null, null, false, false, null]], + 9869 => [[['_route' => '_388'], ['a', 'b', 'c'], null, null, false, false, null]], + 9921 => [[['_route' => '_53'], ['a', 'b', 'c'], null, null, false, false, null]], + 9968 => [[['_route' => '_345'], ['a', 'b', 'c'], null, null, false, false, null]], + 10020 => [[['_route' => '_73'], ['a', 'b', 'c'], null, null, false, false, null]], + 10068 => [[['_route' => '_296'], ['a', 'b', 'c'], null, null, false, false, null]], + 10121 => [[['_route' => '_75'], ['a', 'b', 'c'], null, null, false, false, null]], + 10169 => [[['_route' => '_458'], ['a', 'b', 'c'], null, null, false, false, null]], + 10225 => [[['_route' => '_79'], ['a', 'b', 'c'], null, null, false, false, null]], + 10272 => [[['_route' => '_129'], ['a', 'b', 'c'], null, null, false, false, null]], + 10319 => [[['_route' => '_418'], ['a', 'b', 'c'], null, null, false, false, null]], + 10368 => [[['_route' => '_225'], ['a', 'b', 'c'], null, null, false, false, null]], + 10416 => [[['_route' => '_479'], ['a', 'b', 'c'], null, null, false, false, null]], + 10466 => [[['_route' => '_120'], ['a', 'b', 'c'], null, null, false, false, null]], + 10515 => [[['_route' => '_276'], ['a', 'b', 'c'], null, null, false, false, null]], + 10564 => [[['_route' => '_370'], ['a', 'b', 'c'], null, null, false, false, null]], + 10616 => [[['_route' => '_385'], ['a', 'b', 'c'], null, null, false, false, null]], + 10664 => [[['_route' => '_469'], ['a', 'b', 'c'], null, null, false, false, null]], + 10714 => [[['_route' => '_435'], ['a', 'b', 'c'], null, null, false, false, null]], + 10772 => [[['_route' => '_11'], ['a', 'b', 'c'], null, null, false, false, null]], + 10820 => [[['_route' => '_105'], ['a', 'b', 'c'], null, null, false, false, null]], + 10868 => [[['_route' => '_132'], ['a', 'b', 'c'], null, null, false, false, null]], + 10921 => [[['_route' => '_18'], ['a', 'b', 'c'], null, null, false, false, null]], + 10969 => [[['_route' => '_210'], ['a', 'b', 'c'], null, null, false, false, null]], + 11017 => [[['_route' => '_329'], ['a', 'b', 'c'], null, null, false, false, null]], + 11073 => [[['_route' => '_29'], ['a', 'b', 'c'], null, null, false, false, null]], + 11120 => [[['_route' => '_480'], ['a', 'b', 'c'], null, null, false, false, null]], + 11169 => [[['_route' => '_426'], ['a', 'b', 'c'], null, null, false, false, null]], + 11222 => [[['_route' => '_32'], ['a', 'b', 'c'], null, null, false, false, null]], + 11270 => [[['_route' => '_217'], ['a', 'b', 'c'], null, null, false, false, null]], + 11318 => [[['_route' => '_275'], ['a', 'b', 'c'], null, null, false, false, null]], + 11371 => [[['_route' => '_45'], ['a', 'b', 'c'], null, null, false, false, null]], + 11419 => [[['_route' => '_157'], ['a', 'b', 'c'], null, null, false, false, null]], + 11467 => [[['_route' => '_184'], ['a', 'b', 'c'], null, null, false, false, null]], + 11515 => [[['_route' => '_250'], ['a', 'b', 'c'], null, null, false, false, null]], + 11563 => [[['_route' => '_356'], ['a', 'b', 'c'], null, null, false, false, null]], + 11616 => [[['_route' => '_47'], ['a', 'b', 'c'], null, null, false, false, null]], + 11664 => [[['_route' => '_445'], ['a', 'b', 'c'], null, null, false, false, null]], + 11714 => [[['_route' => '_48'], ['a', 'b', 'c'], null, null, false, false, null]], + 11766 => [[['_route' => '_58'], ['a', 'b', 'c'], null, null, false, false, null]], + 11814 => [[['_route' => '_414'], ['a', 'b', 'c'], null, null, false, false, null]], + 11862 => [[['_route' => '_431'], ['a', 'b', 'c'], null, null, false, false, null]], + 11915 => [[['_route' => '_84'], ['a', 'b', 'c'], null, null, false, false, null]], + 11963 => [[['_route' => '_294'], ['a', 'b', 'c'], null, null, false, false, null]], + 12011 => [[['_route' => '_336'], ['a', 'b', 'c'], null, null, false, false, null]], + 12059 => [[['_route' => '_465'], ['a', 'b', 'c'], null, null, false, false, null]], + 12112 => [[['_route' => '_103'], ['a', 'b', 'c'], null, null, false, false, null]], + 12160 => [[['_route' => '_111'], ['a', 'b', 'c'], null, null, false, false, null]], + 12208 => [[['_route' => '_207'], ['a', 'b', 'c'], null, null, false, false, null]], + 12256 => [[['_route' => '_402'], ['a', 'b', 'c'], null, null, false, false, null]], + 12309 => [[['_route' => '_230'], ['a', 'b', 'c'], null, null, false, false, null]], + 12356 => [[['_route' => '_331'], ['a', 'b', 'c'], null, null, false, false, null]], + 12406 => [[['_route' => '_248'], ['a', 'b', 'c'], null, null, false, false, null]], + 12455 => [[['_route' => '_282'], ['a', 'b', 'c'], null, null, false, false, null]], + 12513 => [[['_route' => '_15'], ['a', 'b', 'c'], null, null, false, false, null]], + 12561 => [[['_route' => '_130'], ['a', 'b', 'c'], null, null, false, false, null]], + 12609 => [[['_route' => '_231'], ['a', 'b', 'c'], null, null, false, false, null]], + 12657 => [[['_route' => '_365'], ['a', 'b', 'c'], null, null, false, false, null]], + 12705 => [[['_route' => '_448'], ['a', 'b', 'c'], null, null, false, false, null]], + 12758 => [[['_route' => '_20'], ['a', 'b', 'c'], null, null, false, false, null]], + 12806 => [[['_route' => '_93'], ['a', 'b', 'c'], null, null, false, false, null]], + 12854 => [[['_route' => '_186'], ['a', 'b', 'c'], null, null, false, false, null]], + 12902 => [[['_route' => '_460'], ['a', 'b', 'c'], null, null, false, false, null]], + 12955 => [[['_route' => '_52'], ['a', 'b', 'c'], null, null, false, false, null]], + 13003 => [[['_route' => '_447'], ['a', 'b', 'c'], null, null, false, false, null]], + 13056 => [[['_route' => '_56'], ['a', 'b', 'c'], null, null, false, false, null]], + 13104 => [[['_route' => '_133'], ['a', 'b', 'c'], null, null, false, false, null]], + 13152 => [[['_route' => '_297'], ['a', 'b', 'c'], null, null, false, false, null]], + 13205 => [[['_route' => '_82'], ['a', 'b', 'c'], null, null, false, false, null]], + 13253 => [[['_route' => '_165'], ['a', 'b', 'c'], null, null, false, false, null]], + 13301 => [[['_route' => '_213'], ['a', 'b', 'c'], null, null, false, false, null]], + 13351 => [[['_route' => '_86'], ['a', 'b', 'c'], null, null, false, false, null]], + 13403 => [[['_route' => '_92'], ['a', 'b', 'c'], null, null, false, false, null]], + 13450 => [[['_route' => '_280'], ['a', 'b', 'c'], null, null, false, false, null]], + 13500 => [[['_route' => '_143'], ['a', 'b', 'c'], null, null, false, false, null]], + 13549 => [[['_route' => '_177'], ['a', 'b', 'c'], null, null, false, false, null]], + 13601 => [[['_route' => '_188'], ['a', 'b', 'c'], null, null, false, false, null]], + 13649 => [[['_route' => '_311'], ['a', 'b', 'c'], null, null, false, false, null]], + 13697 => [[['_route' => '_350'], ['a', 'b', 'c'], null, null, false, false, null]], + 13750 => [[['_route' => '_226'], ['a', 'b', 'c'], null, null, false, false, null]], + 13798 => [[['_route' => '_291'], ['a', 'b', 'c'], null, null, false, false, null]], + 13851 => [[['_route' => '_244'], ['a', 'b', 'c'], null, null, false, false, null]], + 13898 => [[['_route' => '_287'], ['a', 'b', 'c'], null, null, false, false, null]], + 13951 => [[['_route' => '_300'], ['a', 'b', 'c'], null, null, false, false, null]], + 13999 => [[['_route' => '_451'], ['a', 'b', 'c'], null, null, false, false, null]], + 14047 => [[['_route' => '_452'], ['a', 'b', 'c'], null, null, false, false, null]], + 14095 => [[['_route' => '_481'], ['a', 'b', 'c'], null, null, false, false, null]], + 14145 => [[['_route' => '_312'], ['a', 'b', 'c'], null, null, false, false, null]], + 14203 => [[['_route' => '_17'], ['a', 'b', 'c'], null, null, false, false, null]], + 14251 => [[['_route' => '_227'], ['a', 'b', 'c'], null, null, false, false, null]], + 14299 => [[['_route' => '_393'], ['a', 'b', 'c'], null, null, false, false, null]], + 14349 => [[['_route' => '_57'], ['a', 'b', 'c'], null, null, false, false, null]], + 14401 => [[['_route' => '_61'], ['a', 'b', 'c'], null, null, false, false, null]], + 14449 => [[['_route' => '_112'], ['a', 'b', 'c'], null, null, false, false, null]], + 14500 => [[['_route' => '_135'], ['a', 'b', 'c'], null, null, false, false, null]], + 14547 => [[['_route' => '_271'], ['a', 'b', 'c'], null, null, false, false, null]], + 14596 => [[['_route' => '_459'], ['a', 'b', 'c'], null, null, false, false, null]], + 14649 => [[['_route' => '_67'], ['a', 'b', 'c'], null, null, false, false, null]], + 14697 => [[['_route' => '_113'], ['a', 'b', 'c'], null, null, false, false, null]], + 14745 => [[['_route' => '_497'], ['a', 'b', 'c'], null, null, false, false, null]], + 14795 => [[['_route' => '_70'], ['a', 'b', 'c'], null, null, false, false, null]], + 14847 => [[['_route' => '_89'], ['a', 'b', 'c'], null, null, false, false, null]], + 14895 => [[['_route' => '_128'], ['a', 'b', 'c'], null, null, false, false, null]], + 14948 => [[['_route' => '_150'], ['a', 'b', 'c'], null, null, false, false, null]], + 14996 => [[['_route' => '_166'], ['a', 'b', 'c'], null, null, false, false, null]], + 15047 => [[['_route' => '_206'], ['a', 'b', 'c'], null, null, false, false, null]], + 15094 => [[['_route' => '_419'], ['a', 'b', 'c'], null, null, false, false, null]], + 15148 => [[['_route' => '_201'], ['a', 'b', 'c'], null, null, false, false, null]], + 15196 => [[['_route' => '_314'], ['a', 'b', 'c'], null, null, false, false, null]], + 15244 => [[['_route' => '_429'], ['a', 'b', 'c'], null, null, false, false, null]], + 15297 => [[['_route' => '_228'], ['a', 'b', 'c'], null, null, false, false, null]], + 15345 => [[['_route' => '_477'], ['a', 'b', 'c'], null, null, false, false, null]], + 15395 => [[['_route' => '_272'], ['a', 'b', 'c'], null, null, false, false, null]], + 15444 => [[['_route' => '_486'], ['a', 'b', 'c'], null, null, false, false, null]], + 15502 => [[['_route' => '_21'], ['a', 'b', 'c'], null, null, false, false, null]], + 15550 => [[['_route' => '_247'], ['a', 'b', 'c'], null, null, false, false, null]], + 15598 => [[['_route' => '_424'], ['a', 'b', 'c'], null, null, false, false, null]], + 15646 => [[['_route' => '_499'], ['a', 'b', 'c'], null, null, false, false, null]], + 15699 => [[['_route' => '_23'], ['a', 'b', 'c'], null, null, false, false, null]], + 15747 => [[['_route' => '_152'], ['a', 'b', 'c'], null, null, false, false, null]], + 15795 => [[['_route' => '_304'], ['a', 'b', 'c'], null, null, false, false, null]], + 15843 => [[['_route' => '_352'], ['a', 'b', 'c'], null, null, false, false, null]], + 15896 => [[['_route' => '_28'], ['a', 'b', 'c'], null, null, false, false, null]], + 15944 => [[['_route' => '_240'], ['a', 'b', 'c'], null, null, false, false, null]], + 16000 => [[['_route' => '_30'], ['a', 'b', 'c'], null, null, false, false, null]], + 16047 => [[['_route' => '_41'], ['a', 'b', 'c'], null, null, false, false, null]], + 16096 => [[['_route' => '_301'], ['a', 'b', 'c'], null, null, false, false, null]], + 16149 => [[['_route' => '_66'], ['a', 'b', 'c'], null, null, false, false, null]], + 16197 => [[['_route' => '_72'], ['a', 'b', 'c'], null, null, false, false, null]], + 16245 => [[['_route' => '_320'], ['a', 'b', 'c'], null, null, false, false, null]], + 16298 => [[['_route' => '_78'], ['a', 'b', 'c'], null, null, false, false, null]], + 16346 => [[['_route' => '_337'], ['a', 'b', 'c'], null, null, false, false, null]], + 16394 => [[['_route' => '_399'], ['a', 'b', 'c'], null, null, false, false, null]], + 16442 => [[['_route' => '_495'], ['a', 'b', 'c'], null, null, false, false, null]], + 16492 => [[['_route' => '_85'], ['a', 'b', 'c'], null, null, false, false, null]], + 16544 => [[['_route' => '_101'], ['a', 'b', 'c'], null, null, false, false, null]], + 16592 => [[['_route' => '_176'], ['a', 'b', 'c'], null, null, false, false, null]], + 16640 => [[['_route' => '_246'], ['a', 'b', 'c'], null, null, false, false, null]], + 16693 => [[['_route' => '_125'], ['a', 'b', 'c'], null, null, false, false, null]], + 16741 => [[['_route' => '_341'], ['a', 'b', 'c'], null, null, false, false, null]], + 16794 => [[['_route' => '_137'], ['a', 'b', 'c'], null, null, false, false, null]], + 16842 => [[['_route' => '_270'], ['a', 'b', 'c'], null, null, false, false, null]], + 16890 => [[['_route' => '_386'], ['a', 'b', 'c'], null, null, false, false, null]], + 16943 => [[['_route' => '_169'], ['a', 'b', 'c'], null, null, false, false, null]], + 16991 => [[['_route' => '_200'], ['a', 'b', 'c'], null, null, false, false, null]], + 17039 => [[['_route' => '_262'], ['a', 'b', 'c'], null, null, false, false, null]], + 17092 => [[['_route' => '_187'], ['a', 'b', 'c'], null, null, false, false, null]], + 17140 => [[['_route' => '_333'], ['a', 'b', 'c'], null, null, false, false, null]], + 17190 => [[['_route' => '_215'], ['a', 'b', 'c'], null, null, false, false, null]], + 17239 => [[['_route' => '_316'], ['a', 'b', 'c'], null, null, false, false, null]], + 17288 => [[['_route' => '_343'], ['a', 'b', 'c'], null, null, false, false, null]], + 17346 => [[['_route' => '_22'], ['a', 'b', 'c'], null, null, false, false, null]], + 17394 => [[['_route' => '_420'], ['a', 'b', 'c'], null, null, false, false, null]], + 17447 => [[['_route' => '_55'], ['a', 'b', 'c'], null, null, false, false, null]], + 17494 => [[['_route' => '_496'], ['a', 'b', 'c'], null, null, false, false, null]], + 17547 => [[['_route' => '_153'], ['a', 'b', 'c'], null, null, false, false, null]], + 17595 => [[['_route' => '_344'], ['a', 'b', 'c'], null, null, false, false, null]], + 17648 => [[['_route' => '_160'], ['a', 'b', 'c'], null, null, false, false, null]], + 17696 => [[['_route' => '_398'], ['a', 'b', 'c'], null, null, false, false, null]], + 17749 => [[['_route' => '_161'], ['a', 'b', 'c'], null, null, false, false, null]], + 17797 => [[['_route' => '_193'], ['a', 'b', 'c'], null, null, false, false, null]], + 17847 => [[['_route' => '_174'], ['a', 'b', 'c'], null, null, false, false, null]], + 17899 => [[['_route' => '_209'], ['a', 'b', 'c'], null, null, false, false, null]], + 17947 => [[['_route' => '_261'], ['a', 'b', 'c'], null, null, false, false, null]], + 18000 => [[['_route' => '_222'], ['a', 'b', 'c'], null, null, false, false, null]], + 18048 => [[['_route' => '_323'], ['a', 'b', 'c'], null, null, false, false, null]], + 18096 => [[['_route' => '_380'], ['a', 'b', 'c'], null, null, false, false, null]], + 18149 => [[['_route' => '_232'], ['a', 'b', 'c'], null, null, false, false, null]], + 18197 => [[['_route' => '_383'], ['a', 'b', 'c'], null, null, false, false, null]], + 18247 => [[['_route' => '_306'], ['a', 'b', 'c'], null, null, false, false, null]], + 18296 => [[['_route' => '_327'], ['a', 'b', 'c'], null, null, false, false, null]], + 18345 => [[['_route' => '_364'], ['a', 'b', 'c'], null, null, false, false, null]], + 18397 => [[['_route' => '_403'], ['a', 'b', 'c'], null, null, false, false, null]], + 18445 => [[['_route' => '_405'], ['a', 'b', 'c'], null, null, false, false, null]], + 18495 => [[['_route' => '_412'], ['a', 'b', 'c'], null, null, false, false, null]], + 18553 => [[['_route' => '_27'], ['a', 'b', 'c'], null, null, false, false, null]], + 18601 => [[['_route' => '_134'], ['a', 'b', 'c'], null, null, false, false, null]], + 18649 => [[['_route' => '_245'], ['a', 'b', 'c'], null, null, false, false, null]], + 18702 => [[['_route' => '_59'], ['a', 'b', 'c'], null, null, false, false, null]], + 18750 => [[['_route' => '_208'], ['a', 'b', 'c'], null, null, false, false, null]], + 18803 => [[['_route' => '_60'], ['a', 'b', 'c'], null, null, false, false, null]], + 18851 => [[['_route' => '_119'], ['a', 'b', 'c'], null, null, false, false, null]], + 18902 => [[['_route' => '_163'], ['a', 'b', 'c'], null, null, false, false, null]], + 18949 => [[['_route' => '_249'], ['a', 'b', 'c'], null, null, false, false, null]], + 18998 => [[['_route' => '_278'], ['a', 'b', 'c'], null, null, false, false, null]], + 19051 => [[['_route' => '_63'], ['a', 'b', 'c'], null, null, false, false, null]], + 19099 => [[['_route' => '_195'], ['a', 'b', 'c'], null, null, false, false, null]], + 19147 => [[['_route' => '_252'], ['a', 'b', 'c'], null, null, false, false, null]], + 19195 => [[['_route' => '_461'], ['a', 'b', 'c'], null, null, false, false, null]], + 19248 => [[['_route' => '_126'], ['a', 'b', 'c'], null, null, false, false, null]], + 19296 => [[['_route' => '_158'], ['a', 'b', 'c'], null, null, false, false, null]], + 19344 => [[['_route' => '_221'], ['a', 'b', 'c'], null, null, false, false, null]], + 19392 => [[['_route' => '_269'], ['a', 'b', 'c'], null, null, false, false, null]], + 19440 => [[['_route' => '_310'], ['a', 'b', 'c'], null, null, false, false, null]], + 19496 => [[['_route' => '_138'], ['a', 'b', 'c'], null, null, false, false, null]], + 19543 => [[['_route' => '_348'], ['a', 'b', 'c'], null, null, false, false, null]], + 19592 => [[['_route' => '_236'], ['a', 'b', 'c'], null, null, false, false, null]], + 19640 => [[['_route' => '_433'], ['a', 'b', 'c'], null, null, false, false, null]], + 19693 => [[['_route' => '_141'], ['a', 'b', 'c'], null, null, false, false, null]], + 19741 => [[['_route' => '_283'], ['a', 'b', 'c'], null, null, false, false, null]], + 19794 => [[['_route' => '_144'], ['a', 'b', 'c'], null, null, false, false, null]], + 19842 => [[['_route' => '_191'], ['a', 'b', 'c'], null, null, false, false, null]], + 19895 => [[['_route' => '_168'], ['a', 'b', 'c'], null, null, false, false, null]], + 19943 => [[['_route' => '_363'], ['a', 'b', 'c'], null, null, false, false, null]], + 19991 => [[['_route' => '_381'], ['a', 'b', 'c'], null, null, false, false, null]], + 20044 => [[['_route' => '_180'], ['a', 'b', 'c'], null, null, false, false, null]], + 20092 => [[['_route' => '_339'], ['a', 'b', 'c'], null, null, false, false, null]], + 20142 => [[['_route' => '_196'], ['a', 'b', 'c'], null, null, false, false, null]], + 20194 => [[['_route' => '_198'], ['a', 'b', 'c'], null, null, false, false, null]], + 20242 => [[['_route' => '_285'], ['a', 'b', 'c'], null, null, false, false, null]], + 20292 => [[['_route' => '_349'], ['a', 'b', 'c'], null, null, false, false, null]], + 20344 => [[['_route' => '_367'], ['a', 'b', 'c'], null, null, false, false, null]], + 20392 => [[['_route' => '_384'], ['a', 'b', 'c'], null, null, false, false, null]], + 20440 => [[['_route' => '_498'], ['a', 'b', 'c'], null, null, false, false, null]], + 20490 => [[['_route' => '_369'], ['a', 'b', 'c'], null, null, false, false, null]], + 20542 => [[['_route' => '_408'], ['a', 'b', 'c'], null, null, false, false, null]], + 20590 => [[['_route' => '_413'], ['a', 'b', 'c'], null, null, false, false, null]], + 20652 => [[['_route' => '_44'], ['a', 'b', 'c'], null, null, false, false, null]], + 20699 => [[['_route' => '_256'], ['a', 'b', 'c'], null, null, false, false, null]], + 20748 => [[['_route' => '_173'], ['a', 'b', 'c'], null, null, false, false, null]], + 20796 => [[['_route' => '_266'], ['a', 'b', 'c'], null, null, false, false, null]], + 20844 => [[['_route' => '_392'], ['a', 'b', 'c'], null, null, false, false, null]], + 20892 => [[['_route' => '_430'], ['a', 'b', 'c'], null, null, false, false, null]], + 20940 => [[['_route' => '_482'], ['a', 'b', 'c'], null, null, false, false, null]], + 20993 => [[['_route' => '_49'], ['a', 'b', 'c'], null, null, false, false, null]], + 21041 => [[['_route' => '_94'], ['a', 'b', 'c'], null, null, false, false, null]], + 21089 => [[['_route' => '_407'], ['a', 'b', 'c'], null, null, false, false, null]], + 21142 => [[['_route' => '_65'], ['a', 'b', 'c'], null, null, false, false, null]], + 21190 => [[['_route' => '_181'], ['a', 'b', 'c'], null, null, false, false, null]], + 21238 => [[['_route' => '_437'], ['a', 'b', 'c'], null, null, false, false, null]], + 21291 => [[['_route' => '_76'], ['a', 'b', 'c'], null, null, false, false, null]], + 21339 => [[['_route' => '_357'], ['a', 'b', 'c'], null, null, false, false, null]], + 21392 => [[['_route' => '_80'], ['a', 'b', 'c'], null, null, false, false, null]], + 21440 => [[['_route' => '_106'], ['a', 'b', 'c'], null, null, false, false, null]], + 21493 => [[['_route' => '_83'], ['a', 'b', 'c'], null, null, false, false, null]], + 21541 => [[['_route' => '_255'], ['a', 'b', 'c'], null, null, false, false, null]], + 21589 => [[['_route' => '_330'], ['a', 'b', 'c'], null, null, false, false, null]], + 21642 => [[['_route' => '_100'], ['a', 'b', 'c'], null, null, false, false, null]], + 21690 => [[['_route' => '_396'], ['a', 'b', 'c'], null, null, false, false, null]], + 21738 => [[['_route' => '_422'], ['a', 'b', 'c'], null, null, false, false, null]], + 21791 => [[['_route' => '_149'], ['a', 'b', 'c'], null, null, false, false, null]], + 21839 => [[['_route' => '_324'], ['a', 'b', 'c'], null, null, false, false, null]], + 21892 => [[['_route' => '_164'], ['a', 'b', 'c'], null, null, false, false, null]], + 21940 => [[['_route' => '_423'], ['a', 'b', 'c'], null, null, false, false, null]], + 21990 => [[['_route' => '_241'], ['a', 'b', 'c'], null, null, false, false, null]], + 22042 => [[['_route' => '_290'], ['a', 'b', 'c'], null, null, false, false, null]], + 22090 => [[['_route' => '_335'], ['a', 'b', 'c'], null, null, false, false, null]], + 22140 => [[['_route' => '_373'], ['a', 'b', 'c'], null, null, false, false, null]], + 22189 => [[['_route' => '_375'], ['a', 'b', 'c'], null, null, false, false, null]], + 22238 => [[['_route' => '_450'], ['a', 'b', 'c'], null, null, false, false, null]], + 22287 => [[['_route' => '_464'], ['a', 'b', 'c'], null, null, false, false, null]], + 22345 => [[['_route' => '_51'], ['a', 'b', 'c'], null, null, false, false, null]], + 22393 => [[['_route' => '_77'], ['a', 'b', 'c'], null, null, false, false, null]], + 22441 => [[['_route' => '_234'], ['a', 'b', 'c'], null, null, false, false, null]], + 22489 => [[['_route' => '_394'], ['a', 'b', 'c'], null, null, false, false, null]], + 22542 => [[['_route' => '_88'], ['a', 'b', 'c'], null, null, false, false, null]], + 22590 => [[['_route' => '_155'], ['a', 'b', 'c'], null, null, false, false, null]], + 22643 => [[['_route' => '_96'], ['a', 'b', 'c'], null, null, false, false, null]], + 22691 => [[['_route' => '_298'], ['a', 'b', 'c'], null, null, false, false, null]], + 22739 => [[['_route' => '_470'], ['a', 'b', 'c'], null, null, false, false, null]], + 22792 => [[['_route' => '_109'], ['a', 'b', 'c'], null, null, false, false, null]], + 22840 => [[['_route' => '_204'], ['a', 'b', 'c'], null, null, false, false, null]], + 22893 => [[['_route' => '_115'], ['a', 'b', 'c'], null, null, false, false, null]], + 22941 => [[['_route' => '_145'], ['a', 'b', 'c'], null, null, false, false, null]], + 22994 => [[['_route' => '_123'], ['a', 'b', 'c'], null, null, false, false, null]], + 23042 => [[['_route' => '_277'], ['a', 'b', 'c'], null, null, false, false, null]], + 23090 => [[['_route' => '_473'], ['a', 'b', 'c'], null, null, false, false, null]], + 23143 => [[['_route' => '_334'], ['a', 'b', 'c'], null, null, false, false, null]], + 23191 => [[['_route' => '_493'], ['a', 'b', 'c'], null, null, false, false, null]], + 23244 => [[['_route' => '_372'], ['a', 'b', 'c'], null, null, false, false, null]], + 23292 => [[['_route' => '_432'], ['a', 'b', 'c'], null, null, false, false, null]], + 23340 => [[['_route' => '_436'], ['a', 'b', 'c'], null, null, false, false, null]], + 23393 => [[['_route' => '_425'], ['a', 'b', 'c'], null, null, false, false, null]], + 23441 => [[['_route' => '_456'], ['a', 'b', 'c'], null, null, false, false, null]], + 23489 => [[['_route' => '_474'], ['a', 'b', 'c'], null, null, false, false, null]], + 23539 => [[['_route' => '_485'], ['a', 'b', 'c'], null, null, false, false, null]], + 23594 => [[['_route' => '_91'], ['a', 'b', 'c'], null, null, false, false, null]], + 23646 => [[['_route' => '_110'], ['a', 'b', 'c'], null, null, false, false, null]], + 23694 => [[['_route' => '_114'], ['a', 'b', 'c'], null, null, false, false, null]], + 23750 => [[['_route' => '_118'], ['a', 'b', 'c'], null, null, false, false, null]], + 23796 => [[['_route' => '_475'], ['a', 'b', 'c'], null, null, false, false, null]], + 23844 => [[['_route' => '_366'], ['a', 'b', 'c'], null, null, false, false, null]], + 23897 => [[['_route' => '_167'], ['a', 'b', 'c'], null, null, false, false, null]], + 23945 => [[['_route' => '_192'], ['a', 'b', 'c'], null, null, false, false, null]], + 23993 => [[['_route' => '_342'], ['a', 'b', 'c'], null, null, false, false, null]], + 24046 => [[['_route' => '_229'], ['a', 'b', 'c'], null, null, false, false, null]], + 24097 => [[['_route' => '_235'], ['a', 'b', 'c'], null, null, false, false, null]], + 24144 => [[['_route' => '_302'], ['a', 'b', 'c'], null, null, false, false, null]], + 24193 => [[['_route' => '_322'], ['a', 'b', 'c'], null, null, false, false, null]], + 24246 => [[['_route' => '_237'], ['a', 'b', 'c'], null, null, false, false, null]], + 24294 => [[['_route' => '_293'], ['a', 'b', 'c'], null, null, false, false, null]], + 24347 => [[['_route' => '_239'], ['a', 'b', 'c'], null, null, false, false, null]], + 24395 => [[['_route' => '_444'], ['a', 'b', 'c'], null, null, false, false, null]], + 24443 => [[['_route' => '_491'], ['a', 'b', 'c'], null, null, false, false, null]], + 24491 => [[['_route' => '_492'], ['a', 'b', 'c'], null, null, false, false, null]], + 24541 => [[['_route' => '_258'], ['a', 'b', 'c'], null, null, false, false, null]], + 24590 => [[['_route' => '_317'], ['a', 'b', 'c'], null, null, false, false, null]], + 24639 => [[['_route' => '_361'], ['a', 'b', 'c'], null, null, false, false, null]], + 24688 => [[['_route' => '_391'], ['a', 'b', 'c'], null, null, false, false, null]], + 24737 => [[['_route' => '_462'], ['a', 'b', 'c'], null, null, false, false, null]], + 24786 => [[['_route' => '_476'], ['a', 'b', 'c'], null, null, false, false, null]], + 24837 => [[['_route' => '_501'], ['a', 'b', 'c'], null, null, false, false, null]], + 24889 => [[['_route' => '_514'], ['a', 'b', 'c'], null, null, false, false, null]], + 24937 => [[['_route' => '_731'], ['a', 'b', 'c'], null, null, false, false, null]], + 24990 => [[['_route' => '_522'], ['a', 'b', 'c'], null, null, false, false, null]], + 25038 => [[['_route' => '_693'], ['a', 'b', 'c'], null, null, false, false, null]], + 25091 => [[['_route' => '_537'], ['a', 'b', 'c'], null, null, false, false, null]], + 25139 => [[['_route' => '_554'], ['a', 'b', 'c'], null, null, false, false, null]], + 25187 => [[['_route' => '_645'], ['a', 'b', 'c'], null, null, false, false, null]], + 25235 => [[['_route' => '_862'], ['a', 'b', 'c'], null, null, false, false, null]], + 25288 => [[['_route' => '_539'], ['a', 'b', 'c'], null, null, false, false, null]], + 25336 => [[['_route' => '_729'], ['a', 'b', 'c'], null, null, false, false, null]], + 25384 => [[['_route' => '_897'], ['a', 'b', 'c'], null, null, false, false, null]], + 25437 => [[['_route' => '_561'], ['a', 'b', 'c'], null, null, false, false, null]], + 25485 => [[['_route' => '_615'], ['a', 'b', 'c'], null, null, false, false, null]], + 25533 => [[['_route' => '_764'], ['a', 'b', 'c'], null, null, false, false, null]], + 25581 => [[['_route' => '_948'], ['a', 'b', 'c'], null, null, false, false, null]], + 25634 => [[['_route' => '_617'], ['a', 'b', 'c'], null, null, false, false, null]], + 25682 => [[['_route' => '_671'], ['a', 'b', 'c'], null, null, false, false, null]], + 25735 => [[['_route' => '_649'], ['a', 'b', 'c'], null, null, false, false, null]], + 25783 => [[['_route' => '_651'], ['a', 'b', 'c'], null, null, false, false, null]], + 25831 => [[['_route' => '_684'], ['a', 'b', 'c'], null, null, false, false, null]], + 25884 => [[['_route' => '_669'], ['a', 'b', 'c'], null, null, false, false, null]], + 25932 => [[['_route' => '_743'], ['a', 'b', 'c'], null, null, false, false, null]], + 25980 => [[['_route' => '_962'], ['a', 'b', 'c'], null, null, false, false, null]], + 26033 => [[['_route' => '_694'], ['a', 'b', 'c'], null, null, false, false, null]], + 26081 => [[['_route' => '_985'], ['a', 'b', 'c'], null, null, false, false, null]], + 26134 => [[['_route' => '_707'], ['a', 'b', 'c'], null, null, false, false, null]], + 26182 => [[['_route' => '_718'], ['a', 'b', 'c'], null, null, false, false, null]], + 26235 => [[['_route' => '_720'], ['a', 'b', 'c'], null, null, false, false, null]], + 26283 => [[['_route' => '_745'], ['a', 'b', 'c'], null, null, false, false, null]], + 26333 => [[['_route' => '_874'], ['a', 'b', 'c'], null, null, false, false, null]], + 26391 => [[['_route' => '_502'], ['a', 'b', 'c'], null, null, false, false, null]], + 26439 => [[['_route' => '_667'], ['a', 'b', 'c'], null, null, false, false, null]], + 26487 => [[['_route' => '_911'], ['a', 'b', 'c'], null, null, false, false, null]], + 26535 => [[['_route' => '_942'], ['a', 'b', 'c'], null, null, false, false, null]], + 26585 => [[['_route' => '_504'], ['a', 'b', 'c'], null, null, false, false, null]], + 26637 => [[['_route' => '_524'], ['a', 'b', 'c'], null, null, false, false, null]], + 26685 => [[['_route' => '_732'], ['a', 'b', 'c'], null, null, false, false, null]], + 26738 => [[['_route' => '_596'], ['a', 'b', 'c'], null, null, false, false, null]], + 26786 => [[['_route' => '_601'], ['a', 'b', 'c'], null, null, false, false, null]], + 26839 => [[['_route' => '_620'], ['a', 'b', 'c'], null, null, false, false, null]], + 26887 => [[['_route' => '_631'], ['a', 'b', 'c'], null, null, false, false, null]], + 26935 => [[['_route' => '_771'], ['a', 'b', 'c'], null, null, false, false, null]], + 26983 => [[['_route' => '_937'], ['a', 'b', 'c'], null, null, false, false, null]], + 27031 => [[['_route' => '_999'], ['a', 'b', 'c'], null, null, false, false, null]], + 27084 => [[['_route' => '_657'], ['a', 'b', 'c'], null, null, false, false, null]], + 27132 => [[['_route' => '_701'], ['a', 'b', 'c'], null, null, false, false, null]], + 27185 => [[['_route' => '_662'], ['a', 'b', 'c'], null, null, false, false, null]], + 27233 => [[['_route' => '_797'], ['a', 'b', 'c'], null, null, false, false, null]], + 27281 => [[['_route' => '_924'], ['a', 'b', 'c'], null, null, false, false, null]], + 27334 => [[['_route' => '_702'], ['a', 'b', 'c'], null, null, false, false, null]], + 27382 => [[['_route' => '_750'], ['a', 'b', 'c'], null, null, false, false, null]], + 27435 => [[['_route' => '_749'], ['a', 'b', 'c'], null, null, false, false, null]], + 27483 => [[['_route' => '_837'], ['a', 'b', 'c'], null, null, false, false, null]], + 27533 => [[['_route' => '_758'], ['a', 'b', 'c'], null, null, false, false, null]], + 27585 => [[['_route' => '_810'], ['a', 'b', 'c'], null, null, false, false, null]], + 27633 => [[['_route' => '_902'], ['a', 'b', 'c'], null, null, false, false, null]], + 27683 => [[['_route' => '_845'], ['a', 'b', 'c'], null, null, false, false, null]], + 27741 => [[['_route' => '_503'], ['a', 'b', 'c'], null, null, false, false, null]], + 27792 => [[['_route' => '_756'], ['a', 'b', 'c'], null, null, false, false, null]], + 27839 => [[['_route' => '_799'], ['a', 'b', 'c'], null, null, false, false, null]], + 27888 => [[['_route' => '_769'], ['a', 'b', 'c'], null, null, false, false, null]], + 27936 => [[['_route' => '_981'], ['a', 'b', 'c'], null, null, false, false, null]], + 27989 => [[['_route' => '_507'], ['a', 'b', 'c'], null, null, false, false, null]], + 28037 => [[['_route' => '_672'], ['a', 'b', 'c'], null, null, false, false, null]], + 28085 => [[['_route' => '_790'], ['a', 'b', 'c'], null, null, false, false, null]], + 28138 => [[['_route' => '_515'], ['a', 'b', 'c'], null, null, false, false, null]], + 28186 => [[['_route' => '_523'], ['a', 'b', 'c'], null, null, false, false, null]], + 28234 => [[['_route' => '_957'], ['a', 'b', 'c'], null, null, false, false, null]], + 28282 => [[['_route' => '_995'], ['a', 'b', 'c'], null, null, false, false, null]], + 28335 => [[['_route' => '_532'], ['a', 'b', 'c'], null, null, false, false, null]], + 28383 => [[['_route' => '_642'], ['a', 'b', 'c'], null, null, false, false, null]], + 28433 => [[['_route' => '_579'], ['a', 'b', 'c'], null, null, false, false, null]], + 28485 => [[['_route' => '_625'], ['a', 'b', 'c'], null, null, false, false, null]], + 28533 => [[['_route' => '_916'], ['a', 'b', 'c'], null, null, false, false, null]], + 28586 => [[['_route' => '_633'], ['a', 'b', 'c'], null, null, false, false, null]], + 28634 => [[['_route' => '_656'], ['a', 'b', 'c'], null, null, false, false, null]], + 28687 => [[['_route' => '_658'], ['a', 'b', 'c'], null, null, false, false, null]], + 28735 => [[['_route' => '_943'], ['a', 'b', 'c'], null, null, false, false, null]], + 28788 => [[['_route' => '_664'], ['a', 'b', 'c'], null, null, false, false, null]], + 28836 => [[['_route' => '_852'], ['a', 'b', 'c'], null, null, false, false, null]], + 28884 => [[['_route' => '_870'], ['a', 'b', 'c'], null, null, false, false, null]], + 28937 => [[['_route' => '_683'], ['a', 'b', 'c'], null, null, false, false, null]], + 28985 => [[['_route' => '_915'], ['a', 'b', 'c'], null, null, false, false, null]], + 29038 => [[['_route' => '_719'], ['a', 'b', 'c'], null, null, false, false, null]], + 29086 => [[['_route' => '_859'], ['a', 'b', 'c'], null, null, false, false, null]], + 29134 => [[['_route' => '_912'], ['a', 'b', 'c'], null, null, false, false, null]], + 29182 => [[['_route' => '_978'], ['a', 'b', 'c'], null, null, false, false, null]], + 29235 => [[['_route' => '_738'], ['a', 'b', 'c'], null, null, false, false, null]], + 29283 => [[['_route' => '_883'], ['a', 'b', 'c'], null, null, false, false, null]], + 29333 => [[['_route' => '_741'], ['a', 'b', 'c'], null, null, false, false, null]], + 29382 => [[['_route' => '_760'], ['a', 'b', 'c'], null, null, false, false, null]], + 29431 => [[['_route' => '_895'], ['a', 'b', 'c'], null, null, false, false, null]], + 29489 => [[['_route' => '_505'], ['a', 'b', 'c'], null, null, false, false, null]], + 29537 => [[['_route' => '_935'], ['a', 'b', 'c'], null, null, false, false, null]], + 29590 => [[['_route' => '_509'], ['a', 'b', 'c'], null, null, false, false, null]], + 29638 => [[['_route' => '_820'], ['a', 'b', 'c'], null, null, false, false, null]], + 29686 => [[['_route' => '_910'], ['a', 'b', 'c'], null, null, false, false, null]], + 29739 => [[['_route' => '_518'], ['a', 'b', 'c'], null, null, false, false, null]], + 29787 => [[['_route' => '_618'], ['a', 'b', 'c'], null, null, false, false, null]], + 29840 => [[['_route' => '_546'], ['a', 'b', 'c'], null, null, false, false, null]], + 29888 => [[['_route' => '_740'], ['a', 'b', 'c'], null, null, false, false, null]], + 29936 => [[['_route' => '_867'], ['a', 'b', 'c'], null, null, false, false, null]], + 29989 => [[['_route' => '_572'], ['a', 'b', 'c'], null, null, false, false, null]], + 30037 => [[['_route' => '_952'], ['a', 'b', 'c'], null, null, false, false, null]], + 30090 => [[['_route' => '_573'], ['a', 'b', 'c'], null, null, false, false, null]], + 30138 => [[['_route' => '_692'], ['a', 'b', 'c'], null, null, false, false, null]], + 30186 => [[['_route' => '_700'], ['a', 'b', 'c'], null, null, false, false, null]], + 30234 => [[['_route' => '_772'], ['a', 'b', 'c'], null, null, false, false, null]], + 30284 => [[['_route' => '_653'], ['a', 'b', 'c'], null, null, false, false, null]], + 30336 => [[['_route' => '_695'], ['a', 'b', 'c'], null, null, false, false, null]], + 30384 => [[['_route' => '_748'], ['a', 'b', 'c'], null, null, false, false, null]], + 30437 => [[['_route' => '_710'], ['a', 'b', 'c'], null, null, false, false, null]], + 30485 => [[['_route' => '_716'], ['a', 'b', 'c'], null, null, false, false, null]], + 30533 => [[['_route' => '_969'], ['a', 'b', 'c'], null, null, false, false, null]], + 30586 => [[['_route' => '_734'], ['a', 'b', 'c'], null, null, false, false, null]], + 30634 => [[['_route' => '_742'], ['a', 'b', 'c'], null, null, false, false, null]], + 30682 => [[['_route' => '_844'], ['a', 'b', 'c'], null, null, false, false, null]], + 30735 => [[['_route' => '_763'], ['a', 'b', 'c'], null, null, false, false, null]], + 30783 => [[['_route' => '_965'], ['a', 'b', 'c'], null, null, false, false, null]], + 30836 => [[['_route' => '_778'], ['a', 'b', 'c'], null, null, false, false, null]], + 30884 => [[['_route' => '_813'], ['a', 'b', 'c'], null, null, false, false, null]], + 30932 => [[['_route' => '_831'], ['a', 'b', 'c'], null, null, false, false, null]], + 30982 => [[['_route' => '_955'], ['a', 'b', 'c'], null, null, false, false, null]], + 31031 => [[['_route' => '_997'], ['a', 'b', 'c'], null, null, false, false, null]], + 31089 => [[['_route' => '_506'], ['a', 'b', 'c'], null, null, false, false, null]], + 31137 => [[['_route' => '_575'], ['a', 'b', 'c'], null, null, false, false, null]], + 31190 => [[['_route' => '_516'], ['a', 'b', 'c'], null, null, false, false, null]], + 31238 => [[['_route' => '_553'], ['a', 'b', 'c'], null, null, false, false, null]], + 31291 => [[['_route' => '_528'], ['a', 'b', 'c'], null, null, false, false, null]], + 31339 => [[['_route' => '_847'], ['a', 'b', 'c'], null, null, false, false, null]], + 31387 => [[['_route' => '_904'], ['a', 'b', 'c'], null, null, false, false, null]], + 31440 => [[['_route' => '_574'], ['a', 'b', 'c'], null, null, false, false, null]], + 31488 => [[['_route' => '_818'], ['a', 'b', 'c'], null, null, false, false, null]], + 31538 => [[['_route' => '_577'], ['a', 'b', 'c'], null, null, false, false, null]], + 31590 => [[['_route' => '_584'], ['a', 'b', 'c'], null, null, false, false, null]], + 31638 => [[['_route' => '_905'], ['a', 'b', 'c'], null, null, false, false, null]], + 31691 => [[['_route' => '_612'], ['a', 'b', 'c'], null, null, false, false, null]], + 31739 => [[['_route' => '_688'], ['a', 'b', 'c'], null, null, false, false, null]], + 31787 => [[['_route' => '_854'], ['a', 'b', 'c'], null, null, false, false, null]], + 31840 => [[['_route' => '_613'], ['a', 'b', 'c'], null, null, false, false, null]], + 31888 => [[['_route' => '_767'], ['a', 'b', 'c'], null, null, false, false, null]], + 31941 => [[['_route' => '_666'], ['a', 'b', 'c'], null, null, false, false, null]], + 31989 => [[['_route' => '_759'], ['a', 'b', 'c'], null, null, false, false, null]], + 32037 => [[['_route' => '_827'], ['a', 'b', 'c'], null, null, false, false, null]], + 32085 => [[['_route' => '_840'], ['a', 'b', 'c'], null, null, false, false, null]], + 32138 => [[['_route' => '_680'], ['a', 'b', 'c'], null, null, false, false, null]], + 32186 => [[['_route' => '_784'], ['a', 'b', 'c'], null, null, false, false, null]], + 32234 => [[['_route' => '_842'], ['a', 'b', 'c'], null, null, false, false, null]], + 32282 => [[['_route' => '_860'], ['a', 'b', 'c'], null, null, false, false, null]], + 32332 => [[['_route' => '_704'], ['a', 'b', 'c'], null, null, false, false, null]], + 32381 => [[['_route' => '_727'], ['a', 'b', 'c'], null, null, false, false, null]], + 32430 => [[['_route' => '_777'], ['a', 'b', 'c'], null, null, false, false, null]], + 32482 => [[['_route' => '_838'], ['a', 'b', 'c'], null, null, false, false, null]], + 32530 => [[['_route' => '_861'], ['a', 'b', 'c'], null, null, false, false, null]], + 32583 => [[['_route' => '_849'], ['a', 'b', 'c'], null, null, false, false, null]], + 32631 => [[['_route' => '_982'], ['a', 'b', 'c'], null, null, false, false, null]], + 32679 => [[['_route' => '_986'], ['a', 'b', 'c'], null, null, false, false, null]], + 32741 => [[['_route' => '_508'], ['a', 'b', 'c'], null, null, false, false, null]], + 32788 => [[['_route' => '_517'], ['a', 'b', 'c'], null, null, false, false, null]], + 32837 => [[['_route' => '_622'], ['a', 'b', 'c'], null, null, false, false, null]], + 32890 => [[['_route' => '_513'], ['a', 'b', 'c'], null, null, false, false, null]], + 32938 => [[['_route' => '_655'], ['a', 'b', 'c'], null, null, false, false, null]], + 32986 => [[['_route' => '_843'], ['a', 'b', 'c'], null, null, false, false, null]], + 33034 => [[['_route' => '_939'], ['a', 'b', 'c'], null, null, false, false, null]], + 33084 => [[['_route' => '_529'], ['a', 'b', 'c'], null, null, false, false, null]], + 33136 => [[['_route' => '_535'], ['a', 'b', 'c'], null, null, false, false, null]], + 33184 => [[['_route' => '_685'], ['a', 'b', 'c'], null, null, false, false, null]], + 33240 => [[['_route' => '_559'], ['a', 'b', 'c'], null, null, false, false, null]], + 33287 => [[['_route' => '_661'], ['a', 'b', 'c'], null, null, false, false, null]], + 33336 => [[['_route' => '_768'], ['a', 'b', 'c'], null, null, false, false, null]], + 33389 => [[['_route' => '_589'], ['a', 'b', 'c'], null, null, false, false, null]], + 33437 => [[['_route' => '_647'], ['a', 'b', 'c'], null, null, false, false, null]], + 33485 => [[['_route' => '_652'], ['a', 'b', 'c'], null, null, false, false, null]], + 33533 => [[['_route' => '_834'], ['a', 'b', 'c'], null, null, false, false, null]], + 33586 => [[['_route' => '_591'], ['a', 'b', 'c'], null, null, false, false, null]], + 33634 => [[['_route' => '_599'], ['a', 'b', 'c'], null, null, false, false, null]], + 33687 => [[['_route' => '_787'], ['a', 'b', 'c'], null, null, false, false, null]], + 33734 => [[['_route' => '_848'], ['a', 'b', 'c'], null, null, false, false, null]], + 33787 => [[['_route' => '_796'], ['a', 'b', 'c'], null, null, false, false, null]], + 33835 => [[['_route' => '_877'], ['a', 'b', 'c'], null, null, false, false, null]], + 33885 => [[['_route' => '_809'], ['a', 'b', 'c'], null, null, false, false, null]], + 33934 => [[['_route' => '_817'], ['a', 'b', 'c'], null, null, false, false, null]], + 33986 => [[['_route' => '_819'], ['a', 'b', 'c'], null, null, false, false, null]], + 34034 => [[['_route' => '_865'], ['a', 'b', 'c'], null, null, false, false, null]], + 34084 => [[['_route' => '_919'], ['a', 'b', 'c'], null, null, false, false, null]], + 34133 => [[['_route' => '_949'], ['a', 'b', 'c'], null, null, false, false, null]], + 34191 => [[['_route' => '_510'], ['a', 'b', 'c'], null, null, false, false, null]], + 34239 => [[['_route' => '_590'], ['a', 'b', 'c'], null, null, false, false, null]], + 34287 => [[['_route' => '_597'], ['a', 'b', 'c'], null, null, false, false, null]], + 34335 => [[['_route' => '_682'], ['a', 'b', 'c'], null, null, false, false, null]], + 34383 => [[['_route' => '_723'], ['a', 'b', 'c'], null, null, false, false, null]], + 34436 => [[['_route' => '_521'], ['a', 'b', 'c'], null, null, false, false, null]], + 34484 => [[['_route' => '_594'], ['a', 'b', 'c'], null, null, false, false, null]], + 34532 => [[['_route' => '_689'], ['a', 'b', 'c'], null, null, false, false, null]], + 34580 => [[['_route' => '_713'], ['a', 'b', 'c'], null, null, false, false, null]], + 34628 => [[['_route' => '_889'], ['a', 'b', 'c'], null, null, false, false, null]], + 34681 => [[['_route' => '_531'], ['a', 'b', 'c'], null, null, false, false, null]], + 34729 => [[['_route' => '_639'], ['a', 'b', 'c'], null, null, false, false, null]], + 34780 => [[['_route' => '_646'], ['a', 'b', 'c'], null, null, false, false, null]], + 34827 => [[['_route' => '_659'], ['a', 'b', 'c'], null, null, false, false, null]], + 34876 => [[['_route' => '_959'], ['a', 'b', 'c'], null, null, false, false, null]], + 34929 => [[['_route' => '_550'], ['a', 'b', 'c'], null, null, false, false, null]], + 34977 => [[['_route' => '_833'], ['a', 'b', 'c'], null, null, false, false, null]], + 35025 => [[['_route' => '_899'], ['a', 'b', 'c'], null, null, false, false, null]], + 35081 => [[['_route' => '_580'], ['a', 'b', 'c'], null, null, false, false, null]], + 35128 => [[['_route' => '_762'], ['a', 'b', 'c'], null, null, false, false, null]], + 35177 => [[['_route' => '_896'], ['a', 'b', 'c'], null, null, false, false, null]], + 35230 => [[['_route' => '_595'], ['a', 'b', 'c'], null, null, false, false, null]], + 35278 => [[['_route' => '_933'], ['a', 'b', 'c'], null, null, false, false, null]], + 35328 => [[['_route' => '_610'], ['a', 'b', 'c'], null, null, false, false, null]], + 35380 => [[['_route' => '_629'], ['a', 'b', 'c'], null, null, false, false, null]], + 35428 => [[['_route' => '_744'], ['a', 'b', 'c'], null, null, false, false, null]], + 35481 => [[['_route' => '_674'], ['a', 'b', 'c'], null, null, false, false, null]], + 35529 => [[['_route' => '_726'], ['a', 'b', 'c'], null, null, false, false, null]], + 35577 => [[['_route' => '_929'], ['a', 'b', 'c'], null, null, false, false, null]], + 35627 => [[['_route' => '_696'], ['a', 'b', 'c'], null, null, false, false, null]], + 35679 => [[['_route' => '_841'], ['a', 'b', 'c'], null, null, false, false, null]], + 35727 => [[['_route' => '_890'], ['a', 'b', 'c'], null, null, false, false, null]], + 35777 => [[['_route' => '_885'], ['a', 'b', 'c'], null, null, false, false, null]], + 35826 => [[['_route' => '_888'], ['a', 'b', 'c'], null, null, false, false, null]], + 35875 => [[['_route' => '_996'], ['a', 'b', 'c'], null, null, false, false, null]], + 35933 => [[['_route' => '_511'], ['a', 'b', 'c'], null, null, false, false, null]], + 35981 => [[['_route' => '_576'], ['a', 'b', 'c'], null, null, false, false, null]], + 36029 => [[['_route' => '_623'], ['a', 'b', 'c'], null, null, false, false, null]], + 36082 => [[['_route' => '_560'], ['a', 'b', 'c'], null, null, false, false, null]], + 36129 => [[['_route' => '_585'], ['a', 'b', 'c'], null, null, false, false, null]], + 36182 => [[['_route' => '_570'], ['a', 'b', 'c'], null, null, false, false, null]], + 36230 => [[['_route' => '_578'], ['a', 'b', 'c'], null, null, false, false, null]], + 36281 => [[['_route' => '_780'], ['a', 'b', 'c'], null, null, false, false, null]], + 36328 => [[['_route' => '_808'], ['a', 'b', 'c'], null, null, false, false, null]], + 36382 => [[['_route' => '_593'], ['a', 'b', 'c'], null, null, false, false, null]], + 36430 => [[['_route' => '_900'], ['a', 'b', 'c'], null, null, false, false, null]], + 36483 => [[['_route' => '_632'], ['a', 'b', 'c'], null, null, false, false, null]], + 36531 => [[['_route' => '_654'], ['a', 'b', 'c'], null, null, false, false, null]], + 36579 => [[['_route' => '_721'], ['a', 'b', 'c'], null, null, false, false, null]], + 36627 => [[['_route' => '_836'], ['a', 'b', 'c'], null, null, false, false, null]], + 36680 => [[['_route' => '_637'], ['a', 'b', 'c'], null, null, false, false, null]], + 36728 => [[['_route' => '_737'], ['a', 'b', 'c'], null, null, false, false, null]], + 36784 => [[['_route' => '_699'], ['a', 'b', 'c'], null, null, false, false, null]], + 36831 => [[['_route' => '_822'], ['a', 'b', 'c'], null, null, false, false, null]], + 36880 => [[['_route' => '_853'], ['a', 'b', 'c'], null, null, false, false, null]], + 36933 => [[['_route' => '_708'], ['a', 'b', 'c'], null, null, false, false, null]], + 36981 => [[['_route' => '_871'], ['a', 'b', 'c'], null, null, false, false, null]], + 37034 => [[['_route' => '_752'], ['a', 'b', 'c'], null, null, false, false, null]], + 37082 => [[['_route' => '_989'], ['a', 'b', 'c'], null, null, false, false, null]], + 37132 => [[['_route' => '_855'], ['a', 'b', 'c'], null, null, false, false, null]], + 37184 => [[['_route' => '_858'], ['a', 'b', 'c'], null, null, false, false, null]], + 37232 => [[['_route' => '_898'], ['a', 'b', 'c'], null, null, false, false, null]], + 37282 => [[['_route' => '_903'], ['a', 'b', 'c'], null, null, false, false, null]], + 37331 => [[['_route' => '_909'], ['a', 'b', 'c'], null, null, false, false, null]], + 37380 => [[['_route' => '_950'], ['a', 'b', 'c'], null, null, false, false, null]], + 37441 => [[['_route' => '_512'], ['a', 'b', 'c'], null, null, false, false, null]], + 37488 => [[['_route' => '_691'], ['a', 'b', 'c'], null, null, false, false, null]], + 37537 => [[['_route' => '_686'], ['a', 'b', 'c'], null, null, false, false, null]], + 37587 => [[['_route' => '_527'], ['a', 'b', 'c'], null, null, false, false, null]], + 37639 => [[['_route' => '_541'], ['a', 'b', 'c'], null, null, false, false, null]], + 37687 => [[['_route' => '_956'], ['a', 'b', 'c'], null, null, false, false, null]], + 37740 => [[['_route' => '_555'], ['a', 'b', 'c'], null, null, false, false, null]], + 37788 => [[['_route' => '_681'], ['a', 'b', 'c'], null, null, false, false, null]], + 37841 => [[['_route' => '_556'], ['a', 'b', 'c'], null, null, false, false, null]], + 37889 => [[['_route' => '_802'], ['a', 'b', 'c'], null, null, false, false, null]], + 37939 => [[['_route' => '_558'], ['a', 'b', 'c'], null, null, false, false, null]], + 37991 => [[['_route' => '_564'], ['a', 'b', 'c'], null, null, false, false, null]], + 38039 => [[['_route' => '_670'], ['a', 'b', 'c'], null, null, false, false, null]], + 38087 => [[['_route' => '_884'], ['a', 'b', 'c'], null, null, false, false, null]], + 38140 => [[['_route' => '_627'], ['a', 'b', 'c'], null, null, false, false, null]], + 38187 => [[['_route' => '_746'], ['a', 'b', 'c'], null, null, false, false, null]], + 38240 => [[['_route' => '_668'], ['a', 'b', 'c'], null, null, false, false, null]], + 38291 => [[['_route' => '_712'], ['a', 'b', 'c'], null, null, false, false, null]], + 38338 => [[['_route' => '_863'], ['a', 'b', 'c'], null, null, false, false, null]], + 38387 => [[['_route' => '_801'], ['a', 'b', 'c'], null, null, false, false, null]], + 38440 => [[['_route' => '_709'], ['a', 'b', 'c'], null, null, false, false, null]], + 38488 => [[['_route' => '_850'], ['a', 'b', 'c'], null, null, false, false, null]], + 38536 => [[['_route' => '_918'], ['a', 'b', 'c'], null, null, false, false, null]], + 38586 => [[['_route' => '_803'], ['a', 'b', 'c'], null, null, false, false, null]], + 38638 => [[['_route' => '_864'], ['a', 'b', 'c'], null, null, false, false, null]], + 38686 => [[['_route' => '_880'], ['a', 'b', 'c'], null, null, false, false, null]], + 38734 => [[['_route' => '_927'], ['a', 'b', 'c'], null, null, false, false, null]], + 38787 => [[['_route' => '_930'], ['a', 'b', 'c'], null, null, false, false, null]], + 38835 => [[['_route' => '_951'], ['a', 'b', 'c'], null, null, false, false, null]], + 38883 => [[['_route' => '_963'], ['a', 'b', 'c'], null, null, false, false, null]], + 38942 => [[['_route' => '_519'], ['a', 'b', 'c'], null, null, false, false, null]], + 38990 => [[['_route' => '_823'], ['a', 'b', 'c'], null, null, false, false, null]], + 39038 => [[['_route' => '_954'], ['a', 'b', 'c'], null, null, false, false, null]], + 39091 => [[['_route' => '_525'], ['a', 'b', 'c'], null, null, false, false, null]], + 39139 => [[['_route' => '_991'], ['a', 'b', 'c'], null, null, false, false, null]], + 39189 => [[['_route' => '_536'], ['a', 'b', 'c'], null, null, false, false, null]], + 39241 => [[['_route' => '_545'], ['a', 'b', 'c'], null, null, false, false, null]], + 39289 => [[['_route' => '_944'], ['a', 'b', 'c'], null, null, false, false, null]], + 39342 => [[['_route' => '_557'], ['a', 'b', 'c'], null, null, false, false, null]], + 39390 => [[['_route' => '_783'], ['a', 'b', 'c'], null, null, false, false, null]], + 39438 => [[['_route' => '_807'], ['a', 'b', 'c'], null, null, false, false, null]], + 39491 => [[['_route' => '_586'], ['a', 'b', 'c'], null, null, false, false, null]], + 39539 => [[['_route' => '_711'], ['a', 'b', 'c'], null, null, false, false, null]], + 39592 => [[['_route' => '_598'], ['a', 'b', 'c'], null, null, false, false, null]], + 39640 => [[['_route' => '_635'], ['a', 'b', 'c'], null, null, false, false, null]], + 39688 => [[['_route' => '_983'], ['a', 'b', 'c'], null, null, false, false, null]], + 39741 => [[['_route' => '_634'], ['a', 'b', 'c'], null, null, false, false, null]], + 39789 => [[['_route' => '_641'], ['a', 'b', 'c'], null, null, false, false, null]], + 39840 => [[['_route' => '_779'], ['a', 'b', 'c'], null, null, false, false, null]], + 39887 => [[['_route' => '_876'], ['a', 'b', 'c'], null, null, false, false, null]], + 39936 => [[['_route' => '_811'], ['a', 'b', 'c'], null, null, false, false, null]], + 39984 => [[['_route' => '_824'], ['a', 'b', 'c'], null, null, false, false, null]], + 40037 => [[['_route' => '_660'], ['a', 'b', 'c'], null, null, false, false, null]], + 40085 => [[['_route' => '_789'], ['a', 'b', 'c'], null, null, false, false, null]], + 40138 => [[['_route' => '_733'], ['a', 'b', 'c'], null, null, false, false, null]], + 40186 => [[['_route' => '_735'], ['a', 'b', 'c'], null, null, false, false, null]], + 40234 => [[['_route' => '_882'], ['a', 'b', 'c'], null, null, false, false, null]], + 40282 => [[['_route' => '_967'], ['a', 'b', 'c'], null, null, false, false, null]], + 40332 => [[['_route' => '_736'], ['a', 'b', 'c'], null, null, false, false, null]], + 40381 => [[['_route' => '_753'], ['a', 'b', 'c'], null, null, false, false, null]], + 40430 => [[['_route' => '_786'], ['a', 'b', 'c'], null, null, false, false, null]], + 40479 => [[['_route' => '_907'], ['a', 'b', 'c'], null, null, false, false, null]], + 40528 => [[['_route' => '_920'], ['a', 'b', 'c'], null, null, false, false, null]], + 40577 => [[['_route' => '_971'], ['a', 'b', 'c'], null, null, false, false, null]], + 40635 => [[['_route' => '_520'], ['a', 'b', 'c'], null, null, false, false, null]], + 40683 => [[['_route' => '_891'], ['a', 'b', 'c'], null, null, false, false, null]], + 40739 => [[['_route' => '_534'], ['a', 'b', 'c'], null, null, false, false, null]], + 40785 => [[['_route' => '_602'], ['a', 'b', 'c'], null, null, false, false, null]], + 40834 => [[['_route' => '_605'], ['a', 'b', 'c'], null, null, false, false, null]], + 40882 => [[['_route' => '_979'], ['a', 'b', 'c'], null, null, false, false, null]], + 40932 => [[['_route' => '_547'], ['a', 'b', 'c'], null, null, false, false, null]], + 40987 => [[['_route' => '_549'], ['a', 'b', 'c'], null, null, false, false, null]], + 41034 => [[['_route' => '_755'], ['a', 'b', 'c'], null, null, false, false, null]], + 41083 => [[['_route' => '_922'], ['a', 'b', 'c'], null, null, false, false, null]], + 41131 => [[['_route' => '_977'], ['a', 'b', 'c'], null, null, false, false, null]], + 41184 => [[['_route' => '_565'], ['a', 'b', 'c'], null, null, false, false, null]], + 41232 => [[['_route' => '_926'], ['a', 'b', 'c'], null, null, false, false, null]], + 41282 => [[['_route' => '_571'], ['a', 'b', 'c'], null, null, false, false, null]], + 41331 => [[['_route' => '_581'], ['a', 'b', 'c'], null, null, false, false, null]], + 41380 => [[['_route' => '_619'], ['a', 'b', 'c'], null, null, false, false, null]], + 41429 => [[['_route' => '_636'], ['a', 'b', 'c'], null, null, false, false, null]], + 41481 => [[['_route' => '_679'], ['a', 'b', 'c'], null, null, false, false, null]], + 41529 => [[['_route' => '_866'], ['a', 'b', 'c'], null, null, false, false, null]], + 41577 => [[['_route' => '_973'], ['a', 'b', 'c'], null, null, false, false, null]], + 41630 => [[['_route' => '_690'], ['a', 'b', 'c'], null, null, false, false, null]], + 41678 => [[['_route' => '_775'], ['a', 'b', 'c'], null, null, false, false, null]], + 41731 => [[['_route' => '_722'], ['a', 'b', 'c'], null, null, false, false, null]], + 41779 => [[['_route' => '_906'], ['a', 'b', 'c'], null, null, false, false, null]], + 41827 => [[['_route' => '_946'], ['a', 'b', 'c'], null, null, false, false, null]], + 41877 => [[['_route' => '_788'], ['a', 'b', 'c'], null, null, false, false, null]], + 41929 => [[['_route' => '_828'], ['a', 'b', 'c'], null, null, false, false, null]], + 41977 => [[['_route' => '_892'], ['a', 'b', 'c'], null, null, false, false, null]], + 42025 => [[['_route' => '_972'], ['a', 'b', 'c'], null, null, false, false, null]], + 42075 => [[['_route' => '_829'], ['a', 'b', 'c'], null, null, false, false, null]], + 42127 => [[['_route' => '_923'], ['a', 'b', 'c'], null, null, false, false, null]], + 42175 => [[['_route' => '_947'], ['a', 'b', 'c'], null, null, false, false, null]], + 42234 => [[['_route' => '_526'], ['a', 'b', 'c'], null, null, false, false, null]], + 42282 => [[['_route' => '_614'], ['a', 'b', 'c'], null, null, false, false, null]], + 42330 => [[['_route' => '_621'], ['a', 'b', 'c'], null, null, false, false, null]], + 42383 => [[['_route' => '_543'], ['a', 'b', 'c'], null, null, false, false, null]], + 42431 => [[['_route' => '_812'], ['a', 'b', 'c'], null, null, false, false, null]], + 42487 => [[['_route' => '_548'], ['a', 'b', 'c'], null, null, false, false, null]], + 42534 => [[['_route' => '_747'], ['a', 'b', 'c'], null, null, false, false, null]], + 42583 => [[['_route' => '_715'], ['a', 'b', 'c'], null, null, false, false, null]], + 42631 => [[['_route' => '_940'], ['a', 'b', 'c'], null, null, false, false, null]], + 42684 => [[['_route' => '_563'], ['a', 'b', 'c'], null, null, false, false, null]], + 42732 => [[['_route' => '_611'], ['a', 'b', 'c'], null, null, false, false, null]], + 42780 => [[['_route' => '_830'], ['a', 'b', 'c'], null, null, false, false, null]], + 42833 => [[['_route' => '_569'], ['a', 'b', 'c'], null, null, false, false, null]], + 42881 => [[['_route' => '_908'], ['a', 'b', 'c'], null, null, false, false, null]], + 42929 => [[['_route' => '_913'], ['a', 'b', 'c'], null, null, false, false, null]], + 42982 => [[['_route' => '_644'], ['a', 'b', 'c'], null, null, false, false, null]], + 43030 => [[['_route' => '_776'], ['a', 'b', 'c'], null, null, false, false, null]], + 43078 => [[['_route' => '_856'], ['a', 'b', 'c'], null, null, false, false, null]], + 43131 => [[['_route' => '_650'], ['a', 'b', 'c'], null, null, false, false, null]], + 43179 => [[['_route' => '_761'], ['a', 'b', 'c'], null, null, false, false, null]], + 43232 => [[['_route' => '_663'], ['a', 'b', 'c'], null, null, false, false, null]], + 43280 => [[['_route' => '_754'], ['a', 'b', 'c'], null, null, false, false, null]], + 43333 => [[['_route' => '_665'], ['a', 'b', 'c'], null, null, false, false, null]], + 43381 => [[['_route' => '_805'], ['a', 'b', 'c'], null, null, false, false, null]], + 43429 => [[['_route' => '_846'], ['a', 'b', 'c'], null, null, false, false, null]], + 43477 => [[['_route' => '_857'], ['a', 'b', 'c'], null, null, false, false, null]], + 43530 => [[['_route' => '_675'], ['a', 'b', 'c'], null, null, false, false, null]], + 43578 => [[['_route' => '_839'], ['a', 'b', 'c'], null, null, false, false, null]], + 43626 => [[['_route' => '_968'], ['a', 'b', 'c'], null, null, false, false, null]], + 43676 => [[['_route' => '_697'], ['a', 'b', 'c'], null, null, false, false, null]], + 43728 => [[['_route' => '_725'], ['a', 'b', 'c'], null, null, false, false, null]], + 43776 => [[['_route' => '_794'], ['a', 'b', 'c'], null, null, false, false, null]], + 43829 => [[['_route' => '_773'], ['a', 'b', 'c'], null, null, false, false, null]], + 43877 => [[['_route' => '_992'], ['a', 'b', 'c'], null, null, false, false, null]], + 43930 => [[['_route' => '_901'], ['a', 'b', 'c'], null, null, false, false, null]], + 43978 => [[['_route' => '_970'], ['a', 'b', 'c'], null, null, false, false, null]], + 44028 => [[['_route' => '_964'], ['a', 'b', 'c'], null, null, false, false, null]], + 44086 => [[['_route' => '_530'], ['a', 'b', 'c'], null, null, false, false, null]], + 44134 => [[['_route' => '_703'], ['a', 'b', 'c'], null, null, false, false, null]], + 44187 => [[['_route' => '_533'], ['a', 'b', 'c'], null, null, false, false, null]], + 44235 => [[['_route' => '_739'], ['a', 'b', 'c'], null, null, false, false, null]], + 44283 => [[['_route' => '_791'], ['a', 'b', 'c'], null, null, false, false, null]], + 44331 => [[['_route' => '_987'], ['a', 'b', 'c'], null, null, false, false, null]], + 44384 => [[['_route' => '_566'], ['a', 'b', 'c'], null, null, false, false, null]], + 44432 => [[['_route' => '_592'], ['a', 'b', 'c'], null, null, false, false, null]], + 44488 => [[['_route' => '_568'], ['a', 'b', 'c'], null, null, false, false, null]], + 44534 => [[['_route' => '_868'], ['a', 'b', 'c'], null, null, false, false, null]], + 44583 => [[['_route' => '_878'], ['a', 'b', 'c'], null, null, false, false, null]], + 44636 => [[['_route' => '_588'], ['a', 'b', 'c'], null, null, false, false, null]], + 44684 => [[['_route' => '_793'], ['a', 'b', 'c'], null, null, false, false, null]], + 44732 => [[['_route' => '_917'], ['a', 'b', 'c'], null, null, false, false, null]], + 44785 => [[['_route' => '_600'], ['a', 'b', 'c'], null, null, false, false, null]], + 44833 => [[['_route' => '_728'], ['a', 'b', 'c'], null, null, false, false, null]], + 44886 => [[['_route' => '_603'], ['a', 'b', 'c'], null, null, false, false, null]], + 44934 => [[['_route' => '_765'], ['a', 'b', 'c'], null, null, false, false, null]], + 44987 => [[['_route' => '_607'], ['a', 'b', 'c'], null, null, false, false, null]], + 45035 => [[['_route' => '_676'], ['a', 'b', 'c'], null, null, false, false, null]], + 45083 => [[['_route' => '_804'], ['a', 'b', 'c'], null, null, false, false, null]], + 45136 => [[['_route' => '_609'], ['a', 'b', 'c'], null, null, false, false, null]], + 45184 => [[['_route' => '_961'], ['a', 'b', 'c'], null, null, false, false, null]], + 45232 => [[['_route' => '_980'], ['a', 'b', 'c'], null, null, false, false, null]], + 45282 => [[['_route' => '_714'], ['a', 'b', 'c'], null, null, false, false, null]], + 45334 => [[['_route' => '_730'], ['a', 'b', 'c'], null, null, false, false, null]], + 45382 => [[['_route' => '_806'], ['a', 'b', 'c'], null, null, false, false, null]], + 45430 => [[['_route' => '_825'], ['a', 'b', 'c'], null, null, false, false, null]], + 45478 => [[['_route' => '_879'], ['a', 'b', 'c'], null, null, false, false, null]], + 45526 => [[['_route' => '_893'], ['a', 'b', 'c'], null, null, false, false, null]], + 45576 => [[['_route' => '_928'], ['a', 'b', 'c'], null, null, false, false, null]], + 45628 => [[['_route' => '_932'], ['a', 'b', 'c'], null, null, false, false, null]], + 45676 => [[['_route' => '_958'], ['a', 'b', 'c'], null, null, false, false, null]], + 45726 => [[['_route' => '_984'], ['a', 'b', 'c'], null, null, false, false, null]], + 45784 => [[['_route' => '_538'], ['a', 'b', 'c'], null, null, false, false, null]], + 45832 => [[['_route' => '_993'], ['a', 'b', 'c'], null, null, false, false, null]], + 45882 => [[['_route' => '_542'], ['a', 'b', 'c'], null, null, false, false, null]], + 45934 => [[['_route' => '_551'], ['a', 'b', 'c'], null, null, false, false, null]], + 45982 => [[['_route' => '_687'], ['a', 'b', 'c'], null, null, false, false, null]], + 46030 => [[['_route' => '_724'], ['a', 'b', 'c'], null, null, false, false, null]], + 46078 => [[['_route' => '_925'], ['a', 'b', 'c'], null, null, false, false, null]], + 46131 => [[['_route' => '_587'], ['a', 'b', 'c'], null, null, false, false, null]], + 46179 => [[['_route' => '_914'], ['a', 'b', 'c'], null, null, false, false, null]], + 46229 => [[['_route' => '_616'], ['a', 'b', 'c'], null, null, false, false, null]], + 46284 => [[['_route' => '_677'], ['a', 'b', 'c'], null, null, false, false, null]], + 46331 => [[['_route' => '_815'], ['a', 'b', 'c'], null, null, false, false, null]], + 46380 => [[['_route' => '_781'], ['a', 'b', 'c'], null, null, false, false, null]], + 46430 => [[['_route' => '_717'], ['a', 'b', 'c'], null, null, false, false, null]], + 46482 => [[['_route' => '_782'], ['a', 'b', 'c'], null, null, false, false, null]], + 46530 => [[['_route' => '_832'], ['a', 'b', 'c'], null, null, false, false, null]], + 46583 => [[['_route' => '_795'], ['a', 'b', 'c'], null, null, false, false, null]], + 46631 => [[['_route' => '_887'], ['a', 'b', 'c'], null, null, false, false, null]], + 46681 => [[['_route' => '_800'], ['a', 'b', 'c'], null, null, false, false, null]], + 46730 => [[['_route' => '_826'], ['a', 'b', 'c'], null, null, false, false, null]], + 46779 => [[['_route' => '_881'], ['a', 'b', 'c'], null, null, false, false, null]], + 46828 => [[['_route' => '_886'], ['a', 'b', 'c'], null, null, false, false, null]], + 46877 => [[['_route' => '_938'], ['a', 'b', 'c'], null, null, false, false, null]], + 46935 => [[['_route' => '_540'], ['a', 'b', 'c'], null, null, false, false, null]], + 46983 => [[['_route' => '_643'], ['a', 'b', 'c'], null, null, false, false, null]], + 47033 => [[['_route' => '_544'], ['a', 'b', 'c'], null, null, false, false, null]], + 47082 => [[['_route' => '_552'], ['a', 'b', 'c'], null, null, false, false, null]], + 47134 => [[['_route' => '_567'], ['a', 'b', 'c'], null, null, false, false, null]], + 47182 => [[['_route' => '_608'], ['a', 'b', 'c'], null, null, false, false, null]], + 47230 => [[['_route' => '_698'], ['a', 'b', 'c'], null, null, false, false, null]], + 47278 => [[['_route' => '_988'], ['a', 'b', 'c'], null, null, false, false, null]], + 47331 => [[['_route' => '_583'], ['a', 'b', 'c'], null, null, false, false, null]], + 47379 => [[['_route' => '_998'], ['a', 'b', 'c'], null, null, false, false, null]], + 47432 => [[['_route' => '_604'], ['a', 'b', 'c'], null, null, false, false, null]], + 47480 => [[['_route' => '_630'], ['a', 'b', 'c'], null, null, false, false, null]], + 47528 => [[['_route' => '_706'], ['a', 'b', 'c'], null, null, false, false, null]], + 47576 => [[['_route' => '_976'], ['a', 'b', 'c'], null, null, false, false, null]], + 47629 => [[['_route' => '_673'], ['a', 'b', 'c'], null, null, false, false, null]], + 47677 => [[['_route' => '_678'], ['a', 'b', 'c'], null, null, false, false, null]], + 47725 => [[['_route' => '_931'], ['a', 'b', 'c'], null, null, false, false, null]], + 47775 => [[['_route' => '_751'], ['a', 'b', 'c'], null, null, false, false, null]], + 47824 => [[['_route' => '_766'], ['a', 'b', 'c'], null, null, false, false, null]], + 47876 => [[['_route' => '_792'], ['a', 'b', 'c'], null, null, false, false, null]], + 47924 => [[['_route' => '_814'], ['a', 'b', 'c'], null, null, false, false, null]], + 47974 => [[['_route' => '_798'], ['a', 'b', 'c'], null, null, false, false, null]], + 48026 => [[['_route' => '_851'], ['a', 'b', 'c'], null, null, false, false, null]], + 48074 => [[['_route' => '_941'], ['a', 'b', 'c'], null, null, false, false, null]], + 48122 => [[['_route' => '_953'], ['a', 'b', 'c'], null, null, false, false, null]], + 48170 => [[['_route' => '_975'], ['a', 'b', 'c'], null, null, false, false, null]], + 48220 => [[['_route' => '_873'], ['a', 'b', 'c'], null, null, false, false, null]], + 48269 => [[['_route' => '_936'], ['a', 'b', 'c'], null, null, false, false, null]], + 48318 => [[['_route' => '_994'], ['a', 'b', 'c'], null, null, false, false, null]], + 48376 => [[['_route' => '_562'], ['a', 'b', 'c'], null, null, false, false, null]], + 48424 => [[['_route' => '_770'], ['a', 'b', 'c'], null, null, false, false, null]], + 48475 => [[['_route' => '_774'], ['a', 'b', 'c'], null, null, false, false, null]], + 48522 => [[['_route' => '_966'], ['a', 'b', 'c'], null, null, false, false, null]], + 48573 => [[['_route' => '_582'], ['a', 'b', 'c'], null, null, false, false, null]], + 48625 => [[['_route' => '_606'], ['a', 'b', 'c'], null, null, false, false, null]], + 48673 => [[['_route' => '_648'], ['a', 'b', 'c'], null, null, false, false, null]], + 48723 => [[['_route' => '_624'], ['a', 'b', 'c'], null, null, false, false, null]], + 48775 => [[['_route' => '_626'], ['a', 'b', 'c'], null, null, false, false, null]], + 48823 => [[['_route' => '_821'], ['a', 'b', 'c'], null, null, false, false, null]], + 48873 => [[['_route' => '_628'], ['a', 'b', 'c'], null, null, false, false, null]], + 48922 => [[['_route' => '_638'], ['a', 'b', 'c'], null, null, false, false, null]], + 48974 => [[['_route' => '_640'], ['a', 'b', 'c'], null, null, false, false, null]], + 49022 => [[['_route' => '_990'], ['a', 'b', 'c'], null, null, false, false, null]], + 49072 => [[['_route' => '_705'], ['a', 'b', 'c'], null, null, false, false, null]], + 49121 => [[['_route' => '_757'], ['a', 'b', 'c'], null, null, false, false, null]], + 49176 => [[['_route' => '_785'], ['a', 'b', 'c'], null, null, false, false, null]], + 49223 => [[['_route' => '_875'], ['a', 'b', 'c'], null, null, false, false, null]], + 49270 => [[['_route' => '_894'], ['a', 'b', 'c'], null, null, false, false, null]], + 49319 => [[['_route' => '_945'], ['a', 'b', 'c'], null, null, false, false, null]], + 49375 => [[['_route' => '_816'], ['a', 'b', 'c'], null, null, false, false, null]], + 49422 => [[['_route' => '_872'], ['a', 'b', 'c'], null, null, false, false, null]], + 49471 => [[['_route' => '_921'], ['a', 'b', 'c'], null, null, false, false, null]], + 49519 => [[['_route' => '_960'], ['a', 'b', 'c'], null, null, false, false, null]], + 49567 => [[['_route' => '_974'], ['a', 'b', 'c'], null, null, false, false, null]], + 49620 => [[['_route' => '_835'], ['a', 'b', 'c'], null, null, false, false, null]], + 49668 => [[['_route' => '_934'], ['a', 'b', 'c'], null, null, false, false, null]], + 49718 => [ + [['_route' => '_869'], ['a', 'b', 'c'], null, null, false, false, null], + [null, null, null, null, false, false, 0], + ], + ], + null, // $checkCondition +]; diff --git a/vendor/symfony/routing/Tests/Fixtures/dumper/compiled_url_matcher11.php b/vendor/symfony/routing/Tests/Fixtures/dumper/compiled_url_matcher11.php new file mode 100644 index 0000000000000000000000000000000000000000..dc0e5f5545eb099e6e1a6d082097dad19923dc00 --- /dev/null +++ b/vendor/symfony/routing/Tests/Fixtures/dumper/compiled_url_matcher11.php @@ -0,0 +1,64 @@ +<?php + +/** + * This file has been auto-generated + * by the Symfony Routing Component. + */ + +return [ + false, // $matchHost + [ // $staticRoutes + ], + [ // $regexpList + 0 => '{^(?' + .'|/(en|fr)/(?' + .'|admin/post(?' + .'|(*:32)' + .'|/(?' + .'|new(*:46)' + .'|(\\d+)(*:58)' + .'|(\\d+)/edit(*:75)' + .'|(\\d+)/delete(*:94)' + .')' + .')' + .'|blog(?' + .'|(*:110)' + .'|/(?' + .'|rss\\.xml(*:130)' + .'|p(?' + .'|age/([^/]++)(*:154)' + .'|osts/([^/]++)(*:175)' + .')' + .'|comments/(\\d+)/new(*:202)' + .'|search(*:216)' + .')' + .')' + .'|log(?' + .'|in(*:234)' + .'|out(*:245)' + .')' + .')' + .'|/(en|fr)?(*:264)' + .')/?$}sD', + ], + [ // $dynamicRoutes + 32 => [[['_route' => 'a', '_locale' => 'en'], ['_locale'], null, null, true, false, null]], + 46 => [[['_route' => 'b', '_locale' => 'en'], ['_locale'], null, null, false, false, null]], + 58 => [[['_route' => 'c', '_locale' => 'en'], ['_locale', 'id'], null, null, false, true, null]], + 75 => [[['_route' => 'd', '_locale' => 'en'], ['_locale', 'id'], null, null, false, false, null]], + 94 => [[['_route' => 'e', '_locale' => 'en'], ['_locale', 'id'], null, null, false, false, null]], + 110 => [[['_route' => 'f', '_locale' => 'en'], ['_locale'], null, null, true, false, null]], + 130 => [[['_route' => 'g', '_locale' => 'en'], ['_locale'], null, null, false, false, null]], + 154 => [[['_route' => 'h', '_locale' => 'en'], ['_locale', 'page'], null, null, false, true, null]], + 175 => [[['_route' => 'i', '_locale' => 'en'], ['_locale', 'page'], null, null, false, true, null]], + 202 => [[['_route' => 'j', '_locale' => 'en'], ['_locale', 'id'], null, null, false, false, null]], + 216 => [[['_route' => 'k', '_locale' => 'en'], ['_locale'], null, null, false, false, null]], + 234 => [[['_route' => 'l', '_locale' => 'en'], ['_locale'], null, null, false, false, null]], + 245 => [[['_route' => 'm', '_locale' => 'en'], ['_locale'], null, null, false, false, null]], + 264 => [ + [['_route' => 'n', '_locale' => 'en'], ['_locale'], null, null, false, true, null], + [null, null, null, null, false, false, 0], + ], + ], + null, // $checkCondition +]; diff --git a/vendor/symfony/routing/Tests/Fixtures/dumper/compiled_url_matcher12.php b/vendor/symfony/routing/Tests/Fixtures/dumper/compiled_url_matcher12.php new file mode 100644 index 0000000000000000000000000000000000000000..a675d84a4327072fca31881d8f4104d4424261b8 --- /dev/null +++ b/vendor/symfony/routing/Tests/Fixtures/dumper/compiled_url_matcher12.php @@ -0,0 +1,44 @@ +<?php + +/** + * This file has been auto-generated + * by the Symfony Routing Component. + */ + +return [ + false, // $matchHost + [ // $staticRoutes + ], + [ // $regexpList + 0 => '{^(?' + .'|/abc([^/]++)/(?' + .'|1(?' + .'|(*:27)' + .'|0(?' + .'|(*:38)' + .'|0(*:46)' + .')' + .')' + .'|2(?' + .'|(*:59)' + .'|0(?' + .'|(*:70)' + .'|0(*:78)' + .')' + .')' + .')' + .')/?$}sD', + ], + [ // $dynamicRoutes + 27 => [[['_route' => 'r1'], ['foo'], null, null, false, false, null]], + 38 => [[['_route' => 'r10'], ['foo'], null, null, false, false, null]], + 46 => [[['_route' => 'r100'], ['foo'], null, null, false, false, null]], + 59 => [[['_route' => 'r2'], ['foo'], null, null, false, false, null]], + 70 => [[['_route' => 'r20'], ['foo'], null, null, false, false, null]], + 78 => [ + [['_route' => 'r200'], ['foo'], null, null, false, false, null], + [null, null, null, null, false, false, 0], + ], + ], + null, // $checkCondition +]; diff --git a/vendor/symfony/routing/Tests/Fixtures/dumper/compiled_url_matcher13.php b/vendor/symfony/routing/Tests/Fixtures/dumper/compiled_url_matcher13.php new file mode 100644 index 0000000000000000000000000000000000000000..63252943df31c9077851b22d1664753a7828b74e --- /dev/null +++ b/vendor/symfony/routing/Tests/Fixtures/dumper/compiled_url_matcher13.php @@ -0,0 +1,29 @@ +<?php + +/** + * This file has been auto-generated + * by the Symfony Routing Component. + */ + +return [ + true, // $matchHost + [ // $staticRoutes + ], + [ // $regexpList + 0 => '{^(?' + .'|(?i:([^\\.]++)\\.exampple\\.com)\\.(?' + .'|/abc([^/]++)(?' + .'|(*:56)' + .')' + .')' + .')/?$}sD', + ], + [ // $dynamicRoutes + 56 => [ + [['_route' => 'r1'], ['foo', 'foo'], null, null, false, true, null], + [['_route' => 'r2'], ['foo', 'foo'], null, null, false, true, null], + [null, null, null, null, false, false, 0], + ], + ], + null, // $checkCondition +]; diff --git a/vendor/symfony/routing/Tests/Fixtures/dumper/compiled_url_matcher2.php b/vendor/symfony/routing/Tests/Fixtures/dumper/compiled_url_matcher2.php new file mode 100644 index 0000000000000000000000000000000000000000..13629954a8d1206808cd785751b068ad9933fd68 --- /dev/null +++ b/vendor/symfony/routing/Tests/Fixtures/dumper/compiled_url_matcher2.php @@ -0,0 +1,110 @@ +<?php + +/** + * This file has been auto-generated + * by the Symfony Routing Component. + */ + +return [ + true, // $matchHost + [ // $staticRoutes + '/test/baz' => [[['_route' => 'baz'], null, null, null, false, false, null]], + '/test/baz.html' => [[['_route' => 'baz2'], null, null, null, false, false, null]], + '/test/baz3' => [[['_route' => 'baz3'], null, null, null, true, false, null]], + '/foofoo' => [[['_route' => 'foofoo', 'def' => 'test'], null, null, null, false, false, null]], + '/spa ce' => [[['_route' => 'space'], null, null, null, false, false, null]], + '/multi/new' => [[['_route' => 'overridden2'], null, null, null, false, false, null]], + '/multi/hey' => [[['_route' => 'hey'], null, null, null, true, false, null]], + '/ababa' => [[['_route' => 'ababa'], null, null, null, false, false, null]], + '/route1' => [[['_route' => 'route1'], 'a.example.com', null, null, false, false, null]], + '/c2/route2' => [[['_route' => 'route2'], 'a.example.com', null, null, false, false, null]], + '/route4' => [[['_route' => 'route4'], 'a.example.com', null, null, false, false, null]], + '/c2/route3' => [[['_route' => 'route3'], 'b.example.com', null, null, false, false, null]], + '/route5' => [[['_route' => 'route5'], 'c.example.com', null, null, false, false, null]], + '/route6' => [[['_route' => 'route6'], null, null, null, false, false, null]], + '/route11' => [[['_route' => 'route11'], '#^(?P<var1>[^\\.]++)\\.example\\.com$#sDi', null, null, false, false, null]], + '/route12' => [[['_route' => 'route12', 'var1' => 'val'], '#^(?P<var1>[^\\.]++)\\.example\\.com$#sDi', null, null, false, false, null]], + '/route17' => [[['_route' => 'route17'], null, null, null, false, false, null]], + '/secure' => [[['_route' => 'secure'], null, null, ['https' => 0], false, false, null]], + '/nonsecure' => [[['_route' => 'nonsecure'], null, null, ['http' => 0], false, false, null]], + ], + [ // $regexpList + 0 => '{^(?' + .'|(?:(?:[^./]*+\\.)++)(?' + .'|/foo/(baz|symfony)(*:47)' + .'|/bar(?' + .'|/([^/]++)(*:70)' + .'|head/([^/]++)(*:90)' + .')' + .'|/test/([^/]++)(?' + .'|(*:115)' + .')' + .'|/([\']+)(*:131)' + .'|/a/(?' + .'|b\'b/([^/]++)(?' + .'|(*:160)' + .'|(*:168)' + .')' + .'|(.*)(*:181)' + .'|b\'b/([^/]++)(?' + .'|(*:204)' + .'|(*:212)' + .')' + .')' + .'|/multi/hello(?:/([^/]++))?(*:248)' + .'|/([^/]++)/b/([^/]++)(?' + .'|(*:279)' + .'|(*:287)' + .')' + .'|/aba/([^/]++)(*:309)' + .')|(?i:([^\\.]++)\\.example\\.com)\\.(?' + .'|/route1(?' + .'|3/([^/]++)(*:371)' + .'|4/([^/]++)(*:389)' + .')' + .')|(?i:c\\.example\\.com)\\.(?' + .'|/route15/([^/]++)(*:441)' + .')|(?:(?:[^./]*+\\.)++)(?' + .'|/route16/([^/]++)(*:489)' + .'|/a/(?' + .'|a\\.\\.\\.(*:510)' + .'|b/(?' + .'|([^/]++)(*:531)' + .'|c/([^/]++)(*:549)' + .')' + .')' + .')' + .')/?$}sD', + ], + [ // $dynamicRoutes + 47 => [[['_route' => 'foo', 'def' => 'test'], ['bar'], null, null, false, true, null]], + 70 => [[['_route' => 'bar'], ['foo'], ['GET' => 0, 'HEAD' => 1], null, false, true, null]], + 90 => [[['_route' => 'barhead'], ['foo'], ['GET' => 0], null, false, true, null]], + 115 => [ + [['_route' => 'baz4'], ['foo'], null, null, true, true, null], + [['_route' => 'baz5'], ['foo'], ['POST' => 0], null, true, true, null], + [['_route' => 'baz.baz6'], ['foo'], ['PUT' => 0], null, true, true, null], + ], + 131 => [[['_route' => 'quoter'], ['quoter'], null, null, false, true, null]], + 160 => [[['_route' => 'foo1'], ['foo'], ['PUT' => 0], null, false, true, null]], + 168 => [[['_route' => 'bar1'], ['bar'], null, null, false, true, null]], + 181 => [[['_route' => 'overridden'], ['var'], null, null, false, true, null]], + 204 => [[['_route' => 'foo2'], ['foo1'], null, null, false, true, null]], + 212 => [[['_route' => 'bar2'], ['bar1'], null, null, false, true, null]], + 248 => [[['_route' => 'helloWorld', 'who' => 'World!'], ['who'], null, null, false, true, null]], + 279 => [[['_route' => 'foo3'], ['_locale', 'foo'], null, null, false, true, null]], + 287 => [[['_route' => 'bar3'], ['_locale', 'bar'], null, null, false, true, null]], + 309 => [[['_route' => 'foo4'], ['foo'], null, null, false, true, null]], + 371 => [[['_route' => 'route13'], ['var1', 'name'], null, null, false, true, null]], + 389 => [[['_route' => 'route14', 'var1' => 'val'], ['var1', 'name'], null, null, false, true, null]], + 441 => [[['_route' => 'route15'], ['name'], null, null, false, true, null]], + 489 => [[['_route' => 'route16', 'var1' => 'val'], ['name'], null, null, false, true, null]], + 510 => [[['_route' => 'a'], [], null, null, false, false, null]], + 531 => [[['_route' => 'b'], ['var'], null, null, false, true, null]], + 549 => [ + [['_route' => 'c'], ['var'], null, null, false, true, null], + [null, null, null, null, false, false, 0], + ], + ], + null, // $checkCondition +]; diff --git a/vendor/symfony/routing/Tests/Fixtures/dumper/compiled_url_matcher3.php b/vendor/symfony/routing/Tests/Fixtures/dumper/compiled_url_matcher3.php new file mode 100644 index 0000000000000000000000000000000000000000..4fe52b3c83ca6d85b5baa7e4cccf6c99c1cd623b --- /dev/null +++ b/vendor/symfony/routing/Tests/Fixtures/dumper/compiled_url_matcher3.php @@ -0,0 +1,30 @@ +<?php + +/** + * This file has been auto-generated + * by the Symfony Routing Component. + */ + +return [ + false, // $matchHost + [ // $staticRoutes + '/rootprefix/test' => [[['_route' => 'static'], null, null, null, false, false, null]], + '/with-condition' => [[['_route' => 'with-condition'], null, null, null, false, false, -1]], + ], + [ // $regexpList + 0 => '{^(?' + .'|/rootprefix/([^/]++)(*:27)' + .')/?$}sD', + ], + [ // $dynamicRoutes + 27 => [ + [['_route' => 'dynamic'], ['var'], null, null, false, true, null], + [null, null, null, null, false, false, 0], + ], + ], + static function ($condition, $context, $request) { // $checkCondition + switch ($condition) { + case -1: return ($context->getMethod() == "GET"); + } + }, +]; diff --git a/vendor/symfony/routing/Tests/Fixtures/dumper/compiled_url_matcher4.php b/vendor/symfony/routing/Tests/Fixtures/dumper/compiled_url_matcher4.php new file mode 100644 index 0000000000000000000000000000000000000000..d0a354a93e63551ceb4ecc28be3073a9cf26d1dd --- /dev/null +++ b/vendor/symfony/routing/Tests/Fixtures/dumper/compiled_url_matcher4.php @@ -0,0 +1,25 @@ +<?php + +/** + * This file has been auto-generated + * by the Symfony Routing Component. + */ + +return [ + false, // $matchHost + [ // $staticRoutes + '/just_head' => [[['_route' => 'just_head'], null, ['HEAD' => 0], null, false, false, null]], + '/head_and_get' => [[['_route' => 'head_and_get'], null, ['HEAD' => 0, 'GET' => 1], null, false, false, null]], + '/get_and_head' => [[['_route' => 'get_and_head'], null, ['GET' => 0, 'HEAD' => 1], null, false, false, null]], + '/post_and_head' => [[['_route' => 'post_and_head'], null, ['POST' => 0, 'HEAD' => 1], null, false, false, null]], + '/put_and_post' => [ + [['_route' => 'put_and_post'], null, ['PUT' => 0, 'POST' => 1], null, false, false, null], + [['_route' => 'put_and_get_and_head'], null, ['PUT' => 0, 'GET' => 1, 'HEAD' => 2], null, false, false, null], + ], + ], + [ // $regexpList + ], + [ // $dynamicRoutes + ], + null, // $checkCondition +]; diff --git a/vendor/symfony/routing/Tests/Fixtures/dumper/compiled_url_matcher5.php b/vendor/symfony/routing/Tests/Fixtures/dumper/compiled_url_matcher5.php new file mode 100644 index 0000000000000000000000000000000000000000..35c650978e1aedc8dd496264b8e487b1f5548f66 --- /dev/null +++ b/vendor/symfony/routing/Tests/Fixtures/dumper/compiled_url_matcher5.php @@ -0,0 +1,38 @@ +<?php + +/** + * This file has been auto-generated + * by the Symfony Routing Component. + */ + +return [ + false, // $matchHost + [ // $staticRoutes + '/a/11' => [[['_route' => 'a_first'], null, null, null, false, false, null]], + '/a/22' => [[['_route' => 'a_second'], null, null, null, false, false, null]], + '/a/333' => [[['_route' => 'a_third'], null, null, null, false, false, null]], + '/a/44' => [[['_route' => 'a_fourth'], null, null, null, true, false, null]], + '/a/55' => [[['_route' => 'a_fifth'], null, null, null, true, false, null]], + '/a/66' => [[['_route' => 'a_sixth'], null, null, null, true, false, null]], + '/nested/group/a' => [[['_route' => 'nested_a'], null, null, null, true, false, null]], + '/nested/group/b' => [[['_route' => 'nested_b'], null, null, null, true, false, null]], + '/nested/group/c' => [[['_route' => 'nested_c'], null, null, null, true, false, null]], + '/slashed/group' => [[['_route' => 'slashed_a'], null, null, null, true, false, null]], + '/slashed/group/b' => [[['_route' => 'slashed_b'], null, null, null, true, false, null]], + '/slashed/group/c' => [[['_route' => 'slashed_c'], null, null, null, true, false, null]], + ], + [ // $regexpList + 0 => '{^(?' + .'|/([^/]++)(*:16)' + .'|/nested/([^/]++)(*:39)' + .')/?$}sD', + ], + [ // $dynamicRoutes + 16 => [[['_route' => 'a_wildcard'], ['param'], null, null, false, true, null]], + 39 => [ + [['_route' => 'nested_wildcard'], ['param'], null, null, false, true, null], + [null, null, null, null, false, false, 0], + ], + ], + null, // $checkCondition +]; diff --git a/vendor/symfony/routing/Tests/Fixtures/dumper/compiled_url_matcher6.php b/vendor/symfony/routing/Tests/Fixtures/dumper/compiled_url_matcher6.php new file mode 100644 index 0000000000000000000000000000000000000000..571e288a8f954d0f056f6feb00e3f78dfab772a8 --- /dev/null +++ b/vendor/symfony/routing/Tests/Fixtures/dumper/compiled_url_matcher6.php @@ -0,0 +1,50 @@ +<?php + +/** + * This file has been auto-generated + * by the Symfony Routing Component. + */ + +return [ + false, // $matchHost + [ // $staticRoutes + '/trailing/simple/no-methods' => [[['_route' => 'simple_trailing_slash_no_methods'], null, null, null, true, false, null]], + '/trailing/simple/get-method' => [[['_route' => 'simple_trailing_slash_GET_method'], null, ['GET' => 0], null, true, false, null]], + '/trailing/simple/head-method' => [[['_route' => 'simple_trailing_slash_HEAD_method'], null, ['HEAD' => 0], null, true, false, null]], + '/trailing/simple/post-method' => [[['_route' => 'simple_trailing_slash_POST_method'], null, ['POST' => 0], null, true, false, null]], + '/not-trailing/simple/no-methods' => [[['_route' => 'simple_not_trailing_slash_no_methods'], null, null, null, false, false, null]], + '/not-trailing/simple/get-method' => [[['_route' => 'simple_not_trailing_slash_GET_method'], null, ['GET' => 0], null, false, false, null]], + '/not-trailing/simple/head-method' => [[['_route' => 'simple_not_trailing_slash_HEAD_method'], null, ['HEAD' => 0], null, false, false, null]], + '/not-trailing/simple/post-method' => [[['_route' => 'simple_not_trailing_slash_POST_method'], null, ['POST' => 0], null, false, false, null]], + ], + [ // $regexpList + 0 => '{^(?' + .'|/trailing/regex/(?' + .'|no\\-methods/([^/]++)(*:46)' + .'|get\\-method/([^/]++)(*:73)' + .'|head\\-method/([^/]++)(*:101)' + .'|post\\-method/([^/]++)(*:130)' + .')' + .'|/not\\-trailing/regex/(?' + .'|no\\-methods/([^/]++)(*:183)' + .'|get\\-method/([^/]++)(*:211)' + .'|head\\-method/([^/]++)(*:240)' + .'|post\\-method/([^/]++)(*:269)' + .')' + .')/?$}sD', + ], + [ // $dynamicRoutes + 46 => [[['_route' => 'regex_trailing_slash_no_methods'], ['param'], null, null, true, true, null]], + 73 => [[['_route' => 'regex_trailing_slash_GET_method'], ['param'], ['GET' => 0], null, true, true, null]], + 101 => [[['_route' => 'regex_trailing_slash_HEAD_method'], ['param'], ['HEAD' => 0], null, true, true, null]], + 130 => [[['_route' => 'regex_trailing_slash_POST_method'], ['param'], ['POST' => 0], null, true, true, null]], + 183 => [[['_route' => 'regex_not_trailing_slash_no_methods'], ['param'], null, null, false, true, null]], + 211 => [[['_route' => 'regex_not_trailing_slash_GET_method'], ['param'], ['GET' => 0], null, false, true, null]], + 240 => [[['_route' => 'regex_not_trailing_slash_HEAD_method'], ['param'], ['HEAD' => 0], null, false, true, null]], + 269 => [ + [['_route' => 'regex_not_trailing_slash_POST_method'], ['param'], ['POST' => 0], null, false, true, null], + [null, null, null, null, false, false, 0], + ], + ], + null, // $checkCondition +]; diff --git a/vendor/symfony/routing/Tests/Fixtures/dumper/compiled_url_matcher7.php b/vendor/symfony/routing/Tests/Fixtures/dumper/compiled_url_matcher7.php new file mode 100644 index 0000000000000000000000000000000000000000..571e288a8f954d0f056f6feb00e3f78dfab772a8 --- /dev/null +++ b/vendor/symfony/routing/Tests/Fixtures/dumper/compiled_url_matcher7.php @@ -0,0 +1,50 @@ +<?php + +/** + * This file has been auto-generated + * by the Symfony Routing Component. + */ + +return [ + false, // $matchHost + [ // $staticRoutes + '/trailing/simple/no-methods' => [[['_route' => 'simple_trailing_slash_no_methods'], null, null, null, true, false, null]], + '/trailing/simple/get-method' => [[['_route' => 'simple_trailing_slash_GET_method'], null, ['GET' => 0], null, true, false, null]], + '/trailing/simple/head-method' => [[['_route' => 'simple_trailing_slash_HEAD_method'], null, ['HEAD' => 0], null, true, false, null]], + '/trailing/simple/post-method' => [[['_route' => 'simple_trailing_slash_POST_method'], null, ['POST' => 0], null, true, false, null]], + '/not-trailing/simple/no-methods' => [[['_route' => 'simple_not_trailing_slash_no_methods'], null, null, null, false, false, null]], + '/not-trailing/simple/get-method' => [[['_route' => 'simple_not_trailing_slash_GET_method'], null, ['GET' => 0], null, false, false, null]], + '/not-trailing/simple/head-method' => [[['_route' => 'simple_not_trailing_slash_HEAD_method'], null, ['HEAD' => 0], null, false, false, null]], + '/not-trailing/simple/post-method' => [[['_route' => 'simple_not_trailing_slash_POST_method'], null, ['POST' => 0], null, false, false, null]], + ], + [ // $regexpList + 0 => '{^(?' + .'|/trailing/regex/(?' + .'|no\\-methods/([^/]++)(*:46)' + .'|get\\-method/([^/]++)(*:73)' + .'|head\\-method/([^/]++)(*:101)' + .'|post\\-method/([^/]++)(*:130)' + .')' + .'|/not\\-trailing/regex/(?' + .'|no\\-methods/([^/]++)(*:183)' + .'|get\\-method/([^/]++)(*:211)' + .'|head\\-method/([^/]++)(*:240)' + .'|post\\-method/([^/]++)(*:269)' + .')' + .')/?$}sD', + ], + [ // $dynamicRoutes + 46 => [[['_route' => 'regex_trailing_slash_no_methods'], ['param'], null, null, true, true, null]], + 73 => [[['_route' => 'regex_trailing_slash_GET_method'], ['param'], ['GET' => 0], null, true, true, null]], + 101 => [[['_route' => 'regex_trailing_slash_HEAD_method'], ['param'], ['HEAD' => 0], null, true, true, null]], + 130 => [[['_route' => 'regex_trailing_slash_POST_method'], ['param'], ['POST' => 0], null, true, true, null]], + 183 => [[['_route' => 'regex_not_trailing_slash_no_methods'], ['param'], null, null, false, true, null]], + 211 => [[['_route' => 'regex_not_trailing_slash_GET_method'], ['param'], ['GET' => 0], null, false, true, null]], + 240 => [[['_route' => 'regex_not_trailing_slash_HEAD_method'], ['param'], ['HEAD' => 0], null, false, true, null]], + 269 => [ + [['_route' => 'regex_not_trailing_slash_POST_method'], ['param'], ['POST' => 0], null, false, true, null], + [null, null, null, null, false, false, 0], + ], + ], + null, // $checkCondition +]; diff --git a/vendor/symfony/routing/Tests/Fixtures/dumper/compiled_url_matcher8.php b/vendor/symfony/routing/Tests/Fixtures/dumper/compiled_url_matcher8.php new file mode 100644 index 0000000000000000000000000000000000000000..461789590ef0c538d96e85a7ea0c4962362fced7 --- /dev/null +++ b/vendor/symfony/routing/Tests/Fixtures/dumper/compiled_url_matcher8.php @@ -0,0 +1,32 @@ +<?php + +/** + * This file has been auto-generated + * by the Symfony Routing Component. + */ + +return [ + false, // $matchHost + [ // $staticRoutes + ], + [ // $regexpList + 0 => '{^(?' + .'|/(a)(*:11)' + .')/?$}sD', + 11 => '{^(?' + .'|/(.)(*:22)' + .')/?$}sDu', + 22 => '{^(?' + .'|/(.)(*:33)' + .')/?$}sD', + ], + [ // $dynamicRoutes + 11 => [[['_route' => 'a'], ['a'], null, null, false, true, null]], + 22 => [[['_route' => 'b'], ['a'], null, null, false, true, null]], + 33 => [ + [['_route' => 'c'], ['a'], null, null, false, true, null], + [null, null, null, null, false, false, 0], + ], + ], + null, // $checkCondition +]; diff --git a/vendor/symfony/routing/Tests/Fixtures/dumper/compiled_url_matcher9.php b/vendor/symfony/routing/Tests/Fixtures/dumper/compiled_url_matcher9.php new file mode 100644 index 0000000000000000000000000000000000000000..da1c8a706fd00ef576e7f8afa8731e55a9f9ee53 --- /dev/null +++ b/vendor/symfony/routing/Tests/Fixtures/dumper/compiled_url_matcher9.php @@ -0,0 +1,22 @@ +<?php + +/** + * This file has been auto-generated + * by the Symfony Routing Component. + */ + +return [ + true, // $matchHost + [ // $staticRoutes + '/' => [ + [['_route' => 'a'], '#^(?P<d>[^\\.]++)\\.e\\.c\\.b\\.a$#sDi', null, null, false, false, null], + [['_route' => 'c'], '#^(?P<e>[^\\.]++)\\.e\\.c\\.b\\.a$#sDi', null, null, false, false, null], + [['_route' => 'b'], 'd.c.b.a', null, null, false, false, null], + ], + ], + [ // $regexpList + ], + [ // $dynamicRoutes + ], + null, // $checkCondition +]; diff --git a/vendor/symfony/routing/Tests/Fixtures/dumper/url_matcher0.php b/vendor/symfony/routing/Tests/Fixtures/dumper/url_matcher0.php index 839c7d137255bc1c6bbf6fe7b6ee85fd05323790..df09938d61b585953de5d9f020de76c4f70e0b45 100644 --- a/vendor/symfony/routing/Tests/Fixtures/dumper/url_matcher0.php +++ b/vendor/symfony/routing/Tests/Fixtures/dumper/url_matcher0.php @@ -1,7 +1,6 @@ <?php -use Symfony\Component\Routing\Exception\MethodNotAllowedException; -use Symfony\Component\Routing\Exception\ResourceNotFoundException; +use Symfony\Component\Routing\Matcher\Dumper\CompiledUrlMatcherTrait; use Symfony\Component\Routing\RequestContext; /** @@ -10,30 +9,10 @@ use Symfony\Component\Routing\RequestContext; */ class ProjectUrlMatcher extends Symfony\Component\Routing\Matcher\UrlMatcher { + use CompiledUrlMatcherTrait; + public function __construct(RequestContext $context) { $this->context = $context; } - - public function match($rawPathinfo) - { - $allow = array(); - $pathinfo = rawurldecode($rawPathinfo); - $trimmedPathinfo = rtrim($pathinfo, '/'); - $context = $this->context; - $request = $this->request; - $requestMethod = $canonicalMethod = $context->getMethod(); - $scheme = $context->getScheme(); - - if ('HEAD' === $requestMethod) { - $canonicalMethod = 'GET'; - } - - - if ('/' === $pathinfo) { - throw new Symfony\Component\Routing\Exception\NoConfigurationException(); - } - - throw 0 < count($allow) ? new MethodNotAllowedException(array_unique($allow)) : new ResourceNotFoundException(); - } } diff --git a/vendor/symfony/routing/Tests/Fixtures/dumper/url_matcher1.php b/vendor/symfony/routing/Tests/Fixtures/dumper/url_matcher1.php index 5d7dca8e55d0787099c3243f4ec6428ac7f74a9f..1d88511a28ec2365a21c8d28ad8e983223b0cb04 100644 --- a/vendor/symfony/routing/Tests/Fixtures/dumper/url_matcher1.php +++ b/vendor/symfony/routing/Tests/Fixtures/dumper/url_matcher1.php @@ -1,7 +1,6 @@ <?php -use Symfony\Component\Routing\Exception\MethodNotAllowedException; -use Symfony\Component\Routing\Exception\ResourceNotFoundException; +use Symfony\Component\Routing\Matcher\Dumper\CompiledUrlMatcherTrait; use Symfony\Component\Routing\RequestContext; /** @@ -10,303 +9,108 @@ use Symfony\Component\Routing\RequestContext; */ class ProjectUrlMatcher extends Symfony\Component\Routing\Matcher\UrlMatcher { + use CompiledUrlMatcherTrait; + public function __construct(RequestContext $context) { $this->context = $context; - } - - public function match($rawPathinfo) - { - $allow = array(); - $pathinfo = rawurldecode($rawPathinfo); - $trimmedPathinfo = rtrim($pathinfo, '/'); - $context = $this->context; - $request = $this->request; - $requestMethod = $canonicalMethod = $context->getMethod(); - $scheme = $context->getScheme(); - - if ('HEAD' === $requestMethod) { - $canonicalMethod = 'GET'; - } - - - if (0 === strpos($pathinfo, '/foo')) { - // foo - if (preg_match('#^/foo/(?P<bar>baz|symfony)$#s', $pathinfo, $matches)) { - return $this->mergeDefaults(array_replace($matches, array('_route' => 'foo')), array ( 'def' => 'test',)); - } - - // foofoo - if ('/foofoo' === $pathinfo) { - return array ( 'def' => 'test', '_route' => 'foofoo',); - } - - } - - elseif (0 === strpos($pathinfo, '/bar')) { - // bar - if (preg_match('#^/bar/(?P<foo>[^/]++)$#s', $pathinfo, $matches)) { - if ('GET' !== $canonicalMethod) { - $allow[] = 'GET'; - goto not_bar; - } - - return $this->mergeDefaults(array_replace($matches, array('_route' => 'bar')), array ()); - } - not_bar: - - // barhead - if (0 === strpos($pathinfo, '/barhead') && preg_match('#^/barhead/(?P<foo>[^/]++)$#s', $pathinfo, $matches)) { - if ('GET' !== $canonicalMethod) { - $allow[] = 'GET'; - goto not_barhead; - } - - return $this->mergeDefaults(array_replace($matches, array('_route' => 'barhead')), array ()); - } - not_barhead: - - } - - elseif (0 === strpos($pathinfo, '/test')) { - if (0 === strpos($pathinfo, '/test/baz')) { - // baz - if ('/test/baz' === $pathinfo) { - return array('_route' => 'baz'); - } - - // baz2 - if ('/test/baz.html' === $pathinfo) { - return array('_route' => 'baz2'); - } - - // baz3 - if ('/test/baz3/' === $pathinfo) { - return array('_route' => 'baz3'); - } - - } - - // baz4 - if (preg_match('#^/test/(?P<foo>[^/]++)/$#s', $pathinfo, $matches)) { - return $this->mergeDefaults(array_replace($matches, array('_route' => 'baz4')), array ()); - } - - // baz5 - if (preg_match('#^/test/(?P<foo>[^/]++)/$#s', $pathinfo, $matches)) { - if ('POST' !== $canonicalMethod) { - $allow[] = 'POST'; - goto not_baz5; - } - - return $this->mergeDefaults(array_replace($matches, array('_route' => 'baz5')), array ()); - } - not_baz5: - - // baz.baz6 - if (preg_match('#^/test/(?P<foo>[^/]++)/$#s', $pathinfo, $matches)) { - if ('PUT' !== $canonicalMethod) { - $allow[] = 'PUT'; - goto not_bazbaz6; - } - - return $this->mergeDefaults(array_replace($matches, array('_route' => 'baz.baz6')), array ()); - } - not_bazbaz6: - - } - - // quoter - if (preg_match('#^/(?P<quoter>[\']+)$#s', $pathinfo, $matches)) { - return $this->mergeDefaults(array_replace($matches, array('_route' => 'quoter')), array ()); - } - - // space - if ('/spa ce' === $pathinfo) { - return array('_route' => 'space'); - } - - if (0 === strpos($pathinfo, '/a')) { - if (0 === strpos($pathinfo, '/a/b\'b')) { - // foo1 - if (preg_match('#^/a/b\'b/(?P<foo>[^/]++)$#s', $pathinfo, $matches)) { - return $this->mergeDefaults(array_replace($matches, array('_route' => 'foo1')), array ()); - } - - // bar1 - if (preg_match('#^/a/b\'b/(?P<bar>[^/]++)$#s', $pathinfo, $matches)) { - return $this->mergeDefaults(array_replace($matches, array('_route' => 'bar1')), array ()); - } - - } - - // overridden - if (preg_match('#^/a/(?P<var>.*)$#s', $pathinfo, $matches)) { - return $this->mergeDefaults(array_replace($matches, array('_route' => 'overridden')), array ()); - } - - if (0 === strpos($pathinfo, '/a/b\'b')) { - // foo2 - if (preg_match('#^/a/b\'b/(?P<foo1>[^/]++)$#s', $pathinfo, $matches)) { - return $this->mergeDefaults(array_replace($matches, array('_route' => 'foo2')), array ()); - } - - // bar2 - if (preg_match('#^/a/b\'b/(?P<bar1>[^/]++)$#s', $pathinfo, $matches)) { - return $this->mergeDefaults(array_replace($matches, array('_route' => 'bar2')), array ()); - } - - } - - } - - elseif (0 === strpos($pathinfo, '/multi')) { - // helloWorld - if (0 === strpos($pathinfo, '/multi/hello') && preg_match('#^/multi/hello(?:/(?P<who>[^/]++))?$#s', $pathinfo, $matches)) { - return $this->mergeDefaults(array_replace($matches, array('_route' => 'helloWorld')), array ( 'who' => 'World!',)); - } - - // hey - if ('/multi/hey/' === $pathinfo) { - return array('_route' => 'hey'); - } - - // overridden2 - if ('/multi/new' === $pathinfo) { - return array('_route' => 'overridden2'); - } - - } - - // foo3 - if (preg_match('#^/(?P<_locale>[^/]++)/b/(?P<foo>[^/]++)$#s', $pathinfo, $matches)) { - return $this->mergeDefaults(array_replace($matches, array('_route' => 'foo3')), array ()); - } - - // bar3 - if (preg_match('#^/(?P<_locale>[^/]++)/b/(?P<bar>[^/]++)$#s', $pathinfo, $matches)) { - return $this->mergeDefaults(array_replace($matches, array('_route' => 'bar3')), array ()); - } - - if (0 === strpos($pathinfo, '/aba')) { - // ababa - if ('/ababa' === $pathinfo) { - return array('_route' => 'ababa'); - } - - // foo4 - if (preg_match('#^/aba/(?P<foo>[^/]++)$#s', $pathinfo, $matches)) { - return $this->mergeDefaults(array_replace($matches, array('_route' => 'foo4')), array ()); - } - - } - - $host = $context->getHost(); - - if (preg_match('#^a\\.example\\.com$#si', $host, $hostMatches)) { - // route1 - if ('/route1' === $pathinfo) { - return array('_route' => 'route1'); - } - - // route2 - if ('/c2/route2' === $pathinfo) { - return array('_route' => 'route2'); - } - - } - - if (preg_match('#^b\\.example\\.com$#si', $host, $hostMatches)) { - // route3 - if ('/c2/route3' === $pathinfo) { - return array('_route' => 'route3'); - } - - } - - if (preg_match('#^a\\.example\\.com$#si', $host, $hostMatches)) { - // route4 - if ('/route4' === $pathinfo) { - return array('_route' => 'route4'); - } - - } - - if (preg_match('#^c\\.example\\.com$#si', $host, $hostMatches)) { - // route5 - if ('/route5' === $pathinfo) { - return array('_route' => 'route5'); - } - - } - - // route6 - if ('/route6' === $pathinfo) { - return array('_route' => 'route6'); - } - - if (preg_match('#^(?P<var1>[^\\.]++)\\.example\\.com$#si', $host, $hostMatches)) { - if (0 === strpos($pathinfo, '/route1')) { - // route11 - if ('/route11' === $pathinfo) { - return $this->mergeDefaults(array_replace($hostMatches, array('_route' => 'route11')), array ()); - } - - // route12 - if ('/route12' === $pathinfo) { - return $this->mergeDefaults(array_replace($hostMatches, array('_route' => 'route12')), array ( 'var1' => 'val',)); - } - - // route13 - if (0 === strpos($pathinfo, '/route13') && preg_match('#^/route13/(?P<name>[^/]++)$#s', $pathinfo, $matches)) { - return $this->mergeDefaults(array_replace($hostMatches, $matches, array('_route' => 'route13')), array ()); - } - - // route14 - if (0 === strpos($pathinfo, '/route14') && preg_match('#^/route14/(?P<name>[^/]++)$#s', $pathinfo, $matches)) { - return $this->mergeDefaults(array_replace($hostMatches, $matches, array('_route' => 'route14')), array ( 'var1' => 'val',)); - } - - } - - } - - if (preg_match('#^c\\.example\\.com$#si', $host, $hostMatches)) { - // route15 - if (0 === strpos($pathinfo, '/route15') && preg_match('#^/route15/(?P<name>[^/]++)$#s', $pathinfo, $matches)) { - return $this->mergeDefaults(array_replace($matches, array('_route' => 'route15')), array ()); - } - - } - - // route16 - if (0 === strpos($pathinfo, '/route16') && preg_match('#^/route16/(?P<name>[^/]++)$#s', $pathinfo, $matches)) { - return $this->mergeDefaults(array_replace($matches, array('_route' => 'route16')), array ( 'var1' => 'val',)); - } - - // route17 - if ('/route17' === $pathinfo) { - return array('_route' => 'route17'); - } - - // a - if ('/a/a...' === $pathinfo) { - return array('_route' => 'a'); - } - - if (0 === strpos($pathinfo, '/a/b')) { - // b - if (preg_match('#^/a/b/(?P<var>[^/]++)$#s', $pathinfo, $matches)) { - return $this->mergeDefaults(array_replace($matches, array('_route' => 'b')), array ()); - } - - // c - if (0 === strpos($pathinfo, '/a/b/c') && preg_match('#^/a/b/c/(?P<var>[^/]++)$#s', $pathinfo, $matches)) { - return $this->mergeDefaults(array_replace($matches, array('_route' => 'c')), array ()); - } - - } - - throw 0 < count($allow) ? new MethodNotAllowedException(array_unique($allow)) : new ResourceNotFoundException(); + $this->matchHost = true; + $this->staticRoutes = [ + '/test/baz' => [[['_route' => 'baz'], null, null, null, false, false, null]], + '/test/baz.html' => [[['_route' => 'baz2'], null, null, null, false, false, null]], + '/test/baz3' => [[['_route' => 'baz3'], null, null, null, true, false, null]], + '/foofoo' => [[['_route' => 'foofoo', 'def' => 'test'], null, null, null, false, false, null]], + '/spa ce' => [[['_route' => 'space'], null, null, null, false, false, null]], + '/multi/new' => [[['_route' => 'overridden2'], null, null, null, false, false, null]], + '/multi/hey' => [[['_route' => 'hey'], null, null, null, true, false, null]], + '/ababa' => [[['_route' => 'ababa'], null, null, null, false, false, null]], + '/route1' => [[['_route' => 'route1'], 'a.example.com', null, null, false, false, null]], + '/c2/route2' => [[['_route' => 'route2'], 'a.example.com', null, null, false, false, null]], + '/route4' => [[['_route' => 'route4'], 'a.example.com', null, null, false, false, null]], + '/c2/route3' => [[['_route' => 'route3'], 'b.example.com', null, null, false, false, null]], + '/route5' => [[['_route' => 'route5'], 'c.example.com', null, null, false, false, null]], + '/route6' => [[['_route' => 'route6'], null, null, null, false, false, null]], + '/route11' => [[['_route' => 'route11'], '#^(?P<var1>[^\\.]++)\\.example\\.com$#sDi', null, null, false, false, null]], + '/route12' => [[['_route' => 'route12', 'var1' => 'val'], '#^(?P<var1>[^\\.]++)\\.example\\.com$#sDi', null, null, false, false, null]], + '/route17' => [[['_route' => 'route17'], null, null, null, false, false, null]], + ]; + $this->regexpList = [ + 0 => '{^(?' + .'|(?:(?:[^./]*+\\.)++)(?' + .'|/foo/(baz|symfony)(*:47)' + .'|/bar(?' + .'|/([^/]++)(*:70)' + .'|head/([^/]++)(*:90)' + .')' + .'|/test/([^/]++)(?' + .'|(*:115)' + .')' + .'|/([\']+)(*:131)' + .'|/a/(?' + .'|b\'b/([^/]++)(?' + .'|(*:160)' + .'|(*:168)' + .')' + .'|(.*)(*:181)' + .'|b\'b/([^/]++)(?' + .'|(*:204)' + .'|(*:212)' + .')' + .')' + .'|/multi/hello(?:/([^/]++))?(*:248)' + .'|/([^/]++)/b/([^/]++)(?' + .'|(*:279)' + .'|(*:287)' + .')' + .'|/aba/([^/]++)(*:309)' + .')|(?i:([^\\.]++)\\.example\\.com)\\.(?' + .'|/route1(?' + .'|3/([^/]++)(*:371)' + .'|4/([^/]++)(*:389)' + .')' + .')|(?i:c\\.example\\.com)\\.(?' + .'|/route15/([^/]++)(*:441)' + .')|(?:(?:[^./]*+\\.)++)(?' + .'|/route16/([^/]++)(*:489)' + .'|/a/(?' + .'|a\\.\\.\\.(*:510)' + .'|b/(?' + .'|([^/]++)(*:531)' + .'|c/([^/]++)(*:549)' + .')' + .')' + .')' + .')/?$}sD', + ]; + $this->dynamicRoutes = [ + 47 => [[['_route' => 'foo', 'def' => 'test'], ['bar'], null, null, false, true, null]], + 70 => [[['_route' => 'bar'], ['foo'], ['GET' => 0, 'HEAD' => 1], null, false, true, null]], + 90 => [[['_route' => 'barhead'], ['foo'], ['GET' => 0], null, false, true, null]], + 115 => [ + [['_route' => 'baz4'], ['foo'], null, null, true, true, null], + [['_route' => 'baz5'], ['foo'], ['POST' => 0], null, true, true, null], + [['_route' => 'baz.baz6'], ['foo'], ['PUT' => 0], null, true, true, null], + ], + 131 => [[['_route' => 'quoter'], ['quoter'], null, null, false, true, null]], + 160 => [[['_route' => 'foo1'], ['foo'], ['PUT' => 0], null, false, true, null]], + 168 => [[['_route' => 'bar1'], ['bar'], null, null, false, true, null]], + 181 => [[['_route' => 'overridden'], ['var'], null, null, false, true, null]], + 204 => [[['_route' => 'foo2'], ['foo1'], null, null, false, true, null]], + 212 => [[['_route' => 'bar2'], ['bar1'], null, null, false, true, null]], + 248 => [[['_route' => 'helloWorld', 'who' => 'World!'], ['who'], null, null, false, true, null]], + 279 => [[['_route' => 'foo3'], ['_locale', 'foo'], null, null, false, true, null]], + 287 => [[['_route' => 'bar3'], ['_locale', 'bar'], null, null, false, true, null]], + 309 => [[['_route' => 'foo4'], ['foo'], null, null, false, true, null]], + 371 => [[['_route' => 'route13'], ['var1', 'name'], null, null, false, true, null]], + 389 => [[['_route' => 'route14', 'var1' => 'val'], ['var1', 'name'], null, null, false, true, null]], + 441 => [[['_route' => 'route15'], ['name'], null, null, false, true, null]], + 489 => [[['_route' => 'route16', 'var1' => 'val'], ['name'], null, null, false, true, null]], + 510 => [[['_route' => 'a'], [], null, null, false, false, null]], + 531 => [[['_route' => 'b'], ['var'], null, null, false, true, null]], + 549 => [ + [['_route' => 'c'], ['var'], null, null, false, true, null], + [null, null, null, null, false, false, 0], + ], + ]; } } diff --git a/vendor/symfony/routing/Tests/Fixtures/dumper/url_matcher10.php b/vendor/symfony/routing/Tests/Fixtures/dumper/url_matcher10.php new file mode 100644 index 0000000000000000000000000000000000000000..232030cc48d048012b257cc685e44b266749b56c --- /dev/null +++ b/vendor/symfony/routing/Tests/Fixtures/dumper/url_matcher10.php @@ -0,0 +1,2779 @@ +<?php + +use Symfony\Component\Routing\Matcher\Dumper\CompiledUrlMatcherTrait; +use Symfony\Component\Routing\RequestContext; + +/** + * This class has been auto-generated + * by the Symfony Routing Component. + */ +class ProjectUrlMatcher extends Symfony\Component\Routing\Matcher\UrlMatcher +{ + use CompiledUrlMatcherTrait; + + public function __construct(RequestContext $context) + { + $this->context = $context; + $this->regexpList = [ + 0 => '{^(?' + .'|/c(?' + .'|f(?' + .'|cd20/([^/]++)/([^/]++)/([^/]++)/cfcd20(*:54)' + .'|e(?' + .'|cdb/([^/]++)/([^/]++)/([^/]++)/cfecdb(*:102)' + .'|e39/([^/]++)/([^/]++)/([^/]++)/cfee39(*:147)' + .')' + .'|a086/([^/]++)/([^/]++)/([^/]++)/cfa086(*:194)' + .'|004f/([^/]++)/([^/]++)/([^/]++)/cf004f(*:240)' + .')' + .'|4(?' + .'|ca42/([^/]++)/([^/]++)/([^/]++)/c4ca42(*:291)' + .'|5147/([^/]++)/([^/]++)/([^/]++)/c45147(*:337)' + .'|1000/([^/]++)/([^/]++)/([^/]++)/c41000(*:383)' + .')' + .'|8(?' + .'|1e72/([^/]++)/([^/]++)/([^/]++)/c81e72(*:434)' + .'|ffe9/([^/]++)/([^/]++)/([^/]++)/c8ffe9(*:480)' + .'|6a7e/([^/]++)/([^/]++)/([^/]++)/c86a7e(*:526)' + .')' + .'|9(?' + .'|f0f8/([^/]++)/([^/]++)/([^/]++)/c9f0f8(*:577)' + .'|e107/([^/]++)/([^/]++)/([^/]++)/c9e107(*:623)' + .')' + .'|2(?' + .'|0(?' + .'|ad4/([^/]++)/([^/]++)/([^/]++)/c20ad4(*:677)' + .'|3d8/([^/]++)/([^/]++)/([^/]++)/c203d8(*:722)' + .')' + .'|4cd7/([^/]++)/([^/]++)/([^/]++)/c24cd7(*:769)' + .')' + .'|5(?' + .'|1ce4/([^/]++)/([^/]++)/([^/]++)/c51ce4(*:820)' + .'|2f1b/([^/]++)/([^/]++)/([^/]++)/c52f1b(*:866)' + .'|ff25/([^/]++)/([^/]++)/([^/]++)/c5ff25(*:912)' + .')' + .'|7(?' + .'|4d97/([^/]++)/([^/]++)/([^/]++)/c74d97(*:963)' + .'|e124/([^/]++)/([^/]++)/([^/]++)/c7e124(*:1009)' + .')' + .'|16a53/([^/]++)/([^/]++)/([^/]++)/c16a53(*:1058)' + .'|0(?' + .'|c7c7/([^/]++)/([^/]++)/([^/]++)/c0c7c7(*:1109)' + .'|e190/([^/]++)/([^/]++)/([^/]++)/c0e190(*:1156)' + .'|42f4/([^/]++)/([^/]++)/([^/]++)/c042f4(*:1203)' + .'|58f5/([^/]++)/([^/]++)/([^/]++)/c058f5(*:1250)' + .')' + .'|e(?' + .'|debb/([^/]++)/([^/]++)/([^/]++)/cedebb(*:1302)' + .'|e631/([^/]++)/([^/]++)/([^/]++)/cee631(*:1349)' + .')' + .'|a(?' + .'|46c1/([^/]++)/([^/]++)/([^/]++)/ca46c1(*:1401)' + .'|f1a3/([^/]++)/([^/]++)/([^/]++)/caf1a3(*:1448)' + .')' + .'|b70ab/([^/]++)/([^/]++)/([^/]++)/cb70ab(*:1497)' + .'|d0069/([^/]++)/([^/]++)/([^/]++)/cd0069(*:1545)' + .'|3(?' + .'|e878/([^/]++)/([^/]++)/([^/]++)/c3e878(*:1596)' + .'|c59e/([^/]++)/([^/]++)/([^/]++)/c3c59e(*:1643)' + .')' + .')' + .'|/e(?' + .'|c(?' + .'|cbc8/([^/]++)/([^/]++)/([^/]++)/eccbc8(*:1701)' + .'|8(?' + .'|956/([^/]++)/([^/]++)/([^/]++)/ec8956(*:1751)' + .'|ce6/([^/]++)/([^/]++)/([^/]++)/ec8ce6(*:1797)' + .')' + .'|5dec/([^/]++)/([^/]++)/([^/]++)/ec5dec(*:1845)' + .')' + .'|4(?' + .'|da3b/([^/]++)/([^/]++)/([^/]++)/e4da3b(*:1897)' + .'|a622/([^/]++)/([^/]++)/([^/]++)/e4a622(*:1944)' + .'|6de7/([^/]++)/([^/]++)/([^/]++)/e46de7(*:1991)' + .'|4fea/([^/]++)/([^/]++)/([^/]++)/e44fea(*:2038)' + .')' + .'|3(?' + .'|6985/([^/]++)/([^/]++)/([^/]++)/e36985(*:2090)' + .'|796a/([^/]++)/([^/]++)/([^/]++)/e3796a(*:2137)' + .')' + .'|a(?' + .'|5d2f/([^/]++)/([^/]++)/([^/]++)/ea5d2f(*:2189)' + .'|e27d/([^/]++)/([^/]++)/([^/]++)/eae27d(*:2236)' + .')' + .'|2(?' + .'|c(?' + .'|420/([^/]++)/([^/]++)/([^/]++)/e2c420(*:2291)' + .'|0be/([^/]++)/([^/]++)/([^/]++)/e2c0be(*:2337)' + .')' + .'|ef52/([^/]++)/([^/]++)/([^/]++)/e2ef52(*:2385)' + .')' + .'|d(?' + .'|3d2c/([^/]++)/([^/]++)/([^/]++)/ed3d2c(*:2437)' + .'|a80a/([^/]++)/([^/]++)/([^/]++)/eda80a(*:2484)' + .'|dea8/([^/]++)/([^/]++)/([^/]++)/eddea8(*:2531)' + .')' + .'|b(?' + .'|16(?' + .'|0d/([^/]++)/([^/]++)/([^/]++)/eb160d(*:2586)' + .'|37/([^/]++)/([^/]++)/([^/]++)/eb1637(*:2631)' + .')' + .'|a0dc/([^/]++)/([^/]++)/([^/]++)/eba0dc(*:2679)' + .')' + .'|0(?' + .'|0da0/([^/]++)/([^/]++)/([^/]++)/e00da0(*:2731)' + .'|c641/([^/]++)/([^/]++)/([^/]++)/e0c641(*:2778)' + .')' + .'|e(?' + .'|cca5/([^/]++)/([^/]++)/([^/]++)/eecca5(*:2830)' + .'|d5af/([^/]++)/([^/]++)/([^/]++)/eed5af(*:2877)' + .')' + .'|96ed4/([^/]++)/([^/]++)/([^/]++)/e96ed4(*:2926)' + .'|1(?' + .'|6542/([^/]++)/([^/]++)/([^/]++)/e16542(*:2977)' + .'|e32e/([^/]++)/([^/]++)/([^/]++)/e1e32e(*:3024)' + .')' + .'|56954/([^/]++)/([^/]++)/([^/]++)/e56954(*:3073)' + .'|f(?' + .'|0d39/([^/]++)/([^/]++)/([^/]++)/ef0d39(*:3124)' + .'|e937/([^/]++)/([^/]++)/([^/]++)/efe937(*:3171)' + .'|575e/([^/]++)/([^/]++)/([^/]++)/ef575e(*:3218)' + .')' + .'|7b24b/([^/]++)/([^/]++)/([^/]++)/e7b24b(*:3267)' + .'|836d8/([^/]++)/([^/]++)/([^/]++)/e836d8(*:3315)' + .')' + .'|/a(?' + .'|8(?' + .'|7ff6/([^/]++)/([^/]++)/([^/]++)/a87ff6(*:3372)' + .'|baa5/([^/]++)/([^/]++)/([^/]++)/a8baa5(*:3419)' + .'|f15e/([^/]++)/([^/]++)/([^/]++)/a8f15e(*:3466)' + .'|c88a/([^/]++)/([^/]++)/([^/]++)/a8c88a(*:3513)' + .'|abb4/([^/]++)/([^/]++)/([^/]++)/a8abb4(*:3560)' + .')' + .'|a(?' + .'|b323/([^/]++)/([^/]++)/([^/]++)/aab323(*:3612)' + .'|942a/([^/]++)/([^/]++)/([^/]++)/aa942a(*:3659)' + .')' + .'|5(?' + .'|bfc9/([^/]++)/([^/]++)/([^/]++)/a5bfc9(*:3711)' + .'|771b/([^/]++)/([^/]++)/([^/]++)/a5771b(*:3758)' + .'|e001/([^/]++)/([^/]++)/([^/]++)/a5e001(*:3805)' + .'|97e5/([^/]++)/([^/]++)/([^/]++)/a597e5(*:3852)' + .'|16a8/([^/]++)/([^/]++)/([^/]++)/a516a8(*:3899)' + .')' + .'|1d0c6/([^/]++)/([^/]++)/([^/]++)/a1d0c6(*:3948)' + .'|6(?' + .'|84ec/([^/]++)/([^/]++)/([^/]++)/a684ec(*:3999)' + .'|6658/([^/]++)/([^/]++)/([^/]++)/a66658(*:4046)' + .')' + .'|3(?' + .'|f390/([^/]++)/([^/]++)/([^/]++)/a3f390(*:4098)' + .'|c65c/([^/]++)/([^/]++)/([^/]++)/a3c65c(*:4145)' + .')' + .'|d(?' + .'|61ab/([^/]++)/([^/]++)/([^/]++)/ad61ab(*:4197)' + .'|13a2/([^/]++)/([^/]++)/([^/]++)/ad13a2(*:4244)' + .'|972f/([^/]++)/([^/]++)/([^/]++)/ad972f(*:4291)' + .')' + .'|c(?' + .'|627a/([^/]++)/([^/]++)/([^/]++)/ac627a(*:4343)' + .'|1dd2/([^/]++)/([^/]++)/([^/]++)/ac1dd2(*:4390)' + .')' + .'|9(?' + .'|7da6/([^/]++)/([^/]++)/([^/]++)/a97da6(*:4442)' + .'|6b65/([^/]++)/([^/]++)/([^/]++)/a96b65(*:4489)' + .')' + .'|0(?' + .'|a080/([^/]++)/([^/]++)/([^/]++)/a0a080(*:4541)' + .'|2ffd/([^/]++)/([^/]++)/([^/]++)/a02ffd(*:4588)' + .'|1a03/([^/]++)/([^/]++)/([^/]++)/a01a03(*:4635)' + .')' + .'|4(?' + .'|a042/([^/]++)/([^/]++)/([^/]++)/a4a042(*:4687)' + .'|f236/([^/]++)/([^/]++)/([^/]++)/a4f236(*:4734)' + .'|9e94/([^/]++)/([^/]++)/([^/]++)/a49e94(*:4781)' + .')' + .'|2557a/([^/]++)/([^/]++)/([^/]++)/a2557a(*:4830)' + .'|b817c/([^/]++)/([^/]++)/([^/]++)/ab817c(*:4878)' + .')' + .'|/1(?' + .'|6(?' + .'|7909/([^/]++)/([^/]++)/([^/]++)/167909(*:4935)' + .'|a5cd/([^/]++)/([^/]++)/([^/]++)/16a5cd(*:4982)' + .'|51cf/([^/]++)/([^/]++)/([^/]++)/1651cf(*:5029)' + .')' + .'|f(?' + .'|0e3d/([^/]++)/([^/]++)/([^/]++)/1f0e3d(*:5081)' + .'|f(?' + .'|1de/([^/]++)/([^/]++)/([^/]++)/1ff1de(*:5131)' + .'|8a7/([^/]++)/([^/]++)/([^/]++)/1ff8a7(*:5177)' + .')' + .')' + .'|8(?' + .'|2be0/([^/]++)/([^/]++)/([^/]++)/182be0(*:5230)' + .'|d804/([^/]++)/([^/]++)/([^/]++)/18d804(*:5277)' + .'|9977/([^/]++)/([^/]++)/([^/]++)/189977(*:5324)' + .')' + .'|c(?' + .'|383c/([^/]++)/([^/]++)/([^/]++)/1c383c(*:5376)' + .'|9ac0/([^/]++)/([^/]++)/([^/]++)/1c9ac0(*:5423)' + .')' + .'|9(?' + .'|ca14/([^/]++)/([^/]++)/([^/]++)/19ca14(*:5475)' + .'|f3cd/([^/]++)/([^/]++)/([^/]++)/19f3cd(*:5522)' + .')' + .'|7(?' + .'|e621/([^/]++)/([^/]++)/([^/]++)/17e621(*:5574)' + .'|0000/([^/]++)/([^/]++)/([^/]++)/170000(*:5621)' + .'|d63b/([^/]++)/([^/]++)/([^/]++)/17d63b(*:5668)' + .')' + .'|4(?' + .'|bfa6/([^/]++)/([^/]++)/([^/]++)/14bfa6(*:5720)' + .'|0f69/([^/]++)/([^/]++)/([^/]++)/140f69(*:5767)' + .'|9e96/([^/]++)/([^/]++)/([^/]++)/149e96(*:5814)' + .'|2949/([^/]++)/([^/]++)/([^/]++)/142949(*:5861)' + .')' + .'|a(?' + .'|fa34/([^/]++)/([^/]++)/([^/]++)/1afa34(*:5913)' + .'|5b1e/([^/]++)/([^/]++)/([^/]++)/1a5b1e(*:5960)' + .')' + .'|3(?' + .'|8(?' + .'|597/([^/]++)/([^/]++)/([^/]++)/138597(*:6015)' + .'|bb0/([^/]++)/([^/]++)/([^/]++)/138bb0(*:6061)' + .')' + .'|f(?' + .'|e9d/([^/]++)/([^/]++)/([^/]++)/13fe9d(*:6112)' + .'|989/([^/]++)/([^/]++)/([^/]++)/13f989(*:6158)' + .'|3cf/([^/]++)/([^/]++)/([^/]++)/13f3cf(*:6204)' + .')' + .')' + .'|d7f7a/([^/]++)/([^/]++)/([^/]++)/1d7f7a(*:6254)' + .'|5(?' + .'|34b7/([^/]++)/([^/]++)/([^/]++)/1534b7(*:6305)' + .'|8f30/([^/]++)/([^/]++)/([^/]++)/158f30(*:6352)' + .'|4384/([^/]++)/([^/]++)/([^/]++)/154384(*:6399)' + .'|d4e8/([^/]++)/([^/]++)/([^/]++)/15d4e8(*:6446)' + .')' + .'|1(?' + .'|5f89/([^/]++)/([^/]++)/([^/]++)/115f89(*:6498)' + .'|b984/([^/]++)/([^/]++)/([^/]++)/11b984(*:6545)' + .')' + .'|068c6/([^/]++)/([^/]++)/([^/]++)/1068c6(*:6594)' + .'|be3bc/([^/]++)/([^/]++)/([^/]++)/1be3bc(*:6642)' + .')' + .'|/8(?' + .'|f(?' + .'|1(?' + .'|4e4/([^/]++)/([^/]++)/([^/]++)/8f14e4(*:6702)' + .'|21c/([^/]++)/([^/]++)/([^/]++)/8f121c(*:6748)' + .')' + .'|8551/([^/]++)/([^/]++)/([^/]++)/8f8551(*:6796)' + .'|5329/([^/]++)/([^/]++)/([^/]++)/8f5329(*:6843)' + .'|e009/([^/]++)/([^/]++)/([^/]++)/8fe009(*:6890)' + .')' + .'|e(?' + .'|296a/([^/]++)/([^/]++)/([^/]++)/8e296a(*:6942)' + .'|98d8/([^/]++)/([^/]++)/([^/]++)/8e98d8(*:6989)' + .'|fb10/([^/]++)/([^/]++)/([^/]++)/8efb10(*:7036)' + .'|6b42/([^/]++)/([^/]++)/([^/]++)/8e6b42(*:7083)' + .')' + .'|61398/([^/]++)/([^/]++)/([^/]++)/861398(*:7132)' + .'|1(?' + .'|2b4b/([^/]++)/([^/]++)/([^/]++)/812b4b(*:7183)' + .'|9f46/([^/]++)/([^/]++)/([^/]++)/819f46(*:7230)' + .'|6b11/([^/]++)/([^/]++)/([^/]++)/816b11(*:7277)' + .')' + .'|d(?' + .'|5e95/([^/]++)/([^/]++)/([^/]++)/8d5e95(*:7329)' + .'|3bba/([^/]++)/([^/]++)/([^/]++)/8d3bba(*:7376)' + .'|d48d/([^/]++)/([^/]++)/([^/]++)/8dd48d(*:7423)' + .'|7d8e/([^/]++)/([^/]++)/([^/]++)/8d7d8e(*:7470)' + .')' + .'|2(?' + .'|aa4b/([^/]++)/([^/]++)/([^/]++)/82aa4b(*:7522)' + .'|1(?' + .'|612/([^/]++)/([^/]++)/([^/]++)/821612(*:7572)' + .'|fa7/([^/]++)/([^/]++)/([^/]++)/821fa7(*:7618)' + .')' + .'|cec9/([^/]++)/([^/]++)/([^/]++)/82cec9(*:7666)' + .')' + .'|5(?' + .'|d8ce/([^/]++)/([^/]++)/([^/]++)/85d8ce(*:7718)' + .'|4d(?' + .'|6f/([^/]++)/([^/]++)/([^/]++)/854d6f(*:7768)' + .'|9f/([^/]++)/([^/]++)/([^/]++)/854d9f(*:7813)' + .')' + .')' + .'|4d9ee/([^/]++)/([^/]++)/([^/]++)/84d9ee(*:7863)' + .'|c(?' + .'|19f5/([^/]++)/([^/]++)/([^/]++)/8c19f5(*:7914)' + .'|b22b/([^/]++)/([^/]++)/([^/]++)/8cb22b(*:7961)' + .')' + .'|39ab4/([^/]++)/([^/]++)/([^/]++)/839ab4(*:8010)' + .'|9f0fd/([^/]++)/([^/]++)/([^/]++)/89f0fd(*:8058)' + .'|bf121/([^/]++)/([^/]++)/([^/]++)/8bf121(*:8106)' + .'|77a9b/([^/]++)/([^/]++)/([^/]++)/877a9b(*:8154)' + .')' + .'|/4(?' + .'|5(?' + .'|c48c/([^/]++)/([^/]++)/([^/]++)/45c48c(*:8211)' + .'|fbc6/([^/]++)/([^/]++)/([^/]++)/45fbc6(*:8258)' + .')' + .'|e732c/([^/]++)/([^/]++)/([^/]++)/4e732c(*:8307)' + .'|4f683/([^/]++)/([^/]++)/([^/]++)/44f683(*:8355)' + .'|3(?' + .'|ec51/([^/]++)/([^/]++)/([^/]++)/43ec51(*:8406)' + .'|2aca/([^/]++)/([^/]++)/([^/]++)/432aca(*:8453)' + .')' + .'|c5(?' + .'|6ff/([^/]++)/([^/]++)/([^/]++)/4c56ff(*:8505)' + .'|bde/([^/]++)/([^/]++)/([^/]++)/4c5bde(*:8551)' + .')' + .'|2(?' + .'|a0e1/([^/]++)/([^/]++)/([^/]++)/42a0e1(*:8603)' + .'|e7aa/([^/]++)/([^/]++)/([^/]++)/42e7aa(*:8650)' + .'|998c/([^/]++)/([^/]++)/([^/]++)/42998c(*:8697)' + .'|8fca/([^/]++)/([^/]++)/([^/]++)/428fca(*:8744)' + .')' + .'|7(?' + .'|d1e9/([^/]++)/([^/]++)/([^/]++)/47d1e9(*:8796)' + .'|34ba/([^/]++)/([^/]++)/([^/]++)/4734ba(*:8843)' + .')' + .'|6ba9f/([^/]++)/([^/]++)/([^/]++)/46ba9f(*:8892)' + .'|8aedb/([^/]++)/([^/]++)/([^/]++)/48aedb(*:8940)' + .'|9(?' + .'|182f/([^/]++)/([^/]++)/([^/]++)/49182f(*:8991)' + .'|6e05/([^/]++)/([^/]++)/([^/]++)/496e05(*:9038)' + .'|ae49/([^/]++)/([^/]++)/([^/]++)/49ae49(*:9085)' + .')' + .'|0008b/([^/]++)/([^/]++)/([^/]++)/40008b(*:9134)' + .'|1(?' + .'|f1f1/([^/]++)/([^/]++)/([^/]++)/41f1f1(*:9185)' + .'|ae36/([^/]++)/([^/]++)/([^/]++)/41ae36(*:9232)' + .')' + .'|f(?' + .'|6ffe/([^/]++)/([^/]++)/([^/]++)/4f6ffe(*:9284)' + .'|4adc/([^/]++)/([^/]++)/([^/]++)/4f4adc(*:9331)' + .')' + .')' + .'|/d(?' + .'|3(?' + .'|d944/([^/]++)/([^/]++)/([^/]++)/d3d944(*:9389)' + .'|9577/([^/]++)/([^/]++)/([^/]++)/d39577(*:9436)' + .'|4ab1/([^/]++)/([^/]++)/([^/]++)/d34ab1(*:9483)' + .')' + .'|6(?' + .'|7d8a/([^/]++)/([^/]++)/([^/]++)/d67d8a(*:9535)' + .'|4592/([^/]++)/([^/]++)/([^/]++)/d64592(*:9582)' + .'|baf6/([^/]++)/([^/]++)/([^/]++)/d6baf6(*:9629)' + .'|1e4b/([^/]++)/([^/]++)/([^/]++)/d61e4b(*:9676)' + .')' + .'|9(?' + .'|d4f4/([^/]++)/([^/]++)/([^/]++)/d9d4f4(*:9728)' + .'|6409/([^/]++)/([^/]++)/([^/]++)/d96409(*:9775)' + .'|47bf/([^/]++)/([^/]++)/([^/]++)/d947bf(*:9822)' + .'|fc5b/([^/]++)/([^/]++)/([^/]++)/d9fc5b(*:9869)' + .')' + .'|8(?' + .'|2c8d/([^/]++)/([^/]++)/([^/]++)/d82c8d(*:9921)' + .'|1f9c/([^/]++)/([^/]++)/([^/]++)/d81f9c(*:9968)' + .')' + .'|2(?' + .'|ddea/([^/]++)/([^/]++)/([^/]++)/d2ddea(*:10020)' + .'|96c1/([^/]++)/([^/]++)/([^/]++)/d296c1(*:10068)' + .')' + .'|0(?' + .'|9bf4/([^/]++)/([^/]++)/([^/]++)/d09bf4(*:10121)' + .'|7e70/([^/]++)/([^/]++)/([^/]++)/d07e70(*:10169)' + .')' + .'|1(?' + .'|f(?' + .'|e17/([^/]++)/([^/]++)/([^/]++)/d1fe17(*:10225)' + .'|491/([^/]++)/([^/]++)/([^/]++)/d1f491(*:10272)' + .'|255/([^/]++)/([^/]++)/([^/]++)/d1f255(*:10319)' + .')' + .'|c38a/([^/]++)/([^/]++)/([^/]++)/d1c38a(*:10368)' + .'|8f65/([^/]++)/([^/]++)/([^/]++)/d18f65(*:10416)' + .')' + .'|a4fb5/([^/]++)/([^/]++)/([^/]++)/da4fb5(*:10466)' + .'|b8e1a/([^/]++)/([^/]++)/([^/]++)/db8e1a(*:10515)' + .'|709f3/([^/]++)/([^/]++)/([^/]++)/d709f3(*:10564)' + .'|c(?' + .'|912a/([^/]++)/([^/]++)/([^/]++)/dc912a(*:10616)' + .'|6a64/([^/]++)/([^/]++)/([^/]++)/dc6a64(*:10664)' + .')' + .'|db306/([^/]++)/([^/]++)/([^/]++)/ddb306(*:10714)' + .')' + .'|/6(?' + .'|5(?' + .'|12bd/([^/]++)/([^/]++)/([^/]++)/6512bd(*:10772)' + .'|b9ee/([^/]++)/([^/]++)/([^/]++)/65b9ee(*:10820)' + .'|ded5/([^/]++)/([^/]++)/([^/]++)/65ded5(*:10868)' + .')' + .'|f(?' + .'|4922/([^/]++)/([^/]++)/([^/]++)/6f4922(*:10921)' + .'|3ef7/([^/]++)/([^/]++)/([^/]++)/6f3ef7(*:10969)' + .'|aa80/([^/]++)/([^/]++)/([^/]++)/6faa80(*:11017)' + .')' + .'|e(?' + .'|a(?' + .'|9ab/([^/]++)/([^/]++)/([^/]++)/6ea9ab(*:11073)' + .'|2ef/([^/]++)/([^/]++)/([^/]++)/6ea2ef(*:11120)' + .')' + .'|cbdd/([^/]++)/([^/]++)/([^/]++)/6ecbdd(*:11169)' + .')' + .'|3(?' + .'|64d3/([^/]++)/([^/]++)/([^/]++)/6364d3(*:11222)' + .'|dc7e/([^/]++)/([^/]++)/([^/]++)/63dc7e(*:11270)' + .'|923f/([^/]++)/([^/]++)/([^/]++)/63923f(*:11318)' + .')' + .'|c(?' + .'|8349/([^/]++)/([^/]++)/([^/]++)/6c8349(*:11371)' + .'|4b76/([^/]++)/([^/]++)/([^/]++)/6c4b76(*:11419)' + .'|dd60/([^/]++)/([^/]++)/([^/]++)/6cdd60(*:11467)' + .'|9882/([^/]++)/([^/]++)/([^/]++)/6c9882(*:11515)' + .'|524f/([^/]++)/([^/]++)/([^/]++)/6c524f(*:11563)' + .')' + .'|7(?' + .'|c6a1/([^/]++)/([^/]++)/([^/]++)/67c6a1(*:11616)' + .'|f7fb/([^/]++)/([^/]++)/([^/]++)/67f7fb(*:11664)' + .')' + .'|42e92/([^/]++)/([^/]++)/([^/]++)/642e92(*:11714)' + .'|6(?' + .'|f041/([^/]++)/([^/]++)/([^/]++)/66f041(*:11766)' + .'|808e/([^/]++)/([^/]++)/([^/]++)/66808e(*:11814)' + .'|3682/([^/]++)/([^/]++)/([^/]++)/663682(*:11862)' + .')' + .'|8(?' + .'|d30a/([^/]++)/([^/]++)/([^/]++)/68d30a(*:11915)' + .'|8396/([^/]++)/([^/]++)/([^/]++)/688396(*:11963)' + .'|5545/([^/]++)/([^/]++)/([^/]++)/685545(*:12011)' + .'|ce19/([^/]++)/([^/]++)/([^/]++)/68ce19(*:12059)' + .')' + .'|9(?' + .'|74ce/([^/]++)/([^/]++)/([^/]++)/6974ce(*:12112)' + .'|8d51/([^/]++)/([^/]++)/([^/]++)/698d51(*:12160)' + .'|adc1/([^/]++)/([^/]++)/([^/]++)/69adc1(*:12208)' + .'|cb3e/([^/]++)/([^/]++)/([^/]++)/69cb3e(*:12256)' + .')' + .'|da(?' + .'|900/([^/]++)/([^/]++)/([^/]++)/6da900(*:12309)' + .'|37d/([^/]++)/([^/]++)/([^/]++)/6da37d(*:12356)' + .')' + .'|21bf6/([^/]++)/([^/]++)/([^/]++)/621bf6(*:12406)' + .'|a9aed/([^/]++)/([^/]++)/([^/]++)/6a9aed(*:12455)' + .')' + .'|/9(?' + .'|b(?' + .'|f31c/([^/]++)/([^/]++)/([^/]++)/9bf31c(*:12513)' + .'|8619/([^/]++)/([^/]++)/([^/]++)/9b8619(*:12561)' + .'|04d1/([^/]++)/([^/]++)/([^/]++)/9b04d1(*:12609)' + .'|e40c/([^/]++)/([^/]++)/([^/]++)/9be40c(*:12657)' + .'|70e8/([^/]++)/([^/]++)/([^/]++)/9b70e8(*:12705)' + .')' + .'|8(?' + .'|f137/([^/]++)/([^/]++)/([^/]++)/98f137(*:12758)' + .'|dce8/([^/]++)/([^/]++)/([^/]++)/98dce8(*:12806)' + .'|72ed/([^/]++)/([^/]++)/([^/]++)/9872ed(*:12854)' + .'|b297/([^/]++)/([^/]++)/([^/]++)/98b297(*:12902)' + .')' + .'|a(?' + .'|1158/([^/]++)/([^/]++)/([^/]++)/9a1158(*:12955)' + .'|9687/([^/]++)/([^/]++)/([^/]++)/9a9687(*:13003)' + .')' + .'|f(?' + .'|6140/([^/]++)/([^/]++)/([^/]++)/9f6140(*:13056)' + .'|c3d7/([^/]++)/([^/]++)/([^/]++)/9fc3d7(*:13104)' + .'|d818/([^/]++)/([^/]++)/([^/]++)/9fd818(*:13152)' + .')' + .'|7(?' + .'|78d5/([^/]++)/([^/]++)/([^/]++)/9778d5(*:13205)' + .'|6652/([^/]++)/([^/]++)/([^/]++)/976652(*:13253)' + .'|9d47/([^/]++)/([^/]++)/([^/]++)/979d47(*:13301)' + .')' + .'|3db85/([^/]++)/([^/]++)/([^/]++)/93db85(*:13351)' + .'|2c(?' + .'|c22/([^/]++)/([^/]++)/([^/]++)/92cc22(*:13403)' + .'|8c9/([^/]++)/([^/]++)/([^/]++)/92c8c9(*:13450)' + .')' + .'|03ce9/([^/]++)/([^/]++)/([^/]++)/903ce9(*:13500)' + .'|6da2f/([^/]++)/([^/]++)/([^/]++)/96da2f(*:13549)' + .'|d(?' + .'|cb88/([^/]++)/([^/]++)/([^/]++)/9dcb88(*:13601)' + .'|fcd5/([^/]++)/([^/]++)/([^/]++)/9dfcd5(*:13649)' + .'|e6d1/([^/]++)/([^/]++)/([^/]++)/9de6d1(*:13697)' + .')' + .'|c(?' + .'|fdf1/([^/]++)/([^/]++)/([^/]++)/9cfdf1(*:13750)' + .'|838d/([^/]++)/([^/]++)/([^/]++)/9c838d(*:13798)' + .')' + .'|18(?' + .'|890/([^/]++)/([^/]++)/([^/]++)/918890(*:13851)' + .'|317/([^/]++)/([^/]++)/([^/]++)/918317(*:13898)' + .')' + .'|4(?' + .'|f6d7/([^/]++)/([^/]++)/([^/]++)/94f6d7(*:13951)' + .'|1e1a/([^/]++)/([^/]++)/([^/]++)/941e1a(*:13999)' + .'|31c8/([^/]++)/([^/]++)/([^/]++)/9431c8(*:14047)' + .'|61cc/([^/]++)/([^/]++)/([^/]++)/9461cc(*:14095)' + .')' + .'|50a41/([^/]++)/([^/]++)/([^/]++)/950a41(*:14145)' + .')' + .'|/7(?' + .'|0(?' + .'|efdf/([^/]++)/([^/]++)/([^/]++)/70efdf(*:14203)' + .'|5f21/([^/]++)/([^/]++)/([^/]++)/705f21(*:14251)' + .'|c639/([^/]++)/([^/]++)/([^/]++)/70c639(*:14299)' + .')' + .'|2b32a/([^/]++)/([^/]++)/([^/]++)/72b32a(*:14349)' + .'|f(?' + .'|39f8/([^/]++)/([^/]++)/([^/]++)/7f39f8(*:14401)' + .'|6ffa/([^/]++)/([^/]++)/([^/]++)/7f6ffa(*:14449)' + .'|1(?' + .'|de2/([^/]++)/([^/]++)/([^/]++)/7f1de2(*:14500)' + .'|00b/([^/]++)/([^/]++)/([^/]++)/7f100b(*:14547)' + .')' + .'|e1f8/([^/]++)/([^/]++)/([^/]++)/7fe1f8(*:14596)' + .')' + .'|3(?' + .'|5b90/([^/]++)/([^/]++)/([^/]++)/735b90(*:14649)' + .'|278a/([^/]++)/([^/]++)/([^/]++)/73278a(*:14697)' + .'|80ad/([^/]++)/([^/]++)/([^/]++)/7380ad(*:14745)' + .')' + .'|cbbc4/([^/]++)/([^/]++)/([^/]++)/7cbbc4(*:14795)' + .'|6(?' + .'|4796/([^/]++)/([^/]++)/([^/]++)/764796(*:14847)' + .'|dc61/([^/]++)/([^/]++)/([^/]++)/76dc61(*:14895)' + .')' + .'|e(?' + .'|f605/([^/]++)/([^/]++)/([^/]++)/7ef605(*:14948)' + .'|7757/([^/]++)/([^/]++)/([^/]++)/7e7757(*:14996)' + .'|a(?' + .'|be3/([^/]++)/([^/]++)/([^/]++)/7eabe3(*:15047)' + .'|cb5/([^/]++)/([^/]++)/([^/]++)/7eacb5(*:15094)' + .')' + .')' + .'|5(?' + .'|7b50/([^/]++)/([^/]++)/([^/]++)/757b50(*:15148)' + .'|8874/([^/]++)/([^/]++)/([^/]++)/758874(*:15196)' + .'|fc09/([^/]++)/([^/]++)/([^/]++)/75fc09(*:15244)' + .')' + .'|4(?' + .'|db12/([^/]++)/([^/]++)/([^/]++)/74db12(*:15297)' + .'|071a/([^/]++)/([^/]++)/([^/]++)/74071a(*:15345)' + .')' + .'|a614f/([^/]++)/([^/]++)/([^/]++)/7a614f(*:15395)' + .'|d04bb/([^/]++)/([^/]++)/([^/]++)/7d04bb(*:15444)' + .')' + .'|/3(?' + .'|c(?' + .'|59dc/([^/]++)/([^/]++)/([^/]++)/3c59dc(*:15502)' + .'|ec07/([^/]++)/([^/]++)/([^/]++)/3cec07(*:15550)' + .'|7781/([^/]++)/([^/]++)/([^/]++)/3c7781(*:15598)' + .'|f166/([^/]++)/([^/]++)/([^/]++)/3cf166(*:15646)' + .')' + .'|7(?' + .'|693c/([^/]++)/([^/]++)/([^/]++)/37693c(*:15699)' + .'|a749/([^/]++)/([^/]++)/([^/]++)/37a749(*:15747)' + .'|bc2f/([^/]++)/([^/]++)/([^/]++)/37bc2f(*:15795)' + .'|1bce/([^/]++)/([^/]++)/([^/]++)/371bce(*:15843)' + .')' + .'|3(?' + .'|e75f/([^/]++)/([^/]++)/([^/]++)/33e75f(*:15896)' + .'|5f53/([^/]++)/([^/]++)/([^/]++)/335f53(*:15944)' + .')' + .'|4(?' + .'|1(?' + .'|73c/([^/]++)/([^/]++)/([^/]++)/34173c(*:16000)' + .'|6a7/([^/]++)/([^/]++)/([^/]++)/3416a7(*:16047)' + .')' + .'|ed06/([^/]++)/([^/]++)/([^/]++)/34ed06(*:16096)' + .')' + .'|2(?' + .'|95c7/([^/]++)/([^/]++)/([^/]++)/3295c7(*:16149)' + .'|bb90/([^/]++)/([^/]++)/([^/]++)/32bb90(*:16197)' + .'|0722/([^/]++)/([^/]++)/([^/]++)/320722(*:16245)' + .')' + .'|5(?' + .'|f4a8/([^/]++)/([^/]++)/([^/]++)/35f4a8(*:16298)' + .'|7a6f/([^/]++)/([^/]++)/([^/]++)/357a6f(*:16346)' + .'|2fe2/([^/]++)/([^/]++)/([^/]++)/352fe2(*:16394)' + .'|0510/([^/]++)/([^/]++)/([^/]++)/350510(*:16442)' + .')' + .'|ef815/([^/]++)/([^/]++)/([^/]++)/3ef815(*:16492)' + .'|8(?' + .'|b3ef/([^/]++)/([^/]++)/([^/]++)/38b3ef(*:16544)' + .'|af86/([^/]++)/([^/]++)/([^/]++)/38af86(*:16592)' + .'|db3a/([^/]++)/([^/]++)/([^/]++)/38db3a(*:16640)' + .')' + .'|d(?' + .'|ef18/([^/]++)/([^/]++)/([^/]++)/3def18(*:16693)' + .'|d48a/([^/]++)/([^/]++)/([^/]++)/3dd48a(*:16741)' + .')' + .'|9(?' + .'|88c7/([^/]++)/([^/]++)/([^/]++)/3988c7(*:16794)' + .'|0597/([^/]++)/([^/]++)/([^/]++)/390597(*:16842)' + .'|461a/([^/]++)/([^/]++)/([^/]++)/39461a(*:16890)' + .')' + .'|6(?' + .'|3663/([^/]++)/([^/]++)/([^/]++)/363663(*:16943)' + .'|44a6/([^/]++)/([^/]++)/([^/]++)/3644a6(*:16991)' + .'|660e/([^/]++)/([^/]++)/([^/]++)/36660e(*:17039)' + .')' + .'|1(?' + .'|fefc/([^/]++)/([^/]++)/([^/]++)/31fefc(*:17092)' + .'|0dcb/([^/]++)/([^/]++)/([^/]++)/310dcb(*:17140)' + .')' + .'|b8a61/([^/]++)/([^/]++)/([^/]++)/3b8a61(*:17190)' + .'|fe94a/([^/]++)/([^/]++)/([^/]++)/3fe94a(*:17239)' + .'|ad7c2/([^/]++)/([^/]++)/([^/]++)/3ad7c2(*:17288)' + .')' + .'|/b(?' + .'|6(?' + .'|d767/([^/]++)/([^/]++)/([^/]++)/b6d767(*:17346)' + .'|f047/([^/]++)/([^/]++)/([^/]++)/b6f047(*:17394)' + .')' + .'|53(?' + .'|b3a/([^/]++)/([^/]++)/([^/]++)/b53b3a(*:17447)' + .'|4ba/([^/]++)/([^/]++)/([^/]++)/b534ba(*:17494)' + .')' + .'|3(?' + .'|e3e3/([^/]++)/([^/]++)/([^/]++)/b3e3e3(*:17547)' + .'|967a/([^/]++)/([^/]++)/([^/]++)/b3967a(*:17595)' + .')' + .'|7(?' + .'|3ce3/([^/]++)/([^/]++)/([^/]++)/b73ce3(*:17648)' + .'|b16e/([^/]++)/([^/]++)/([^/]++)/b7b16e(*:17696)' + .')' + .'|d(?' + .'|4c9a/([^/]++)/([^/]++)/([^/]++)/bd4c9a(*:17749)' + .'|686f/([^/]++)/([^/]++)/([^/]++)/bd686f(*:17797)' + .')' + .'|f8229/([^/]++)/([^/]++)/([^/]++)/bf8229(*:17847)' + .'|1(?' + .'|d10e/([^/]++)/([^/]++)/([^/]++)/b1d10e(*:17899)' + .'|a59b/([^/]++)/([^/]++)/([^/]++)/b1a59b(*:17947)' + .')' + .'|c(?' + .'|be33/([^/]++)/([^/]++)/([^/]++)/bcbe33(*:18000)' + .'|6dc4/([^/]++)/([^/]++)/([^/]++)/bc6dc4(*:18048)' + .'|a82e/([^/]++)/([^/]++)/([^/]++)/bca82e(*:18096)' + .')' + .'|e(?' + .'|83ab/([^/]++)/([^/]++)/([^/]++)/be83ab(*:18149)' + .'|ed13/([^/]++)/([^/]++)/([^/]++)/beed13(*:18197)' + .')' + .'|2eb73/([^/]++)/([^/]++)/([^/]++)/b2eb73(*:18247)' + .'|83aac/([^/]++)/([^/]++)/([^/]++)/b83aac(*:18296)' + .'|ac916/([^/]++)/([^/]++)/([^/]++)/bac916(*:18345)' + .'|b(?' + .'|f94b/([^/]++)/([^/]++)/([^/]++)/bbf94b(*:18397)' + .'|cbff/([^/]++)/([^/]++)/([^/]++)/bbcbff(*:18445)' + .')' + .'|9228e/([^/]++)/([^/]++)/([^/]++)/b9228e(*:18495)' + .')' + .'|/0(?' + .'|2(?' + .'|e74f/([^/]++)/([^/]++)/([^/]++)/02e74f(*:18553)' + .'|522a/([^/]++)/([^/]++)/([^/]++)/02522a(*:18601)' + .'|66e3/([^/]++)/([^/]++)/([^/]++)/0266e3(*:18649)' + .')' + .'|9(?' + .'|3f65/([^/]++)/([^/]++)/([^/]++)/093f65(*:18702)' + .'|1d58/([^/]++)/([^/]++)/([^/]++)/091d58(*:18750)' + .')' + .'|7(?' + .'|2b03/([^/]++)/([^/]++)/([^/]++)/072b03(*:18803)' + .'|e1cd/([^/]++)/([^/]++)/([^/]++)/07e1cd(*:18851)' + .'|7(?' + .'|7d5/([^/]++)/([^/]++)/([^/]++)/0777d5(*:18902)' + .'|e29/([^/]++)/([^/]++)/([^/]++)/077e29(*:18949)' + .')' + .'|cdfd/([^/]++)/([^/]++)/([^/]++)/07cdfd(*:18998)' + .')' + .'|3(?' + .'|afdb/([^/]++)/([^/]++)/([^/]++)/03afdb(*:19051)' + .'|36dc/([^/]++)/([^/]++)/([^/]++)/0336dc(*:19099)' + .'|c6b0/([^/]++)/([^/]++)/([^/]++)/03c6b0(*:19147)' + .'|53ab/([^/]++)/([^/]++)/([^/]++)/0353ab(*:19195)' + .')' + .'|6(?' + .'|9059/([^/]++)/([^/]++)/([^/]++)/069059(*:19248)' + .'|4096/([^/]++)/([^/]++)/([^/]++)/064096(*:19296)' + .'|0ad9/([^/]++)/([^/]++)/([^/]++)/060ad9(*:19344)' + .'|138b/([^/]++)/([^/]++)/([^/]++)/06138b(*:19392)' + .'|eb61/([^/]++)/([^/]++)/([^/]++)/06eb61(*:19440)' + .')' + .'|1(?' + .'|3(?' + .'|d40/([^/]++)/([^/]++)/([^/]++)/013d40(*:19496)' + .'|86b/([^/]++)/([^/]++)/([^/]++)/01386b(*:19543)' + .')' + .'|161a/([^/]++)/([^/]++)/([^/]++)/01161a(*:19592)' + .'|9d38/([^/]++)/([^/]++)/([^/]++)/019d38(*:19640)' + .')' + .'|f(?' + .'|28b5/([^/]++)/([^/]++)/([^/]++)/0f28b5(*:19693)' + .'|49c8/([^/]++)/([^/]++)/([^/]++)/0f49c8(*:19741)' + .')' + .'|a(?' + .'|09c8/([^/]++)/([^/]++)/([^/]++)/0a09c8(*:19794)' + .'|a188/([^/]++)/([^/]++)/([^/]++)/0aa188(*:19842)' + .')' + .'|0(?' + .'|6f52/([^/]++)/([^/]++)/([^/]++)/006f52(*:19895)' + .'|4114/([^/]++)/([^/]++)/([^/]++)/004114(*:19943)' + .'|ec53/([^/]++)/([^/]++)/([^/]++)/00ec53(*:19991)' + .')' + .'|4(?' + .'|5117/([^/]++)/([^/]++)/([^/]++)/045117(*:20044)' + .'|0259/([^/]++)/([^/]++)/([^/]++)/040259(*:20092)' + .')' + .'|84b6f/([^/]++)/([^/]++)/([^/]++)/084b6f(*:20142)' + .'|e(?' + .'|6597/([^/]++)/([^/]++)/([^/]++)/0e6597(*:20194)' + .'|0193/([^/]++)/([^/]++)/([^/]++)/0e0193(*:20242)' + .')' + .'|bb4ae/([^/]++)/([^/]++)/([^/]++)/0bb4ae(*:20292)' + .'|5(?' + .'|049e/([^/]++)/([^/]++)/([^/]++)/05049e(*:20344)' + .'|84ce/([^/]++)/([^/]++)/([^/]++)/0584ce(*:20392)' + .'|f971/([^/]++)/([^/]++)/([^/]++)/05f971(*:20440)' + .')' + .'|c74b7/([^/]++)/([^/]++)/([^/]++)/0c74b7(*:20490)' + .'|d(?' + .'|0fd7/([^/]++)/([^/]++)/([^/]++)/0d0fd7(*:20542)' + .'|eb1c/([^/]++)/([^/]++)/([^/]++)/0deb1c(*:20590)' + .')' + .')' + .'|/f(?' + .'|7(?' + .'|1(?' + .'|771/([^/]++)/([^/]++)/([^/]++)/f71771(*:20652)' + .'|849/([^/]++)/([^/]++)/([^/]++)/f71849(*:20699)' + .')' + .'|e6c8/([^/]++)/([^/]++)/([^/]++)/f7e6c8(*:20748)' + .'|6640/([^/]++)/([^/]++)/([^/]++)/f76640(*:20796)' + .'|3b76/([^/]++)/([^/]++)/([^/]++)/f73b76(*:20844)' + .'|4909/([^/]++)/([^/]++)/([^/]++)/f74909(*:20892)' + .'|70b6/([^/]++)/([^/]++)/([^/]++)/f770b6(*:20940)' + .')' + .'|4(?' + .'|57c5/([^/]++)/([^/]++)/([^/]++)/f457c5(*:20993)' + .'|b9ec/([^/]++)/([^/]++)/([^/]++)/f4b9ec(*:21041)' + .'|f6dc/([^/]++)/([^/]++)/([^/]++)/f4f6dc(*:21089)' + .')' + .'|c(?' + .'|490c/([^/]++)/([^/]++)/([^/]++)/fc490c(*:21142)' + .'|2213/([^/]++)/([^/]++)/([^/]++)/fc2213(*:21190)' + .'|cb60/([^/]++)/([^/]++)/([^/]++)/fccb60(*:21238)' + .')' + .'|b(?' + .'|d793/([^/]++)/([^/]++)/([^/]++)/fbd793(*:21291)' + .'|7b9f/([^/]++)/([^/]++)/([^/]++)/fb7b9f(*:21339)' + .')' + .'|0(?' + .'|33ab/([^/]++)/([^/]++)/([^/]++)/f033ab(*:21392)' + .'|935e/([^/]++)/([^/]++)/([^/]++)/f0935e(*:21440)' + .')' + .'|e(?' + .'|9fc2/([^/]++)/([^/]++)/([^/]++)/fe9fc2(*:21493)' + .'|131d/([^/]++)/([^/]++)/([^/]++)/fe131d(*:21541)' + .'|73f6/([^/]++)/([^/]++)/([^/]++)/fe73f6(*:21589)' + .')' + .'|8(?' + .'|9913/([^/]++)/([^/]++)/([^/]++)/f89913(*:21642)' + .'|c1f2/([^/]++)/([^/]++)/([^/]++)/f8c1f2(*:21690)' + .'|5454/([^/]++)/([^/]++)/([^/]++)/f85454(*:21738)' + .')' + .'|2(?' + .'|2170/([^/]++)/([^/]++)/([^/]++)/f22170(*:21791)' + .'|fc99/([^/]++)/([^/]++)/([^/]++)/f2fc99(*:21839)' + .')' + .'|a(?' + .'|7cdf/([^/]++)/([^/]++)/([^/]++)/fa7cdf(*:21892)' + .'|a9af/([^/]++)/([^/]++)/([^/]++)/faa9af(*:21940)' + .')' + .'|340f1/([^/]++)/([^/]++)/([^/]++)/f340f1(*:21990)' + .'|9(?' + .'|0f2a/([^/]++)/([^/]++)/([^/]++)/f90f2a(*:22042)' + .'|b902/([^/]++)/([^/]++)/([^/]++)/f9b902(*:22090)' + .')' + .'|fd52f/([^/]++)/([^/]++)/([^/]++)/ffd52f(*:22140)' + .'|61d69/([^/]++)/([^/]++)/([^/]++)/f61d69(*:22189)' + .'|5f859/([^/]++)/([^/]++)/([^/]++)/f5f859(*:22238)' + .'|1b6f2/([^/]++)/([^/]++)/([^/]++)/f1b6f2(*:22287)' + .')' + .'|/2(?' + .'|8(?' + .'|3802/([^/]++)/([^/]++)/([^/]++)/283802(*:22345)' + .'|dd2c/([^/]++)/([^/]++)/([^/]++)/28dd2c(*:22393)' + .'|9dff/([^/]++)/([^/]++)/([^/]++)/289dff(*:22441)' + .'|f0b8/([^/]++)/([^/]++)/([^/]++)/28f0b8(*:22489)' + .')' + .'|a(?' + .'|38a4/([^/]++)/([^/]++)/([^/]++)/2a38a4(*:22542)' + .'|79ea/([^/]++)/([^/]++)/([^/]++)/2a79ea(*:22590)' + .')' + .'|6(?' + .'|657d/([^/]++)/([^/]++)/([^/]++)/26657d(*:22643)' + .'|e359/([^/]++)/([^/]++)/([^/]++)/26e359(*:22691)' + .'|3373/([^/]++)/([^/]++)/([^/]++)/263373(*:22739)' + .')' + .'|7(?' + .'|23d0/([^/]++)/([^/]++)/([^/]++)/2723d0(*:22792)' + .'|4ad4/([^/]++)/([^/]++)/([^/]++)/274ad4(*:22840)' + .')' + .'|b(?' + .'|4492/([^/]++)/([^/]++)/([^/]++)/2b4492(*:22893)' + .'|24d4/([^/]++)/([^/]++)/([^/]++)/2b24d4(*:22941)' + .')' + .'|0(?' + .'|2cb9/([^/]++)/([^/]++)/([^/]++)/202cb9(*:22994)' + .'|f075/([^/]++)/([^/]++)/([^/]++)/20f075(*:23042)' + .'|50e0/([^/]++)/([^/]++)/([^/]++)/2050e0(*:23090)' + .')' + .'|f(?' + .'|2b26/([^/]++)/([^/]++)/([^/]++)/2f2b26(*:23143)' + .'|5570/([^/]++)/([^/]++)/([^/]++)/2f5570(*:23191)' + .')' + .'|4(?' + .'|b16f/([^/]++)/([^/]++)/([^/]++)/24b16f(*:23244)' + .'|8e84/([^/]++)/([^/]++)/([^/]++)/248e84(*:23292)' + .'|21fc/([^/]++)/([^/]++)/([^/]++)/2421fc(*:23340)' + .')' + .'|5(?' + .'|b282/([^/]++)/([^/]++)/([^/]++)/25b282(*:23393)' + .'|0cf8/([^/]++)/([^/]++)/([^/]++)/250cf8(*:23441)' + .'|ddc0/([^/]++)/([^/]++)/([^/]++)/25ddc0(*:23489)' + .')' + .'|18a0a/([^/]++)/([^/]++)/([^/]++)/218a0a(*:23539)' + .')' + .'|/5(?' + .'|4229a/([^/]++)/([^/]++)/([^/]++)/54229a(*:23594)' + .'|f(?' + .'|93f9/([^/]++)/([^/]++)/([^/]++)/5f93f9(*:23646)' + .'|d0b3/([^/]++)/([^/]++)/([^/]++)/5fd0b3(*:23694)' + .')' + .'|ef(?' + .'|0(?' + .'|59/([^/]++)/([^/]++)/([^/]++)/5ef059(*:23750)' + .'|b4/([^/]++)/([^/]++)/([^/]++)/5ef0b4(*:23796)' + .')' + .'|698/([^/]++)/([^/]++)/([^/]++)/5ef698(*:23844)' + .')' + .'|8(?' + .'|78a7/([^/]++)/([^/]++)/([^/]++)/5878a7(*:23897)' + .'|a2fc/([^/]++)/([^/]++)/([^/]++)/58a2fc(*:23945)' + .'|238e/([^/]++)/([^/]++)/([^/]++)/58238e(*:23993)' + .')' + .'|7(?' + .'|aeee/([^/]++)/([^/]++)/([^/]++)/57aeee(*:24046)' + .'|7(?' + .'|ef1/([^/]++)/([^/]++)/([^/]++)/577ef1(*:24097)' + .'|bcc/([^/]++)/([^/]++)/([^/]++)/577bcc(*:24144)' + .')' + .'|37c6/([^/]++)/([^/]++)/([^/]++)/5737c6(*:24193)' + .')' + .'|3(?' + .'|9fd5/([^/]++)/([^/]++)/([^/]++)/539fd5(*:24246)' + .'|c3bc/([^/]++)/([^/]++)/([^/]++)/53c3bc(*:24294)' + .')' + .'|5(?' + .'|5d67/([^/]++)/([^/]++)/([^/]++)/555d67(*:24347)' + .'|0a14/([^/]++)/([^/]++)/([^/]++)/550a14(*:24395)' + .'|9cb9/([^/]++)/([^/]++)/([^/]++)/559cb9(*:24443)' + .'|a7cf/([^/]++)/([^/]++)/([^/]++)/55a7cf(*:24491)' + .')' + .'|02e4a/([^/]++)/([^/]++)/([^/]++)/502e4a(*:24541)' + .'|b8add/([^/]++)/([^/]++)/([^/]++)/5b8add(*:24590)' + .'|2720e/([^/]++)/([^/]++)/([^/]++)/52720e(*:24639)' + .'|a4b25/([^/]++)/([^/]++)/([^/]++)/5a4b25(*:24688)' + .'|1d92b/([^/]++)/([^/]++)/([^/]++)/51d92b(*:24737)' + .'|98b3e/([^/]++)/([^/]++)/([^/]++)/598b3e(*:24786)' + .')' + .')/?$}sD', + 24786 => '{^(?' + .'|/5(?' + .'|b69b9/([^/]++)/([^/]++)/([^/]++)/5b69b9(*:24837)' + .'|9(?' + .'|b90e/([^/]++)/([^/]++)/([^/]++)/59b90e(*:24889)' + .'|c330/([^/]++)/([^/]++)/([^/]++)/59c330(*:24937)' + .')' + .'|3(?' + .'|fde9/([^/]++)/([^/]++)/([^/]++)/53fde9(*:24990)' + .'|e3a7/([^/]++)/([^/]++)/([^/]++)/53e3a7(*:25038)' + .')' + .'|e(?' + .'|a164/([^/]++)/([^/]++)/([^/]++)/5ea164(*:25091)' + .'|3881/([^/]++)/([^/]++)/([^/]++)/5e3881(*:25139)' + .'|9f92/([^/]++)/([^/]++)/([^/]++)/5e9f92(*:25187)' + .'|c91a/([^/]++)/([^/]++)/([^/]++)/5ec91a(*:25235)' + .')' + .'|7(?' + .'|3703/([^/]++)/([^/]++)/([^/]++)/573703(*:25288)' + .'|51ec/([^/]++)/([^/]++)/([^/]++)/5751ec(*:25336)' + .'|05e1/([^/]++)/([^/]++)/([^/]++)/5705e1(*:25384)' + .')' + .'|8(?' + .'|ae74/([^/]++)/([^/]++)/([^/]++)/58ae74(*:25437)' + .'|d4d1/([^/]++)/([^/]++)/([^/]++)/58d4d1(*:25485)' + .'|07a6/([^/]++)/([^/]++)/([^/]++)/5807a6(*:25533)' + .'|e4d4/([^/]++)/([^/]++)/([^/]++)/58e4d4(*:25581)' + .')' + .'|d(?' + .'|44ee/([^/]++)/([^/]++)/([^/]++)/5d44ee(*:25634)' + .'|d9db/([^/]++)/([^/]++)/([^/]++)/5dd9db(*:25682)' + .')' + .'|5(?' + .'|b37c/([^/]++)/([^/]++)/([^/]++)/55b37c(*:25735)' + .'|743c/([^/]++)/([^/]++)/([^/]++)/55743c(*:25783)' + .'|6f39/([^/]++)/([^/]++)/([^/]++)/556f39(*:25831)' + .')' + .'|c(?' + .'|0492/([^/]++)/([^/]++)/([^/]++)/5c0492(*:25884)' + .'|572e/([^/]++)/([^/]++)/([^/]++)/5c572e(*:25932)' + .'|9362/([^/]++)/([^/]++)/([^/]++)/5c9362(*:25980)' + .')' + .'|4(?' + .'|8731/([^/]++)/([^/]++)/([^/]++)/548731(*:26033)' + .'|a367/([^/]++)/([^/]++)/([^/]++)/54a367(*:26081)' + .')' + .'|0(?' + .'|0e75/([^/]++)/([^/]++)/([^/]++)/500e75(*:26134)' + .'|c3d7/([^/]++)/([^/]++)/([^/]++)/50c3d7(*:26182)' + .')' + .'|f(?' + .'|2c22/([^/]++)/([^/]++)/([^/]++)/5f2c22(*:26235)' + .'|0f5e/([^/]++)/([^/]++)/([^/]++)/5f0f5e(*:26283)' + .')' + .'|1ef18/([^/]++)/([^/]++)/([^/]++)/51ef18(*:26333)' + .')' + .'|/b(?' + .'|5(?' + .'|b41f/([^/]++)/([^/]++)/([^/]++)/b5b41f(*:26391)' + .'|dc4e/([^/]++)/([^/]++)/([^/]++)/b5dc4e(*:26439)' + .'|6a18/([^/]++)/([^/]++)/([^/]++)/b56a18(*:26487)' + .'|5ec2/([^/]++)/([^/]++)/([^/]++)/b55ec2(*:26535)' + .')' + .'|337e8/([^/]++)/([^/]++)/([^/]++)/b337e8(*:26585)' + .'|a(?' + .'|2fd3/([^/]++)/([^/]++)/([^/]++)/ba2fd3(*:26637)' + .'|3866/([^/]++)/([^/]++)/([^/]++)/ba3866(*:26685)' + .')' + .'|2(?' + .'|eeb7/([^/]++)/([^/]++)/([^/]++)/b2eeb7(*:26738)' + .'|f627/([^/]++)/([^/]++)/([^/]++)/b2f627(*:26786)' + .')' + .'|7(?' + .'|3dfe/([^/]++)/([^/]++)/([^/]++)/b73dfe(*:26839)' + .'|bb35/([^/]++)/([^/]++)/([^/]++)/b7bb35(*:26887)' + .'|ee6f/([^/]++)/([^/]++)/([^/]++)/b7ee6f(*:26935)' + .'|892f/([^/]++)/([^/]++)/([^/]++)/b7892f(*:26983)' + .'|0683/([^/]++)/([^/]++)/([^/]++)/b70683(*:27031)' + .')' + .'|4(?' + .'|288d/([^/]++)/([^/]++)/([^/]++)/b4288d(*:27084)' + .'|a528/([^/]++)/([^/]++)/([^/]++)/b4a528(*:27132)' + .')' + .'|e(?' + .'|3159/([^/]++)/([^/]++)/([^/]++)/be3159(*:27185)' + .'|b22f/([^/]++)/([^/]++)/([^/]++)/beb22f(*:27233)' + .'|a595/([^/]++)/([^/]++)/([^/]++)/bea595(*:27281)' + .')' + .'|1(?' + .'|eec3/([^/]++)/([^/]++)/([^/]++)/b1eec3(*:27334)' + .'|37fd/([^/]++)/([^/]++)/([^/]++)/b137fd(*:27382)' + .')' + .'|0(?' + .'|56eb/([^/]++)/([^/]++)/([^/]++)/b056eb(*:27435)' + .'|b183/([^/]++)/([^/]++)/([^/]++)/b0b183(*:27483)' + .')' + .'|f6276/([^/]++)/([^/]++)/([^/]++)/bf6276(*:27533)' + .'|6(?' + .'|edc1/([^/]++)/([^/]++)/([^/]++)/b6edc1(*:27585)' + .'|a108/([^/]++)/([^/]++)/([^/]++)/b6a108(*:27633)' + .')' + .'|86e8d/([^/]++)/([^/]++)/([^/]++)/b86e8d(*:27683)' + .')' + .'|/2(?' + .'|8(?' + .'|5e19/([^/]++)/([^/]++)/([^/]++)/285e19(*:27741)' + .'|2(?' + .'|3f4/([^/]++)/([^/]++)/([^/]++)/2823f4(*:27792)' + .'|67a/([^/]++)/([^/]++)/([^/]++)/28267a(*:27839)' + .')' + .'|8cc0/([^/]++)/([^/]++)/([^/]++)/288cc0(*:27888)' + .'|7e03/([^/]++)/([^/]++)/([^/]++)/287e03(*:27936)' + .')' + .'|d(?' + .'|6cc4/([^/]++)/([^/]++)/([^/]++)/2d6cc4(*:27989)' + .'|ea61/([^/]++)/([^/]++)/([^/]++)/2dea61(*:28037)' + .'|ace7/([^/]++)/([^/]++)/([^/]++)/2dace7(*:28085)' + .')' + .'|b(?' + .'|8a61/([^/]++)/([^/]++)/([^/]++)/2b8a61(*:28138)' + .'|b232/([^/]++)/([^/]++)/([^/]++)/2bb232(*:28186)' + .'|a596/([^/]++)/([^/]++)/([^/]++)/2ba596(*:28234)' + .'|cab9/([^/]++)/([^/]++)/([^/]++)/2bcab9(*:28282)' + .')' + .'|9(?' + .'|8f95/([^/]++)/([^/]++)/([^/]++)/298f95(*:28335)' + .'|1597/([^/]++)/([^/]++)/([^/]++)/291597(*:28383)' + .')' + .'|58be1/([^/]++)/([^/]++)/([^/]++)/258be1(*:28433)' + .'|3(?' + .'|3509/([^/]++)/([^/]++)/([^/]++)/233509(*:28485)' + .'|ce18/([^/]++)/([^/]++)/([^/]++)/23ce18(*:28533)' + .')' + .'|6(?' + .'|dd0d/([^/]++)/([^/]++)/([^/]++)/26dd0d(*:28586)' + .'|408f/([^/]++)/([^/]++)/([^/]++)/26408f(*:28634)' + .')' + .'|f(?' + .'|37d1/([^/]++)/([^/]++)/([^/]++)/2f37d1(*:28687)' + .'|885d/([^/]++)/([^/]++)/([^/]++)/2f885d(*:28735)' + .')' + .'|2(?' + .'|91d2/([^/]++)/([^/]++)/([^/]++)/2291d2(*:28788)' + .'|ac3c/([^/]++)/([^/]++)/([^/]++)/22ac3c(*:28836)' + .'|fb0c/([^/]++)/([^/]++)/([^/]++)/22fb0c(*:28884)' + .')' + .'|4(?' + .'|6819/([^/]++)/([^/]++)/([^/]++)/246819(*:28937)' + .'|896e/([^/]++)/([^/]++)/([^/]++)/24896e(*:28985)' + .')' + .'|a(?' + .'|fe45/([^/]++)/([^/]++)/([^/]++)/2afe45(*:29038)' + .'|084e/([^/]++)/([^/]++)/([^/]++)/2a084e(*:29086)' + .'|9d12/([^/]++)/([^/]++)/([^/]++)/2a9d12(*:29134)' + .'|b564/([^/]++)/([^/]++)/([^/]++)/2ab564(*:29182)' + .')' + .'|1(?' + .'|7eed/([^/]++)/([^/]++)/([^/]++)/217eed(*:29235)' + .'|0f76/([^/]++)/([^/]++)/([^/]++)/210f76(*:29283)' + .')' + .'|e65f2/([^/]++)/([^/]++)/([^/]++)/2e65f2(*:29333)' + .'|ca65f/([^/]++)/([^/]++)/([^/]++)/2ca65f(*:29382)' + .'|0aee3/([^/]++)/([^/]++)/([^/]++)/20aee3(*:29431)' + .')' + .'|/e(?' + .'|8(?' + .'|c065/([^/]++)/([^/]++)/([^/]++)/e8c065(*:29489)' + .'|20a4/([^/]++)/([^/]++)/([^/]++)/e820a4(*:29537)' + .')' + .'|2(?' + .'|230b/([^/]++)/([^/]++)/([^/]++)/e2230b(*:29590)' + .'|a2dc/([^/]++)/([^/]++)/([^/]++)/e2a2dc(*:29638)' + .'|05ee/([^/]++)/([^/]++)/([^/]++)/e205ee(*:29686)' + .')' + .'|b(?' + .'|d962/([^/]++)/([^/]++)/([^/]++)/ebd962(*:29739)' + .'|6fdc/([^/]++)/([^/]++)/([^/]++)/eb6fdc(*:29787)' + .')' + .'|d(?' + .'|265b/([^/]++)/([^/]++)/([^/]++)/ed265b(*:29840)' + .'|fbe1/([^/]++)/([^/]++)/([^/]++)/edfbe1(*:29888)' + .'|e7e2/([^/]++)/([^/]++)/([^/]++)/ede7e2(*:29936)' + .')' + .'|6(?' + .'|b4b2/([^/]++)/([^/]++)/([^/]++)/e6b4b2(*:29989)' + .'|cb2a/([^/]++)/([^/]++)/([^/]++)/e6cb2a(*:30037)' + .')' + .'|5(?' + .'|f6ad/([^/]++)/([^/]++)/([^/]++)/e5f6ad(*:30090)' + .'|55eb/([^/]++)/([^/]++)/([^/]++)/e555eb(*:30138)' + .'|841d/([^/]++)/([^/]++)/([^/]++)/e5841d(*:30186)' + .'|7c6b/([^/]++)/([^/]++)/([^/]++)/e57c6b(*:30234)' + .')' + .'|aae33/([^/]++)/([^/]++)/([^/]++)/eaae33(*:30284)' + .'|4(?' + .'|bb4c/([^/]++)/([^/]++)/([^/]++)/e4bb4c(*:30336)' + .'|9b8b/([^/]++)/([^/]++)/([^/]++)/e49b8b(*:30384)' + .')' + .'|7(?' + .'|0611/([^/]++)/([^/]++)/([^/]++)/e70611(*:30437)' + .'|f8a7/([^/]++)/([^/]++)/([^/]++)/e7f8a7(*:30485)' + .'|44f9/([^/]++)/([^/]++)/([^/]++)/e744f9(*:30533)' + .')' + .'|9(?' + .'|95f9/([^/]++)/([^/]++)/([^/]++)/e995f9(*:30586)' + .'|4550/([^/]++)/([^/]++)/([^/]++)/e94550(*:30634)' + .'|7ee2/([^/]++)/([^/]++)/([^/]++)/e97ee2(*:30682)' + .')' + .'|e(?' + .'|fc9e/([^/]++)/([^/]++)/([^/]++)/eefc9e(*:30735)' + .'|b69a/([^/]++)/([^/]++)/([^/]++)/eeb69a(*:30783)' + .')' + .'|0(?' + .'|7413/([^/]++)/([^/]++)/([^/]++)/e07413(*:30836)' + .'|cf1f/([^/]++)/([^/]++)/([^/]++)/e0cf1f(*:30884)' + .'|ec45/([^/]++)/([^/]++)/([^/]++)/e0ec45(*:30932)' + .')' + .'|f4e3b/([^/]++)/([^/]++)/([^/]++)/ef4e3b(*:30982)' + .'|c5aa0/([^/]++)/([^/]++)/([^/]++)/ec5aa0(*:31031)' + .')' + .'|/f(?' + .'|f(?' + .'|4d5f/([^/]++)/([^/]++)/([^/]++)/ff4d5f(*:31089)' + .'|eabd/([^/]++)/([^/]++)/([^/]++)/ffeabd(*:31137)' + .')' + .'|3(?' + .'|f27a/([^/]++)/([^/]++)/([^/]++)/f3f27a(*:31190)' + .'|8762/([^/]++)/([^/]++)/([^/]++)/f38762(*:31238)' + .')' + .'|4(?' + .'|be00/([^/]++)/([^/]++)/([^/]++)/f4be00(*:31291)' + .'|5526/([^/]++)/([^/]++)/([^/]++)/f45526(*:31339)' + .'|7d0a/([^/]++)/([^/]++)/([^/]++)/f47d0a(*:31387)' + .')' + .'|0(?' + .'|e52b/([^/]++)/([^/]++)/([^/]++)/f0e52b(*:31440)' + .'|adc8/([^/]++)/([^/]++)/([^/]++)/f0adc8(*:31488)' + .')' + .'|de926/([^/]++)/([^/]++)/([^/]++)/fde926(*:31538)' + .'|5(?' + .'|deae/([^/]++)/([^/]++)/([^/]++)/f5deae(*:31590)' + .'|7a2f/([^/]++)/([^/]++)/([^/]++)/f57a2f(*:31638)' + .')' + .'|7(?' + .'|6a89/([^/]++)/([^/]++)/([^/]++)/f76a89(*:31691)' + .'|9921/([^/]++)/([^/]++)/([^/]++)/f79921(*:31739)' + .'|e905/([^/]++)/([^/]++)/([^/]++)/f7e905(*:31787)' + .')' + .'|2(?' + .'|9c21/([^/]++)/([^/]++)/([^/]++)/f29c21(*:31840)' + .'|201f/([^/]++)/([^/]++)/([^/]++)/f2201f(*:31888)' + .')' + .'|a(?' + .'|e0b2/([^/]++)/([^/]++)/([^/]++)/fae0b2(*:31941)' + .'|14d4/([^/]++)/([^/]++)/([^/]++)/fa14d4(*:31989)' + .'|3a3c/([^/]++)/([^/]++)/([^/]++)/fa3a3c(*:32037)' + .'|83a1/([^/]++)/([^/]++)/([^/]++)/fa83a1(*:32085)' + .')' + .'|c(?' + .'|cb3c/([^/]++)/([^/]++)/([^/]++)/fccb3c(*:32138)' + .'|8001/([^/]++)/([^/]++)/([^/]++)/fc8001(*:32186)' + .'|3cf4/([^/]++)/([^/]++)/([^/]++)/fc3cf4(*:32234)' + .'|4930/([^/]++)/([^/]++)/([^/]++)/fc4930(*:32282)' + .')' + .'|64eac/([^/]++)/([^/]++)/([^/]++)/f64eac(*:32332)' + .'|b8970/([^/]++)/([^/]++)/([^/]++)/fb8970(*:32381)' + .'|1c159/([^/]++)/([^/]++)/([^/]++)/f1c159(*:32430)' + .'|9(?' + .'|028f/([^/]++)/([^/]++)/([^/]++)/f9028f(*:32482)' + .'|a40a/([^/]++)/([^/]++)/([^/]++)/f9a40a(*:32530)' + .')' + .'|e(?' + .'|8c15/([^/]++)/([^/]++)/([^/]++)/fe8c15(*:32583)' + .'|c8d4/([^/]++)/([^/]++)/([^/]++)/fec8d4(*:32631)' + .'|7ee8/([^/]++)/([^/]++)/([^/]++)/fe7ee8(*:32679)' + .')' + .')' + .'|/3(?' + .'|8(?' + .'|9(?' + .'|bc7/([^/]++)/([^/]++)/([^/]++)/389bc7(*:32741)' + .'|13e/([^/]++)/([^/]++)/([^/]++)/38913e(*:32788)' + .')' + .'|71bd/([^/]++)/([^/]++)/([^/]++)/3871bd(*:32837)' + .')' + .'|d(?' + .'|c487/([^/]++)/([^/]++)/([^/]++)/3dc487(*:32890)' + .'|2d8c/([^/]++)/([^/]++)/([^/]++)/3d2d8c(*:32938)' + .'|8e28/([^/]++)/([^/]++)/([^/]++)/3d8e28(*:32986)' + .'|f1d4/([^/]++)/([^/]++)/([^/]++)/3df1d4(*:33034)' + .')' + .'|7f0e8/([^/]++)/([^/]++)/([^/]++)/37f0e8(*:33084)' + .'|3(?' + .'|e807/([^/]++)/([^/]++)/([^/]++)/33e807(*:33136)' + .'|28bd/([^/]++)/([^/]++)/([^/]++)/3328bd(*:33184)' + .')' + .'|a(?' + .'|0(?' + .'|772/([^/]++)/([^/]++)/([^/]++)/3a0772(*:33240)' + .'|66b/([^/]++)/([^/]++)/([^/]++)/3a066b(*:33287)' + .')' + .'|835d/([^/]++)/([^/]++)/([^/]++)/3a835d(*:33336)' + .')' + .'|0(?' + .'|bb38/([^/]++)/([^/]++)/([^/]++)/30bb38(*:33389)' + .'|3ed4/([^/]++)/([^/]++)/([^/]++)/303ed4(*:33437)' + .'|ef30/([^/]++)/([^/]++)/([^/]++)/30ef30(*:33485)' + .'|1ad0/([^/]++)/([^/]++)/([^/]++)/301ad0(*:33533)' + .')' + .'|4(?' + .'|9389/([^/]++)/([^/]++)/([^/]++)/349389(*:33586)' + .'|35c3/([^/]++)/([^/]++)/([^/]++)/3435c3(*:33634)' + .')' + .'|62(?' + .'|1f1/([^/]++)/([^/]++)/([^/]++)/3621f1(*:33687)' + .'|e80/([^/]++)/([^/]++)/([^/]++)/362e80(*:33734)' + .')' + .'|5(?' + .'|cf86/([^/]++)/([^/]++)/([^/]++)/35cf86(*:33787)' + .'|2407/([^/]++)/([^/]++)/([^/]++)/352407(*:33835)' + .')' + .'|2b30a/([^/]++)/([^/]++)/([^/]++)/32b30a(*:33885)' + .'|1839b/([^/]++)/([^/]++)/([^/]++)/31839b(*:33934)' + .'|b(?' + .'|5dca/([^/]++)/([^/]++)/([^/]++)/3b5dca(*:33986)' + .'|3dba/([^/]++)/([^/]++)/([^/]++)/3b3dba(*:34034)' + .')' + .'|e89eb/([^/]++)/([^/]++)/([^/]++)/3e89eb(*:34084)' + .'|cef96/([^/]++)/([^/]++)/([^/]++)/3cef96(*:34133)' + .')' + .'|/0(?' + .'|8(?' + .'|7408/([^/]++)/([^/]++)/([^/]++)/087408(*:34191)' + .'|b255/([^/]++)/([^/]++)/([^/]++)/08b255(*:34239)' + .'|c543/([^/]++)/([^/]++)/([^/]++)/08c543(*:34287)' + .'|d986/([^/]++)/([^/]++)/([^/]++)/08d986(*:34335)' + .'|419b/([^/]++)/([^/]++)/([^/]++)/08419b(*:34383)' + .')' + .'|7(?' + .'|563a/([^/]++)/([^/]++)/([^/]++)/07563a(*:34436)' + .'|6a0c/([^/]++)/([^/]++)/([^/]++)/076a0c(*:34484)' + .'|a96b/([^/]++)/([^/]++)/([^/]++)/07a96b(*:34532)' + .'|c580/([^/]++)/([^/]++)/([^/]++)/07c580(*:34580)' + .'|8719/([^/]++)/([^/]++)/([^/]++)/078719(*:34628)' + .')' + .'|f(?' + .'|cbc6/([^/]++)/([^/]++)/([^/]++)/0fcbc6(*:34681)' + .'|9661/([^/]++)/([^/]++)/([^/]++)/0f9661(*:34729)' + .'|f(?' + .'|39b/([^/]++)/([^/]++)/([^/]++)/0ff39b(*:34780)' + .'|803/([^/]++)/([^/]++)/([^/]++)/0ff803(*:34827)' + .')' + .'|840b/([^/]++)/([^/]++)/([^/]++)/0f840b(*:34876)' + .')' + .'|1(?' + .'|f78b/([^/]++)/([^/]++)/([^/]++)/01f78b(*:34929)' + .'|3a00/([^/]++)/([^/]++)/([^/]++)/013a00(*:34977)' + .'|8825/([^/]++)/([^/]++)/([^/]++)/018825(*:35025)' + .')' + .'|6(?' + .'|9(?' + .'|d3b/([^/]++)/([^/]++)/([^/]++)/069d3b(*:35081)' + .'|97f/([^/]++)/([^/]++)/([^/]++)/06997f(*:35128)' + .')' + .'|1412/([^/]++)/([^/]++)/([^/]++)/061412(*:35177)' + .')' + .'|4(?' + .'|ecb1/([^/]++)/([^/]++)/([^/]++)/04ecb1(*:35230)' + .'|3c3d/([^/]++)/([^/]++)/([^/]++)/043c3d(*:35278)' + .')' + .'|0ac8e/([^/]++)/([^/]++)/([^/]++)/00ac8e(*:35328)' + .'|5(?' + .'|1e4e/([^/]++)/([^/]++)/([^/]++)/051e4e(*:35380)' + .'|37fb/([^/]++)/([^/]++)/([^/]++)/0537fb(*:35428)' + .')' + .'|d(?' + .'|7de1/([^/]++)/([^/]++)/([^/]++)/0d7de1(*:35481)' + .'|3180/([^/]++)/([^/]++)/([^/]++)/0d3180(*:35529)' + .'|0871/([^/]++)/([^/]++)/([^/]++)/0d0871(*:35577)' + .')' + .'|cb929/([^/]++)/([^/]++)/([^/]++)/0cb929(*:35627)' + .'|2(?' + .'|a32a/([^/]++)/([^/]++)/([^/]++)/02a32a(*:35679)' + .'|4d7f/([^/]++)/([^/]++)/([^/]++)/024d7f(*:35727)' + .')' + .'|efe32/([^/]++)/([^/]++)/([^/]++)/0efe32(*:35777)' + .'|a113e/([^/]++)/([^/]++)/([^/]++)/0a113e(*:35826)' + .'|b8aff/([^/]++)/([^/]++)/([^/]++)/0b8aff(*:35875)' + .')' + .'|/a(?' + .'|7(?' + .'|6088/([^/]++)/([^/]++)/([^/]++)/a76088(*:35933)' + .'|aeed/([^/]++)/([^/]++)/([^/]++)/a7aeed(*:35981)' + .'|33fa/([^/]++)/([^/]++)/([^/]++)/a733fa(*:36029)' + .')' + .'|9a(?' + .'|665/([^/]++)/([^/]++)/([^/]++)/a9a665(*:36082)' + .'|1d5/([^/]++)/([^/]++)/([^/]++)/a9a1d5(*:36129)' + .')' + .'|8(?' + .'|6c45/([^/]++)/([^/]++)/([^/]++)/a86c45(*:36182)' + .'|849b/([^/]++)/([^/]++)/([^/]++)/a8849b(*:36230)' + .'|e(?' + .'|864/([^/]++)/([^/]++)/([^/]++)/a8e864(*:36281)' + .'|cba/([^/]++)/([^/]++)/([^/]++)/a8ecba(*:36328)' + .')' + .')' + .'|c(?' + .'|c3e0/([^/]++)/([^/]++)/([^/]++)/acc3e0(*:36382)' + .'|f4b8/([^/]++)/([^/]++)/([^/]++)/acf4b8(*:36430)' + .')' + .'|b(?' + .'|d815/([^/]++)/([^/]++)/([^/]++)/abd815(*:36483)' + .'|233b/([^/]++)/([^/]++)/([^/]++)/ab233b(*:36531)' + .'|a3b6/([^/]++)/([^/]++)/([^/]++)/aba3b6(*:36579)' + .'|88b1/([^/]++)/([^/]++)/([^/]++)/ab88b1(*:36627)' + .')' + .'|5(?' + .'|3240/([^/]++)/([^/]++)/([^/]++)/a53240(*:36680)' + .'|cdd4/([^/]++)/([^/]++)/([^/]++)/a5cdd4(*:36728)' + .')' + .'|f(?' + .'|d(?' + .'|483/([^/]++)/([^/]++)/([^/]++)/afd483(*:36784)' + .'|a33/([^/]++)/([^/]++)/([^/]++)/afda33(*:36831)' + .')' + .'|f162/([^/]++)/([^/]++)/([^/]++)/aff162(*:36880)' + .')' + .'|e(?' + .'|0eb3/([^/]++)/([^/]++)/([^/]++)/ae0eb3(*:36933)' + .'|b313/([^/]++)/([^/]++)/([^/]++)/aeb313(*:36981)' + .')' + .'|1(?' + .'|d33d/([^/]++)/([^/]++)/([^/]++)/a1d33d(*:37034)' + .'|140a/([^/]++)/([^/]++)/([^/]++)/a1140a(*:37082)' + .')' + .'|ddfa9/([^/]++)/([^/]++)/([^/]++)/addfa9(*:37132)' + .'|6(?' + .'|7f09/([^/]++)/([^/]++)/([^/]++)/a67f09(*:37184)' + .'|4c94/([^/]++)/([^/]++)/([^/]++)/a64c94(*:37232)' + .')' + .'|a169b/([^/]++)/([^/]++)/([^/]++)/aa169b(*:37282)' + .'|4300b/([^/]++)/([^/]++)/([^/]++)/a4300b(*:37331)' + .'|3d68b/([^/]++)/([^/]++)/([^/]++)/a3d68b(*:37380)' + .')' + .'|/1(?' + .'|0(?' + .'|a(?' + .'|7cd/([^/]++)/([^/]++)/([^/]++)/10a7cd(*:37441)' + .'|5ab/([^/]++)/([^/]++)/([^/]++)/10a5ab(*:37488)' + .')' + .'|9a0c/([^/]++)/([^/]++)/([^/]++)/109a0c(*:37537)' + .')' + .'|3f320/([^/]++)/([^/]++)/([^/]++)/13f320(*:37587)' + .'|6(?' + .'|c222/([^/]++)/([^/]++)/([^/]++)/16c222(*:37639)' + .'|8908/([^/]++)/([^/]++)/([^/]++)/168908(*:37687)' + .')' + .'|5(?' + .'|de21/([^/]++)/([^/]++)/([^/]++)/15de21(*:37740)' + .'|95af/([^/]++)/([^/]++)/([^/]++)/1595af(*:37788)' + .')' + .'|1(?' + .'|b921/([^/]++)/([^/]++)/([^/]++)/11b921(*:37841)' + .'|4193/([^/]++)/([^/]++)/([^/]++)/114193(*:37889)' + .')' + .'|bb91f/([^/]++)/([^/]++)/([^/]++)/1bb91f(*:37939)' + .'|7(?' + .'|28ef/([^/]++)/([^/]++)/([^/]++)/1728ef(*:37991)' + .'|c276/([^/]++)/([^/]++)/([^/]++)/17c276(*:38039)' + .'|0c94/([^/]++)/([^/]++)/([^/]++)/170c94(*:38087)' + .')' + .'|85(?' + .'|c29/([^/]++)/([^/]++)/([^/]++)/185c29(*:38140)' + .'|e65/([^/]++)/([^/]++)/([^/]++)/185e65(*:38187)' + .')' + .'|9(?' + .'|2fc0/([^/]++)/([^/]++)/([^/]++)/192fc0(*:38240)' + .'|b(?' + .'|c91/([^/]++)/([^/]++)/([^/]++)/19bc91(*:38291)' + .'|650/([^/]++)/([^/]++)/([^/]++)/19b650(*:38338)' + .')' + .'|05ae/([^/]++)/([^/]++)/([^/]++)/1905ae(*:38387)' + .')' + .'|e(?' + .'|cfb4/([^/]++)/([^/]++)/([^/]++)/1ecfb4(*:38440)' + .'|fa39/([^/]++)/([^/]++)/([^/]++)/1efa39(*:38488)' + .'|056d/([^/]++)/([^/]++)/([^/]++)/1e056d(*:38536)' + .')' + .'|aa48f/([^/]++)/([^/]++)/([^/]++)/1aa48f(*:38586)' + .'|f(?' + .'|c214/([^/]++)/([^/]++)/([^/]++)/1fc214(*:38638)' + .'|5089/([^/]++)/([^/]++)/([^/]++)/1f5089(*:38686)' + .'|4477/([^/]++)/([^/]++)/([^/]++)/1f4477(*:38734)' + .')' + .'|c(?' + .'|c363/([^/]++)/([^/]++)/([^/]++)/1cc363(*:38787)' + .'|1d4d/([^/]++)/([^/]++)/([^/]++)/1c1d4d(*:38835)' + .'|e927/([^/]++)/([^/]++)/([^/]++)/1ce927(*:38883)' + .')' + .')' + .'|/6(?' + .'|3(?' + .'|538f/([^/]++)/([^/]++)/([^/]++)/63538f(*:38942)' + .'|2cee/([^/]++)/([^/]++)/([^/]++)/632cee(*:38990)' + .'|95eb/([^/]++)/([^/]++)/([^/]++)/6395eb(*:39038)' + .')' + .'|9(?' + .'|421f/([^/]++)/([^/]++)/([^/]++)/69421f(*:39091)' + .'|2f93/([^/]++)/([^/]++)/([^/]++)/692f93(*:39139)' + .')' + .'|5658f/([^/]++)/([^/]++)/([^/]++)/65658f(*:39189)' + .'|4(?' + .'|7bba/([^/]++)/([^/]++)/([^/]++)/647bba(*:39241)' + .'|223c/([^/]++)/([^/]++)/([^/]++)/64223c(*:39289)' + .')' + .'|e(?' + .'|2713/([^/]++)/([^/]++)/([^/]++)/6e2713(*:39342)' + .'|0721/([^/]++)/([^/]++)/([^/]++)/6e0721(*:39390)' + .'|7b33/([^/]++)/([^/]++)/([^/]++)/6e7b33(*:39438)' + .')' + .'|0(?' + .'|5ff7/([^/]++)/([^/]++)/([^/]++)/605ff7(*:39491)' + .'|8159/([^/]++)/([^/]++)/([^/]++)/608159(*:39539)' + .')' + .'|a(?' + .'|ca97/([^/]++)/([^/]++)/([^/]++)/6aca97(*:39592)' + .'|10bb/([^/]++)/([^/]++)/([^/]++)/6a10bb(*:39640)' + .'|ab12/([^/]++)/([^/]++)/([^/]++)/6aab12(*:39688)' + .')' + .'|7(?' + .'|66aa/([^/]++)/([^/]++)/([^/]++)/6766aa(*:39741)' + .'|e103/([^/]++)/([^/]++)/([^/]++)/67e103(*:39789)' + .'|d(?' + .'|96d/([^/]++)/([^/]++)/([^/]++)/67d96d(*:39840)' + .'|16d/([^/]++)/([^/]++)/([^/]++)/67d16d(*:39887)' + .')' + .'|0e8a/([^/]++)/([^/]++)/([^/]++)/670e8a(*:39936)' + .'|7e09/([^/]++)/([^/]++)/([^/]++)/677e09(*:39984)' + .')' + .'|8(?' + .'|264b/([^/]++)/([^/]++)/([^/]++)/68264b(*:40037)' + .'|053a/([^/]++)/([^/]++)/([^/]++)/68053a(*:40085)' + .')' + .'|c(?' + .'|2979/([^/]++)/([^/]++)/([^/]++)/6c2979(*:40138)' + .'|d67d/([^/]++)/([^/]++)/([^/]++)/6cd67d(*:40186)' + .'|3cf7/([^/]++)/([^/]++)/([^/]++)/6c3cf7(*:40234)' + .'|fe0e/([^/]++)/([^/]++)/([^/]++)/6cfe0e(*:40282)' + .')' + .'|bc24f/([^/]++)/([^/]++)/([^/]++)/6bc24f(*:40332)' + .'|f2268/([^/]++)/([^/]++)/([^/]++)/6f2268(*:40381)' + .'|1b4a6/([^/]++)/([^/]++)/([^/]++)/61b4a6(*:40430)' + .'|21461/([^/]++)/([^/]++)/([^/]++)/621461(*:40479)' + .'|d0f84/([^/]++)/([^/]++)/([^/]++)/6d0f84(*:40528)' + .'|60229/([^/]++)/([^/]++)/([^/]++)/660229(*:40577)' + .')' + .'|/c(?' + .'|f(?' + .'|6735/([^/]++)/([^/]++)/([^/]++)/cf6735(*:40635)' + .'|bce4/([^/]++)/([^/]++)/([^/]++)/cfbce4(*:40683)' + .')' + .'|3(?' + .'|99(?' + .'|86/([^/]++)/([^/]++)/([^/]++)/c39986(*:40739)' + .'|2e/([^/]++)/([^/]++)/([^/]++)/c3992e(*:40785)' + .')' + .'|61bc/([^/]++)/([^/]++)/([^/]++)/c361bc(*:40834)' + .'|2d9b/([^/]++)/([^/]++)/([^/]++)/c32d9b(*:40882)' + .')' + .'|75b6f/([^/]++)/([^/]++)/([^/]++)/c75b6f(*:40932)' + .'|c(?' + .'|b(?' + .'|1d4/([^/]++)/([^/]++)/([^/]++)/ccb1d4(*:40987)' + .'|098/([^/]++)/([^/]++)/([^/]++)/ccb098(*:41034)' + .')' + .'|c0aa/([^/]++)/([^/]++)/([^/]++)/ccc0aa(*:41083)' + .'|1aa4/([^/]++)/([^/]++)/([^/]++)/cc1aa4(*:41131)' + .')' + .'|b(?' + .'|cb58/([^/]++)/([^/]++)/([^/]++)/cbcb58(*:41184)' + .'|b6a3/([^/]++)/([^/]++)/([^/]++)/cbb6a3(*:41232)' + .')' + .'|9892a/([^/]++)/([^/]++)/([^/]++)/c9892a(*:41282)' + .'|6e19e/([^/]++)/([^/]++)/([^/]++)/c6e19e(*:41331)' + .'|dc0d6/([^/]++)/([^/]++)/([^/]++)/cdc0d6(*:41380)' + .'|5ab0b/([^/]++)/([^/]++)/([^/]++)/c5ab0b(*:41429)' + .'|a(?' + .'|9c26/([^/]++)/([^/]++)/([^/]++)/ca9c26(*:41481)' + .'|8155/([^/]++)/([^/]++)/([^/]++)/ca8155(*:41529)' + .'|7591/([^/]++)/([^/]++)/([^/]++)/ca7591(*:41577)' + .')' + .'|0(?' + .'|6d06/([^/]++)/([^/]++)/([^/]++)/c06d06(*:41630)' + .'|f168/([^/]++)/([^/]++)/([^/]++)/c0f168(*:41678)' + .')' + .'|8(?' + .'|ed21/([^/]++)/([^/]++)/([^/]++)/c8ed21(*:41731)' + .'|fbbc/([^/]++)/([^/]++)/([^/]++)/c8fbbc(*:41779)' + .'|c41c/([^/]++)/([^/]++)/([^/]++)/c8c41c(*:41827)' + .')' + .'|15da1/([^/]++)/([^/]++)/([^/]++)/c15da1(*:41877)' + .'|2(?' + .'|626d/([^/]++)/([^/]++)/([^/]++)/c2626d(*:41929)' + .'|aee8/([^/]++)/([^/]++)/([^/]++)/c2aee8(*:41977)' + .'|2abf/([^/]++)/([^/]++)/([^/]++)/c22abf(*:42025)' + .')' + .'|e78d1/([^/]++)/([^/]++)/([^/]++)/ce78d1(*:42075)' + .'|4(?' + .'|015b/([^/]++)/([^/]++)/([^/]++)/c4015b(*:42127)' + .'|b31c/([^/]++)/([^/]++)/([^/]++)/c4b31c(*:42175)' + .')' + .')' + .'|/8(?' + .'|5(?' + .'|422a/([^/]++)/([^/]++)/([^/]++)/85422a(*:42234)' + .'|1ddf/([^/]++)/([^/]++)/([^/]++)/851ddf(*:42282)' + .'|fc37/([^/]++)/([^/]++)/([^/]++)/85fc37(*:42330)' + .')' + .'|1(?' + .'|4481/([^/]++)/([^/]++)/([^/]++)/814481(*:42383)' + .'|e74d/([^/]++)/([^/]++)/([^/]++)/81e74d(*:42431)' + .')' + .'|d(?' + .'|3(?' + .'|420/([^/]++)/([^/]++)/([^/]++)/8d3420(*:42487)' + .'|17b/([^/]++)/([^/]++)/([^/]++)/8d317b(*:42534)' + .')' + .'|f707/([^/]++)/([^/]++)/([^/]++)/8df707(*:42583)' + .'|6dc3/([^/]++)/([^/]++)/([^/]++)/8d6dc3(*:42631)' + .')' + .'|e(?' + .'|efcf/([^/]++)/([^/]++)/([^/]++)/8eefcf(*:42684)' + .'|bda5/([^/]++)/([^/]++)/([^/]++)/8ebda5(*:42732)' + .'|82ab/([^/]++)/([^/]++)/([^/]++)/8e82ab(*:42780)' + .')' + .'|b(?' + .'|16eb/([^/]++)/([^/]++)/([^/]++)/8b16eb(*:42833)' + .'|6dd7/([^/]++)/([^/]++)/([^/]++)/8b6dd7(*:42881)' + .'|5040/([^/]++)/([^/]++)/([^/]++)/8b5040(*:42929)' + .')' + .'|c(?' + .'|7bbb/([^/]++)/([^/]++)/([^/]++)/8c7bbb(*:42982)' + .'|6744/([^/]++)/([^/]++)/([^/]++)/8c6744(*:43030)' + .'|235f/([^/]++)/([^/]++)/([^/]++)/8c235f(*:43078)' + .')' + .'|8(?' + .'|4d24/([^/]++)/([^/]++)/([^/]++)/884d24(*:43131)' + .'|ae63/([^/]++)/([^/]++)/([^/]++)/88ae63(*:43179)' + .')' + .'|7(?' + .'|5715/([^/]++)/([^/]++)/([^/]++)/875715(*:43232)' + .'|2488/([^/]++)/([^/]++)/([^/]++)/872488(*:43280)' + .')' + .'|4(?' + .'|1172/([^/]++)/([^/]++)/([^/]++)/841172(*:43333)' + .'|6c26/([^/]++)/([^/]++)/([^/]++)/846c26(*:43381)' + .'|f7e6/([^/]++)/([^/]++)/([^/]++)/84f7e6(*:43429)' + .'|7cc5/([^/]++)/([^/]++)/([^/]++)/847cc5(*:43477)' + .')' + .'|f(?' + .'|ecb2/([^/]++)/([^/]++)/([^/]++)/8fecb2(*:43530)' + .'|7d80/([^/]++)/([^/]++)/([^/]++)/8f7d80(*:43578)' + .'|468c/([^/]++)/([^/]++)/([^/]++)/8f468c(*:43626)' + .')' + .'|a0e11/([^/]++)/([^/]++)/([^/]++)/8a0e11(*:43676)' + .'|2(?' + .'|f2b3/([^/]++)/([^/]++)/([^/]++)/82f2b3(*:43728)' + .'|489c/([^/]++)/([^/]++)/([^/]++)/82489c(*:43776)' + .')' + .'|6(?' + .'|b122/([^/]++)/([^/]++)/([^/]++)/86b122(*:43829)' + .'|0320/([^/]++)/([^/]++)/([^/]++)/860320(*:43877)' + .')' + .'|9(?' + .'|2c91/([^/]++)/([^/]++)/([^/]++)/892c91(*:43930)' + .'|fcd0/([^/]++)/([^/]++)/([^/]++)/89fcd0(*:43978)' + .')' + .'|065d0/([^/]++)/([^/]++)/([^/]++)/8065d0(*:44028)' + .')' + .'|/d(?' + .'|6(?' + .'|4a34/([^/]++)/([^/]++)/([^/]++)/d64a34(*:44086)' + .'|c651/([^/]++)/([^/]++)/([^/]++)/d6c651(*:44134)' + .')' + .'|f(?' + .'|877f/([^/]++)/([^/]++)/([^/]++)/df877f(*:44187)' + .'|263d/([^/]++)/([^/]++)/([^/]++)/df263d(*:44235)' + .'|7f28/([^/]++)/([^/]++)/([^/]++)/df7f28(*:44283)' + .'|6d23/([^/]++)/([^/]++)/([^/]++)/df6d23(*:44331)' + .')' + .'|b(?' + .'|85e2/([^/]++)/([^/]++)/([^/]++)/db85e2(*:44384)' + .'|e272/([^/]++)/([^/]++)/([^/]++)/dbe272(*:44432)' + .')' + .'|d(?' + .'|45(?' + .'|85/([^/]++)/([^/]++)/([^/]++)/dd4585(*:44488)' + .'|04/([^/]++)/([^/]++)/([^/]++)/dd4504(*:44534)' + .')' + .'|8eb9/([^/]++)/([^/]++)/([^/]++)/dd8eb9(*:44583)' + .')' + .'|a(?' + .'|ca41/([^/]++)/([^/]++)/([^/]++)/daca41(*:44636)' + .'|8ce5/([^/]++)/([^/]++)/([^/]++)/da8ce5(*:44684)' + .'|0d11/([^/]++)/([^/]++)/([^/]++)/da0d11(*:44732)' + .')' + .'|4(?' + .'|90d7/([^/]++)/([^/]++)/([^/]++)/d490d7(*:44785)' + .'|c2e4/([^/]++)/([^/]++)/([^/]++)/d4c2e4(*:44833)' + .')' + .'|8(?' + .'|6ea6/([^/]++)/([^/]++)/([^/]++)/d86ea6(*:44886)' + .'|40cc/([^/]++)/([^/]++)/([^/]++)/d840cc(*:44934)' + .')' + .'|c(?' + .'|82d6/([^/]++)/([^/]++)/([^/]++)/dc82d6(*:44987)' + .'|6a70/([^/]++)/([^/]++)/([^/]++)/dc6a70(*:45035)' + .'|5689/([^/]++)/([^/]++)/([^/]++)/dc5689(*:45083)' + .')' + .'|7(?' + .'|a728/([^/]++)/([^/]++)/([^/]++)/d7a728(*:45136)' + .'|0732/([^/]++)/([^/]++)/([^/]++)/d70732(*:45184)' + .'|9aac/([^/]++)/([^/]++)/([^/]++)/d79aac(*:45232)' + .')' + .'|14220/([^/]++)/([^/]++)/([^/]++)/d14220(*:45282)' + .'|5(?' + .'|cfea/([^/]++)/([^/]++)/([^/]++)/d5cfea(*:45334)' + .'|8072/([^/]++)/([^/]++)/([^/]++)/d58072(*:45382)' + .'|54f7/([^/]++)/([^/]++)/([^/]++)/d554f7(*:45430)' + .'|16b1/([^/]++)/([^/]++)/([^/]++)/d516b1(*:45478)' + .'|6b9f/([^/]++)/([^/]++)/([^/]++)/d56b9f(*:45526)' + .')' + .'|045c5/([^/]++)/([^/]++)/([^/]++)/d045c5(*:45576)' + .'|2(?' + .'|ed45/([^/]++)/([^/]++)/([^/]++)/d2ed45(*:45628)' + .'|40e3/([^/]++)/([^/]++)/([^/]++)/d240e3(*:45676)' + .')' + .'|93ed5/([^/]++)/([^/]++)/([^/]++)/d93ed5(*:45726)' + .')' + .'|/7(?' + .'|b(?' + .'|cdf7/([^/]++)/([^/]++)/([^/]++)/7bcdf7(*:45784)' + .'|13b2/([^/]++)/([^/]++)/([^/]++)/7b13b2(*:45832)' + .')' + .'|dcd34/([^/]++)/([^/]++)/([^/]++)/7dcd34(*:45882)' + .'|f(?' + .'|24d2/([^/]++)/([^/]++)/([^/]++)/7f24d2(*:45934)' + .'|5d04/([^/]++)/([^/]++)/([^/]++)/7f5d04(*:45982)' + .'|1171/([^/]++)/([^/]++)/([^/]++)/7f1171(*:46030)' + .'|a732/([^/]++)/([^/]++)/([^/]++)/7fa732(*:46078)' + .')' + .'|6(?' + .'|6ebc/([^/]++)/([^/]++)/([^/]++)/766ebc(*:46131)' + .'|34ea/([^/]++)/([^/]++)/([^/]++)/7634ea(*:46179)' + .')' + .'|750ca/([^/]++)/([^/]++)/([^/]++)/7750ca(*:46229)' + .'|1(?' + .'|a(?' + .'|3cb/([^/]++)/([^/]++)/([^/]++)/71a3cb(*:46284)' + .'|d16/([^/]++)/([^/]++)/([^/]++)/71ad16(*:46331)' + .')' + .'|43d7/([^/]++)/([^/]++)/([^/]++)/7143d7(*:46380)' + .')' + .'|88d98/([^/]++)/([^/]++)/([^/]++)/788d98(*:46430)' + .'|2(?' + .'|da7f/([^/]++)/([^/]++)/([^/]++)/72da7f(*:46482)' + .'|50eb/([^/]++)/([^/]++)/([^/]++)/7250eb(*:46530)' + .')' + .'|c(?' + .'|590f/([^/]++)/([^/]++)/([^/]++)/7c590f(*:46583)' + .'|e328/([^/]++)/([^/]++)/([^/]++)/7ce328(*:46631)' + .')' + .'|a5392/([^/]++)/([^/]++)/([^/]++)/7a5392(*:46681)' + .'|95c7a/([^/]++)/([^/]++)/([^/]++)/795c7a(*:46730)' + .'|504ad/([^/]++)/([^/]++)/([^/]++)/7504ad(*:46779)' + .'|04afe/([^/]++)/([^/]++)/([^/]++)/704afe(*:46828)' + .'|4bba2/([^/]++)/([^/]++)/([^/]++)/74bba2(*:46877)' + .')' + .'|/9(?' + .'|b(?' + .'|72e3/([^/]++)/([^/]++)/([^/]++)/9b72e3(*:46935)' + .'|698e/([^/]++)/([^/]++)/([^/]++)/9b698e(*:46983)' + .')' + .'|7e852/([^/]++)/([^/]++)/([^/]++)/97e852(*:47033)' + .'|4c7bb/([^/]++)/([^/]++)/([^/]++)/94c7bb(*:47082)' + .'|9(?' + .'|c5e0/([^/]++)/([^/]++)/([^/]++)/99c5e0(*:47134)' + .'|6a7f/([^/]++)/([^/]++)/([^/]++)/996a7f(*:47182)' + .'|bcfc/([^/]++)/([^/]++)/([^/]++)/99bcfc(*:47230)' + .'|0827/([^/]++)/([^/]++)/([^/]++)/990827(*:47278)' + .')' + .'|a(?' + .'|d6aa/([^/]++)/([^/]++)/([^/]++)/9ad6aa(*:47331)' + .'|b0d8/([^/]++)/([^/]++)/([^/]++)/9ab0d8(*:47379)' + .')' + .'|c(?' + .'|f81d/([^/]++)/([^/]++)/([^/]++)/9cf81d(*:47432)' + .'|c138/([^/]++)/([^/]++)/([^/]++)/9cc138(*:47480)' + .'|82c7/([^/]++)/([^/]++)/([^/]++)/9c82c7(*:47528)' + .'|0180/([^/]++)/([^/]++)/([^/]++)/9c0180(*:47576)' + .')' + .'|f(?' + .'|396f/([^/]++)/([^/]++)/([^/]++)/9f396f(*:47629)' + .'|e859/([^/]++)/([^/]++)/([^/]++)/9fe859(*:47677)' + .'|53d8/([^/]++)/([^/]++)/([^/]++)/9f53d8(*:47725)' + .')' + .'|12d2b/([^/]++)/([^/]++)/([^/]++)/912d2b(*:47775)' + .'|59a55/([^/]++)/([^/]++)/([^/]++)/959a55(*:47824)' + .'|6(?' + .'|ea64/([^/]++)/([^/]++)/([^/]++)/96ea64(*:47876)' + .'|b9bf/([^/]++)/([^/]++)/([^/]++)/96b9bf(*:47924)' + .')' + .'|e3cfc/([^/]++)/([^/]++)/([^/]++)/9e3cfc(*:47974)' + .'|2(?' + .'|fb0c/([^/]++)/([^/]++)/([^/]++)/92fb0c(*:48026)' + .'|262b/([^/]++)/([^/]++)/([^/]++)/92262b(*:48074)' + .'|32fe/([^/]++)/([^/]++)/([^/]++)/9232fe(*:48122)' + .'|977a/([^/]++)/([^/]++)/([^/]++)/92977a(*:48170)' + .')' + .'|8d6f5/([^/]++)/([^/]++)/([^/]++)/98d6f5(*:48220)' + .'|0794e/([^/]++)/([^/]++)/([^/]++)/90794e(*:48269)' + .'|34815/([^/]++)/([^/]++)/([^/]++)/934815(*:48318)' + .')' + .'|/4(?' + .'|e(?' + .'|4b5f/([^/]++)/([^/]++)/([^/]++)/4e4b5f(*:48376)' + .'|a06f/([^/]++)/([^/]++)/([^/]++)/4ea06f(*:48424)' + .'|0(?' + .'|928/([^/]++)/([^/]++)/([^/]++)/4e0928(*:48475)' + .'|cb6/([^/]++)/([^/]++)/([^/]++)/4e0cb6(*:48522)' + .')' + .')' + .'|6922a/([^/]++)/([^/]++)/([^/]++)/46922a(*:48573)' + .'|4(?' + .'|c4c1/([^/]++)/([^/]++)/([^/]++)/44c4c1(*:48625)' + .'|3cb0/([^/]++)/([^/]++)/([^/]++)/443cb0(*:48673)' + .')' + .'|8ab2f/([^/]++)/([^/]++)/([^/]++)/48ab2f(*:48723)' + .'|5(?' + .'|645a/([^/]++)/([^/]++)/([^/]++)/45645a(*:48775)' + .'|58db/([^/]++)/([^/]++)/([^/]++)/4558db(*:48823)' + .')' + .'|2e77b/([^/]++)/([^/]++)/([^/]++)/42e77b(*:48873)' + .'|c27ce/([^/]++)/([^/]++)/([^/]++)/4c27ce(*:48922)' + .'|f(?' + .'|fce0/([^/]++)/([^/]++)/([^/]++)/4ffce0(*:48974)' + .'|ac9b/([^/]++)/([^/]++)/([^/]++)/4fac9b(*:49022)' + .')' + .'|a47d2/([^/]++)/([^/]++)/([^/]++)/4a47d2(*:49072)' + .'|70e7a/([^/]++)/([^/]++)/([^/]++)/470e7a(*:49121)' + .'|b(?' + .'|0(?' + .'|4a6/([^/]++)/([^/]++)/([^/]++)/4b04a6(*:49176)' + .'|a59/([^/]++)/([^/]++)/([^/]++)/4b0a59(*:49223)' + .'|250/([^/]++)/([^/]++)/([^/]++)/4b0250(*:49270)' + .')' + .'|6538/([^/]++)/([^/]++)/([^/]++)/4b6538(*:49319)' + .')' + .'|3(?' + .'|f(?' + .'|a7f/([^/]++)/([^/]++)/([^/]++)/43fa7f(*:49375)' + .'|eae/([^/]++)/([^/]++)/([^/]++)/43feae(*:49422)' + .')' + .'|0c36/([^/]++)/([^/]++)/([^/]++)/430c36(*:49471)' + .'|7d7d/([^/]++)/([^/]++)/([^/]++)/437d7d(*:49519)' + .'|1135/([^/]++)/([^/]++)/([^/]++)/431135(*:49567)' + .')' + .'|d(?' + .'|5b99/([^/]++)/([^/]++)/([^/]++)/4d5b99(*:49620)' + .'|aa3d/([^/]++)/([^/]++)/([^/]++)/4daa3d(*:49668)' + .')' + .'|9c9ad/([^/]++)/([^/]++)/([^/]++)/49c9ad(*:49718)' + .')' + .')/?$}sD', + ]; + $this->dynamicRoutes = [ + 54 => [[['_route' => '_0'], ['a', 'b', 'c'], null, null, false, false, null]], + 102 => [[['_route' => '_190'], ['a', 'b', 'c'], null, null, false, false, null]], + 147 => [[['_route' => '_478'], ['a', 'b', 'c'], null, null, false, false, null]], + 194 => [[['_route' => '_259'], ['a', 'b', 'c'], null, null, false, false, null]], + 240 => [[['_route' => '_368'], ['a', 'b', 'c'], null, null, false, false, null]], + 291 => [[['_route' => '_1'], ['a', 'b', 'c'], null, null, false, false, null]], + 337 => [[['_route' => '_116'], ['a', 'b', 'c'], null, null, false, false, null]], + 383 => [[['_route' => '_490'], ['a', 'b', 'c'], null, null, false, false, null]], + 434 => [[['_route' => '_2'], ['a', 'b', 'c'], null, null, false, false, null]], + 480 => [[['_route' => '_124'], ['a', 'b', 'c'], null, null, false, false, null]], + 526 => [[['_route' => '_389'], ['a', 'b', 'c'], null, null, false, false, null]], + 577 => [[['_route' => '_8'], ['a', 'b', 'c'], null, null, false, false, null]], + 623 => [[['_route' => '_104'], ['a', 'b', 'c'], null, null, false, false, null]], + 677 => [[['_route' => '_12'], ['a', 'b', 'c'], null, null, false, false, null]], + 722 => [[['_route' => '_442'], ['a', 'b', 'c'], null, null, false, false, null]], + 769 => [[['_route' => '_253'], ['a', 'b', 'c'], null, null, false, false, null]], + 820 => [[['_route' => '_13'], ['a', 'b', 'c'], null, null, false, false, null]], + 866 => [[['_route' => '_254'], ['a', 'b', 'c'], null, null, false, false, null]], + 912 => [[['_route' => '_347'], ['a', 'b', 'c'], null, null, false, false, null]], + 963 => [[['_route' => '_16'], ['a', 'b', 'c'], null, null, false, false, null]], + 1009 => [[['_route' => '_87'], ['a', 'b', 'c'], null, null, false, false, null]], + 1058 => [[['_route' => '_31'], ['a', 'b', 'c'], null, null, false, false, null]], + 1109 => [[['_route' => '_50'], ['a', 'b', 'c'], null, null, false, false, null]], + 1156 => [[['_route' => '_219'], ['a', 'b', 'c'], null, null, false, false, null]], + 1203 => [[['_route' => '_332'], ['a', 'b', 'c'], null, null, false, false, null]], + 1250 => [[['_route' => '_359'], ['a', 'b', 'c'], null, null, false, false, null]], + 1302 => [[['_route' => '_183'], ['a', 'b', 'c'], null, null, false, false, null]], + 1349 => [[['_route' => '_500'], ['a', 'b', 'c'], null, null, false, false, null]], + 1401 => [[['_route' => '_214'], ['a', 'b', 'c'], null, null, false, false, null]], + 1448 => [[['_route' => '_321'], ['a', 'b', 'c'], null, null, false, false, null]], + 1497 => [[['_route' => '_243'], ['a', 'b', 'c'], null, null, false, false, null]], + 1545 => [[['_route' => '_328'], ['a', 'b', 'c'], null, null, false, false, null]], + 1596 => [[['_route' => '_362'], ['a', 'b', 'c'], null, null, false, false, null]], + 1643 => [[['_route' => '_488'], ['a', 'b', 'c'], null, null, false, false, null]], + 1701 => [[['_route' => '_3'], ['a', 'b', 'c'], null, null, false, false, null]], + 1751 => [[['_route' => '_102'], ['a', 'b', 'c'], null, null, false, false, null]], + 1797 => [[['_route' => '_220'], ['a', 'b', 'c'], null, null, false, false, null]], + 1845 => [[['_route' => '_127'], ['a', 'b', 'c'], null, null, false, false, null]], + 1897 => [[['_route' => '_5'], ['a', 'b', 'c'], null, null, false, false, null]], + 1944 => [[['_route' => '_242'], ['a', 'b', 'c'], null, null, false, false, null]], + 1991 => [[['_route' => '_397'], ['a', 'b', 'c'], null, null, false, false, null]], + 2038 => [[['_route' => '_454'], ['a', 'b', 'c'], null, null, false, false, null]], + 2090 => [[['_route' => '_34'], ['a', 'b', 'c'], null, null, false, false, null]], + 2137 => [[['_route' => '_281'], ['a', 'b', 'c'], null, null, false, false, null]], + 2189 => [[['_route' => '_64'], ['a', 'b', 'c'], null, null, false, false, null]], + 2236 => [[['_route' => '_205'], ['a', 'b', 'c'], null, null, false, false, null]], + 2291 => [[['_route' => '_71'], ['a', 'b', 'c'], null, null, false, false, null]], + 2337 => [[['_route' => '_203'], ['a', 'b', 'c'], null, null, false, false, null]], + 2385 => [[['_route' => '_97'], ['a', 'b', 'c'], null, null, false, false, null]], + 2437 => [[['_route' => '_98'], ['a', 'b', 'c'], null, null, false, false, null]], + 2484 => [[['_route' => '_267'], ['a', 'b', 'c'], null, null, false, false, null]], + 2531 => [[['_route' => '_309'], ['a', 'b', 'c'], null, null, false, false, null]], + 2586 => [[['_route' => '_117'], ['a', 'b', 'c'], null, null, false, false, null]], + 2631 => [[['_route' => '_211'], ['a', 'b', 'c'], null, null, false, false, null]], + 2679 => [[['_route' => '_484'], ['a', 'b', 'c'], null, null, false, false, null]], + 2731 => [[['_route' => '_139'], ['a', 'b', 'c'], null, null, false, false, null]], + 2778 => [[['_route' => '_421'], ['a', 'b', 'c'], null, null, false, false, null]], + 2830 => [[['_route' => '_185'], ['a', 'b', 'c'], null, null, false, false, null]], + 2877 => [[['_route' => '_439'], ['a', 'b', 'c'], null, null, false, false, null]], + 2926 => [[['_route' => '_218'], ['a', 'b', 'c'], null, null, false, false, null]], + 2977 => [[['_route' => '_233'], ['a', 'b', 'c'], null, null, false, false, null]], + 3024 => [[['_route' => '_483'], ['a', 'b', 'c'], null, null, false, false, null]], + 3073 => [[['_route' => '_265'], ['a', 'b', 'c'], null, null, false, false, null]], + 3124 => [[['_route' => '_299'], ['a', 'b', 'c'], null, null, false, false, null]], + 3171 => [[['_route' => '_351'], ['a', 'b', 'c'], null, null, false, false, null]], + 3218 => [[['_route' => '_472'], ['a', 'b', 'c'], null, null, false, false, null]], + 3267 => [[['_route' => '_360'], ['a', 'b', 'c'], null, null, false, false, null]], + 3315 => [[['_route' => '_466'], ['a', 'b', 'c'], null, null, false, false, null]], + 3372 => [[['_route' => '_4'], ['a', 'b', 'c'], null, null, false, false, null]], + 3419 => [[['_route' => '_142'], ['a', 'b', 'c'], null, null, false, false, null]], + 3466 => [[['_route' => '_151'], ['a', 'b', 'c'], null, null, false, false, null]], + 3513 => [[['_route' => '_308'], ['a', 'b', 'c'], null, null, false, false, null]], + 3560 => [[['_route' => '_440'], ['a', 'b', 'c'], null, null, false, false, null]], + 3612 => [[['_route' => '_14'], ['a', 'b', 'c'], null, null, false, false, null]], + 3659 => [[['_route' => '_358'], ['a', 'b', 'c'], null, null, false, false, null]], + 3711 => [[['_route' => '_37'], ['a', 'b', 'c'], null, null, false, false, null]], + 3758 => [[['_route' => '_38'], ['a', 'b', 'c'], null, null, false, false, null]], + 3805 => [[['_route' => '_146'], ['a', 'b', 'c'], null, null, false, false, null]], + 3852 => [[['_route' => '_194'], ['a', 'b', 'c'], null, null, false, false, null]], + 3899 => [[['_route' => '_487'], ['a', 'b', 'c'], null, null, false, false, null]], + 3948 => [[['_route' => '_42'], ['a', 'b', 'c'], null, null, false, false, null]], + 3999 => [[['_route' => '_54'], ['a', 'b', 'c'], null, null, false, false, null]], + 4046 => [[['_route' => '_326'], ['a', 'b', 'c'], null, null, false, false, null]], + 4098 => [[['_route' => '_68'], ['a', 'b', 'c'], null, null, false, false, null]], + 4145 => [[['_route' => '_108'], ['a', 'b', 'c'], null, null, false, false, null]], + 4197 => [[['_route' => '_74'], ['a', 'b', 'c'], null, null, false, false, null]], + 4244 => [[['_route' => '_315'], ['a', 'b', 'c'], null, null, false, false, null]], + 4291 => [[['_route' => '_374'], ['a', 'b', 'c'], null, null, false, false, null]], + 4343 => [[['_route' => '_99'], ['a', 'b', 'c'], null, null, false, false, null]], + 4390 => [[['_route' => '_238'], ['a', 'b', 'c'], null, null, false, false, null]], + 4442 => [[['_route' => '_107'], ['a', 'b', 'c'], null, null, false, false, null]], + 4489 => [[['_route' => '_409'], ['a', 'b', 'c'], null, null, false, false, null]], + 4541 => [[['_route' => '_122'], ['a', 'b', 'c'], null, null, false, false, null]], + 4588 => [[['_route' => '_379'], ['a', 'b', 'c'], null, null, false, false, null]], + 4635 => [[['_route' => '_390'], ['a', 'b', 'c'], null, null, false, false, null]], + 4687 => [[['_route' => '_171'], ['a', 'b', 'c'], null, null, false, false, null]], + 4734 => [[['_route' => '_260'], ['a', 'b', 'c'], null, null, false, false, null]], + 4781 => [[['_route' => '_434'], ['a', 'b', 'c'], null, null, false, false, null]], + 4830 => [[['_route' => '_189'], ['a', 'b', 'c'], null, null, false, false, null]], + 4878 => [[['_route' => '_467'], ['a', 'b', 'c'], null, null, false, false, null]], + 4935 => [[['_route' => '_6'], ['a', 'b', 'c'], null, null, false, false, null]], + 4982 => [[['_route' => '_286'], ['a', 'b', 'c'], null, null, false, false, null]], + 5029 => [[['_route' => '_438'], ['a', 'b', 'c'], null, null, false, false, null]], + 5081 => [[['_route' => '_19'], ['a', 'b', 'c'], null, null, false, false, null]], + 5131 => [[['_route' => '_24'], ['a', 'b', 'c'], null, null, false, false, null]], + 5177 => [[['_route' => '_172'], ['a', 'b', 'c'], null, null, false, false, null]], + 5230 => [[['_route' => '_33'], ['a', 'b', 'c'], null, null, false, false, null]], + 5277 => [[['_route' => '_400'], ['a', 'b', 'c'], null, null, false, false, null]], + 5324 => [[['_route' => '_427'], ['a', 'b', 'c'], null, null, false, false, null]], + 5376 => [[['_route' => '_35'], ['a', 'b', 'c'], null, null, false, false, null]], + 5423 => [[['_route' => '_156'], ['a', 'b', 'c'], null, null, false, false, null]], + 5475 => [[['_route' => '_36'], ['a', 'b', 'c'], null, null, false, false, null]], + 5522 => [[['_route' => '_251'], ['a', 'b', 'c'], null, null, false, false, null]], + 5574 => [[['_route' => '_43'], ['a', 'b', 'c'], null, null, false, false, null]], + 5621 => [[['_route' => '_292'], ['a', 'b', 'c'], null, null, false, false, null]], + 5668 => [[['_route' => '_411'], ['a', 'b', 'c'], null, null, false, false, null]], + 5720 => [[['_route' => '_69'], ['a', 'b', 'c'], null, null, false, false, null]], + 5767 => [[['_route' => '_159'], ['a', 'b', 'c'], null, null, false, false, null]], + 5814 => [[['_route' => '_170'], ['a', 'b', 'c'], null, null, false, false, null]], + 5861 => [[['_route' => '_376'], ['a', 'b', 'c'], null, null, false, false, null]], + 5913 => [[['_route' => '_131'], ['a', 'b', 'c'], null, null, false, false, null]], + 5960 => [[['_route' => '_446'], ['a', 'b', 'c'], null, null, false, false, null]], + 6015 => [[['_route' => '_140'], ['a', 'b', 'c'], null, null, false, false, null]], + 6061 => [[['_route' => '_353'], ['a', 'b', 'c'], null, null, false, false, null]], + 6112 => [[['_route' => '_224'], ['a', 'b', 'c'], null, null, false, false, null]], + 6158 => [[['_route' => '_346'], ['a', 'b', 'c'], null, null, false, false, null]], + 6204 => [[['_route' => '_443'], ['a', 'b', 'c'], null, null, false, false, null]], + 6254 => [[['_route' => '_154'], ['a', 'b', 'c'], null, null, false, false, null]], + 6305 => [[['_route' => '_212'], ['a', 'b', 'c'], null, null, false, false, null]], + 6352 => [[['_route' => '_313'], ['a', 'b', 'c'], null, null, false, false, null]], + 6399 => [[['_route' => '_395'], ['a', 'b', 'c'], null, null, false, false, null]], + 6446 => [[['_route' => '_441'], ['a', 'b', 'c'], null, null, false, false, null]], + 6498 => [[['_route' => '_223'], ['a', 'b', 'c'], null, null, false, false, null]], + 6545 => [[['_route' => '_303'], ['a', 'b', 'c'], null, null, false, false, null]], + 6594 => [[['_route' => '_410'], ['a', 'b', 'c'], null, null, false, false, null]], + 6642 => [[['_route' => '_494'], ['a', 'b', 'c'], null, null, false, false, null]], + 6702 => [[['_route' => '_7'], ['a', 'b', 'c'], null, null, false, false, null]], + 6748 => [[['_route' => '_268'], ['a', 'b', 'c'], null, null, false, false, null]], + 6796 => [[['_route' => '_178'], ['a', 'b', 'c'], null, null, false, false, null]], + 6843 => [[['_route' => '_179'], ['a', 'b', 'c'], null, null, false, false, null]], + 6890 => [[['_route' => '_416'], ['a', 'b', 'c'], null, null, false, false, null]], + 6942 => [[['_route' => '_25'], ['a', 'b', 'c'], null, null, false, false, null]], + 6989 => [[['_route' => '_307'], ['a', 'b', 'c'], null, null, false, false, null]], + 7036 => [[['_route' => '_387'], ['a', 'b', 'c'], null, null, false, false, null]], + 7083 => [[['_route' => '_471'], ['a', 'b', 'c'], null, null, false, false, null]], + 7132 => [[['_route' => '_90'], ['a', 'b', 'c'], null, null, false, false, null]], + 7183 => [[['_route' => '_95'], ['a', 'b', 'c'], null, null, false, false, null]], + 7230 => [[['_route' => '_338'], ['a', 'b', 'c'], null, null, false, false, null]], + 7277 => [[['_route' => '_401'], ['a', 'b', 'c'], null, null, false, false, null]], + 7329 => [[['_route' => '_147'], ['a', 'b', 'c'], null, null, false, false, null]], + 7376 => [[['_route' => '_319'], ['a', 'b', 'c'], null, null, false, false, null]], + 7423 => [[['_route' => '_354'], ['a', 'b', 'c'], null, null, false, false, null]], + 7470 => [[['_route' => '_428'], ['a', 'b', 'c'], null, null, false, false, null]], + 7522 => [[['_route' => '_162'], ['a', 'b', 'c'], null, null, false, false, null]], + 7572 => [[['_route' => '_175'], ['a', 'b', 'c'], null, null, false, false, null]], + 7618 => [[['_route' => '_455'], ['a', 'b', 'c'], null, null, false, false, null]], + 7666 => [[['_route' => '_355'], ['a', 'b', 'c'], null, null, false, false, null]], + 7718 => [[['_route' => '_197'], ['a', 'b', 'c'], null, null, false, false, null]], + 7768 => [[['_route' => '_202'], ['a', 'b', 'c'], null, null, false, false, null]], + 7813 => [[['_route' => '_489'], ['a', 'b', 'c'], null, null, false, false, null]], + 7863 => [[['_route' => '_199'], ['a', 'b', 'c'], null, null, false, false, null]], + 7914 => [[['_route' => '_263'], ['a', 'b', 'c'], null, null, false, false, null]], + 7961 => [[['_route' => '_406'], ['a', 'b', 'c'], null, null, false, false, null]], + 8010 => [[['_route' => '_289'], ['a', 'b', 'c'], null, null, false, false, null]], + 8058 => [[['_route' => '_325'], ['a', 'b', 'c'], null, null, false, false, null]], + 8106 => [[['_route' => '_378'], ['a', 'b', 'c'], null, null, false, false, null]], + 8154 => [[['_route' => '_468'], ['a', 'b', 'c'], null, null, false, false, null]], + 8211 => [[['_route' => '_9'], ['a', 'b', 'c'], null, null, false, false, null]], + 8258 => [[['_route' => '_216'], ['a', 'b', 'c'], null, null, false, false, null]], + 8307 => [[['_route' => '_26'], ['a', 'b', 'c'], null, null, false, false, null]], + 8355 => [[['_route' => '_62'], ['a', 'b', 'c'], null, null, false, false, null]], + 8406 => [[['_route' => '_81'], ['a', 'b', 'c'], null, null, false, false, null]], + 8453 => [[['_route' => '_318'], ['a', 'b', 'c'], null, null, false, false, null]], + 8505 => [[['_route' => '_121'], ['a', 'b', 'c'], null, null, false, false, null]], + 8551 => [[['_route' => '_182'], ['a', 'b', 'c'], null, null, false, false, null]], + 8603 => [[['_route' => '_136'], ['a', 'b', 'c'], null, null, false, false, null]], + 8650 => [[['_route' => '_415'], ['a', 'b', 'c'], null, null, false, false, null]], + 8697 => [[['_route' => '_457'], ['a', 'b', 'c'], null, null, false, false, null]], + 8744 => [[['_route' => '_463'], ['a', 'b', 'c'], null, null, false, false, null]], + 8796 => [[['_route' => '_148'], ['a', 'b', 'c'], null, null, false, false, null]], + 8843 => [[['_route' => '_273'], ['a', 'b', 'c'], null, null, false, false, null]], + 8892 => [[['_route' => '_284'], ['a', 'b', 'c'], null, null, false, false, null]], + 8940 => [[['_route' => '_288'], ['a', 'b', 'c'], null, null, false, false, null]], + 8991 => [[['_route' => '_295'], ['a', 'b', 'c'], null, null, false, false, null]], + 9038 => [[['_route' => '_305'], ['a', 'b', 'c'], null, null, false, false, null]], + 9085 => [[['_route' => '_453'], ['a', 'b', 'c'], null, null, false, false, null]], + 9134 => [[['_route' => '_340'], ['a', 'b', 'c'], null, null, false, false, null]], + 9185 => [[['_route' => '_371'], ['a', 'b', 'c'], null, null, false, false, null]], + 9232 => [[['_route' => '_417'], ['a', 'b', 'c'], null, null, false, false, null]], + 9284 => [[['_route' => '_382'], ['a', 'b', 'c'], null, null, false, false, null]], + 9331 => [[['_route' => '_404'], ['a', 'b', 'c'], null, null, false, false, null]], + 9389 => [[['_route' => '_10'], ['a', 'b', 'c'], null, null, false, false, null]], + 9436 => [[['_route' => '_279'], ['a', 'b', 'c'], null, null, false, false, null]], + 9483 => [[['_route' => '_377'], ['a', 'b', 'c'], null, null, false, false, null]], + 9535 => [[['_route' => '_39'], ['a', 'b', 'c'], null, null, false, false, null]], + 9582 => [[['_route' => '_40'], ['a', 'b', 'c'], null, null, false, false, null]], + 9629 => [[['_route' => '_264'], ['a', 'b', 'c'], null, null, false, false, null]], + 9676 => [[['_route' => '_449'], ['a', 'b', 'c'], null, null, false, false, null]], + 9728 => [[['_route' => '_46'], ['a', 'b', 'c'], null, null, false, false, null]], + 9775 => [[['_route' => '_257'], ['a', 'b', 'c'], null, null, false, false, null]], + 9822 => [[['_route' => '_274'], ['a', 'b', 'c'], null, null, false, false, null]], + 9869 => [[['_route' => '_388'], ['a', 'b', 'c'], null, null, false, false, null]], + 9921 => [[['_route' => '_53'], ['a', 'b', 'c'], null, null, false, false, null]], + 9968 => [[['_route' => '_345'], ['a', 'b', 'c'], null, null, false, false, null]], + 10020 => [[['_route' => '_73'], ['a', 'b', 'c'], null, null, false, false, null]], + 10068 => [[['_route' => '_296'], ['a', 'b', 'c'], null, null, false, false, null]], + 10121 => [[['_route' => '_75'], ['a', 'b', 'c'], null, null, false, false, null]], + 10169 => [[['_route' => '_458'], ['a', 'b', 'c'], null, null, false, false, null]], + 10225 => [[['_route' => '_79'], ['a', 'b', 'c'], null, null, false, false, null]], + 10272 => [[['_route' => '_129'], ['a', 'b', 'c'], null, null, false, false, null]], + 10319 => [[['_route' => '_418'], ['a', 'b', 'c'], null, null, false, false, null]], + 10368 => [[['_route' => '_225'], ['a', 'b', 'c'], null, null, false, false, null]], + 10416 => [[['_route' => '_479'], ['a', 'b', 'c'], null, null, false, false, null]], + 10466 => [[['_route' => '_120'], ['a', 'b', 'c'], null, null, false, false, null]], + 10515 => [[['_route' => '_276'], ['a', 'b', 'c'], null, null, false, false, null]], + 10564 => [[['_route' => '_370'], ['a', 'b', 'c'], null, null, false, false, null]], + 10616 => [[['_route' => '_385'], ['a', 'b', 'c'], null, null, false, false, null]], + 10664 => [[['_route' => '_469'], ['a', 'b', 'c'], null, null, false, false, null]], + 10714 => [[['_route' => '_435'], ['a', 'b', 'c'], null, null, false, false, null]], + 10772 => [[['_route' => '_11'], ['a', 'b', 'c'], null, null, false, false, null]], + 10820 => [[['_route' => '_105'], ['a', 'b', 'c'], null, null, false, false, null]], + 10868 => [[['_route' => '_132'], ['a', 'b', 'c'], null, null, false, false, null]], + 10921 => [[['_route' => '_18'], ['a', 'b', 'c'], null, null, false, false, null]], + 10969 => [[['_route' => '_210'], ['a', 'b', 'c'], null, null, false, false, null]], + 11017 => [[['_route' => '_329'], ['a', 'b', 'c'], null, null, false, false, null]], + 11073 => [[['_route' => '_29'], ['a', 'b', 'c'], null, null, false, false, null]], + 11120 => [[['_route' => '_480'], ['a', 'b', 'c'], null, null, false, false, null]], + 11169 => [[['_route' => '_426'], ['a', 'b', 'c'], null, null, false, false, null]], + 11222 => [[['_route' => '_32'], ['a', 'b', 'c'], null, null, false, false, null]], + 11270 => [[['_route' => '_217'], ['a', 'b', 'c'], null, null, false, false, null]], + 11318 => [[['_route' => '_275'], ['a', 'b', 'c'], null, null, false, false, null]], + 11371 => [[['_route' => '_45'], ['a', 'b', 'c'], null, null, false, false, null]], + 11419 => [[['_route' => '_157'], ['a', 'b', 'c'], null, null, false, false, null]], + 11467 => [[['_route' => '_184'], ['a', 'b', 'c'], null, null, false, false, null]], + 11515 => [[['_route' => '_250'], ['a', 'b', 'c'], null, null, false, false, null]], + 11563 => [[['_route' => '_356'], ['a', 'b', 'c'], null, null, false, false, null]], + 11616 => [[['_route' => '_47'], ['a', 'b', 'c'], null, null, false, false, null]], + 11664 => [[['_route' => '_445'], ['a', 'b', 'c'], null, null, false, false, null]], + 11714 => [[['_route' => '_48'], ['a', 'b', 'c'], null, null, false, false, null]], + 11766 => [[['_route' => '_58'], ['a', 'b', 'c'], null, null, false, false, null]], + 11814 => [[['_route' => '_414'], ['a', 'b', 'c'], null, null, false, false, null]], + 11862 => [[['_route' => '_431'], ['a', 'b', 'c'], null, null, false, false, null]], + 11915 => [[['_route' => '_84'], ['a', 'b', 'c'], null, null, false, false, null]], + 11963 => [[['_route' => '_294'], ['a', 'b', 'c'], null, null, false, false, null]], + 12011 => [[['_route' => '_336'], ['a', 'b', 'c'], null, null, false, false, null]], + 12059 => [[['_route' => '_465'], ['a', 'b', 'c'], null, null, false, false, null]], + 12112 => [[['_route' => '_103'], ['a', 'b', 'c'], null, null, false, false, null]], + 12160 => [[['_route' => '_111'], ['a', 'b', 'c'], null, null, false, false, null]], + 12208 => [[['_route' => '_207'], ['a', 'b', 'c'], null, null, false, false, null]], + 12256 => [[['_route' => '_402'], ['a', 'b', 'c'], null, null, false, false, null]], + 12309 => [[['_route' => '_230'], ['a', 'b', 'c'], null, null, false, false, null]], + 12356 => [[['_route' => '_331'], ['a', 'b', 'c'], null, null, false, false, null]], + 12406 => [[['_route' => '_248'], ['a', 'b', 'c'], null, null, false, false, null]], + 12455 => [[['_route' => '_282'], ['a', 'b', 'c'], null, null, false, false, null]], + 12513 => [[['_route' => '_15'], ['a', 'b', 'c'], null, null, false, false, null]], + 12561 => [[['_route' => '_130'], ['a', 'b', 'c'], null, null, false, false, null]], + 12609 => [[['_route' => '_231'], ['a', 'b', 'c'], null, null, false, false, null]], + 12657 => [[['_route' => '_365'], ['a', 'b', 'c'], null, null, false, false, null]], + 12705 => [[['_route' => '_448'], ['a', 'b', 'c'], null, null, false, false, null]], + 12758 => [[['_route' => '_20'], ['a', 'b', 'c'], null, null, false, false, null]], + 12806 => [[['_route' => '_93'], ['a', 'b', 'c'], null, null, false, false, null]], + 12854 => [[['_route' => '_186'], ['a', 'b', 'c'], null, null, false, false, null]], + 12902 => [[['_route' => '_460'], ['a', 'b', 'c'], null, null, false, false, null]], + 12955 => [[['_route' => '_52'], ['a', 'b', 'c'], null, null, false, false, null]], + 13003 => [[['_route' => '_447'], ['a', 'b', 'c'], null, null, false, false, null]], + 13056 => [[['_route' => '_56'], ['a', 'b', 'c'], null, null, false, false, null]], + 13104 => [[['_route' => '_133'], ['a', 'b', 'c'], null, null, false, false, null]], + 13152 => [[['_route' => '_297'], ['a', 'b', 'c'], null, null, false, false, null]], + 13205 => [[['_route' => '_82'], ['a', 'b', 'c'], null, null, false, false, null]], + 13253 => [[['_route' => '_165'], ['a', 'b', 'c'], null, null, false, false, null]], + 13301 => [[['_route' => '_213'], ['a', 'b', 'c'], null, null, false, false, null]], + 13351 => [[['_route' => '_86'], ['a', 'b', 'c'], null, null, false, false, null]], + 13403 => [[['_route' => '_92'], ['a', 'b', 'c'], null, null, false, false, null]], + 13450 => [[['_route' => '_280'], ['a', 'b', 'c'], null, null, false, false, null]], + 13500 => [[['_route' => '_143'], ['a', 'b', 'c'], null, null, false, false, null]], + 13549 => [[['_route' => '_177'], ['a', 'b', 'c'], null, null, false, false, null]], + 13601 => [[['_route' => '_188'], ['a', 'b', 'c'], null, null, false, false, null]], + 13649 => [[['_route' => '_311'], ['a', 'b', 'c'], null, null, false, false, null]], + 13697 => [[['_route' => '_350'], ['a', 'b', 'c'], null, null, false, false, null]], + 13750 => [[['_route' => '_226'], ['a', 'b', 'c'], null, null, false, false, null]], + 13798 => [[['_route' => '_291'], ['a', 'b', 'c'], null, null, false, false, null]], + 13851 => [[['_route' => '_244'], ['a', 'b', 'c'], null, null, false, false, null]], + 13898 => [[['_route' => '_287'], ['a', 'b', 'c'], null, null, false, false, null]], + 13951 => [[['_route' => '_300'], ['a', 'b', 'c'], null, null, false, false, null]], + 13999 => [[['_route' => '_451'], ['a', 'b', 'c'], null, null, false, false, null]], + 14047 => [[['_route' => '_452'], ['a', 'b', 'c'], null, null, false, false, null]], + 14095 => [[['_route' => '_481'], ['a', 'b', 'c'], null, null, false, false, null]], + 14145 => [[['_route' => '_312'], ['a', 'b', 'c'], null, null, false, false, null]], + 14203 => [[['_route' => '_17'], ['a', 'b', 'c'], null, null, false, false, null]], + 14251 => [[['_route' => '_227'], ['a', 'b', 'c'], null, null, false, false, null]], + 14299 => [[['_route' => '_393'], ['a', 'b', 'c'], null, null, false, false, null]], + 14349 => [[['_route' => '_57'], ['a', 'b', 'c'], null, null, false, false, null]], + 14401 => [[['_route' => '_61'], ['a', 'b', 'c'], null, null, false, false, null]], + 14449 => [[['_route' => '_112'], ['a', 'b', 'c'], null, null, false, false, null]], + 14500 => [[['_route' => '_135'], ['a', 'b', 'c'], null, null, false, false, null]], + 14547 => [[['_route' => '_271'], ['a', 'b', 'c'], null, null, false, false, null]], + 14596 => [[['_route' => '_459'], ['a', 'b', 'c'], null, null, false, false, null]], + 14649 => [[['_route' => '_67'], ['a', 'b', 'c'], null, null, false, false, null]], + 14697 => [[['_route' => '_113'], ['a', 'b', 'c'], null, null, false, false, null]], + 14745 => [[['_route' => '_497'], ['a', 'b', 'c'], null, null, false, false, null]], + 14795 => [[['_route' => '_70'], ['a', 'b', 'c'], null, null, false, false, null]], + 14847 => [[['_route' => '_89'], ['a', 'b', 'c'], null, null, false, false, null]], + 14895 => [[['_route' => '_128'], ['a', 'b', 'c'], null, null, false, false, null]], + 14948 => [[['_route' => '_150'], ['a', 'b', 'c'], null, null, false, false, null]], + 14996 => [[['_route' => '_166'], ['a', 'b', 'c'], null, null, false, false, null]], + 15047 => [[['_route' => '_206'], ['a', 'b', 'c'], null, null, false, false, null]], + 15094 => [[['_route' => '_419'], ['a', 'b', 'c'], null, null, false, false, null]], + 15148 => [[['_route' => '_201'], ['a', 'b', 'c'], null, null, false, false, null]], + 15196 => [[['_route' => '_314'], ['a', 'b', 'c'], null, null, false, false, null]], + 15244 => [[['_route' => '_429'], ['a', 'b', 'c'], null, null, false, false, null]], + 15297 => [[['_route' => '_228'], ['a', 'b', 'c'], null, null, false, false, null]], + 15345 => [[['_route' => '_477'], ['a', 'b', 'c'], null, null, false, false, null]], + 15395 => [[['_route' => '_272'], ['a', 'b', 'c'], null, null, false, false, null]], + 15444 => [[['_route' => '_486'], ['a', 'b', 'c'], null, null, false, false, null]], + 15502 => [[['_route' => '_21'], ['a', 'b', 'c'], null, null, false, false, null]], + 15550 => [[['_route' => '_247'], ['a', 'b', 'c'], null, null, false, false, null]], + 15598 => [[['_route' => '_424'], ['a', 'b', 'c'], null, null, false, false, null]], + 15646 => [[['_route' => '_499'], ['a', 'b', 'c'], null, null, false, false, null]], + 15699 => [[['_route' => '_23'], ['a', 'b', 'c'], null, null, false, false, null]], + 15747 => [[['_route' => '_152'], ['a', 'b', 'c'], null, null, false, false, null]], + 15795 => [[['_route' => '_304'], ['a', 'b', 'c'], null, null, false, false, null]], + 15843 => [[['_route' => '_352'], ['a', 'b', 'c'], null, null, false, false, null]], + 15896 => [[['_route' => '_28'], ['a', 'b', 'c'], null, null, false, false, null]], + 15944 => [[['_route' => '_240'], ['a', 'b', 'c'], null, null, false, false, null]], + 16000 => [[['_route' => '_30'], ['a', 'b', 'c'], null, null, false, false, null]], + 16047 => [[['_route' => '_41'], ['a', 'b', 'c'], null, null, false, false, null]], + 16096 => [[['_route' => '_301'], ['a', 'b', 'c'], null, null, false, false, null]], + 16149 => [[['_route' => '_66'], ['a', 'b', 'c'], null, null, false, false, null]], + 16197 => [[['_route' => '_72'], ['a', 'b', 'c'], null, null, false, false, null]], + 16245 => [[['_route' => '_320'], ['a', 'b', 'c'], null, null, false, false, null]], + 16298 => [[['_route' => '_78'], ['a', 'b', 'c'], null, null, false, false, null]], + 16346 => [[['_route' => '_337'], ['a', 'b', 'c'], null, null, false, false, null]], + 16394 => [[['_route' => '_399'], ['a', 'b', 'c'], null, null, false, false, null]], + 16442 => [[['_route' => '_495'], ['a', 'b', 'c'], null, null, false, false, null]], + 16492 => [[['_route' => '_85'], ['a', 'b', 'c'], null, null, false, false, null]], + 16544 => [[['_route' => '_101'], ['a', 'b', 'c'], null, null, false, false, null]], + 16592 => [[['_route' => '_176'], ['a', 'b', 'c'], null, null, false, false, null]], + 16640 => [[['_route' => '_246'], ['a', 'b', 'c'], null, null, false, false, null]], + 16693 => [[['_route' => '_125'], ['a', 'b', 'c'], null, null, false, false, null]], + 16741 => [[['_route' => '_341'], ['a', 'b', 'c'], null, null, false, false, null]], + 16794 => [[['_route' => '_137'], ['a', 'b', 'c'], null, null, false, false, null]], + 16842 => [[['_route' => '_270'], ['a', 'b', 'c'], null, null, false, false, null]], + 16890 => [[['_route' => '_386'], ['a', 'b', 'c'], null, null, false, false, null]], + 16943 => [[['_route' => '_169'], ['a', 'b', 'c'], null, null, false, false, null]], + 16991 => [[['_route' => '_200'], ['a', 'b', 'c'], null, null, false, false, null]], + 17039 => [[['_route' => '_262'], ['a', 'b', 'c'], null, null, false, false, null]], + 17092 => [[['_route' => '_187'], ['a', 'b', 'c'], null, null, false, false, null]], + 17140 => [[['_route' => '_333'], ['a', 'b', 'c'], null, null, false, false, null]], + 17190 => [[['_route' => '_215'], ['a', 'b', 'c'], null, null, false, false, null]], + 17239 => [[['_route' => '_316'], ['a', 'b', 'c'], null, null, false, false, null]], + 17288 => [[['_route' => '_343'], ['a', 'b', 'c'], null, null, false, false, null]], + 17346 => [[['_route' => '_22'], ['a', 'b', 'c'], null, null, false, false, null]], + 17394 => [[['_route' => '_420'], ['a', 'b', 'c'], null, null, false, false, null]], + 17447 => [[['_route' => '_55'], ['a', 'b', 'c'], null, null, false, false, null]], + 17494 => [[['_route' => '_496'], ['a', 'b', 'c'], null, null, false, false, null]], + 17547 => [[['_route' => '_153'], ['a', 'b', 'c'], null, null, false, false, null]], + 17595 => [[['_route' => '_344'], ['a', 'b', 'c'], null, null, false, false, null]], + 17648 => [[['_route' => '_160'], ['a', 'b', 'c'], null, null, false, false, null]], + 17696 => [[['_route' => '_398'], ['a', 'b', 'c'], null, null, false, false, null]], + 17749 => [[['_route' => '_161'], ['a', 'b', 'c'], null, null, false, false, null]], + 17797 => [[['_route' => '_193'], ['a', 'b', 'c'], null, null, false, false, null]], + 17847 => [[['_route' => '_174'], ['a', 'b', 'c'], null, null, false, false, null]], + 17899 => [[['_route' => '_209'], ['a', 'b', 'c'], null, null, false, false, null]], + 17947 => [[['_route' => '_261'], ['a', 'b', 'c'], null, null, false, false, null]], + 18000 => [[['_route' => '_222'], ['a', 'b', 'c'], null, null, false, false, null]], + 18048 => [[['_route' => '_323'], ['a', 'b', 'c'], null, null, false, false, null]], + 18096 => [[['_route' => '_380'], ['a', 'b', 'c'], null, null, false, false, null]], + 18149 => [[['_route' => '_232'], ['a', 'b', 'c'], null, null, false, false, null]], + 18197 => [[['_route' => '_383'], ['a', 'b', 'c'], null, null, false, false, null]], + 18247 => [[['_route' => '_306'], ['a', 'b', 'c'], null, null, false, false, null]], + 18296 => [[['_route' => '_327'], ['a', 'b', 'c'], null, null, false, false, null]], + 18345 => [[['_route' => '_364'], ['a', 'b', 'c'], null, null, false, false, null]], + 18397 => [[['_route' => '_403'], ['a', 'b', 'c'], null, null, false, false, null]], + 18445 => [[['_route' => '_405'], ['a', 'b', 'c'], null, null, false, false, null]], + 18495 => [[['_route' => '_412'], ['a', 'b', 'c'], null, null, false, false, null]], + 18553 => [[['_route' => '_27'], ['a', 'b', 'c'], null, null, false, false, null]], + 18601 => [[['_route' => '_134'], ['a', 'b', 'c'], null, null, false, false, null]], + 18649 => [[['_route' => '_245'], ['a', 'b', 'c'], null, null, false, false, null]], + 18702 => [[['_route' => '_59'], ['a', 'b', 'c'], null, null, false, false, null]], + 18750 => [[['_route' => '_208'], ['a', 'b', 'c'], null, null, false, false, null]], + 18803 => [[['_route' => '_60'], ['a', 'b', 'c'], null, null, false, false, null]], + 18851 => [[['_route' => '_119'], ['a', 'b', 'c'], null, null, false, false, null]], + 18902 => [[['_route' => '_163'], ['a', 'b', 'c'], null, null, false, false, null]], + 18949 => [[['_route' => '_249'], ['a', 'b', 'c'], null, null, false, false, null]], + 18998 => [[['_route' => '_278'], ['a', 'b', 'c'], null, null, false, false, null]], + 19051 => [[['_route' => '_63'], ['a', 'b', 'c'], null, null, false, false, null]], + 19099 => [[['_route' => '_195'], ['a', 'b', 'c'], null, null, false, false, null]], + 19147 => [[['_route' => '_252'], ['a', 'b', 'c'], null, null, false, false, null]], + 19195 => [[['_route' => '_461'], ['a', 'b', 'c'], null, null, false, false, null]], + 19248 => [[['_route' => '_126'], ['a', 'b', 'c'], null, null, false, false, null]], + 19296 => [[['_route' => '_158'], ['a', 'b', 'c'], null, null, false, false, null]], + 19344 => [[['_route' => '_221'], ['a', 'b', 'c'], null, null, false, false, null]], + 19392 => [[['_route' => '_269'], ['a', 'b', 'c'], null, null, false, false, null]], + 19440 => [[['_route' => '_310'], ['a', 'b', 'c'], null, null, false, false, null]], + 19496 => [[['_route' => '_138'], ['a', 'b', 'c'], null, null, false, false, null]], + 19543 => [[['_route' => '_348'], ['a', 'b', 'c'], null, null, false, false, null]], + 19592 => [[['_route' => '_236'], ['a', 'b', 'c'], null, null, false, false, null]], + 19640 => [[['_route' => '_433'], ['a', 'b', 'c'], null, null, false, false, null]], + 19693 => [[['_route' => '_141'], ['a', 'b', 'c'], null, null, false, false, null]], + 19741 => [[['_route' => '_283'], ['a', 'b', 'c'], null, null, false, false, null]], + 19794 => [[['_route' => '_144'], ['a', 'b', 'c'], null, null, false, false, null]], + 19842 => [[['_route' => '_191'], ['a', 'b', 'c'], null, null, false, false, null]], + 19895 => [[['_route' => '_168'], ['a', 'b', 'c'], null, null, false, false, null]], + 19943 => [[['_route' => '_363'], ['a', 'b', 'c'], null, null, false, false, null]], + 19991 => [[['_route' => '_381'], ['a', 'b', 'c'], null, null, false, false, null]], + 20044 => [[['_route' => '_180'], ['a', 'b', 'c'], null, null, false, false, null]], + 20092 => [[['_route' => '_339'], ['a', 'b', 'c'], null, null, false, false, null]], + 20142 => [[['_route' => '_196'], ['a', 'b', 'c'], null, null, false, false, null]], + 20194 => [[['_route' => '_198'], ['a', 'b', 'c'], null, null, false, false, null]], + 20242 => [[['_route' => '_285'], ['a', 'b', 'c'], null, null, false, false, null]], + 20292 => [[['_route' => '_349'], ['a', 'b', 'c'], null, null, false, false, null]], + 20344 => [[['_route' => '_367'], ['a', 'b', 'c'], null, null, false, false, null]], + 20392 => [[['_route' => '_384'], ['a', 'b', 'c'], null, null, false, false, null]], + 20440 => [[['_route' => '_498'], ['a', 'b', 'c'], null, null, false, false, null]], + 20490 => [[['_route' => '_369'], ['a', 'b', 'c'], null, null, false, false, null]], + 20542 => [[['_route' => '_408'], ['a', 'b', 'c'], null, null, false, false, null]], + 20590 => [[['_route' => '_413'], ['a', 'b', 'c'], null, null, false, false, null]], + 20652 => [[['_route' => '_44'], ['a', 'b', 'c'], null, null, false, false, null]], + 20699 => [[['_route' => '_256'], ['a', 'b', 'c'], null, null, false, false, null]], + 20748 => [[['_route' => '_173'], ['a', 'b', 'c'], null, null, false, false, null]], + 20796 => [[['_route' => '_266'], ['a', 'b', 'c'], null, null, false, false, null]], + 20844 => [[['_route' => '_392'], ['a', 'b', 'c'], null, null, false, false, null]], + 20892 => [[['_route' => '_430'], ['a', 'b', 'c'], null, null, false, false, null]], + 20940 => [[['_route' => '_482'], ['a', 'b', 'c'], null, null, false, false, null]], + 20993 => [[['_route' => '_49'], ['a', 'b', 'c'], null, null, false, false, null]], + 21041 => [[['_route' => '_94'], ['a', 'b', 'c'], null, null, false, false, null]], + 21089 => [[['_route' => '_407'], ['a', 'b', 'c'], null, null, false, false, null]], + 21142 => [[['_route' => '_65'], ['a', 'b', 'c'], null, null, false, false, null]], + 21190 => [[['_route' => '_181'], ['a', 'b', 'c'], null, null, false, false, null]], + 21238 => [[['_route' => '_437'], ['a', 'b', 'c'], null, null, false, false, null]], + 21291 => [[['_route' => '_76'], ['a', 'b', 'c'], null, null, false, false, null]], + 21339 => [[['_route' => '_357'], ['a', 'b', 'c'], null, null, false, false, null]], + 21392 => [[['_route' => '_80'], ['a', 'b', 'c'], null, null, false, false, null]], + 21440 => [[['_route' => '_106'], ['a', 'b', 'c'], null, null, false, false, null]], + 21493 => [[['_route' => '_83'], ['a', 'b', 'c'], null, null, false, false, null]], + 21541 => [[['_route' => '_255'], ['a', 'b', 'c'], null, null, false, false, null]], + 21589 => [[['_route' => '_330'], ['a', 'b', 'c'], null, null, false, false, null]], + 21642 => [[['_route' => '_100'], ['a', 'b', 'c'], null, null, false, false, null]], + 21690 => [[['_route' => '_396'], ['a', 'b', 'c'], null, null, false, false, null]], + 21738 => [[['_route' => '_422'], ['a', 'b', 'c'], null, null, false, false, null]], + 21791 => [[['_route' => '_149'], ['a', 'b', 'c'], null, null, false, false, null]], + 21839 => [[['_route' => '_324'], ['a', 'b', 'c'], null, null, false, false, null]], + 21892 => [[['_route' => '_164'], ['a', 'b', 'c'], null, null, false, false, null]], + 21940 => [[['_route' => '_423'], ['a', 'b', 'c'], null, null, false, false, null]], + 21990 => [[['_route' => '_241'], ['a', 'b', 'c'], null, null, false, false, null]], + 22042 => [[['_route' => '_290'], ['a', 'b', 'c'], null, null, false, false, null]], + 22090 => [[['_route' => '_335'], ['a', 'b', 'c'], null, null, false, false, null]], + 22140 => [[['_route' => '_373'], ['a', 'b', 'c'], null, null, false, false, null]], + 22189 => [[['_route' => '_375'], ['a', 'b', 'c'], null, null, false, false, null]], + 22238 => [[['_route' => '_450'], ['a', 'b', 'c'], null, null, false, false, null]], + 22287 => [[['_route' => '_464'], ['a', 'b', 'c'], null, null, false, false, null]], + 22345 => [[['_route' => '_51'], ['a', 'b', 'c'], null, null, false, false, null]], + 22393 => [[['_route' => '_77'], ['a', 'b', 'c'], null, null, false, false, null]], + 22441 => [[['_route' => '_234'], ['a', 'b', 'c'], null, null, false, false, null]], + 22489 => [[['_route' => '_394'], ['a', 'b', 'c'], null, null, false, false, null]], + 22542 => [[['_route' => '_88'], ['a', 'b', 'c'], null, null, false, false, null]], + 22590 => [[['_route' => '_155'], ['a', 'b', 'c'], null, null, false, false, null]], + 22643 => [[['_route' => '_96'], ['a', 'b', 'c'], null, null, false, false, null]], + 22691 => [[['_route' => '_298'], ['a', 'b', 'c'], null, null, false, false, null]], + 22739 => [[['_route' => '_470'], ['a', 'b', 'c'], null, null, false, false, null]], + 22792 => [[['_route' => '_109'], ['a', 'b', 'c'], null, null, false, false, null]], + 22840 => [[['_route' => '_204'], ['a', 'b', 'c'], null, null, false, false, null]], + 22893 => [[['_route' => '_115'], ['a', 'b', 'c'], null, null, false, false, null]], + 22941 => [[['_route' => '_145'], ['a', 'b', 'c'], null, null, false, false, null]], + 22994 => [[['_route' => '_123'], ['a', 'b', 'c'], null, null, false, false, null]], + 23042 => [[['_route' => '_277'], ['a', 'b', 'c'], null, null, false, false, null]], + 23090 => [[['_route' => '_473'], ['a', 'b', 'c'], null, null, false, false, null]], + 23143 => [[['_route' => '_334'], ['a', 'b', 'c'], null, null, false, false, null]], + 23191 => [[['_route' => '_493'], ['a', 'b', 'c'], null, null, false, false, null]], + 23244 => [[['_route' => '_372'], ['a', 'b', 'c'], null, null, false, false, null]], + 23292 => [[['_route' => '_432'], ['a', 'b', 'c'], null, null, false, false, null]], + 23340 => [[['_route' => '_436'], ['a', 'b', 'c'], null, null, false, false, null]], + 23393 => [[['_route' => '_425'], ['a', 'b', 'c'], null, null, false, false, null]], + 23441 => [[['_route' => '_456'], ['a', 'b', 'c'], null, null, false, false, null]], + 23489 => [[['_route' => '_474'], ['a', 'b', 'c'], null, null, false, false, null]], + 23539 => [[['_route' => '_485'], ['a', 'b', 'c'], null, null, false, false, null]], + 23594 => [[['_route' => '_91'], ['a', 'b', 'c'], null, null, false, false, null]], + 23646 => [[['_route' => '_110'], ['a', 'b', 'c'], null, null, false, false, null]], + 23694 => [[['_route' => '_114'], ['a', 'b', 'c'], null, null, false, false, null]], + 23750 => [[['_route' => '_118'], ['a', 'b', 'c'], null, null, false, false, null]], + 23796 => [[['_route' => '_475'], ['a', 'b', 'c'], null, null, false, false, null]], + 23844 => [[['_route' => '_366'], ['a', 'b', 'c'], null, null, false, false, null]], + 23897 => [[['_route' => '_167'], ['a', 'b', 'c'], null, null, false, false, null]], + 23945 => [[['_route' => '_192'], ['a', 'b', 'c'], null, null, false, false, null]], + 23993 => [[['_route' => '_342'], ['a', 'b', 'c'], null, null, false, false, null]], + 24046 => [[['_route' => '_229'], ['a', 'b', 'c'], null, null, false, false, null]], + 24097 => [[['_route' => '_235'], ['a', 'b', 'c'], null, null, false, false, null]], + 24144 => [[['_route' => '_302'], ['a', 'b', 'c'], null, null, false, false, null]], + 24193 => [[['_route' => '_322'], ['a', 'b', 'c'], null, null, false, false, null]], + 24246 => [[['_route' => '_237'], ['a', 'b', 'c'], null, null, false, false, null]], + 24294 => [[['_route' => '_293'], ['a', 'b', 'c'], null, null, false, false, null]], + 24347 => [[['_route' => '_239'], ['a', 'b', 'c'], null, null, false, false, null]], + 24395 => [[['_route' => '_444'], ['a', 'b', 'c'], null, null, false, false, null]], + 24443 => [[['_route' => '_491'], ['a', 'b', 'c'], null, null, false, false, null]], + 24491 => [[['_route' => '_492'], ['a', 'b', 'c'], null, null, false, false, null]], + 24541 => [[['_route' => '_258'], ['a', 'b', 'c'], null, null, false, false, null]], + 24590 => [[['_route' => '_317'], ['a', 'b', 'c'], null, null, false, false, null]], + 24639 => [[['_route' => '_361'], ['a', 'b', 'c'], null, null, false, false, null]], + 24688 => [[['_route' => '_391'], ['a', 'b', 'c'], null, null, false, false, null]], + 24737 => [[['_route' => '_462'], ['a', 'b', 'c'], null, null, false, false, null]], + 24786 => [[['_route' => '_476'], ['a', 'b', 'c'], null, null, false, false, null]], + 24837 => [[['_route' => '_501'], ['a', 'b', 'c'], null, null, false, false, null]], + 24889 => [[['_route' => '_514'], ['a', 'b', 'c'], null, null, false, false, null]], + 24937 => [[['_route' => '_731'], ['a', 'b', 'c'], null, null, false, false, null]], + 24990 => [[['_route' => '_522'], ['a', 'b', 'c'], null, null, false, false, null]], + 25038 => [[['_route' => '_693'], ['a', 'b', 'c'], null, null, false, false, null]], + 25091 => [[['_route' => '_537'], ['a', 'b', 'c'], null, null, false, false, null]], + 25139 => [[['_route' => '_554'], ['a', 'b', 'c'], null, null, false, false, null]], + 25187 => [[['_route' => '_645'], ['a', 'b', 'c'], null, null, false, false, null]], + 25235 => [[['_route' => '_862'], ['a', 'b', 'c'], null, null, false, false, null]], + 25288 => [[['_route' => '_539'], ['a', 'b', 'c'], null, null, false, false, null]], + 25336 => [[['_route' => '_729'], ['a', 'b', 'c'], null, null, false, false, null]], + 25384 => [[['_route' => '_897'], ['a', 'b', 'c'], null, null, false, false, null]], + 25437 => [[['_route' => '_561'], ['a', 'b', 'c'], null, null, false, false, null]], + 25485 => [[['_route' => '_615'], ['a', 'b', 'c'], null, null, false, false, null]], + 25533 => [[['_route' => '_764'], ['a', 'b', 'c'], null, null, false, false, null]], + 25581 => [[['_route' => '_948'], ['a', 'b', 'c'], null, null, false, false, null]], + 25634 => [[['_route' => '_617'], ['a', 'b', 'c'], null, null, false, false, null]], + 25682 => [[['_route' => '_671'], ['a', 'b', 'c'], null, null, false, false, null]], + 25735 => [[['_route' => '_649'], ['a', 'b', 'c'], null, null, false, false, null]], + 25783 => [[['_route' => '_651'], ['a', 'b', 'c'], null, null, false, false, null]], + 25831 => [[['_route' => '_684'], ['a', 'b', 'c'], null, null, false, false, null]], + 25884 => [[['_route' => '_669'], ['a', 'b', 'c'], null, null, false, false, null]], + 25932 => [[['_route' => '_743'], ['a', 'b', 'c'], null, null, false, false, null]], + 25980 => [[['_route' => '_962'], ['a', 'b', 'c'], null, null, false, false, null]], + 26033 => [[['_route' => '_694'], ['a', 'b', 'c'], null, null, false, false, null]], + 26081 => [[['_route' => '_985'], ['a', 'b', 'c'], null, null, false, false, null]], + 26134 => [[['_route' => '_707'], ['a', 'b', 'c'], null, null, false, false, null]], + 26182 => [[['_route' => '_718'], ['a', 'b', 'c'], null, null, false, false, null]], + 26235 => [[['_route' => '_720'], ['a', 'b', 'c'], null, null, false, false, null]], + 26283 => [[['_route' => '_745'], ['a', 'b', 'c'], null, null, false, false, null]], + 26333 => [[['_route' => '_874'], ['a', 'b', 'c'], null, null, false, false, null]], + 26391 => [[['_route' => '_502'], ['a', 'b', 'c'], null, null, false, false, null]], + 26439 => [[['_route' => '_667'], ['a', 'b', 'c'], null, null, false, false, null]], + 26487 => [[['_route' => '_911'], ['a', 'b', 'c'], null, null, false, false, null]], + 26535 => [[['_route' => '_942'], ['a', 'b', 'c'], null, null, false, false, null]], + 26585 => [[['_route' => '_504'], ['a', 'b', 'c'], null, null, false, false, null]], + 26637 => [[['_route' => '_524'], ['a', 'b', 'c'], null, null, false, false, null]], + 26685 => [[['_route' => '_732'], ['a', 'b', 'c'], null, null, false, false, null]], + 26738 => [[['_route' => '_596'], ['a', 'b', 'c'], null, null, false, false, null]], + 26786 => [[['_route' => '_601'], ['a', 'b', 'c'], null, null, false, false, null]], + 26839 => [[['_route' => '_620'], ['a', 'b', 'c'], null, null, false, false, null]], + 26887 => [[['_route' => '_631'], ['a', 'b', 'c'], null, null, false, false, null]], + 26935 => [[['_route' => '_771'], ['a', 'b', 'c'], null, null, false, false, null]], + 26983 => [[['_route' => '_937'], ['a', 'b', 'c'], null, null, false, false, null]], + 27031 => [[['_route' => '_999'], ['a', 'b', 'c'], null, null, false, false, null]], + 27084 => [[['_route' => '_657'], ['a', 'b', 'c'], null, null, false, false, null]], + 27132 => [[['_route' => '_701'], ['a', 'b', 'c'], null, null, false, false, null]], + 27185 => [[['_route' => '_662'], ['a', 'b', 'c'], null, null, false, false, null]], + 27233 => [[['_route' => '_797'], ['a', 'b', 'c'], null, null, false, false, null]], + 27281 => [[['_route' => '_924'], ['a', 'b', 'c'], null, null, false, false, null]], + 27334 => [[['_route' => '_702'], ['a', 'b', 'c'], null, null, false, false, null]], + 27382 => [[['_route' => '_750'], ['a', 'b', 'c'], null, null, false, false, null]], + 27435 => [[['_route' => '_749'], ['a', 'b', 'c'], null, null, false, false, null]], + 27483 => [[['_route' => '_837'], ['a', 'b', 'c'], null, null, false, false, null]], + 27533 => [[['_route' => '_758'], ['a', 'b', 'c'], null, null, false, false, null]], + 27585 => [[['_route' => '_810'], ['a', 'b', 'c'], null, null, false, false, null]], + 27633 => [[['_route' => '_902'], ['a', 'b', 'c'], null, null, false, false, null]], + 27683 => [[['_route' => '_845'], ['a', 'b', 'c'], null, null, false, false, null]], + 27741 => [[['_route' => '_503'], ['a', 'b', 'c'], null, null, false, false, null]], + 27792 => [[['_route' => '_756'], ['a', 'b', 'c'], null, null, false, false, null]], + 27839 => [[['_route' => '_799'], ['a', 'b', 'c'], null, null, false, false, null]], + 27888 => [[['_route' => '_769'], ['a', 'b', 'c'], null, null, false, false, null]], + 27936 => [[['_route' => '_981'], ['a', 'b', 'c'], null, null, false, false, null]], + 27989 => [[['_route' => '_507'], ['a', 'b', 'c'], null, null, false, false, null]], + 28037 => [[['_route' => '_672'], ['a', 'b', 'c'], null, null, false, false, null]], + 28085 => [[['_route' => '_790'], ['a', 'b', 'c'], null, null, false, false, null]], + 28138 => [[['_route' => '_515'], ['a', 'b', 'c'], null, null, false, false, null]], + 28186 => [[['_route' => '_523'], ['a', 'b', 'c'], null, null, false, false, null]], + 28234 => [[['_route' => '_957'], ['a', 'b', 'c'], null, null, false, false, null]], + 28282 => [[['_route' => '_995'], ['a', 'b', 'c'], null, null, false, false, null]], + 28335 => [[['_route' => '_532'], ['a', 'b', 'c'], null, null, false, false, null]], + 28383 => [[['_route' => '_642'], ['a', 'b', 'c'], null, null, false, false, null]], + 28433 => [[['_route' => '_579'], ['a', 'b', 'c'], null, null, false, false, null]], + 28485 => [[['_route' => '_625'], ['a', 'b', 'c'], null, null, false, false, null]], + 28533 => [[['_route' => '_916'], ['a', 'b', 'c'], null, null, false, false, null]], + 28586 => [[['_route' => '_633'], ['a', 'b', 'c'], null, null, false, false, null]], + 28634 => [[['_route' => '_656'], ['a', 'b', 'c'], null, null, false, false, null]], + 28687 => [[['_route' => '_658'], ['a', 'b', 'c'], null, null, false, false, null]], + 28735 => [[['_route' => '_943'], ['a', 'b', 'c'], null, null, false, false, null]], + 28788 => [[['_route' => '_664'], ['a', 'b', 'c'], null, null, false, false, null]], + 28836 => [[['_route' => '_852'], ['a', 'b', 'c'], null, null, false, false, null]], + 28884 => [[['_route' => '_870'], ['a', 'b', 'c'], null, null, false, false, null]], + 28937 => [[['_route' => '_683'], ['a', 'b', 'c'], null, null, false, false, null]], + 28985 => [[['_route' => '_915'], ['a', 'b', 'c'], null, null, false, false, null]], + 29038 => [[['_route' => '_719'], ['a', 'b', 'c'], null, null, false, false, null]], + 29086 => [[['_route' => '_859'], ['a', 'b', 'c'], null, null, false, false, null]], + 29134 => [[['_route' => '_912'], ['a', 'b', 'c'], null, null, false, false, null]], + 29182 => [[['_route' => '_978'], ['a', 'b', 'c'], null, null, false, false, null]], + 29235 => [[['_route' => '_738'], ['a', 'b', 'c'], null, null, false, false, null]], + 29283 => [[['_route' => '_883'], ['a', 'b', 'c'], null, null, false, false, null]], + 29333 => [[['_route' => '_741'], ['a', 'b', 'c'], null, null, false, false, null]], + 29382 => [[['_route' => '_760'], ['a', 'b', 'c'], null, null, false, false, null]], + 29431 => [[['_route' => '_895'], ['a', 'b', 'c'], null, null, false, false, null]], + 29489 => [[['_route' => '_505'], ['a', 'b', 'c'], null, null, false, false, null]], + 29537 => [[['_route' => '_935'], ['a', 'b', 'c'], null, null, false, false, null]], + 29590 => [[['_route' => '_509'], ['a', 'b', 'c'], null, null, false, false, null]], + 29638 => [[['_route' => '_820'], ['a', 'b', 'c'], null, null, false, false, null]], + 29686 => [[['_route' => '_910'], ['a', 'b', 'c'], null, null, false, false, null]], + 29739 => [[['_route' => '_518'], ['a', 'b', 'c'], null, null, false, false, null]], + 29787 => [[['_route' => '_618'], ['a', 'b', 'c'], null, null, false, false, null]], + 29840 => [[['_route' => '_546'], ['a', 'b', 'c'], null, null, false, false, null]], + 29888 => [[['_route' => '_740'], ['a', 'b', 'c'], null, null, false, false, null]], + 29936 => [[['_route' => '_867'], ['a', 'b', 'c'], null, null, false, false, null]], + 29989 => [[['_route' => '_572'], ['a', 'b', 'c'], null, null, false, false, null]], + 30037 => [[['_route' => '_952'], ['a', 'b', 'c'], null, null, false, false, null]], + 30090 => [[['_route' => '_573'], ['a', 'b', 'c'], null, null, false, false, null]], + 30138 => [[['_route' => '_692'], ['a', 'b', 'c'], null, null, false, false, null]], + 30186 => [[['_route' => '_700'], ['a', 'b', 'c'], null, null, false, false, null]], + 30234 => [[['_route' => '_772'], ['a', 'b', 'c'], null, null, false, false, null]], + 30284 => [[['_route' => '_653'], ['a', 'b', 'c'], null, null, false, false, null]], + 30336 => [[['_route' => '_695'], ['a', 'b', 'c'], null, null, false, false, null]], + 30384 => [[['_route' => '_748'], ['a', 'b', 'c'], null, null, false, false, null]], + 30437 => [[['_route' => '_710'], ['a', 'b', 'c'], null, null, false, false, null]], + 30485 => [[['_route' => '_716'], ['a', 'b', 'c'], null, null, false, false, null]], + 30533 => [[['_route' => '_969'], ['a', 'b', 'c'], null, null, false, false, null]], + 30586 => [[['_route' => '_734'], ['a', 'b', 'c'], null, null, false, false, null]], + 30634 => [[['_route' => '_742'], ['a', 'b', 'c'], null, null, false, false, null]], + 30682 => [[['_route' => '_844'], ['a', 'b', 'c'], null, null, false, false, null]], + 30735 => [[['_route' => '_763'], ['a', 'b', 'c'], null, null, false, false, null]], + 30783 => [[['_route' => '_965'], ['a', 'b', 'c'], null, null, false, false, null]], + 30836 => [[['_route' => '_778'], ['a', 'b', 'c'], null, null, false, false, null]], + 30884 => [[['_route' => '_813'], ['a', 'b', 'c'], null, null, false, false, null]], + 30932 => [[['_route' => '_831'], ['a', 'b', 'c'], null, null, false, false, null]], + 30982 => [[['_route' => '_955'], ['a', 'b', 'c'], null, null, false, false, null]], + 31031 => [[['_route' => '_997'], ['a', 'b', 'c'], null, null, false, false, null]], + 31089 => [[['_route' => '_506'], ['a', 'b', 'c'], null, null, false, false, null]], + 31137 => [[['_route' => '_575'], ['a', 'b', 'c'], null, null, false, false, null]], + 31190 => [[['_route' => '_516'], ['a', 'b', 'c'], null, null, false, false, null]], + 31238 => [[['_route' => '_553'], ['a', 'b', 'c'], null, null, false, false, null]], + 31291 => [[['_route' => '_528'], ['a', 'b', 'c'], null, null, false, false, null]], + 31339 => [[['_route' => '_847'], ['a', 'b', 'c'], null, null, false, false, null]], + 31387 => [[['_route' => '_904'], ['a', 'b', 'c'], null, null, false, false, null]], + 31440 => [[['_route' => '_574'], ['a', 'b', 'c'], null, null, false, false, null]], + 31488 => [[['_route' => '_818'], ['a', 'b', 'c'], null, null, false, false, null]], + 31538 => [[['_route' => '_577'], ['a', 'b', 'c'], null, null, false, false, null]], + 31590 => [[['_route' => '_584'], ['a', 'b', 'c'], null, null, false, false, null]], + 31638 => [[['_route' => '_905'], ['a', 'b', 'c'], null, null, false, false, null]], + 31691 => [[['_route' => '_612'], ['a', 'b', 'c'], null, null, false, false, null]], + 31739 => [[['_route' => '_688'], ['a', 'b', 'c'], null, null, false, false, null]], + 31787 => [[['_route' => '_854'], ['a', 'b', 'c'], null, null, false, false, null]], + 31840 => [[['_route' => '_613'], ['a', 'b', 'c'], null, null, false, false, null]], + 31888 => [[['_route' => '_767'], ['a', 'b', 'c'], null, null, false, false, null]], + 31941 => [[['_route' => '_666'], ['a', 'b', 'c'], null, null, false, false, null]], + 31989 => [[['_route' => '_759'], ['a', 'b', 'c'], null, null, false, false, null]], + 32037 => [[['_route' => '_827'], ['a', 'b', 'c'], null, null, false, false, null]], + 32085 => [[['_route' => '_840'], ['a', 'b', 'c'], null, null, false, false, null]], + 32138 => [[['_route' => '_680'], ['a', 'b', 'c'], null, null, false, false, null]], + 32186 => [[['_route' => '_784'], ['a', 'b', 'c'], null, null, false, false, null]], + 32234 => [[['_route' => '_842'], ['a', 'b', 'c'], null, null, false, false, null]], + 32282 => [[['_route' => '_860'], ['a', 'b', 'c'], null, null, false, false, null]], + 32332 => [[['_route' => '_704'], ['a', 'b', 'c'], null, null, false, false, null]], + 32381 => [[['_route' => '_727'], ['a', 'b', 'c'], null, null, false, false, null]], + 32430 => [[['_route' => '_777'], ['a', 'b', 'c'], null, null, false, false, null]], + 32482 => [[['_route' => '_838'], ['a', 'b', 'c'], null, null, false, false, null]], + 32530 => [[['_route' => '_861'], ['a', 'b', 'c'], null, null, false, false, null]], + 32583 => [[['_route' => '_849'], ['a', 'b', 'c'], null, null, false, false, null]], + 32631 => [[['_route' => '_982'], ['a', 'b', 'c'], null, null, false, false, null]], + 32679 => [[['_route' => '_986'], ['a', 'b', 'c'], null, null, false, false, null]], + 32741 => [[['_route' => '_508'], ['a', 'b', 'c'], null, null, false, false, null]], + 32788 => [[['_route' => '_517'], ['a', 'b', 'c'], null, null, false, false, null]], + 32837 => [[['_route' => '_622'], ['a', 'b', 'c'], null, null, false, false, null]], + 32890 => [[['_route' => '_513'], ['a', 'b', 'c'], null, null, false, false, null]], + 32938 => [[['_route' => '_655'], ['a', 'b', 'c'], null, null, false, false, null]], + 32986 => [[['_route' => '_843'], ['a', 'b', 'c'], null, null, false, false, null]], + 33034 => [[['_route' => '_939'], ['a', 'b', 'c'], null, null, false, false, null]], + 33084 => [[['_route' => '_529'], ['a', 'b', 'c'], null, null, false, false, null]], + 33136 => [[['_route' => '_535'], ['a', 'b', 'c'], null, null, false, false, null]], + 33184 => [[['_route' => '_685'], ['a', 'b', 'c'], null, null, false, false, null]], + 33240 => [[['_route' => '_559'], ['a', 'b', 'c'], null, null, false, false, null]], + 33287 => [[['_route' => '_661'], ['a', 'b', 'c'], null, null, false, false, null]], + 33336 => [[['_route' => '_768'], ['a', 'b', 'c'], null, null, false, false, null]], + 33389 => [[['_route' => '_589'], ['a', 'b', 'c'], null, null, false, false, null]], + 33437 => [[['_route' => '_647'], ['a', 'b', 'c'], null, null, false, false, null]], + 33485 => [[['_route' => '_652'], ['a', 'b', 'c'], null, null, false, false, null]], + 33533 => [[['_route' => '_834'], ['a', 'b', 'c'], null, null, false, false, null]], + 33586 => [[['_route' => '_591'], ['a', 'b', 'c'], null, null, false, false, null]], + 33634 => [[['_route' => '_599'], ['a', 'b', 'c'], null, null, false, false, null]], + 33687 => [[['_route' => '_787'], ['a', 'b', 'c'], null, null, false, false, null]], + 33734 => [[['_route' => '_848'], ['a', 'b', 'c'], null, null, false, false, null]], + 33787 => [[['_route' => '_796'], ['a', 'b', 'c'], null, null, false, false, null]], + 33835 => [[['_route' => '_877'], ['a', 'b', 'c'], null, null, false, false, null]], + 33885 => [[['_route' => '_809'], ['a', 'b', 'c'], null, null, false, false, null]], + 33934 => [[['_route' => '_817'], ['a', 'b', 'c'], null, null, false, false, null]], + 33986 => [[['_route' => '_819'], ['a', 'b', 'c'], null, null, false, false, null]], + 34034 => [[['_route' => '_865'], ['a', 'b', 'c'], null, null, false, false, null]], + 34084 => [[['_route' => '_919'], ['a', 'b', 'c'], null, null, false, false, null]], + 34133 => [[['_route' => '_949'], ['a', 'b', 'c'], null, null, false, false, null]], + 34191 => [[['_route' => '_510'], ['a', 'b', 'c'], null, null, false, false, null]], + 34239 => [[['_route' => '_590'], ['a', 'b', 'c'], null, null, false, false, null]], + 34287 => [[['_route' => '_597'], ['a', 'b', 'c'], null, null, false, false, null]], + 34335 => [[['_route' => '_682'], ['a', 'b', 'c'], null, null, false, false, null]], + 34383 => [[['_route' => '_723'], ['a', 'b', 'c'], null, null, false, false, null]], + 34436 => [[['_route' => '_521'], ['a', 'b', 'c'], null, null, false, false, null]], + 34484 => [[['_route' => '_594'], ['a', 'b', 'c'], null, null, false, false, null]], + 34532 => [[['_route' => '_689'], ['a', 'b', 'c'], null, null, false, false, null]], + 34580 => [[['_route' => '_713'], ['a', 'b', 'c'], null, null, false, false, null]], + 34628 => [[['_route' => '_889'], ['a', 'b', 'c'], null, null, false, false, null]], + 34681 => [[['_route' => '_531'], ['a', 'b', 'c'], null, null, false, false, null]], + 34729 => [[['_route' => '_639'], ['a', 'b', 'c'], null, null, false, false, null]], + 34780 => [[['_route' => '_646'], ['a', 'b', 'c'], null, null, false, false, null]], + 34827 => [[['_route' => '_659'], ['a', 'b', 'c'], null, null, false, false, null]], + 34876 => [[['_route' => '_959'], ['a', 'b', 'c'], null, null, false, false, null]], + 34929 => [[['_route' => '_550'], ['a', 'b', 'c'], null, null, false, false, null]], + 34977 => [[['_route' => '_833'], ['a', 'b', 'c'], null, null, false, false, null]], + 35025 => [[['_route' => '_899'], ['a', 'b', 'c'], null, null, false, false, null]], + 35081 => [[['_route' => '_580'], ['a', 'b', 'c'], null, null, false, false, null]], + 35128 => [[['_route' => '_762'], ['a', 'b', 'c'], null, null, false, false, null]], + 35177 => [[['_route' => '_896'], ['a', 'b', 'c'], null, null, false, false, null]], + 35230 => [[['_route' => '_595'], ['a', 'b', 'c'], null, null, false, false, null]], + 35278 => [[['_route' => '_933'], ['a', 'b', 'c'], null, null, false, false, null]], + 35328 => [[['_route' => '_610'], ['a', 'b', 'c'], null, null, false, false, null]], + 35380 => [[['_route' => '_629'], ['a', 'b', 'c'], null, null, false, false, null]], + 35428 => [[['_route' => '_744'], ['a', 'b', 'c'], null, null, false, false, null]], + 35481 => [[['_route' => '_674'], ['a', 'b', 'c'], null, null, false, false, null]], + 35529 => [[['_route' => '_726'], ['a', 'b', 'c'], null, null, false, false, null]], + 35577 => [[['_route' => '_929'], ['a', 'b', 'c'], null, null, false, false, null]], + 35627 => [[['_route' => '_696'], ['a', 'b', 'c'], null, null, false, false, null]], + 35679 => [[['_route' => '_841'], ['a', 'b', 'c'], null, null, false, false, null]], + 35727 => [[['_route' => '_890'], ['a', 'b', 'c'], null, null, false, false, null]], + 35777 => [[['_route' => '_885'], ['a', 'b', 'c'], null, null, false, false, null]], + 35826 => [[['_route' => '_888'], ['a', 'b', 'c'], null, null, false, false, null]], + 35875 => [[['_route' => '_996'], ['a', 'b', 'c'], null, null, false, false, null]], + 35933 => [[['_route' => '_511'], ['a', 'b', 'c'], null, null, false, false, null]], + 35981 => [[['_route' => '_576'], ['a', 'b', 'c'], null, null, false, false, null]], + 36029 => [[['_route' => '_623'], ['a', 'b', 'c'], null, null, false, false, null]], + 36082 => [[['_route' => '_560'], ['a', 'b', 'c'], null, null, false, false, null]], + 36129 => [[['_route' => '_585'], ['a', 'b', 'c'], null, null, false, false, null]], + 36182 => [[['_route' => '_570'], ['a', 'b', 'c'], null, null, false, false, null]], + 36230 => [[['_route' => '_578'], ['a', 'b', 'c'], null, null, false, false, null]], + 36281 => [[['_route' => '_780'], ['a', 'b', 'c'], null, null, false, false, null]], + 36328 => [[['_route' => '_808'], ['a', 'b', 'c'], null, null, false, false, null]], + 36382 => [[['_route' => '_593'], ['a', 'b', 'c'], null, null, false, false, null]], + 36430 => [[['_route' => '_900'], ['a', 'b', 'c'], null, null, false, false, null]], + 36483 => [[['_route' => '_632'], ['a', 'b', 'c'], null, null, false, false, null]], + 36531 => [[['_route' => '_654'], ['a', 'b', 'c'], null, null, false, false, null]], + 36579 => [[['_route' => '_721'], ['a', 'b', 'c'], null, null, false, false, null]], + 36627 => [[['_route' => '_836'], ['a', 'b', 'c'], null, null, false, false, null]], + 36680 => [[['_route' => '_637'], ['a', 'b', 'c'], null, null, false, false, null]], + 36728 => [[['_route' => '_737'], ['a', 'b', 'c'], null, null, false, false, null]], + 36784 => [[['_route' => '_699'], ['a', 'b', 'c'], null, null, false, false, null]], + 36831 => [[['_route' => '_822'], ['a', 'b', 'c'], null, null, false, false, null]], + 36880 => [[['_route' => '_853'], ['a', 'b', 'c'], null, null, false, false, null]], + 36933 => [[['_route' => '_708'], ['a', 'b', 'c'], null, null, false, false, null]], + 36981 => [[['_route' => '_871'], ['a', 'b', 'c'], null, null, false, false, null]], + 37034 => [[['_route' => '_752'], ['a', 'b', 'c'], null, null, false, false, null]], + 37082 => [[['_route' => '_989'], ['a', 'b', 'c'], null, null, false, false, null]], + 37132 => [[['_route' => '_855'], ['a', 'b', 'c'], null, null, false, false, null]], + 37184 => [[['_route' => '_858'], ['a', 'b', 'c'], null, null, false, false, null]], + 37232 => [[['_route' => '_898'], ['a', 'b', 'c'], null, null, false, false, null]], + 37282 => [[['_route' => '_903'], ['a', 'b', 'c'], null, null, false, false, null]], + 37331 => [[['_route' => '_909'], ['a', 'b', 'c'], null, null, false, false, null]], + 37380 => [[['_route' => '_950'], ['a', 'b', 'c'], null, null, false, false, null]], + 37441 => [[['_route' => '_512'], ['a', 'b', 'c'], null, null, false, false, null]], + 37488 => [[['_route' => '_691'], ['a', 'b', 'c'], null, null, false, false, null]], + 37537 => [[['_route' => '_686'], ['a', 'b', 'c'], null, null, false, false, null]], + 37587 => [[['_route' => '_527'], ['a', 'b', 'c'], null, null, false, false, null]], + 37639 => [[['_route' => '_541'], ['a', 'b', 'c'], null, null, false, false, null]], + 37687 => [[['_route' => '_956'], ['a', 'b', 'c'], null, null, false, false, null]], + 37740 => [[['_route' => '_555'], ['a', 'b', 'c'], null, null, false, false, null]], + 37788 => [[['_route' => '_681'], ['a', 'b', 'c'], null, null, false, false, null]], + 37841 => [[['_route' => '_556'], ['a', 'b', 'c'], null, null, false, false, null]], + 37889 => [[['_route' => '_802'], ['a', 'b', 'c'], null, null, false, false, null]], + 37939 => [[['_route' => '_558'], ['a', 'b', 'c'], null, null, false, false, null]], + 37991 => [[['_route' => '_564'], ['a', 'b', 'c'], null, null, false, false, null]], + 38039 => [[['_route' => '_670'], ['a', 'b', 'c'], null, null, false, false, null]], + 38087 => [[['_route' => '_884'], ['a', 'b', 'c'], null, null, false, false, null]], + 38140 => [[['_route' => '_627'], ['a', 'b', 'c'], null, null, false, false, null]], + 38187 => [[['_route' => '_746'], ['a', 'b', 'c'], null, null, false, false, null]], + 38240 => [[['_route' => '_668'], ['a', 'b', 'c'], null, null, false, false, null]], + 38291 => [[['_route' => '_712'], ['a', 'b', 'c'], null, null, false, false, null]], + 38338 => [[['_route' => '_863'], ['a', 'b', 'c'], null, null, false, false, null]], + 38387 => [[['_route' => '_801'], ['a', 'b', 'c'], null, null, false, false, null]], + 38440 => [[['_route' => '_709'], ['a', 'b', 'c'], null, null, false, false, null]], + 38488 => [[['_route' => '_850'], ['a', 'b', 'c'], null, null, false, false, null]], + 38536 => [[['_route' => '_918'], ['a', 'b', 'c'], null, null, false, false, null]], + 38586 => [[['_route' => '_803'], ['a', 'b', 'c'], null, null, false, false, null]], + 38638 => [[['_route' => '_864'], ['a', 'b', 'c'], null, null, false, false, null]], + 38686 => [[['_route' => '_880'], ['a', 'b', 'c'], null, null, false, false, null]], + 38734 => [[['_route' => '_927'], ['a', 'b', 'c'], null, null, false, false, null]], + 38787 => [[['_route' => '_930'], ['a', 'b', 'c'], null, null, false, false, null]], + 38835 => [[['_route' => '_951'], ['a', 'b', 'c'], null, null, false, false, null]], + 38883 => [[['_route' => '_963'], ['a', 'b', 'c'], null, null, false, false, null]], + 38942 => [[['_route' => '_519'], ['a', 'b', 'c'], null, null, false, false, null]], + 38990 => [[['_route' => '_823'], ['a', 'b', 'c'], null, null, false, false, null]], + 39038 => [[['_route' => '_954'], ['a', 'b', 'c'], null, null, false, false, null]], + 39091 => [[['_route' => '_525'], ['a', 'b', 'c'], null, null, false, false, null]], + 39139 => [[['_route' => '_991'], ['a', 'b', 'c'], null, null, false, false, null]], + 39189 => [[['_route' => '_536'], ['a', 'b', 'c'], null, null, false, false, null]], + 39241 => [[['_route' => '_545'], ['a', 'b', 'c'], null, null, false, false, null]], + 39289 => [[['_route' => '_944'], ['a', 'b', 'c'], null, null, false, false, null]], + 39342 => [[['_route' => '_557'], ['a', 'b', 'c'], null, null, false, false, null]], + 39390 => [[['_route' => '_783'], ['a', 'b', 'c'], null, null, false, false, null]], + 39438 => [[['_route' => '_807'], ['a', 'b', 'c'], null, null, false, false, null]], + 39491 => [[['_route' => '_586'], ['a', 'b', 'c'], null, null, false, false, null]], + 39539 => [[['_route' => '_711'], ['a', 'b', 'c'], null, null, false, false, null]], + 39592 => [[['_route' => '_598'], ['a', 'b', 'c'], null, null, false, false, null]], + 39640 => [[['_route' => '_635'], ['a', 'b', 'c'], null, null, false, false, null]], + 39688 => [[['_route' => '_983'], ['a', 'b', 'c'], null, null, false, false, null]], + 39741 => [[['_route' => '_634'], ['a', 'b', 'c'], null, null, false, false, null]], + 39789 => [[['_route' => '_641'], ['a', 'b', 'c'], null, null, false, false, null]], + 39840 => [[['_route' => '_779'], ['a', 'b', 'c'], null, null, false, false, null]], + 39887 => [[['_route' => '_876'], ['a', 'b', 'c'], null, null, false, false, null]], + 39936 => [[['_route' => '_811'], ['a', 'b', 'c'], null, null, false, false, null]], + 39984 => [[['_route' => '_824'], ['a', 'b', 'c'], null, null, false, false, null]], + 40037 => [[['_route' => '_660'], ['a', 'b', 'c'], null, null, false, false, null]], + 40085 => [[['_route' => '_789'], ['a', 'b', 'c'], null, null, false, false, null]], + 40138 => [[['_route' => '_733'], ['a', 'b', 'c'], null, null, false, false, null]], + 40186 => [[['_route' => '_735'], ['a', 'b', 'c'], null, null, false, false, null]], + 40234 => [[['_route' => '_882'], ['a', 'b', 'c'], null, null, false, false, null]], + 40282 => [[['_route' => '_967'], ['a', 'b', 'c'], null, null, false, false, null]], + 40332 => [[['_route' => '_736'], ['a', 'b', 'c'], null, null, false, false, null]], + 40381 => [[['_route' => '_753'], ['a', 'b', 'c'], null, null, false, false, null]], + 40430 => [[['_route' => '_786'], ['a', 'b', 'c'], null, null, false, false, null]], + 40479 => [[['_route' => '_907'], ['a', 'b', 'c'], null, null, false, false, null]], + 40528 => [[['_route' => '_920'], ['a', 'b', 'c'], null, null, false, false, null]], + 40577 => [[['_route' => '_971'], ['a', 'b', 'c'], null, null, false, false, null]], + 40635 => [[['_route' => '_520'], ['a', 'b', 'c'], null, null, false, false, null]], + 40683 => [[['_route' => '_891'], ['a', 'b', 'c'], null, null, false, false, null]], + 40739 => [[['_route' => '_534'], ['a', 'b', 'c'], null, null, false, false, null]], + 40785 => [[['_route' => '_602'], ['a', 'b', 'c'], null, null, false, false, null]], + 40834 => [[['_route' => '_605'], ['a', 'b', 'c'], null, null, false, false, null]], + 40882 => [[['_route' => '_979'], ['a', 'b', 'c'], null, null, false, false, null]], + 40932 => [[['_route' => '_547'], ['a', 'b', 'c'], null, null, false, false, null]], + 40987 => [[['_route' => '_549'], ['a', 'b', 'c'], null, null, false, false, null]], + 41034 => [[['_route' => '_755'], ['a', 'b', 'c'], null, null, false, false, null]], + 41083 => [[['_route' => '_922'], ['a', 'b', 'c'], null, null, false, false, null]], + 41131 => [[['_route' => '_977'], ['a', 'b', 'c'], null, null, false, false, null]], + 41184 => [[['_route' => '_565'], ['a', 'b', 'c'], null, null, false, false, null]], + 41232 => [[['_route' => '_926'], ['a', 'b', 'c'], null, null, false, false, null]], + 41282 => [[['_route' => '_571'], ['a', 'b', 'c'], null, null, false, false, null]], + 41331 => [[['_route' => '_581'], ['a', 'b', 'c'], null, null, false, false, null]], + 41380 => [[['_route' => '_619'], ['a', 'b', 'c'], null, null, false, false, null]], + 41429 => [[['_route' => '_636'], ['a', 'b', 'c'], null, null, false, false, null]], + 41481 => [[['_route' => '_679'], ['a', 'b', 'c'], null, null, false, false, null]], + 41529 => [[['_route' => '_866'], ['a', 'b', 'c'], null, null, false, false, null]], + 41577 => [[['_route' => '_973'], ['a', 'b', 'c'], null, null, false, false, null]], + 41630 => [[['_route' => '_690'], ['a', 'b', 'c'], null, null, false, false, null]], + 41678 => [[['_route' => '_775'], ['a', 'b', 'c'], null, null, false, false, null]], + 41731 => [[['_route' => '_722'], ['a', 'b', 'c'], null, null, false, false, null]], + 41779 => [[['_route' => '_906'], ['a', 'b', 'c'], null, null, false, false, null]], + 41827 => [[['_route' => '_946'], ['a', 'b', 'c'], null, null, false, false, null]], + 41877 => [[['_route' => '_788'], ['a', 'b', 'c'], null, null, false, false, null]], + 41929 => [[['_route' => '_828'], ['a', 'b', 'c'], null, null, false, false, null]], + 41977 => [[['_route' => '_892'], ['a', 'b', 'c'], null, null, false, false, null]], + 42025 => [[['_route' => '_972'], ['a', 'b', 'c'], null, null, false, false, null]], + 42075 => [[['_route' => '_829'], ['a', 'b', 'c'], null, null, false, false, null]], + 42127 => [[['_route' => '_923'], ['a', 'b', 'c'], null, null, false, false, null]], + 42175 => [[['_route' => '_947'], ['a', 'b', 'c'], null, null, false, false, null]], + 42234 => [[['_route' => '_526'], ['a', 'b', 'c'], null, null, false, false, null]], + 42282 => [[['_route' => '_614'], ['a', 'b', 'c'], null, null, false, false, null]], + 42330 => [[['_route' => '_621'], ['a', 'b', 'c'], null, null, false, false, null]], + 42383 => [[['_route' => '_543'], ['a', 'b', 'c'], null, null, false, false, null]], + 42431 => [[['_route' => '_812'], ['a', 'b', 'c'], null, null, false, false, null]], + 42487 => [[['_route' => '_548'], ['a', 'b', 'c'], null, null, false, false, null]], + 42534 => [[['_route' => '_747'], ['a', 'b', 'c'], null, null, false, false, null]], + 42583 => [[['_route' => '_715'], ['a', 'b', 'c'], null, null, false, false, null]], + 42631 => [[['_route' => '_940'], ['a', 'b', 'c'], null, null, false, false, null]], + 42684 => [[['_route' => '_563'], ['a', 'b', 'c'], null, null, false, false, null]], + 42732 => [[['_route' => '_611'], ['a', 'b', 'c'], null, null, false, false, null]], + 42780 => [[['_route' => '_830'], ['a', 'b', 'c'], null, null, false, false, null]], + 42833 => [[['_route' => '_569'], ['a', 'b', 'c'], null, null, false, false, null]], + 42881 => [[['_route' => '_908'], ['a', 'b', 'c'], null, null, false, false, null]], + 42929 => [[['_route' => '_913'], ['a', 'b', 'c'], null, null, false, false, null]], + 42982 => [[['_route' => '_644'], ['a', 'b', 'c'], null, null, false, false, null]], + 43030 => [[['_route' => '_776'], ['a', 'b', 'c'], null, null, false, false, null]], + 43078 => [[['_route' => '_856'], ['a', 'b', 'c'], null, null, false, false, null]], + 43131 => [[['_route' => '_650'], ['a', 'b', 'c'], null, null, false, false, null]], + 43179 => [[['_route' => '_761'], ['a', 'b', 'c'], null, null, false, false, null]], + 43232 => [[['_route' => '_663'], ['a', 'b', 'c'], null, null, false, false, null]], + 43280 => [[['_route' => '_754'], ['a', 'b', 'c'], null, null, false, false, null]], + 43333 => [[['_route' => '_665'], ['a', 'b', 'c'], null, null, false, false, null]], + 43381 => [[['_route' => '_805'], ['a', 'b', 'c'], null, null, false, false, null]], + 43429 => [[['_route' => '_846'], ['a', 'b', 'c'], null, null, false, false, null]], + 43477 => [[['_route' => '_857'], ['a', 'b', 'c'], null, null, false, false, null]], + 43530 => [[['_route' => '_675'], ['a', 'b', 'c'], null, null, false, false, null]], + 43578 => [[['_route' => '_839'], ['a', 'b', 'c'], null, null, false, false, null]], + 43626 => [[['_route' => '_968'], ['a', 'b', 'c'], null, null, false, false, null]], + 43676 => [[['_route' => '_697'], ['a', 'b', 'c'], null, null, false, false, null]], + 43728 => [[['_route' => '_725'], ['a', 'b', 'c'], null, null, false, false, null]], + 43776 => [[['_route' => '_794'], ['a', 'b', 'c'], null, null, false, false, null]], + 43829 => [[['_route' => '_773'], ['a', 'b', 'c'], null, null, false, false, null]], + 43877 => [[['_route' => '_992'], ['a', 'b', 'c'], null, null, false, false, null]], + 43930 => [[['_route' => '_901'], ['a', 'b', 'c'], null, null, false, false, null]], + 43978 => [[['_route' => '_970'], ['a', 'b', 'c'], null, null, false, false, null]], + 44028 => [[['_route' => '_964'], ['a', 'b', 'c'], null, null, false, false, null]], + 44086 => [[['_route' => '_530'], ['a', 'b', 'c'], null, null, false, false, null]], + 44134 => [[['_route' => '_703'], ['a', 'b', 'c'], null, null, false, false, null]], + 44187 => [[['_route' => '_533'], ['a', 'b', 'c'], null, null, false, false, null]], + 44235 => [[['_route' => '_739'], ['a', 'b', 'c'], null, null, false, false, null]], + 44283 => [[['_route' => '_791'], ['a', 'b', 'c'], null, null, false, false, null]], + 44331 => [[['_route' => '_987'], ['a', 'b', 'c'], null, null, false, false, null]], + 44384 => [[['_route' => '_566'], ['a', 'b', 'c'], null, null, false, false, null]], + 44432 => [[['_route' => '_592'], ['a', 'b', 'c'], null, null, false, false, null]], + 44488 => [[['_route' => '_568'], ['a', 'b', 'c'], null, null, false, false, null]], + 44534 => [[['_route' => '_868'], ['a', 'b', 'c'], null, null, false, false, null]], + 44583 => [[['_route' => '_878'], ['a', 'b', 'c'], null, null, false, false, null]], + 44636 => [[['_route' => '_588'], ['a', 'b', 'c'], null, null, false, false, null]], + 44684 => [[['_route' => '_793'], ['a', 'b', 'c'], null, null, false, false, null]], + 44732 => [[['_route' => '_917'], ['a', 'b', 'c'], null, null, false, false, null]], + 44785 => [[['_route' => '_600'], ['a', 'b', 'c'], null, null, false, false, null]], + 44833 => [[['_route' => '_728'], ['a', 'b', 'c'], null, null, false, false, null]], + 44886 => [[['_route' => '_603'], ['a', 'b', 'c'], null, null, false, false, null]], + 44934 => [[['_route' => '_765'], ['a', 'b', 'c'], null, null, false, false, null]], + 44987 => [[['_route' => '_607'], ['a', 'b', 'c'], null, null, false, false, null]], + 45035 => [[['_route' => '_676'], ['a', 'b', 'c'], null, null, false, false, null]], + 45083 => [[['_route' => '_804'], ['a', 'b', 'c'], null, null, false, false, null]], + 45136 => [[['_route' => '_609'], ['a', 'b', 'c'], null, null, false, false, null]], + 45184 => [[['_route' => '_961'], ['a', 'b', 'c'], null, null, false, false, null]], + 45232 => [[['_route' => '_980'], ['a', 'b', 'c'], null, null, false, false, null]], + 45282 => [[['_route' => '_714'], ['a', 'b', 'c'], null, null, false, false, null]], + 45334 => [[['_route' => '_730'], ['a', 'b', 'c'], null, null, false, false, null]], + 45382 => [[['_route' => '_806'], ['a', 'b', 'c'], null, null, false, false, null]], + 45430 => [[['_route' => '_825'], ['a', 'b', 'c'], null, null, false, false, null]], + 45478 => [[['_route' => '_879'], ['a', 'b', 'c'], null, null, false, false, null]], + 45526 => [[['_route' => '_893'], ['a', 'b', 'c'], null, null, false, false, null]], + 45576 => [[['_route' => '_928'], ['a', 'b', 'c'], null, null, false, false, null]], + 45628 => [[['_route' => '_932'], ['a', 'b', 'c'], null, null, false, false, null]], + 45676 => [[['_route' => '_958'], ['a', 'b', 'c'], null, null, false, false, null]], + 45726 => [[['_route' => '_984'], ['a', 'b', 'c'], null, null, false, false, null]], + 45784 => [[['_route' => '_538'], ['a', 'b', 'c'], null, null, false, false, null]], + 45832 => [[['_route' => '_993'], ['a', 'b', 'c'], null, null, false, false, null]], + 45882 => [[['_route' => '_542'], ['a', 'b', 'c'], null, null, false, false, null]], + 45934 => [[['_route' => '_551'], ['a', 'b', 'c'], null, null, false, false, null]], + 45982 => [[['_route' => '_687'], ['a', 'b', 'c'], null, null, false, false, null]], + 46030 => [[['_route' => '_724'], ['a', 'b', 'c'], null, null, false, false, null]], + 46078 => [[['_route' => '_925'], ['a', 'b', 'c'], null, null, false, false, null]], + 46131 => [[['_route' => '_587'], ['a', 'b', 'c'], null, null, false, false, null]], + 46179 => [[['_route' => '_914'], ['a', 'b', 'c'], null, null, false, false, null]], + 46229 => [[['_route' => '_616'], ['a', 'b', 'c'], null, null, false, false, null]], + 46284 => [[['_route' => '_677'], ['a', 'b', 'c'], null, null, false, false, null]], + 46331 => [[['_route' => '_815'], ['a', 'b', 'c'], null, null, false, false, null]], + 46380 => [[['_route' => '_781'], ['a', 'b', 'c'], null, null, false, false, null]], + 46430 => [[['_route' => '_717'], ['a', 'b', 'c'], null, null, false, false, null]], + 46482 => [[['_route' => '_782'], ['a', 'b', 'c'], null, null, false, false, null]], + 46530 => [[['_route' => '_832'], ['a', 'b', 'c'], null, null, false, false, null]], + 46583 => [[['_route' => '_795'], ['a', 'b', 'c'], null, null, false, false, null]], + 46631 => [[['_route' => '_887'], ['a', 'b', 'c'], null, null, false, false, null]], + 46681 => [[['_route' => '_800'], ['a', 'b', 'c'], null, null, false, false, null]], + 46730 => [[['_route' => '_826'], ['a', 'b', 'c'], null, null, false, false, null]], + 46779 => [[['_route' => '_881'], ['a', 'b', 'c'], null, null, false, false, null]], + 46828 => [[['_route' => '_886'], ['a', 'b', 'c'], null, null, false, false, null]], + 46877 => [[['_route' => '_938'], ['a', 'b', 'c'], null, null, false, false, null]], + 46935 => [[['_route' => '_540'], ['a', 'b', 'c'], null, null, false, false, null]], + 46983 => [[['_route' => '_643'], ['a', 'b', 'c'], null, null, false, false, null]], + 47033 => [[['_route' => '_544'], ['a', 'b', 'c'], null, null, false, false, null]], + 47082 => [[['_route' => '_552'], ['a', 'b', 'c'], null, null, false, false, null]], + 47134 => [[['_route' => '_567'], ['a', 'b', 'c'], null, null, false, false, null]], + 47182 => [[['_route' => '_608'], ['a', 'b', 'c'], null, null, false, false, null]], + 47230 => [[['_route' => '_698'], ['a', 'b', 'c'], null, null, false, false, null]], + 47278 => [[['_route' => '_988'], ['a', 'b', 'c'], null, null, false, false, null]], + 47331 => [[['_route' => '_583'], ['a', 'b', 'c'], null, null, false, false, null]], + 47379 => [[['_route' => '_998'], ['a', 'b', 'c'], null, null, false, false, null]], + 47432 => [[['_route' => '_604'], ['a', 'b', 'c'], null, null, false, false, null]], + 47480 => [[['_route' => '_630'], ['a', 'b', 'c'], null, null, false, false, null]], + 47528 => [[['_route' => '_706'], ['a', 'b', 'c'], null, null, false, false, null]], + 47576 => [[['_route' => '_976'], ['a', 'b', 'c'], null, null, false, false, null]], + 47629 => [[['_route' => '_673'], ['a', 'b', 'c'], null, null, false, false, null]], + 47677 => [[['_route' => '_678'], ['a', 'b', 'c'], null, null, false, false, null]], + 47725 => [[['_route' => '_931'], ['a', 'b', 'c'], null, null, false, false, null]], + 47775 => [[['_route' => '_751'], ['a', 'b', 'c'], null, null, false, false, null]], + 47824 => [[['_route' => '_766'], ['a', 'b', 'c'], null, null, false, false, null]], + 47876 => [[['_route' => '_792'], ['a', 'b', 'c'], null, null, false, false, null]], + 47924 => [[['_route' => '_814'], ['a', 'b', 'c'], null, null, false, false, null]], + 47974 => [[['_route' => '_798'], ['a', 'b', 'c'], null, null, false, false, null]], + 48026 => [[['_route' => '_851'], ['a', 'b', 'c'], null, null, false, false, null]], + 48074 => [[['_route' => '_941'], ['a', 'b', 'c'], null, null, false, false, null]], + 48122 => [[['_route' => '_953'], ['a', 'b', 'c'], null, null, false, false, null]], + 48170 => [[['_route' => '_975'], ['a', 'b', 'c'], null, null, false, false, null]], + 48220 => [[['_route' => '_873'], ['a', 'b', 'c'], null, null, false, false, null]], + 48269 => [[['_route' => '_936'], ['a', 'b', 'c'], null, null, false, false, null]], + 48318 => [[['_route' => '_994'], ['a', 'b', 'c'], null, null, false, false, null]], + 48376 => [[['_route' => '_562'], ['a', 'b', 'c'], null, null, false, false, null]], + 48424 => [[['_route' => '_770'], ['a', 'b', 'c'], null, null, false, false, null]], + 48475 => [[['_route' => '_774'], ['a', 'b', 'c'], null, null, false, false, null]], + 48522 => [[['_route' => '_966'], ['a', 'b', 'c'], null, null, false, false, null]], + 48573 => [[['_route' => '_582'], ['a', 'b', 'c'], null, null, false, false, null]], + 48625 => [[['_route' => '_606'], ['a', 'b', 'c'], null, null, false, false, null]], + 48673 => [[['_route' => '_648'], ['a', 'b', 'c'], null, null, false, false, null]], + 48723 => [[['_route' => '_624'], ['a', 'b', 'c'], null, null, false, false, null]], + 48775 => [[['_route' => '_626'], ['a', 'b', 'c'], null, null, false, false, null]], + 48823 => [[['_route' => '_821'], ['a', 'b', 'c'], null, null, false, false, null]], + 48873 => [[['_route' => '_628'], ['a', 'b', 'c'], null, null, false, false, null]], + 48922 => [[['_route' => '_638'], ['a', 'b', 'c'], null, null, false, false, null]], + 48974 => [[['_route' => '_640'], ['a', 'b', 'c'], null, null, false, false, null]], + 49022 => [[['_route' => '_990'], ['a', 'b', 'c'], null, null, false, false, null]], + 49072 => [[['_route' => '_705'], ['a', 'b', 'c'], null, null, false, false, null]], + 49121 => [[['_route' => '_757'], ['a', 'b', 'c'], null, null, false, false, null]], + 49176 => [[['_route' => '_785'], ['a', 'b', 'c'], null, null, false, false, null]], + 49223 => [[['_route' => '_875'], ['a', 'b', 'c'], null, null, false, false, null]], + 49270 => [[['_route' => '_894'], ['a', 'b', 'c'], null, null, false, false, null]], + 49319 => [[['_route' => '_945'], ['a', 'b', 'c'], null, null, false, false, null]], + 49375 => [[['_route' => '_816'], ['a', 'b', 'c'], null, null, false, false, null]], + 49422 => [[['_route' => '_872'], ['a', 'b', 'c'], null, null, false, false, null]], + 49471 => [[['_route' => '_921'], ['a', 'b', 'c'], null, null, false, false, null]], + 49519 => [[['_route' => '_960'], ['a', 'b', 'c'], null, null, false, false, null]], + 49567 => [[['_route' => '_974'], ['a', 'b', 'c'], null, null, false, false, null]], + 49620 => [[['_route' => '_835'], ['a', 'b', 'c'], null, null, false, false, null]], + 49668 => [[['_route' => '_934'], ['a', 'b', 'c'], null, null, false, false, null]], + 49718 => [ + [['_route' => '_869'], ['a', 'b', 'c'], null, null, false, false, null], + [null, null, null, null, false, false, 0], + ], + ]; + } +} diff --git a/vendor/symfony/routing/Tests/Fixtures/dumper/url_matcher11.php b/vendor/symfony/routing/Tests/Fixtures/dumper/url_matcher11.php new file mode 100644 index 0000000000000000000000000000000000000000..c3929d6e63056997e29d40de0789e1b8b991353f --- /dev/null +++ b/vendor/symfony/routing/Tests/Fixtures/dumper/url_matcher11.php @@ -0,0 +1,69 @@ +<?php + +use Symfony\Component\Routing\Matcher\Dumper\CompiledUrlMatcherTrait; +use Symfony\Component\Routing\RequestContext; + +/** + * This class has been auto-generated + * by the Symfony Routing Component. + */ +class ProjectUrlMatcher extends Symfony\Component\Routing\Tests\Fixtures\RedirectableUrlMatcher +{ + use CompiledUrlMatcherTrait; + + public function __construct(RequestContext $context) + { + $this->context = $context; + $this->regexpList = [ + 0 => '{^(?' + .'|/(en|fr)/(?' + .'|admin/post(?' + .'|(*:32)' + .'|/(?' + .'|new(*:46)' + .'|(\\d+)(*:58)' + .'|(\\d+)/edit(*:75)' + .'|(\\d+)/delete(*:94)' + .')' + .')' + .'|blog(?' + .'|(*:110)' + .'|/(?' + .'|rss\\.xml(*:130)' + .'|p(?' + .'|age/([^/]++)(*:154)' + .'|osts/([^/]++)(*:175)' + .')' + .'|comments/(\\d+)/new(*:202)' + .'|search(*:216)' + .')' + .')' + .'|log(?' + .'|in(*:234)' + .'|out(*:245)' + .')' + .')' + .'|/(en|fr)?(*:264)' + .')/?$}sD', + ]; + $this->dynamicRoutes = [ + 32 => [[['_route' => 'a', '_locale' => 'en'], ['_locale'], null, null, true, false, null]], + 46 => [[['_route' => 'b', '_locale' => 'en'], ['_locale'], null, null, false, false, null]], + 58 => [[['_route' => 'c', '_locale' => 'en'], ['_locale', 'id'], null, null, false, true, null]], + 75 => [[['_route' => 'd', '_locale' => 'en'], ['_locale', 'id'], null, null, false, false, null]], + 94 => [[['_route' => 'e', '_locale' => 'en'], ['_locale', 'id'], null, null, false, false, null]], + 110 => [[['_route' => 'f', '_locale' => 'en'], ['_locale'], null, null, true, false, null]], + 130 => [[['_route' => 'g', '_locale' => 'en'], ['_locale'], null, null, false, false, null]], + 154 => [[['_route' => 'h', '_locale' => 'en'], ['_locale', 'page'], null, null, false, true, null]], + 175 => [[['_route' => 'i', '_locale' => 'en'], ['_locale', 'page'], null, null, false, true, null]], + 202 => [[['_route' => 'j', '_locale' => 'en'], ['_locale', 'id'], null, null, false, false, null]], + 216 => [[['_route' => 'k', '_locale' => 'en'], ['_locale'], null, null, false, false, null]], + 234 => [[['_route' => 'l', '_locale' => 'en'], ['_locale'], null, null, false, false, null]], + 245 => [[['_route' => 'm', '_locale' => 'en'], ['_locale'], null, null, false, false, null]], + 264 => [ + [['_route' => 'n', '_locale' => 'en'], ['_locale'], null, null, false, true, null], + [null, null, null, null, false, false, 0], + ], + ]; + } +} diff --git a/vendor/symfony/routing/Tests/Fixtures/dumper/url_matcher12.php b/vendor/symfony/routing/Tests/Fixtures/dumper/url_matcher12.php new file mode 100644 index 0000000000000000000000000000000000000000..77e52992deca5b0b85e346b361a1f24552e1c731 --- /dev/null +++ b/vendor/symfony/routing/Tests/Fixtures/dumper/url_matcher12.php @@ -0,0 +1,49 @@ +<?php + +use Symfony\Component\Routing\Matcher\Dumper\CompiledUrlMatcherTrait; +use Symfony\Component\Routing\RequestContext; + +/** + * This class has been auto-generated + * by the Symfony Routing Component. + */ +class ProjectUrlMatcher extends Symfony\Component\Routing\Matcher\UrlMatcher +{ + use CompiledUrlMatcherTrait; + + public function __construct(RequestContext $context) + { + $this->context = $context; + $this->regexpList = [ + 0 => '{^(?' + .'|/abc([^/]++)/(?' + .'|1(?' + .'|(*:27)' + .'|0(?' + .'|(*:38)' + .'|0(*:46)' + .')' + .')' + .'|2(?' + .'|(*:59)' + .'|0(?' + .'|(*:70)' + .'|0(*:78)' + .')' + .')' + .')' + .')/?$}sD', + ]; + $this->dynamicRoutes = [ + 27 => [[['_route' => 'r1'], ['foo'], null, null, false, false, null]], + 38 => [[['_route' => 'r10'], ['foo'], null, null, false, false, null]], + 46 => [[['_route' => 'r100'], ['foo'], null, null, false, false, null]], + 59 => [[['_route' => 'r2'], ['foo'], null, null, false, false, null]], + 70 => [[['_route' => 'r20'], ['foo'], null, null, false, false, null]], + 78 => [ + [['_route' => 'r200'], ['foo'], null, null, false, false, null], + [null, null, null, null, false, false, 0], + ], + ]; + } +} diff --git a/vendor/symfony/routing/Tests/Fixtures/dumper/url_matcher13.php b/vendor/symfony/routing/Tests/Fixtures/dumper/url_matcher13.php new file mode 100644 index 0000000000000000000000000000000000000000..8e54cc87580e4164bb0f0bb77251dfb1b320c8ef --- /dev/null +++ b/vendor/symfony/routing/Tests/Fixtures/dumper/url_matcher13.php @@ -0,0 +1,35 @@ +<?php + +use Symfony\Component\Routing\Matcher\Dumper\CompiledUrlMatcherTrait; +use Symfony\Component\Routing\RequestContext; + +/** + * This class has been auto-generated + * by the Symfony Routing Component. + */ +class ProjectUrlMatcher extends Symfony\Component\Routing\Matcher\UrlMatcher +{ + use CompiledUrlMatcherTrait; + + public function __construct(RequestContext $context) + { + $this->context = $context; + $this->matchHost = true; + $this->regexpList = [ + 0 => '{^(?' + .'|(?i:([^\\.]++)\\.exampple\\.com)\\.(?' + .'|/abc([^/]++)(?' + .'|(*:56)' + .')' + .')' + .')/?$}sD', + ]; + $this->dynamicRoutes = [ + 56 => [ + [['_route' => 'r1'], ['foo', 'foo'], null, null, false, true, null], + [['_route' => 'r2'], ['foo', 'foo'], null, null, false, true, null], + [null, null, null, null, false, false, 0], + ], + ]; + } +} diff --git a/vendor/symfony/routing/Tests/Fixtures/dumper/url_matcher2.php b/vendor/symfony/routing/Tests/Fixtures/dumper/url_matcher2.php index 49ce082a817333d614e0326f0aa7bdc2aa60be8f..155882448d1ef16465d0f87fd5aa60ecf796a84e 100644 --- a/vendor/symfony/routing/Tests/Fixtures/dumper/url_matcher2.php +++ b/vendor/symfony/routing/Tests/Fixtures/dumper/url_matcher2.php @@ -1,7 +1,6 @@ <?php -use Symfony\Component\Routing\Exception\MethodNotAllowedException; -use Symfony\Component\Routing\Exception\ResourceNotFoundException; +use Symfony\Component\Routing\Matcher\Dumper\CompiledUrlMatcherTrait; use Symfony\Component\Routing\RequestContext; /** @@ -10,340 +9,110 @@ use Symfony\Component\Routing\RequestContext; */ class ProjectUrlMatcher extends Symfony\Component\Routing\Tests\Fixtures\RedirectableUrlMatcher { + use CompiledUrlMatcherTrait; + public function __construct(RequestContext $context) { $this->context = $context; - } - - public function match($rawPathinfo) - { - $allow = array(); - $pathinfo = rawurldecode($rawPathinfo); - $trimmedPathinfo = rtrim($pathinfo, '/'); - $context = $this->context; - $request = $this->request; - $requestMethod = $canonicalMethod = $context->getMethod(); - $scheme = $context->getScheme(); - - if ('HEAD' === $requestMethod) { - $canonicalMethod = 'GET'; - } - - - if (0 === strpos($pathinfo, '/foo')) { - // foo - if (preg_match('#^/foo/(?P<bar>baz|symfony)$#s', $pathinfo, $matches)) { - return $this->mergeDefaults(array_replace($matches, array('_route' => 'foo')), array ( 'def' => 'test',)); - } - - // foofoo - if ('/foofoo' === $pathinfo) { - return array ( 'def' => 'test', '_route' => 'foofoo',); - } - - } - - elseif (0 === strpos($pathinfo, '/bar')) { - // bar - if (preg_match('#^/bar/(?P<foo>[^/]++)$#s', $pathinfo, $matches)) { - if ('GET' !== $canonicalMethod) { - $allow[] = 'GET'; - goto not_bar; - } - - return $this->mergeDefaults(array_replace($matches, array('_route' => 'bar')), array ()); - } - not_bar: - - // barhead - if (0 === strpos($pathinfo, '/barhead') && preg_match('#^/barhead/(?P<foo>[^/]++)$#s', $pathinfo, $matches)) { - if ('GET' !== $canonicalMethod) { - $allow[] = 'GET'; - goto not_barhead; - } - - return $this->mergeDefaults(array_replace($matches, array('_route' => 'barhead')), array ()); - } - not_barhead: - - } - - elseif (0 === strpos($pathinfo, '/test')) { - if (0 === strpos($pathinfo, '/test/baz')) { - // baz - if ('/test/baz' === $pathinfo) { - return array('_route' => 'baz'); - } - - // baz2 - if ('/test/baz.html' === $pathinfo) { - return array('_route' => 'baz2'); - } - - // baz3 - if ('/test/baz3' === $trimmedPathinfo) { - $ret = array('_route' => 'baz3'); - if (substr($pathinfo, -1) !== '/') { - return array_replace($ret, $this->redirect($rawPathinfo.'/', 'baz3')); - } - - return $ret; - } - - } - - // baz4 - if (preg_match('#^/test/(?P<foo>[^/]++)/?$#s', $pathinfo, $matches)) { - $ret = $this->mergeDefaults(array_replace($matches, array('_route' => 'baz4')), array ()); - if (substr($pathinfo, -1) !== '/') { - return array_replace($ret, $this->redirect($rawPathinfo.'/', 'baz4')); - } - - return $ret; - } - - // baz5 - if (preg_match('#^/test/(?P<foo>[^/]++)/$#s', $pathinfo, $matches)) { - if ('POST' !== $canonicalMethod) { - $allow[] = 'POST'; - goto not_baz5; - } - - return $this->mergeDefaults(array_replace($matches, array('_route' => 'baz5')), array ()); - } - not_baz5: - - // baz.baz6 - if (preg_match('#^/test/(?P<foo>[^/]++)/$#s', $pathinfo, $matches)) { - if ('PUT' !== $canonicalMethod) { - $allow[] = 'PUT'; - goto not_bazbaz6; - } - - return $this->mergeDefaults(array_replace($matches, array('_route' => 'baz.baz6')), array ()); - } - not_bazbaz6: - - } - - // quoter - if (preg_match('#^/(?P<quoter>[\']+)$#s', $pathinfo, $matches)) { - return $this->mergeDefaults(array_replace($matches, array('_route' => 'quoter')), array ()); - } - - // space - if ('/spa ce' === $pathinfo) { - return array('_route' => 'space'); - } - - if (0 === strpos($pathinfo, '/a')) { - if (0 === strpos($pathinfo, '/a/b\'b')) { - // foo1 - if (preg_match('#^/a/b\'b/(?P<foo>[^/]++)$#s', $pathinfo, $matches)) { - return $this->mergeDefaults(array_replace($matches, array('_route' => 'foo1')), array ()); - } - - // bar1 - if (preg_match('#^/a/b\'b/(?P<bar>[^/]++)$#s', $pathinfo, $matches)) { - return $this->mergeDefaults(array_replace($matches, array('_route' => 'bar1')), array ()); - } - - } - - // overridden - if (preg_match('#^/a/(?P<var>.*)$#s', $pathinfo, $matches)) { - return $this->mergeDefaults(array_replace($matches, array('_route' => 'overridden')), array ()); - } - - if (0 === strpos($pathinfo, '/a/b\'b')) { - // foo2 - if (preg_match('#^/a/b\'b/(?P<foo1>[^/]++)$#s', $pathinfo, $matches)) { - return $this->mergeDefaults(array_replace($matches, array('_route' => 'foo2')), array ()); - } - - // bar2 - if (preg_match('#^/a/b\'b/(?P<bar1>[^/]++)$#s', $pathinfo, $matches)) { - return $this->mergeDefaults(array_replace($matches, array('_route' => 'bar2')), array ()); - } - - } - - } - - elseif (0 === strpos($pathinfo, '/multi')) { - // helloWorld - if (0 === strpos($pathinfo, '/multi/hello') && preg_match('#^/multi/hello(?:/(?P<who>[^/]++))?$#s', $pathinfo, $matches)) { - return $this->mergeDefaults(array_replace($matches, array('_route' => 'helloWorld')), array ( 'who' => 'World!',)); - } - - // hey - if ('/multi/hey' === $trimmedPathinfo) { - $ret = array('_route' => 'hey'); - if (substr($pathinfo, -1) !== '/') { - return array_replace($ret, $this->redirect($rawPathinfo.'/', 'hey')); - } - - return $ret; - } - - // overridden2 - if ('/multi/new' === $pathinfo) { - return array('_route' => 'overridden2'); - } - - } - - // foo3 - if (preg_match('#^/(?P<_locale>[^/]++)/b/(?P<foo>[^/]++)$#s', $pathinfo, $matches)) { - return $this->mergeDefaults(array_replace($matches, array('_route' => 'foo3')), array ()); - } - - // bar3 - if (preg_match('#^/(?P<_locale>[^/]++)/b/(?P<bar>[^/]++)$#s', $pathinfo, $matches)) { - return $this->mergeDefaults(array_replace($matches, array('_route' => 'bar3')), array ()); - } - - if (0 === strpos($pathinfo, '/aba')) { - // ababa - if ('/ababa' === $pathinfo) { - return array('_route' => 'ababa'); - } - - // foo4 - if (preg_match('#^/aba/(?P<foo>[^/]++)$#s', $pathinfo, $matches)) { - return $this->mergeDefaults(array_replace($matches, array('_route' => 'foo4')), array ()); - } - - } - - $host = $context->getHost(); - - if (preg_match('#^a\\.example\\.com$#si', $host, $hostMatches)) { - // route1 - if ('/route1' === $pathinfo) { - return array('_route' => 'route1'); - } - - // route2 - if ('/c2/route2' === $pathinfo) { - return array('_route' => 'route2'); - } - - } - - if (preg_match('#^b\\.example\\.com$#si', $host, $hostMatches)) { - // route3 - if ('/c2/route3' === $pathinfo) { - return array('_route' => 'route3'); - } - - } - - if (preg_match('#^a\\.example\\.com$#si', $host, $hostMatches)) { - // route4 - if ('/route4' === $pathinfo) { - return array('_route' => 'route4'); - } - - } - - if (preg_match('#^c\\.example\\.com$#si', $host, $hostMatches)) { - // route5 - if ('/route5' === $pathinfo) { - return array('_route' => 'route5'); - } - - } - - // route6 - if ('/route6' === $pathinfo) { - return array('_route' => 'route6'); - } - - if (preg_match('#^(?P<var1>[^\\.]++)\\.example\\.com$#si', $host, $hostMatches)) { - if (0 === strpos($pathinfo, '/route1')) { - // route11 - if ('/route11' === $pathinfo) { - return $this->mergeDefaults(array_replace($hostMatches, array('_route' => 'route11')), array ()); - } - - // route12 - if ('/route12' === $pathinfo) { - return $this->mergeDefaults(array_replace($hostMatches, array('_route' => 'route12')), array ( 'var1' => 'val',)); - } - - // route13 - if (0 === strpos($pathinfo, '/route13') && preg_match('#^/route13/(?P<name>[^/]++)$#s', $pathinfo, $matches)) { - return $this->mergeDefaults(array_replace($hostMatches, $matches, array('_route' => 'route13')), array ()); - } - - // route14 - if (0 === strpos($pathinfo, '/route14') && preg_match('#^/route14/(?P<name>[^/]++)$#s', $pathinfo, $matches)) { - return $this->mergeDefaults(array_replace($hostMatches, $matches, array('_route' => 'route14')), array ( 'var1' => 'val',)); - } - - } - - } - - if (preg_match('#^c\\.example\\.com$#si', $host, $hostMatches)) { - // route15 - if (0 === strpos($pathinfo, '/route15') && preg_match('#^/route15/(?P<name>[^/]++)$#s', $pathinfo, $matches)) { - return $this->mergeDefaults(array_replace($matches, array('_route' => 'route15')), array ()); - } - - } - - // route16 - if (0 === strpos($pathinfo, '/route16') && preg_match('#^/route16/(?P<name>[^/]++)$#s', $pathinfo, $matches)) { - return $this->mergeDefaults(array_replace($matches, array('_route' => 'route16')), array ( 'var1' => 'val',)); - } - - // route17 - if ('/route17' === $pathinfo) { - return array('_route' => 'route17'); - } - - // a - if ('/a/a...' === $pathinfo) { - return array('_route' => 'a'); - } - - if (0 === strpos($pathinfo, '/a/b')) { - // b - if (preg_match('#^/a/b/(?P<var>[^/]++)$#s', $pathinfo, $matches)) { - return $this->mergeDefaults(array_replace($matches, array('_route' => 'b')), array ()); - } - - // c - if (0 === strpos($pathinfo, '/a/b/c') && preg_match('#^/a/b/c/(?P<var>[^/]++)$#s', $pathinfo, $matches)) { - return $this->mergeDefaults(array_replace($matches, array('_route' => 'c')), array ()); - } - - } - - // secure - if ('/secure' === $pathinfo) { - $ret = array('_route' => 'secure'); - $requiredSchemes = array ( 'https' => 0,); - if (!isset($requiredSchemes[$scheme])) { - return array_replace($ret, $this->redirect($rawPathinfo, 'secure', key($requiredSchemes))); - } - - return $ret; - } - - // nonsecure - if ('/nonsecure' === $pathinfo) { - $ret = array('_route' => 'nonsecure'); - $requiredSchemes = array ( 'http' => 0,); - if (!isset($requiredSchemes[$scheme])) { - return array_replace($ret, $this->redirect($rawPathinfo, 'nonsecure', key($requiredSchemes))); - } - - return $ret; - } - - throw 0 < count($allow) ? new MethodNotAllowedException(array_unique($allow)) : new ResourceNotFoundException(); + $this->matchHost = true; + $this->staticRoutes = [ + '/test/baz' => [[['_route' => 'baz'], null, null, null, false, false, null]], + '/test/baz.html' => [[['_route' => 'baz2'], null, null, null, false, false, null]], + '/test/baz3' => [[['_route' => 'baz3'], null, null, null, true, false, null]], + '/foofoo' => [[['_route' => 'foofoo', 'def' => 'test'], null, null, null, false, false, null]], + '/spa ce' => [[['_route' => 'space'], null, null, null, false, false, null]], + '/multi/new' => [[['_route' => 'overridden2'], null, null, null, false, false, null]], + '/multi/hey' => [[['_route' => 'hey'], null, null, null, true, false, null]], + '/ababa' => [[['_route' => 'ababa'], null, null, null, false, false, null]], + '/route1' => [[['_route' => 'route1'], 'a.example.com', null, null, false, false, null]], + '/c2/route2' => [[['_route' => 'route2'], 'a.example.com', null, null, false, false, null]], + '/route4' => [[['_route' => 'route4'], 'a.example.com', null, null, false, false, null]], + '/c2/route3' => [[['_route' => 'route3'], 'b.example.com', null, null, false, false, null]], + '/route5' => [[['_route' => 'route5'], 'c.example.com', null, null, false, false, null]], + '/route6' => [[['_route' => 'route6'], null, null, null, false, false, null]], + '/route11' => [[['_route' => 'route11'], '#^(?P<var1>[^\\.]++)\\.example\\.com$#sDi', null, null, false, false, null]], + '/route12' => [[['_route' => 'route12', 'var1' => 'val'], '#^(?P<var1>[^\\.]++)\\.example\\.com$#sDi', null, null, false, false, null]], + '/route17' => [[['_route' => 'route17'], null, null, null, false, false, null]], + '/secure' => [[['_route' => 'secure'], null, null, ['https' => 0], false, false, null]], + '/nonsecure' => [[['_route' => 'nonsecure'], null, null, ['http' => 0], false, false, null]], + ]; + $this->regexpList = [ + 0 => '{^(?' + .'|(?:(?:[^./]*+\\.)++)(?' + .'|/foo/(baz|symfony)(*:47)' + .'|/bar(?' + .'|/([^/]++)(*:70)' + .'|head/([^/]++)(*:90)' + .')' + .'|/test/([^/]++)(?' + .'|(*:115)' + .')' + .'|/([\']+)(*:131)' + .'|/a/(?' + .'|b\'b/([^/]++)(?' + .'|(*:160)' + .'|(*:168)' + .')' + .'|(.*)(*:181)' + .'|b\'b/([^/]++)(?' + .'|(*:204)' + .'|(*:212)' + .')' + .')' + .'|/multi/hello(?:/([^/]++))?(*:248)' + .'|/([^/]++)/b/([^/]++)(?' + .'|(*:279)' + .'|(*:287)' + .')' + .'|/aba/([^/]++)(*:309)' + .')|(?i:([^\\.]++)\\.example\\.com)\\.(?' + .'|/route1(?' + .'|3/([^/]++)(*:371)' + .'|4/([^/]++)(*:389)' + .')' + .')|(?i:c\\.example\\.com)\\.(?' + .'|/route15/([^/]++)(*:441)' + .')|(?:(?:[^./]*+\\.)++)(?' + .'|/route16/([^/]++)(*:489)' + .'|/a/(?' + .'|a\\.\\.\\.(*:510)' + .'|b/(?' + .'|([^/]++)(*:531)' + .'|c/([^/]++)(*:549)' + .')' + .')' + .')' + .')/?$}sD', + ]; + $this->dynamicRoutes = [ + 47 => [[['_route' => 'foo', 'def' => 'test'], ['bar'], null, null, false, true, null]], + 70 => [[['_route' => 'bar'], ['foo'], ['GET' => 0, 'HEAD' => 1], null, false, true, null]], + 90 => [[['_route' => 'barhead'], ['foo'], ['GET' => 0], null, false, true, null]], + 115 => [ + [['_route' => 'baz4'], ['foo'], null, null, true, true, null], + [['_route' => 'baz5'], ['foo'], ['POST' => 0], null, true, true, null], + [['_route' => 'baz.baz6'], ['foo'], ['PUT' => 0], null, true, true, null], + ], + 131 => [[['_route' => 'quoter'], ['quoter'], null, null, false, true, null]], + 160 => [[['_route' => 'foo1'], ['foo'], ['PUT' => 0], null, false, true, null]], + 168 => [[['_route' => 'bar1'], ['bar'], null, null, false, true, null]], + 181 => [[['_route' => 'overridden'], ['var'], null, null, false, true, null]], + 204 => [[['_route' => 'foo2'], ['foo1'], null, null, false, true, null]], + 212 => [[['_route' => 'bar2'], ['bar1'], null, null, false, true, null]], + 248 => [[['_route' => 'helloWorld', 'who' => 'World!'], ['who'], null, null, false, true, null]], + 279 => [[['_route' => 'foo3'], ['_locale', 'foo'], null, null, false, true, null]], + 287 => [[['_route' => 'bar3'], ['_locale', 'bar'], null, null, false, true, null]], + 309 => [[['_route' => 'foo4'], ['foo'], null, null, false, true, null]], + 371 => [[['_route' => 'route13'], ['var1', 'name'], null, null, false, true, null]], + 389 => [[['_route' => 'route14', 'var1' => 'val'], ['var1', 'name'], null, null, false, true, null]], + 441 => [[['_route' => 'route15'], ['name'], null, null, false, true, null]], + 489 => [[['_route' => 'route16', 'var1' => 'val'], ['name'], null, null, false, true, null]], + 510 => [[['_route' => 'a'], [], null, null, false, false, null]], + 531 => [[['_route' => 'b'], ['var'], null, null, false, true, null]], + 549 => [ + [['_route' => 'c'], ['var'], null, null, false, true, null], + [null, null, null, null, false, false, 0], + ], + ]; } } diff --git a/vendor/symfony/routing/Tests/Fixtures/dumper/url_matcher3.php b/vendor/symfony/routing/Tests/Fixtures/dumper/url_matcher3.php index ae54956312554df800cab6882742788cf8a6c907..efafbb24695e6908d038bc2ccf838820d2f0f1fe 100644 --- a/vendor/symfony/routing/Tests/Fixtures/dumper/url_matcher3.php +++ b/vendor/symfony/routing/Tests/Fixtures/dumper/url_matcher3.php @@ -1,7 +1,6 @@ <?php -use Symfony\Component\Routing\Exception\MethodNotAllowedException; -use Symfony\Component\Routing\Exception\ResourceNotFoundException; +use Symfony\Component\Routing\Matcher\Dumper\CompiledUrlMatcherTrait; use Symfony\Component\Routing\RequestContext; /** @@ -10,44 +9,30 @@ use Symfony\Component\Routing\RequestContext; */ class ProjectUrlMatcher extends Symfony\Component\Routing\Matcher\UrlMatcher { + use CompiledUrlMatcherTrait; + public function __construct(RequestContext $context) { $this->context = $context; - } - - public function match($rawPathinfo) - { - $allow = array(); - $pathinfo = rawurldecode($rawPathinfo); - $trimmedPathinfo = rtrim($pathinfo, '/'); - $context = $this->context; - $request = $this->request; - $requestMethod = $canonicalMethod = $context->getMethod(); - $scheme = $context->getScheme(); - - if ('HEAD' === $requestMethod) { - $canonicalMethod = 'GET'; - } - - - if (0 === strpos($pathinfo, '/rootprefix')) { - // static - if ('/rootprefix/test' === $pathinfo) { - return array('_route' => 'static'); - } - - // dynamic - if (preg_match('#^/rootprefix/(?P<var>[^/]++)$#s', $pathinfo, $matches)) { - return $this->mergeDefaults(array_replace($matches, array('_route' => 'dynamic')), array ()); + $this->staticRoutes = [ + '/rootprefix/test' => [[['_route' => 'static'], null, null, null, false, false, null]], + '/with-condition' => [[['_route' => 'with-condition'], null, null, null, false, false, -1]], + ]; + $this->regexpList = [ + 0 => '{^(?' + .'|/rootprefix/([^/]++)(*:27)' + .')/?$}sD', + ]; + $this->dynamicRoutes = [ + 27 => [ + [['_route' => 'dynamic'], ['var'], null, null, false, true, null], + [null, null, null, null, false, false, 0], + ], + ]; + $this->checkCondition = static function ($condition, $context, $request) { + switch ($condition) { + case -1: return ($context->getMethod() == "GET"); } - - } - - // with-condition - if ('/with-condition' === $pathinfo && ($context->getMethod() == "GET")) { - return array('_route' => 'with-condition'); - } - - throw 0 < count($allow) ? new MethodNotAllowedException(array_unique($allow)) : new ResourceNotFoundException(); + }; } } diff --git a/vendor/symfony/routing/Tests/Fixtures/dumper/url_matcher4.php b/vendor/symfony/routing/Tests/Fixtures/dumper/url_matcher4.php index 50da489fb2a0b7883608abbd482d957c5c5ea3d1..605901cda28c8e539186b9b8177f8071fdffb6ae 100644 --- a/vendor/symfony/routing/Tests/Fixtures/dumper/url_matcher4.php +++ b/vendor/symfony/routing/Tests/Fixtures/dumper/url_matcher4.php @@ -1,7 +1,6 @@ <?php -use Symfony\Component\Routing\Exception\MethodNotAllowedException; -use Symfony\Component\Routing\Exception\ResourceNotFoundException; +use Symfony\Component\Routing\Matcher\Dumper\CompiledUrlMatcherTrait; use Symfony\Component\Routing\RequestContext; /** @@ -10,95 +9,20 @@ use Symfony\Component\Routing\RequestContext; */ class ProjectUrlMatcher extends Symfony\Component\Routing\Matcher\UrlMatcher { + use CompiledUrlMatcherTrait; + public function __construct(RequestContext $context) { $this->context = $context; - } - - public function match($rawPathinfo) - { - $allow = array(); - $pathinfo = rawurldecode($rawPathinfo); - $trimmedPathinfo = rtrim($pathinfo, '/'); - $context = $this->context; - $request = $this->request; - $requestMethod = $canonicalMethod = $context->getMethod(); - $scheme = $context->getScheme(); - - if ('HEAD' === $requestMethod) { - $canonicalMethod = 'GET'; - } - - - // just_head - if ('/just_head' === $pathinfo) { - if ('HEAD' !== $requestMethod) { - $allow[] = 'HEAD'; - goto not_just_head; - } - - return array('_route' => 'just_head'); - } - not_just_head: - - // head_and_get - if ('/head_and_get' === $pathinfo) { - if ('GET' !== $canonicalMethod) { - $allow[] = 'GET'; - goto not_head_and_get; - } - - return array('_route' => 'head_and_get'); - } - not_head_and_get: - - // get_and_head - if ('/get_and_head' === $pathinfo) { - if ('GET' !== $canonicalMethod) { - $allow[] = 'GET'; - goto not_get_and_head; - } - - return array('_route' => 'get_and_head'); - } - not_get_and_head: - - // post_and_head - if ('/post_and_get' === $pathinfo) { - if (!in_array($requestMethod, array('POST', 'HEAD'))) { - $allow = array_merge($allow, array('POST', 'HEAD')); - goto not_post_and_head; - } - - return array('_route' => 'post_and_head'); - } - not_post_and_head: - - if (0 === strpos($pathinfo, '/put_and_post')) { - // put_and_post - if ('/put_and_post' === $pathinfo) { - if (!in_array($requestMethod, array('PUT', 'POST'))) { - $allow = array_merge($allow, array('PUT', 'POST')); - goto not_put_and_post; - } - - return array('_route' => 'put_and_post'); - } - not_put_and_post: - - // put_and_get_and_head - if ('/put_and_post' === $pathinfo) { - if (!in_array($canonicalMethod, array('PUT', 'GET'))) { - $allow = array_merge($allow, array('PUT', 'GET')); - goto not_put_and_get_and_head; - } - - return array('_route' => 'put_and_get_and_head'); - } - not_put_and_get_and_head: - - } - - throw 0 < count($allow) ? new MethodNotAllowedException(array_unique($allow)) : new ResourceNotFoundException(); + $this->staticRoutes = [ + '/just_head' => [[['_route' => 'just_head'], null, ['HEAD' => 0], null, false, false, null]], + '/head_and_get' => [[['_route' => 'head_and_get'], null, ['HEAD' => 0, 'GET' => 1], null, false, false, null]], + '/get_and_head' => [[['_route' => 'get_and_head'], null, ['GET' => 0, 'HEAD' => 1], null, false, false, null]], + '/post_and_head' => [[['_route' => 'post_and_head'], null, ['POST' => 0, 'HEAD' => 1], null, false, false, null]], + '/put_and_post' => [ + [['_route' => 'put_and_post'], null, ['PUT' => 0, 'POST' => 1], null, false, false, null], + [['_route' => 'put_and_get_and_head'], null, ['PUT' => 0, 'GET' => 1, 'HEAD' => 2], null, false, false, null], + ], + ]; } } diff --git a/vendor/symfony/routing/Tests/Fixtures/dumper/url_matcher5.php b/vendor/symfony/routing/Tests/Fixtures/dumper/url_matcher5.php index 51be5b0bc886fbebca6f65aee3d9ac4c4b400fb9..97fcab92dca413671701ab264a5ea23bcf98bf04 100644 --- a/vendor/symfony/routing/Tests/Fixtures/dumper/url_matcher5.php +++ b/vendor/symfony/routing/Tests/Fixtures/dumper/url_matcher5.php @@ -1,7 +1,6 @@ <?php -use Symfony\Component\Routing\Exception\MethodNotAllowedException; -use Symfony\Component\Routing\Exception\ResourceNotFoundException; +use Symfony\Component\Routing\Matcher\Dumper\CompiledUrlMatcherTrait; use Symfony\Component\Routing\RequestContext; /** @@ -10,153 +9,37 @@ use Symfony\Component\Routing\RequestContext; */ class ProjectUrlMatcher extends Symfony\Component\Routing\Tests\Fixtures\RedirectableUrlMatcher { + use CompiledUrlMatcherTrait; + public function __construct(RequestContext $context) { $this->context = $context; - } - - public function match($rawPathinfo) - { - $allow = array(); - $pathinfo = rawurldecode($rawPathinfo); - $trimmedPathinfo = rtrim($pathinfo, '/'); - $context = $this->context; - $request = $this->request; - $requestMethod = $canonicalMethod = $context->getMethod(); - $scheme = $context->getScheme(); - - if ('HEAD' === $requestMethod) { - $canonicalMethod = 'GET'; - } - - - if (0 === strpos($pathinfo, '/a')) { - // a_first - if ('/a/11' === $pathinfo) { - return array('_route' => 'a_first'); - } - - // a_second - if ('/a/22' === $pathinfo) { - return array('_route' => 'a_second'); - } - - // a_third - if ('/a/333' === $pathinfo) { - return array('_route' => 'a_third'); - } - - } - - // a_wildcard - if (preg_match('#^/(?P<param>[^/]++)$#s', $pathinfo, $matches)) { - return $this->mergeDefaults(array_replace($matches, array('_route' => 'a_wildcard')), array ()); - } - - if (0 === strpos($pathinfo, '/a')) { - // a_fourth - if ('/a/44' === $trimmedPathinfo) { - $ret = array('_route' => 'a_fourth'); - if (substr($pathinfo, -1) !== '/') { - return array_replace($ret, $this->redirect($rawPathinfo.'/', 'a_fourth')); - } - - return $ret; - } - - // a_fifth - if ('/a/55' === $trimmedPathinfo) { - $ret = array('_route' => 'a_fifth'); - if (substr($pathinfo, -1) !== '/') { - return array_replace($ret, $this->redirect($rawPathinfo.'/', 'a_fifth')); - } - - return $ret; - } - - // a_sixth - if ('/a/66' === $trimmedPathinfo) { - $ret = array('_route' => 'a_sixth'); - if (substr($pathinfo, -1) !== '/') { - return array_replace($ret, $this->redirect($rawPathinfo.'/', 'a_sixth')); - } - - return $ret; - } - - } - - // nested_wildcard - if (0 === strpos($pathinfo, '/nested') && preg_match('#^/nested/(?P<param>[^/]++)$#s', $pathinfo, $matches)) { - return $this->mergeDefaults(array_replace($matches, array('_route' => 'nested_wildcard')), array ()); - } - - if (0 === strpos($pathinfo, '/nested/group')) { - // nested_a - if ('/nested/group/a' === $trimmedPathinfo) { - $ret = array('_route' => 'nested_a'); - if (substr($pathinfo, -1) !== '/') { - return array_replace($ret, $this->redirect($rawPathinfo.'/', 'nested_a')); - } - - return $ret; - } - - // nested_b - if ('/nested/group/b' === $trimmedPathinfo) { - $ret = array('_route' => 'nested_b'); - if (substr($pathinfo, -1) !== '/') { - return array_replace($ret, $this->redirect($rawPathinfo.'/', 'nested_b')); - } - - return $ret; - } - - // nested_c - if ('/nested/group/c' === $trimmedPathinfo) { - $ret = array('_route' => 'nested_c'); - if (substr($pathinfo, -1) !== '/') { - return array_replace($ret, $this->redirect($rawPathinfo.'/', 'nested_c')); - } - - return $ret; - } - - } - - elseif (0 === strpos($pathinfo, '/slashed/group')) { - // slashed_a - if ('/slashed/group' === $trimmedPathinfo) { - $ret = array('_route' => 'slashed_a'); - if (substr($pathinfo, -1) !== '/') { - return array_replace($ret, $this->redirect($rawPathinfo.'/', 'slashed_a')); - } - - return $ret; - } - - // slashed_b - if ('/slashed/group/b' === $trimmedPathinfo) { - $ret = array('_route' => 'slashed_b'); - if (substr($pathinfo, -1) !== '/') { - return array_replace($ret, $this->redirect($rawPathinfo.'/', 'slashed_b')); - } - - return $ret; - } - - // slashed_c - if ('/slashed/group/c' === $trimmedPathinfo) { - $ret = array('_route' => 'slashed_c'); - if (substr($pathinfo, -1) !== '/') { - return array_replace($ret, $this->redirect($rawPathinfo.'/', 'slashed_c')); - } - - return $ret; - } - - } - - throw 0 < count($allow) ? new MethodNotAllowedException(array_unique($allow)) : new ResourceNotFoundException(); + $this->staticRoutes = [ + '/a/11' => [[['_route' => 'a_first'], null, null, null, false, false, null]], + '/a/22' => [[['_route' => 'a_second'], null, null, null, false, false, null]], + '/a/333' => [[['_route' => 'a_third'], null, null, null, false, false, null]], + '/a/44' => [[['_route' => 'a_fourth'], null, null, null, true, false, null]], + '/a/55' => [[['_route' => 'a_fifth'], null, null, null, true, false, null]], + '/a/66' => [[['_route' => 'a_sixth'], null, null, null, true, false, null]], + '/nested/group/a' => [[['_route' => 'nested_a'], null, null, null, true, false, null]], + '/nested/group/b' => [[['_route' => 'nested_b'], null, null, null, true, false, null]], + '/nested/group/c' => [[['_route' => 'nested_c'], null, null, null, true, false, null]], + '/slashed/group' => [[['_route' => 'slashed_a'], null, null, null, true, false, null]], + '/slashed/group/b' => [[['_route' => 'slashed_b'], null, null, null, true, false, null]], + '/slashed/group/c' => [[['_route' => 'slashed_c'], null, null, null, true, false, null]], + ]; + $this->regexpList = [ + 0 => '{^(?' + .'|/([^/]++)(*:16)' + .'|/nested/([^/]++)(*:39)' + .')/?$}sD', + ]; + $this->dynamicRoutes = [ + 16 => [[['_route' => 'a_wildcard'], ['param'], null, null, false, true, null]], + 39 => [ + [['_route' => 'nested_wildcard'], ['param'], null, null, false, true, null], + [null, null, null, null, false, false, 0], + ], + ]; } } diff --git a/vendor/symfony/routing/Tests/Fixtures/dumper/url_matcher6.php b/vendor/symfony/routing/Tests/Fixtures/dumper/url_matcher6.php index 933525699c0e76ef3577acce45230dbf66b9f5c4..850b3bb53282bb5d23d4697ba7c2c16c4276a7b7 100644 --- a/vendor/symfony/routing/Tests/Fixtures/dumper/url_matcher6.php +++ b/vendor/symfony/routing/Tests/Fixtures/dumper/url_matcher6.php @@ -1,7 +1,6 @@ <?php -use Symfony\Component\Routing\Exception\MethodNotAllowedException; -use Symfony\Component\Routing\Exception\ResourceNotFoundException; +use Symfony\Component\Routing\Matcher\Dumper\CompiledUrlMatcherTrait; use Symfony\Component\Routing\RequestContext; /** @@ -10,190 +9,49 @@ use Symfony\Component\Routing\RequestContext; */ class ProjectUrlMatcher extends Symfony\Component\Routing\Matcher\UrlMatcher { + use CompiledUrlMatcherTrait; + public function __construct(RequestContext $context) { $this->context = $context; - } - - public function match($rawPathinfo) - { - $allow = array(); - $pathinfo = rawurldecode($rawPathinfo); - $trimmedPathinfo = rtrim($pathinfo, '/'); - $context = $this->context; - $request = $this->request; - $requestMethod = $canonicalMethod = $context->getMethod(); - $scheme = $context->getScheme(); - - if ('HEAD' === $requestMethod) { - $canonicalMethod = 'GET'; - } - - - if (0 === strpos($pathinfo, '/trailing/simple')) { - // simple_trailing_slash_no_methods - if ('/trailing/simple/no-methods/' === $pathinfo) { - return array('_route' => 'simple_trailing_slash_no_methods'); - } - - // simple_trailing_slash_GET_method - if ('/trailing/simple/get-method/' === $pathinfo) { - if ('GET' !== $canonicalMethod) { - $allow[] = 'GET'; - goto not_simple_trailing_slash_GET_method; - } - - return array('_route' => 'simple_trailing_slash_GET_method'); - } - not_simple_trailing_slash_GET_method: - - // simple_trailing_slash_HEAD_method - if ('/trailing/simple/head-method/' === $pathinfo) { - if ('HEAD' !== $requestMethod) { - $allow[] = 'HEAD'; - goto not_simple_trailing_slash_HEAD_method; - } - - return array('_route' => 'simple_trailing_slash_HEAD_method'); - } - not_simple_trailing_slash_HEAD_method: - - // simple_trailing_slash_POST_method - if ('/trailing/simple/post-method/' === $pathinfo) { - if ('POST' !== $canonicalMethod) { - $allow[] = 'POST'; - goto not_simple_trailing_slash_POST_method; - } - - return array('_route' => 'simple_trailing_slash_POST_method'); - } - not_simple_trailing_slash_POST_method: - - } - - elseif (0 === strpos($pathinfo, '/trailing/regex')) { - // regex_trailing_slash_no_methods - if (0 === strpos($pathinfo, '/trailing/regex/no-methods') && preg_match('#^/trailing/regex/no\\-methods/(?P<param>[^/]++)/$#s', $pathinfo, $matches)) { - return $this->mergeDefaults(array_replace($matches, array('_route' => 'regex_trailing_slash_no_methods')), array ()); - } - - // regex_trailing_slash_GET_method - if (0 === strpos($pathinfo, '/trailing/regex/get-method') && preg_match('#^/trailing/regex/get\\-method/(?P<param>[^/]++)/$#s', $pathinfo, $matches)) { - if ('GET' !== $canonicalMethod) { - $allow[] = 'GET'; - goto not_regex_trailing_slash_GET_method; - } - - return $this->mergeDefaults(array_replace($matches, array('_route' => 'regex_trailing_slash_GET_method')), array ()); - } - not_regex_trailing_slash_GET_method: - - // regex_trailing_slash_HEAD_method - if (0 === strpos($pathinfo, '/trailing/regex/head-method') && preg_match('#^/trailing/regex/head\\-method/(?P<param>[^/]++)/$#s', $pathinfo, $matches)) { - if ('HEAD' !== $requestMethod) { - $allow[] = 'HEAD'; - goto not_regex_trailing_slash_HEAD_method; - } - - return $this->mergeDefaults(array_replace($matches, array('_route' => 'regex_trailing_slash_HEAD_method')), array ()); - } - not_regex_trailing_slash_HEAD_method: - - // regex_trailing_slash_POST_method - if (0 === strpos($pathinfo, '/trailing/regex/post-method') && preg_match('#^/trailing/regex/post\\-method/(?P<param>[^/]++)/$#s', $pathinfo, $matches)) { - if ('POST' !== $canonicalMethod) { - $allow[] = 'POST'; - goto not_regex_trailing_slash_POST_method; - } - - return $this->mergeDefaults(array_replace($matches, array('_route' => 'regex_trailing_slash_POST_method')), array ()); - } - not_regex_trailing_slash_POST_method: - - } - - elseif (0 === strpos($pathinfo, '/not-trailing/simple')) { - // simple_not_trailing_slash_no_methods - if ('/not-trailing/simple/no-methods' === $pathinfo) { - return array('_route' => 'simple_not_trailing_slash_no_methods'); - } - - // simple_not_trailing_slash_GET_method - if ('/not-trailing/simple/get-method' === $pathinfo) { - if ('GET' !== $canonicalMethod) { - $allow[] = 'GET'; - goto not_simple_not_trailing_slash_GET_method; - } - - return array('_route' => 'simple_not_trailing_slash_GET_method'); - } - not_simple_not_trailing_slash_GET_method: - - // simple_not_trailing_slash_HEAD_method - if ('/not-trailing/simple/head-method' === $pathinfo) { - if ('HEAD' !== $requestMethod) { - $allow[] = 'HEAD'; - goto not_simple_not_trailing_slash_HEAD_method; - } - - return array('_route' => 'simple_not_trailing_slash_HEAD_method'); - } - not_simple_not_trailing_slash_HEAD_method: - - // simple_not_trailing_slash_POST_method - if ('/not-trailing/simple/post-method' === $pathinfo) { - if ('POST' !== $canonicalMethod) { - $allow[] = 'POST'; - goto not_simple_not_trailing_slash_POST_method; - } - - return array('_route' => 'simple_not_trailing_slash_POST_method'); - } - not_simple_not_trailing_slash_POST_method: - - } - - elseif (0 === strpos($pathinfo, '/not-trailing/regex')) { - // regex_not_trailing_slash_no_methods - if (0 === strpos($pathinfo, '/not-trailing/regex/no-methods') && preg_match('#^/not\\-trailing/regex/no\\-methods/(?P<param>[^/]++)$#s', $pathinfo, $matches)) { - return $this->mergeDefaults(array_replace($matches, array('_route' => 'regex_not_trailing_slash_no_methods')), array ()); - } - - // regex_not_trailing_slash_GET_method - if (0 === strpos($pathinfo, '/not-trailing/regex/get-method') && preg_match('#^/not\\-trailing/regex/get\\-method/(?P<param>[^/]++)$#s', $pathinfo, $matches)) { - if ('GET' !== $canonicalMethod) { - $allow[] = 'GET'; - goto not_regex_not_trailing_slash_GET_method; - } - - return $this->mergeDefaults(array_replace($matches, array('_route' => 'regex_not_trailing_slash_GET_method')), array ()); - } - not_regex_not_trailing_slash_GET_method: - - // regex_not_trailing_slash_HEAD_method - if (0 === strpos($pathinfo, '/not-trailing/regex/head-method') && preg_match('#^/not\\-trailing/regex/head\\-method/(?P<param>[^/]++)$#s', $pathinfo, $matches)) { - if ('HEAD' !== $requestMethod) { - $allow[] = 'HEAD'; - goto not_regex_not_trailing_slash_HEAD_method; - } - - return $this->mergeDefaults(array_replace($matches, array('_route' => 'regex_not_trailing_slash_HEAD_method')), array ()); - } - not_regex_not_trailing_slash_HEAD_method: - - // regex_not_trailing_slash_POST_method - if (0 === strpos($pathinfo, '/not-trailing/regex/post-method') && preg_match('#^/not\\-trailing/regex/post\\-method/(?P<param>[^/]++)$#s', $pathinfo, $matches)) { - if ('POST' !== $canonicalMethod) { - $allow[] = 'POST'; - goto not_regex_not_trailing_slash_POST_method; - } - - return $this->mergeDefaults(array_replace($matches, array('_route' => 'regex_not_trailing_slash_POST_method')), array ()); - } - not_regex_not_trailing_slash_POST_method: - - } - - throw 0 < count($allow) ? new MethodNotAllowedException(array_unique($allow)) : new ResourceNotFoundException(); + $this->staticRoutes = [ + '/trailing/simple/no-methods' => [[['_route' => 'simple_trailing_slash_no_methods'], null, null, null, true, false, null]], + '/trailing/simple/get-method' => [[['_route' => 'simple_trailing_slash_GET_method'], null, ['GET' => 0], null, true, false, null]], + '/trailing/simple/head-method' => [[['_route' => 'simple_trailing_slash_HEAD_method'], null, ['HEAD' => 0], null, true, false, null]], + '/trailing/simple/post-method' => [[['_route' => 'simple_trailing_slash_POST_method'], null, ['POST' => 0], null, true, false, null]], + '/not-trailing/simple/no-methods' => [[['_route' => 'simple_not_trailing_slash_no_methods'], null, null, null, false, false, null]], + '/not-trailing/simple/get-method' => [[['_route' => 'simple_not_trailing_slash_GET_method'], null, ['GET' => 0], null, false, false, null]], + '/not-trailing/simple/head-method' => [[['_route' => 'simple_not_trailing_slash_HEAD_method'], null, ['HEAD' => 0], null, false, false, null]], + '/not-trailing/simple/post-method' => [[['_route' => 'simple_not_trailing_slash_POST_method'], null, ['POST' => 0], null, false, false, null]], + ]; + $this->regexpList = [ + 0 => '{^(?' + .'|/trailing/regex/(?' + .'|no\\-methods/([^/]++)(*:46)' + .'|get\\-method/([^/]++)(*:73)' + .'|head\\-method/([^/]++)(*:101)' + .'|post\\-method/([^/]++)(*:130)' + .')' + .'|/not\\-trailing/regex/(?' + .'|no\\-methods/([^/]++)(*:183)' + .'|get\\-method/([^/]++)(*:211)' + .'|head\\-method/([^/]++)(*:240)' + .'|post\\-method/([^/]++)(*:269)' + .')' + .')/?$}sD', + ]; + $this->dynamicRoutes = [ + 46 => [[['_route' => 'regex_trailing_slash_no_methods'], ['param'], null, null, true, true, null]], + 73 => [[['_route' => 'regex_trailing_slash_GET_method'], ['param'], ['GET' => 0], null, true, true, null]], + 101 => [[['_route' => 'regex_trailing_slash_HEAD_method'], ['param'], ['HEAD' => 0], null, true, true, null]], + 130 => [[['_route' => 'regex_trailing_slash_POST_method'], ['param'], ['POST' => 0], null, true, true, null]], + 183 => [[['_route' => 'regex_not_trailing_slash_no_methods'], ['param'], null, null, false, true, null]], + 211 => [[['_route' => 'regex_not_trailing_slash_GET_method'], ['param'], ['GET' => 0], null, false, true, null]], + 240 => [[['_route' => 'regex_not_trailing_slash_HEAD_method'], ['param'], ['HEAD' => 0], null, false, true, null]], + 269 => [ + [['_route' => 'regex_not_trailing_slash_POST_method'], ['param'], ['POST' => 0], null, false, true, null], + [null, null, null, null, false, false, 0], + ], + ]; } } diff --git a/vendor/symfony/routing/Tests/Fixtures/dumper/url_matcher7.php b/vendor/symfony/routing/Tests/Fixtures/dumper/url_matcher7.php index bceee6f3a329d57202f70633700fd9c39fa49b36..3f07f80017c2ae3d18f706cd0824a284c138c72f 100644 --- a/vendor/symfony/routing/Tests/Fixtures/dumper/url_matcher7.php +++ b/vendor/symfony/routing/Tests/Fixtures/dumper/url_matcher7.php @@ -1,7 +1,6 @@ <?php -use Symfony\Component\Routing\Exception\MethodNotAllowedException; -use Symfony\Component\Routing\Exception\ResourceNotFoundException; +use Symfony\Component\Routing\Matcher\Dumper\CompiledUrlMatcherTrait; use Symfony\Component\Routing\RequestContext; /** @@ -10,220 +9,49 @@ use Symfony\Component\Routing\RequestContext; */ class ProjectUrlMatcher extends Symfony\Component\Routing\Tests\Fixtures\RedirectableUrlMatcher { + use CompiledUrlMatcherTrait; + public function __construct(RequestContext $context) { $this->context = $context; - } - - public function match($rawPathinfo) - { - $allow = array(); - $pathinfo = rawurldecode($rawPathinfo); - $trimmedPathinfo = rtrim($pathinfo, '/'); - $context = $this->context; - $request = $this->request; - $requestMethod = $canonicalMethod = $context->getMethod(); - $scheme = $context->getScheme(); - - if ('HEAD' === $requestMethod) { - $canonicalMethod = 'GET'; - } - - - if (0 === strpos($pathinfo, '/trailing/simple')) { - // simple_trailing_slash_no_methods - if ('/trailing/simple/no-methods' === $trimmedPathinfo) { - $ret = array('_route' => 'simple_trailing_slash_no_methods'); - if (substr($pathinfo, -1) !== '/') { - return array_replace($ret, $this->redirect($rawPathinfo.'/', 'simple_trailing_slash_no_methods')); - } - - return $ret; - } - - // simple_trailing_slash_GET_method - if ('/trailing/simple/get-method' === $trimmedPathinfo) { - if ('GET' !== $canonicalMethod) { - $allow[] = 'GET'; - goto not_simple_trailing_slash_GET_method; - } - - $ret = array('_route' => 'simple_trailing_slash_GET_method'); - if (substr($pathinfo, -1) !== '/') { - return array_replace($ret, $this->redirect($rawPathinfo.'/', 'simple_trailing_slash_GET_method')); - } - - return $ret; - } - not_simple_trailing_slash_GET_method: - - // simple_trailing_slash_HEAD_method - if ('/trailing/simple/head-method' === $trimmedPathinfo) { - if ('HEAD' !== $requestMethod) { - $allow[] = 'HEAD'; - goto not_simple_trailing_slash_HEAD_method; - } - - $ret = array('_route' => 'simple_trailing_slash_HEAD_method'); - if (substr($pathinfo, -1) !== '/') { - return array_replace($ret, $this->redirect($rawPathinfo.'/', 'simple_trailing_slash_HEAD_method')); - } - - return $ret; - } - not_simple_trailing_slash_HEAD_method: - - // simple_trailing_slash_POST_method - if ('/trailing/simple/post-method/' === $pathinfo) { - if ('POST' !== $canonicalMethod) { - $allow[] = 'POST'; - goto not_simple_trailing_slash_POST_method; - } - - return array('_route' => 'simple_trailing_slash_POST_method'); - } - not_simple_trailing_slash_POST_method: - - } - - elseif (0 === strpos($pathinfo, '/trailing/regex')) { - // regex_trailing_slash_no_methods - if (0 === strpos($pathinfo, '/trailing/regex/no-methods') && preg_match('#^/trailing/regex/no\\-methods/(?P<param>[^/]++)/?$#s', $pathinfo, $matches)) { - $ret = $this->mergeDefaults(array_replace($matches, array('_route' => 'regex_trailing_slash_no_methods')), array ()); - if (substr($pathinfo, -1) !== '/') { - return array_replace($ret, $this->redirect($rawPathinfo.'/', 'regex_trailing_slash_no_methods')); - } - - return $ret; - } - - // regex_trailing_slash_GET_method - if (0 === strpos($pathinfo, '/trailing/regex/get-method') && preg_match('#^/trailing/regex/get\\-method/(?P<param>[^/]++)/?$#s', $pathinfo, $matches)) { - if ('GET' !== $canonicalMethod) { - $allow[] = 'GET'; - goto not_regex_trailing_slash_GET_method; - } - - $ret = $this->mergeDefaults(array_replace($matches, array('_route' => 'regex_trailing_slash_GET_method')), array ()); - if (substr($pathinfo, -1) !== '/') { - return array_replace($ret, $this->redirect($rawPathinfo.'/', 'regex_trailing_slash_GET_method')); - } - - return $ret; - } - not_regex_trailing_slash_GET_method: - - // regex_trailing_slash_HEAD_method - if (0 === strpos($pathinfo, '/trailing/regex/head-method') && preg_match('#^/trailing/regex/head\\-method/(?P<param>[^/]++)/?$#s', $pathinfo, $matches)) { - if ('HEAD' !== $requestMethod) { - $allow[] = 'HEAD'; - goto not_regex_trailing_slash_HEAD_method; - } - - $ret = $this->mergeDefaults(array_replace($matches, array('_route' => 'regex_trailing_slash_HEAD_method')), array ()); - if (substr($pathinfo, -1) !== '/') { - return array_replace($ret, $this->redirect($rawPathinfo.'/', 'regex_trailing_slash_HEAD_method')); - } - - return $ret; - } - not_regex_trailing_slash_HEAD_method: - - // regex_trailing_slash_POST_method - if (0 === strpos($pathinfo, '/trailing/regex/post-method') && preg_match('#^/trailing/regex/post\\-method/(?P<param>[^/]++)/$#s', $pathinfo, $matches)) { - if ('POST' !== $canonicalMethod) { - $allow[] = 'POST'; - goto not_regex_trailing_slash_POST_method; - } - - return $this->mergeDefaults(array_replace($matches, array('_route' => 'regex_trailing_slash_POST_method')), array ()); - } - not_regex_trailing_slash_POST_method: - - } - - elseif (0 === strpos($pathinfo, '/not-trailing/simple')) { - // simple_not_trailing_slash_no_methods - if ('/not-trailing/simple/no-methods' === $pathinfo) { - return array('_route' => 'simple_not_trailing_slash_no_methods'); - } - - // simple_not_trailing_slash_GET_method - if ('/not-trailing/simple/get-method' === $pathinfo) { - if ('GET' !== $canonicalMethod) { - $allow[] = 'GET'; - goto not_simple_not_trailing_slash_GET_method; - } - - return array('_route' => 'simple_not_trailing_slash_GET_method'); - } - not_simple_not_trailing_slash_GET_method: - - // simple_not_trailing_slash_HEAD_method - if ('/not-trailing/simple/head-method' === $pathinfo) { - if ('HEAD' !== $requestMethod) { - $allow[] = 'HEAD'; - goto not_simple_not_trailing_slash_HEAD_method; - } - - return array('_route' => 'simple_not_trailing_slash_HEAD_method'); - } - not_simple_not_trailing_slash_HEAD_method: - - // simple_not_trailing_slash_POST_method - if ('/not-trailing/simple/post-method' === $pathinfo) { - if ('POST' !== $canonicalMethod) { - $allow[] = 'POST'; - goto not_simple_not_trailing_slash_POST_method; - } - - return array('_route' => 'simple_not_trailing_slash_POST_method'); - } - not_simple_not_trailing_slash_POST_method: - - } - - elseif (0 === strpos($pathinfo, '/not-trailing/regex')) { - // regex_not_trailing_slash_no_methods - if (0 === strpos($pathinfo, '/not-trailing/regex/no-methods') && preg_match('#^/not\\-trailing/regex/no\\-methods/(?P<param>[^/]++)$#s', $pathinfo, $matches)) { - return $this->mergeDefaults(array_replace($matches, array('_route' => 'regex_not_trailing_slash_no_methods')), array ()); - } - - // regex_not_trailing_slash_GET_method - if (0 === strpos($pathinfo, '/not-trailing/regex/get-method') && preg_match('#^/not\\-trailing/regex/get\\-method/(?P<param>[^/]++)$#s', $pathinfo, $matches)) { - if ('GET' !== $canonicalMethod) { - $allow[] = 'GET'; - goto not_regex_not_trailing_slash_GET_method; - } - - return $this->mergeDefaults(array_replace($matches, array('_route' => 'regex_not_trailing_slash_GET_method')), array ()); - } - not_regex_not_trailing_slash_GET_method: - - // regex_not_trailing_slash_HEAD_method - if (0 === strpos($pathinfo, '/not-trailing/regex/head-method') && preg_match('#^/not\\-trailing/regex/head\\-method/(?P<param>[^/]++)$#s', $pathinfo, $matches)) { - if ('HEAD' !== $requestMethod) { - $allow[] = 'HEAD'; - goto not_regex_not_trailing_slash_HEAD_method; - } - - return $this->mergeDefaults(array_replace($matches, array('_route' => 'regex_not_trailing_slash_HEAD_method')), array ()); - } - not_regex_not_trailing_slash_HEAD_method: - - // regex_not_trailing_slash_POST_method - if (0 === strpos($pathinfo, '/not-trailing/regex/post-method') && preg_match('#^/not\\-trailing/regex/post\\-method/(?P<param>[^/]++)$#s', $pathinfo, $matches)) { - if ('POST' !== $canonicalMethod) { - $allow[] = 'POST'; - goto not_regex_not_trailing_slash_POST_method; - } - - return $this->mergeDefaults(array_replace($matches, array('_route' => 'regex_not_trailing_slash_POST_method')), array ()); - } - not_regex_not_trailing_slash_POST_method: - - } - - throw 0 < count($allow) ? new MethodNotAllowedException(array_unique($allow)) : new ResourceNotFoundException(); + $this->staticRoutes = [ + '/trailing/simple/no-methods' => [[['_route' => 'simple_trailing_slash_no_methods'], null, null, null, true, false, null]], + '/trailing/simple/get-method' => [[['_route' => 'simple_trailing_slash_GET_method'], null, ['GET' => 0], null, true, false, null]], + '/trailing/simple/head-method' => [[['_route' => 'simple_trailing_slash_HEAD_method'], null, ['HEAD' => 0], null, true, false, null]], + '/trailing/simple/post-method' => [[['_route' => 'simple_trailing_slash_POST_method'], null, ['POST' => 0], null, true, false, null]], + '/not-trailing/simple/no-methods' => [[['_route' => 'simple_not_trailing_slash_no_methods'], null, null, null, false, false, null]], + '/not-trailing/simple/get-method' => [[['_route' => 'simple_not_trailing_slash_GET_method'], null, ['GET' => 0], null, false, false, null]], + '/not-trailing/simple/head-method' => [[['_route' => 'simple_not_trailing_slash_HEAD_method'], null, ['HEAD' => 0], null, false, false, null]], + '/not-trailing/simple/post-method' => [[['_route' => 'simple_not_trailing_slash_POST_method'], null, ['POST' => 0], null, false, false, null]], + ]; + $this->regexpList = [ + 0 => '{^(?' + .'|/trailing/regex/(?' + .'|no\\-methods/([^/]++)(*:46)' + .'|get\\-method/([^/]++)(*:73)' + .'|head\\-method/([^/]++)(*:101)' + .'|post\\-method/([^/]++)(*:130)' + .')' + .'|/not\\-trailing/regex/(?' + .'|no\\-methods/([^/]++)(*:183)' + .'|get\\-method/([^/]++)(*:211)' + .'|head\\-method/([^/]++)(*:240)' + .'|post\\-method/([^/]++)(*:269)' + .')' + .')/?$}sD', + ]; + $this->dynamicRoutes = [ + 46 => [[['_route' => 'regex_trailing_slash_no_methods'], ['param'], null, null, true, true, null]], + 73 => [[['_route' => 'regex_trailing_slash_GET_method'], ['param'], ['GET' => 0], null, true, true, null]], + 101 => [[['_route' => 'regex_trailing_slash_HEAD_method'], ['param'], ['HEAD' => 0], null, true, true, null]], + 130 => [[['_route' => 'regex_trailing_slash_POST_method'], ['param'], ['POST' => 0], null, true, true, null]], + 183 => [[['_route' => 'regex_not_trailing_slash_no_methods'], ['param'], null, null, false, true, null]], + 211 => [[['_route' => 'regex_not_trailing_slash_GET_method'], ['param'], ['GET' => 0], null, false, true, null]], + 240 => [[['_route' => 'regex_not_trailing_slash_HEAD_method'], ['param'], ['HEAD' => 0], null, false, true, null]], + 269 => [ + [['_route' => 'regex_not_trailing_slash_POST_method'], ['param'], ['POST' => 0], null, false, true, null], + [null, null, null, null, false, false, 0], + ], + ]; } } diff --git a/vendor/symfony/routing/Tests/Fixtures/dumper/url_matcher8.php b/vendor/symfony/routing/Tests/Fixtures/dumper/url_matcher8.php new file mode 100644 index 0000000000000000000000000000000000000000..3ae962b8edaa4894f6a74f114cbc5aedfa89a2ef --- /dev/null +++ b/vendor/symfony/routing/Tests/Fixtures/dumper/url_matcher8.php @@ -0,0 +1,37 @@ +<?php + +use Symfony\Component\Routing\Matcher\Dumper\CompiledUrlMatcherTrait; +use Symfony\Component\Routing\RequestContext; + +/** + * This class has been auto-generated + * by the Symfony Routing Component. + */ +class ProjectUrlMatcher extends Symfony\Component\Routing\Matcher\UrlMatcher +{ + use CompiledUrlMatcherTrait; + + public function __construct(RequestContext $context) + { + $this->context = $context; + $this->regexpList = [ + 0 => '{^(?' + .'|/(a)(*:11)' + .')/?$}sD', + 11 => '{^(?' + .'|/(.)(*:22)' + .')/?$}sDu', + 22 => '{^(?' + .'|/(.)(*:33)' + .')/?$}sD', + ]; + $this->dynamicRoutes = [ + 11 => [[['_route' => 'a'], ['a'], null, null, false, true, null]], + 22 => [[['_route' => 'b'], ['a'], null, null, false, true, null]], + 33 => [ + [['_route' => 'c'], ['a'], null, null, false, true, null], + [null, null, null, null, false, false, 0], + ], + ]; + } +} diff --git a/vendor/symfony/routing/Tests/Fixtures/dumper/url_matcher9.php b/vendor/symfony/routing/Tests/Fixtures/dumper/url_matcher9.php new file mode 100644 index 0000000000000000000000000000000000000000..e233cd1ca95329671b03bc6b1e2994a99bdf8e34 --- /dev/null +++ b/vendor/symfony/routing/Tests/Fixtures/dumper/url_matcher9.php @@ -0,0 +1,26 @@ +<?php + +use Symfony\Component\Routing\Matcher\Dumper\CompiledUrlMatcherTrait; +use Symfony\Component\Routing\RequestContext; + +/** + * This class has been auto-generated + * by the Symfony Routing Component. + */ +class ProjectUrlMatcher extends Symfony\Component\Routing\Matcher\UrlMatcher +{ + use CompiledUrlMatcherTrait; + + public function __construct(RequestContext $context) + { + $this->context = $context; + $this->matchHost = true; + $this->staticRoutes = [ + '/' => [ + [['_route' => 'a'], '#^(?P<d>[^\\.]++)\\.e\\.c\\.b\\.a$#sDi', null, null, false, false, null], + [['_route' => 'c'], '#^(?P<e>[^\\.]++)\\.e\\.c\\.b\\.a$#sDi', null, null, false, false, null], + [['_route' => 'b'], 'd.c.b.a', null, null, false, false, null], + ], + ]; + } +} diff --git a/vendor/symfony/routing/Tests/Fixtures/glob/bar.xml b/vendor/symfony/routing/Tests/Fixtures/glob/bar.xml new file mode 100644 index 0000000000000000000000000000000000000000..8a0410c5e65dc08830505d1d4939991e35633fdc --- /dev/null +++ b/vendor/symfony/routing/Tests/Fixtures/glob/bar.xml @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<routes xmlns="http://symfony.com/schema/routing" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://symfony.com/schema/routing + https://symfony.com/schema/routing/routing-1.0.xsd"> + + <route id="bar_route" path="/bar" controller="AppBundle:Bar:view" /> +</routes> diff --git a/vendor/symfony/routing/Tests/Fixtures/glob/bar.yml b/vendor/symfony/routing/Tests/Fixtures/glob/bar.yml new file mode 100644 index 0000000000000000000000000000000000000000..ba3bc2294b340896467ee59375b98deddddc7fb1 --- /dev/null +++ b/vendor/symfony/routing/Tests/Fixtures/glob/bar.yml @@ -0,0 +1,4 @@ +bar_route: + path: /bar + defaults: + _controller: AppBundle:Bar:view diff --git a/vendor/symfony/routing/Tests/Fixtures/glob/baz.xml b/vendor/symfony/routing/Tests/Fixtures/glob/baz.xml new file mode 100644 index 0000000000000000000000000000000000000000..4b48a0f3d161eda5e6708c5bb86f9194abad533f --- /dev/null +++ b/vendor/symfony/routing/Tests/Fixtures/glob/baz.xml @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<routes xmlns="http://symfony.com/schema/routing" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://symfony.com/schema/routing + https://symfony.com/schema/routing/routing-1.0.xsd"> + + <route id="baz_route" path="/baz" controller="AppBundle:Baz:view" /> +</routes> diff --git a/vendor/symfony/routing/Tests/Fixtures/glob/baz.yml b/vendor/symfony/routing/Tests/Fixtures/glob/baz.yml new file mode 100644 index 0000000000000000000000000000000000000000..f7d8c67f266a87af4d872f0752c1ac58d4cc185a --- /dev/null +++ b/vendor/symfony/routing/Tests/Fixtures/glob/baz.yml @@ -0,0 +1,4 @@ +baz_route: + path: /baz + defaults: + _controller: AppBundle:Baz:view diff --git a/vendor/symfony/routing/Tests/Fixtures/glob/import_multiple.xml b/vendor/symfony/routing/Tests/Fixtures/glob/import_multiple.xml new file mode 100644 index 0000000000000000000000000000000000000000..a08e96d65a0a6f1025170a879b849c3b80fed10d --- /dev/null +++ b/vendor/symfony/routing/Tests/Fixtures/glob/import_multiple.xml @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<routes xmlns="http://symfony.com/schema/routing" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://symfony.com/schema/routing + https://symfony.com/schema/routing/routing-1.0.xsd"> + + <import resource="ba?.xml" /> +</routes> diff --git a/vendor/symfony/routing/Tests/Fixtures/glob/import_multiple.yml b/vendor/symfony/routing/Tests/Fixtures/glob/import_multiple.yml new file mode 100644 index 0000000000000000000000000000000000000000..d1ae5854a51c158bd00fd8a0fd4eb14bdae2278d --- /dev/null +++ b/vendor/symfony/routing/Tests/Fixtures/glob/import_multiple.yml @@ -0,0 +1,2 @@ +_static: + resource: ba?.yml diff --git a/vendor/symfony/routing/Tests/Fixtures/glob/import_single.xml b/vendor/symfony/routing/Tests/Fixtures/glob/import_single.xml new file mode 100644 index 0000000000000000000000000000000000000000..3b26eef1140394bcf61f3051198954e69b9b7b1b --- /dev/null +++ b/vendor/symfony/routing/Tests/Fixtures/glob/import_single.xml @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<routes xmlns="http://symfony.com/schema/routing" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://symfony.com/schema/routing + https://symfony.com/schema/routing/routing-1.0.xsd"> + + <import resource="b?r.xml" /> +</routes> diff --git a/vendor/symfony/routing/Tests/Fixtures/glob/import_single.yml b/vendor/symfony/routing/Tests/Fixtures/glob/import_single.yml new file mode 100644 index 0000000000000000000000000000000000000000..f56ddbd0be9f790eecf4886342e9305ee959e67a --- /dev/null +++ b/vendor/symfony/routing/Tests/Fixtures/glob/import_single.yml @@ -0,0 +1,2 @@ +_static: + resource: b?r.yml diff --git a/vendor/symfony/routing/Tests/Fixtures/glob/php_dsl.php b/vendor/symfony/routing/Tests/Fixtures/glob/php_dsl.php new file mode 100644 index 0000000000000000000000000000000000000000..897fa11f282af8b3e12c36a66377e4bd2cf11b98 --- /dev/null +++ b/vendor/symfony/routing/Tests/Fixtures/glob/php_dsl.php @@ -0,0 +1,7 @@ +<?php + +namespace Symfony\Component\Routing\Loader\Configurator; + +return function (RoutingConfigurator $routes) { + return $routes->import('php_dsl_ba?.php'); +}; diff --git a/vendor/symfony/routing/Tests/Fixtures/glob/php_dsl_bar.php b/vendor/symfony/routing/Tests/Fixtures/glob/php_dsl_bar.php new file mode 100644 index 0000000000000000000000000000000000000000..e6ccf24f4e5299643b145a97d771d678109ac7d2 --- /dev/null +++ b/vendor/symfony/routing/Tests/Fixtures/glob/php_dsl_bar.php @@ -0,0 +1,12 @@ +<?php + +namespace Symfony\Component\Routing\Loader\Configurator; + +return function (RoutingConfigurator $routes) { + $collection = $routes->collection(); + + $collection->add('bar_route', '/bar') + ->defaults(['_controller' => 'AppBundle:Bar:view']); + + return $collection; +}; diff --git a/vendor/symfony/routing/Tests/Fixtures/glob/php_dsl_baz.php b/vendor/symfony/routing/Tests/Fixtures/glob/php_dsl_baz.php new file mode 100644 index 0000000000000000000000000000000000000000..cce65d7054f9604da7f611d4aea214e8251a324c --- /dev/null +++ b/vendor/symfony/routing/Tests/Fixtures/glob/php_dsl_baz.php @@ -0,0 +1,12 @@ +<?php + +namespace Symfony\Component\Routing\Loader\Configurator; + +return function (RoutingConfigurator $routes) { + $collection = $routes->collection(); + + $collection->add('baz_route', '/baz') + ->defaults(['_controller' => 'AppBundle:Baz:view']); + + return $collection; +}; diff --git a/vendor/symfony/routing/Tests/Fixtures/import_with_name_prefix/routing.xml b/vendor/symfony/routing/Tests/Fixtures/import_with_name_prefix/routing.xml new file mode 100644 index 0000000000000000000000000000000000000000..8699f399c448c2fd4e334fc93798d44071c2052a --- /dev/null +++ b/vendor/symfony/routing/Tests/Fixtures/import_with_name_prefix/routing.xml @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<routes xmlns="http://symfony.com/schema/routing" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://symfony.com/schema/routing + https://symfony.com/schema/routing/routing-1.0.xsd"> + + <import resource="../controller/routing.xml" /> + <import resource="../controller/routing.xml" prefix="/api" name-prefix="api_" /> + +</routes> diff --git a/vendor/symfony/routing/Tests/Fixtures/import_with_name_prefix/routing.yml b/vendor/symfony/routing/Tests/Fixtures/import_with_name_prefix/routing.yml new file mode 100644 index 0000000000000000000000000000000000000000..90dce0ea1bfc435a304f2ad700ad6f4b95566088 --- /dev/null +++ b/vendor/symfony/routing/Tests/Fixtures/import_with_name_prefix/routing.yml @@ -0,0 +1,7 @@ +app: + resource: ../controller/routing.yml + +api: + resource: ../controller/routing.yml + name_prefix: api_ + prefix: /api diff --git a/vendor/symfony/routing/Tests/Fixtures/import_with_no_trailing_slash/routing.xml b/vendor/symfony/routing/Tests/Fixtures/import_with_no_trailing_slash/routing.xml new file mode 100644 index 0000000000000000000000000000000000000000..8e768136a3212b0404b346f6c1d604fc7ab5db23 --- /dev/null +++ b/vendor/symfony/routing/Tests/Fixtures/import_with_no_trailing_slash/routing.xml @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<routes xmlns="http://symfony.com/schema/routing" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://symfony.com/schema/routing + https://symfony.com/schema/routing/routing-1.0.xsd"> + + <import resource="../controller/routing.xml" prefix="/slash" name-prefix="a_" /> + <import resource="../controller/routing.xml" prefix="/no-slash" name-prefix="b_" trailing-slash-on-root="false" /> + +</routes> diff --git a/vendor/symfony/routing/Tests/Fixtures/import_with_no_trailing_slash/routing.yml b/vendor/symfony/routing/Tests/Fixtures/import_with_no_trailing_slash/routing.yml new file mode 100644 index 0000000000000000000000000000000000000000..f840ecf8b427b0367f815b87ea91df4c8a97939f --- /dev/null +++ b/vendor/symfony/routing/Tests/Fixtures/import_with_no_trailing_slash/routing.yml @@ -0,0 +1,10 @@ +app: + resource: ../controller/routing.yml + name_prefix: a_ + prefix: /slash + +api: + resource: ../controller/routing.yml + name_prefix: b_ + prefix: /no-slash + trailing_slash_on_root: false diff --git a/vendor/symfony/routing/Tests/Fixtures/imported-with-defaults.php b/vendor/symfony/routing/Tests/Fixtures/imported-with-defaults.php new file mode 100644 index 0000000000000000000000000000000000000000..3606f3e6626986050d749553ca648dc8a85f2fd8 --- /dev/null +++ b/vendor/symfony/routing/Tests/Fixtures/imported-with-defaults.php @@ -0,0 +1,10 @@ +<?php + +namespace Symfony\Component\Routing\Loader\Configurator; + +return function (RoutingConfigurator $routes) { + $routes + ->add('one', '/one') + ->add('two', '/two')->defaults(['specific' => 'imported']) + ; +}; diff --git a/vendor/symfony/routing/Tests/Fixtures/imported-with-defaults.xml b/vendor/symfony/routing/Tests/Fixtures/imported-with-defaults.xml new file mode 100644 index 0000000000000000000000000000000000000000..64fd35b799ee2ed402a45ca669339f3e85a73581 --- /dev/null +++ b/vendor/symfony/routing/Tests/Fixtures/imported-with-defaults.xml @@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<routes xmlns="http://symfony.com/schema/routing" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://symfony.com/schema/routing + https://symfony.com/schema/routing/routing-1.0.xsd"> + + <route id="one" path="/one" /> + <route id="two" path="/two"> + <default key="specific">imported</default> + </route> +</routes> diff --git a/vendor/symfony/routing/Tests/Fixtures/imported-with-defaults.yml b/vendor/symfony/routing/Tests/Fixtures/imported-with-defaults.yml new file mode 100644 index 0000000000000000000000000000000000000000..9af819067f6f5102bbd594f6b56059551b65c7f5 --- /dev/null +++ b/vendor/symfony/routing/Tests/Fixtures/imported-with-defaults.yml @@ -0,0 +1,7 @@ +one: + path: /one + +two: + path: /two + defaults: + specific: imported diff --git a/vendor/symfony/routing/Tests/Fixtures/importer-with-defaults.php b/vendor/symfony/routing/Tests/Fixtures/importer-with-defaults.php new file mode 100644 index 0000000000000000000000000000000000000000..6ac9d69e623ba3d511cd17bdcef1a8897c7a7739 --- /dev/null +++ b/vendor/symfony/routing/Tests/Fixtures/importer-with-defaults.php @@ -0,0 +1,11 @@ +<?php + +namespace Symfony\Component\Routing\Loader\Configurator; + +return function (RoutingConfigurator $routes) { + $routes->import('imported-with-defaults.php') + ->prefix('/defaults') + ->locale('g_locale') + ->format('g_format') + ; +}; diff --git a/vendor/symfony/routing/Tests/Fixtures/importer-with-defaults.xml b/vendor/symfony/routing/Tests/Fixtures/importer-with-defaults.xml new file mode 100644 index 0000000000000000000000000000000000000000..bdd25318d51017b2c3859bfeb55836e59f44901d --- /dev/null +++ b/vendor/symfony/routing/Tests/Fixtures/importer-with-defaults.xml @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<routes xmlns="http://symfony.com/schema/routing" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://symfony.com/schema/routing + https://symfony.com/schema/routing/routing-1.0.xsd"> + + <import resource="imported-with-defaults.xml" prefix="/defaults" + locale="g_locale" + format="g_format" /> +</routes> diff --git a/vendor/symfony/routing/Tests/Fixtures/importer-with-defaults.yml b/vendor/symfony/routing/Tests/Fixtures/importer-with-defaults.yml new file mode 100644 index 0000000000000000000000000000000000000000..2e7d59002145b4064b4b00dc03b199a82fdea796 --- /dev/null +++ b/vendor/symfony/routing/Tests/Fixtures/importer-with-defaults.yml @@ -0,0 +1,5 @@ +defaults: + resource: imported-with-defaults.yml + prefix: /defaults + locale: g_locale + format: g_format diff --git a/vendor/symfony/routing/Tests/Fixtures/list_defaults.xml b/vendor/symfony/routing/Tests/Fixtures/list_defaults.xml index f93bf9c6aef32aa1d8c7a5fe0c8e76c98eacd566..01be7c186dcbdbda9607adb3f25bb20f71b833b1 100644 --- a/vendor/symfony/routing/Tests/Fixtures/list_defaults.xml +++ b/vendor/symfony/routing/Tests/Fixtures/list_defaults.xml @@ -2,7 +2,7 @@ <routes xmlns="http://symfony.com/schema/routing" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://symfony.com/schema/routing - http://symfony.com/schema/routing/routing-1.0.xsd"> + https://symfony.com/schema/routing/routing-1.0.xsd"> <route id="blog" path="/blog"> <default key="_controller"> diff --git a/vendor/symfony/routing/Tests/Fixtures/list_in_list_defaults.xml b/vendor/symfony/routing/Tests/Fixtures/list_in_list_defaults.xml index 987086dbdf21a3328f54d6d55c64cef2e30b6a4a..65baabe333f483b879a15fa3a69d156d816afeba 100644 --- a/vendor/symfony/routing/Tests/Fixtures/list_in_list_defaults.xml +++ b/vendor/symfony/routing/Tests/Fixtures/list_in_list_defaults.xml @@ -2,7 +2,7 @@ <routes xmlns="http://symfony.com/schema/routing" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://symfony.com/schema/routing - http://symfony.com/schema/routing/routing-1.0.xsd"> + https://symfony.com/schema/routing/routing-1.0.xsd"> <route id="blog" path="/blog"> <default key="_controller"> diff --git a/vendor/symfony/routing/Tests/Fixtures/list_in_map_defaults.xml b/vendor/symfony/routing/Tests/Fixtures/list_in_map_defaults.xml index 32d393c56ffc3aae3fde306c0bab555e1a3d80a3..f0d972d1f2687160648760ee4fb66c3941feb75e 100644 --- a/vendor/symfony/routing/Tests/Fixtures/list_in_map_defaults.xml +++ b/vendor/symfony/routing/Tests/Fixtures/list_in_map_defaults.xml @@ -2,7 +2,7 @@ <routes xmlns="http://symfony.com/schema/routing" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://symfony.com/schema/routing - http://symfony.com/schema/routing/routing-1.0.xsd"> + https://symfony.com/schema/routing/routing-1.0.xsd"> <route id="blog" path="/blog"> <default key="_controller"> diff --git a/vendor/symfony/routing/Tests/Fixtures/list_null_values.xml b/vendor/symfony/routing/Tests/Fixtures/list_null_values.xml index c70e03ccc6815bb49584d15acefd6d485446c6da..45bdd9da4a50927f82e2e20c32f0bfe8510ce08f 100644 --- a/vendor/symfony/routing/Tests/Fixtures/list_null_values.xml +++ b/vendor/symfony/routing/Tests/Fixtures/list_null_values.xml @@ -2,7 +2,7 @@ <routes xmlns="http://symfony.com/schema/routing" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://symfony.com/schema/routing - http://symfony.com/schema/routing/routing-1.0.xsd"> + https://symfony.com/schema/routing/routing-1.0.xsd"> <route id="blog" path="/blog"> <default key="_controller"> diff --git a/vendor/symfony/routing/Tests/Fixtures/localized.xml b/vendor/symfony/routing/Tests/Fixtures/localized.xml new file mode 100644 index 0000000000000000000000000000000000000000..d3585c46db1247f9d4eef5668dcefd7bdc53761b --- /dev/null +++ b/vendor/symfony/routing/Tests/Fixtures/localized.xml @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="UTF-8" ?> + +<routes xmlns="http://symfony.com/schema/routing" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://symfony.com/schema/routing https://symfony.com/schema/routing/routing-1.0.xsd"> + + <route id="localized"> + <default key="_controller">MyBundle:Blog:show</default> + <path locale="en">/path</path> + <path locale="fr">/route</path> + </route> + +</routes> diff --git a/vendor/symfony/routing/Tests/Fixtures/localized/imported-with-locale-but-not-localized.xml b/vendor/symfony/routing/Tests/Fixtures/localized/imported-with-locale-but-not-localized.xml new file mode 100644 index 0000000000000000000000000000000000000000..e618b9cea71dafa115f1ad7017778baa99325d94 --- /dev/null +++ b/vendor/symfony/routing/Tests/Fixtures/localized/imported-with-locale-but-not-localized.xml @@ -0,0 +1,9 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<routes xmlns="http://symfony.com/schema/routing" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://symfony.com/schema/routing + https://symfony.com/schema/routing/routing-1.0.xsd"> + <route id="imported" path="/suffix"> + <default key="_controller">MyBundle:Blog:show</default> + </route> +</routes> diff --git a/vendor/symfony/routing/Tests/Fixtures/localized/imported-with-locale-but-not-localized.yml b/vendor/symfony/routing/Tests/Fixtures/localized/imported-with-locale-but-not-localized.yml new file mode 100644 index 0000000000000000000000000000000000000000..b62b569351576673c307792842b792f48e66b2ae --- /dev/null +++ b/vendor/symfony/routing/Tests/Fixtures/localized/imported-with-locale-but-not-localized.yml @@ -0,0 +1,4 @@ +--- +imported: + controller: ImportedController::someAction + path: /imported diff --git a/vendor/symfony/routing/Tests/Fixtures/localized/imported-with-locale.xml b/vendor/symfony/routing/Tests/Fixtures/localized/imported-with-locale.xml new file mode 100644 index 0000000000000000000000000000000000000000..3fe523218567f22ee22e2bcb82da7e6f9946133f --- /dev/null +++ b/vendor/symfony/routing/Tests/Fixtures/localized/imported-with-locale.xml @@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<routes xmlns="http://symfony.com/schema/routing" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://symfony.com/schema/routing + https://symfony.com/schema/routing/routing-1.0.xsd"> + <route id="imported"> + <default key="_controller">MyBundle:Blog:show</default> + <path locale="en">/suffix</path> + <path locale="fr">/le-suffix</path> + </route> +</routes> diff --git a/vendor/symfony/routing/Tests/Fixtures/localized/imported-with-locale.yml b/vendor/symfony/routing/Tests/Fixtures/localized/imported-with-locale.yml new file mode 100644 index 0000000000000000000000000000000000000000..65def8a9265084eb8793b118580307024f4091c1 --- /dev/null +++ b/vendor/symfony/routing/Tests/Fixtures/localized/imported-with-locale.yml @@ -0,0 +1,6 @@ +--- +imported: + controller: ImportedController::someAction + path: + nl: /voorbeeld + en: /example diff --git a/vendor/symfony/routing/Tests/Fixtures/localized/imported-with-utf8.php b/vendor/symfony/routing/Tests/Fixtures/localized/imported-with-utf8.php new file mode 100644 index 0000000000000000000000000000000000000000..a32189fb99282fa729cea00f8fc3d72f58de1aa4 --- /dev/null +++ b/vendor/symfony/routing/Tests/Fixtures/localized/imported-with-utf8.php @@ -0,0 +1,10 @@ +<?php + +namespace Symfony\Component\Routing\Loader\Configurator; + +return function (RoutingConfigurator $routes) { + $routes + ->add('utf8_one', '/one') + ->add('utf8_two', '/two') + ; +}; diff --git a/vendor/symfony/routing/Tests/Fixtures/localized/imported-with-utf8.xml b/vendor/symfony/routing/Tests/Fixtures/localized/imported-with-utf8.xml new file mode 100644 index 0000000000000000000000000000000000000000..751d5c5441da8b14b67ea92cc333f7000c9c6140 --- /dev/null +++ b/vendor/symfony/routing/Tests/Fixtures/localized/imported-with-utf8.xml @@ -0,0 +1,8 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<routes xmlns="http://symfony.com/schema/routing" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://symfony.com/schema/routing"> + + <route id="utf8_one" path="/one" /> + <route id="utf8_two" path="/two" /> +</routes> diff --git a/vendor/symfony/routing/Tests/Fixtures/localized/imported-with-utf8.yml b/vendor/symfony/routing/Tests/Fixtures/localized/imported-with-utf8.yml new file mode 100644 index 0000000000000000000000000000000000000000..f04e7ac731385b01526245e7fc7576aebafd995b --- /dev/null +++ b/vendor/symfony/routing/Tests/Fixtures/localized/imported-with-utf8.yml @@ -0,0 +1,5 @@ +utf8_one: + path: /one + +utf8_two: + path: /two diff --git a/vendor/symfony/routing/Tests/Fixtures/localized/importer-with-controller-default.yml b/vendor/symfony/routing/Tests/Fixtures/localized/importer-with-controller-default.yml new file mode 100644 index 0000000000000000000000000000000000000000..1d13a06342a8ce827bb9a5d0be9a9a55750cf89f --- /dev/null +++ b/vendor/symfony/routing/Tests/Fixtures/localized/importer-with-controller-default.yml @@ -0,0 +1,5 @@ +--- +i_need: + defaults: + _controller: DefaultController::defaultAction + resource: ./localized-route.yml diff --git a/vendor/symfony/routing/Tests/Fixtures/localized/importer-with-locale-imports-non-localized-route.xml b/vendor/symfony/routing/Tests/Fixtures/localized/importer-with-locale-imports-non-localized-route.xml new file mode 100644 index 0000000000000000000000000000000000000000..7acbe689527602b0beaaadca716d1b53442519dc --- /dev/null +++ b/vendor/symfony/routing/Tests/Fixtures/localized/importer-with-locale-imports-non-localized-route.xml @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<routes xmlns="http://symfony.com/schema/routing" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://symfony.com/schema/routing + https://symfony.com/schema/routing/routing-1.0.xsd"> + <import resource="./imported-with-locale-but-not-localized.xml"> + <prefix locale="fr">/le-prefix</prefix> + <prefix locale="en">/the-prefix</prefix> + </import> +</routes> diff --git a/vendor/symfony/routing/Tests/Fixtures/localized/importer-with-locale-imports-non-localized-route.yml b/vendor/symfony/routing/Tests/Fixtures/localized/importer-with-locale-imports-non-localized-route.yml new file mode 100644 index 0000000000000000000000000000000000000000..bc33f3f8d528babd79938946e26e9a7c402e742e --- /dev/null +++ b/vendor/symfony/routing/Tests/Fixtures/localized/importer-with-locale-imports-non-localized-route.yml @@ -0,0 +1,6 @@ +--- +i_need: + resource: ./imported-with-locale-but-not-localized.yml + prefix: + nl: /nl + en: /en diff --git a/vendor/symfony/routing/Tests/Fixtures/localized/importer-with-locale.xml b/vendor/symfony/routing/Tests/Fixtures/localized/importer-with-locale.xml new file mode 100644 index 0000000000000000000000000000000000000000..c3af109806878450df99ac4b42f6ef233e7ad235 --- /dev/null +++ b/vendor/symfony/routing/Tests/Fixtures/localized/importer-with-locale.xml @@ -0,0 +1,10 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<routes xmlns="http://symfony.com/schema/routing" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://symfony.com/schema/routing + https://symfony.com/schema/routing/routing-1.0.xsd"> + <import resource="./imported-with-locale.xml"> + <prefix locale="fr">/le-prefix</prefix> + <prefix locale="en">/the-prefix</prefix> + </import> +</routes> diff --git a/vendor/symfony/routing/Tests/Fixtures/localized/importer-with-locale.yml b/vendor/symfony/routing/Tests/Fixtures/localized/importer-with-locale.yml new file mode 100644 index 0000000000000000000000000000000000000000..29d3571bbd55d0f9bf5a6bf0e2a26d318b5ad7b7 --- /dev/null +++ b/vendor/symfony/routing/Tests/Fixtures/localized/importer-with-locale.yml @@ -0,0 +1,6 @@ +--- +i_need: + resource: ./imported-with-locale.yml + prefix: + nl: /nl + en: /en diff --git a/vendor/symfony/routing/Tests/Fixtures/localized/importer-with-utf8.php b/vendor/symfony/routing/Tests/Fixtures/localized/importer-with-utf8.php new file mode 100644 index 0000000000000000000000000000000000000000..105528dda43df0866fc1bbb3ee1a73f7b623d2c5 --- /dev/null +++ b/vendor/symfony/routing/Tests/Fixtures/localized/importer-with-utf8.php @@ -0,0 +1,7 @@ +<?php + +namespace Symfony\Component\Routing\Loader\Configurator; + +return function (RoutingConfigurator $routes) { + $routes->import('imported-with-utf8.php')->utf8(); +}; diff --git a/vendor/symfony/routing/Tests/Fixtures/localized/importer-with-utf8.xml b/vendor/symfony/routing/Tests/Fixtures/localized/importer-with-utf8.xml new file mode 100644 index 0000000000000000000000000000000000000000..20f8e38ee1b43242dc69d75ac7eb8b7cb1341a95 --- /dev/null +++ b/vendor/symfony/routing/Tests/Fixtures/localized/importer-with-utf8.xml @@ -0,0 +1,7 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<routes xmlns="http://symfony.com/schema/routing" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://symfony.com/schema/routing + https://symfony.com/schema/routing/routing-1.0.xsd"> + <import resource="imported-with-utf8.xml" utf8="true" /> +</routes> diff --git a/vendor/symfony/routing/Tests/Fixtures/localized/importer-with-utf8.yml b/vendor/symfony/routing/Tests/Fixtures/localized/importer-with-utf8.yml new file mode 100644 index 0000000000000000000000000000000000000000..20ad443bb177099d8d554b81ddacb3d38d8c3f99 --- /dev/null +++ b/vendor/symfony/routing/Tests/Fixtures/localized/importer-with-utf8.yml @@ -0,0 +1,3 @@ +utf8_routes: + resource: imported-with-utf8.yml + utf8: true diff --git a/vendor/symfony/routing/Tests/Fixtures/localized/importing-localized-route.yml b/vendor/symfony/routing/Tests/Fixtures/localized/importing-localized-route.yml new file mode 100644 index 0000000000000000000000000000000000000000..ab54ee496ecf9f309a2521faaccc0ad84201ae2b --- /dev/null +++ b/vendor/symfony/routing/Tests/Fixtures/localized/importing-localized-route.yml @@ -0,0 +1,3 @@ +--- +i_need: + resource: ./localized-route.yml diff --git a/vendor/symfony/routing/Tests/Fixtures/localized/localized-route.yml b/vendor/symfony/routing/Tests/Fixtures/localized/localized-route.yml new file mode 100644 index 0000000000000000000000000000000000000000..351a418075b0c86bc19e8c42d805197b5cdc96f7 --- /dev/null +++ b/vendor/symfony/routing/Tests/Fixtures/localized/localized-route.yml @@ -0,0 +1,9 @@ +--- +home: + path: + nl: /nl + en: /en + +not_localized: + controller: HomeController::otherAction + path: /here diff --git a/vendor/symfony/routing/Tests/Fixtures/localized/missing-locale-in-importer.yml b/vendor/symfony/routing/Tests/Fixtures/localized/missing-locale-in-importer.yml new file mode 100644 index 0000000000000000000000000000000000000000..b6d3f5ec019cf660d7685d6acec8de89c0405c2f --- /dev/null +++ b/vendor/symfony/routing/Tests/Fixtures/localized/missing-locale-in-importer.yml @@ -0,0 +1,5 @@ +--- +importing_with_missing_prefix: + resource: ./localized-route.yml + prefix: + nl: /prefix diff --git a/vendor/symfony/routing/Tests/Fixtures/localized/not-localized.yml b/vendor/symfony/routing/Tests/Fixtures/localized/not-localized.yml new file mode 100644 index 0000000000000000000000000000000000000000..4be493da029ab37206bf1bcab3f674d2043c8ef0 --- /dev/null +++ b/vendor/symfony/routing/Tests/Fixtures/localized/not-localized.yml @@ -0,0 +1,4 @@ +--- +not_localized: + controller: string + path: /here diff --git a/vendor/symfony/routing/Tests/Fixtures/localized/officially_formatted_locales.yml b/vendor/symfony/routing/Tests/Fixtures/localized/officially_formatted_locales.yml new file mode 100644 index 0000000000000000000000000000000000000000..a125a4efe81720deadbb92149e1ea52e3dacfa12 --- /dev/null +++ b/vendor/symfony/routing/Tests/Fixtures/localized/officially_formatted_locales.yml @@ -0,0 +1,7 @@ +--- +official: + controller: HomeController::someAction + path: + fr.UTF-8: /omelette-au-fromage + pt-PT: /eu-não-sou-espanhol + pt_BR: /churrasco diff --git a/vendor/symfony/routing/Tests/Fixtures/localized/route-without-path-or-locales.yml b/vendor/symfony/routing/Tests/Fixtures/localized/route-without-path-or-locales.yml new file mode 100644 index 0000000000000000000000000000000000000000..4c7c599f3d649a8a3c3b225ccc4f3acb883de4f2 --- /dev/null +++ b/vendor/symfony/routing/Tests/Fixtures/localized/route-without-path-or-locales.yml @@ -0,0 +1,3 @@ +--- +routename: + controller: Here::here diff --git a/vendor/symfony/routing/Tests/Fixtures/localized/utf8.php b/vendor/symfony/routing/Tests/Fixtures/localized/utf8.php new file mode 100644 index 0000000000000000000000000000000000000000..e7826d0a7896bf07b3ee3ba843f027c182aab92b --- /dev/null +++ b/vendor/symfony/routing/Tests/Fixtures/localized/utf8.php @@ -0,0 +1,10 @@ +<?php + +namespace Symfony\Component\Routing\Loader\Configurator; + +return function (RoutingConfigurator $routes) { + $routes + ->add('some_route', '/') + ->add('some_utf8_route', '/utf8')->utf8() + ; +}; diff --git a/vendor/symfony/routing/Tests/Fixtures/localized/utf8.xml b/vendor/symfony/routing/Tests/Fixtures/localized/utf8.xml new file mode 100644 index 0000000000000000000000000000000000000000..95aff20cfee1a996562536910df28a8b6a06bdd1 --- /dev/null +++ b/vendor/symfony/routing/Tests/Fixtures/localized/utf8.xml @@ -0,0 +1,13 @@ +<?xml version="1.0" encoding="UTF-8" ?> +<routes xmlns="http://symfony.com/schema/routing" + xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://symfony.com/schema/routing + http://symfony.com/schema/routing/routing-1.0.xsd"> + + <route id="app_utf8" path="/utf8"> + <option key="utf8">true</option> + </route> + <route id="app_no_utf8" path="/no-utf8"> + <option key="utf8">false</option> + </route> +</routes> diff --git a/vendor/symfony/routing/Tests/Fixtures/localized/utf8.yml b/vendor/symfony/routing/Tests/Fixtures/localized/utf8.yml new file mode 100644 index 0000000000000000000000000000000000000000..3154c83fd0020d23cb0ef8d6aefb57ec3596fb03 --- /dev/null +++ b/vendor/symfony/routing/Tests/Fixtures/localized/utf8.yml @@ -0,0 +1,6 @@ +some_route: + path: / + +some_utf8_route: + path: /utf8 + utf8: true diff --git a/vendor/symfony/routing/Tests/Fixtures/map_defaults.xml b/vendor/symfony/routing/Tests/Fixtures/map_defaults.xml index 47feb29b9a3d79850755a0e2aaac5e4ab73f5bae..9f080443213765bec09f9343f3c6629ca8afb422 100644 --- a/vendor/symfony/routing/Tests/Fixtures/map_defaults.xml +++ b/vendor/symfony/routing/Tests/Fixtures/map_defaults.xml @@ -2,7 +2,7 @@ <routes xmlns="http://symfony.com/schema/routing" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://symfony.com/schema/routing - http://symfony.com/schema/routing/routing-1.0.xsd"> + https://symfony.com/schema/routing/routing-1.0.xsd"> <route id="blog" path="/blog"> <default key="_controller"> diff --git a/vendor/symfony/routing/Tests/Fixtures/map_in_list_defaults.xml b/vendor/symfony/routing/Tests/Fixtures/map_in_list_defaults.xml index 6d770653bbb721d53cc91a51dbfac6b31ab38a23..1c8b87df3bf0b2fc2c24f51255464a3f1899ea4c 100644 --- a/vendor/symfony/routing/Tests/Fixtures/map_in_list_defaults.xml +++ b/vendor/symfony/routing/Tests/Fixtures/map_in_list_defaults.xml @@ -2,7 +2,7 @@ <routes xmlns="http://symfony.com/schema/routing" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://symfony.com/schema/routing - http://symfony.com/schema/routing/routing-1.0.xsd"> + https://symfony.com/schema/routing/routing-1.0.xsd"> <route id="blog" path="/blog"> <default key="_controller"> diff --git a/vendor/symfony/routing/Tests/Fixtures/map_in_map_defaults.xml b/vendor/symfony/routing/Tests/Fixtures/map_in_map_defaults.xml index 2beee6143357f2dd95b20ede5ff99552590e7f49..a3af49283e28313438dc9af1a17e8e6b227406aa 100644 --- a/vendor/symfony/routing/Tests/Fixtures/map_in_map_defaults.xml +++ b/vendor/symfony/routing/Tests/Fixtures/map_in_map_defaults.xml @@ -2,7 +2,7 @@ <routes xmlns="http://symfony.com/schema/routing" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://symfony.com/schema/routing - http://symfony.com/schema/routing/routing-1.0.xsd"> + https://symfony.com/schema/routing/routing-1.0.xsd"> <route id="blog" path="/blog"> <default key="_controller"> diff --git a/vendor/symfony/routing/Tests/Fixtures/map_null_values.xml b/vendor/symfony/routing/Tests/Fixtures/map_null_values.xml index 8fd8954e02f30a6f72807ea398c4423dd3da993c..a8153ad1fff7f09736c8c0d17fae9cb006b090b4 100644 --- a/vendor/symfony/routing/Tests/Fixtures/map_null_values.xml +++ b/vendor/symfony/routing/Tests/Fixtures/map_null_values.xml @@ -2,7 +2,7 @@ <routes xmlns="http://symfony.com/schema/routing" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://symfony.com/schema/routing - http://symfony.com/schema/routing/routing-1.0.xsd"> + https://symfony.com/schema/routing/routing-1.0.xsd"> <route id="blog" path="/blog"> <default key="_controller"> diff --git a/vendor/symfony/routing/Tests/Fixtures/missing_id.xml b/vendor/symfony/routing/Tests/Fixtures/missing_id.xml index 4ea4115f281a1d40fda70ce51cae0952111fb4cf..fa42e98b7f6303a6ca7abc66f1b12b2829e2d2b6 100644 --- a/vendor/symfony/routing/Tests/Fixtures/missing_id.xml +++ b/vendor/symfony/routing/Tests/Fixtures/missing_id.xml @@ -2,7 +2,7 @@ <routes xmlns="http://symfony.com/schema/routing" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:schemaLocation="http://symfony.com/schema/routing http://symfony.com/schema/routing/routing-1.0.xsd"> + xsi:schemaLocation="http://symfony.com/schema/routing https://symfony.com/schema/routing/routing-1.0.xsd"> <route path="/test"></route> </routes> diff --git a/vendor/symfony/routing/Tests/Fixtures/missing_path.xml b/vendor/symfony/routing/Tests/Fixtures/missing_path.xml index ef5bc088dd003522eaa50dfa8edb0c1d9b0a9792..d048adb17c35bdb3705bd9ee0fcadb9a557bd0c2 100644 --- a/vendor/symfony/routing/Tests/Fixtures/missing_path.xml +++ b/vendor/symfony/routing/Tests/Fixtures/missing_path.xml @@ -2,7 +2,7 @@ <routes xmlns="http://symfony.com/schema/routing" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:schemaLocation="http://symfony.com/schema/routing http://symfony.com/schema/routing/routing-1.0.xsd"> + xsi:schemaLocation="http://symfony.com/schema/routing https://symfony.com/schema/routing/routing-1.0.xsd"> <route id="myroute"></route> </routes> diff --git a/vendor/symfony/routing/Tests/Fixtures/namespaceprefix.xml b/vendor/symfony/routing/Tests/Fixtures/namespaceprefix.xml index e33955ae47857ff82f44a8bfcd077579ec253e28..f303464d6d0be43d89fc1ca67f25c68a2cf6098c 100644 --- a/vendor/symfony/routing/Tests/Fixtures/namespaceprefix.xml +++ b/vendor/symfony/routing/Tests/Fixtures/namespaceprefix.xml @@ -2,7 +2,7 @@ <r:routes xmlns:r="http://symfony.com/schema/routing" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:schemaLocation="http://symfony.com/schema/routing http://symfony.com/schema/routing/routing-1.0.xsd"> + xsi:schemaLocation="http://symfony.com/schema/routing https://symfony.com/schema/routing/routing-1.0.xsd"> <r:route id="blog_show" path="/blog/{slug}" host="{_locale}.example.com"> <r:default key="_controller">MyBundle:Blog:show</r:default> diff --git a/vendor/symfony/routing/Tests/Fixtures/nonvalid.xml b/vendor/symfony/routing/Tests/Fixtures/nonvalid.xml index dc147d2e67a25ca21f2b391370e5d4030a4667ff..07f5f801c6b8797d6ae44db9c6a5a7b1a47fbc75 100644 --- a/vendor/symfony/routing/Tests/Fixtures/nonvalid.xml +++ b/vendor/symfony/routing/Tests/Fixtures/nonvalid.xml @@ -2,7 +2,7 @@ <routes xmlns="http://symfony.com/schema/routing" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:schemaLocation="http://symfony.com/schema/routing http://symfony.com/schema/routing/routing-1.0.xsd"> + xsi:schemaLocation="http://symfony.com/schema/routing https://symfony.com/schema/routing/routing-1.0.xsd"> <route id="blog_show" path="/blog/{slug}"> <default key="_controller">MyBundle:Blog:show</default> diff --git a/vendor/symfony/routing/Tests/Fixtures/nonvalidkeys.yml b/vendor/symfony/routing/Tests/Fixtures/nonvalidkeys.yml index 015e270fb187b0e4e615e617e4f5fd4cb84ae302..b01d50273828485896f29649061bba38f7c34fcc 100644 --- a/vendor/symfony/routing/Tests/Fixtures/nonvalidkeys.yml +++ b/vendor/symfony/routing/Tests/Fixtures/nonvalidkeys.yml @@ -1,3 +1,3 @@ someroute: resource: path/to/some.yml - name_prefix: test_ + not_valid_key: test_ diff --git a/vendor/symfony/routing/Tests/Fixtures/nonvalidnode.xml b/vendor/symfony/routing/Tests/Fixtures/nonvalidnode.xml index 863ef03b90cebfa57b2c5bc9d51edc87f16db331..71093a4dd48097d0f659f5e6880e544ec9a80791 100644 --- a/vendor/symfony/routing/Tests/Fixtures/nonvalidnode.xml +++ b/vendor/symfony/routing/Tests/Fixtures/nonvalidnode.xml @@ -2,7 +2,7 @@ <routes xmlns="http://symfony.com/schema/routing" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:schemaLocation="http://symfony.com/schema/routing http://symfony.com/schema/routing/routing-1.0.xsd"> + xsi:schemaLocation="http://symfony.com/schema/routing https://symfony.com/schema/routing/routing-1.0.xsd"> <foo>bar</foo> </routes> diff --git a/vendor/symfony/routing/Tests/Fixtures/nonvalidroute.xml b/vendor/symfony/routing/Tests/Fixtures/nonvalidroute.xml index 908958c032d38024ec73093a3a79ebf9658afacf..f0b84496c8f2f7db047e1fee2df4ba9eba8e0b9b 100644 --- a/vendor/symfony/routing/Tests/Fixtures/nonvalidroute.xml +++ b/vendor/symfony/routing/Tests/Fixtures/nonvalidroute.xml @@ -2,7 +2,7 @@ <routes xmlns="http://symfony.com/schema/routing" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:schemaLocation="http://symfony.com/schema/routing http://symfony.com/schema/routing/routing-1.0.xsd"> + xsi:schemaLocation="http://symfony.com/schema/routing https://symfony.com/schema/routing/routing-1.0.xsd"> <route id="blog_show" path="/blog/{slug}"> <default key="_controller">MyBundle:Blog:show</default> diff --git a/vendor/symfony/routing/Tests/Fixtures/null_values.xml b/vendor/symfony/routing/Tests/Fixtures/null_values.xml index f9e2aa24df804f6ab8c09b20f54fc05c813b6903..078d49ae4f5a33fa6ad2fcd731762ad56a020e95 100644 --- a/vendor/symfony/routing/Tests/Fixtures/null_values.xml +++ b/vendor/symfony/routing/Tests/Fixtures/null_values.xml @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="UTF-8" ?> <routes xmlns="http://symfony.com/schema/routing" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:schemaLocation="http://symfony.com/schema/routing http://symfony.com/schema/routing/routing-1.0.xsd"> + xsi:schemaLocation="http://symfony.com/schema/routing https://symfony.com/schema/routing/routing-1.0.xsd"> <route id="blog_show" path="/blog/{slug}"> <default key="foo" xsi:nil="true" /> diff --git a/vendor/symfony/routing/Tests/Fixtures/php_dsl.php b/vendor/symfony/routing/Tests/Fixtures/php_dsl.php index 04f6d7ed6eab2d3da3774894f34cad9cb1468fb1..86caa99696149c27c1ed7fdde325c90e635e9f1b 100644 --- a/vendor/symfony/routing/Tests/Fixtures/php_dsl.php +++ b/vendor/symfony/routing/Tests/Fixtures/php_dsl.php @@ -4,18 +4,26 @@ namespace Symfony\Component\Routing\Loader\Configurator; return function (RoutingConfigurator $routes) { $routes + ->collection() ->add('foo', '/foo') ->condition('abc') - ->options(array('utf8' => true)) + ->options(['utf8' => true]) ->add('buz', 'zub') ->controller('foo:act'); $routes->import('php_dsl_sub.php') ->prefix('/sub') - ->requirements(array('id' => '\d+')); + ->requirements(['id' => '\d+']); + + $routes->import('php_dsl_sub.php') + ->namePrefix('z_') + ->prefix('/zub'); + + $routes->import('php_dsl_sub_root.php') + ->prefix('/bus', false); $routes->add('ouf', '/ouf') - ->schemes(array('https')) - ->methods(array('GET')) - ->defaults(array('id' => 0)); + ->schemes(['https']) + ->methods(['GET']) + ->defaults(['id' => 0]); }; diff --git a/vendor/symfony/routing/Tests/Fixtures/php_dsl_i18n.php b/vendor/symfony/routing/Tests/Fixtures/php_dsl_i18n.php new file mode 100644 index 0000000000000000000000000000000000000000..7489360cc26888cbd78000ced7ee33f64b11ce4d --- /dev/null +++ b/vendor/symfony/routing/Tests/Fixtures/php_dsl_i18n.php @@ -0,0 +1,17 @@ +<?php + +namespace Symfony\Component\Routing\Loader\Configurator; + +return function (RoutingConfigurator $routes) { + $routes + ->collection() + ->prefix(['en' => '/glish']) + ->add('foo', '/foo') + ->add('bar', ['en' => '/bar']); + + $routes + ->add('baz', ['en' => '/baz']); + + $routes->import('php_dsl_sub_i18n.php') + ->prefix(['fr' => '/ench']); +}; diff --git a/vendor/symfony/routing/Tests/Fixtures/php_dsl_sub.php b/vendor/symfony/routing/Tests/Fixtures/php_dsl_sub.php index 9eb444ded0c1c728eba491b74bfea21d83910e5a..08b05633b1dd6b6dc2a33d741732afae2dc4c1fc 100644 --- a/vendor/symfony/routing/Tests/Fixtures/php_dsl_sub.php +++ b/vendor/symfony/routing/Tests/Fixtures/php_dsl_sub.php @@ -6,6 +6,7 @@ return function (RoutingConfigurator $routes) { $add = $routes->collection('c_') ->prefix('pub'); + $add('root', '/'); $add('bar', '/bar'); $add->collection('pub_') diff --git a/vendor/symfony/routing/Tests/Fixtures/php_dsl_sub_i18n.php b/vendor/symfony/routing/Tests/Fixtures/php_dsl_sub_i18n.php new file mode 100644 index 0000000000000000000000000000000000000000..e79edc869d2de443d103d308c8a459f1d1a871a6 --- /dev/null +++ b/vendor/symfony/routing/Tests/Fixtures/php_dsl_sub_i18n.php @@ -0,0 +1,11 @@ +<?php + +namespace Symfony\Component\Routing\Loader\Configurator; + +return function (RoutingConfigurator $routes) { + $add = $routes->collection('c_') + ->prefix('pub'); + + $add('foo', ['fr' => '/foo']); + $add('bar', ['fr' => '/bar']); +}; diff --git a/vendor/symfony/routing/Tests/Fixtures/php_dsl_sub_root.php b/vendor/symfony/routing/Tests/Fixtures/php_dsl_sub_root.php new file mode 100644 index 0000000000000000000000000000000000000000..9b309fc132465a0299e6fe19f19f4c5b31d91844 --- /dev/null +++ b/vendor/symfony/routing/Tests/Fixtures/php_dsl_sub_root.php @@ -0,0 +1,10 @@ +<?php + +namespace Symfony\Component\Routing\Loader\Configurator; + +return function (RoutingConfigurator $routes) { + $add = $routes->collection('r_'); + + $add('root', '/'); + $add('bar', '/bar/'); +}; diff --git a/vendor/symfony/routing/Tests/Fixtures/php_object_dsl.php b/vendor/symfony/routing/Tests/Fixtures/php_object_dsl.php new file mode 100644 index 0000000000000000000000000000000000000000..9b9183a1b94272aaecd6ce61d0565d9380ae46fe --- /dev/null +++ b/vendor/symfony/routing/Tests/Fixtures/php_object_dsl.php @@ -0,0 +1,32 @@ +<?php + +namespace Symfony\Component\Routing\Loader\Configurator; + +return new class() { + public function __invoke(RoutingConfigurator $routes) + { + $routes + ->collection() + ->add('foo', '/foo') + ->condition('abc') + ->options(['utf8' => true]) + ->add('buz', 'zub') + ->controller('foo:act'); + + $routes->import('php_dsl_sub.php') + ->prefix('/sub') + ->requirements(['id' => '\d+']); + + $routes->import('php_dsl_sub.php') + ->namePrefix('z_') + ->prefix('/zub'); + + $routes->import('php_dsl_sub_root.php') + ->prefix('/bus', false); + + $routes->add('ouf', '/ouf') + ->schemes(['https']) + ->methods(['GET']) + ->defaults(['id' => 0]); + } +}; diff --git a/vendor/symfony/routing/Tests/Fixtures/requirements_without_placeholder_name.yml b/vendor/symfony/routing/Tests/Fixtures/requirements_without_placeholder_name.yml new file mode 100644 index 0000000000000000000000000000000000000000..be8f04dd650aaa4d421cd1364e6ae7f945bea4aa --- /dev/null +++ b/vendor/symfony/routing/Tests/Fixtures/requirements_without_placeholder_name.yml @@ -0,0 +1,4 @@ +foo: + path: '/{foo}' + requirements: + - '\d+' diff --git a/vendor/symfony/routing/Tests/Fixtures/scalar_defaults.xml b/vendor/symfony/routing/Tests/Fixtures/scalar_defaults.xml index ecfde2801e851b1c7ec39c4e59d6a5977f1c7591..e3f81cc474ca85daad7f6b348ae3ed01269e2ec5 100644 --- a/vendor/symfony/routing/Tests/Fixtures/scalar_defaults.xml +++ b/vendor/symfony/routing/Tests/Fixtures/scalar_defaults.xml @@ -2,7 +2,7 @@ <routes xmlns="http://symfony.com/schema/routing" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://symfony.com/schema/routing - http://symfony.com/schema/routing/routing-1.0.xsd"> + https://symfony.com/schema/routing/routing-1.0.xsd"> <route id="blog" path="/blog"> <default key="_controller"> diff --git a/vendor/symfony/routing/Tests/Fixtures/validpattern.php b/vendor/symfony/routing/Tests/Fixtures/validpattern.php index edc16d8c2cb284eec5a570327009b4f6221f1016..3ef0e14862f2a74233b04a28a60e99d54a057fd1 100644 --- a/vendor/symfony/routing/Tests/Fixtures/validpattern.php +++ b/vendor/symfony/routing/Tests/Fixtures/validpattern.php @@ -1,17 +1,17 @@ <?php -use Symfony\Component\Routing\RouteCollection; use Symfony\Component\Routing\Route; +use Symfony\Component\Routing\RouteCollection; $collection = new RouteCollection(); $collection->add('blog_show', new Route( '/blog/{slug}', - array('_controller' => 'MyBlogBundle:Blog:show'), - array('locale' => '\w+'), - array('compiler_class' => 'RouteCompiler'), + ['_controller' => 'MyBlogBundle:Blog:show'], + ['locale' => '\w+'], + ['compiler_class' => 'RouteCompiler'], '{locale}.example.com', - array('https'), - array('GET', 'POST', 'put', 'OpTiOnS'), + ['https'], + ['GET', 'POST', 'put', 'OpTiOnS'], 'context.getMethod() == "GET"' )); diff --git a/vendor/symfony/routing/Tests/Fixtures/validpattern.xml b/vendor/symfony/routing/Tests/Fixtures/validpattern.xml index dbc72e46ddd4df0510a001ebc686d3c7d4fc5534..93e59d62a762de344aa0be51b57271a6246ba91d 100644 --- a/vendor/symfony/routing/Tests/Fixtures/validpattern.xml +++ b/vendor/symfony/routing/Tests/Fixtures/validpattern.xml @@ -2,7 +2,7 @@ <routes xmlns="http://symfony.com/schema/routing" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:schemaLocation="http://symfony.com/schema/routing http://symfony.com/schema/routing/routing-1.0.xsd"> + xsi:schemaLocation="http://symfony.com/schema/routing https://symfony.com/schema/routing/routing-1.0.xsd"> <route id="blog_show" path="/blog/{slug}" host="{locale}.example.com" methods="GET|POST put,OpTiOnS" schemes="hTTps"> <default key="_controller">MyBundle:Blog:show</default> diff --git a/vendor/symfony/routing/Tests/Fixtures/validresource.php b/vendor/symfony/routing/Tests/Fixtures/validresource.php index 482c80b29e919e0d06c4ef62e7e65e376b955302..31d354a34cd0082d0b989142fc1a2a50c3bbb70a 100644 --- a/vendor/symfony/routing/Tests/Fixtures/validresource.php +++ b/vendor/symfony/routing/Tests/Fixtures/validresource.php @@ -3,15 +3,15 @@ /** @var $loader \Symfony\Component\Routing\Loader\PhpFileLoader */ /** @var \Symfony\Component\Routing\RouteCollection $collection */ $collection = $loader->import('validpattern.php'); -$collection->addDefaults(array( +$collection->addDefaults([ 'foo' => 123, -)); -$collection->addRequirements(array( +]); +$collection->addRequirements([ 'foo' => '\d+', -)); -$collection->addOptions(array( +]); +$collection->addOptions([ 'foo' => 'bar', -)); +]); $collection->setCondition('context.getMethod() == "POST"'); $collection->addPrefix('/prefix'); diff --git a/vendor/symfony/routing/Tests/Fixtures/validresource.xml b/vendor/symfony/routing/Tests/Fixtures/validresource.xml index b7a15ddc7ee1fc008d3f80ee566b5359a83eb6ca..02dfe6be80d1d0f0b64acd0a2b960ac0b8588731 100644 --- a/vendor/symfony/routing/Tests/Fixtures/validresource.xml +++ b/vendor/symfony/routing/Tests/Fixtures/validresource.xml @@ -2,7 +2,7 @@ <routes xmlns="http://symfony.com/schema/routing" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:schemaLocation="http://symfony.com/schema/routing http://symfony.com/schema/routing/routing-1.0.xsd"> + xsi:schemaLocation="http://symfony.com/schema/routing https://symfony.com/schema/routing/routing-1.0.xsd"> <import resource="validpattern.xml" prefix="/{foo}" host=""> <default key="foo">123</default> diff --git a/vendor/symfony/routing/Tests/Generator/Dumper/CompiledUrlGeneratorDumperTest.php b/vendor/symfony/routing/Tests/Generator/Dumper/CompiledUrlGeneratorDumperTest.php new file mode 100644 index 0000000000000000000000000000000000000000..513e1c80e1e66cf2bd4ebf91543322b3992323d2 --- /dev/null +++ b/vendor/symfony/routing/Tests/Generator/Dumper/CompiledUrlGeneratorDumperTest.php @@ -0,0 +1,234 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Tests\Generator\Dumper; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Routing\Generator\CompiledUrlGenerator; +use Symfony\Component\Routing\Generator\Dumper\CompiledUrlGeneratorDumper; +use Symfony\Component\Routing\Generator\UrlGeneratorInterface; +use Symfony\Component\Routing\RequestContext; +use Symfony\Component\Routing\Route; +use Symfony\Component\Routing\RouteCollection; + +class CompiledUrlGeneratorDumperTest extends TestCase +{ + /** + * @var RouteCollection + */ + private $routeCollection; + + /** + * @var CompiledUrlGeneratorDumper + */ + private $generatorDumper; + + /** + * @var string + */ + private $testTmpFilepath; + + /** + * @var string + */ + private $largeTestTmpFilepath; + + protected function setUp(): void + { + parent::setUp(); + + $this->routeCollection = new RouteCollection(); + $this->generatorDumper = new CompiledUrlGeneratorDumper($this->routeCollection); + $this->testTmpFilepath = sys_get_temp_dir().'/php_generator.'.$this->getName().'.php'; + $this->largeTestTmpFilepath = sys_get_temp_dir().'/php_generator.'.$this->getName().'.large.php'; + @unlink($this->testTmpFilepath); + @unlink($this->largeTestTmpFilepath); + } + + protected function tearDown(): void + { + parent::tearDown(); + + @unlink($this->testTmpFilepath); + + $this->routeCollection = null; + $this->generatorDumper = null; + $this->testTmpFilepath = null; + } + + public function testDumpWithRoutes() + { + $this->routeCollection->add('Test', new Route('/testing/{foo}')); + $this->routeCollection->add('Test2', new Route('/testing2')); + + file_put_contents($this->testTmpFilepath, $this->generatorDumper->dump()); + + $projectUrlGenerator = new CompiledUrlGenerator(require $this->testTmpFilepath, new RequestContext('/app.php')); + + $absoluteUrlWithParameter = $projectUrlGenerator->generate('Test', ['foo' => 'bar'], UrlGeneratorInterface::ABSOLUTE_URL); + $absoluteUrlWithoutParameter = $projectUrlGenerator->generate('Test2', [], UrlGeneratorInterface::ABSOLUTE_URL); + $relativeUrlWithParameter = $projectUrlGenerator->generate('Test', ['foo' => 'bar'], UrlGeneratorInterface::ABSOLUTE_PATH); + $relativeUrlWithoutParameter = $projectUrlGenerator->generate('Test2', [], UrlGeneratorInterface::ABSOLUTE_PATH); + + $this->assertEquals('http://localhost/app.php/testing/bar', $absoluteUrlWithParameter); + $this->assertEquals('http://localhost/app.php/testing2', $absoluteUrlWithoutParameter); + $this->assertEquals('/app.php/testing/bar', $relativeUrlWithParameter); + $this->assertEquals('/app.php/testing2', $relativeUrlWithoutParameter); + } + + public function testDumpWithSimpleLocalizedRoutes() + { + $this->routeCollection->add('test', (new Route('/foo'))); + $this->routeCollection->add('test.en', (new Route('/testing/is/fun'))->setDefault('_locale', 'en')->setDefault('_canonical_route', 'test')); + $this->routeCollection->add('test.nl', (new Route('/testen/is/leuk'))->setDefault('_locale', 'nl')->setDefault('_canonical_route', 'test')); + + $code = $this->generatorDumper->dump(); + file_put_contents($this->testTmpFilepath, $code); + + $context = new RequestContext('/app.php'); + $projectUrlGenerator = new CompiledUrlGenerator(require $this->testTmpFilepath, $context, null, 'en'); + + $urlWithDefaultLocale = $projectUrlGenerator->generate('test'); + $urlWithSpecifiedLocale = $projectUrlGenerator->generate('test', ['_locale' => 'nl']); + $context->setParameter('_locale', 'en'); + $urlWithEnglishContext = $projectUrlGenerator->generate('test'); + $context->setParameter('_locale', 'nl'); + $urlWithDutchContext = $projectUrlGenerator->generate('test'); + + $this->assertEquals('/app.php/testing/is/fun', $urlWithDefaultLocale); + $this->assertEquals('/app.php/testen/is/leuk', $urlWithSpecifiedLocale); + $this->assertEquals('/app.php/testing/is/fun', $urlWithEnglishContext); + $this->assertEquals('/app.php/testen/is/leuk', $urlWithDutchContext); + + // test with full route name + $this->assertEquals('/app.php/testing/is/fun', $projectUrlGenerator->generate('test.en')); + + $context->setParameter('_locale', 'de_DE'); + // test that it fall backs to another route when there is no matching localized route + $this->assertEquals('/app.php/foo', $projectUrlGenerator->generate('test')); + } + + public function testDumpWithRouteNotFoundLocalizedRoutes() + { + $this->expectException('Symfony\Component\Routing\Exception\RouteNotFoundException'); + $this->expectExceptionMessage('Unable to generate a URL for the named route "test" as such route does not exist.'); + $this->routeCollection->add('test.en', (new Route('/testing/is/fun'))->setDefault('_locale', 'en')->setDefault('_canonical_route', 'test')); + + $code = $this->generatorDumper->dump(); + file_put_contents($this->testTmpFilepath, $code); + + $projectUrlGenerator = new CompiledUrlGenerator(require $this->testTmpFilepath, new RequestContext('/app.php'), null, 'pl_PL'); + $projectUrlGenerator->generate('test'); + } + + public function testDumpWithFallbackLocaleLocalizedRoutes() + { + $this->routeCollection->add('test.en', (new Route('/testing/is/fun'))->setDefault('_canonical_route', 'test')); + $this->routeCollection->add('test.nl', (new Route('/testen/is/leuk'))->setDefault('_canonical_route', 'test')); + $this->routeCollection->add('test.fr', (new Route('/tester/est/amusant'))->setDefault('_canonical_route', 'test')); + + $code = $this->generatorDumper->dump(); + file_put_contents($this->testTmpFilepath, $code); + + $context = new RequestContext('/app.php'); + $context->setParameter('_locale', 'en_GB'); + $projectUrlGenerator = new CompiledUrlGenerator(require $this->testTmpFilepath, $context, null, null); + + // test with context _locale + $this->assertEquals('/app.php/testing/is/fun', $projectUrlGenerator->generate('test')); + // test with parameters _locale + $this->assertEquals('/app.php/testen/is/leuk', $projectUrlGenerator->generate('test', ['_locale' => 'nl_BE'])); + + $projectUrlGenerator = new CompiledUrlGenerator(require $this->testTmpFilepath, new RequestContext('/app.php'), null, 'fr_CA'); + // test with default locale + $this->assertEquals('/app.php/tester/est/amusant', $projectUrlGenerator->generate('test')); + } + + public function testDumpWithTooManyRoutes() + { + $this->routeCollection->add('Test', new Route('/testing/{foo}')); + for ($i = 0; $i < 32769; ++$i) { + $this->routeCollection->add('route_'.$i, new Route('/route_'.$i)); + } + $this->routeCollection->add('Test2', new Route('/testing2')); + + file_put_contents($this->largeTestTmpFilepath, $this->generatorDumper->dump()); + $this->routeCollection = $this->generatorDumper = null; + + $projectUrlGenerator = new CompiledUrlGenerator(require $this->largeTestTmpFilepath, new RequestContext('/app.php')); + + $absoluteUrlWithParameter = $projectUrlGenerator->generate('Test', ['foo' => 'bar'], UrlGeneratorInterface::ABSOLUTE_URL); + $absoluteUrlWithoutParameter = $projectUrlGenerator->generate('Test2', [], UrlGeneratorInterface::ABSOLUTE_URL); + $relativeUrlWithParameter = $projectUrlGenerator->generate('Test', ['foo' => 'bar'], UrlGeneratorInterface::ABSOLUTE_PATH); + $relativeUrlWithoutParameter = $projectUrlGenerator->generate('Test2', [], UrlGeneratorInterface::ABSOLUTE_PATH); + + $this->assertEquals('http://localhost/app.php/testing/bar', $absoluteUrlWithParameter); + $this->assertEquals('http://localhost/app.php/testing2', $absoluteUrlWithoutParameter); + $this->assertEquals('/app.php/testing/bar', $relativeUrlWithParameter); + $this->assertEquals('/app.php/testing2', $relativeUrlWithoutParameter); + } + + public function testDumpWithoutRoutes() + { + $this->expectException('InvalidArgumentException'); + file_put_contents($this->testTmpFilepath, $this->generatorDumper->dump()); + + $projectUrlGenerator = new CompiledUrlGenerator(require $this->testTmpFilepath, new RequestContext('/app.php')); + + $projectUrlGenerator->generate('Test', []); + } + + public function testGenerateNonExistingRoute() + { + $this->expectException('Symfony\Component\Routing\Exception\RouteNotFoundException'); + $this->routeCollection->add('Test', new Route('/test')); + + file_put_contents($this->testTmpFilepath, $this->generatorDumper->dump()); + + $projectUrlGenerator = new CompiledUrlGenerator(require $this->testTmpFilepath, new RequestContext()); + $url = $projectUrlGenerator->generate('NonExisting', []); + } + + public function testDumpForRouteWithDefaults() + { + $this->routeCollection->add('Test', new Route('/testing/{foo}', ['foo' => 'bar'])); + + file_put_contents($this->testTmpFilepath, $this->generatorDumper->dump()); + + $projectUrlGenerator = new CompiledUrlGenerator(require $this->testTmpFilepath, new RequestContext()); + $url = $projectUrlGenerator->generate('Test', []); + + $this->assertEquals('/testing', $url); + } + + public function testDumpWithSchemeRequirement() + { + $this->routeCollection->add('Test1', new Route('/testing', [], [], [], '', ['ftp', 'https'])); + + file_put_contents($this->testTmpFilepath, $this->generatorDumper->dump()); + + $projectUrlGenerator = new CompiledUrlGenerator(require $this->testTmpFilepath, new RequestContext('/app.php')); + + $absoluteUrl = $projectUrlGenerator->generate('Test1', [], UrlGeneratorInterface::ABSOLUTE_URL); + $relativeUrl = $projectUrlGenerator->generate('Test1', [], UrlGeneratorInterface::ABSOLUTE_PATH); + + $this->assertEquals('ftp://localhost/app.php/testing', $absoluteUrl); + $this->assertEquals('ftp://localhost/app.php/testing', $relativeUrl); + + $projectUrlGenerator = new CompiledUrlGenerator(require $this->testTmpFilepath, new RequestContext('/app.php', 'GET', 'localhost', 'https')); + + $absoluteUrl = $projectUrlGenerator->generate('Test1', [], UrlGeneratorInterface::ABSOLUTE_URL); + $relativeUrl = $projectUrlGenerator->generate('Test1', [], UrlGeneratorInterface::ABSOLUTE_PATH); + + $this->assertEquals('https://localhost/app.php/testing', $absoluteUrl); + $this->assertEquals('/app.php/testing', $relativeUrl); + } +} diff --git a/vendor/symfony/routing/Tests/Generator/Dumper/PhpGeneratorDumperTest.php b/vendor/symfony/routing/Tests/Generator/Dumper/PhpGeneratorDumperTest.php index f84802b35b255d6ce1867ca46adb52bc83075bb8..8ea60eb279f3cfd8c057a81f2469ca7b098f1683 100644 --- a/vendor/symfony/routing/Tests/Generator/Dumper/PhpGeneratorDumperTest.php +++ b/vendor/symfony/routing/Tests/Generator/Dumper/PhpGeneratorDumperTest.php @@ -12,12 +12,15 @@ namespace Symfony\Component\Routing\Tests\Generator\Dumper; use PHPUnit\Framework\TestCase; -use Symfony\Component\Routing\Generator\UrlGeneratorInterface; -use Symfony\Component\Routing\RouteCollection; -use Symfony\Component\Routing\Route; use Symfony\Component\Routing\Generator\Dumper\PhpGeneratorDumper; +use Symfony\Component\Routing\Generator\UrlGeneratorInterface; use Symfony\Component\Routing\RequestContext; +use Symfony\Component\Routing\Route; +use Symfony\Component\Routing\RouteCollection; +/** + * @group legacy + */ class PhpGeneratorDumperTest extends TestCase { /** @@ -40,19 +43,19 @@ class PhpGeneratorDumperTest extends TestCase */ private $largeTestTmpFilepath; - protected function setUp() + protected function setUp(): void { parent::setUp(); $this->routeCollection = new RouteCollection(); $this->generatorDumper = new PhpGeneratorDumper($this->routeCollection); - $this->testTmpFilepath = sys_get_temp_dir().DIRECTORY_SEPARATOR.'php_generator.'.$this->getName().'.php'; - $this->largeTestTmpFilepath = sys_get_temp_dir().DIRECTORY_SEPARATOR.'php_generator.'.$this->getName().'.large.php'; + $this->testTmpFilepath = sys_get_temp_dir().\DIRECTORY_SEPARATOR.'php_generator.'.$this->getName().'.php'; + $this->largeTestTmpFilepath = sys_get_temp_dir().\DIRECTORY_SEPARATOR.'php_generator.'.$this->getName().'.large.php'; @unlink($this->testTmpFilepath); @unlink($this->largeTestTmpFilepath); } - protected function tearDown() + protected function tearDown(): void { parent::tearDown(); @@ -73,10 +76,10 @@ class PhpGeneratorDumperTest extends TestCase $projectUrlGenerator = new \ProjectUrlGenerator(new RequestContext('/app.php')); - $absoluteUrlWithParameter = $projectUrlGenerator->generate('Test', array('foo' => 'bar'), UrlGeneratorInterface::ABSOLUTE_URL); - $absoluteUrlWithoutParameter = $projectUrlGenerator->generate('Test2', array(), UrlGeneratorInterface::ABSOLUTE_URL); - $relativeUrlWithParameter = $projectUrlGenerator->generate('Test', array('foo' => 'bar'), UrlGeneratorInterface::ABSOLUTE_PATH); - $relativeUrlWithoutParameter = $projectUrlGenerator->generate('Test2', array(), UrlGeneratorInterface::ABSOLUTE_PATH); + $absoluteUrlWithParameter = $projectUrlGenerator->generate('Test', ['foo' => 'bar'], UrlGeneratorInterface::ABSOLUTE_URL); + $absoluteUrlWithoutParameter = $projectUrlGenerator->generate('Test2', [], UrlGeneratorInterface::ABSOLUTE_URL); + $relativeUrlWithParameter = $projectUrlGenerator->generate('Test', ['foo' => 'bar'], UrlGeneratorInterface::ABSOLUTE_PATH); + $relativeUrlWithoutParameter = $projectUrlGenerator->generate('Test2', [], UrlGeneratorInterface::ABSOLUTE_PATH); $this->assertEquals('http://localhost/app.php/testing/bar', $absoluteUrlWithParameter); $this->assertEquals('http://localhost/app.php/testing2', $absoluteUrlWithoutParameter); @@ -84,30 +87,103 @@ class PhpGeneratorDumperTest extends TestCase $this->assertEquals('/app.php/testing2', $relativeUrlWithoutParameter); } - public function testDumpWithTooManyRoutes() + public function testDumpWithSimpleLocalizedRoutes() { - if (defined('HHVM_VERSION_ID')) { - $this->markTestSkipped('HHVM consumes too much memory on this test.'); - } + $this->routeCollection->add('test', (new Route('/foo'))); + $this->routeCollection->add('test.en', (new Route('/testing/is/fun'))->setDefault('_locale', 'en')->setDefault('_canonical_route', 'test')); + $this->routeCollection->add('test.nl', (new Route('/testen/is/leuk'))->setDefault('_locale', 'nl')->setDefault('_canonical_route', 'test')); + + $code = $this->generatorDumper->dump([ + 'class' => 'SimpleLocalizedProjectUrlGenerator', + ]); + file_put_contents($this->testTmpFilepath, $code); + include $this->testTmpFilepath; + + $context = new RequestContext('/app.php'); + $projectUrlGenerator = new \SimpleLocalizedProjectUrlGenerator($context, null, 'en'); + + $urlWithDefaultLocale = $projectUrlGenerator->generate('test'); + $urlWithSpecifiedLocale = $projectUrlGenerator->generate('test', ['_locale' => 'nl']); + $context->setParameter('_locale', 'en'); + $urlWithEnglishContext = $projectUrlGenerator->generate('test'); + $context->setParameter('_locale', 'nl'); + $urlWithDutchContext = $projectUrlGenerator->generate('test'); + + $this->assertEquals('/app.php/testing/is/fun', $urlWithDefaultLocale); + $this->assertEquals('/app.php/testen/is/leuk', $urlWithSpecifiedLocale); + $this->assertEquals('/app.php/testing/is/fun', $urlWithEnglishContext); + $this->assertEquals('/app.php/testen/is/leuk', $urlWithDutchContext); + + // test with full route name + $this->assertEquals('/app.php/testing/is/fun', $projectUrlGenerator->generate('test.en')); + + $context->setParameter('_locale', 'de_DE'); + // test that it fall backs to another route when there is no matching localized route + $this->assertEquals('/app.php/foo', $projectUrlGenerator->generate('test')); + } + + public function testDumpWithRouteNotFoundLocalizedRoutes() + { + $this->expectException('Symfony\Component\Routing\Exception\RouteNotFoundException'); + $this->expectExceptionMessage('Unable to generate a URL for the named route "test" as such route does not exist.'); + $this->routeCollection->add('test.en', (new Route('/testing/is/fun'))->setDefault('_locale', 'en')->setDefault('_canonical_route', 'test')); + + $code = $this->generatorDumper->dump([ + 'class' => 'RouteNotFoundLocalizedProjectUrlGenerator', + ]); + file_put_contents($this->testTmpFilepath, $code); + include $this->testTmpFilepath; + + $projectUrlGenerator = new \RouteNotFoundLocalizedProjectUrlGenerator(new RequestContext('/app.php'), null, 'pl_PL'); + $projectUrlGenerator->generate('test'); + } + + public function testDumpWithFallbackLocaleLocalizedRoutes() + { + $this->routeCollection->add('test.en', (new Route('/testing/is/fun'))->setDefault('_canonical_route', 'test')); + $this->routeCollection->add('test.nl', (new Route('/testen/is/leuk'))->setDefault('_canonical_route', 'test')); + $this->routeCollection->add('test.fr', (new Route('/tester/est/amusant'))->setDefault('_canonical_route', 'test')); + + $code = $this->generatorDumper->dump([ + 'class' => 'FallbackLocaleLocalizedProjectUrlGenerator', + ]); + file_put_contents($this->testTmpFilepath, $code); + include $this->testTmpFilepath; + + $context = new RequestContext('/app.php'); + $context->setParameter('_locale', 'en_GB'); + $projectUrlGenerator = new \FallbackLocaleLocalizedProjectUrlGenerator($context, null, null); + + // test with context _locale + $this->assertEquals('/app.php/testing/is/fun', $projectUrlGenerator->generate('test')); + // test with parameters _locale + $this->assertEquals('/app.php/testen/is/leuk', $projectUrlGenerator->generate('test', ['_locale' => 'nl_BE'])); + $projectUrlGenerator = new \FallbackLocaleLocalizedProjectUrlGenerator(new RequestContext('/app.php'), null, 'fr_CA'); + // test with default locale + $this->assertEquals('/app.php/tester/est/amusant', $projectUrlGenerator->generate('test')); + } + + public function testDumpWithTooManyRoutes() + { $this->routeCollection->add('Test', new Route('/testing/{foo}')); for ($i = 0; $i < 32769; ++$i) { $this->routeCollection->add('route_'.$i, new Route('/route_'.$i)); } $this->routeCollection->add('Test2', new Route('/testing2')); - file_put_contents($this->largeTestTmpFilepath, $this->generatorDumper->dump(array( + file_put_contents($this->largeTestTmpFilepath, $this->generatorDumper->dump([ 'class' => 'ProjectLargeUrlGenerator', - ))); + ])); $this->routeCollection = $this->generatorDumper = null; include $this->largeTestTmpFilepath; $projectUrlGenerator = new \ProjectLargeUrlGenerator(new RequestContext('/app.php')); - $absoluteUrlWithParameter = $projectUrlGenerator->generate('Test', array('foo' => 'bar'), UrlGeneratorInterface::ABSOLUTE_URL); - $absoluteUrlWithoutParameter = $projectUrlGenerator->generate('Test2', array(), UrlGeneratorInterface::ABSOLUTE_URL); - $relativeUrlWithParameter = $projectUrlGenerator->generate('Test', array('foo' => 'bar'), UrlGeneratorInterface::ABSOLUTE_PATH); - $relativeUrlWithoutParameter = $projectUrlGenerator->generate('Test2', array(), UrlGeneratorInterface::ABSOLUTE_PATH); + $absoluteUrlWithParameter = $projectUrlGenerator->generate('Test', ['foo' => 'bar'], UrlGeneratorInterface::ABSOLUTE_URL); + $absoluteUrlWithoutParameter = $projectUrlGenerator->generate('Test2', [], UrlGeneratorInterface::ABSOLUTE_URL); + $relativeUrlWithParameter = $projectUrlGenerator->generate('Test', ['foo' => 'bar'], UrlGeneratorInterface::ABSOLUTE_PATH); + $relativeUrlWithoutParameter = $projectUrlGenerator->generate('Test2', [], UrlGeneratorInterface::ABSOLUTE_PATH); $this->assertEquals('http://localhost/app.php/testing/bar', $absoluteUrlWithParameter); $this->assertEquals('http://localhost/app.php/testing2', $absoluteUrlWithoutParameter); @@ -115,65 +191,61 @@ class PhpGeneratorDumperTest extends TestCase $this->assertEquals('/app.php/testing2', $relativeUrlWithoutParameter); } - /** - * @expectedException \InvalidArgumentException - */ public function testDumpWithoutRoutes() { - file_put_contents($this->testTmpFilepath, $this->generatorDumper->dump(array('class' => 'WithoutRoutesUrlGenerator'))); + $this->expectException('InvalidArgumentException'); + file_put_contents($this->testTmpFilepath, $this->generatorDumper->dump(['class' => 'WithoutRoutesUrlGenerator'])); include $this->testTmpFilepath; $projectUrlGenerator = new \WithoutRoutesUrlGenerator(new RequestContext('/app.php')); - $projectUrlGenerator->generate('Test', array()); + $projectUrlGenerator->generate('Test', []); } - /** - * @expectedException \Symfony\Component\Routing\Exception\RouteNotFoundException - */ public function testGenerateNonExistingRoute() { + $this->expectException('Symfony\Component\Routing\Exception\RouteNotFoundException'); $this->routeCollection->add('Test', new Route('/test')); - file_put_contents($this->testTmpFilepath, $this->generatorDumper->dump(array('class' => 'NonExistingRoutesUrlGenerator'))); + file_put_contents($this->testTmpFilepath, $this->generatorDumper->dump(['class' => 'NonExistingRoutesUrlGenerator'])); include $this->testTmpFilepath; $projectUrlGenerator = new \NonExistingRoutesUrlGenerator(new RequestContext()); - $url = $projectUrlGenerator->generate('NonExisting', array()); + $url = $projectUrlGenerator->generate('NonExisting', []); } public function testDumpForRouteWithDefaults() { - $this->routeCollection->add('Test', new Route('/testing/{foo}', array('foo' => 'bar'))); + $this->routeCollection->add('Test', new Route('/testing/{foo}', ['foo' => 'bar'])); - file_put_contents($this->testTmpFilepath, $this->generatorDumper->dump(array('class' => 'DefaultRoutesUrlGenerator'))); + file_put_contents($this->testTmpFilepath, $this->generatorDumper->dump(['class' => 'DefaultRoutesUrlGenerator'])); include $this->testTmpFilepath; $projectUrlGenerator = new \DefaultRoutesUrlGenerator(new RequestContext()); - $url = $projectUrlGenerator->generate('Test', array()); + $url = $projectUrlGenerator->generate('Test', []); $this->assertEquals('/testing', $url); } public function testDumpWithSchemeRequirement() { - $this->routeCollection->add('Test1', new Route('/testing', array(), array(), array(), '', array('ftp', 'https'))); + $this->routeCollection->add('Test1', new Route('/testing', [], [], [], '', ['ftp', 'https'])); - file_put_contents($this->testTmpFilepath, $this->generatorDumper->dump(array('class' => 'SchemeUrlGenerator'))); + file_put_contents($this->testTmpFilepath, $this->generatorDumper->dump(['class' => 'SchemeUrlGenerator'])); include $this->testTmpFilepath; $projectUrlGenerator = new \SchemeUrlGenerator(new RequestContext('/app.php')); - $absoluteUrl = $projectUrlGenerator->generate('Test1', array(), UrlGeneratorInterface::ABSOLUTE_URL); - $relativeUrl = $projectUrlGenerator->generate('Test1', array(), UrlGeneratorInterface::ABSOLUTE_PATH); + $absoluteUrl = $projectUrlGenerator->generate('Test1', [], UrlGeneratorInterface::ABSOLUTE_URL); + $relativeUrl = $projectUrlGenerator->generate('Test1', [], UrlGeneratorInterface::ABSOLUTE_PATH); $this->assertEquals('ftp://localhost/app.php/testing', $absoluteUrl); $this->assertEquals('ftp://localhost/app.php/testing', $relativeUrl); $projectUrlGenerator = new \SchemeUrlGenerator(new RequestContext('/app.php', 'GET', 'localhost', 'https')); - $absoluteUrl = $projectUrlGenerator->generate('Test1', array(), UrlGeneratorInterface::ABSOLUTE_URL); - $relativeUrl = $projectUrlGenerator->generate('Test1', array(), UrlGeneratorInterface::ABSOLUTE_PATH); + $absoluteUrl = $projectUrlGenerator->generate('Test1', [], UrlGeneratorInterface::ABSOLUTE_URL); + $relativeUrl = $projectUrlGenerator->generate('Test1', [], UrlGeneratorInterface::ABSOLUTE_PATH); $this->assertEquals('https://localhost/app.php/testing', $absoluteUrl); $this->assertEquals('/app.php/testing', $relativeUrl); diff --git a/vendor/symfony/routing/Tests/Generator/UrlGeneratorTest.php b/vendor/symfony/routing/Tests/Generator/UrlGeneratorTest.php index 68add771b7189d24e1d4349db6bb107555461b18..a768384747684adf79a86908cd43cd65759b511e 100644 --- a/vendor/symfony/routing/Tests/Generator/UrlGeneratorTest.php +++ b/vendor/symfony/routing/Tests/Generator/UrlGeneratorTest.php @@ -12,18 +12,18 @@ namespace Symfony\Component\Routing\Tests\Generator; use PHPUnit\Framework\TestCase; -use Symfony\Component\Routing\RouteCollection; -use Symfony\Component\Routing\Route; use Symfony\Component\Routing\Generator\UrlGenerator; use Symfony\Component\Routing\Generator\UrlGeneratorInterface; use Symfony\Component\Routing\RequestContext; +use Symfony\Component\Routing\Route; +use Symfony\Component\Routing\RouteCollection; class UrlGeneratorTest extends TestCase { public function testAbsoluteUrlWithPort80() { $routes = $this->getRoutes('test', new Route('/testing')); - $url = $this->getGenerator($routes)->generate('test', array(), UrlGeneratorInterface::ABSOLUTE_URL); + $url = $this->getGenerator($routes)->generate('test', [], UrlGeneratorInterface::ABSOLUTE_URL); $this->assertEquals('http://localhost/app.php/testing', $url); } @@ -31,7 +31,7 @@ class UrlGeneratorTest extends TestCase public function testAbsoluteSecureUrlWithPort443() { $routes = $this->getRoutes('test', new Route('/testing')); - $url = $this->getGenerator($routes, array('scheme' => 'https'))->generate('test', array(), UrlGeneratorInterface::ABSOLUTE_URL); + $url = $this->getGenerator($routes, ['scheme' => 'https'])->generate('test', [], UrlGeneratorInterface::ABSOLUTE_URL); $this->assertEquals('https://localhost/app.php/testing', $url); } @@ -39,7 +39,7 @@ class UrlGeneratorTest extends TestCase public function testAbsoluteUrlWithNonStandardPort() { $routes = $this->getRoutes('test', new Route('/testing')); - $url = $this->getGenerator($routes, array('httpPort' => 8080))->generate('test', array(), UrlGeneratorInterface::ABSOLUTE_URL); + $url = $this->getGenerator($routes, ['httpPort' => 8080])->generate('test', [], UrlGeneratorInterface::ABSOLUTE_URL); $this->assertEquals('http://localhost:8080/app.php/testing', $url); } @@ -47,7 +47,7 @@ class UrlGeneratorTest extends TestCase public function testAbsoluteSecureUrlWithNonStandardPort() { $routes = $this->getRoutes('test', new Route('/testing')); - $url = $this->getGenerator($routes, array('httpsPort' => 8080, 'scheme' => 'https'))->generate('test', array(), UrlGeneratorInterface::ABSOLUTE_URL); + $url = $this->getGenerator($routes, ['httpsPort' => 8080, 'scheme' => 'https'])->generate('test', [], UrlGeneratorInterface::ABSOLUTE_URL); $this->assertEquals('https://localhost:8080/app.php/testing', $url); } @@ -55,7 +55,7 @@ class UrlGeneratorTest extends TestCase public function testRelativeUrlWithoutParameters() { $routes = $this->getRoutes('test', new Route('/testing')); - $url = $this->getGenerator($routes)->generate('test', array(), UrlGeneratorInterface::ABSOLUTE_PATH); + $url = $this->getGenerator($routes)->generate('test', [], UrlGeneratorInterface::ABSOLUTE_PATH); $this->assertEquals('/app.php/testing', $url); } @@ -63,49 +63,47 @@ class UrlGeneratorTest extends TestCase public function testRelativeUrlWithParameter() { $routes = $this->getRoutes('test', new Route('/testing/{foo}')); - $url = $this->getGenerator($routes)->generate('test', array('foo' => 'bar'), UrlGeneratorInterface::ABSOLUTE_PATH); + $url = $this->getGenerator($routes)->generate('test', ['foo' => 'bar'], UrlGeneratorInterface::ABSOLUTE_PATH); $this->assertEquals('/app.php/testing/bar', $url); } public function testRelativeUrlWithNullParameter() { - $routes = $this->getRoutes('test', new Route('/testing.{format}', array('format' => null))); - $url = $this->getGenerator($routes)->generate('test', array(), UrlGeneratorInterface::ABSOLUTE_PATH); + $routes = $this->getRoutes('test', new Route('/testing.{format}', ['format' => null])); + $url = $this->getGenerator($routes)->generate('test', [], UrlGeneratorInterface::ABSOLUTE_PATH); $this->assertEquals('/app.php/testing', $url); } - /** - * @expectedException \Symfony\Component\Routing\Exception\InvalidParameterException - */ public function testRelativeUrlWithNullParameterButNotOptional() { - $routes = $this->getRoutes('test', new Route('/testing/{foo}/bar', array('foo' => null))); + $this->expectException('Symfony\Component\Routing\Exception\InvalidParameterException'); + $routes = $this->getRoutes('test', new Route('/testing/{foo}/bar', ['foo' => null])); // This must raise an exception because the default requirement for "foo" is "[^/]+" which is not met with these params. // Generating path "/testing//bar" would be wrong as matching this route would fail. - $this->getGenerator($routes)->generate('test', array(), UrlGeneratorInterface::ABSOLUTE_PATH); + $this->getGenerator($routes)->generate('test', [], UrlGeneratorInterface::ABSOLUTE_PATH); } public function testRelativeUrlWithOptionalZeroParameter() { $routes = $this->getRoutes('test', new Route('/testing/{page}')); - $url = $this->getGenerator($routes)->generate('test', array('page' => 0), UrlGeneratorInterface::ABSOLUTE_PATH); + $url = $this->getGenerator($routes)->generate('test', ['page' => 0], UrlGeneratorInterface::ABSOLUTE_PATH); $this->assertEquals('/app.php/testing/0', $url); } public function testNotPassedOptionalParameterInBetween() { - $routes = $this->getRoutes('test', new Route('/{slug}/{page}', array('slug' => 'index', 'page' => 0))); - $this->assertSame('/app.php/index/1', $this->getGenerator($routes)->generate('test', array('page' => 1))); + $routes = $this->getRoutes('test', new Route('/{slug}/{page}', ['slug' => 'index', 'page' => 0])); + $this->assertSame('/app.php/index/1', $this->getGenerator($routes)->generate('test', ['page' => 1])); $this->assertSame('/app.php/', $this->getGenerator($routes)->generate('test')); } public function testRelativeUrlWithExtraParameters() { $routes = $this->getRoutes('test', new Route('/testing')); - $url = $this->getGenerator($routes)->generate('test', array('foo' => 'bar'), UrlGeneratorInterface::ABSOLUTE_PATH); + $url = $this->getGenerator($routes)->generate('test', ['foo' => 'bar'], UrlGeneratorInterface::ABSOLUTE_PATH); $this->assertEquals('/app.php/testing?foo=bar', $url); } @@ -113,7 +111,7 @@ class UrlGeneratorTest extends TestCase public function testAbsoluteUrlWithExtraParameters() { $routes = $this->getRoutes('test', new Route('/testing')); - $url = $this->getGenerator($routes)->generate('test', array('foo' => 'bar'), UrlGeneratorInterface::ABSOLUTE_URL); + $url = $this->getGenerator($routes)->generate('test', ['foo' => 'bar'], UrlGeneratorInterface::ABSOLUTE_URL); $this->assertEquals('http://localhost/app.php/testing?foo=bar', $url); } @@ -121,7 +119,7 @@ class UrlGeneratorTest extends TestCase public function testUrlWithNullExtraParameters() { $routes = $this->getRoutes('test', new Route('/testing')); - $url = $this->getGenerator($routes)->generate('test', array('foo' => null), UrlGeneratorInterface::ABSOLUTE_URL); + $url = $this->getGenerator($routes)->generate('test', ['foo' => null], UrlGeneratorInterface::ABSOLUTE_URL); $this->assertEquals('http://localhost/app.php/testing', $url); } @@ -133,7 +131,7 @@ class UrlGeneratorTest extends TestCase $context = new RequestContext('/app.php'); $context->setParameter('bar', 'bar'); $generator->setContext($context); - $url = $generator->generate('test', array('foo' => 'bar')); + $url = $generator->generate('test', ['foo' => 'bar']); $this->assertEquals('/app.php/testing?foo=bar', $url); } @@ -145,134 +143,217 @@ class UrlGeneratorTest extends TestCase $context = new RequestContext('/app.php'); $context->setParameter('foo', 'bar'); $generator->setContext($context); - $url = $generator->generate('test', array()); + $url = $generator->generate('test', []); $this->assertEquals('/app.php/testing/bar', $url); } public function testGlobalParameterHasHigherPriorityThanDefault() { - $routes = $this->getRoutes('test', new Route('/{_locale}', array('_locale' => 'en'))); + $routes = $this->getRoutes('test', new Route('/{_locale}', ['_locale' => 'en'])); $generator = $this->getGenerator($routes); $context = new RequestContext('/app.php'); $context->setParameter('_locale', 'de'); $generator->setContext($context); - $url = $generator->generate('test', array()); + $url = $generator->generate('test', []); $this->assertSame('/app.php/de', $url); } - /** - * @expectedException \Symfony\Component\Routing\Exception\RouteNotFoundException - */ + public function testGenerateWithDefaultLocale() + { + $routes = new RouteCollection(); + + $route = new Route(''); + + $name = 'test'; + + foreach (['hr' => '/foo', 'en' => '/bar'] as $locale => $path) { + $localizedRoute = clone $route; + $localizedRoute->setDefault('_locale', $locale); + $localizedRoute->setDefault('_canonical_route', $name); + $localizedRoute->setPath($path); + $routes->add($name.'.'.$locale, $localizedRoute); + } + + $generator = $this->getGenerator($routes, [], null, 'hr'); + + $this->assertSame( + 'http://localhost/app.php/foo', + $generator->generate($name, [], UrlGeneratorInterface::ABSOLUTE_URL) + ); + } + + public function testGenerateWithOverriddenParameterLocale() + { + $routes = new RouteCollection(); + + $route = new Route(''); + + $name = 'test'; + + foreach (['hr' => '/foo', 'en' => '/bar'] as $locale => $path) { + $localizedRoute = clone $route; + $localizedRoute->setDefault('_locale', $locale); + $localizedRoute->setDefault('_canonical_route', $name); + $localizedRoute->setPath($path); + $routes->add($name.'.'.$locale, $localizedRoute); + } + + $generator = $this->getGenerator($routes, [], null, 'hr'); + + $this->assertSame( + 'http://localhost/app.php/bar', + $generator->generate($name, ['_locale' => 'en'], UrlGeneratorInterface::ABSOLUTE_URL) + ); + } + + public function testGenerateWithOverriddenParameterLocaleFromRequestContext() + { + $routes = new RouteCollection(); + + $route = new Route(''); + + $name = 'test'; + + foreach (['hr' => '/foo', 'en' => '/bar'] as $locale => $path) { + $localizedRoute = clone $route; + $localizedRoute->setDefault('_locale', $locale); + $localizedRoute->setDefault('_canonical_route', $name); + $localizedRoute->setPath($path); + $routes->add($name.'.'.$locale, $localizedRoute); + } + + $generator = $this->getGenerator($routes, [], null, 'hr'); + + $context = new RequestContext('/app.php'); + $context->setParameter('_locale', 'en'); + $generator->setContext($context); + + $this->assertSame( + 'http://localhost/app.php/bar', + $generator->generate($name, [], UrlGeneratorInterface::ABSOLUTE_URL) + ); + } + public function testGenerateWithoutRoutes() { + $this->expectException('Symfony\Component\Routing\Exception\RouteNotFoundException'); $routes = $this->getRoutes('foo', new Route('/testing/{foo}')); - $this->getGenerator($routes)->generate('test', array(), UrlGeneratorInterface::ABSOLUTE_URL); + $this->getGenerator($routes)->generate('test', [], UrlGeneratorInterface::ABSOLUTE_URL); + } + + public function testGenerateWithInvalidLocale() + { + $this->expectException('Symfony\Component\Routing\Exception\RouteNotFoundException'); + $routes = new RouteCollection(); + + $route = new Route(''); + + $name = 'test'; + + foreach (['hr' => '/foo', 'en' => '/bar'] as $locale => $path) { + $localizedRoute = clone $route; + $localizedRoute->setDefault('_locale', $locale); + $localizedRoute->setDefault('_canonical_route', $name); + $localizedRoute->setPath($path); + $routes->add($name.'.'.$locale, $localizedRoute); + } + + $generator = $this->getGenerator($routes, [], null, 'fr'); + $generator->generate($name); } - /** - * @expectedException \Symfony\Component\Routing\Exception\MissingMandatoryParametersException - */ public function testGenerateForRouteWithoutMandatoryParameter() { + $this->expectException('Symfony\Component\Routing\Exception\MissingMandatoryParametersException'); $routes = $this->getRoutes('test', new Route('/testing/{foo}')); - $this->getGenerator($routes)->generate('test', array(), UrlGeneratorInterface::ABSOLUTE_URL); + $this->getGenerator($routes)->generate('test', [], UrlGeneratorInterface::ABSOLUTE_URL); } - /** - * @expectedException \Symfony\Component\Routing\Exception\InvalidParameterException - */ public function testGenerateForRouteWithInvalidOptionalParameter() { - $routes = $this->getRoutes('test', new Route('/testing/{foo}', array('foo' => '1'), array('foo' => 'd+'))); - $this->getGenerator($routes)->generate('test', array('foo' => 'bar'), UrlGeneratorInterface::ABSOLUTE_URL); + $this->expectException('Symfony\Component\Routing\Exception\InvalidParameterException'); + $routes = $this->getRoutes('test', new Route('/testing/{foo}', ['foo' => '1'], ['foo' => 'd+'])); + $this->getGenerator($routes)->generate('test', ['foo' => 'bar'], UrlGeneratorInterface::ABSOLUTE_URL); } - /** - * @expectedException \Symfony\Component\Routing\Exception\InvalidParameterException - */ public function testGenerateForRouteWithInvalidParameter() { - $routes = $this->getRoutes('test', new Route('/testing/{foo}', array(), array('foo' => '1|2'))); - $this->getGenerator($routes)->generate('test', array('foo' => '0'), UrlGeneratorInterface::ABSOLUTE_URL); + $this->expectException('Symfony\Component\Routing\Exception\InvalidParameterException'); + $routes = $this->getRoutes('test', new Route('/testing/{foo}', [], ['foo' => '1|2'])); + $this->getGenerator($routes)->generate('test', ['foo' => '0'], UrlGeneratorInterface::ABSOLUTE_URL); } public function testGenerateForRouteWithInvalidOptionalParameterNonStrict() { - $routes = $this->getRoutes('test', new Route('/testing/{foo}', array('foo' => '1'), array('foo' => 'd+'))); + $routes = $this->getRoutes('test', new Route('/testing/{foo}', ['foo' => '1'], ['foo' => 'd+'])); $generator = $this->getGenerator($routes); $generator->setStrictRequirements(false); - $this->assertNull($generator->generate('test', array('foo' => 'bar'), UrlGeneratorInterface::ABSOLUTE_URL)); + $this->assertSame('', $generator->generate('test', ['foo' => 'bar'], UrlGeneratorInterface::ABSOLUTE_URL)); } public function testGenerateForRouteWithInvalidOptionalParameterNonStrictWithLogger() { - $routes = $this->getRoutes('test', new Route('/testing/{foo}', array('foo' => '1'), array('foo' => 'd+'))); + $routes = $this->getRoutes('test', new Route('/testing/{foo}', ['foo' => '1'], ['foo' => 'd+'])); $logger = $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock(); $logger->expects($this->once()) ->method('error'); - $generator = $this->getGenerator($routes, array(), $logger); + $generator = $this->getGenerator($routes, [], $logger); $generator->setStrictRequirements(false); - $this->assertNull($generator->generate('test', array('foo' => 'bar'), UrlGeneratorInterface::ABSOLUTE_URL)); + $this->assertSame('', $generator->generate('test', ['foo' => 'bar'], UrlGeneratorInterface::ABSOLUTE_URL)); } public function testGenerateForRouteWithInvalidParameterButDisabledRequirementsCheck() { - $routes = $this->getRoutes('test', new Route('/testing/{foo}', array('foo' => '1'), array('foo' => 'd+'))); + $routes = $this->getRoutes('test', new Route('/testing/{foo}', ['foo' => '1'], ['foo' => 'd+'])); $generator = $this->getGenerator($routes); $generator->setStrictRequirements(null); - $this->assertSame('/app.php/testing/bar', $generator->generate('test', array('foo' => 'bar'))); + $this->assertSame('/app.php/testing/bar', $generator->generate('test', ['foo' => 'bar'])); } - /** - * @expectedException \Symfony\Component\Routing\Exception\InvalidParameterException - */ public function testGenerateForRouteWithInvalidMandatoryParameter() { - $routes = $this->getRoutes('test', new Route('/testing/{foo}', array(), array('foo' => 'd+'))); - $this->getGenerator($routes)->generate('test', array('foo' => 'bar'), UrlGeneratorInterface::ABSOLUTE_URL); + $this->expectException('Symfony\Component\Routing\Exception\InvalidParameterException'); + $routes = $this->getRoutes('test', new Route('/testing/{foo}', [], ['foo' => 'd+'])); + $this->getGenerator($routes)->generate('test', ['foo' => 'bar'], UrlGeneratorInterface::ABSOLUTE_URL); } - /** - * @expectedException \Symfony\Component\Routing\Exception\InvalidParameterException - */ public function testGenerateForRouteWithInvalidUtf8Parameter() { - $routes = $this->getRoutes('test', new Route('/testing/{foo}', array(), array('foo' => '\pL+'), array('utf8' => true))); - $this->getGenerator($routes)->generate('test', array('foo' => 'abc123'), UrlGeneratorInterface::ABSOLUTE_URL); + $this->expectException('Symfony\Component\Routing\Exception\InvalidParameterException'); + $routes = $this->getRoutes('test', new Route('/testing/{foo}', [], ['foo' => '\pL+'], ['utf8' => true])); + $this->getGenerator($routes)->generate('test', ['foo' => 'abc123'], UrlGeneratorInterface::ABSOLUTE_URL); } - /** - * @expectedException \Symfony\Component\Routing\Exception\InvalidParameterException - */ public function testRequiredParamAndEmptyPassed() { - $routes = $this->getRoutes('test', new Route('/{slug}', array(), array('slug' => '.+'))); - $this->getGenerator($routes)->generate('test', array('slug' => '')); + $this->expectException('Symfony\Component\Routing\Exception\InvalidParameterException'); + $routes = $this->getRoutes('test', new Route('/{slug}', [], ['slug' => '.+'])); + $this->getGenerator($routes)->generate('test', ['slug' => '']); } public function testSchemeRequirementDoesNothingIfSameCurrentScheme() { - $routes = $this->getRoutes('test', new Route('/', array(), array(), array(), '', array('http'))); + $routes = $this->getRoutes('test', new Route('/', [], [], [], '', ['http'])); $this->assertEquals('/app.php/', $this->getGenerator($routes)->generate('test')); - $routes = $this->getRoutes('test', new Route('/', array(), array(), array(), '', array('https'))); - $this->assertEquals('/app.php/', $this->getGenerator($routes, array('scheme' => 'https'))->generate('test')); + $routes = $this->getRoutes('test', new Route('/', [], [], [], '', ['https'])); + $this->assertEquals('/app.php/', $this->getGenerator($routes, ['scheme' => 'https'])->generate('test')); } public function testSchemeRequirementForcesAbsoluteUrl() { - $routes = $this->getRoutes('test', new Route('/', array(), array(), array(), '', array('https'))); + $routes = $this->getRoutes('test', new Route('/', [], [], [], '', ['https'])); $this->assertEquals('https://localhost/app.php/', $this->getGenerator($routes)->generate('test')); - $routes = $this->getRoutes('test', new Route('/', array(), array(), array(), '', array('http'))); - $this->assertEquals('http://localhost/app.php/', $this->getGenerator($routes, array('scheme' => 'https'))->generate('test')); + $routes = $this->getRoutes('test', new Route('/', [], [], [], '', ['http'])); + $this->assertEquals('http://localhost/app.php/', $this->getGenerator($routes, ['scheme' => 'https'])->generate('test')); } public function testSchemeRequirementCreatesUrlForFirstRequiredScheme() { - $routes = $this->getRoutes('test', new Route('/', array(), array(), array(), '', array('Ftp', 'https'))); + $routes = $this->getRoutes('test', new Route('/', [], [], [], '', ['Ftp', 'https'])); $this->assertEquals('ftp://localhost/app.php/', $this->getGenerator($routes)->generate('test')); } @@ -281,48 +362,48 @@ class UrlGeneratorTest extends TestCase $routes = $this->getRoutes('test', new Route('//path-and-not-domain')); // this must not generate '//path-and-not-domain' because that would be a network path - $this->assertSame('/path-and-not-domain', $this->getGenerator($routes, array('BaseUrl' => ''))->generate('test')); + $this->assertSame('/path-and-not-domain', $this->getGenerator($routes, ['BaseUrl' => ''])->generate('test')); } public function testNoTrailingSlashForMultipleOptionalParameters() { - $routes = $this->getRoutes('test', new Route('/category/{slug1}/{slug2}/{slug3}', array('slug2' => null, 'slug3' => null))); + $routes = $this->getRoutes('test', new Route('/category/{slug1}/{slug2}/{slug3}', ['slug2' => null, 'slug3' => null])); - $this->assertEquals('/app.php/category/foo', $this->getGenerator($routes)->generate('test', array('slug1' => 'foo'))); + $this->assertEquals('/app.php/category/foo', $this->getGenerator($routes)->generate('test', ['slug1' => 'foo'])); } public function testWithAnIntegerAsADefaultValue() { - $routes = $this->getRoutes('test', new Route('/{default}', array('default' => 0))); + $routes = $this->getRoutes('test', new Route('/{default}', ['default' => 0])); - $this->assertEquals('/app.php/foo', $this->getGenerator($routes)->generate('test', array('default' => 'foo'))); + $this->assertEquals('/app.php/foo', $this->getGenerator($routes)->generate('test', ['default' => 'foo'])); } public function testNullForOptionalParameterIsIgnored() { - $routes = $this->getRoutes('test', new Route('/test/{default}', array('default' => 0))); + $routes = $this->getRoutes('test', new Route('/test/{default}', ['default' => 0])); - $this->assertEquals('/app.php/test', $this->getGenerator($routes)->generate('test', array('default' => null))); + $this->assertEquals('/app.php/test', $this->getGenerator($routes)->generate('test', ['default' => null])); } public function testQueryParamSameAsDefault() { - $routes = $this->getRoutes('test', new Route('/test', array('page' => 1))); + $routes = $this->getRoutes('test', new Route('/test', ['page' => 1])); - $this->assertSame('/app.php/test?page=2', $this->getGenerator($routes)->generate('test', array('page' => 2))); - $this->assertSame('/app.php/test', $this->getGenerator($routes)->generate('test', array('page' => 1))); - $this->assertSame('/app.php/test', $this->getGenerator($routes)->generate('test', array('page' => '1'))); + $this->assertSame('/app.php/test?page=2', $this->getGenerator($routes)->generate('test', ['page' => 2])); + $this->assertSame('/app.php/test', $this->getGenerator($routes)->generate('test', ['page' => 1])); + $this->assertSame('/app.php/test', $this->getGenerator($routes)->generate('test', ['page' => '1'])); $this->assertSame('/app.php/test', $this->getGenerator($routes)->generate('test')); } public function testArrayQueryParamSameAsDefault() { - $routes = $this->getRoutes('test', new Route('/test', array('array' => array('foo', 'bar')))); + $routes = $this->getRoutes('test', new Route('/test', ['array' => ['foo', 'bar']])); - $this->assertSame('/app.php/test?array%5B0%5D=bar&array%5B1%5D=foo', $this->getGenerator($routes)->generate('test', array('array' => array('bar', 'foo')))); - $this->assertSame('/app.php/test?array%5Ba%5D=foo&array%5Bb%5D=bar', $this->getGenerator($routes)->generate('test', array('array' => array('a' => 'foo', 'b' => 'bar')))); - $this->assertSame('/app.php/test', $this->getGenerator($routes)->generate('test', array('array' => array('foo', 'bar')))); - $this->assertSame('/app.php/test', $this->getGenerator($routes)->generate('test', array('array' => array(1 => 'bar', 0 => 'foo')))); + $this->assertSame('/app.php/test?array%5B0%5D=bar&array%5B1%5D=foo', $this->getGenerator($routes)->generate('test', ['array' => ['bar', 'foo']])); + $this->assertSame('/app.php/test?array%5Ba%5D=foo&array%5Bb%5D=bar', $this->getGenerator($routes)->generate('test', ['array' => ['a' => 'foo', 'b' => 'bar']])); + $this->assertSame('/app.php/test', $this->getGenerator($routes)->generate('test', ['array' => ['foo', 'bar']])); + $this->assertSame('/app.php/test', $this->getGenerator($routes)->generate('test', ['array' => [1 => 'bar', 0 => 'foo']])); $this->assertSame('/app.php/test', $this->getGenerator($routes)->generate('test')); } @@ -337,16 +418,16 @@ class UrlGeneratorTest extends TestCase { $expectedPath = '/app.php/@:%5B%5D/%28%29*%27%22%20+,;-._~%26%24%3C%3E|%7B%7D%25%5C%5E%60!%3Ffoo=bar%23id' .'/@:%5B%5D/%28%29*%27%22%20+,;-._~%26%24%3C%3E|%7B%7D%25%5C%5E%60!%3Ffoo=bar%23id' - .'?query=%40%3A%5B%5D/%28%29%2A%27%22%20%2B%2C%3B-._~%26%24%3C%3E%7C%7B%7D%25%5C%5E%60%21%3Ffoo%3Dbar%23id'; + .'?query=@:%5B%5D/%28%29*%27%22%20%2B,;-._~%26%24%3C%3E%7C%7B%7D%25%5C%5E%60!?foo%3Dbar%23id'; // This tests the encoding of reserved characters that are used for delimiting of URI components (defined in RFC 3986) // and other special ASCII chars. These chars are tested as static text path, variable path and query param. $chars = '@:[]/()*\'" +,;-._~&$<>|{}%\\^`!?foo=bar#id'; - $routes = $this->getRoutes('test', new Route("/$chars/{varpath}", array(), array('varpath' => '.+'))); - $this->assertSame($expectedPath, $this->getGenerator($routes)->generate('test', array( + $routes = $this->getRoutes('test', new Route("/$chars/{varpath}", [], ['varpath' => '.+'])); + $this->assertSame($expectedPath, $this->getGenerator($routes)->generate('test', [ 'varpath' => $chars, 'query' => $chars, - ))); + ])); } public function testEncodingOfRelativePathSegments() @@ -361,24 +442,24 @@ class UrlGeneratorTest extends TestCase public function testAdjacentVariables() { - $routes = $this->getRoutes('test', new Route('/{x}{y}{z}.{_format}', array('z' => 'default-z', '_format' => 'html'), array('y' => '\d+'))); + $routes = $this->getRoutes('test', new Route('/{x}{y}{z}.{_format}', ['z' => 'default-z', '_format' => 'html'], ['y' => '\d+'])); $generator = $this->getGenerator($routes); - $this->assertSame('/app.php/foo123', $generator->generate('test', array('x' => 'foo', 'y' => '123'))); - $this->assertSame('/app.php/foo123bar.xml', $generator->generate('test', array('x' => 'foo', 'y' => '123', 'z' => 'bar', '_format' => 'xml'))); + $this->assertSame('/app.php/foo123', $generator->generate('test', ['x' => 'foo', 'y' => '123'])); + $this->assertSame('/app.php/foo123bar.xml', $generator->generate('test', ['x' => 'foo', 'y' => '123', 'z' => 'bar', '_format' => 'xml'])); // The default requirement for 'x' should not allow the separator '.' in this case because it would otherwise match everything // and following optional variables like _format could never match. - $this->{method_exists($this, $_ = 'expectException') ? $_ : 'setExpectedException'}('Symfony\Component\Routing\Exception\InvalidParameterException'); - $generator->generate('test', array('x' => 'do.t', 'y' => '123', 'z' => 'bar', '_format' => 'xml')); + $this->expectException('Symfony\Component\Routing\Exception\InvalidParameterException'); + $generator->generate('test', ['x' => 'do.t', 'y' => '123', 'z' => 'bar', '_format' => 'xml']); } public function testOptionalVariableWithNoRealSeparator() { - $routes = $this->getRoutes('test', new Route('/get{what}', array('what' => 'All'))); + $routes = $this->getRoutes('test', new Route('/get{what}', ['what' => 'All'])); $generator = $this->getGenerator($routes); $this->assertSame('/app.php/get', $generator->generate('test')); - $this->assertSame('/app.php/getSites', $generator->generate('test', array('what' => 'Sites'))); + $this->assertSame('/app.php/getSites', $generator->generate('test', ['what' => 'Sites'])); } public function testRequiredVariableWithNoRealSeparator() @@ -386,7 +467,7 @@ class UrlGeneratorTest extends TestCase $routes = $this->getRoutes('test', new Route('/get{what}Suffix')); $generator = $this->getGenerator($routes); - $this->assertSame('/app.php/getSitesSuffix', $generator->generate('test', array('what' => 'Sites'))); + $this->assertSame('/app.php/getSitesSuffix', $generator->generate('test', ['what' => 'Sites'])); } public function testDefaultRequirementOfVariable() @@ -394,137 +475,178 @@ class UrlGeneratorTest extends TestCase $routes = $this->getRoutes('test', new Route('/{page}.{_format}')); $generator = $this->getGenerator($routes); - $this->assertSame('/app.php/index.mobile.html', $generator->generate('test', array('page' => 'index', '_format' => 'mobile.html'))); + $this->assertSame('/app.php/index.mobile.html', $generator->generate('test', ['page' => 'index', '_format' => 'mobile.html'])); + } + + public function testImportantVariable() + { + $routes = $this->getRoutes('test', (new Route('/{page}.{!_format}'))->addDefaults(['_format' => 'mobile.html'])); + $generator = $this->getGenerator($routes); + + $this->assertSame('/app.php/index.xml', $generator->generate('test', ['page' => 'index', '_format' => 'xml'])); + $this->assertSame('/app.php/index.mobile.html', $generator->generate('test', ['page' => 'index', '_format' => 'mobile.html'])); + $this->assertSame('/app.php/index.mobile.html', $generator->generate('test', ['page' => 'index'])); + } + + public function testImportantVariableWithNoDefault() + { + $this->expectException('Symfony\Component\Routing\Exception\MissingMandatoryParametersException'); + $routes = $this->getRoutes('test', new Route('/{page}.{!_format}')); + $generator = $this->getGenerator($routes); + + $generator->generate('test', ['page' => 'index']); } - /** - * @expectedException \Symfony\Component\Routing\Exception\InvalidParameterException - */ public function testDefaultRequirementOfVariableDisallowsSlash() { + $this->expectException('Symfony\Component\Routing\Exception\InvalidParameterException'); $routes = $this->getRoutes('test', new Route('/{page}.{_format}')); - $this->getGenerator($routes)->generate('test', array('page' => 'index', '_format' => 'sl/ash')); + $this->getGenerator($routes)->generate('test', ['page' => 'index', '_format' => 'sl/ash']); } - /** - * @expectedException \Symfony\Component\Routing\Exception\InvalidParameterException - */ public function testDefaultRequirementOfVariableDisallowsNextSeparator() { + $this->expectException('Symfony\Component\Routing\Exception\InvalidParameterException'); $routes = $this->getRoutes('test', new Route('/{page}.{_format}')); - $this->getGenerator($routes)->generate('test', array('page' => 'do.t', '_format' => 'html')); + $this->getGenerator($routes)->generate('test', ['page' => 'do.t', '_format' => 'html']); } public function testWithHostDifferentFromContext() { - $routes = $this->getRoutes('test', new Route('/{name}', array(), array(), array(), '{locale}.example.com')); + $routes = $this->getRoutes('test', new Route('/{name}', [], [], [], '{locale}.example.com')); - $this->assertEquals('//fr.example.com/app.php/Fabien', $this->getGenerator($routes)->generate('test', array('name' => 'Fabien', 'locale' => 'fr'))); + $this->assertEquals('//fr.example.com/app.php/Fabien', $this->getGenerator($routes)->generate('test', ['name' => 'Fabien', 'locale' => 'fr'])); } public function testWithHostSameAsContext() { - $routes = $this->getRoutes('test', new Route('/{name}', array(), array(), array(), '{locale}.example.com')); + $routes = $this->getRoutes('test', new Route('/{name}', [], [], [], '{locale}.example.com')); - $this->assertEquals('/app.php/Fabien', $this->getGenerator($routes, array('host' => 'fr.example.com'))->generate('test', array('name' => 'Fabien', 'locale' => 'fr'))); + $this->assertEquals('/app.php/Fabien', $this->getGenerator($routes, ['host' => 'fr.example.com'])->generate('test', ['name' => 'Fabien', 'locale' => 'fr'])); } public function testWithHostSameAsContextAndAbsolute() { - $routes = $this->getRoutes('test', new Route('/{name}', array(), array(), array(), '{locale}.example.com')); + $routes = $this->getRoutes('test', new Route('/{name}', [], [], [], '{locale}.example.com')); - $this->assertEquals('http://fr.example.com/app.php/Fabien', $this->getGenerator($routes, array('host' => 'fr.example.com'))->generate('test', array('name' => 'Fabien', 'locale' => 'fr'), UrlGeneratorInterface::ABSOLUTE_URL)); + $this->assertEquals('http://fr.example.com/app.php/Fabien', $this->getGenerator($routes, ['host' => 'fr.example.com'])->generate('test', ['name' => 'Fabien', 'locale' => 'fr'], UrlGeneratorInterface::ABSOLUTE_URL)); } - /** - * @expectedException \Symfony\Component\Routing\Exception\InvalidParameterException - */ public function testUrlWithInvalidParameterInHost() { - $routes = $this->getRoutes('test', new Route('/', array(), array('foo' => 'bar'), array(), '{foo}.example.com')); - $this->getGenerator($routes)->generate('test', array('foo' => 'baz'), UrlGeneratorInterface::ABSOLUTE_PATH); + $this->expectException('Symfony\Component\Routing\Exception\InvalidParameterException'); + $routes = $this->getRoutes('test', new Route('/', [], ['foo' => 'bar'], [], '{foo}.example.com')); + $this->getGenerator($routes)->generate('test', ['foo' => 'baz'], UrlGeneratorInterface::ABSOLUTE_PATH); } - /** - * @expectedException \Symfony\Component\Routing\Exception\InvalidParameterException - */ public function testUrlWithInvalidParameterInHostWhenParamHasADefaultValue() { - $routes = $this->getRoutes('test', new Route('/', array('foo' => 'bar'), array('foo' => 'bar'), array(), '{foo}.example.com')); - $this->getGenerator($routes)->generate('test', array('foo' => 'baz'), UrlGeneratorInterface::ABSOLUTE_PATH); + $this->expectException('Symfony\Component\Routing\Exception\InvalidParameterException'); + $routes = $this->getRoutes('test', new Route('/', ['foo' => 'bar'], ['foo' => 'bar'], [], '{foo}.example.com')); + $this->getGenerator($routes)->generate('test', ['foo' => 'baz'], UrlGeneratorInterface::ABSOLUTE_PATH); } - /** - * @expectedException \Symfony\Component\Routing\Exception\InvalidParameterException - */ public function testUrlWithInvalidParameterEqualsDefaultValueInHost() { - $routes = $this->getRoutes('test', new Route('/', array('foo' => 'baz'), array('foo' => 'bar'), array(), '{foo}.example.com')); - $this->getGenerator($routes)->generate('test', array('foo' => 'baz'), UrlGeneratorInterface::ABSOLUTE_PATH); + $this->expectException('Symfony\Component\Routing\Exception\InvalidParameterException'); + $routes = $this->getRoutes('test', new Route('/', ['foo' => 'baz'], ['foo' => 'bar'], [], '{foo}.example.com')); + $this->getGenerator($routes)->generate('test', ['foo' => 'baz'], UrlGeneratorInterface::ABSOLUTE_PATH); } public function testUrlWithInvalidParameterInHostInNonStrictMode() { - $routes = $this->getRoutes('test', new Route('/', array(), array('foo' => 'bar'), array(), '{foo}.example.com')); + $routes = $this->getRoutes('test', new Route('/', [], ['foo' => 'bar'], [], '{foo}.example.com')); $generator = $this->getGenerator($routes); $generator->setStrictRequirements(false); - $this->assertNull($generator->generate('test', array('foo' => 'baz'), UrlGeneratorInterface::ABSOLUTE_PATH)); + $this->assertSame('', $generator->generate('test', ['foo' => 'baz'], UrlGeneratorInterface::ABSOLUTE_PATH)); } public function testHostIsCaseInsensitive() { - $routes = $this->getRoutes('test', new Route('/', array(), array('locale' => 'en|de|fr'), array(), '{locale}.FooBar.com')); + $routes = $this->getRoutes('test', new Route('/', [], ['locale' => 'en|de|fr'], [], '{locale}.FooBar.com')); $generator = $this->getGenerator($routes); - $this->assertSame('//EN.FooBar.com/app.php/', $generator->generate('test', array('locale' => 'EN'), UrlGeneratorInterface::NETWORK_PATH)); + $this->assertSame('//EN.FooBar.com/app.php/', $generator->generate('test', ['locale' => 'EN'], UrlGeneratorInterface::NETWORK_PATH)); } public function testDefaultHostIsUsedWhenContextHostIsEmpty() { - $routes = $this->getRoutes('test', new Route('/route', array('domain' => 'my.fallback.host'), array('domain' => '.+'), array(), '{domain}', array('http'))); + $routes = $this->getRoutes('test', new Route('/path', ['domain' => 'my.fallback.host'], ['domain' => '.+'], [], '{domain}')); $generator = $this->getGenerator($routes); $generator->getContext()->setHost(''); - $this->assertSame('http://my.fallback.host/app.php/route', $generator->generate('test', array(), UrlGeneratorInterface::ABSOLUTE_URL)); + $this->assertSame('http://my.fallback.host/app.php/path', $generator->generate('test', [], UrlGeneratorInterface::ABSOLUTE_URL)); } - public function testDefaultHostIsUsedWhenContextHostIsEmptyAndSchemeIsNot() + public function testDefaultHostIsUsedWhenContextHostIsEmptyAndPathReferenceType() { - $routes = $this->getRoutes('test', new Route('/route', array('domain' => 'my.fallback.host'), array('domain' => '.+'), array(), '{domain}', array('http', 'https'))); + $routes = $this->getRoutes('test', new Route('/path', ['domain' => 'my.fallback.host'], ['domain' => '.+'], [], '{domain}')); $generator = $this->getGenerator($routes); $generator->getContext()->setHost(''); - $generator->getContext()->setScheme('https'); - $this->assertSame('https://my.fallback.host/app.php/route', $generator->generate('test', array(), UrlGeneratorInterface::ABSOLUTE_URL)); + $this->assertSame('//my.fallback.host/app.php/path', $generator->generate('test', [], UrlGeneratorInterface::ABSOLUTE_PATH)); } - public function testAbsoluteUrlFallbackToRelativeIfHostIsEmptyAndSchemeIsNot() + public function testAbsoluteUrlFallbackToPathIfHostIsEmptyAndSchemeIsHttp() { - $routes = $this->getRoutes('test', new Route('/route', array(), array(), array(), '', array('http', 'https'))); + $routes = $this->getRoutes('test', new Route('/route')); $generator = $this->getGenerator($routes); $generator->getContext()->setHost(''); $generator->getContext()->setScheme('https'); - $this->assertSame('/app.php/route', $generator->generate('test', array(), UrlGeneratorInterface::ABSOLUTE_URL)); + $this->assertSame('/app.php/route', $generator->generate('test', [], UrlGeneratorInterface::ABSOLUTE_URL)); + } + + public function testAbsoluteUrlFallbackToNetworkIfSchemeIsEmptyAndHostIsNot() + { + $routes = $this->getRoutes('test', new Route('/path')); + + $generator = $this->getGenerator($routes); + $generator->getContext()->setHost('example.com'); + $generator->getContext()->setScheme(''); + + $this->assertSame('//example.com/app.php/path', $generator->generate('test', [], UrlGeneratorInterface::ABSOLUTE_URL)); + } + + public function testAbsoluteUrlFallbackToPathIfSchemeAndHostAreEmpty() + { + $routes = $this->getRoutes('test', new Route('/path')); + + $generator = $this->getGenerator($routes); + $generator->getContext()->setHost(''); + $generator->getContext()->setScheme(''); + + $this->assertSame('/app.php/path', $generator->generate('test', [], UrlGeneratorInterface::ABSOLUTE_URL)); + } + + public function testAbsoluteUrlWithNonHttpSchemeAndEmptyHost() + { + $routes = $this->getRoutes('test', new Route('/path', [], [], [], '', ['file'])); + + $generator = $this->getGenerator($routes); + $generator->getContext()->setBaseUrl(''); + $generator->getContext()->setHost(''); + + $this->assertSame('file:///path', $generator->generate('test', [], UrlGeneratorInterface::ABSOLUTE_URL)); } public function testGenerateNetworkPath() { - $routes = $this->getRoutes('test', new Route('/{name}', array(), array(), array(), '{locale}.example.com', array('http'))); + $routes = $this->getRoutes('test', new Route('/{name}', [], [], [], '{locale}.example.com', ['http'])); $this->assertSame('//fr.example.com/app.php/Fabien', $this->getGenerator($routes)->generate('test', - array('name' => 'Fabien', 'locale' => 'fr'), UrlGeneratorInterface::NETWORK_PATH), 'network path with different host' + ['name' => 'Fabien', 'locale' => 'fr'], UrlGeneratorInterface::NETWORK_PATH), 'network path with different host' ); - $this->assertSame('//fr.example.com/app.php/Fabien?query=string', $this->getGenerator($routes, array('host' => 'fr.example.com'))->generate('test', - array('name' => 'Fabien', 'locale' => 'fr', 'query' => 'string'), UrlGeneratorInterface::NETWORK_PATH), 'network path although host same as context' + $this->assertSame('//fr.example.com/app.php/Fabien?query=string', $this->getGenerator($routes, ['host' => 'fr.example.com'])->generate('test', + ['name' => 'Fabien', 'locale' => 'fr', 'query' => 'string'], UrlGeneratorInterface::NETWORK_PATH), 'network path although host same as context' ); - $this->assertSame('http://fr.example.com/app.php/Fabien', $this->getGenerator($routes, array('scheme' => 'https'))->generate('test', - array('name' => 'Fabien', 'locale' => 'fr'), UrlGeneratorInterface::NETWORK_PATH), 'absolute URL because scheme requirement does not match context' + $this->assertSame('http://fr.example.com/app.php/Fabien', $this->getGenerator($routes, ['scheme' => 'https'])->generate('test', + ['name' => 'Fabien', 'locale' => 'fr'], UrlGeneratorInterface::NETWORK_PATH), 'absolute URL because scheme requirement does not match context' ); $this->assertSame('http://fr.example.com/app.php/Fabien', $this->getGenerator($routes)->generate('test', - array('name' => 'Fabien', 'locale' => 'fr'), UrlGeneratorInterface::ABSOLUTE_URL), 'absolute URL with same scheme because it is requested' + ['name' => 'Fabien', 'locale' => 'fr'], UrlGeneratorInterface::ABSOLUTE_URL), 'absolute URL with same scheme because it is requested' ); } @@ -533,32 +655,32 @@ class UrlGeneratorTest extends TestCase $routes = new RouteCollection(); $routes->add('article', new Route('/{author}/{article}/')); $routes->add('comments', new Route('/{author}/{article}/comments')); - $routes->add('host', new Route('/{article}', array(), array(), array(), '{author}.example.com')); - $routes->add('scheme', new Route('/{author}/blog', array(), array(), array(), '', array('https'))); + $routes->add('host', new Route('/{article}', [], [], [], '{author}.example.com')); + $routes->add('scheme', new Route('/{author}/blog', [], [], [], '', ['https'])); $routes->add('unrelated', new Route('/about')); - $generator = $this->getGenerator($routes, array('host' => 'example.com', 'pathInfo' => '/fabien/symfony-is-great/')); + $generator = $this->getGenerator($routes, ['host' => 'example.com', 'pathInfo' => '/fabien/symfony-is-great/']); $this->assertSame('comments', $generator->generate('comments', - array('author' => 'fabien', 'article' => 'symfony-is-great'), UrlGeneratorInterface::RELATIVE_PATH) + ['author' => 'fabien', 'article' => 'symfony-is-great'], UrlGeneratorInterface::RELATIVE_PATH) ); $this->assertSame('comments?page=2', $generator->generate('comments', - array('author' => 'fabien', 'article' => 'symfony-is-great', 'page' => 2), UrlGeneratorInterface::RELATIVE_PATH) + ['author' => 'fabien', 'article' => 'symfony-is-great', 'page' => 2], UrlGeneratorInterface::RELATIVE_PATH) ); $this->assertSame('../twig-is-great/', $generator->generate('article', - array('author' => 'fabien', 'article' => 'twig-is-great'), UrlGeneratorInterface::RELATIVE_PATH) + ['author' => 'fabien', 'article' => 'twig-is-great'], UrlGeneratorInterface::RELATIVE_PATH) ); $this->assertSame('../../bernhard/forms-are-great/', $generator->generate('article', - array('author' => 'bernhard', 'article' => 'forms-are-great'), UrlGeneratorInterface::RELATIVE_PATH) + ['author' => 'bernhard', 'article' => 'forms-are-great'], UrlGeneratorInterface::RELATIVE_PATH) ); $this->assertSame('//bernhard.example.com/app.php/forms-are-great', $generator->generate('host', - array('author' => 'bernhard', 'article' => 'forms-are-great'), UrlGeneratorInterface::RELATIVE_PATH) + ['author' => 'bernhard', 'article' => 'forms-are-great'], UrlGeneratorInterface::RELATIVE_PATH) ); $this->assertSame('https://example.com/app.php/bernhard/blog', $generator->generate('scheme', - array('author' => 'bernhard'), UrlGeneratorInterface::RELATIVE_PATH) + ['author' => 'bernhard'], UrlGeneratorInterface::RELATIVE_PATH) ); $this->assertSame('../../about', $generator->generate('unrelated', - array(), UrlGeneratorInterface::RELATIVE_PATH) + [], UrlGeneratorInterface::RELATIVE_PATH) ); } @@ -572,138 +694,155 @@ class UrlGeneratorTest extends TestCase public function provideRelativePaths() { - return array( - array( + return [ + [ '/same/dir/', '/same/dir/', '', - ), - array( + ], + [ '/same/file', '/same/file', '', - ), - array( + ], + [ '/', '/file', 'file', - ), - array( + ], + [ '/', '/dir/file', 'dir/file', - ), - array( + ], + [ '/dir/file.html', '/dir/different-file.html', 'different-file.html', - ), - array( + ], + [ '/same/dir/extra-file', '/same/dir/', './', - ), - array( + ], + [ '/parent/dir/', '/parent/', '../', - ), - array( + ], + [ '/parent/dir/extra-file', '/parent/', '../', - ), - array( + ], + [ '/a/b/', '/x/y/z/', '../../x/y/z/', - ), - array( + ], + [ '/a/b/c/d/e', '/a/c/d', '../../../c/d', - ), - array( + ], + [ '/a/b/c//', '/a/b/c/', '../', - ), - array( + ], + [ '/a/b/c/', '/a/b/c//', './/', - ), - array( + ], + [ '/root/a/b/c/', '/root/x/b/c/', '../../../x/b/c/', - ), - array( + ], + [ '/a/b/c/d/', '/a', '../../../../a', - ), - array( + ], + [ '/special-chars/sp%20ce/1€/mäh/e=mc²', '/special-chars/sp%20ce/1€/<µ>/e=mc²', '../<µ>/e=mc²', - ), - array( + ], + [ 'not-rooted', 'dir/file', 'dir/file', - ), - array( + ], + [ '//dir/', '', '../../', - ), - array( + ], + [ '/dir/', '/dir/file:with-colon', './file:with-colon', - ), - array( + ], + [ '/dir/', '/dir/subdir/file:with-colon', 'subdir/file:with-colon', - ), - array( + ], + [ '/dir/', '/dir/:subdir/', './:subdir/', - ), - ); + ], + ]; } public function testFragmentsCanBeAppendedToUrls() { $routes = $this->getRoutes('test', new Route('/testing')); - $url = $this->getGenerator($routes)->generate('test', array('_fragment' => 'frag ment'), UrlGeneratorInterface::ABSOLUTE_PATH); + $url = $this->getGenerator($routes)->generate('test', ['_fragment' => 'frag ment'], UrlGeneratorInterface::ABSOLUTE_PATH); $this->assertEquals('/app.php/testing#frag%20ment', $url); - $url = $this->getGenerator($routes)->generate('test', array('_fragment' => '0'), UrlGeneratorInterface::ABSOLUTE_PATH); + $url = $this->getGenerator($routes)->generate('test', ['_fragment' => '0'], UrlGeneratorInterface::ABSOLUTE_PATH); $this->assertEquals('/app.php/testing#0', $url); } public function testFragmentsDoNotEscapeValidCharacters() { $routes = $this->getRoutes('test', new Route('/testing')); - $url = $this->getGenerator($routes)->generate('test', array('_fragment' => '?/'), UrlGeneratorInterface::ABSOLUTE_PATH); + $url = $this->getGenerator($routes)->generate('test', ['_fragment' => '?/'], UrlGeneratorInterface::ABSOLUTE_PATH); $this->assertEquals('/app.php/testing#?/', $url); } public function testFragmentsCanBeDefinedAsDefaults() { - $routes = $this->getRoutes('test', new Route('/testing', array('_fragment' => 'fragment'))); - $url = $this->getGenerator($routes)->generate('test', array(), UrlGeneratorInterface::ABSOLUTE_PATH); + $routes = $this->getRoutes('test', new Route('/testing', ['_fragment' => 'fragment'])); + $url = $this->getGenerator($routes)->generate('test', [], UrlGeneratorInterface::ABSOLUTE_PATH); $this->assertEquals('/app.php/testing#fragment', $url); } - protected function getGenerator(RouteCollection $routes, array $parameters = array(), $logger = null) + /** + * @dataProvider provideLookAroundRequirementsInPath + */ + public function testLookRoundRequirementsInPath($expected, $path, $requirement) + { + $routes = $this->getRoutes('test', new Route($path, [], ['foo' => $requirement, 'baz' => '.+?'])); + $this->assertSame($expected, $this->getGenerator($routes)->generate('test', ['foo' => 'a/b', 'baz' => 'c/d/e'])); + } + + public function provideLookAroundRequirementsInPath() + { + yield ['/app.php/a/b/b%28ar/c/d/e', '/{foo}/b(ar/{baz}', '.+(?=/b\\(ar/)']; + yield ['/app.php/a/b/bar/c/d/e', '/{foo}/bar/{baz}', '.+(?!$)']; + yield ['/app.php/bar/a/b/bam/c/d/e', '/bar/{foo}/bam/{baz}', '(?<=/bar/).+']; + yield ['/app.php/bar/a/b/bam/c/d/e', '/bar/{foo}/bam/{baz}', '(?<!^).+']; + } + + protected function getGenerator(RouteCollection $routes, array $parameters = [], $logger = null, string $defaultLocale = null) { $context = new RequestContext('/app.php'); foreach ($parameters as $key => $value) { @@ -711,7 +850,7 @@ class UrlGeneratorTest extends TestCase $context->$method($value); } - return new UrlGenerator($routes, $context, $logger); + return new UrlGenerator($routes, $context, $logger, $defaultLocale); } protected function getRoutes($name, Route $route) diff --git a/vendor/symfony/routing/Tests/Loader/AbstractAnnotationLoaderTest.php b/vendor/symfony/routing/Tests/Loader/AbstractAnnotationLoaderTest.php index e8bbe8fcf43e1f774c3398732281e80c468320ee..0ce4a47ec1317dfa7e39599f202e29641ea427be 100644 --- a/vendor/symfony/routing/Tests/Loader/AbstractAnnotationLoaderTest.php +++ b/vendor/symfony/routing/Tests/Loader/AbstractAnnotationLoaderTest.php @@ -26,7 +26,7 @@ abstract class AbstractAnnotationLoaderTest extends TestCase public function getClassLoader($reader) { return $this->getMockBuilder('Symfony\Component\Routing\Loader\AnnotationClassLoader') - ->setConstructorArgs(array($reader)) + ->setConstructorArgs([$reader]) ->getMockForAbstractClass() ; } diff --git a/vendor/symfony/routing/Tests/Loader/AnnotationClassLoaderTest.php b/vendor/symfony/routing/Tests/Loader/AnnotationClassLoaderTest.php index 70db1ccd9ad6a47c6f0e8874c55adc0ed4c83ab5..078e6c71aad63c33d972bae793e9c23ab66196ef 100644 --- a/vendor/symfony/routing/Tests/Loader/AnnotationClassLoaderTest.php +++ b/vendor/symfony/routing/Tests/Loader/AnnotationClassLoaderTest.php @@ -11,35 +11,49 @@ namespace Symfony\Component\Routing\Tests\Loader; -use Symfony\Component\Routing\Annotation\Route; +use Doctrine\Common\Annotations\AnnotationReader; +use Doctrine\Common\Annotations\AnnotationRegistry; +use Symfony\Component\Routing\Annotation\Route as RouteAnnotation; +use Symfony\Component\Routing\Loader\AnnotationClassLoader; +use Symfony\Component\Routing\Route; +use Symfony\Component\Routing\Tests\Fixtures\AnnotationFixtures\AbstractClassController; +use Symfony\Component\Routing\Tests\Fixtures\AnnotationFixtures\ActionPathController; +use Symfony\Component\Routing\Tests\Fixtures\AnnotationFixtures\DefaultValueController; +use Symfony\Component\Routing\Tests\Fixtures\AnnotationFixtures\ExplicitLocalizedActionPathController; +use Symfony\Component\Routing\Tests\Fixtures\AnnotationFixtures\GlobalDefaultsClass; +use Symfony\Component\Routing\Tests\Fixtures\AnnotationFixtures\InvokableController; +use Symfony\Component\Routing\Tests\Fixtures\AnnotationFixtures\InvokableLocalizedController; +use Symfony\Component\Routing\Tests\Fixtures\AnnotationFixtures\LocalizedActionPathController; +use Symfony\Component\Routing\Tests\Fixtures\AnnotationFixtures\LocalizedMethodActionControllers; +use Symfony\Component\Routing\Tests\Fixtures\AnnotationFixtures\LocalizedPrefixLocalizedActionController; +use Symfony\Component\Routing\Tests\Fixtures\AnnotationFixtures\LocalizedPrefixMissingLocaleActionController; +use Symfony\Component\Routing\Tests\Fixtures\AnnotationFixtures\LocalizedPrefixMissingRouteLocaleActionController; +use Symfony\Component\Routing\Tests\Fixtures\AnnotationFixtures\LocalizedPrefixWithRouteWithoutLocale; +use Symfony\Component\Routing\Tests\Fixtures\AnnotationFixtures\MethodActionControllers; +use Symfony\Component\Routing\Tests\Fixtures\AnnotationFixtures\MissingRouteNameController; +use Symfony\Component\Routing\Tests\Fixtures\AnnotationFixtures\NothingButNameController; +use Symfony\Component\Routing\Tests\Fixtures\AnnotationFixtures\PrefixedActionLocalizedRouteController; +use Symfony\Component\Routing\Tests\Fixtures\AnnotationFixtures\PrefixedActionPathController; +use Symfony\Component\Routing\Tests\Fixtures\AnnotationFixtures\RequirementsWithoutPlaceholderNameController; +use Symfony\Component\Routing\Tests\Fixtures\AnnotationFixtures\RouteWithPrefixController; +use Symfony\Component\Routing\Tests\Fixtures\AnnotationFixtures\Utf8ActionControllers; class AnnotationClassLoaderTest extends AbstractAnnotationLoaderTest { - protected $loader; - private $reader; - - protected function setUp() - { - parent::setUp(); - - $this->reader = $this->getReader(); - $this->loader = $this->getClassLoader($this->reader); - } - /** - * @expectedException \InvalidArgumentException + * @var AnnotationClassLoader */ - public function testLoadMissingClass() - { - $this->loader->load('MissingClass'); - } + private $loader; - /** - * @expectedException \InvalidArgumentException - */ - public function testLoadAbstractClass() + protected function setUp(): void { - $this->loader->load('Symfony\Component\Routing\Tests\Fixtures\AnnotatedClasses\AbstractClass'); + $reader = new AnnotationReader(); + $this->loader = new class($reader) extends AnnotationClassLoader { + protected function configureRoute(Route $route, \ReflectionClass $class, \ReflectionMethod $method, $annot) + { + } + }; + AnnotationRegistry::registerLoader('class_exists'); } /** @@ -52,15 +66,15 @@ class AnnotationClassLoaderTest extends AbstractAnnotationLoaderTest public function provideTestSupportsChecksResource() { - return array( - array('class', true), - array('\fully\qualified\class\name', true), - array('namespaced\class\without\leading\slash', true), - array('ÿClassWithLegalSpecialCharacters', true), - array('5', false), - array('foo.foo', false), - array(null, false), - ); + return [ + ['class', true], + ['\fully\qualified\class\name', true], + ['namespaced\class\without\leading\slash', true], + ['ÿClassWithLegalSpecialCharacters', true], + ['5', false], + ['foo.foo', false], + [null, false], + ]; } public function testSupportsChecksTypeIfSpecified() @@ -69,187 +83,261 @@ class AnnotationClassLoaderTest extends AbstractAnnotationLoaderTest $this->assertFalse($this->loader->supports('class', 'foo'), '->supports() checks the resource type if specified'); } - public function getLoadTests() - { - return array( - array( - 'Symfony\Component\Routing\Tests\Fixtures\AnnotatedClasses\BarClass', - array('name' => 'route1', 'path' => '/path'), - array('arg2' => 'defaultValue2', 'arg3' => 'defaultValue3'), - ), - array( - 'Symfony\Component\Routing\Tests\Fixtures\AnnotatedClasses\BarClass', - array('defaults' => array('arg2' => 'foo'), 'requirements' => array('arg3' => '\w+')), - array('arg2' => 'defaultValue2', 'arg3' => 'defaultValue3'), - ), - array( - 'Symfony\Component\Routing\Tests\Fixtures\AnnotatedClasses\BarClass', - array('options' => array('foo' => 'bar')), - array('arg2' => 'defaultValue2', 'arg3' => 'defaultValue3'), - ), - array( - 'Symfony\Component\Routing\Tests\Fixtures\AnnotatedClasses\BarClass', - array('schemes' => array('https'), 'methods' => array('GET')), - array('arg2' => 'defaultValue2', 'arg3' => 'defaultValue3'), - ), - array( - 'Symfony\Component\Routing\Tests\Fixtures\AnnotatedClasses\BarClass', - array('condition' => 'context.getMethod() == "GET"'), - array('arg2' => 'defaultValue2', 'arg3' => 'defaultValue3'), - ), - ); + public function testSimplePathRoute() + { + $routes = $this->loader->load(ActionPathController::class); + $this->assertCount(1, $routes); + $this->assertEquals('/path', $routes->get('action')->getPath()); } /** - * @dataProvider getLoadTests + * @group legacy + * @expectedDeprecation A placeholder name must be a string (0 given). Did you forget to specify the placeholder key for the requirement "foo" in "Symfony\Component\Routing\Tests\Fixtures\AnnotationFixtures\RequirementsWithoutPlaceholderNameController"? + * @expectedDeprecation A placeholder name must be a string (1 given). Did you forget to specify the placeholder key for the requirement "\d+" in "Symfony\Component\Routing\Tests\Fixtures\AnnotationFixtures\RequirementsWithoutPlaceholderNameController"? + * @expectedDeprecation A placeholder name must be a string (0 given). Did you forget to specify the placeholder key for the requirement "foo" of route "foo" in "Symfony\Component\Routing\Tests\Fixtures\AnnotationFixtures\RequirementsWithoutPlaceholderNameController::foo()"? + * @expectedDeprecation A placeholder name must be a string (1 given). Did you forget to specify the placeholder key for the requirement "\d+" of route "foo" in "Symfony\Component\Routing\Tests\Fixtures\AnnotationFixtures\RequirementsWithoutPlaceholderNameController::foo()"? */ - public function testLoad($className, $routeData = array(), $methodArgs = array()) - { - $routeData = array_replace(array( - 'name' => 'route', - 'path' => '/', - 'requirements' => array(), - 'options' => array(), - 'defaults' => array(), - 'schemes' => array(), - 'methods' => array(), - 'condition' => '', - ), $routeData); - - $this->reader - ->expects($this->once()) - ->method('getMethodAnnotations') - ->will($this->returnValue(array($this->getAnnotatedRoute($routeData)))) - ; + public function testRequirementsWithoutPlaceholderName() + { + $this->loader->load(RequirementsWithoutPlaceholderNameController::class); + } - $routeCollection = $this->loader->load($className); - $route = $routeCollection->get($routeData['name']); - - $this->assertSame($routeData['path'], $route->getPath(), '->load preserves path annotation'); - $this->assertCount( - count($routeData['requirements']), - array_intersect_assoc($routeData['requirements'], $route->getRequirements()), - '->load preserves requirements annotation' - ); - $this->assertCount( - count($routeData['options']), - array_intersect_assoc($routeData['options'], $route->getOptions()), - '->load preserves options annotation' - ); - $this->assertCount( - count($routeData['defaults']), - $route->getDefaults(), - '->load preserves defaults annotation' - ); - $this->assertEquals($routeData['schemes'], $route->getSchemes(), '->load preserves schemes annotation'); - $this->assertEquals($routeData['methods'], $route->getMethods(), '->load preserves methods annotation'); - $this->assertSame($routeData['condition'], $route->getCondition(), '->load preserves condition annotation'); - } - - public function testClassRouteLoad() - { - $classRouteData = array( - 'name' => 'prefix_', - 'path' => '/prefix', - 'schemes' => array('https'), - 'methods' => array('GET'), - ); - - $methodRouteData = array( - 'name' => 'route1', - 'path' => '/path', - 'schemes' => array('http'), - 'methods' => array('POST', 'PUT'), - ); + public function testInvokableControllerLoader() + { + $routes = $this->loader->load(InvokableController::class); + $this->assertCount(1, $routes); + $this->assertEquals('/here', $routes->get('lol')->getPath()); + $this->assertEquals(['GET', 'POST'], $routes->get('lol')->getMethods()); + $this->assertEquals(['https'], $routes->get('lol')->getSchemes()); + } - $this->reader - ->expects($this->once()) - ->method('getClassAnnotation') - ->will($this->returnValue($this->getAnnotatedRoute($classRouteData))) - ; - $this->reader - ->expects($this->once()) - ->method('getMethodAnnotations') - ->will($this->returnValue(array($this->getAnnotatedRoute($methodRouteData)))) - ; + public function testInvokableLocalizedControllerLoading() + { + $routes = $this->loader->load(InvokableLocalizedController::class); + $this->assertCount(2, $routes); + $this->assertEquals('/here', $routes->get('action.en')->getPath()); + $this->assertEquals('/hier', $routes->get('action.nl')->getPath()); + } + + public function testLocalizedPathRoutes() + { + $routes = $this->loader->load(LocalizedActionPathController::class); + $this->assertCount(2, $routes); + $this->assertEquals('/path', $routes->get('action.en')->getPath()); + $this->assertEquals('/pad', $routes->get('action.nl')->getPath()); + } + + public function testLocalizedPathRoutesWithExplicitPathPropety() + { + $routes = $this->loader->load(ExplicitLocalizedActionPathController::class); + $this->assertCount(2, $routes); + $this->assertEquals('/path', $routes->get('action.en')->getPath()); + $this->assertEquals('/pad', $routes->get('action.nl')->getPath()); + } + + public function testDefaultValuesForMethods() + { + $routes = $this->loader->load(DefaultValueController::class); + $this->assertCount(3, $routes); + $this->assertEquals('/{default}/path', $routes->get('action')->getPath()); + $this->assertEquals('value', $routes->get('action')->getDefault('default')); + $this->assertEquals('Symfony', $routes->get('hello_with_default')->getDefault('name')); + $this->assertEquals('World', $routes->get('hello_without_default')->getDefault('name')); + } + + public function testMethodActionControllers() + { + $routes = $this->loader->load(MethodActionControllers::class); + $this->assertCount(2, $routes); + $this->assertEquals('/the/path', $routes->get('put')->getPath()); + $this->assertEquals('/the/path', $routes->get('post')->getPath()); + } + + public function testInvokableClassRouteLoadWithMethodAnnotation() + { + $routes = $this->loader->load(LocalizedMethodActionControllers::class); + $this->assertCount(4, $routes); + $this->assertEquals('/the/path', $routes->get('put.en')->getPath()); + $this->assertEquals('/the/path', $routes->get('post.en')->getPath()); + } + + public function testGlobalDefaultsRoutesLoadWithAnnotation() + { + $routes = $this->loader->load(GlobalDefaultsClass::class); + $this->assertCount(2, $routes); + + $specificLocaleRoute = $routes->get('specific_locale'); + + $this->assertSame('/defaults/specific-locale', $specificLocaleRoute->getPath()); + $this->assertSame('s_locale', $specificLocaleRoute->getDefault('_locale')); + $this->assertSame('g_format', $specificLocaleRoute->getDefault('_format')); - $routeCollection = $this->loader->load('Symfony\Component\Routing\Tests\Fixtures\AnnotatedClasses\BarClass'); - $route = $routeCollection->get($classRouteData['name'].$methodRouteData['name']); + $specificFormatRoute = $routes->get('specific_format'); - $this->assertSame($classRouteData['path'].$methodRouteData['path'], $route->getPath(), '->load concatenates class and method route path'); - $this->assertEquals(array_merge($classRouteData['schemes'], $methodRouteData['schemes']), $route->getSchemes(), '->load merges class and method route schemes'); - $this->assertEquals(array_merge($classRouteData['methods'], $methodRouteData['methods']), $route->getMethods(), '->load merges class and method route methods'); + $this->assertSame('/defaults/specific-format', $specificFormatRoute->getPath()); + $this->assertSame('g_locale', $specificFormatRoute->getDefault('_locale')); + $this->assertSame('s_format', $specificFormatRoute->getDefault('_format')); } - public function testInvokableClassRouteLoad() + public function testUtf8RoutesLoadWithAnnotation() { - $classRouteData = array( + $routes = $this->loader->load(Utf8ActionControllers::class); + $this->assertCount(2, $routes); + $this->assertTrue($routes->get('one')->getOption('utf8'), 'The route must accept utf8'); + $this->assertFalse($routes->get('two')->getOption('utf8'), 'The route must not accept utf8'); + } + + public function testRouteWithPathWithPrefix() + { + $routes = $this->loader->load(PrefixedActionPathController::class); + $this->assertCount(1, $routes); + $route = $routes->get('action'); + $this->assertEquals('/prefix/path', $route->getPath()); + $this->assertEquals('lol=fun', $route->getCondition()); + $this->assertEquals('frankdejonge.nl', $route->getHost()); + } + + public function testLocalizedRouteWithPathWithPrefix() + { + $routes = $this->loader->load(PrefixedActionLocalizedRouteController::class); + $this->assertCount(2, $routes); + $this->assertEquals('/prefix/path', $routes->get('action.en')->getPath()); + $this->assertEquals('/prefix/pad', $routes->get('action.nl')->getPath()); + } + + public function testLocalizedPrefixLocalizedRoute() + { + $routes = $this->loader->load(LocalizedPrefixLocalizedActionController::class); + $this->assertCount(2, $routes); + $this->assertEquals('/nl/actie', $routes->get('action.nl')->getPath()); + $this->assertEquals('/en/action', $routes->get('action.en')->getPath()); + } + + public function testInvokableClassMultipleRouteLoad() + { + $classRouteData1 = [ 'name' => 'route1', - 'path' => '/', - 'schemes' => array('https'), - 'methods' => array('GET'), - ); - - $this->reader - ->expects($this->exactly(2)) - ->method('getClassAnnotation') - ->will($this->returnValue($this->getAnnotatedRoute($classRouteData))) + 'path' => '/1', + 'schemes' => ['https'], + 'methods' => ['GET'], + ]; + + $classRouteData2 = [ + 'name' => 'route2', + 'path' => '/2', + 'schemes' => ['https'], + 'methods' => ['GET'], + ]; + + $reader = $this->getReader(); + $reader + ->expects($this->exactly(1)) + ->method('getClassAnnotations') + ->willReturn([new RouteAnnotation($classRouteData1), new RouteAnnotation($classRouteData2)]) ; - $this->reader + $reader ->expects($this->once()) ->method('getMethodAnnotations') - ->will($this->returnValue(array())) + ->willReturn([]) ; + $loader = new class($reader) extends AnnotationClassLoader { + protected function configureRoute(Route $route, \ReflectionClass $class, \ReflectionMethod $method, $annot) + { + } + }; - $routeCollection = $this->loader->load('Symfony\Component\Routing\Tests\Fixtures\AnnotatedClasses\BazClass'); - $route = $routeCollection->get($classRouteData['name']); + $routeCollection = $loader->load('Symfony\Component\Routing\Tests\Fixtures\AnnotatedClasses\BazClass'); + $route = $routeCollection->get($classRouteData1['name']); - $this->assertSame($classRouteData['path'], $route->getPath(), '->load preserves class route path'); - $this->assertEquals(array_merge($classRouteData['schemes'], $classRouteData['schemes']), $route->getSchemes(), '->load preserves class route schemes'); - $this->assertEquals(array_merge($classRouteData['methods'], $classRouteData['methods']), $route->getMethods(), '->load preserves class route methods'); + $this->assertSame($classRouteData1['path'], $route->getPath(), '->load preserves class route path'); + $this->assertEquals($classRouteData1['schemes'], $route->getSchemes(), '->load preserves class route schemes'); + $this->assertEquals($classRouteData1['methods'], $route->getMethods(), '->load preserves class route methods'); + + $route = $routeCollection->get($classRouteData2['name']); + + $this->assertSame($classRouteData2['path'], $route->getPath(), '->load preserves class route path'); + $this->assertEquals($classRouteData2['schemes'], $route->getSchemes(), '->load preserves class route schemes'); + $this->assertEquals($classRouteData2['methods'], $route->getMethods(), '->load preserves class route methods'); } - public function testInvokableClassWithMethodRouteLoad() + public function testMissingPrefixLocale() { - $classRouteData = array( - 'name' => 'route1', - 'path' => '/prefix', - 'schemes' => array('https'), - 'methods' => array('GET'), - ); + $this->expectException(\LogicException::class); + $this->loader->load(LocalizedPrefixMissingLocaleActionController::class); + } - $methodRouteData = array( - 'name' => 'route2', - 'path' => '/path', - 'schemes' => array('http'), - 'methods' => array('POST', 'PUT'), - ); + public function testMissingRouteLocale() + { + $this->expectException(\LogicException::class); + $this->loader->load(LocalizedPrefixMissingRouteLocaleActionController::class); + } - $this->reader - ->expects($this->once()) - ->method('getClassAnnotation') - ->will($this->returnValue($this->getAnnotatedRoute($classRouteData))) - ; - $this->reader + public function testRouteWithoutName() + { + $routes = $this->loader->load(MissingRouteNameController::class)->all(); + $this->assertCount(1, $routes); + $this->assertEquals('/path', reset($routes)->getPath()); + } + + public function testNothingButName() + { + $routes = $this->loader->load(NothingButNameController::class)->all(); + $this->assertCount(1, $routes); + $this->assertEquals('/', reset($routes)->getPath()); + } + + public function testNonExistingClass() + { + $this->expectException(\LogicException::class); + $this->loader->load('ClassThatDoesNotExist'); + } + + public function testLoadingAbstractClass() + { + $this->expectException(\LogicException::class); + $this->loader->load(AbstractClassController::class); + } + + public function testLocalizedPrefixWithoutRouteLocale() + { + $routes = $this->loader->load(LocalizedPrefixWithRouteWithoutLocale::class); + $this->assertCount(2, $routes); + $this->assertEquals('/en/suffix', $routes->get('action.en')->getPath()); + $this->assertEquals('/nl/suffix', $routes->get('action.nl')->getPath()); + } + + /** + * @requires function mb_strtolower + */ + public function testDefaultRouteName() + { + $methodRouteData = [ + 'name' => null, + ]; + + $reader = $this->getReader(); + $reader ->expects($this->once()) ->method('getMethodAnnotations') - ->will($this->returnValue(array($this->getAnnotatedRoute($methodRouteData)))) + ->willReturn([new RouteAnnotation($methodRouteData)]) ; - $routeCollection = $this->loader->load('Symfony\Component\Routing\Tests\Fixtures\AnnotatedClasses\BazClass'); - $route = $routeCollection->get($classRouteData['name']); - - $this->assertNull($route, '->load ignores class route'); + $loader = new class($reader) extends AnnotationClassLoader { + protected function configureRoute(Route $route, \ReflectionClass $class, \ReflectionMethod $method, $annot) + { + } + }; + $routeCollection = $loader->load('Symfony\Component\Routing\Tests\Fixtures\AnnotatedClasses\EncodingClass'); - $route = $routeCollection->get($classRouteData['name'].$methodRouteData['name']); + $defaultName = array_keys($routeCollection->all())[0]; - $this->assertSame($classRouteData['path'].$methodRouteData['path'], $route->getPath(), '->load concatenates class and method route path'); - $this->assertEquals(array_merge($classRouteData['schemes'], $methodRouteData['schemes']), $route->getSchemes(), '->load merges class and method route schemes'); - $this->assertEquals(array_merge($classRouteData['methods'], $methodRouteData['methods']), $route->getMethods(), '->load merges class and method route methods'); + $this->assertSame($defaultName, 'symfony_component_routing_tests_fixtures_annotatedclasses_encodingclass_routeà ction'); } - private function getAnnotatedRoute($data) + public function testLoadingRouteWithPrefix() { - return new Route($data); + $routes = $this->loader->load(RouteWithPrefixController::class); + $this->assertCount(1, $routes); + $this->assertEquals('/prefix/path', $routes->get('action')->getPath()); } } diff --git a/vendor/symfony/routing/Tests/Loader/AnnotationDirectoryLoaderTest.php b/vendor/symfony/routing/Tests/Loader/AnnotationDirectoryLoaderTest.php index 1e8ee394015e14784cffbe891830e663ddc98c79..858044d459f7ec27c3b74b8e71ff39ab556d79fc 100644 --- a/vendor/symfony/routing/Tests/Loader/AnnotationDirectoryLoaderTest.php +++ b/vendor/symfony/routing/Tests/Loader/AnnotationDirectoryLoaderTest.php @@ -11,15 +11,15 @@ namespace Symfony\Component\Routing\Tests\Loader; -use Symfony\Component\Routing\Loader\AnnotationDirectoryLoader; use Symfony\Component\Config\FileLocator; +use Symfony\Component\Routing\Loader\AnnotationDirectoryLoader; class AnnotationDirectoryLoaderTest extends AbstractAnnotationLoaderTest { protected $loader; protected $reader; - protected function setUp() + protected function setUp(): void { parent::setUp(); @@ -34,7 +34,13 @@ class AnnotationDirectoryLoaderTest extends AbstractAnnotationLoaderTest $this->reader ->expects($this->any()) ->method('getMethodAnnotations') - ->will($this->returnValue(array())) + ->willReturn([]) + ; + + $this->reader + ->expects($this->any()) + ->method('getClassAnnotations') + ->willReturn([]) ; $this->loader->load(__DIR__.'/../Fixtures/AnnotatedClasses'); @@ -42,17 +48,23 @@ class AnnotationDirectoryLoaderTest extends AbstractAnnotationLoaderTest public function testLoadIgnoresHiddenDirectories() { - $this->expectAnnotationsToBeReadFrom(array( + $this->expectAnnotationsToBeReadFrom([ 'Symfony\Component\Routing\Tests\Fixtures\AnnotatedClasses\BarClass', 'Symfony\Component\Routing\Tests\Fixtures\AnnotatedClasses\BazClass', - 'Symfony\Component\Routing\Tests\Fixtures\AnnotatedClasses\BazClass', 'Symfony\Component\Routing\Tests\Fixtures\AnnotatedClasses\FooClass', - )); + 'Symfony\Component\Routing\Tests\Fixtures\AnnotatedClasses\EncodingClass', + ]); $this->reader ->expects($this->any()) ->method('getMethodAnnotations') - ->will($this->returnValue(array())) + ->willReturn([]) + ; + + $this->reader + ->expects($this->any()) + ->method('getClassAnnotations') + ->willReturn([]) ; $this->loader->load(__DIR__.'/../Fixtures/AnnotatedClasses'); @@ -81,7 +93,7 @@ class AnnotationDirectoryLoaderTest extends AbstractAnnotationLoaderTest $this->reader ->expects($this->any()) ->method('getMethodAnnotations') - ->will($this->returnValue(array())) + ->willReturn([]) ; $this->loader->load(__DIR__.'/../Fixtures/AnnotatedClasses/FooClass.php'); @@ -89,10 +101,10 @@ class AnnotationDirectoryLoaderTest extends AbstractAnnotationLoaderTest private function expectAnnotationsToBeReadFrom(array $classes) { - $this->reader->expects($this->exactly(count($classes))) + $this->reader->expects($this->exactly(\count($classes))) ->method('getClassAnnotation') ->with($this->callback(function (\ReflectionClass $class) use ($classes) { - return in_array($class->getName(), $classes); + return \in_array($class->getName(), $classes); })); } } diff --git a/vendor/symfony/routing/Tests/Loader/AnnotationFileLoaderTest.php b/vendor/symfony/routing/Tests/Loader/AnnotationFileLoaderTest.php index 7f1d5765574a49284da8605ad7c8c88b23bbaf11..d0b670c3e2ed6cf574d180214651f86eab100b92 100644 --- a/vendor/symfony/routing/Tests/Loader/AnnotationFileLoaderTest.php +++ b/vendor/symfony/routing/Tests/Loader/AnnotationFileLoaderTest.php @@ -11,16 +11,16 @@ namespace Symfony\Component\Routing\Tests\Loader; -use Symfony\Component\Routing\Loader\AnnotationFileLoader; use Symfony\Component\Config\FileLocator; use Symfony\Component\Routing\Annotation\Route; +use Symfony\Component\Routing\Loader\AnnotationFileLoader; class AnnotationFileLoaderTest extends AbstractAnnotationLoaderTest { protected $loader; protected $reader; - protected function setUp() + protected function setUp(): void { parent::setUp(); @@ -35,9 +35,6 @@ class AnnotationFileLoaderTest extends AbstractAnnotationLoaderTest $this->loader->load(__DIR__.'/../Fixtures/AnnotatedClasses/FooClass.php'); } - /** - * @requires PHP 5.4 - */ public function testLoadTraitWithClassConstant() { $this->reader->expects($this->never())->method('getClassAnnotation'); @@ -45,24 +42,19 @@ class AnnotationFileLoaderTest extends AbstractAnnotationLoaderTest $this->loader->load(__DIR__.'/../Fixtures/AnnotatedClasses/FooTrait.php'); } - /** - * @expectedException \InvalidArgumentException - * @expectedExceptionMessage Did you forgot to add the "<?php" start tag at the beginning of the file? - */ public function testLoadFileWithoutStartTag() { + $this->expectException('InvalidArgumentException'); + $this->expectExceptionMessage('Did you forgot to add the "<?php" start tag at the beginning of the file?'); $this->loader->load(__DIR__.'/../Fixtures/OtherAnnotatedClasses/NoStartTagClass.php'); } - /** - * @requires PHP 5.6 - */ public function testLoadVariadic() { - $route = new Route(array('path' => '/path/to/{id}')); + $route = new Route(['path' => '/path/to/{id}']); $this->reader->expects($this->once())->method('getClassAnnotation'); $this->reader->expects($this->once())->method('getMethodAnnotations') - ->will($this->returnValue(array($route))); + ->willReturn([$route]); $this->loader->load(__DIR__.'/../Fixtures/OtherAnnotatedClasses/VariadicClass.php'); } @@ -78,6 +70,14 @@ class AnnotationFileLoaderTest extends AbstractAnnotationLoaderTest $this->loader->load(__DIR__.'/../Fixtures/OtherAnnotatedClasses/AnonymousClassInTrait.php'); } + public function testLoadAbstractClass() + { + $this->reader->expects($this->never())->method('getClassAnnotation'); + $this->reader->expects($this->never())->method('getMethodAnnotations'); + + $this->loader->load(__DIR__.'/../Fixtures/AnnotatedClasses/AbstractClass.php'); + } + public function testSupports() { $fixture = __DIR__.'/../Fixtures/annotated.php'; diff --git a/vendor/symfony/routing/Tests/Loader/DirectoryLoaderTest.php b/vendor/symfony/routing/Tests/Loader/DirectoryLoaderTest.php index fc29d371ed15d85b8616db08fff335d9ca8dcfe7..184d5089bc6331f34b311d070cbf3fc4c3de52c2 100644 --- a/vendor/symfony/routing/Tests/Loader/DirectoryLoaderTest.php +++ b/vendor/symfony/routing/Tests/Loader/DirectoryLoaderTest.php @@ -11,11 +11,11 @@ namespace Symfony\Component\Routing\Tests\Loader; +use Symfony\Component\Config\FileLocator; +use Symfony\Component\Config\Loader\LoaderResolver; +use Symfony\Component\Routing\Loader\AnnotationFileLoader; use Symfony\Component\Routing\Loader\DirectoryLoader; use Symfony\Component\Routing\Loader\YamlFileLoader; -use Symfony\Component\Routing\Loader\AnnotationFileLoader; -use Symfony\Component\Config\Loader\LoaderResolver; -use Symfony\Component\Config\FileLocator; use Symfony\Component\Routing\RouteCollection; class DirectoryLoaderTest extends AbstractAnnotationLoaderTest @@ -23,18 +23,18 @@ class DirectoryLoaderTest extends AbstractAnnotationLoaderTest private $loader; private $reader; - protected function setUp() + protected function setUp(): void { parent::setUp(); $locator = new FileLocator(); $this->reader = $this->getReader(); $this->loader = new DirectoryLoader($locator); - $resolver = new LoaderResolver(array( + $resolver = new LoaderResolver([ new YamlFileLoader($locator), new AnnotationFileLoader($locator, $this->getClassLoader($this->reader)), $this->loader, - )); + ]); $this->loader->setResolver($resolver); } diff --git a/vendor/symfony/routing/Tests/Loader/FileLocatorStub.php b/vendor/symfony/routing/Tests/Loader/FileLocatorStub.php new file mode 100644 index 0000000000000000000000000000000000000000..870c3cf4f4c386574f7eb222d6363451145c5b66 --- /dev/null +++ b/vendor/symfony/routing/Tests/Loader/FileLocatorStub.php @@ -0,0 +1,17 @@ +<?php + +namespace Symfony\Component\Routing\Tests\Loader; + +use Symfony\Component\Config\FileLocatorInterface; + +class FileLocatorStub implements FileLocatorInterface +{ + public function locate($name, $currentPath = null, $first = true) + { + if (0 === strpos($name, 'http')) { + return $name; + } + + return rtrim($currentPath, '/').'/'.$name; + } +} diff --git a/vendor/symfony/routing/Tests/Loader/GlobFileLoaderTest.php b/vendor/symfony/routing/Tests/Loader/GlobFileLoaderTest.php new file mode 100644 index 0000000000000000000000000000000000000000..e4e12b8815c3f9a127f83bd6d257300370f72bc7 --- /dev/null +++ b/vendor/symfony/routing/Tests/Loader/GlobFileLoaderTest.php @@ -0,0 +1,45 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Tests\Loader; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Config\FileLocator; +use Symfony\Component\Config\Resource\GlobResource; +use Symfony\Component\Routing\Loader\GlobFileLoader; +use Symfony\Component\Routing\RouteCollection; + +class GlobFileLoaderTest extends TestCase +{ + public function testSupports() + { + $loader = new GlobFileLoader(new FileLocator()); + + $this->assertTrue($loader->supports('any-path', 'glob'), '->supports() returns true if the resource has the glob type'); + $this->assertFalse($loader->supports('any-path'), '->supports() returns false if the resource is not of glob type'); + } + + public function testLoadAddsTheGlobResourceToTheContainer() + { + $loader = new GlobFileLoaderWithoutImport(new FileLocator()); + $collection = $loader->load(__DIR__.'/../Fixtures/directory/*.yml'); + + $this->assertEquals(new GlobResource(__DIR__.'/../Fixtures/directory', '/*.yml', false), $collection->getResources()[0]); + } +} + +class GlobFileLoaderWithoutImport extends GlobFileLoader +{ + public function import($resource, $type = null, $ignoreErrors = false, $sourceResource = null) + { + return new RouteCollection(); + } +} diff --git a/vendor/symfony/routing/Tests/Loader/ObjectRouteLoaderTest.php b/vendor/symfony/routing/Tests/Loader/ObjectRouteLoaderTest.php index 408fa0b45c48c349c9be70aea5b1747c5d0815b8..a00bc136ac94d0c242a4dce92e6e475eeeaccf63 100644 --- a/vendor/symfony/routing/Tests/Loader/ObjectRouteLoaderTest.php +++ b/vendor/symfony/routing/Tests/Loader/ObjectRouteLoaderTest.php @@ -18,7 +18,11 @@ use Symfony\Component\Routing\RouteCollection; class ObjectRouteLoaderTest extends TestCase { - public function testLoadCallsServiceAndReturnsCollection() + /** + * @group legacy + * @expectedDeprecation Referencing service route loaders with a single colon is deprecated since Symfony 4.1. Use my_route_provider_service::loadRoutes instead. + */ + public function testLoadCallsServiceAndReturnsCollectionWithLegacyNotation() { $loader = new ObjectRouteLoaderForTest(); @@ -26,9 +30,9 @@ class ObjectRouteLoaderTest extends TestCase $collection = new RouteCollection(); $collection->add('foo', new Route('/foo')); - $loader->loaderMap = array( + $loader->loaderMap = [ 'my_route_provider_service' => new RouteService($collection), - ); + ]; $actualRoutes = $loader->load( 'my_route_provider_service:loadRoutes', @@ -40,66 +44,85 @@ class ObjectRouteLoaderTest extends TestCase $this->assertNotEmpty($actualRoutes->getResources()); } + public function testLoadCallsServiceAndReturnsCollection() + { + $loader = new ObjectRouteLoaderForTest(); + + // create a basic collection that will be returned + $collection = new RouteCollection(); + $collection->add('foo', new Route('/foo')); + + $loader->loaderMap = [ + 'my_route_provider_service' => new RouteService($collection), + ]; + + $actualRoutes = $loader->load( + 'my_route_provider_service::loadRoutes', + 'service' + ); + + $this->assertSame($collection, $actualRoutes); + // the service file should be listed as a resource + $this->assertNotEmpty($actualRoutes->getResources()); + } + /** - * @expectedException \InvalidArgumentException * @dataProvider getBadResourceStrings */ - public function testExceptionWithoutSyntax($resourceString) + public function testExceptionWithoutSyntax(string $resourceString): void { + $this->expectException('InvalidArgumentException'); $loader = new ObjectRouteLoaderForTest(); $loader->load($resourceString); } public function getBadResourceStrings() { - return array( - array('Foo'), - array('Bar::baz'), - array('Foo:Bar:baz'), - ); + return [ + ['Foo:Bar:baz'], + ['Foo::Bar::baz'], + ['Foo:'], + ['Foo::'], + [':Foo'], + ['::Foo'], + ]; } - /** - * @expectedException \LogicException - */ public function testExceptionOnNoObjectReturned() { + $this->expectException('LogicException'); $loader = new ObjectRouteLoaderForTest(); - $loader->loaderMap = array('my_service' => 'NOT_AN_OBJECT'); - $loader->load('my_service:method'); + $loader->loaderMap = ['my_service' => 'NOT_AN_OBJECT']; + $loader->load('my_service::method'); } - /** - * @expectedException \BadMethodCallException - */ public function testExceptionOnBadMethod() { + $this->expectException('BadMethodCallException'); $loader = new ObjectRouteLoaderForTest(); - $loader->loaderMap = array('my_service' => new \stdClass()); - $loader->load('my_service:method'); + $loader->loaderMap = ['my_service' => new \stdClass()]; + $loader->load('my_service::method'); } - /** - * @expectedException \LogicException - */ public function testExceptionOnMethodNotReturningCollection() { + $this->expectException('LogicException'); $service = $this->getMockBuilder('stdClass') - ->setMethods(array('loadRoutes')) + ->setMethods(['loadRoutes']) ->getMock(); $service->expects($this->once()) ->method('loadRoutes') - ->will($this->returnValue('NOT_A_COLLECTION')); + ->willReturn('NOT_A_COLLECTION'); $loader = new ObjectRouteLoaderForTest(); - $loader->loaderMap = array('my_service' => $service); - $loader->load('my_service:loadRoutes'); + $loader->loaderMap = ['my_service' => $service]; + $loader->load('my_service::loadRoutes'); } } class ObjectRouteLoaderForTest extends ObjectRouteLoader { - public $loaderMap = array(); + public $loaderMap = []; protected function getServiceObject($id) { diff --git a/vendor/symfony/routing/Tests/Loader/PhpFileLoaderTest.php b/vendor/symfony/routing/Tests/Loader/PhpFileLoaderTest.php index 608d84ed7a20feccdb7ea64e2eaa898e72fca435..71f9df15470a1d5aae8796e2b43111ed29683d81 100644 --- a/vendor/symfony/routing/Tests/Loader/PhpFileLoaderTest.php +++ b/vendor/symfony/routing/Tests/Loader/PhpFileLoaderTest.php @@ -33,7 +33,7 @@ class PhpFileLoaderTest extends TestCase public function testLoadWithRoute() { - $loader = new PhpFileLoader(new FileLocator(array(__DIR__.'/../Fixtures'))); + $loader = new PhpFileLoader(new FileLocator([__DIR__.'/../Fixtures'])); $routeCollection = $loader->load('validpattern.php'); $routes = $routeCollection->all(); @@ -45,14 +45,14 @@ class PhpFileLoaderTest extends TestCase $this->assertSame('MyBlogBundle:Blog:show', $route->getDefault('_controller')); $this->assertSame('{locale}.example.com', $route->getHost()); $this->assertSame('RouteCompiler', $route->getOption('compiler_class')); - $this->assertEquals(array('GET', 'POST', 'PUT', 'OPTIONS'), $route->getMethods()); - $this->assertEquals(array('https'), $route->getSchemes()); + $this->assertEquals(['GET', 'POST', 'PUT', 'OPTIONS'], $route->getMethods()); + $this->assertEquals(['https'], $route->getSchemes()); } } public function testLoadWithImport() { - $loader = new PhpFileLoader(new FileLocator(array(__DIR__.'/../Fixtures'))); + $loader = new PhpFileLoader(new FileLocator([__DIR__.'/../Fixtures'])); $routeCollection = $loader->load('validresource.php'); $routes = $routeCollection->all(); @@ -64,14 +64,14 @@ class PhpFileLoaderTest extends TestCase $this->assertSame('MyBlogBundle:Blog:show', $route->getDefault('_controller')); $this->assertSame('{locale}.example.com', $route->getHost()); $this->assertSame('RouteCompiler', $route->getOption('compiler_class')); - $this->assertEquals(array('GET', 'POST', 'PUT', 'OPTIONS'), $route->getMethods()); - $this->assertEquals(array('https'), $route->getSchemes()); + $this->assertEquals(['GET', 'POST', 'PUT', 'OPTIONS'], $route->getMethods()); + $this->assertEquals(['https'], $route->getSchemes()); } } public function testThatDefiningVariableInConfigFileHasNoSideEffects() { - $locator = new FileLocator(array(__DIR__.'/../Fixtures')); + $locator = new FileLocator([__DIR__.'/../Fixtures']); $loader = new PhpFileLoader($locator); $routeCollection = $loader->load('with_define_path_variable.php'); $resources = $routeCollection->getResources(); @@ -84,36 +84,159 @@ class PhpFileLoaderTest extends TestCase ); } + public function testLoadingRouteWithDefaults() + { + $loader = new PhpFileLoader(new FileLocator([__DIR__.'/../Fixtures'])); + $routes = $loader->load('defaults.php'); + + $this->assertCount(1, $routes); + + $defaultsRoute = $routes->get('defaults'); + + $this->assertSame('/defaults', $defaultsRoute->getPath()); + $this->assertSame('en', $defaultsRoute->getDefault('_locale')); + $this->assertSame('html', $defaultsRoute->getDefault('_format')); + } + + public function testLoadingImportedRoutesWithDefaults() + { + $loader = new PhpFileLoader(new FileLocator([__DIR__.'/../Fixtures'])); + $routes = $loader->load('importer-with-defaults.php'); + + $this->assertCount(2, $routes); + + $expectedRoutes = new RouteCollection(); + $expectedRoutes->add('one', $localeRoute = new Route('/defaults/one')); + $localeRoute->setDefault('_locale', 'g_locale'); + $localeRoute->setDefault('_format', 'g_format'); + $expectedRoutes->add('two', $formatRoute = new Route('/defaults/two')); + $formatRoute->setDefault('_locale', 'g_locale'); + $formatRoute->setDefault('_format', 'g_format'); + $formatRoute->setDefault('specific', 'imported'); + + $expectedRoutes->addResource(new FileResource(__DIR__.'/../Fixtures/imported-with-defaults.php')); + $expectedRoutes->addResource(new FileResource(__DIR__.'/../Fixtures/importer-with-defaults.php')); + + $this->assertEquals($expectedRoutes, $routes); + } + + public function testLoadingUtf8Route() + { + $loader = new PhpFileLoader(new FileLocator([__DIR__.'/../Fixtures/localized'])); + $routes = $loader->load('utf8.php'); + + $this->assertCount(2, $routes); + + $expectedRoutes = new RouteCollection(); + $expectedRoutes->add('some_route', new Route('/')); + + $expectedRoutes->add('some_utf8_route', $route = new Route('/utf8')); + $route->setOption('utf8', true); + + $expectedRoutes->addResource(new FileResource(__DIR__.'/../Fixtures/localized/utf8.php')); + + $this->assertEquals($expectedRoutes, $routes); + } + + public function testLoadingUtf8ImportedRoutes() + { + $loader = new PhpFileLoader(new FileLocator([__DIR__.'/../Fixtures/localized'])); + $routes = $loader->load('importer-with-utf8.php'); + + $this->assertCount(2, $routes); + + $expectedRoutes = new RouteCollection(); + $expectedRoutes->add('utf8_one', $one = new Route('/one')); + $one->setOption('utf8', true); + + $expectedRoutes->add('utf8_two', $two = new Route('/two')); + $two->setOption('utf8', true); + + $expectedRoutes->addResource(new FileResource(__DIR__.'/../Fixtures/localized/imported-with-utf8.php')); + $expectedRoutes->addResource(new FileResource(__DIR__.'/../Fixtures/localized/importer-with-utf8.php')); + + $this->assertEquals($expectedRoutes, $routes); + } + public function testRoutingConfigurator() { - $locator = new FileLocator(array(__DIR__.'/../Fixtures')); + $locator = new FileLocator([__DIR__.'/../Fixtures']); $loader = new PhpFileLoader($locator); - $routeCollection = $loader->load('php_dsl.php'); + $routeCollectionClosure = $loader->load('php_dsl.php'); + $routeCollectionObject = $loader->load('php_object_dsl.php'); $expectedCollection = new RouteCollection(); $expectedCollection->add('foo', (new Route('/foo')) - ->setOptions(array('utf8' => true)) + ->setOptions(['utf8' => true]) ->setCondition('abc') ); $expectedCollection->add('buz', (new Route('/zub')) - ->setDefaults(array('_controller' => 'foo:act')) + ->setDefaults(['_controller' => 'foo:act']) + ); + $expectedCollection->add('c_root', (new Route('/sub/pub/')) + ->setRequirements(['id' => '\d+']) ); $expectedCollection->add('c_bar', (new Route('/sub/pub/bar')) - ->setRequirements(array('id' => '\d+')) + ->setRequirements(['id' => '\d+']) ); $expectedCollection->add('c_pub_buz', (new Route('/sub/pub/buz')) ->setHost('host') - ->setRequirements(array('id' => '\d+')) + ->setRequirements(['id' => '\d+']) ); + $expectedCollection->add('z_c_root', new Route('/zub/pub/')); + $expectedCollection->add('z_c_bar', new Route('/zub/pub/bar')); + $expectedCollection->add('z_c_pub_buz', (new Route('/zub/pub/buz'))->setHost('host')); + $expectedCollection->add('r_root', new Route('/bus')); + $expectedCollection->add('r_bar', new Route('/bus/bar/')); $expectedCollection->add('ouf', (new Route('/ouf')) - ->setSchemes(array('https')) - ->setMethods(array('GET')) - ->setDefaults(array('id' => 0)) + ->setSchemes(['https']) + ->setMethods(['GET']) + ->setDefaults(['id' => 0]) ); $expectedCollection->addResource(new FileResource(realpath(__DIR__.'/../Fixtures/php_dsl_sub.php'))); - $expectedCollection->addResource(new FileResource(realpath(__DIR__.'/../Fixtures/php_dsl.php'))); + $expectedCollection->addResource(new FileResource(realpath(__DIR__.'/../Fixtures/php_dsl_sub_root.php'))); + + $expectedCollectionClosure = $expectedCollection; + $expectedCollectionObject = clone $expectedCollection; + + $expectedCollectionClosure->addResource(new FileResource(realpath(__DIR__.'/../Fixtures/php_dsl.php'))); + $expectedCollectionObject->addResource(new FileResource(realpath(__DIR__.'/../Fixtures/php_object_dsl.php'))); + + $this->assertEquals($expectedCollectionClosure, $routeCollectionClosure); + $this->assertEquals($expectedCollectionObject, $routeCollectionObject); + } + + public function testRoutingConfiguratorCanImportGlobPatterns() + { + $locator = new FileLocator([__DIR__.'/../Fixtures/glob']); + $loader = new PhpFileLoader($locator); + $routeCollection = $loader->load('php_dsl.php'); + + $route = $routeCollection->get('bar_route'); + $this->assertSame('AppBundle:Bar:view', $route->getDefault('_controller')); + + $route = $routeCollection->get('baz_route'); + $this->assertSame('AppBundle:Baz:view', $route->getDefault('_controller')); + } + + public function testRoutingI18nConfigurator() + { + $locator = new FileLocator([__DIR__.'/../Fixtures']); + $loader = new PhpFileLoader($locator); + $routeCollection = $loader->load('php_dsl_i18n.php'); + + $expectedCollection = new RouteCollection(); + + $expectedCollection->add('foo.en', (new Route('/glish/foo'))->setDefaults(['_locale' => 'en', '_canonical_route' => 'foo'])); + $expectedCollection->add('bar.en', (new Route('/glish/bar'))->setDefaults(['_locale' => 'en', '_canonical_route' => 'bar'])); + $expectedCollection->add('baz.en', (new Route('/baz'))->setDefaults(['_locale' => 'en', '_canonical_route' => 'baz'])); + $expectedCollection->add('c_foo.fr', (new Route('/ench/pub/foo'))->setDefaults(['_locale' => 'fr', '_canonical_route' => 'c_foo'])); + $expectedCollection->add('c_bar.fr', (new Route('/ench/pub/bar'))->setDefaults(['_locale' => 'fr', '_canonical_route' => 'c_bar'])); + + $expectedCollection->addResource(new FileResource(realpath(__DIR__.'/../Fixtures/php_dsl_sub_i18n.php'))); + $expectedCollection->addResource(new FileResource(realpath(__DIR__.'/../Fixtures/php_dsl_i18n.php'))); $this->assertEquals($expectedCollection, $routeCollection); } diff --git a/vendor/symfony/routing/Tests/Loader/XmlFileLoaderTest.php b/vendor/symfony/routing/Tests/Loader/XmlFileLoaderTest.php index 221434b0068aa8467b9436f1aed7df6071bb30ba..e27149f93125cc6ffcb48df71c8f3f2201ba120b 100644 --- a/vendor/symfony/routing/Tests/Loader/XmlFileLoaderTest.php +++ b/vendor/symfony/routing/Tests/Loader/XmlFileLoaderTest.php @@ -13,7 +13,10 @@ namespace Symfony\Component\Routing\Tests\Loader; use PHPUnit\Framework\TestCase; use Symfony\Component\Config\FileLocator; +use Symfony\Component\Config\Resource\FileResource; use Symfony\Component\Routing\Loader\XmlFileLoader; +use Symfony\Component\Routing\Route; +use Symfony\Component\Routing\RouteCollection; use Symfony\Component\Routing\Tests\Fixtures\CustomXmlFileLoader; class XmlFileLoaderTest extends TestCase @@ -31,7 +34,7 @@ class XmlFileLoaderTest extends TestCase public function testLoadWithRoute() { - $loader = new XmlFileLoader(new FileLocator(array(__DIR__.'/../Fixtures'))); + $loader = new XmlFileLoader(new FileLocator([__DIR__.'/../Fixtures'])); $routeCollection = $loader->load('validpattern.xml'); $route = $routeCollection->get('blog_show'); @@ -41,14 +44,14 @@ class XmlFileLoaderTest extends TestCase $this->assertSame('MyBundle:Blog:show', $route->getDefault('_controller')); $this->assertSame('\w+', $route->getRequirement('locale')); $this->assertSame('RouteCompiler', $route->getOption('compiler_class')); - $this->assertEquals(array('GET', 'POST', 'PUT', 'OPTIONS'), $route->getMethods()); - $this->assertEquals(array('https'), $route->getSchemes()); + $this->assertEquals(['GET', 'POST', 'PUT', 'OPTIONS'], $route->getMethods()); + $this->assertEquals(['https'], $route->getSchemes()); $this->assertEquals('context.getMethod() == "GET"', $route->getCondition()); } public function testLoadWithNamespacePrefix() { - $loader = new XmlFileLoader(new FileLocator(array(__DIR__.'/../Fixtures'))); + $loader = new XmlFileLoader(new FileLocator([__DIR__.'/../Fixtures'])); $routeCollection = $loader->load('namespaceprefix.xml'); $this->assertCount(1, $routeCollection->all(), 'One route is loaded'); @@ -66,7 +69,7 @@ class XmlFileLoaderTest extends TestCase public function testLoadWithImport() { - $loader = new XmlFileLoader(new FileLocator(array(__DIR__.'/../Fixtures'))); + $loader = new XmlFileLoader(new FileLocator([__DIR__.'/../Fixtures'])); $routeCollection = $loader->load('validresource.xml'); $routes = $routeCollection->all(); @@ -83,44 +86,156 @@ class XmlFileLoaderTest extends TestCase } } + public function testLoadingRouteWithDefaults() + { + $loader = new XmlFileLoader(new FileLocator([__DIR__.'/../Fixtures'])); + $routes = $loader->load('defaults.xml'); + + $this->assertCount(1, $routes); + + $defaultsRoute = $routes->get('defaults'); + + $this->assertSame('/defaults', $defaultsRoute->getPath()); + $this->assertSame('en', $defaultsRoute->getDefault('_locale')); + $this->assertSame('html', $defaultsRoute->getDefault('_format')); + } + + public function testLoadingImportedRoutesWithDefaults() + { + $loader = new XmlFileLoader(new FileLocator([__DIR__.'/../Fixtures'])); + $routes = $loader->load('importer-with-defaults.xml'); + + $this->assertCount(2, $routes); + + $expectedRoutes = new RouteCollection(); + $expectedRoutes->add('one', $localeRoute = new Route('/defaults/one')); + $localeRoute->setDefault('_locale', 'g_locale'); + $localeRoute->setDefault('_format', 'g_format'); + $expectedRoutes->add('two', $formatRoute = new Route('/defaults/two')); + $formatRoute->setDefault('_locale', 'g_locale'); + $formatRoute->setDefault('_format', 'g_format'); + $formatRoute->setDefault('specific', 'imported'); + + $expectedRoutes->addResource(new FileResource(__DIR__.'/../Fixtures/imported-with-defaults.xml')); + $expectedRoutes->addResource(new FileResource(__DIR__.'/../Fixtures/importer-with-defaults.xml')); + + $this->assertEquals($expectedRoutes, $routes); + } + + public function testLoadingUtf8Route() + { + $loader = new XmlFileLoader(new FileLocator([__DIR__.'/../Fixtures/localized'])); + $routes = $loader->load('utf8.xml'); + + $this->assertCount(2, $routes); + + $expectedRoutes = new RouteCollection(); + $expectedRoutes->add('app_utf8', $route = new Route('/utf8')); + $route->setOption('utf8', true); + + $expectedRoutes->add('app_no_utf8', $route = new Route('/no-utf8')); + $route->setOption('utf8', false); + + $expectedRoutes->addResource(new FileResource(__DIR__.'/../Fixtures/localized/utf8.xml')); + + $this->assertEquals($expectedRoutes, $routes); + } + + public function testLoadingUtf8ImportedRoutes() + { + $loader = new XmlFileLoader(new FileLocator([__DIR__.'/../Fixtures/localized'])); + $routes = $loader->load('importer-with-utf8.xml'); + + $this->assertCount(2, $routes); + + $expectedRoutes = new RouteCollection(); + $expectedRoutes->add('utf8_one', $one = new Route('/one')); + $one->setOption('utf8', true); + + $expectedRoutes->add('utf8_two', $two = new Route('/two')); + $two->setOption('utf8', true); + + $expectedRoutes->addResource(new FileResource(__DIR__.'/../Fixtures/localized/imported-with-utf8.xml')); + $expectedRoutes->addResource(new FileResource(__DIR__.'/../Fixtures/localized/importer-with-utf8.xml')); + + $this->assertEquals($expectedRoutes, $routes); + } + + public function testLoadLocalized() + { + $loader = new XmlFileLoader(new FileLocator([__DIR__.'/../Fixtures'])); + $routeCollection = $loader->load('localized.xml'); + $routes = $routeCollection->all(); + + $this->assertCount(2, $routes, 'Two routes are loaded'); + $this->assertContainsOnly('Symfony\Component\Routing\Route', $routes); + + $this->assertEquals('/route', $routeCollection->get('localized.fr')->getPath()); + $this->assertEquals('/path', $routeCollection->get('localized.en')->getPath()); + } + + public function testLocalizedImports() + { + $loader = new XmlFileLoader(new FileLocator([__DIR__.'/../Fixtures/localized'])); + $routeCollection = $loader->load('importer-with-locale.xml'); + $routes = $routeCollection->all(); + + $this->assertCount(2, $routes, 'Two routes are loaded'); + $this->assertContainsOnly('Symfony\Component\Routing\Route', $routes); + + $this->assertEquals('/le-prefix/le-suffix', $routeCollection->get('imported.fr')->getPath()); + $this->assertEquals('/the-prefix/suffix', $routeCollection->get('imported.en')->getPath()); + } + + public function testLocalizedImportsOfNotLocalizedRoutes() + { + $loader = new XmlFileLoader(new FileLocator([__DIR__.'/../Fixtures/localized'])); + $routeCollection = $loader->load('importer-with-locale-imports-non-localized-route.xml'); + $routes = $routeCollection->all(); + + $this->assertCount(2, $routes, 'Two routes are loaded'); + $this->assertContainsOnly('Symfony\Component\Routing\Route', $routes); + + $this->assertEquals('/le-prefix/suffix', $routeCollection->get('imported.fr')->getPath()); + $this->assertEquals('/the-prefix/suffix', $routeCollection->get('imported.en')->getPath()); + } + /** - * @expectedException \InvalidArgumentException * @dataProvider getPathsToInvalidFiles */ public function testLoadThrowsExceptionWithInvalidFile($filePath) { - $loader = new XmlFileLoader(new FileLocator(array(__DIR__.'/../Fixtures'))); + $this->expectException('InvalidArgumentException'); + $loader = new XmlFileLoader(new FileLocator([__DIR__.'/../Fixtures'])); $loader->load($filePath); } /** - * @expectedException \InvalidArgumentException * @dataProvider getPathsToInvalidFiles */ public function testLoadThrowsExceptionWithInvalidFileEvenWithoutSchemaValidation($filePath) { - $loader = new CustomXmlFileLoader(new FileLocator(array(__DIR__.'/../Fixtures'))); + $this->expectException('InvalidArgumentException'); + $loader = new CustomXmlFileLoader(new FileLocator([__DIR__.'/../Fixtures'])); $loader->load($filePath); } public function getPathsToInvalidFiles() { - return array(array('nonvalidnode.xml'), array('nonvalidroute.xml'), array('nonvalid.xml'), array('missing_id.xml'), array('missing_path.xml')); + return [['nonvalidnode.xml'], ['nonvalidroute.xml'], ['nonvalid.xml'], ['missing_id.xml'], ['missing_path.xml']]; } - /** - * @expectedException \InvalidArgumentException - * @expectedExceptionMessage Document types are not allowed. - */ public function testDocTypeIsNotAllowed() { - $loader = new XmlFileLoader(new FileLocator(array(__DIR__.'/../Fixtures'))); + $this->expectException('InvalidArgumentException'); + $this->expectExceptionMessage('Document types are not allowed.'); + $loader = new XmlFileLoader(new FileLocator([__DIR__.'/../Fixtures'])); $loader->load('withdoctype.xml'); } public function testNullValues() { - $loader = new XmlFileLoader(new FileLocator(array(__DIR__.'/../Fixtures'))); + $loader = new XmlFileLoader(new FileLocator([__DIR__.'/../Fixtures'])); $routeCollection = $loader->load('null_values.xml'); $route = $routeCollection->get('blog_show'); @@ -134,12 +249,12 @@ class XmlFileLoaderTest extends TestCase public function testScalarDataTypeDefaults() { - $loader = new XmlFileLoader(new FileLocator(array(__DIR__.'/../Fixtures'))); + $loader = new XmlFileLoader(new FileLocator([__DIR__.'/../Fixtures'])); $routeCollection = $loader->load('scalar_defaults.xml'); $route = $routeCollection->get('blog'); $this->assertSame( - array( + [ '_controller' => 'AcmeBlogBundle:Blog:index', 'slug' => null, 'published' => true, @@ -150,147 +265,147 @@ class XmlFileLoaderTest extends TestCase 'locked' => false, 'foo' => null, 'bar' => null, - ), + ], $route->getDefaults() ); } public function testListDefaults() { - $loader = new XmlFileLoader(new FileLocator(array(__DIR__.'/../Fixtures'))); + $loader = new XmlFileLoader(new FileLocator([__DIR__.'/../Fixtures'])); $routeCollection = $loader->load('list_defaults.xml'); $route = $routeCollection->get('blog'); $this->assertSame( - array( + [ '_controller' => 'AcmeBlogBundle:Blog:index', - 'values' => array(true, 1, 3.5, 'foo'), - ), + 'values' => [true, 1, 3.5, 'foo'], + ], $route->getDefaults() ); } public function testListInListDefaults() { - $loader = new XmlFileLoader(new FileLocator(array(__DIR__.'/../Fixtures'))); + $loader = new XmlFileLoader(new FileLocator([__DIR__.'/../Fixtures'])); $routeCollection = $loader->load('list_in_list_defaults.xml'); $route = $routeCollection->get('blog'); $this->assertSame( - array( + [ '_controller' => 'AcmeBlogBundle:Blog:index', - 'values' => array(array(true, 1, 3.5, 'foo')), - ), + 'values' => [[true, 1, 3.5, 'foo']], + ], $route->getDefaults() ); } public function testListInMapDefaults() { - $loader = new XmlFileLoader(new FileLocator(array(__DIR__.'/../Fixtures'))); + $loader = new XmlFileLoader(new FileLocator([__DIR__.'/../Fixtures'])); $routeCollection = $loader->load('list_in_map_defaults.xml'); $route = $routeCollection->get('blog'); $this->assertSame( - array( + [ '_controller' => 'AcmeBlogBundle:Blog:index', - 'values' => array('list' => array(true, 1, 3.5, 'foo')), - ), + 'values' => ['list' => [true, 1, 3.5, 'foo']], + ], $route->getDefaults() ); } public function testMapDefaults() { - $loader = new XmlFileLoader(new FileLocator(array(__DIR__.'/../Fixtures'))); + $loader = new XmlFileLoader(new FileLocator([__DIR__.'/../Fixtures'])); $routeCollection = $loader->load('map_defaults.xml'); $route = $routeCollection->get('blog'); $this->assertSame( - array( + [ '_controller' => 'AcmeBlogBundle:Blog:index', - 'values' => array( + 'values' => [ 'public' => true, 'page' => 1, 'price' => 3.5, 'title' => 'foo', - ), - ), + ], + ], $route->getDefaults() ); } public function testMapInListDefaults() { - $loader = new XmlFileLoader(new FileLocator(array(__DIR__.'/../Fixtures'))); + $loader = new XmlFileLoader(new FileLocator([__DIR__.'/../Fixtures'])); $routeCollection = $loader->load('map_in_list_defaults.xml'); $route = $routeCollection->get('blog'); $this->assertSame( - array( + [ '_controller' => 'AcmeBlogBundle:Blog:index', - 'values' => array(array( + 'values' => [[ 'public' => true, 'page' => 1, 'price' => 3.5, 'title' => 'foo', - )), - ), + ]], + ], $route->getDefaults() ); } public function testMapInMapDefaults() { - $loader = new XmlFileLoader(new FileLocator(array(__DIR__.'/../Fixtures'))); + $loader = new XmlFileLoader(new FileLocator([__DIR__.'/../Fixtures'])); $routeCollection = $loader->load('map_in_map_defaults.xml'); $route = $routeCollection->get('blog'); $this->assertSame( - array( + [ '_controller' => 'AcmeBlogBundle:Blog:index', - 'values' => array('map' => array( + 'values' => ['map' => [ 'public' => true, 'page' => 1, 'price' => 3.5, 'title' => 'foo', - )), - ), + ]], + ], $route->getDefaults() ); } public function testNullValuesInList() { - $loader = new XmlFileLoader(new FileLocator(array(__DIR__.'/../Fixtures'))); + $loader = new XmlFileLoader(new FileLocator([__DIR__.'/../Fixtures'])); $routeCollection = $loader->load('list_null_values.xml'); $route = $routeCollection->get('blog'); - $this->assertSame(array(null, null, null, null, null, null), $route->getDefault('list')); + $this->assertSame([null, null, null, null, null, null], $route->getDefault('list')); } public function testNullValuesInMap() { - $loader = new XmlFileLoader(new FileLocator(array(__DIR__.'/../Fixtures'))); + $loader = new XmlFileLoader(new FileLocator([__DIR__.'/../Fixtures'])); $routeCollection = $loader->load('map_null_values.xml'); $route = $routeCollection->get('blog'); $this->assertSame( - array( + [ 'boolean' => null, 'integer' => null, 'float' => null, 'string' => null, 'list' => null, 'map' => null, - ), + ], $route->getDefault('map') ); } public function testLoadRouteWithControllerAttribute() { - $loader = new XmlFileLoader(new FileLocator(array(__DIR__.'/../Fixtures/controller'))); + $loader = new XmlFileLoader(new FileLocator([__DIR__.'/../Fixtures/controller'])); $routeCollection = $loader->load('routing.xml'); $route = $routeCollection->get('app_homepage'); @@ -300,7 +415,7 @@ class XmlFileLoaderTest extends TestCase public function testLoadRouteWithoutControllerAttribute() { - $loader = new XmlFileLoader(new FileLocator(array(__DIR__.'/../Fixtures/controller'))); + $loader = new XmlFileLoader(new FileLocator([__DIR__.'/../Fixtures/controller'])); $routeCollection = $loader->load('routing.xml'); $route = $routeCollection->get('app_logout'); @@ -310,7 +425,7 @@ class XmlFileLoaderTest extends TestCase public function testLoadRouteWithControllerSetInDefaults() { - $loader = new XmlFileLoader(new FileLocator(array(__DIR__.'/../Fixtures/controller'))); + $loader = new XmlFileLoader(new FileLocator([__DIR__.'/../Fixtures/controller'])); $routeCollection = $loader->load('routing.xml'); $route = $routeCollection->get('app_blog'); @@ -318,13 +433,11 @@ class XmlFileLoaderTest extends TestCase $this->assertSame('AppBundle:Blog:list', $route->getDefault('_controller')); } - /** - * @expectedException \InvalidArgumentException - * @expectedExceptionMessageRegExp /The routing file "[^"]*" must not specify both the "controller" attribute and the defaults key "_controller" for "app_blog"/ - */ public function testOverrideControllerInDefaults() { - $loader = new XmlFileLoader(new FileLocator(array(__DIR__.'/../Fixtures/controller'))); + $this->expectException('InvalidArgumentException'); + $this->expectExceptionMessageRegExp('/The routing file "[^"]*" must not specify both the "controller" attribute and the defaults key "_controller" for "app_blog"/'); + $loader = new XmlFileLoader(new FileLocator([__DIR__.'/../Fixtures/controller'])); $loader->load('override_defaults.xml'); } @@ -333,7 +446,7 @@ class XmlFileLoaderTest extends TestCase */ public function testImportRouteWithController($file) { - $loader = new XmlFileLoader(new FileLocator(array(__DIR__.'/../Fixtures/controller'))); + $loader = new XmlFileLoader(new FileLocator([__DIR__.'/../Fixtures/controller'])); $routeCollection = $loader->load($file); $route = $routeCollection->get('app_homepage'); @@ -348,17 +461,56 @@ class XmlFileLoaderTest extends TestCase public function provideFilesImportingRoutesWithControllers() { - yield array('import_controller.xml'); - yield array('import__controller.xml'); + yield ['import_controller.xml']; + yield ['import__controller.xml']; } - /** - * @expectedException \InvalidArgumentException - * @expectedExceptionMessageRegExp /The routing file "[^"]*" must not specify both the "controller" attribute and the defaults key "_controller" for the "import" tag/ - */ public function testImportWithOverriddenController() { - $loader = new XmlFileLoader(new FileLocator(array(__DIR__.'/../Fixtures/controller'))); + $this->expectException('InvalidArgumentException'); + $this->expectExceptionMessageRegExp('/The routing file "[^"]*" must not specify both the "controller" attribute and the defaults key "_controller" for the "import" tag/'); + $loader = new XmlFileLoader(new FileLocator([__DIR__.'/../Fixtures/controller'])); $loader->load('import_override_defaults.xml'); } + + public function testImportRouteWithGlobMatchingSingleFile() + { + $loader = new XmlFileLoader(new FileLocator([__DIR__.'/../Fixtures/glob'])); + $routeCollection = $loader->load('import_single.xml'); + + $route = $routeCollection->get('bar_route'); + $this->assertSame('AppBundle:Bar:view', $route->getDefault('_controller')); + } + + public function testImportRouteWithGlobMatchingMultipleFiles() + { + $loader = new XmlFileLoader(new FileLocator([__DIR__.'/../Fixtures/glob'])); + $routeCollection = $loader->load('import_multiple.xml'); + + $route = $routeCollection->get('bar_route'); + $this->assertSame('AppBundle:Bar:view', $route->getDefault('_controller')); + + $route = $routeCollection->get('baz_route'); + $this->assertSame('AppBundle:Baz:view', $route->getDefault('_controller')); + } + + public function testImportRouteWithNamePrefix() + { + $loader = new XmlFileLoader(new FileLocator([__DIR__.'/../Fixtures/import_with_name_prefix'])); + $routeCollection = $loader->load('routing.xml'); + + $this->assertNotNull($routeCollection->get('app_blog')); + $this->assertEquals('/blog', $routeCollection->get('app_blog')->getPath()); + $this->assertNotNull($routeCollection->get('api_app_blog')); + $this->assertEquals('/api/blog', $routeCollection->get('api_app_blog')->getPath()); + } + + public function testImportRouteWithNoTrailingSlash() + { + $loader = new XmlFileLoader(new FileLocator([__DIR__.'/../Fixtures/import_with_no_trailing_slash'])); + $routeCollection = $loader->load('routing.xml'); + + $this->assertEquals('/slash/', $routeCollection->get('a_app_homepage')->getPath()); + $this->assertEquals('/no-slash', $routeCollection->get('b_app_homepage')->getPath()); + } } diff --git a/vendor/symfony/routing/Tests/Loader/YamlFileLoaderTest.php b/vendor/symfony/routing/Tests/Loader/YamlFileLoaderTest.php index 1f7fd43897ae34b56095c8dbf4d620825e3c998c..caad0aa978ea68bb781c2696656ce2a930432f5c 100644 --- a/vendor/symfony/routing/Tests/Loader/YamlFileLoaderTest.php +++ b/vendor/symfony/routing/Tests/Loader/YamlFileLoaderTest.php @@ -13,8 +13,10 @@ namespace Symfony\Component\Routing\Tests\Loader; use PHPUnit\Framework\TestCase; use Symfony\Component\Config\FileLocator; -use Symfony\Component\Routing\Loader\YamlFileLoader; use Symfony\Component\Config\Resource\FileResource; +use Symfony\Component\Routing\Loader\YamlFileLoader; +use Symfony\Component\Routing\Route; +use Symfony\Component\Routing\RouteCollection; class YamlFileLoaderTest extends TestCase { @@ -33,39 +35,39 @@ class YamlFileLoaderTest extends TestCase public function testLoadDoesNothingIfEmpty() { - $loader = new YamlFileLoader(new FileLocator(array(__DIR__.'/../Fixtures'))); + $loader = new YamlFileLoader(new FileLocator([__DIR__.'/../Fixtures'])); $collection = $loader->load('empty.yml'); - $this->assertEquals(array(), $collection->all()); - $this->assertEquals(array(new FileResource(realpath(__DIR__.'/../Fixtures/empty.yml'))), $collection->getResources()); + $this->assertEquals([], $collection->all()); + $this->assertEquals([new FileResource(realpath(__DIR__.'/../Fixtures/empty.yml'))], $collection->getResources()); } /** - * @expectedException \InvalidArgumentException * @dataProvider getPathsToInvalidFiles */ public function testLoadThrowsExceptionWithInvalidFile($filePath) { - $loader = new YamlFileLoader(new FileLocator(array(__DIR__.'/../Fixtures'))); + $this->expectException('InvalidArgumentException'); + $loader = new YamlFileLoader(new FileLocator([__DIR__.'/../Fixtures'])); $loader->load($filePath); } public function getPathsToInvalidFiles() { - return array( - array('nonvalid.yml'), - array('nonvalid2.yml'), - array('incomplete.yml'), - array('nonvalidkeys.yml'), - array('nonesense_resource_plus_path.yml'), - array('nonesense_type_without_resource.yml'), - array('bad_format.yml'), - ); + return [ + ['nonvalid.yml'], + ['nonvalid2.yml'], + ['incomplete.yml'], + ['nonvalidkeys.yml'], + ['nonesense_resource_plus_path.yml'], + ['nonesense_type_without_resource.yml'], + ['bad_format.yml'], + ]; } public function testLoadSpecialRouteName() { - $loader = new YamlFileLoader(new FileLocator(array(__DIR__.'/../Fixtures'))); + $loader = new YamlFileLoader(new FileLocator([__DIR__.'/../Fixtures'])); $routeCollection = $loader->load('special_route_name.yml'); $route = $routeCollection->get('#$péß^a|'); @@ -75,7 +77,7 @@ class YamlFileLoaderTest extends TestCase public function testLoadWithRoute() { - $loader = new YamlFileLoader(new FileLocator(array(__DIR__.'/../Fixtures'))); + $loader = new YamlFileLoader(new FileLocator([__DIR__.'/../Fixtures'])); $routeCollection = $loader->load('validpattern.yml'); $route = $routeCollection->get('blog_show'); @@ -85,14 +87,14 @@ class YamlFileLoaderTest extends TestCase $this->assertSame('MyBundle:Blog:show', $route->getDefault('_controller')); $this->assertSame('\w+', $route->getRequirement('locale')); $this->assertSame('RouteCompiler', $route->getOption('compiler_class')); - $this->assertEquals(array('GET', 'POST', 'PUT', 'OPTIONS'), $route->getMethods()); - $this->assertEquals(array('https'), $route->getSchemes()); + $this->assertEquals(['GET', 'POST', 'PUT', 'OPTIONS'], $route->getMethods()); + $this->assertEquals(['https'], $route->getSchemes()); $this->assertEquals('context.getMethod() == "GET"', $route->getCondition()); } public function testLoadWithResource() { - $loader = new YamlFileLoader(new FileLocator(array(__DIR__.'/../Fixtures'))); + $loader = new YamlFileLoader(new FileLocator([__DIR__.'/../Fixtures'])); $routeCollection = $loader->load('validresource.yml'); $routes = $routeCollection->all(); @@ -111,7 +113,7 @@ class YamlFileLoaderTest extends TestCase public function testLoadRouteWithControllerAttribute() { - $loader = new YamlFileLoader(new FileLocator(array(__DIR__.'/../Fixtures/controller'))); + $loader = new YamlFileLoader(new FileLocator([__DIR__.'/../Fixtures/controller'])); $routeCollection = $loader->load('routing.yml'); $route = $routeCollection->get('app_homepage'); @@ -121,7 +123,7 @@ class YamlFileLoaderTest extends TestCase public function testLoadRouteWithoutControllerAttribute() { - $loader = new YamlFileLoader(new FileLocator(array(__DIR__.'/../Fixtures/controller'))); + $loader = new YamlFileLoader(new FileLocator([__DIR__.'/../Fixtures/controller'])); $routeCollection = $loader->load('routing.yml'); $route = $routeCollection->get('app_logout'); @@ -131,7 +133,7 @@ class YamlFileLoaderTest extends TestCase public function testLoadRouteWithControllerSetInDefaults() { - $loader = new YamlFileLoader(new FileLocator(array(__DIR__.'/../Fixtures/controller'))); + $loader = new YamlFileLoader(new FileLocator([__DIR__.'/../Fixtures/controller'])); $routeCollection = $loader->load('routing.yml'); $route = $routeCollection->get('app_blog'); @@ -139,13 +141,11 @@ class YamlFileLoaderTest extends TestCase $this->assertSame('AppBundle:Blog:list', $route->getDefault('_controller')); } - /** - * @expectedException \InvalidArgumentException - * @expectedExceptionMessageRegExp /The routing file "[^"]*" must not specify both the "controller" key and the defaults key "_controller" for "app_blog"/ - */ public function testOverrideControllerInDefaults() { - $loader = new YamlFileLoader(new FileLocator(array(__DIR__.'/../Fixtures/controller'))); + $this->expectException('InvalidArgumentException'); + $this->expectExceptionMessageRegExp('/The routing file "[^"]*" must not specify both the "controller" key and the defaults key "_controller" for "app_blog"/'); + $loader = new YamlFileLoader(new FileLocator([__DIR__.'/../Fixtures/controller'])); $loader->load('override_defaults.yml'); } @@ -154,7 +154,7 @@ class YamlFileLoaderTest extends TestCase */ public function testImportRouteWithController($file) { - $loader = new YamlFileLoader(new FileLocator(array(__DIR__.'/../Fixtures/controller'))); + $loader = new YamlFileLoader(new FileLocator([__DIR__.'/../Fixtures/controller'])); $routeCollection = $loader->load($file); $route = $routeCollection->get('app_homepage'); @@ -169,17 +169,221 @@ class YamlFileLoaderTest extends TestCase public function provideFilesImportingRoutesWithControllers() { - yield array('import_controller.yml'); - yield array('import__controller.yml'); + yield ['import_controller.yml']; + yield ['import__controller.yml']; } - /** - * @expectedException \InvalidArgumentException - * @expectedExceptionMessageRegExp /The routing file "[^"]*" must not specify both the "controller" key and the defaults key "_controller" for "_static"/ - */ public function testImportWithOverriddenController() { - $loader = new YamlFileLoader(new FileLocator(array(__DIR__.'/../Fixtures/controller'))); + $this->expectException('InvalidArgumentException'); + $this->expectExceptionMessageRegExp('/The routing file "[^"]*" must not specify both the "controller" key and the defaults key "_controller" for "_static"/'); + $loader = new YamlFileLoader(new FileLocator([__DIR__.'/../Fixtures/controller'])); $loader->load('import_override_defaults.yml'); } + + public function testImportRouteWithGlobMatchingSingleFile() + { + $loader = new YamlFileLoader(new FileLocator([__DIR__.'/../Fixtures/glob'])); + $routeCollection = $loader->load('import_single.yml'); + + $route = $routeCollection->get('bar_route'); + $this->assertSame('AppBundle:Bar:view', $route->getDefault('_controller')); + } + + public function testImportRouteWithGlobMatchingMultipleFiles() + { + $loader = new YamlFileLoader(new FileLocator([__DIR__.'/../Fixtures/glob'])); + $routeCollection = $loader->load('import_multiple.yml'); + + $route = $routeCollection->get('bar_route'); + $this->assertSame('AppBundle:Bar:view', $route->getDefault('_controller')); + + $route = $routeCollection->get('baz_route'); + $this->assertSame('AppBundle:Baz:view', $route->getDefault('_controller')); + } + + public function testImportRouteWithNamePrefix() + { + $loader = new YamlFileLoader(new FileLocator([__DIR__.'/../Fixtures/import_with_name_prefix'])); + $routeCollection = $loader->load('routing.yml'); + + $this->assertNotNull($routeCollection->get('app_blog')); + $this->assertEquals('/blog', $routeCollection->get('app_blog')->getPath()); + $this->assertNotNull($routeCollection->get('api_app_blog')); + $this->assertEquals('/api/blog', $routeCollection->get('api_app_blog')->getPath()); + } + + public function testRemoteSourcesAreNotAccepted() + { + $loader = new YamlFileLoader(new FileLocatorStub()); + $this->expectException(\InvalidArgumentException::class); + $loader->load('http://remote.com/here.yml'); + } + + public function testLoadingRouteWithDefaults() + { + $loader = new YamlFileLoader(new FileLocator([__DIR__.'/../Fixtures'])); + $routes = $loader->load('defaults.yml'); + + $this->assertCount(1, $routes); + + $defaultsRoute = $routes->get('defaults'); + + $this->assertSame('/defaults', $defaultsRoute->getPath()); + $this->assertSame('en', $defaultsRoute->getDefault('_locale')); + $this->assertSame('html', $defaultsRoute->getDefault('_format')); + } + + public function testLoadingImportedRoutesWithDefaults() + { + $loader = new YamlFileLoader(new FileLocator([__DIR__.'/../Fixtures'])); + $routes = $loader->load('importer-with-defaults.yml'); + + $this->assertCount(2, $routes); + + $expectedRoutes = new RouteCollection(); + $expectedRoutes->add('one', $localeRoute = new Route('/defaults/one')); + $localeRoute->setDefault('_locale', 'g_locale'); + $localeRoute->setDefault('_format', 'g_format'); + $expectedRoutes->add('two', $formatRoute = new Route('/defaults/two')); + $formatRoute->setDefault('_locale', 'g_locale'); + $formatRoute->setDefault('_format', 'g_format'); + $formatRoute->setDefault('specific', 'imported'); + + $expectedRoutes->addResource(new FileResource(__DIR__.'/../Fixtures/imported-with-defaults.yml')); + $expectedRoutes->addResource(new FileResource(__DIR__.'/../Fixtures/importer-with-defaults.yml')); + + $this->assertEquals($expectedRoutes, $routes); + } + + public function testLoadingUtf8Route() + { + $loader = new YamlFileLoader(new FileLocator([__DIR__.'/../Fixtures/localized'])); + $routes = $loader->load('utf8.yml'); + + $this->assertCount(2, $routes); + + $expectedRoutes = new RouteCollection(); + $expectedRoutes->add('some_route', new Route('/')); + + $expectedRoutes->add('some_utf8_route', $route = new Route('/utf8')); + $route->setOption('utf8', true); + + $expectedRoutes->addResource(new FileResource(__DIR__.'/../Fixtures/localized/utf8.yml')); + + $this->assertEquals($expectedRoutes, $routes); + } + + public function testLoadingUtf8ImportedRoutes() + { + $loader = new YamlFileLoader(new FileLocator([__DIR__.'/../Fixtures/localized'])); + $routes = $loader->load('importer-with-utf8.yml'); + + $this->assertCount(2, $routes); + + $expectedRoutes = new RouteCollection(); + $expectedRoutes->add('utf8_one', $one = new Route('/one')); + $one->setOption('utf8', true); + + $expectedRoutes->add('utf8_two', $two = new Route('/two')); + $two->setOption('utf8', true); + + $expectedRoutes->addResource(new FileResource(__DIR__.'/../Fixtures/localized/imported-with-utf8.yml')); + $expectedRoutes->addResource(new FileResource(__DIR__.'/../Fixtures/localized/importer-with-utf8.yml')); + + $this->assertEquals($expectedRoutes, $routes); + } + + public function testLoadingLocalizedRoute() + { + $loader = new YamlFileLoader(new FileLocator([__DIR__.'/../Fixtures/localized'])); + $routes = $loader->load('localized-route.yml'); + + $this->assertCount(3, $routes); + } + + public function testImportingRoutesFromDefinition() + { + $loader = new YamlFileLoader(new FileLocator([__DIR__.'/../Fixtures/localized'])); + $routes = $loader->load('importing-localized-route.yml'); + + $this->assertCount(3, $routes); + $this->assertEquals('/nl', $routes->get('home.nl')->getPath()); + $this->assertEquals('/en', $routes->get('home.en')->getPath()); + $this->assertEquals('/here', $routes->get('not_localized')->getPath()); + } + + public function testImportingRoutesWithLocales() + { + $loader = new YamlFileLoader(new FileLocator([__DIR__.'/../Fixtures/localized'])); + $routes = $loader->load('importer-with-locale.yml'); + + $this->assertCount(2, $routes); + $this->assertEquals('/nl/voorbeeld', $routes->get('imported.nl')->getPath()); + $this->assertEquals('/en/example', $routes->get('imported.en')->getPath()); + } + + public function testImportingNonLocalizedRoutesWithLocales() + { + $loader = new YamlFileLoader(new FileLocator([__DIR__.'/../Fixtures/localized'])); + $routes = $loader->load('importer-with-locale-imports-non-localized-route.yml'); + + $this->assertCount(2, $routes); + $this->assertEquals('/nl/imported', $routes->get('imported.nl')->getPath()); + $this->assertEquals('/en/imported', $routes->get('imported.en')->getPath()); + } + + public function testImportingRoutesWithOfficialLocales() + { + $loader = new YamlFileLoader(new FileLocator([__DIR__.'/../Fixtures/localized'])); + $routes = $loader->load('officially_formatted_locales.yml'); + + $this->assertCount(3, $routes); + $this->assertEquals('/omelette-au-fromage', $routes->get('official.fr.UTF-8')->getPath()); + $this->assertEquals('/eu-não-sou-espanhol', $routes->get('official.pt-PT')->getPath()); + $this->assertEquals('/churrasco', $routes->get('official.pt_BR')->getPath()); + } + + public function testImportingRoutesFromDefinitionMissingLocalePrefix() + { + $loader = new YamlFileLoader(new FileLocator([__DIR__.'/../Fixtures/localized'])); + $this->expectException(\InvalidArgumentException::class); + $loader->load('missing-locale-in-importer.yml'); + } + + public function testImportingRouteWithoutPathOrLocales() + { + $loader = new YamlFileLoader(new FileLocator([__DIR__.'/../Fixtures/localized'])); + $this->expectException(\InvalidArgumentException::class); + $loader->load('route-without-path-or-locales.yml'); + } + + public function testImportingWithControllerDefault() + { + $loader = new YamlFileLoader(new FileLocator([__DIR__.'/../Fixtures/localized'])); + $routes = $loader->load('importer-with-controller-default.yml'); + $this->assertCount(3, $routes); + $this->assertEquals('DefaultController::defaultAction', $routes->get('home.en')->getDefault('_controller')); + $this->assertEquals('DefaultController::defaultAction', $routes->get('home.nl')->getDefault('_controller')); + $this->assertEquals('DefaultController::defaultAction', $routes->get('not_localized')->getDefault('_controller')); + } + + public function testImportRouteWithNoTrailingSlash() + { + $loader = new YamlFileLoader(new FileLocator([__DIR__.'/../Fixtures/import_with_no_trailing_slash'])); + $routeCollection = $loader->load('routing.yml'); + + $this->assertEquals('/slash/', $routeCollection->get('a_app_homepage')->getPath()); + $this->assertEquals('/no-slash', $routeCollection->get('b_app_homepage')->getPath()); + } + + /** + * @group legacy + * @expectedDeprecation A placeholder name must be a string (0 given). Did you forget to specify the placeholder key for the requirement "\d+" of route "foo" in "%srequirements_without_placeholder_name.yml"? + */ + public function testRequirementsWithoutPlaceholderName() + { + $loader = new YamlFileLoader(new FileLocator([__DIR__.'/../Fixtures'])); + $loader->load('requirements_without_placeholder_name.yml'); + } } diff --git a/vendor/symfony/routing/Tests/Matcher/CompiledRedirectableUrlMatcherTest.php b/vendor/symfony/routing/Tests/Matcher/CompiledRedirectableUrlMatcherTest.php new file mode 100644 index 0000000000000000000000000000000000000000..7fb7dfef9e97bd50bf2e20f5ef1f0c37416207bd --- /dev/null +++ b/vendor/symfony/routing/Tests/Matcher/CompiledRedirectableUrlMatcherTest.php @@ -0,0 +1,40 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Tests\Matcher; + +use Symfony\Component\Routing\Matcher\CompiledUrlMatcher; +use Symfony\Component\Routing\Matcher\Dumper\CompiledUrlMatcherDumper; +use Symfony\Component\Routing\Matcher\RedirectableUrlMatcherInterface; +use Symfony\Component\Routing\RequestContext; +use Symfony\Component\Routing\RouteCollection; + +class CompiledRedirectableUrlMatcherTest extends RedirectableUrlMatcherTest +{ + protected function getUrlMatcher(RouteCollection $routes, RequestContext $context = null) + { + $dumper = new CompiledUrlMatcherDumper($routes); + $compiledRoutes = $dumper->getCompiledRoutes(); + + return $this->getMockBuilder(TestCompiledRedirectableUrlMatcher::class) + ->setConstructorArgs([$compiledRoutes, $context ?: new RequestContext()]) + ->setMethods(['redirect']) + ->getMock(); + } +} + +class TestCompiledRedirectableUrlMatcher extends CompiledUrlMatcher implements RedirectableUrlMatcherInterface +{ + public function redirect($path, $route, $scheme = null) + { + return []; + } +} diff --git a/vendor/symfony/routing/Tests/Matcher/CompiledUrlMatcherTest.php b/vendor/symfony/routing/Tests/Matcher/CompiledUrlMatcherTest.php new file mode 100644 index 0000000000000000000000000000000000000000..0a93f5ee7531715f3209cebaae359dc1fe2cf9b1 --- /dev/null +++ b/vendor/symfony/routing/Tests/Matcher/CompiledUrlMatcherTest.php @@ -0,0 +1,27 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Tests\Matcher; + +use Symfony\Component\Routing\Matcher\CompiledUrlMatcher; +use Symfony\Component\Routing\Matcher\Dumper\CompiledUrlMatcherDumper; +use Symfony\Component\Routing\RequestContext; +use Symfony\Component\Routing\RouteCollection; + +class CompiledUrlMatcherTest extends UrlMatcherTest +{ + protected function getUrlMatcher(RouteCollection $routes, RequestContext $context = null) + { + $dumper = new CompiledUrlMatcherDumper($routes); + + return new CompiledUrlMatcher($dumper->getCompiledRoutes(), $context ?: new RequestContext()); + } +} diff --git a/vendor/symfony/routing/Tests/Matcher/DumpedRedirectableUrlMatcherTest.php b/vendor/symfony/routing/Tests/Matcher/DumpedRedirectableUrlMatcherTest.php new file mode 100644 index 0000000000000000000000000000000000000000..aed006f710c0570e1a9bea6f7f98df4ff0a045e1 --- /dev/null +++ b/vendor/symfony/routing/Tests/Matcher/DumpedRedirectableUrlMatcherTest.php @@ -0,0 +1,46 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Tests\Matcher; + +use Symfony\Component\Routing\Matcher\Dumper\PhpMatcherDumper; +use Symfony\Component\Routing\Matcher\RedirectableUrlMatcherInterface; +use Symfony\Component\Routing\Matcher\UrlMatcher; +use Symfony\Component\Routing\RequestContext; +use Symfony\Component\Routing\RouteCollection; + +/** + * @group legacy + */ +class DumpedRedirectableUrlMatcherTest extends RedirectableUrlMatcherTest +{ + protected function getUrlMatcher(RouteCollection $routes, RequestContext $context = null) + { + static $i = 0; + + $class = 'DumpedRedirectableUrlMatcher'.++$i; + $dumper = new PhpMatcherDumper($routes); + eval('?>'.$dumper->dump(['class' => $class, 'base_class' => 'Symfony\Component\Routing\Tests\Matcher\TestDumpedRedirectableUrlMatcher'])); + + return $this->getMockBuilder($class) + ->setConstructorArgs([$context ?: new RequestContext()]) + ->setMethods(['redirect']) + ->getMock(); + } +} + +class TestDumpedRedirectableUrlMatcher extends UrlMatcher implements RedirectableUrlMatcherInterface +{ + public function redirect($path, $route, $scheme = null) + { + return []; + } +} diff --git a/vendor/symfony/routing/Tests/Matcher/DumpedUrlMatcherTest.php b/vendor/symfony/routing/Tests/Matcher/DumpedUrlMatcherTest.php new file mode 100644 index 0000000000000000000000000000000000000000..1766c04d7ed1b26d123104dcd8ffd5d4fbcc00ed --- /dev/null +++ b/vendor/symfony/routing/Tests/Matcher/DumpedUrlMatcherTest.php @@ -0,0 +1,33 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Tests\Matcher; + +use Symfony\Component\Routing\Matcher\Dumper\PhpMatcherDumper; +use Symfony\Component\Routing\RequestContext; +use Symfony\Component\Routing\RouteCollection; + +/** + * @group legacy + */ +class DumpedUrlMatcherTest extends UrlMatcherTest +{ + protected function getUrlMatcher(RouteCollection $routes, RequestContext $context = null) + { + static $i = 0; + + $class = 'DumpedUrlMatcher'.++$i; + $dumper = new PhpMatcherDumper($routes); + eval('?>'.$dumper->dump(['class' => $class])); + + return new $class($context ?: new RequestContext()); + } +} diff --git a/vendor/symfony/routing/Tests/Matcher/Dumper/CompiledUrlMatcherDumperTest.php b/vendor/symfony/routing/Tests/Matcher/Dumper/CompiledUrlMatcherDumperTest.php new file mode 100644 index 0000000000000000000000000000000000000000..744229b3ef9a726f0525ee20b11fa267befa1737 --- /dev/null +++ b/vendor/symfony/routing/Tests/Matcher/Dumper/CompiledUrlMatcherDumperTest.php @@ -0,0 +1,494 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Routing\Tests\Matcher\Dumper; + +use PHPUnit\Framework\TestCase; +use Symfony\Component\Routing\Matcher\CompiledUrlMatcher; +use Symfony\Component\Routing\Matcher\Dumper\CompiledUrlMatcherDumper; +use Symfony\Component\Routing\Matcher\RedirectableUrlMatcherInterface; +use Symfony\Component\Routing\RequestContext; +use Symfony\Component\Routing\Route; +use Symfony\Component\Routing\RouteCollection; + +class CompiledUrlMatcherDumperTest extends TestCase +{ + /** + * @var string + */ + private $dumpPath; + + protected function setUp(): void + { + parent::setUp(); + + $this->dumpPath = sys_get_temp_dir().\DIRECTORY_SEPARATOR.'php_matcher.'.uniqid('CompiledUrlMatcher').'.php'; + } + + protected function tearDown(): void + { + parent::tearDown(); + + @unlink($this->dumpPath); + } + + public function testRedirectPreservesUrlEncoding() + { + $collection = new RouteCollection(); + $collection->add('foo', new Route('/foo:bar/')); + + $matcher = $this->generateDumpedMatcher($collection); + $matcher->expects($this->once())->method('redirect')->with('/foo%3Abar/', 'foo')->willReturn([]); + + $matcher->match('/foo%3Abar'); + } + + /** + * @dataProvider getRouteCollections + */ + public function testDump(RouteCollection $collection, $fixture) + { + $basePath = __DIR__.'/../../Fixtures/dumper/'; + + $dumper = new CompiledUrlMatcherDumper($collection); + $this->assertStringEqualsFile($basePath.$fixture, $dumper->dump()); + } + + public function getRouteCollections() + { + /* test case 1 */ + + $collection = new RouteCollection(); + + $collection->add('overridden', new Route('/overridden')); + + // defaults and requirements + $collection->add('foo', new Route( + '/foo/{bar}', + ['def' => 'test'], + ['bar' => 'baz|symfony'] + )); + // method requirement + $collection->add('bar', new Route( + '/bar/{foo}', + [], + [], + [], + '', + [], + ['GET', 'head'] + )); + // GET method requirement automatically adds HEAD as valid + $collection->add('barhead', new Route( + '/barhead/{foo}', + [], + [], + [], + '', + [], + ['GET'] + )); + // simple + $collection->add('baz', new Route( + '/test/baz' + )); + // simple with extension + $collection->add('baz2', new Route( + '/test/baz.html' + )); + // trailing slash + $collection->add('baz3', new Route( + '/test/baz3/' + )); + // trailing slash with variable + $collection->add('baz4', new Route( + '/test/{foo}/' + )); + // trailing slash and method + $collection->add('baz5', new Route( + '/test/{foo}/', + [], + [], + [], + '', + [], + ['post'] + )); + // complex name + $collection->add('baz.baz6', new Route( + '/test/{foo}/', + [], + [], + [], + '', + [], + ['put'] + )); + // defaults without variable + $collection->add('foofoo', new Route( + '/foofoo', + ['def' => 'test'] + )); + // pattern with quotes + $collection->add('quoter', new Route( + '/{quoter}', + [], + ['quoter' => '[\']+'] + )); + // space in pattern + $collection->add('space', new Route( + '/spa ce' + )); + + // prefixes + $collection1 = new RouteCollection(); + $collection1->add('overridden', new Route('/overridden1')); + $collection1->add('foo1', (new Route('/{foo}'))->setMethods('PUT')); + $collection1->add('bar1', new Route('/{bar}')); + $collection1->addPrefix('/b\'b'); + $collection2 = new RouteCollection(); + $collection2->addCollection($collection1); + $collection2->add('overridden', new Route('/{var}', [], ['var' => '.*'])); + $collection1 = new RouteCollection(); + $collection1->add('foo2', new Route('/{foo1}')); + $collection1->add('bar2', new Route('/{bar1}')); + $collection1->addPrefix('/b\'b'); + $collection2->addCollection($collection1); + $collection2->addPrefix('/a'); + $collection->addCollection($collection2); + + // overridden through addCollection() and multiple sub-collections with no own prefix + $collection1 = new RouteCollection(); + $collection1->add('overridden2', new Route('/old')); + $collection1->add('helloWorld', new Route('/hello/{who}', ['who' => 'World!'])); + $collection2 = new RouteCollection(); + $collection3 = new RouteCollection(); + $collection3->add('overridden2', new Route('/new')); + $collection3->add('hey', new Route('/hey/')); + $collection2->addCollection($collection3); + $collection1->addCollection($collection2); + $collection1->addPrefix('/multi'); + $collection->addCollection($collection1); + + // "dynamic" prefix + $collection1 = new RouteCollection(); + $collection1->add('foo3', new Route('/{foo}')); + $collection1->add('bar3', new Route('/{bar}')); + $collection1->addPrefix('/b'); + $collection1->addPrefix('{_locale}'); + $collection->addCollection($collection1); + + // route between collections + $collection->add('ababa', new Route('/ababa')); + + // collection with static prefix but only one route + $collection1 = new RouteCollection(); + $collection1->add('foo4', new Route('/{foo}')); + $collection1->addPrefix('/aba'); + $collection->addCollection($collection1); + + // prefix and host + + $collection1 = new RouteCollection(); + + $route1 = new Route('/route1', [], [], [], 'a.example.com'); + $collection1->add('route1', $route1); + + $route2 = new Route('/c2/route2', [], [], [], 'a.example.com'); + $collection1->add('route2', $route2); + + $route3 = new Route('/c2/route3', [], [], [], 'b.example.com'); + $collection1->add('route3', $route3); + + $route4 = new Route('/route4', [], [], [], 'a.example.com'); + $collection1->add('route4', $route4); + + $route5 = new Route('/route5', [], [], [], 'c.example.com'); + $collection1->add('route5', $route5); + + $route6 = new Route('/route6', [], [], [], null); + $collection1->add('route6', $route6); + + $collection->addCollection($collection1); + + // host and variables + + $collection1 = new RouteCollection(); + + $route11 = new Route('/route11', [], [], [], '{var1}.example.com'); + $collection1->add('route11', $route11); + + $route12 = new Route('/route12', ['var1' => 'val'], [], [], '{var1}.example.com'); + $collection1->add('route12', $route12); + + $route13 = new Route('/route13/{name}', [], [], [], '{var1}.example.com'); + $collection1->add('route13', $route13); + + $route14 = new Route('/route14/{name}', ['var1' => 'val'], [], [], '{var1}.example.com'); + $collection1->add('route14', $route14); + + $route15 = new Route('/route15/{name}', [], [], [], 'c.example.com'); + $collection1->add('route15', $route15); + + $route16 = new Route('/route16/{name}', ['var1' => 'val'], [], [], null); + $collection1->add('route16', $route16); + + $route17 = new Route('/route17', [], [], [], null); + $collection1->add('route17', $route17); + + $collection->addCollection($collection1); + + // multiple sub-collections with a single route and a prefix each + $collection1 = new RouteCollection(); + $collection1->add('a', new Route('/a...')); + $collection2 = new RouteCollection(); + $collection2->add('b', new Route('/{var}')); + $collection3 = new RouteCollection(); + $collection3->add('c', new Route('/{var}')); + $collection3->addPrefix('/c'); + $collection2->addCollection($collection3); + $collection2->addPrefix('/b'); + $collection1->addCollection($collection2); + $collection1->addPrefix('/a'); + $collection->addCollection($collection1); + + /* test case 2 */ + + $redirectCollection = clone $collection; + + // force HTTPS redirection + $redirectCollection->add('secure', new Route( + '/secure', + [], + [], + [], + '', + ['https'] + )); + + // force HTTP redirection + $redirectCollection->add('nonsecure', new Route( + '/nonsecure', + [], + [], + [], + '', + ['http'] + )); + + /* test case 3 */ + + $rootprefixCollection = new RouteCollection(); + $rootprefixCollection->add('static', new Route('/test')); + $rootprefixCollection->add('dynamic', new Route('/{var}')); + $rootprefixCollection->addPrefix('rootprefix'); + $route = new Route('/with-condition'); + $route->setCondition('context.getMethod() == "GET"'); + $rootprefixCollection->add('with-condition', $route); + + /* test case 4 */ + $headMatchCasesCollection = new RouteCollection(); + $headMatchCasesCollection->add('just_head', new Route( + '/just_head', + [], + [], + [], + '', + [], + ['HEAD'] + )); + $headMatchCasesCollection->add('head_and_get', new Route( + '/head_and_get', + [], + [], + [], + '', + [], + ['HEAD', 'GET'] + )); + $headMatchCasesCollection->add('get_and_head', new Route( + '/get_and_head', + [], + [], + [], + '', + [], + ['GET', 'HEAD'] + )); + $headMatchCasesCollection->add('post_and_head', new Route( + '/post_and_head', + [], + [], + [], + '', + [], + ['POST', 'HEAD'] + )); + $headMatchCasesCollection->add('put_and_post', new Route( + '/put_and_post', + [], + [], + [], + '', + [], + ['PUT', 'POST'] + )); + $headMatchCasesCollection->add('put_and_get_and_head', new Route( + '/put_and_post', + [], + [], + [], + '', + [], + ['PUT', 'GET', 'HEAD'] + )); + + /* test case 5 */ + $groupOptimisedCollection = new RouteCollection(); + $groupOptimisedCollection->add('a_first', new Route('/a/11')); + $groupOptimisedCollection->add('a_second', new Route('/a/22')); + $groupOptimisedCollection->add('a_third', new Route('/a/333')); + $groupOptimisedCollection->add('a_wildcard', new Route('/{param}')); + $groupOptimisedCollection->add('a_fourth', new Route('/a/44/')); + $groupOptimisedCollection->add('a_fifth', new Route('/a/55/')); + $groupOptimisedCollection->add('a_sixth', new Route('/a/66/')); + $groupOptimisedCollection->add('nested_wildcard', new Route('/nested/{param}')); + $groupOptimisedCollection->add('nested_a', new Route('/nested/group/a/')); + $groupOptimisedCollection->add('nested_b', new Route('/nested/group/b/')); + $groupOptimisedCollection->add('nested_c', new Route('/nested/group/c/')); + + $groupOptimisedCollection->add('slashed_a', new Route('/slashed/group/')); + $groupOptimisedCollection->add('slashed_b', new Route('/slashed/group/b/')); + $groupOptimisedCollection->add('slashed_c', new Route('/slashed/group/c/')); + + /* test case 6 & 7 */ + $trailingSlashCollection = new RouteCollection(); + $trailingSlashCollection->add('simple_trailing_slash_no_methods', new Route('/trailing/simple/no-methods/', [], [], [], '', [], [])); + $trailingSlashCollection->add('simple_trailing_slash_GET_method', new Route('/trailing/simple/get-method/', [], [], [], '', [], ['GET'])); + $trailingSlashCollection->add('simple_trailing_slash_HEAD_method', new Route('/trailing/simple/head-method/', [], [], [], '', [], ['HEAD'])); + $trailingSlashCollection->add('simple_trailing_slash_POST_method', new Route('/trailing/simple/post-method/', [], [], [], '', [], ['POST'])); + $trailingSlashCollection->add('regex_trailing_slash_no_methods', new Route('/trailing/regex/no-methods/{param}/', [], [], [], '', [], [])); + $trailingSlashCollection->add('regex_trailing_slash_GET_method', new Route('/trailing/regex/get-method/{param}/', [], [], [], '', [], ['GET'])); + $trailingSlashCollection->add('regex_trailing_slash_HEAD_method', new Route('/trailing/regex/head-method/{param}/', [], [], [], '', [], ['HEAD'])); + $trailingSlashCollection->add('regex_trailing_slash_POST_method', new Route('/trailing/regex/post-method/{param}/', [], [], [], '', [], ['POST'])); + + $trailingSlashCollection->add('simple_not_trailing_slash_no_methods', new Route('/not-trailing/simple/no-methods', [], [], [], '', [], [])); + $trailingSlashCollection->add('simple_not_trailing_slash_GET_method', new Route('/not-trailing/simple/get-method', [], [], [], '', [], ['GET'])); + $trailingSlashCollection->add('simple_not_trailing_slash_HEAD_method', new Route('/not-trailing/simple/head-method', [], [], [], '', [], ['HEAD'])); + $trailingSlashCollection->add('simple_not_trailing_slash_POST_method', new Route('/not-trailing/simple/post-method', [], [], [], '', [], ['POST'])); + $trailingSlashCollection->add('regex_not_trailing_slash_no_methods', new Route('/not-trailing/regex/no-methods/{param}', [], [], [], '', [], [])); + $trailingSlashCollection->add('regex_not_trailing_slash_GET_method', new Route('/not-trailing/regex/get-method/{param}', [], [], [], '', [], ['GET'])); + $trailingSlashCollection->add('regex_not_trailing_slash_HEAD_method', new Route('/not-trailing/regex/head-method/{param}', [], [], [], '', [], ['HEAD'])); + $trailingSlashCollection->add('regex_not_trailing_slash_POST_method', new Route('/not-trailing/regex/post-method/{param}', [], [], [], '', [], ['POST'])); + + /* test case 8 */ + $unicodeCollection = new RouteCollection(); + $unicodeCollection->add('a', new Route('/{a}', [], ['a' => 'a'], ['utf8' => false])); + $unicodeCollection->add('b', new Route('/{a}', [], ['a' => '.'], ['utf8' => true])); + $unicodeCollection->add('c', new Route('/{a}', [], ['a' => '.'], ['utf8' => false])); + + /* test case 9 */ + $hostTreeCollection = new RouteCollection(); + $hostTreeCollection->add('a', (new Route('/'))->setHost('{d}.e.c.b.a')); + $hostTreeCollection->add('b', (new Route('/'))->setHost('d.c.b.a')); + $hostTreeCollection->add('c', (new Route('/'))->setHost('{e}.e.c.b.a')); + + /* test case 10 */ + $chunkedCollection = new RouteCollection(); + for ($i = 0; $i < 1000; ++$i) { + $h = substr(md5($i), 0, 6); + $chunkedCollection->add('_'.$i, new Route('/'.$h.'/{a}/{b}/{c}/'.$h)); + } + + /* test case 11 */ + $demoCollection = new RouteCollection(); + $demoCollection->add('a', new Route('/admin/post/')); + $demoCollection->add('b', new Route('/admin/post/new')); + $demoCollection->add('c', (new Route('/admin/post/{id}'))->setRequirements(['id' => '\d+'])); + $demoCollection->add('d', (new Route('/admin/post/{id}/edit'))->setRequirements(['id' => '\d+'])); + $demoCollection->add('e', (new Route('/admin/post/{id}/delete'))->setRequirements(['id' => '\d+'])); + $demoCollection->add('f', new Route('/blog/')); + $demoCollection->add('g', new Route('/blog/rss.xml')); + $demoCollection->add('h', (new Route('/blog/page/{page}'))->setRequirements(['id' => '\d+'])); + $demoCollection->add('i', (new Route('/blog/posts/{page}'))->setRequirements(['id' => '\d+'])); + $demoCollection->add('j', (new Route('/blog/comments/{id}/new'))->setRequirements(['id' => '\d+'])); + $demoCollection->add('k', new Route('/blog/search')); + $demoCollection->add('l', new Route('/login')); + $demoCollection->add('m', new Route('/logout')); + $demoCollection->addPrefix('/{_locale}'); + $demoCollection->add('n', new Route('/{_locale}')); + $demoCollection->addRequirements(['_locale' => 'en|fr']); + $demoCollection->addDefaults(['_locale' => 'en']); + + /* test case 12 */ + $suffixCollection = new RouteCollection(); + $suffixCollection->add('r1', new Route('abc{foo}/1')); + $suffixCollection->add('r2', new Route('abc{foo}/2')); + $suffixCollection->add('r10', new Route('abc{foo}/10')); + $suffixCollection->add('r20', new Route('abc{foo}/20')); + $suffixCollection->add('r100', new Route('abc{foo}/100')); + $suffixCollection->add('r200', new Route('abc{foo}/200')); + + /* test case 13 */ + $hostCollection = new RouteCollection(); + $hostCollection->add('r1', (new Route('abc{foo}'))->setHost('{foo}.exampple.com')); + $hostCollection->add('r2', (new Route('abc{foo}'))->setHost('{foo}.exampple.com')); + + return [ + [new RouteCollection(), 'compiled_url_matcher0.php'], + [$collection, 'compiled_url_matcher1.php'], + [$redirectCollection, 'compiled_url_matcher2.php'], + [$rootprefixCollection, 'compiled_url_matcher3.php'], + [$headMatchCasesCollection, 'compiled_url_matcher4.php'], + [$groupOptimisedCollection, 'compiled_url_matcher5.php'], + [$trailingSlashCollection, 'compiled_url_matcher6.php'], + [$trailingSlashCollection, 'compiled_url_matcher7.php'], + [$unicodeCollection, 'compiled_url_matcher8.php'], + [$hostTreeCollection, 'compiled_url_matcher9.php'], + [$chunkedCollection, 'compiled_url_matcher10.php'], + [$demoCollection, 'compiled_url_matcher11.php'], + [$suffixCollection, 'compiled_url_matcher12.php'], + [$hostCollection, 'compiled_url_matcher13.php'], + ]; + } + + private function generateDumpedMatcher(RouteCollection $collection) + { + $dumper = new CompiledUrlMatcherDumper($collection); + $code = $dumper->dump(); + + file_put_contents($this->dumpPath, $code); + $compiledRoutes = require $this->dumpPath; + + return $this->getMockBuilder(TestCompiledUrlMatcher::class) + ->setConstructorArgs([$compiledRoutes, new RequestContext()]) + ->setMethods(['redirect']) + ->getMock(); + } + + public function testGenerateDumperMatcherWithObject() + { + $this->expectException('InvalidArgumentException'); + $this->expectExceptionMessage('Symfony\Component\Routing\Route cannot contain objects'); + $routeCollection = new RouteCollection(); + $routeCollection->add('_', new Route('/', [new \stdClass()])); + $dumper = new CompiledUrlMatcherDumper($routeCollection); + $dumper->dump(); + } +} + +class TestCompiledUrlMatcher extends CompiledUrlMatcher implements RedirectableUrlMatcherInterface +{ + public function redirect($path, $route, $scheme = null) + { + return []; + } +} diff --git a/vendor/symfony/routing/Tests/Matcher/Dumper/DumperCollectionTest.php b/vendor/symfony/routing/Tests/Matcher/Dumper/DumperCollectionTest.php deleted file mode 100644 index 823efdb840022eba9f394c829b93714488427e11..0000000000000000000000000000000000000000 --- a/vendor/symfony/routing/Tests/Matcher/Dumper/DumperCollectionTest.php +++ /dev/null @@ -1,34 +0,0 @@ -<?php - -/* - * This file is part of the Symfony package. - * - * (c) Fabien Potencier <fabien@symfony.com> - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Routing\Tests\Matcher\Dumper; - -use PHPUnit\Framework\TestCase; -use Symfony\Component\Routing\Matcher\Dumper\DumperCollection; - -class DumperCollectionTest extends TestCase -{ - public function testGetRoot() - { - $a = new DumperCollection(); - - $b = new DumperCollection(); - $a->add($b); - - $c = new DumperCollection(); - $b->add($c); - - $d = new DumperCollection(); - $c->add($d); - - $this->assertSame($a, $c->getRoot()); - } -} diff --git a/vendor/symfony/routing/Tests/Matcher/Dumper/PhpMatcherDumperTest.php b/vendor/symfony/routing/Tests/Matcher/Dumper/PhpMatcherDumperTest.php index e4c18c47b144fc66a6904538176f12433a9f1c4a..4c15451209b0e3d68a0a611697f683c0d86e65f6 100644 --- a/vendor/symfony/routing/Tests/Matcher/Dumper/PhpMatcherDumperTest.php +++ b/vendor/symfony/routing/Tests/Matcher/Dumper/PhpMatcherDumperTest.php @@ -19,6 +19,9 @@ use Symfony\Component\Routing\RequestContext; use Symfony\Component\Routing\Route; use Symfony\Component\Routing\RouteCollection; +/** + * @group legacy + */ class PhpMatcherDumperTest extends TestCase { /** @@ -31,39 +34,21 @@ class PhpMatcherDumperTest extends TestCase */ private $dumpPath; - protected function setUp() + protected function setUp(): void { parent::setUp(); $this->matcherClass = uniqid('ProjectUrlMatcher'); - $this->dumpPath = sys_get_temp_dir().DIRECTORY_SEPARATOR.'php_matcher.'.$this->matcherClass.'.php'; + $this->dumpPath = sys_get_temp_dir().\DIRECTORY_SEPARATOR.'php_matcher.'.$this->matcherClass.'.php'; } - protected function tearDown() + protected function tearDown(): void { parent::tearDown(); @unlink($this->dumpPath); } - /** - * @expectedException \LogicException - */ - public function testDumpWhenSchemeIsUsedWithoutAProperDumper() - { - $collection = new RouteCollection(); - $collection->add('secure', new Route( - '/secure', - array(), - array(), - array(), - '', - array('https') - )); - $dumper = new PhpMatcherDumper($collection); - $dumper->dump(); - } - public function testRedirectPreservesUrlEncoding() { $collection = new RouteCollection(); @@ -72,11 +57,11 @@ class PhpMatcherDumperTest extends TestCase $class = $this->generateDumpedMatcher($collection, true); $matcher = $this->getMockBuilder($class) - ->setMethods(array('redirect')) - ->setConstructorArgs(array(new RequestContext())) + ->setMethods(['redirect']) + ->setConstructorArgs([new RequestContext()]) ->getMock(); - $matcher->expects($this->once())->method('redirect')->with('/foo%3Abar/', 'foo')->willReturn(array()); + $matcher->expects($this->once())->method('redirect')->with('/foo%3Abar/', 'foo')->willReturn([]); $matcher->match('/foo%3Abar'); } @@ -84,7 +69,7 @@ class PhpMatcherDumperTest extends TestCase /** * @dataProvider getRouteCollections */ - public function testDump(RouteCollection $collection, $fixture, $options = array()) + public function testDump(RouteCollection $collection, $fixture, $options = []) { $basePath = __DIR__.'/../../Fixtures/dumper/'; @@ -103,28 +88,28 @@ class PhpMatcherDumperTest extends TestCase // defaults and requirements $collection->add('foo', new Route( '/foo/{bar}', - array('def' => 'test'), - array('bar' => 'baz|symfony') + ['def' => 'test'], + ['bar' => 'baz|symfony'] )); // method requirement $collection->add('bar', new Route( '/bar/{foo}', - array(), - array(), - array(), + [], + [], + [], '', - array(), - array('GET', 'head') + [], + ['GET', 'head'] )); // GET method requirement automatically adds HEAD as valid $collection->add('barhead', new Route( '/barhead/{foo}', - array(), - array(), - array(), + [], + [], + [], '', - array(), - array('GET') + [], + ['GET'] )); // simple $collection->add('baz', new Route( @@ -145,33 +130,33 @@ class PhpMatcherDumperTest extends TestCase // trailing slash and method $collection->add('baz5', new Route( '/test/{foo}/', - array(), - array(), - array(), + [], + [], + [], '', - array(), - array('post') + [], + ['post'] )); // complex name $collection->add('baz.baz6', new Route( '/test/{foo}/', - array(), - array(), - array(), + [], + [], + [], '', - array(), - array('put') + [], + ['put'] )); // defaults without variable $collection->add('foofoo', new Route( '/foofoo', - array('def' => 'test') + ['def' => 'test'] )); // pattern with quotes $collection->add('quoter', new Route( '/{quoter}', - array(), - array('quoter' => '[\']+') + [], + ['quoter' => '[\']+'] )); // space in pattern $collection->add('space', new Route( @@ -181,12 +166,12 @@ class PhpMatcherDumperTest extends TestCase // prefixes $collection1 = new RouteCollection(); $collection1->add('overridden', new Route('/overridden1')); - $collection1->add('foo1', new Route('/{foo}')); + $collection1->add('foo1', (new Route('/{foo}'))->setMethods('PUT')); $collection1->add('bar1', new Route('/{bar}')); $collection1->addPrefix('/b\'b'); $collection2 = new RouteCollection(); $collection2->addCollection($collection1); - $collection2->add('overridden', new Route('/{var}', array(), array('var' => '.*'))); + $collection2->add('overridden', new Route('/{var}', [], ['var' => '.*'])); $collection1 = new RouteCollection(); $collection1->add('foo2', new Route('/{foo1}')); $collection1->add('bar2', new Route('/{bar1}')); @@ -198,7 +183,7 @@ class PhpMatcherDumperTest extends TestCase // overridden through addCollection() and multiple sub-collections with no own prefix $collection1 = new RouteCollection(); $collection1->add('overridden2', new Route('/old')); - $collection1->add('helloWorld', new Route('/hello/{who}', array('who' => 'World!'))); + $collection1->add('helloWorld', new Route('/hello/{who}', ['who' => 'World!'])); $collection2 = new RouteCollection(); $collection3 = new RouteCollection(); $collection3->add('overridden2', new Route('/new')); @@ -229,22 +214,22 @@ class PhpMatcherDumperTest extends TestCase $collection1 = new RouteCollection(); - $route1 = new Route('/route1', array(), array(), array(), 'a.example.com'); + $route1 = new Route('/route1', [], [], [], 'a.example.com'); $collection1->add('route1', $route1); - $route2 = new Route('/c2/route2', array(), array(), array(), 'a.example.com'); + $route2 = new Route('/c2/route2', [], [], [], 'a.example.com'); $collection1->add('route2', $route2); - $route3 = new Route('/c2/route3', array(), array(), array(), 'b.example.com'); + $route3 = new Route('/c2/route3', [], [], [], 'b.example.com'); $collection1->add('route3', $route3); - $route4 = new Route('/route4', array(), array(), array(), 'a.example.com'); + $route4 = new Route('/route4', [], [], [], 'a.example.com'); $collection1->add('route4', $route4); - $route5 = new Route('/route5', array(), array(), array(), 'c.example.com'); + $route5 = new Route('/route5', [], [], [], 'c.example.com'); $collection1->add('route5', $route5); - $route6 = new Route('/route6', array(), array(), array(), null); + $route6 = new Route('/route6', [], [], [], null); $collection1->add('route6', $route6); $collection->addCollection($collection1); @@ -253,25 +238,25 @@ class PhpMatcherDumperTest extends TestCase $collection1 = new RouteCollection(); - $route11 = new Route('/route11', array(), array(), array(), '{var1}.example.com'); + $route11 = new Route('/route11', [], [], [], '{var1}.example.com'); $collection1->add('route11', $route11); - $route12 = new Route('/route12', array('var1' => 'val'), array(), array(), '{var1}.example.com'); + $route12 = new Route('/route12', ['var1' => 'val'], [], [], '{var1}.example.com'); $collection1->add('route12', $route12); - $route13 = new Route('/route13/{name}', array(), array(), array(), '{var1}.example.com'); + $route13 = new Route('/route13/{name}', [], [], [], '{var1}.example.com'); $collection1->add('route13', $route13); - $route14 = new Route('/route14/{name}', array('var1' => 'val'), array(), array(), '{var1}.example.com'); + $route14 = new Route('/route14/{name}', ['var1' => 'val'], [], [], '{var1}.example.com'); $collection1->add('route14', $route14); - $route15 = new Route('/route15/{name}', array(), array(), array(), 'c.example.com'); + $route15 = new Route('/route15/{name}', [], [], [], 'c.example.com'); $collection1->add('route15', $route15); - $route16 = new Route('/route16/{name}', array('var1' => 'val'), array(), array(), null); + $route16 = new Route('/route16/{name}', ['var1' => 'val'], [], [], null); $collection1->add('route16', $route16); - $route17 = new Route('/route17', array(), array(), array(), null); + $route17 = new Route('/route17', [], [], [], null); $collection1->add('route17', $route17); $collection->addCollection($collection1); @@ -297,21 +282,21 @@ class PhpMatcherDumperTest extends TestCase // force HTTPS redirection $redirectCollection->add('secure', new Route( '/secure', - array(), - array(), - array(), + [], + [], + [], '', - array('https') + ['https'] )); // force HTTP redirection $redirectCollection->add('nonsecure', new Route( '/nonsecure', - array(), - array(), - array(), + [], + [], + [], '', - array('http') + ['http'] )); /* test case 3 */ @@ -328,57 +313,57 @@ class PhpMatcherDumperTest extends TestCase $headMatchCasesCollection = new RouteCollection(); $headMatchCasesCollection->add('just_head', new Route( '/just_head', - array(), - array(), - array(), + [], + [], + [], '', - array(), - array('HEAD') + [], + ['HEAD'] )); $headMatchCasesCollection->add('head_and_get', new Route( '/head_and_get', - array(), - array(), - array(), + [], + [], + [], '', - array(), - array('HEAD', 'GET') + [], + ['HEAD', 'GET'] )); $headMatchCasesCollection->add('get_and_head', new Route( '/get_and_head', - array(), - array(), - array(), + [], + [], + [], '', - array(), - array('GET', 'HEAD') + [], + ['GET', 'HEAD'] )); $headMatchCasesCollection->add('post_and_head', new Route( - '/post_and_get', - array(), - array(), - array(), + '/post_and_head', + [], + [], + [], '', - array(), - array('POST', 'HEAD') + [], + ['POST', 'HEAD'] )); $headMatchCasesCollection->add('put_and_post', new Route( '/put_and_post', - array(), - array(), - array(), + [], + [], + [], '', - array(), - array('PUT', 'POST') + [], + ['PUT', 'POST'] )); $headMatchCasesCollection->add('put_and_get_and_head', new Route( '/put_and_post', - array(), - array(), - array(), + [], + [], + [], '', - array(), - array('PUT', 'GET', 'HEAD') + [], + ['PUT', 'GET', 'HEAD'] )); /* test case 5 */ @@ -399,43 +384,100 @@ class PhpMatcherDumperTest extends TestCase $groupOptimisedCollection->add('slashed_b', new Route('/slashed/group/b/')); $groupOptimisedCollection->add('slashed_c', new Route('/slashed/group/c/')); + /* test case 6 & 7 */ $trailingSlashCollection = new RouteCollection(); - $trailingSlashCollection->add('simple_trailing_slash_no_methods', new Route('/trailing/simple/no-methods/', array(), array(), array(), '', array(), array())); - $trailingSlashCollection->add('simple_trailing_slash_GET_method', new Route('/trailing/simple/get-method/', array(), array(), array(), '', array(), array('GET'))); - $trailingSlashCollection->add('simple_trailing_slash_HEAD_method', new Route('/trailing/simple/head-method/', array(), array(), array(), '', array(), array('HEAD'))); - $trailingSlashCollection->add('simple_trailing_slash_POST_method', new Route('/trailing/simple/post-method/', array(), array(), array(), '', array(), array('POST'))); - $trailingSlashCollection->add('regex_trailing_slash_no_methods', new Route('/trailing/regex/no-methods/{param}/', array(), array(), array(), '', array(), array())); - $trailingSlashCollection->add('regex_trailing_slash_GET_method', new Route('/trailing/regex/get-method/{param}/', array(), array(), array(), '', array(), array('GET'))); - $trailingSlashCollection->add('regex_trailing_slash_HEAD_method', new Route('/trailing/regex/head-method/{param}/', array(), array(), array(), '', array(), array('HEAD'))); - $trailingSlashCollection->add('regex_trailing_slash_POST_method', new Route('/trailing/regex/post-method/{param}/', array(), array(), array(), '', array(), array('POST'))); - - $trailingSlashCollection->add('simple_not_trailing_slash_no_methods', new Route('/not-trailing/simple/no-methods', array(), array(), array(), '', array(), array())); - $trailingSlashCollection->add('simple_not_trailing_slash_GET_method', new Route('/not-trailing/simple/get-method', array(), array(), array(), '', array(), array('GET'))); - $trailingSlashCollection->add('simple_not_trailing_slash_HEAD_method', new Route('/not-trailing/simple/head-method', array(), array(), array(), '', array(), array('HEAD'))); - $trailingSlashCollection->add('simple_not_trailing_slash_POST_method', new Route('/not-trailing/simple/post-method', array(), array(), array(), '', array(), array('POST'))); - $trailingSlashCollection->add('regex_not_trailing_slash_no_methods', new Route('/not-trailing/regex/no-methods/{param}', array(), array(), array(), '', array(), array())); - $trailingSlashCollection->add('regex_not_trailing_slash_GET_method', new Route('/not-trailing/regex/get-method/{param}', array(), array(), array(), '', array(), array('GET'))); - $trailingSlashCollection->add('regex_not_trailing_slash_HEAD_method', new Route('/not-trailing/regex/head-method/{param}', array(), array(), array(), '', array(), array('HEAD'))); - $trailingSlashCollection->add('regex_not_trailing_slash_POST_method', new Route('/not-trailing/regex/post-method/{param}', array(), array(), array(), '', array(), array('POST'))); - - return array( - array(new RouteCollection(), 'url_matcher0.php', array()), - array($collection, 'url_matcher1.php', array()), - array($redirectCollection, 'url_matcher2.php', array('base_class' => 'Symfony\Component\Routing\Tests\Fixtures\RedirectableUrlMatcher')), - array($rootprefixCollection, 'url_matcher3.php', array()), - array($headMatchCasesCollection, 'url_matcher4.php', array()), - array($groupOptimisedCollection, 'url_matcher5.php', array('base_class' => 'Symfony\Component\Routing\Tests\Fixtures\RedirectableUrlMatcher')), - array($trailingSlashCollection, 'url_matcher6.php', array()), - array($trailingSlashCollection, 'url_matcher7.php', array('base_class' => 'Symfony\Component\Routing\Tests\Fixtures\RedirectableUrlMatcher')), - ); + $trailingSlashCollection->add('simple_trailing_slash_no_methods', new Route('/trailing/simple/no-methods/', [], [], [], '', [], [])); + $trailingSlashCollection->add('simple_trailing_slash_GET_method', new Route('/trailing/simple/get-method/', [], [], [], '', [], ['GET'])); + $trailingSlashCollection->add('simple_trailing_slash_HEAD_method', new Route('/trailing/simple/head-method/', [], [], [], '', [], ['HEAD'])); + $trailingSlashCollection->add('simple_trailing_slash_POST_method', new Route('/trailing/simple/post-method/', [], [], [], '', [], ['POST'])); + $trailingSlashCollection->add('regex_trailing_slash_no_methods', new Route('/trailing/regex/no-methods/{param}/', [], [], [], '', [], [])); + $trailingSlashCollection->add('regex_trailing_slash_GET_method', new Route('/trailing/regex/get-method/{param}/', [], [], [], '', [], ['GET'])); + $trailingSlashCollection->add('regex_trailing_slash_HEAD_method', new Route('/trailing/regex/head-method/{param}/', [], [], [], '', [], ['HEAD'])); + $trailingSlashCollection->add('regex_trailing_slash_POST_method', new Route('/trailing/regex/post-method/{param}/', [], [], [], '', [], ['POST'])); + + $trailingSlashCollection->add('simple_not_trailing_slash_no_methods', new Route('/not-trailing/simple/no-methods', [], [], [], '', [], [])); + $trailingSlashCollection->add('simple_not_trailing_slash_GET_method', new Route('/not-trailing/simple/get-method', [], [], [], '', [], ['GET'])); + $trailingSlashCollection->add('simple_not_trailing_slash_HEAD_method', new Route('/not-trailing/simple/head-method', [], [], [], '', [], ['HEAD'])); + $trailingSlashCollection->add('simple_not_trailing_slash_POST_method', new Route('/not-trailing/simple/post-method', [], [], [], '', [], ['POST'])); + $trailingSlashCollection->add('regex_not_trailing_slash_no_methods', new Route('/not-trailing/regex/no-methods/{param}', [], [], [], '', [], [])); + $trailingSlashCollection->add('regex_not_trailing_slash_GET_method', new Route('/not-trailing/regex/get-method/{param}', [], [], [], '', [], ['GET'])); + $trailingSlashCollection->add('regex_not_trailing_slash_HEAD_method', new Route('/not-trailing/regex/head-method/{param}', [], [], [], '', [], ['HEAD'])); + $trailingSlashCollection->add('regex_not_trailing_slash_POST_method', new Route('/not-trailing/regex/post-method/{param}', [], [], [], '', [], ['POST'])); + + /* test case 8 */ + $unicodeCollection = new RouteCollection(); + $unicodeCollection->add('a', new Route('/{a}', [], ['a' => 'a'], ['utf8' => false])); + $unicodeCollection->add('b', new Route('/{a}', [], ['a' => '.'], ['utf8' => true])); + $unicodeCollection->add('c', new Route('/{a}', [], ['a' => '.'], ['utf8' => false])); + + /* test case 9 */ + $hostTreeCollection = new RouteCollection(); + $hostTreeCollection->add('a', (new Route('/'))->setHost('{d}.e.c.b.a')); + $hostTreeCollection->add('b', (new Route('/'))->setHost('d.c.b.a')); + $hostTreeCollection->add('c', (new Route('/'))->setHost('{e}.e.c.b.a')); + + /* test case 10 */ + $chunkedCollection = new RouteCollection(); + for ($i = 0; $i < 1000; ++$i) { + $h = substr(md5($i), 0, 6); + $chunkedCollection->add('_'.$i, new Route('/'.$h.'/{a}/{b}/{c}/'.$h)); + } + + /* test case 11 */ + $demoCollection = new RouteCollection(); + $demoCollection->add('a', new Route('/admin/post/')); + $demoCollection->add('b', new Route('/admin/post/new')); + $demoCollection->add('c', (new Route('/admin/post/{id}'))->setRequirements(['id' => '\d+'])); + $demoCollection->add('d', (new Route('/admin/post/{id}/edit'))->setRequirements(['id' => '\d+'])); + $demoCollection->add('e', (new Route('/admin/post/{id}/delete'))->setRequirements(['id' => '\d+'])); + $demoCollection->add('f', new Route('/blog/')); + $demoCollection->add('g', new Route('/blog/rss.xml')); + $demoCollection->add('h', (new Route('/blog/page/{page}'))->setRequirements(['id' => '\d+'])); + $demoCollection->add('i', (new Route('/blog/posts/{page}'))->setRequirements(['id' => '\d+'])); + $demoCollection->add('j', (new Route('/blog/comments/{id}/new'))->setRequirements(['id' => '\d+'])); + $demoCollection->add('k', new Route('/blog/search')); + $demoCollection->add('l', new Route('/login')); + $demoCollection->add('m', new Route('/logout')); + $demoCollection->addPrefix('/{_locale}'); + $demoCollection->add('n', new Route('/{_locale}')); + $demoCollection->addRequirements(['_locale' => 'en|fr']); + $demoCollection->addDefaults(['_locale' => 'en']); + + /* test case 12 */ + $suffixCollection = new RouteCollection(); + $suffixCollection->add('r1', new Route('abc{foo}/1')); + $suffixCollection->add('r2', new Route('abc{foo}/2')); + $suffixCollection->add('r10', new Route('abc{foo}/10')); + $suffixCollection->add('r20', new Route('abc{foo}/20')); + $suffixCollection->add('r100', new Route('abc{foo}/100')); + $suffixCollection->add('r200', new Route('abc{foo}/200')); + + /* test case 13 */ + $hostCollection = new RouteCollection(); + $hostCollection->add('r1', (new Route('abc{foo}'))->setHost('{foo}.exampple.com')); + $hostCollection->add('r2', (new Route('abc{foo}'))->setHost('{foo}.exampple.com')); + + return [ + [new RouteCollection(), 'url_matcher0.php', []], + [$collection, 'url_matcher1.php', []], + [$redirectCollection, 'url_matcher2.php', ['base_class' => 'Symfony\Component\Routing\Tests\Fixtures\RedirectableUrlMatcher']], + [$rootprefixCollection, 'url_matcher3.php', []], + [$headMatchCasesCollection, 'url_matcher4.php', []], + [$groupOptimisedCollection, 'url_matcher5.php', ['base_class' => 'Symfony\Component\Routing\Tests\Fixtures\RedirectableUrlMatcher']], + [$trailingSlashCollection, 'url_matcher6.php', []], + [$trailingSlashCollection, 'url_matcher7.php', ['base_class' => 'Symfony\Component\Routing\Tests\Fixtures\RedirectableUrlMatcher']], + [$unicodeCollection, 'url_matcher8.php', []], + [$hostTreeCollection, 'url_matcher9.php', []], + [$chunkedCollection, 'url_matcher10.php', []], + [$demoCollection, 'url_matcher11.php', ['base_class' => 'Symfony\Component\Routing\Tests\Fixtures\RedirectableUrlMatcher']], + [$suffixCollection, 'url_matcher12.php', []], + [$hostCollection, 'url_matcher13.php', []], + ]; } - /** - * @param $dumper - */ private function generateDumpedMatcher(RouteCollection $collection, $redirectableStub = false) { - $options = array('class' => $this->matcherClass); + $options = ['class' => $this->matcherClass]; if ($redirectableStub) { $options['base_class'] = '\Symfony\Component\Routing\Tests\Matcher\Dumper\RedirectableUrlMatcherStub'; @@ -449,6 +491,16 @@ class PhpMatcherDumperTest extends TestCase return $this->matcherClass; } + + public function testGenerateDumperMatcherWithObject() + { + $this->expectException('InvalidArgumentException'); + $this->expectExceptionMessage('Symfony\Component\Routing\Route cannot contain objects'); + $routeCollection = new RouteCollection(); + $routeCollection->add('_', new Route('/', [new \stdClass()])); + $dumper = new PhpMatcherDumper($routeCollection); + $dumper->dump(); + } } abstract class RedirectableUrlMatcherStub extends UrlMatcher implements RedirectableUrlMatcherInterface diff --git a/vendor/symfony/routing/Tests/Matcher/Dumper/StaticPrefixCollectionTest.php b/vendor/symfony/routing/Tests/Matcher/Dumper/StaticPrefixCollectionTest.php index 37419e77436405b833b3a17d7e14589958581d5b..fe5014fc80007240bc519614920a4e2101010547 100644 --- a/vendor/symfony/routing/Tests/Matcher/Dumper/StaticPrefixCollectionTest.php +++ b/vendor/symfony/routing/Tests/Matcher/Dumper/StaticPrefixCollectionTest.php @@ -18,150 +18,152 @@ class StaticPrefixCollectionTest extends TestCase foreach ($routes as $route) { list($path, $name) = $route; $staticPrefix = (new Route($path))->compile()->getStaticPrefix(); - $collection->addRoute($staticPrefix, $name); + $collection->addRoute($staticPrefix, [$name]); } - $collection->optimizeGroups(); $dumped = $this->dumpCollection($collection); $this->assertEquals($expected, $dumped); } public function routeProvider() { - return array( - 'Simple - not nested' => array( - array( - array('/', 'root'), - array('/prefix/segment/', 'prefix_segment'), - array('/leading/segment/', 'leading_segment'), - ), + return [ + 'Simple - not nested' => [ + [ + ['/', 'root'], + ['/prefix/segment/', 'prefix_segment'], + ['/leading/segment/', 'leading_segment'], + ], <<<EOF -/ root -/prefix/segment prefix_segment -/leading/segment leading_segment +root +prefix_segment +leading_segment EOF - ), - 'Not nested - group too small' => array( - array( - array('/', 'root'), - array('/prefix/segment/aa', 'prefix_segment'), - array('/prefix/segment/bb', 'leading_segment'), - ), + ], + 'Nested - small group' => [ + [ + ['/', 'root'], + ['/prefix/segment/aa', 'prefix_segment'], + ['/prefix/segment/bb', 'leading_segment'], + ], <<<EOF -/ root -/prefix/segment/aa prefix_segment -/prefix/segment/bb leading_segment +root +/prefix/segment/ +-> prefix_segment +-> leading_segment EOF - ), - 'Nested - contains item at intersection' => array( - array( - array('/', 'root'), - array('/prefix/segment/', 'prefix_segment'), - array('/prefix/segment/bb', 'leading_segment'), - ), + ], + 'Nested - contains item at intersection' => [ + [ + ['/', 'root'], + ['/prefix/segment/', 'prefix_segment'], + ['/prefix/segment/bb', 'leading_segment'], + ], <<<EOF -/ root -/prefix/segment --> /prefix/segment prefix_segment --> /prefix/segment/bb leading_segment +root +/prefix/segment/ +-> prefix_segment +-> leading_segment EOF - ), - 'Simple one level nesting' => array( - array( - array('/', 'root'), - array('/group/segment/', 'nested_segment'), - array('/group/thing/', 'some_segment'), - array('/group/other/', 'other_segment'), - ), + ], + 'Simple one level nesting' => [ + [ + ['/', 'root'], + ['/group/segment/', 'nested_segment'], + ['/group/thing/', 'some_segment'], + ['/group/other/', 'other_segment'], + ], <<<EOF -/ root -/group --> /group/segment nested_segment --> /group/thing some_segment --> /group/other other_segment +root +/group/ +-> nested_segment +-> some_segment +-> other_segment EOF - ), - 'Retain matching order with groups' => array( - array( - array('/group/aa/', 'aa'), - array('/group/bb/', 'bb'), - array('/group/cc/', 'cc'), - array('/', 'root'), - array('/group/dd/', 'dd'), - array('/group/ee/', 'ee'), - array('/group/ff/', 'ff'), - ), + ], + 'Retain matching order with groups' => [ + [ + ['/group/aa/', 'aa'], + ['/group/bb/', 'bb'], + ['/group/cc/', 'cc'], + ['/(.*)', 'root'], + ['/group/dd/', 'dd'], + ['/group/ee/', 'ee'], + ['/group/ff/', 'ff'], + ], <<<EOF -/group --> /group/aa aa --> /group/bb bb --> /group/cc cc -/ root -/group --> /group/dd dd --> /group/ee ee --> /group/ff ff +/group/ +-> aa +-> bb +-> cc +root +/group/ +-> dd +-> ee +-> ff EOF - ), - 'Retain complex matching order with groups at base' => array( - array( - array('/aaa/111/', 'first_aaa'), - array('/prefixed/group/aa/', 'aa'), - array('/prefixed/group/bb/', 'bb'), - array('/prefixed/group/cc/', 'cc'), - array('/prefixed/', 'root'), - array('/prefixed/group/dd/', 'dd'), - array('/prefixed/group/ee/', 'ee'), - array('/prefixed/group/ff/', 'ff'), - array('/aaa/222/', 'second_aaa'), - array('/aaa/333/', 'third_aaa'), - ), + ], + 'Retain complex matching order with groups at base' => [ + [ + ['/aaa/111/', 'first_aaa'], + ['/prefixed/group/aa/', 'aa'], + ['/prefixed/group/bb/', 'bb'], + ['/prefixed/group/cc/', 'cc'], + ['/prefixed/(.*)', 'root'], + ['/prefixed/group/dd/', 'dd'], + ['/prefixed/group/ee/', 'ee'], + ['/prefixed/', 'parent'], + ['/prefixed/group/ff/', 'ff'], + ['/aaa/222/', 'second_aaa'], + ['/aaa/333/', 'third_aaa'], + ], <<<EOF -/aaa --> /aaa/111 first_aaa --> /aaa/222 second_aaa --> /aaa/333 third_aaa -/prefixed --> /prefixed/group --> -> /prefixed/group/aa aa --> -> /prefixed/group/bb bb --> -> /prefixed/group/cc cc --> /prefixed root --> /prefixed/group --> -> /prefixed/group/dd dd --> -> /prefixed/group/ee ee --> -> /prefixed/group/ff ff +/aaa/ +-> first_aaa +-> second_aaa +-> third_aaa +/prefixed/ +-> /prefixed/group/ +-> -> aa +-> -> bb +-> -> cc +-> root +-> /prefixed/group/ +-> -> dd +-> -> ee +-> -> ff +-> parent EOF - ), + ], - 'Group regardless of segments' => array( - array( - array('/aaa-111/', 'a1'), - array('/aaa-222/', 'a2'), - array('/aaa-333/', 'a3'), - array('/group-aa/', 'g1'), - array('/group-bb/', 'g2'), - array('/group-cc/', 'g3'), - ), + 'Group regardless of segments' => [ + [ + ['/aaa-111/', 'a1'], + ['/aaa-222/', 'a2'], + ['/aaa-333/', 'a3'], + ['/group-aa/', 'g1'], + ['/group-bb/', 'g2'], + ['/group-cc/', 'g3'], + ], <<<EOF /aaa- --> /aaa-111 a1 --> /aaa-222 a2 --> /aaa-333 a3 +-> a1 +-> a2 +-> a3 /group- --> /group-aa g1 --> /group-bb g2 --> /group-cc g3 +-> g1 +-> g2 +-> g3 EOF - ), - ); + ], + ]; } private function dumpCollection(StaticPrefixCollection $collection, $prefix = '') { - $lines = array(); + $lines = []; - foreach ($collection->getItems() as $item) { + foreach ($collection->getRoutes() as $item) { if ($item instanceof StaticPrefixCollection) { $lines[] = $prefix.$item->getPrefix(); $lines[] = $this->dumpCollection($item, $prefix.'-> '); diff --git a/vendor/symfony/routing/Tests/Matcher/RedirectableUrlMatcherTest.php b/vendor/symfony/routing/Tests/Matcher/RedirectableUrlMatcherTest.php index 0948e002adf8aade34bab1d67baf1afcc690c656..1461b4b911b9c012bc5dea2658f7aeca03c7d730 100644 --- a/vendor/symfony/routing/Tests/Matcher/RedirectableUrlMatcherTest.php +++ b/vendor/symfony/routing/Tests/Matcher/RedirectableUrlMatcherTest.php @@ -11,58 +11,65 @@ namespace Symfony\Component\Routing\Tests\Matcher; -use PHPUnit\Framework\TestCase; +use Symfony\Component\Routing\RequestContext; use Symfony\Component\Routing\Route; use Symfony\Component\Routing\RouteCollection; -use Symfony\Component\Routing\RequestContext; -class RedirectableUrlMatcherTest extends TestCase +class RedirectableUrlMatcherTest extends UrlMatcherTest { - public function testRedirectWhenNoSlash() + public function testMissingTrailingSlash() { $coll = new RouteCollection(); $coll->add('foo', new Route('/foo/')); - $matcher = $this->getMockForAbstractClass('Symfony\Component\Routing\Matcher\RedirectableUrlMatcher', array($coll, new RequestContext())); - $matcher->expects($this->once())->method('redirect')->will($this->returnValue(array())); + $matcher = $this->getUrlMatcher($coll); + $matcher->expects($this->once())->method('redirect')->willReturn([]); $matcher->match('/foo'); } - /** - * @expectedException \Symfony\Component\Routing\Exception\ResourceNotFoundException - */ + public function testExtraTrailingSlash() + { + $coll = new RouteCollection(); + $coll->add('foo', new Route('/foo')); + + $matcher = $this->getUrlMatcher($coll); + $matcher->expects($this->once())->method('redirect')->willReturn([]); + $matcher->match('/foo/'); + } + public function testRedirectWhenNoSlashForNonSafeMethod() { + $this->expectException('Symfony\Component\Routing\Exception\ResourceNotFoundException'); $coll = new RouteCollection(); $coll->add('foo', new Route('/foo/')); $context = new RequestContext(); $context->setMethod('POST'); - $matcher = $this->getMockForAbstractClass('Symfony\Component\Routing\Matcher\RedirectableUrlMatcher', array($coll, $context)); + $matcher = $this->getUrlMatcher($coll, $context); $matcher->match('/foo'); } public function testSchemeRedirectRedirectsToFirstScheme() { $coll = new RouteCollection(); - $coll->add('foo', new Route('/foo', array(), array(), array(), '', array('FTP', 'HTTPS'))); + $coll->add('foo', new Route('/foo', [], [], [], '', ['FTP', 'HTTPS'])); - $matcher = $this->getMockForAbstractClass('Symfony\Component\Routing\Matcher\RedirectableUrlMatcher', array($coll, new RequestContext())); + $matcher = $this->getUrlMatcher($coll); $matcher ->expects($this->once()) ->method('redirect') ->with('/foo', 'foo', 'ftp') - ->will($this->returnValue(array('_route' => 'foo'))) + ->willReturn(['_route' => 'foo']) ; $matcher->match('/foo'); } - public function testNoSchemaRedirectIfOnOfMultipleSchemesMatches() + public function testNoSchemaRedirectIfOneOfMultipleSchemesMatches() { $coll = new RouteCollection(); - $coll->add('foo', new Route('/foo', array(), array(), array(), '', array('https', 'http'))); + $coll->add('foo', new Route('/foo', [], [], [], '', ['https', 'http'])); - $matcher = $this->getMockForAbstractClass('Symfony\Component\Routing\Matcher\RedirectableUrlMatcher', array($coll, new RequestContext())); + $matcher = $this->getUrlMatcher($coll); $matcher ->expects($this->never()) ->method('redirect'); @@ -72,16 +79,30 @@ class RedirectableUrlMatcherTest extends TestCase public function testSchemeRedirectWithParams() { $coll = new RouteCollection(); - $coll->add('foo', new Route('/foo/{bar}', array(), array(), array(), '', array('https'))); + $coll->add('foo', new Route('/foo/{bar}', [], [], [], '', ['https'])); - $matcher = $this->getMockForAbstractClass('Symfony\Component\Routing\Matcher\RedirectableUrlMatcher', array($coll, new RequestContext())); + $matcher = $this->getUrlMatcher($coll); $matcher ->expects($this->once()) ->method('redirect') ->with('/foo/baz', 'foo', 'https') - ->will($this->returnValue(array('redirect' => 'value'))) + ->willReturn(['redirect' => 'value']) ; - $this->assertEquals(array('_route' => 'foo', 'bar' => 'baz', 'redirect' => 'value'), $matcher->match('/foo/baz')); + $this->assertEquals(['_route' => 'foo', 'bar' => 'baz', 'redirect' => 'value'], $matcher->match('/foo/baz')); + } + + public function testSchemeRedirectForRoot() + { + $coll = new RouteCollection(); + $coll->add('foo', new Route('/', [], [], [], '', ['https'])); + + $matcher = $this->getUrlMatcher($coll); + $matcher + ->expects($this->once()) + ->method('redirect') + ->with('/', 'foo', 'https') + ->willReturn(['redirect' => 'value']); + $this->assertEquals(['_route' => 'foo', 'redirect' => 'value'], $matcher->match('/')); } public function testSlashRedirectWithParams() @@ -89,14 +110,14 @@ class RedirectableUrlMatcherTest extends TestCase $coll = new RouteCollection(); $coll->add('foo', new Route('/foo/{bar}/')); - $matcher = $this->getMockForAbstractClass('Symfony\Component\Routing\Matcher\RedirectableUrlMatcher', array($coll, new RequestContext())); + $matcher = $this->getUrlMatcher($coll); $matcher ->expects($this->once()) ->method('redirect') ->with('/foo/baz/', 'foo', null) - ->will($this->returnValue(array('redirect' => 'value'))) + ->willReturn(['redirect' => 'value']) ; - $this->assertEquals(array('_route' => 'foo', 'bar' => 'baz', 'redirect' => 'value'), $matcher->match('/foo/baz')); + $this->assertEquals(['_route' => 'foo', 'bar' => 'baz', 'redirect' => 'value'], $matcher->match('/foo/baz')); } public function testRedirectPreservesUrlEncoding() @@ -104,8 +125,90 @@ class RedirectableUrlMatcherTest extends TestCase $coll = new RouteCollection(); $coll->add('foo', new Route('/foo:bar/')); - $matcher = $this->getMockForAbstractClass('Symfony\Component\Routing\Matcher\RedirectableUrlMatcher', array($coll, new RequestContext())); - $matcher->expects($this->once())->method('redirect')->with('/foo%3Abar/')->willReturn(array()); + $matcher = $this->getUrlMatcher($coll); + $matcher->expects($this->once())->method('redirect')->with('/foo%3Abar/')->willReturn([]); $matcher->match('/foo%3Abar'); } + + public function testSchemeRequirement() + { + $coll = new RouteCollection(); + $coll->add('foo', new Route('/foo', [], [], [], '', ['https'])); + $matcher = $this->getUrlMatcher($coll, new RequestContext()); + $matcher->expects($this->once())->method('redirect')->with('/foo', 'foo', 'https')->willReturn([]); + $this->assertSame(['_route' => 'foo'], $matcher->match('/foo')); + } + + public function testFallbackPage() + { + $coll = new RouteCollection(); + $coll->add('foo', new Route('/foo/')); + $coll->add('bar', new Route('/{name}')); + + $matcher = $this->getUrlMatcher($coll); + $matcher->expects($this->once())->method('redirect')->with('/foo/', 'foo')->willReturn(['_route' => 'foo']); + $this->assertSame(['_route' => 'foo'], $matcher->match('/foo')); + + $coll = new RouteCollection(); + $coll->add('foo', new Route('/foo')); + $coll->add('bar', new Route('/{name}/')); + + $matcher = $this->getUrlMatcher($coll); + $matcher->expects($this->once())->method('redirect')->with('/foo', 'foo')->willReturn(['_route' => 'foo']); + $this->assertSame(['_route' => 'foo'], $matcher->match('/foo/')); + } + + public function testMissingTrailingSlashAndScheme() + { + $coll = new RouteCollection(); + $coll->add('foo', (new Route('/foo/'))->setSchemes(['https'])); + + $matcher = $this->getUrlMatcher($coll); + $matcher->expects($this->once())->method('redirect')->with('/foo/', 'foo', 'https')->willReturn([]); + $matcher->match('/foo'); + } + + public function testSlashAndVerbPrecedenceWithRedirection() + { + $coll = new RouteCollection(); + $coll->add('a', new Route('/api/customers/{customerId}/contactpersons', [], [], [], '', [], ['post'])); + $coll->add('b', new Route('/api/customers/{customerId}/contactpersons/', [], [], [], '', [], ['get'])); + + $matcher = $this->getUrlMatcher($coll); + $expected = [ + '_route' => 'b', + 'customerId' => '123', + ]; + $this->assertEquals($expected, $matcher->match('/api/customers/123/contactpersons/')); + + $matcher->expects($this->once())->method('redirect')->with('/api/customers/123/contactpersons/')->willReturn([]); + $this->assertEquals($expected, $matcher->match('/api/customers/123/contactpersons')); + } + + public function testNonGreedyTrailingRequirement() + { + $coll = new RouteCollection(); + $coll->add('a', new Route('/{a}', [], ['a' => '\d+'])); + + $matcher = $this->getUrlMatcher($coll); + $matcher->expects($this->once())->method('redirect')->with('/123')->willReturn([]); + + $this->assertEquals(['_route' => 'a', 'a' => '123'], $matcher->match('/123/')); + } + + public function testTrailingRequirementWithDefault_A() + { + $coll = new RouteCollection(); + $coll->add('a', new Route('/fr-fr/{a}', ['a' => 'aaa'], ['a' => '.+'])); + + $matcher = $this->getUrlMatcher($coll); + $matcher->expects($this->once())->method('redirect')->with('/fr-fr')->willReturn([]); + + $this->assertEquals(['_route' => 'a', 'a' => 'aaa'], $matcher->match('/fr-fr/')); + } + + protected function getUrlMatcher(RouteCollection $routes, RequestContext $context = null) + { + return $this->getMockForAbstractClass('Symfony\Component\Routing\Matcher\RedirectableUrlMatcher', [$routes, $context ?: new RequestContext()]); + } } diff --git a/vendor/symfony/routing/Tests/Matcher/TraceableUrlMatcherTest.php b/vendor/symfony/routing/Tests/Matcher/TraceableUrlMatcherTest.php index 9f0529e2de5d618bcff679a5e4953cb5b56930c8..b31f99e0c4964b84196888198beedd8f3ca74ef8 100644 --- a/vendor/symfony/routing/Tests/Matcher/TraceableUrlMatcherTest.php +++ b/vendor/symfony/routing/Tests/Matcher/TraceableUrlMatcherTest.php @@ -11,53 +11,52 @@ namespace Symfony\Component\Routing\Tests\Matcher; -use PHPUnit\Framework\TestCase; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\Routing\Matcher\TraceableUrlMatcher; +use Symfony\Component\Routing\RequestContext; use Symfony\Component\Routing\Route; use Symfony\Component\Routing\RouteCollection; -use Symfony\Component\Routing\RequestContext; -use Symfony\Component\Routing\Matcher\TraceableUrlMatcher; -class TraceableUrlMatcherTest extends TestCase +class TraceableUrlMatcherTest extends UrlMatcherTest { public function test() { $coll = new RouteCollection(); - $coll->add('foo', new Route('/foo', array(), array(), array(), '', array(), array('POST'))); - $coll->add('bar', new Route('/bar/{id}', array(), array('id' => '\d+'))); - $coll->add('bar1', new Route('/bar/{name}', array(), array('id' => '\w+'), array(), '', array(), array('POST'))); - $coll->add('bar2', new Route('/foo', array(), array(), array(), 'baz')); - $coll->add('bar3', new Route('/foo1', array(), array(), array(), 'baz')); - $coll->add('bar4', new Route('/foo2', array(), array(), array(), 'baz', array(), array(), 'context.getMethod() == "GET"')); + $coll->add('foo', new Route('/foo', [], [], [], '', [], ['POST'])); + $coll->add('bar', new Route('/bar/{id}', [], ['id' => '\d+'])); + $coll->add('bar1', new Route('/bar/{name}', [], ['id' => '\w+'], [], '', [], ['POST'])); + $coll->add('bar2', new Route('/foo', [], [], [], 'baz')); + $coll->add('bar3', new Route('/foo1', [], [], [], 'baz')); + $coll->add('bar4', new Route('/foo2', [], [], [], 'baz', [], [], 'context.getMethod() == "GET"')); $context = new RequestContext(); $context->setHost('baz'); $matcher = new TraceableUrlMatcher($coll, $context); $traces = $matcher->getTraces('/babar'); - $this->assertSame(array(0, 0, 0, 0, 0, 0), $this->getLevels($traces)); + $this->assertSame([0, 0, 0, 0, 0, 0], $this->getLevels($traces)); $traces = $matcher->getTraces('/foo'); - $this->assertSame(array(1, 0, 0, 2), $this->getLevels($traces)); + $this->assertSame([1, 0, 0, 2], $this->getLevels($traces)); $traces = $matcher->getTraces('/bar/12'); - $this->assertSame(array(0, 2), $this->getLevels($traces)); + $this->assertSame([0, 2], $this->getLevels($traces)); $traces = $matcher->getTraces('/bar/dd'); - $this->assertSame(array(0, 1, 1, 0, 0, 0), $this->getLevels($traces)); + $this->assertSame([0, 1, 1, 0, 0, 0], $this->getLevels($traces)); $traces = $matcher->getTraces('/foo1'); - $this->assertSame(array(0, 0, 0, 0, 2), $this->getLevels($traces)); + $this->assertSame([0, 0, 0, 0, 2], $this->getLevels($traces)); $context->setMethod('POST'); $traces = $matcher->getTraces('/foo'); - $this->assertSame(array(2), $this->getLevels($traces)); + $this->assertSame([2], $this->getLevels($traces)); $traces = $matcher->getTraces('/bar/dd'); - $this->assertSame(array(0, 1, 2), $this->getLevels($traces)); + $this->assertSame([0, 1, 2], $this->getLevels($traces)); $traces = $matcher->getTraces('/foo2'); - $this->assertSame(array(0, 0, 0, 0, 0, 1), $this->getLevels($traces)); + $this->assertSame([0, 0, 0, 0, 0, 1], $this->getLevels($traces)); } public function testMatchRouteOnMultipleHosts() @@ -65,17 +64,17 @@ class TraceableUrlMatcherTest extends TestCase $routes = new RouteCollection(); $routes->add('first', new Route( '/mypath/', - array('_controller' => 'MainBundle:Info:first'), - array(), - array(), + ['_controller' => 'MainBundle:Info:first'], + [], + [], 'some.example.com' )); $routes->add('second', new Route( '/mypath/', - array('_controller' => 'MainBundle:Info:second'), - array(), - array(), + ['_controller' => 'MainBundle:Info:second'], + [], + [], 'another.example.com' )); @@ -86,14 +85,14 @@ class TraceableUrlMatcherTest extends TestCase $traces = $matcher->getTraces('/mypath/'); $this->assertSame( - array(TraceableUrlMatcher::ROUTE_ALMOST_MATCHES, TraceableUrlMatcher::ROUTE_ALMOST_MATCHES), + [TraceableUrlMatcher::ROUTE_ALMOST_MATCHES, TraceableUrlMatcher::ROUTE_ALMOST_MATCHES], $this->getLevels($traces) ); } public function getLevels($traces) { - $levels = array(); + $levels = []; foreach ($traces as $trace) { $levels[] = $trace['level']; } @@ -104,7 +103,7 @@ class TraceableUrlMatcherTest extends TestCase public function testRoutesWithConditions() { $routes = new RouteCollection(); - $routes->add('foo', new Route('/foo', array(), array(), array(), 'baz', array(), array(), "request.headers.get('User-Agent') matches '/firefox/i'")); + $routes->add('foo', new Route('/foo', [], [], [], 'baz', [], [], "request.headers.get('User-Agent') matches '/firefox/i'")); $context = new RequestContext(); $context->setHost('baz'); @@ -115,8 +114,13 @@ class TraceableUrlMatcherTest extends TestCase $traces = $matcher->getTracesForRequest($notMatchingRequest); $this->assertEquals("Condition \"request.headers.get('User-Agent') matches '/firefox/i'\" does not evaluate to \"true\"", $traces[0]['log']); - $matchingRequest = Request::create('/foo', 'GET', array(), array(), array(), array('HTTP_USER_AGENT' => 'Firefox')); + $matchingRequest = Request::create('/foo', 'GET', [], [], [], ['HTTP_USER_AGENT' => 'Firefox']); $traces = $matcher->getTracesForRequest($matchingRequest); $this->assertEquals('Route matches!', $traces[0]['log']); } + + protected function getUrlMatcher(RouteCollection $routes, RequestContext $context = null) + { + return new TraceableUrlMatcher($routes, $context ?: new RequestContext()); + } } diff --git a/vendor/symfony/routing/Tests/Matcher/UrlMatcherTest.php b/vendor/symfony/routing/Tests/Matcher/UrlMatcherTest.php index 8545c2c29d83d726dbb4566f7d26ad696e906cde..c6846ae8b5e643cc70bae18c20af72e47a25395c 100644 --- a/vendor/symfony/routing/Tests/Matcher/UrlMatcherTest.php +++ b/vendor/symfony/routing/Tests/Matcher/UrlMatcherTest.php @@ -15,9 +15,9 @@ use PHPUnit\Framework\TestCase; use Symfony\Component\Routing\Exception\MethodNotAllowedException; use Symfony\Component\Routing\Exception\ResourceNotFoundException; use Symfony\Component\Routing\Matcher\UrlMatcher; +use Symfony\Component\Routing\RequestContext; use Symfony\Component\Routing\Route; use Symfony\Component\Routing\RouteCollection; -use Symfony\Component\Routing\RequestContext; class UrlMatcherTest extends TestCase { @@ -26,77 +26,98 @@ class UrlMatcherTest extends TestCase $coll = new RouteCollection(); $coll->add('foo', new Route('/foo')); - $matcher = new UrlMatcher($coll, new RequestContext()); - $this->assertInternalType('array', $matcher->match('/foo')); + $matcher = $this->getUrlMatcher($coll); + $this->assertIsArray($matcher->match('/foo')); } public function testMethodNotAllowed() { $coll = new RouteCollection(); - $coll->add('foo', new Route('/foo', array(), array(), array(), '', array(), array('post'))); + $coll->add('foo', new Route('/foo', [], [], [], '', [], ['post'])); - $matcher = new UrlMatcher($coll, new RequestContext()); + $matcher = $this->getUrlMatcher($coll); try { $matcher->match('/foo'); $this->fail(); } catch (MethodNotAllowedException $e) { - $this->assertEquals(array('POST'), $e->getAllowedMethods()); + $this->assertEquals(['POST'], $e->getAllowedMethods()); + } + } + + public function testMethodNotAllowedOnRoot() + { + $coll = new RouteCollection(); + $coll->add('foo', new Route('/', [], [], [], '', [], ['GET'])); + + $matcher = $this->getUrlMatcher($coll, new RequestContext('', 'POST')); + + try { + $matcher->match('/'); + $this->fail(); + } catch (MethodNotAllowedException $e) { + $this->assertEquals(['GET'], $e->getAllowedMethods()); } } public function testHeadAllowedWhenRequirementContainsGet() { $coll = new RouteCollection(); - $coll->add('foo', new Route('/foo', array(), array(), array(), '', array(), array('get'))); + $coll->add('foo', new Route('/foo', [], [], [], '', [], ['get'])); - $matcher = new UrlMatcher($coll, new RequestContext('', 'head')); - $this->assertInternalType('array', $matcher->match('/foo')); + $matcher = $this->getUrlMatcher($coll, new RequestContext('', 'head')); + $this->assertIsArray($matcher->match('/foo')); } public function testMethodNotAllowedAggregatesAllowedMethods() { $coll = new RouteCollection(); - $coll->add('foo1', new Route('/foo', array(), array(), array(), '', array(), array('post'))); - $coll->add('foo2', new Route('/foo', array(), array(), array(), '', array(), array('put', 'delete'))); + $coll->add('foo1', new Route('/foo', [], [], [], '', [], ['post'])); + $coll->add('foo2', new Route('/foo', [], [], [], '', [], ['put', 'delete'])); - $matcher = new UrlMatcher($coll, new RequestContext()); + $matcher = $this->getUrlMatcher($coll); try { $matcher->match('/foo'); $this->fail(); } catch (MethodNotAllowedException $e) { - $this->assertEquals(array('POST', 'PUT', 'DELETE'), $e->getAllowedMethods()); + $this->assertEquals(['POST', 'PUT', 'DELETE'], $e->getAllowedMethods()); } } - public function testMatch() + public function testPatternMatchAndParameterReturn() { - // test the patterns are matched and parameters are returned $collection = new RouteCollection(); $collection->add('foo', new Route('/foo/{bar}')); - $matcher = new UrlMatcher($collection, new RequestContext()); + $matcher = $this->getUrlMatcher($collection); try { $matcher->match('/no-match'); $this->fail(); } catch (ResourceNotFoundException $e) { } - $this->assertEquals(array('_route' => 'foo', 'bar' => 'baz'), $matcher->match('/foo/baz')); + $this->assertEquals(['_route' => 'foo', 'bar' => 'baz'], $matcher->match('/foo/baz')); + } + + public function testDefaultsAreMerged() + { // test that defaults are merged $collection = new RouteCollection(); - $collection->add('foo', new Route('/foo/{bar}', array('def' => 'test'))); - $matcher = new UrlMatcher($collection, new RequestContext()); - $this->assertEquals(array('_route' => 'foo', 'bar' => 'baz', 'def' => 'test'), $matcher->match('/foo/baz')); + $collection->add('foo', new Route('/foo/{bar}', ['def' => 'test'])); + $matcher = $this->getUrlMatcher($collection); + $this->assertEquals(['_route' => 'foo', 'bar' => 'baz', 'def' => 'test'], $matcher->match('/foo/baz')); + } + public function testMethodIsIgnoredIfNoMethodGiven() + { // test that route "method" is ignored if no method is given in the context $collection = new RouteCollection(); - $collection->add('foo', new Route('/foo', array(), array(), array(), '', array(), array('get', 'head'))); - $matcher = new UrlMatcher($collection, new RequestContext()); - $this->assertInternalType('array', $matcher->match('/foo')); + $collection->add('foo', new Route('/foo', [], [], [], '', [], ['get', 'head'])); + $matcher = $this->getUrlMatcher($collection); + $this->assertIsArray($matcher->match('/foo')); // route does not match with POST method context - $matcher = new UrlMatcher($collection, new RequestContext('', 'post')); + $matcher = $this->getUrlMatcher($collection, new RequestContext('', 'post')); try { $matcher->match('/foo'); $this->fail(); @@ -104,31 +125,35 @@ class UrlMatcherTest extends TestCase } // route does match with GET or HEAD method context - $matcher = new UrlMatcher($collection, new RequestContext()); - $this->assertInternalType('array', $matcher->match('/foo')); - $matcher = new UrlMatcher($collection, new RequestContext('', 'head')); - $this->assertInternalType('array', $matcher->match('/foo')); + $matcher = $this->getUrlMatcher($collection); + $this->assertIsArray($matcher->match('/foo')); + $matcher = $this->getUrlMatcher($collection, new RequestContext('', 'head')); + $this->assertIsArray($matcher->match('/foo')); + } - // route with an optional variable as the first segment + public function testRouteWithOptionalVariableAsFirstSegment() + { $collection = new RouteCollection(); - $collection->add('bar', new Route('/{bar}/foo', array('bar' => 'bar'), array('bar' => 'foo|bar'))); - $matcher = new UrlMatcher($collection, new RequestContext()); - $this->assertEquals(array('_route' => 'bar', 'bar' => 'bar'), $matcher->match('/bar/foo')); - $this->assertEquals(array('_route' => 'bar', 'bar' => 'foo'), $matcher->match('/foo/foo')); + $collection->add('bar', new Route('/{bar}/foo', ['bar' => 'bar'], ['bar' => 'foo|bar'])); + $matcher = $this->getUrlMatcher($collection); + $this->assertEquals(['_route' => 'bar', 'bar' => 'bar'], $matcher->match('/bar/foo')); + $this->assertEquals(['_route' => 'bar', 'bar' => 'foo'], $matcher->match('/foo/foo')); $collection = new RouteCollection(); - $collection->add('bar', new Route('/{bar}', array('bar' => 'bar'), array('bar' => 'foo|bar'))); - $matcher = new UrlMatcher($collection, new RequestContext()); - $this->assertEquals(array('_route' => 'bar', 'bar' => 'foo'), $matcher->match('/foo')); - $this->assertEquals(array('_route' => 'bar', 'bar' => 'bar'), $matcher->match('/')); + $collection->add('bar', new Route('/{bar}', ['bar' => 'bar'], ['bar' => 'foo|bar'])); + $matcher = $this->getUrlMatcher($collection); + $this->assertEquals(['_route' => 'bar', 'bar' => 'foo'], $matcher->match('/foo')); + $this->assertEquals(['_route' => 'bar', 'bar' => 'bar'], $matcher->match('/')); + } - // route with only optional variables + public function testRouteWithOnlyOptionalVariables() + { $collection = new RouteCollection(); - $collection->add('bar', new Route('/{foo}/{bar}', array('foo' => 'foo', 'bar' => 'bar'), array())); - $matcher = new UrlMatcher($collection, new RequestContext()); - $this->assertEquals(array('_route' => 'bar', 'foo' => 'foo', 'bar' => 'bar'), $matcher->match('/')); - $this->assertEquals(array('_route' => 'bar', 'foo' => 'a', 'bar' => 'bar'), $matcher->match('/a')); - $this->assertEquals(array('_route' => 'bar', 'foo' => 'a', 'bar' => 'b'), $matcher->match('/a/b')); + $collection->add('bar', new Route('/{foo}/{bar}', ['foo' => 'foo', 'bar' => 'bar'], [])); + $matcher = $this->getUrlMatcher($collection); + $this->assertEquals(['_route' => 'bar', 'foo' => 'foo', 'bar' => 'bar'], $matcher->match('/')); + $this->assertEquals(['_route' => 'bar', 'foo' => 'a', 'bar' => 'bar'], $matcher->match('/a')); + $this->assertEquals(['_route' => 'bar', 'foo' => 'a', 'bar' => 'b'], $matcher->match('/a/b')); } public function testMatchWithPrefixes() @@ -138,8 +163,8 @@ class UrlMatcherTest extends TestCase $collection->addPrefix('/b'); $collection->addPrefix('/a'); - $matcher = new UrlMatcher($collection, new RequestContext()); - $this->assertEquals(array('_route' => 'foo', 'foo' => 'foo'), $matcher->match('/a/b/foo')); + $matcher = $this->getUrlMatcher($collection); + $this->assertEquals(['_route' => 'foo', 'foo' => 'foo'], $matcher->match('/a/b/foo')); } public function testMatchWithDynamicPrefix() @@ -149,8 +174,8 @@ class UrlMatcherTest extends TestCase $collection->addPrefix('/b'); $collection->addPrefix('/{_locale}'); - $matcher = new UrlMatcher($collection, new RequestContext()); - $this->assertEquals(array('_locale' => 'fr', '_route' => 'foo', 'foo' => 'foo'), $matcher->match('/fr/b/foo')); + $matcher = $this->getUrlMatcher($collection); + $this->assertEquals(['_locale' => 'fr', '_route' => 'foo', 'foo' => 'foo'], $matcher->match('/fr/b/foo')); } public function testMatchSpecialRouteName() @@ -158,28 +183,57 @@ class UrlMatcherTest extends TestCase $collection = new RouteCollection(); $collection->add('$péß^a|', new Route('/bar')); - $matcher = new UrlMatcher($collection, new RequestContext()); - $this->assertEquals(array('_route' => '$péß^a|'), $matcher->match('/bar')); + $matcher = $this->getUrlMatcher($collection); + $this->assertEquals(['_route' => '$péß^a|'], $matcher->match('/bar')); + } + + public function testMatchImportantVariable() + { + $collection = new RouteCollection(); + $collection->add('index', new Route('/index.{!_format}', ['_format' => 'xml'])); + + $matcher = $this->getUrlMatcher($collection); + $this->assertEquals(['_route' => 'index', '_format' => 'xml'], $matcher->match('/index.xml')); + } + + public function testShortPathDoesNotMatchImportantVariable() + { + $this->expectException('Symfony\Component\Routing\Exception\ResourceNotFoundException'); + + $collection = new RouteCollection(); + $collection->add('index', new Route('/index.{!_format}', ['_format' => 'xml'])); + + $this->getUrlMatcher($collection)->match('/index'); + } + + public function testTrailingEncodedNewlineIsNotOverlooked() + { + $this->expectException('Symfony\Component\Routing\Exception\ResourceNotFoundException'); + $collection = new RouteCollection(); + $collection->add('foo', new Route('/foo')); + + $matcher = $this->getUrlMatcher($collection); + $matcher->match('/foo%0a'); } public function testMatchNonAlpha() { $collection = new RouteCollection(); $chars = '!"$%éà &\'()*+,./:;<=>@ABCDEFGHIJKLMNOPQRSTUVWXYZ\\[]^_`abcdefghijklmnopqrstuvwxyz{|}~-'; - $collection->add('foo', new Route('/{foo}/bar', array(), array('foo' => '['.preg_quote($chars).']+'), array('utf8' => true))); + $collection->add('foo', new Route('/{foo}/bar', [], ['foo' => '['.preg_quote($chars).']+'], ['utf8' => true])); - $matcher = new UrlMatcher($collection, new RequestContext()); - $this->assertEquals(array('_route' => 'foo', 'foo' => $chars), $matcher->match('/'.rawurlencode($chars).'/bar')); - $this->assertEquals(array('_route' => 'foo', 'foo' => $chars), $matcher->match('/'.strtr($chars, array('%' => '%25')).'/bar')); + $matcher = $this->getUrlMatcher($collection); + $this->assertEquals(['_route' => 'foo', 'foo' => $chars], $matcher->match('/'.rawurlencode($chars).'/bar')); + $this->assertEquals(['_route' => 'foo', 'foo' => $chars], $matcher->match('/'.strtr($chars, ['%' => '%25']).'/bar')); } public function testMatchWithDotMetacharacterInRequirements() { $collection = new RouteCollection(); - $collection->add('foo', new Route('/{foo}/bar', array(), array('foo' => '.+'))); + $collection->add('foo', new Route('/{foo}/bar', [], ['foo' => '.+'])); - $matcher = new UrlMatcher($collection, new RequestContext()); - $this->assertEquals(array('_route' => 'foo', 'foo' => "\n"), $matcher->match('/'.urlencode("\n").'/bar'), 'linefeed character is matched'); + $matcher = $this->getUrlMatcher($collection); + $this->assertEquals(['_route' => 'foo', 'foo' => "\n"], $matcher->match('/'.urlencode("\n").'/bar'), 'linefeed character is matched'); } public function testMatchOverriddenRoute() @@ -192,11 +246,11 @@ class UrlMatcherTest extends TestCase $collection->addCollection($collection1); - $matcher = new UrlMatcher($collection, new RequestContext()); + $matcher = $this->getUrlMatcher($collection); - $this->assertEquals(array('_route' => 'foo'), $matcher->match('/foo1')); - $this->{method_exists($this, $_ = 'expectException') ? $_ : 'setExpectedException'}('Symfony\Component\Routing\Exception\ResourceNotFoundException'); - $this->assertEquals(array(), $matcher->match('/foo')); + $this->assertEquals(['_route' => 'foo'], $matcher->match('/foo1')); + $this->expectException('Symfony\Component\Routing\Exception\ResourceNotFoundException'); + $this->assertEquals([], $matcher->match('/foo')); } public function testMatchRegression() @@ -205,12 +259,12 @@ class UrlMatcherTest extends TestCase $coll->add('foo', new Route('/foo/{foo}')); $coll->add('bar', new Route('/foo/bar/{foo}')); - $matcher = new UrlMatcher($coll, new RequestContext()); - $this->assertEquals(array('foo' => 'bar', '_route' => 'bar'), $matcher->match('/foo/bar/bar')); + $matcher = $this->getUrlMatcher($coll); + $this->assertEquals(['foo' => 'bar', '_route' => 'bar'], $matcher->match('/foo/bar/bar')); $collection = new RouteCollection(); $collection->add('foo', new Route('/{bar}')); - $matcher = new UrlMatcher($collection, new RequestContext()); + $matcher = $this->getUrlMatcher($collection); try { $matcher->match('/'); $this->fail(); @@ -218,56 +272,68 @@ class UrlMatcherTest extends TestCase } } + public function testMultipleParams() + { + $coll = new RouteCollection(); + $coll->add('foo1', new Route('/foo/{a}/{b}')); + $coll->add('foo2', new Route('/foo/{a}/test/test/{b}')); + $coll->add('foo3', new Route('/foo/{a}/{b}/{c}/{d}')); + + $route = $this->getUrlMatcher($coll)->match('/foo/test/test/test/bar')['_route']; + + $this->assertEquals('foo2', $route); + } + public function testDefaultRequirementForOptionalVariables() { $coll = new RouteCollection(); - $coll->add('test', new Route('/{page}.{_format}', array('page' => 'index', '_format' => 'html'))); + $coll->add('test', new Route('/{page}.{_format}', ['page' => 'index', '_format' => 'html'])); - $matcher = new UrlMatcher($coll, new RequestContext()); - $this->assertEquals(array('page' => 'my-page', '_format' => 'xml', '_route' => 'test'), $matcher->match('/my-page.xml')); + $matcher = $this->getUrlMatcher($coll); + $this->assertEquals(['page' => 'my-page', '_format' => 'xml', '_route' => 'test'], $matcher->match('/my-page.xml')); } public function testMatchingIsEager() { $coll = new RouteCollection(); - $coll->add('test', new Route('/{foo}-{bar}-', array(), array('foo' => '.+', 'bar' => '.+'))); + $coll->add('test', new Route('/{foo}-{bar}-', [], ['foo' => '.+', 'bar' => '.+'])); - $matcher = new UrlMatcher($coll, new RequestContext()); - $this->assertEquals(array('foo' => 'text1-text2-text3', 'bar' => 'text4', '_route' => 'test'), $matcher->match('/text1-text2-text3-text4-')); + $matcher = $this->getUrlMatcher($coll); + $this->assertEquals(['foo' => 'text1-text2-text3', 'bar' => 'text4', '_route' => 'test'], $matcher->match('/text1-text2-text3-text4-')); } public function testAdjacentVariables() { $coll = new RouteCollection(); - $coll->add('test', new Route('/{w}{x}{y}{z}.{_format}', array('z' => 'default-z', '_format' => 'html'), array('y' => 'y|Y'))); + $coll->add('test', new Route('/{w}{x}{y}{z}.{_format}', ['z' => 'default-z', '_format' => 'html'], ['y' => 'y|Y'])); - $matcher = new UrlMatcher($coll, new RequestContext()); + $matcher = $this->getUrlMatcher($coll); // 'w' eagerly matches as much as possible and the other variables match the remaining chars. // This also shows that the variables w-z must all exclude the separating char (the dot '.' in this case) by default requirement. // Otherwise they would also consume '.xml' and _format would never match as it's an optional variable. - $this->assertEquals(array('w' => 'wwwww', 'x' => 'x', 'y' => 'Y', 'z' => 'Z', '_format' => 'xml', '_route' => 'test'), $matcher->match('/wwwwwxYZ.xml')); + $this->assertEquals(['w' => 'wwwww', 'x' => 'x', 'y' => 'Y', 'z' => 'Z', '_format' => 'xml', '_route' => 'test'], $matcher->match('/wwwwwxYZ.xml')); // As 'y' has custom requirement and can only be of value 'y|Y', it will leave 'ZZZ' to variable z. // So with carefully chosen requirements adjacent variables, can be useful. - $this->assertEquals(array('w' => 'wwwww', 'x' => 'x', 'y' => 'y', 'z' => 'ZZZ', '_format' => 'html', '_route' => 'test'), $matcher->match('/wwwwwxyZZZ')); + $this->assertEquals(['w' => 'wwwww', 'x' => 'x', 'y' => 'y', 'z' => 'ZZZ', '_format' => 'html', '_route' => 'test'], $matcher->match('/wwwwwxyZZZ')); // z and _format are optional. - $this->assertEquals(array('w' => 'wwwww', 'x' => 'x', 'y' => 'y', 'z' => 'default-z', '_format' => 'html', '_route' => 'test'), $matcher->match('/wwwwwxy')); + $this->assertEquals(['w' => 'wwwww', 'x' => 'x', 'y' => 'y', 'z' => 'default-z', '_format' => 'html', '_route' => 'test'], $matcher->match('/wwwwwxy')); - $this->{method_exists($this, $_ = 'expectException') ? $_ : 'setExpectedException'}('Symfony\Component\Routing\Exception\ResourceNotFoundException'); + $this->expectException('Symfony\Component\Routing\Exception\ResourceNotFoundException'); $matcher->match('/wxy.html'); } public function testOptionalVariableWithNoRealSeparator() { $coll = new RouteCollection(); - $coll->add('test', new Route('/get{what}', array('what' => 'All'))); - $matcher = new UrlMatcher($coll, new RequestContext()); + $coll->add('test', new Route('/get{what}', ['what' => 'All'])); + $matcher = $this->getUrlMatcher($coll); - $this->assertEquals(array('what' => 'All', '_route' => 'test'), $matcher->match('/get')); - $this->assertEquals(array('what' => 'Sites', '_route' => 'test'), $matcher->match('/getSites')); + $this->assertEquals(['what' => 'All', '_route' => 'test'], $matcher->match('/get')); + $this->assertEquals(['what' => 'Sites', '_route' => 'test'], $matcher->match('/getSites')); // Usually the character in front of an optional parameter can be left out, e.g. with pattern '/get/{what}' just '/get' would match. // But here the 't' in 'get' is not a separating character, so it makes no sense to match without it. - $this->{method_exists($this, $_ = 'expectException') ? $_ : 'setExpectedException'}('Symfony\Component\Routing\Exception\ResourceNotFoundException'); + $this->expectException('Symfony\Component\Routing\Exception\ResourceNotFoundException'); $matcher->match('/ge'); } @@ -275,65 +341,122 @@ class UrlMatcherTest extends TestCase { $coll = new RouteCollection(); $coll->add('test', new Route('/get{what}Suffix')); - $matcher = new UrlMatcher($coll, new RequestContext()); + $matcher = $this->getUrlMatcher($coll); - $this->assertEquals(array('what' => 'Sites', '_route' => 'test'), $matcher->match('/getSitesSuffix')); + $this->assertEquals(['what' => 'Sites', '_route' => 'test'], $matcher->match('/getSitesSuffix')); } public function testDefaultRequirementOfVariable() { $coll = new RouteCollection(); $coll->add('test', new Route('/{page}.{_format}')); - $matcher = new UrlMatcher($coll, new RequestContext()); + $matcher = $this->getUrlMatcher($coll); - $this->assertEquals(array('page' => 'index', '_format' => 'mobile.html', '_route' => 'test'), $matcher->match('/index.mobile.html')); + $this->assertEquals(['page' => 'index', '_format' => 'mobile.html', '_route' => 'test'], $matcher->match('/index.mobile.html')); } - /** - * @expectedException \Symfony\Component\Routing\Exception\ResourceNotFoundException - */ public function testDefaultRequirementOfVariableDisallowsSlash() { + $this->expectException('Symfony\Component\Routing\Exception\ResourceNotFoundException'); $coll = new RouteCollection(); $coll->add('test', new Route('/{page}.{_format}')); - $matcher = new UrlMatcher($coll, new RequestContext()); + $matcher = $this->getUrlMatcher($coll); $matcher->match('/index.sl/ash'); } - /** - * @expectedException \Symfony\Component\Routing\Exception\ResourceNotFoundException - */ public function testDefaultRequirementOfVariableDisallowsNextSeparator() { + $this->expectException('Symfony\Component\Routing\Exception\ResourceNotFoundException'); $coll = new RouteCollection(); - $coll->add('test', new Route('/{page}.{_format}', array(), array('_format' => 'html|xml'))); - $matcher = new UrlMatcher($coll, new RequestContext()); + $coll->add('test', new Route('/{page}.{_format}', [], ['_format' => 'html|xml'])); + $matcher = $this->getUrlMatcher($coll); $matcher->match('/do.t.html'); } - /** - * @expectedException \Symfony\Component\Routing\Exception\ResourceNotFoundException - */ + public function testMissingTrailingSlash() + { + $this->expectException('Symfony\Component\Routing\Exception\ResourceNotFoundException'); + $coll = new RouteCollection(); + $coll->add('foo', new Route('/foo/')); + + $matcher = $this->getUrlMatcher($coll); + $matcher->match('/foo'); + } + + public function testExtraTrailingSlash() + { + $this->getExpectedException() ?: $this->expectException('Symfony\Component\Routing\Exception\ResourceNotFoundException'); + $coll = new RouteCollection(); + $coll->add('foo', new Route('/foo')); + + $matcher = $this->getUrlMatcher($coll); + $matcher->match('/foo/'); + } + + public function testMissingTrailingSlashForNonSafeMethod() + { + $this->getExpectedException() ?: $this->expectException('Symfony\Component\Routing\Exception\ResourceNotFoundException'); + $coll = new RouteCollection(); + $coll->add('foo', new Route('/foo/')); + + $context = new RequestContext(); + $context->setMethod('POST'); + $matcher = $this->getUrlMatcher($coll, $context); + $matcher->match('/foo'); + } + + public function testExtraTrailingSlashForNonSafeMethod() + { + $this->getExpectedException() ?: $this->expectException('Symfony\Component\Routing\Exception\ResourceNotFoundException'); + $coll = new RouteCollection(); + $coll->add('foo', new Route('/foo')); + + $context = new RequestContext(); + $context->setMethod('POST'); + $matcher = $this->getUrlMatcher($coll, $context); + $matcher->match('/foo/'); + } + public function testSchemeRequirement() { + $this->getExpectedException() ?: $this->expectException('Symfony\Component\Routing\Exception\ResourceNotFoundException'); + $coll = new RouteCollection(); + $coll->add('foo', new Route('/foo', [], [], [], '', ['https'])); + $matcher = $this->getUrlMatcher($coll); + $matcher->match('/foo'); + } + + public function testSchemeRequirementForNonSafeMethod() + { + $this->getExpectedException() ?: $this->expectException('Symfony\Component\Routing\Exception\ResourceNotFoundException'); $coll = new RouteCollection(); - $coll->add('foo', new Route('/foo', array(), array(), array(), '', array('https'))); - $matcher = new UrlMatcher($coll, new RequestContext()); + $coll->add('foo', new Route('/foo', [], [], [], '', ['https'])); + + $context = new RequestContext(); + $context->setMethod('POST'); + $matcher = $this->getUrlMatcher($coll, $context); $matcher->match('/foo'); } - /** - * @expectedException \Symfony\Component\Routing\Exception\ResourceNotFoundException - */ + public function testSamePathWithDifferentScheme() + { + $coll = new RouteCollection(); + $coll->add('https_route', new Route('/', [], [], [], '', ['https'])); + $coll->add('http_route', new Route('/', [], [], [], '', ['http'])); + $matcher = $this->getUrlMatcher($coll); + $this->assertEquals(['_route' => 'http_route'], $matcher->match('/')); + } + public function testCondition() { + $this->expectException('Symfony\Component\Routing\Exception\ResourceNotFoundException'); $coll = new RouteCollection(); $route = new Route('/foo'); $route->setCondition('context.getMethod() == "POST"'); $coll->add('foo', $route); - $matcher = new UrlMatcher($coll, new RequestContext()); + $matcher = $this->getUrlMatcher($coll); $matcher->match('/foo'); } @@ -341,10 +464,13 @@ class UrlMatcherTest extends TestCase { $coll = new RouteCollection(); $route = new Route('/foo/{bar}'); + $route->setCondition('request.getBaseUrl() == "/bar"'); + $coll->add('bar', $route); + $route = new Route('/foo/{bar}'); $route->setCondition('request.getBaseUrl() == "/sub/front.php" and request.getPathInfo() == "/foo/bar"'); $coll->add('foo', $route); - $matcher = new UrlMatcher($coll, new RequestContext('/sub/front.php')); - $this->assertEquals(array('bar' => 'bar', '_route' => 'foo'), $matcher->match('/foo/bar')); + $matcher = $this->getUrlMatcher($coll, new RequestContext('/sub/front.php')); + $this->assertEquals(['bar' => 'bar', '_route' => 'foo'], $matcher->match('/foo/bar')); } public function testDecodeOnce() @@ -352,8 +478,8 @@ class UrlMatcherTest extends TestCase $coll = new RouteCollection(); $coll->add('foo', new Route('/foo/{foo}')); - $matcher = new UrlMatcher($coll, new RequestContext()); - $this->assertEquals(array('foo' => 'bar%23', '_route' => 'foo'), $matcher->match('/foo/bar%2523')); + $matcher = $this->getUrlMatcher($coll); + $this->assertEquals(['foo' => 'bar%23', '_route' => 'foo'], $matcher->match('/foo/bar%2523')); } public function testCannotRelyOnPrefix() @@ -368,74 +494,454 @@ class UrlMatcherTest extends TestCase $coll->addCollection($subColl); - $matcher = new UrlMatcher($coll, new RequestContext()); - $this->assertEquals(array('_route' => 'bar'), $matcher->match('/new')); + $matcher = $this->getUrlMatcher($coll); + $this->assertEquals(['_route' => 'bar'], $matcher->match('/new')); } public function testWithHost() { $coll = new RouteCollection(); - $coll->add('foo', new Route('/foo/{foo}', array(), array(), array(), '{locale}.example.com')); + $coll->add('foo', new Route('/foo/{foo}', [], [], [], '{locale}.example.com')); - $matcher = new UrlMatcher($coll, new RequestContext('', 'GET', 'en.example.com')); - $this->assertEquals(array('foo' => 'bar', '_route' => 'foo', 'locale' => 'en'), $matcher->match('/foo/bar')); + $matcher = $this->getUrlMatcher($coll, new RequestContext('', 'GET', 'en.example.com')); + $this->assertEquals(['foo' => 'bar', '_route' => 'foo', 'locale' => 'en'], $matcher->match('/foo/bar')); } public function testWithHostOnRouteCollection() { $coll = new RouteCollection(); $coll->add('foo', new Route('/foo/{foo}')); - $coll->add('bar', new Route('/bar/{foo}', array(), array(), array(), '{locale}.example.net')); + $coll->add('bar', new Route('/bar/{foo}', [], [], [], '{locale}.example.net')); $coll->setHost('{locale}.example.com'); - $matcher = new UrlMatcher($coll, new RequestContext('', 'GET', 'en.example.com')); - $this->assertEquals(array('foo' => 'bar', '_route' => 'foo', 'locale' => 'en'), $matcher->match('/foo/bar')); + $matcher = $this->getUrlMatcher($coll, new RequestContext('', 'GET', 'en.example.com')); + $this->assertEquals(['foo' => 'bar', '_route' => 'foo', 'locale' => 'en'], $matcher->match('/foo/bar')); + + $matcher = $this->getUrlMatcher($coll, new RequestContext('', 'GET', 'en.example.com')); + $this->assertEquals(['foo' => 'bar', '_route' => 'bar', 'locale' => 'en'], $matcher->match('/bar/bar')); + } + + public function testVariationInTrailingSlashWithHosts() + { + $coll = new RouteCollection(); + $coll->add('foo', new Route('/foo/', [], [], [], 'foo.example.com')); + $coll->add('bar', new Route('/foo', [], [], [], 'bar.example.com')); + + $matcher = $this->getUrlMatcher($coll, new RequestContext('', 'GET', 'foo.example.com')); + $this->assertEquals(['_route' => 'foo'], $matcher->match('/foo/')); + + $matcher = $this->getUrlMatcher($coll, new RequestContext('', 'GET', 'bar.example.com')); + $this->assertEquals(['_route' => 'bar'], $matcher->match('/foo')); + } + + public function testVariationInTrailingSlashWithHostsInReverse() + { + // The order should not matter + $coll = new RouteCollection(); + $coll->add('bar', new Route('/foo', [], [], [], 'bar.example.com')); + $coll->add('foo', new Route('/foo/', [], [], [], 'foo.example.com')); + + $matcher = $this->getUrlMatcher($coll, new RequestContext('', 'GET', 'foo.example.com')); + $this->assertEquals(['_route' => 'foo'], $matcher->match('/foo/')); + + $matcher = $this->getUrlMatcher($coll, new RequestContext('', 'GET', 'bar.example.com')); + $this->assertEquals(['_route' => 'bar'], $matcher->match('/foo')); + } + + public function testVariationInTrailingSlashWithHostsAndVariable() + { + $coll = new RouteCollection(); + $coll->add('foo', new Route('/{foo}/', [], [], [], 'foo.example.com')); + $coll->add('bar', new Route('/{foo}', [], [], [], 'bar.example.com')); + + $matcher = $this->getUrlMatcher($coll, new RequestContext('', 'GET', 'foo.example.com')); + $this->assertEquals(['foo' => 'bar', '_route' => 'foo'], $matcher->match('/bar/')); + + $matcher = $this->getUrlMatcher($coll, new RequestContext('', 'GET', 'bar.example.com')); + $this->assertEquals(['foo' => 'bar', '_route' => 'bar'], $matcher->match('/bar')); + } + + public function testVariationInTrailingSlashWithHostsAndVariableInReverse() + { + // The order should not matter + $coll = new RouteCollection(); + $coll->add('bar', new Route('/{foo}', [], [], [], 'bar.example.com')); + $coll->add('foo', new Route('/{foo}/', [], [], [], 'foo.example.com')); + + $matcher = $this->getUrlMatcher($coll, new RequestContext('', 'GET', 'foo.example.com')); + $this->assertEquals(['foo' => 'bar', '_route' => 'foo'], $matcher->match('/bar/')); + + $matcher = $this->getUrlMatcher($coll, new RequestContext('', 'GET', 'bar.example.com')); + $this->assertEquals(['foo' => 'bar', '_route' => 'bar'], $matcher->match('/bar')); + } + + public function testVariationInTrailingSlashWithMethods() + { + $coll = new RouteCollection(); + $coll->add('foo', new Route('/foo/', [], [], [], '', [], ['POST'])); + $coll->add('bar', new Route('/foo', [], [], [], '', [], ['GET'])); + + $matcher = $this->getUrlMatcher($coll, new RequestContext('', 'POST')); + $this->assertEquals(['_route' => 'foo'], $matcher->match('/foo/')); + + $matcher = $this->getUrlMatcher($coll, new RequestContext('', 'GET')); + $this->assertEquals(['_route' => 'bar'], $matcher->match('/foo')); + } + + public function testVariationInTrailingSlashWithMethodsInReverse() + { + // The order should not matter + $coll = new RouteCollection(); + $coll->add('bar', new Route('/foo', [], [], [], '', [], ['GET'])); + $coll->add('foo', new Route('/foo/', [], [], [], '', [], ['POST'])); + + $matcher = $this->getUrlMatcher($coll, new RequestContext('', 'POST')); + $this->assertEquals(['_route' => 'foo'], $matcher->match('/foo/')); + + $matcher = $this->getUrlMatcher($coll, new RequestContext('', 'GET')); + $this->assertEquals(['_route' => 'bar'], $matcher->match('/foo')); + } + + public function testVariableVariationInTrailingSlashWithMethods() + { + $coll = new RouteCollection(); + $coll->add('foo', new Route('/{foo}/', [], [], [], '', [], ['POST'])); + $coll->add('bar', new Route('/{foo}', [], [], [], '', [], ['GET'])); + + $matcher = $this->getUrlMatcher($coll, new RequestContext('', 'POST')); + $this->assertEquals(['foo' => 'bar', '_route' => 'foo'], $matcher->match('/bar/')); + + $matcher = $this->getUrlMatcher($coll, new RequestContext('', 'GET')); + $this->assertEquals(['foo' => 'bar', '_route' => 'bar'], $matcher->match('/bar')); + } + + public function testVariableVariationInTrailingSlashWithMethodsInReverse() + { + // The order should not matter + $coll = new RouteCollection(); + $coll->add('bar', new Route('/{foo}', [], [], [], '', [], ['GET'])); + $coll->add('foo', new Route('/{foo}/', [], [], [], '', [], ['POST'])); + + $matcher = $this->getUrlMatcher($coll, new RequestContext('', 'POST')); + $this->assertEquals(['foo' => 'bar', '_route' => 'foo'], $matcher->match('/bar/')); + + $matcher = $this->getUrlMatcher($coll, new RequestContext('', 'GET')); + $this->assertEquals(['foo' => 'bar', '_route' => 'bar'], $matcher->match('/bar')); + } + + public function testMixOfStaticAndVariableVariationInTrailingSlashWithHosts() + { + $coll = new RouteCollection(); + $coll->add('foo', new Route('/foo/', [], [], [], 'foo.example.com')); + $coll->add('bar', new Route('/{foo}', [], [], [], 'bar.example.com')); + + $matcher = $this->getUrlMatcher($coll, new RequestContext('', 'GET', 'foo.example.com')); + $this->assertEquals(['_route' => 'foo'], $matcher->match('/foo/')); + + $matcher = $this->getUrlMatcher($coll, new RequestContext('', 'GET', 'bar.example.com')); + $this->assertEquals(['foo' => 'bar', '_route' => 'bar'], $matcher->match('/bar')); + } + + public function testMixOfStaticAndVariableVariationInTrailingSlashWithMethods() + { + $coll = new RouteCollection(); + $coll->add('foo', new Route('/foo/', [], [], [], '', [], ['POST'])); + $coll->add('bar', new Route('/{foo}', [], [], [], '', [], ['GET'])); - $matcher = new UrlMatcher($coll, new RequestContext('', 'GET', 'en.example.com')); - $this->assertEquals(array('foo' => 'bar', '_route' => 'bar', 'locale' => 'en'), $matcher->match('/bar/bar')); + $matcher = $this->getUrlMatcher($coll, new RequestContext('', 'POST')); + $this->assertEquals(['_route' => 'foo'], $matcher->match('/foo/')); + + $matcher = $this->getUrlMatcher($coll, new RequestContext('', 'GET')); + $this->assertEquals(['foo' => 'bar', '_route' => 'bar'], $matcher->match('/bar')); + $this->assertEquals(['foo' => 'foo', '_route' => 'bar'], $matcher->match('/foo')); } - /** - * @expectedException \Symfony\Component\Routing\Exception\ResourceNotFoundException - */ public function testWithOutHostHostDoesNotMatch() { + $this->expectException('Symfony\Component\Routing\Exception\ResourceNotFoundException'); $coll = new RouteCollection(); - $coll->add('foo', new Route('/foo/{foo}', array(), array(), array(), '{locale}.example.com')); + $coll->add('foo', new Route('/foo/{foo}', [], [], [], '{locale}.example.com')); - $matcher = new UrlMatcher($coll, new RequestContext('', 'GET', 'example.com')); + $matcher = $this->getUrlMatcher($coll, new RequestContext('', 'GET', 'example.com')); $matcher->match('/foo/bar'); } - /** - * @expectedException \Symfony\Component\Routing\Exception\ResourceNotFoundException - */ public function testPathIsCaseSensitive() { + $this->expectException('Symfony\Component\Routing\Exception\ResourceNotFoundException'); $coll = new RouteCollection(); - $coll->add('foo', new Route('/locale', array(), array('locale' => 'EN|FR|DE'))); + $coll->add('foo', new Route('/locale', [], ['locale' => 'EN|FR|DE'])); - $matcher = new UrlMatcher($coll, new RequestContext()); + $matcher = $this->getUrlMatcher($coll); $matcher->match('/en'); } public function testHostIsCaseInsensitive() { $coll = new RouteCollection(); - $coll->add('foo', new Route('/', array(), array('locale' => 'EN|FR|DE'), array(), '{locale}.example.com')); + $coll->add('foo', new Route('/', [], ['locale' => 'EN|FR|DE'], [], '{locale}.example.com')); - $matcher = new UrlMatcher($coll, new RequestContext('', 'GET', 'en.example.com')); - $this->assertEquals(array('_route' => 'foo', 'locale' => 'en'), $matcher->match('/')); + $matcher = $this->getUrlMatcher($coll, new RequestContext('', 'GET', 'en.example.com')); + $this->assertEquals(['_route' => 'foo', 'locale' => 'en'], $matcher->match('/')); } - /** - * @expectedException \Symfony\Component\Routing\Exception\NoConfigurationException - */ public function testNoConfiguration() { + $this->expectException('Symfony\Component\Routing\Exception\NoConfigurationException'); + $coll = new RouteCollection(); + + $matcher = $this->getUrlMatcher($coll); + $matcher->match('/'); + } + + public function testNestedCollections() + { + $coll = new RouteCollection(); + + $subColl = new RouteCollection(); + $subColl->add('a', new Route('/a')); + $subColl->add('b', new Route('/b')); + $subColl->add('c', new Route('/c')); + $subColl->addPrefix('/p'); + $coll->addCollection($subColl); + + $coll->add('baz', new Route('/{baz}')); + + $subColl = new RouteCollection(); + $subColl->add('buz', new Route('/buz')); + $subColl->addPrefix('/prefix'); + $coll->addCollection($subColl); + + $matcher = $this->getUrlMatcher($coll); + $this->assertEquals(['_route' => 'a'], $matcher->match('/p/a')); + $this->assertEquals(['_route' => 'baz', 'baz' => 'p'], $matcher->match('/p')); + $this->assertEquals(['_route' => 'buz'], $matcher->match('/prefix/buz')); + } + + public function testSchemeAndMethodMismatch() + { + $this->expectException('Symfony\Component\Routing\Exception\ResourceNotFoundException'); + $this->expectExceptionMessage('No routes found for "/".'); $coll = new RouteCollection(); + $coll->add('foo', new Route('/', [], [], [], null, ['https'], ['POST'])); - $matcher = new UrlMatcher($coll, new RequestContext()); + $matcher = $this->getUrlMatcher($coll); $matcher->match('/'); } + + public function testSiblingRoutes() + { + $coll = new RouteCollection(); + $coll->add('a', (new Route('/a{a}'))->setMethods('POST')); + $coll->add('b', (new Route('/a{a}'))->setMethods('PUT')); + $coll->add('c', new Route('/a{a}')); + $coll->add('d', (new Route('/b{a}'))->setCondition('false')); + $coll->add('e', (new Route('/{b}{a}'))->setCondition('false')); + $coll->add('f', (new Route('/{b}{a}'))->setRequirements(['b' => 'b'])); + + $matcher = $this->getUrlMatcher($coll); + $this->assertEquals(['_route' => 'c', 'a' => 'a'], $matcher->match('/aa')); + $this->assertEquals(['_route' => 'f', 'b' => 'b', 'a' => 'a'], $matcher->match('/ba')); + } + + public function testUnicodeRoute() + { + $coll = new RouteCollection(); + $coll->add('a', new Route('/{a}', [], ['a' => '.'], ['utf8' => false])); + $coll->add('b', new Route('/{a}', [], ['a' => '.'], ['utf8' => true])); + + $matcher = $this->getUrlMatcher($coll); + $this->assertEquals(['_route' => 'b', 'a' => 'é'], $matcher->match('/é')); + } + + public function testRequirementWithCapturingGroup() + { + $coll = new RouteCollection(); + $coll->add('a', new Route('/{a}/{b}', [], ['a' => '(a|b)'])); + + $matcher = $this->getUrlMatcher($coll); + $this->assertEquals(['_route' => 'a', 'a' => 'a', 'b' => 'b'], $matcher->match('/a/b')); + } + + public function testDotAllWithCatchAll() + { + $coll = new RouteCollection(); + $coll->add('a', new Route('/{id}.html', [], ['id' => '.+'])); + $coll->add('b', new Route('/{all}', [], ['all' => '.+'])); + + $matcher = $this->getUrlMatcher($coll); + $this->assertEquals(['_route' => 'a', 'id' => 'foo/bar'], $matcher->match('/foo/bar.html')); + } + + public function testHostPattern() + { + $coll = new RouteCollection(); + $coll->add('a', new Route('/{app}/{action}/{unused}', [], [], [], '{host}')); + + $expected = [ + '_route' => 'a', + 'app' => 'an_app', + 'action' => 'an_action', + 'unused' => 'unused', + 'host' => 'foo', + ]; + $matcher = $this->getUrlMatcher($coll, new RequestContext('', 'GET', 'foo')); + $this->assertEquals($expected, $matcher->match('/an_app/an_action/unused')); + } + + public function testUtf8Prefix() + { + $coll = new RouteCollection(); + $coll->add('a', new Route('/é{foo}', [], [], ['utf8' => true])); + $coll->add('b', new Route('/è{bar}', [], [], ['utf8' => true])); + + $matcher = $this->getUrlMatcher($coll); + $this->assertEquals('a', $matcher->match('/éo')['_route']); + } + + public function testUtf8AndMethodMatching() + { + $coll = new RouteCollection(); + $coll->add('a', new Route('/admin/api/list/{shortClassName}/{id}.{_format}', [], [], ['utf8' => true], '', [], ['PUT'])); + $coll->add('b', new Route('/admin/api/package.{_format}', [], [], [], '', [], ['POST'])); + $coll->add('c', new Route('/admin/api/package.{_format}', ['_format' => 'json'], [], [], '', [], ['GET'])); + + $matcher = $this->getUrlMatcher($coll); + $this->assertEquals('c', $matcher->match('/admin/api/package.json')['_route']); + } + + public function testHostWithDot() + { + $coll = new RouteCollection(); + $coll->add('a', new Route('/foo', [], [], [], 'foo.example.com')); + $coll->add('b', new Route('/bar/{baz}')); + + $matcher = $this->getUrlMatcher($coll); + $this->assertEquals('b', $matcher->match('/bar/abc.123')['_route']); + } + + public function testSlashVariant() + { + $coll = new RouteCollection(); + $coll->add('a', new Route('/foo/{bar}', [], ['bar' => '.*'])); + + $matcher = $this->getUrlMatcher($coll); + $this->assertEquals('a', $matcher->match('/foo/')['_route']); + } + + public function testSlashVariant2() + { + $coll = new RouteCollection(); + $coll->add('a', new Route('/foo/{bar}/', [], ['bar' => '.*'])); + + $matcher = $this->getUrlMatcher($coll); + $this->assertEquals(['_route' => 'a', 'bar' => 'bar'], $matcher->match('/foo/bar/')); + } + + public function testSlashWithVerb() + { + $coll = new RouteCollection(); + $coll->add('a', new Route('/{foo}', [], [], [], '', [], ['put', 'delete'])); + $coll->add('b', new Route('/bar/')); + + $matcher = $this->getUrlMatcher($coll); + $this->assertSame(['_route' => 'b'], $matcher->match('/bar/')); + + $coll = new RouteCollection(); + $coll->add('a', new Route('/dav/{foo}', [], ['foo' => '.*'], [], '', [], ['GET', 'OPTIONS'])); + + $matcher = $this->getUrlMatcher($coll, new RequestContext('', 'OPTIONS')); + $expected = [ + '_route' => 'a', + 'foo' => 'files/bar/', + ]; + $this->assertEquals($expected, $matcher->match('/dav/files/bar/')); + } + + public function testSlashAndVerbPrecedence() + { + $coll = new RouteCollection(); + $coll->add('a', new Route('/api/customers/{customerId}/contactpersons/', [], [], [], '', [], ['post'])); + $coll->add('b', new Route('/api/customers/{customerId}/contactpersons', [], [], [], '', [], ['get'])); + + $matcher = $this->getUrlMatcher($coll); + $expected = [ + '_route' => 'b', + 'customerId' => '123', + ]; + $this->assertEquals($expected, $matcher->match('/api/customers/123/contactpersons')); + + $coll = new RouteCollection(); + $coll->add('a', new Route('/api/customers/{customerId}/contactpersons/', [], [], [], '', [], ['get'])); + $coll->add('b', new Route('/api/customers/{customerId}/contactpersons', [], [], [], '', [], ['post'])); + + $matcher = $this->getUrlMatcher($coll, new RequestContext('', 'POST')); + $expected = [ + '_route' => 'b', + 'customerId' => '123', + ]; + $this->assertEquals($expected, $matcher->match('/api/customers/123/contactpersons')); + } + + public function testGreedyTrailingRequirement() + { + $coll = new RouteCollection(); + $coll->add('a', new Route('/{a}', [], ['a' => '.+'])); + + $matcher = $this->getUrlMatcher($coll); + + $this->assertEquals(['_route' => 'a', 'a' => 'foo'], $matcher->match('/foo')); + $this->assertEquals(['_route' => 'a', 'a' => 'foo/'], $matcher->match('/foo/')); + } + + public function testTrailingRequirementWithDefault() + { + $coll = new RouteCollection(); + $coll->add('a', new Route('/fr-fr/{a}', ['a' => 'aaa'], ['a' => '.+'])); + $coll->add('b', new Route('/en-en/{b}', ['b' => 'bbb'], ['b' => '.*'])); + + $matcher = $this->getUrlMatcher($coll); + + $this->assertEquals(['_route' => 'a', 'a' => 'aaa'], $matcher->match('/fr-fr')); + $this->assertEquals(['_route' => 'a', 'a' => 'AAA'], $matcher->match('/fr-fr/AAA')); + $this->assertEquals(['_route' => 'b', 'b' => 'bbb'], $matcher->match('/en-en')); + $this->assertEquals(['_route' => 'b', 'b' => 'BBB'], $matcher->match('/en-en/BBB')); + } + + public function testTrailingRequirementWithDefault_A() + { + $coll = new RouteCollection(); + $coll->add('a', new Route('/fr-fr/{a}', ['a' => 'aaa'], ['a' => '.+'])); + + $matcher = $this->getUrlMatcher($coll); + + $this->expectException(ResourceNotFoundException::class); + $matcher->match('/fr-fr/'); + } + + public function testTrailingRequirementWithDefault_B() + { + $coll = new RouteCollection(); + $coll->add('b', new Route('/en-en/{b}', ['b' => 'bbb'], ['b' => '.*'])); + + $matcher = $this->getUrlMatcher($coll); + + $this->assertEquals(['_route' => 'b', 'b' => ''], $matcher->match('/en-en/')); + } + + public function testRestrictiveTrailingRequirementWithStaticRouteAfter() + { + $coll = new RouteCollection(); + $coll->add('a', new Route('/hello{_}', [], ['_' => '/(?!/)'])); + $coll->add('b', new Route('/hello')); + + $matcher = $this->getUrlMatcher($coll); + + $this->assertEquals(['_route' => 'a', '_' => '/'], $matcher->match('/hello/')); + } + + protected function getUrlMatcher(RouteCollection $routes, RequestContext $context = null) + { + return new UrlMatcher($routes, $context ?: new RequestContext()); + } } diff --git a/vendor/symfony/routing/Tests/RequestContextTest.php b/vendor/symfony/routing/Tests/RequestContextTest.php index ffe29d1a747c9fdad60e741e14553f2774003a33..3d23b0e8947a2e07cd52daad4e9b43e95477f662 100644 --- a/vendor/symfony/routing/Tests/RequestContextTest.php +++ b/vendor/symfony/routing/Tests/RequestContextTest.php @@ -68,16 +68,16 @@ class RequestContextTest extends TestCase public function testGetParameters() { $requestContext = new RequestContext(); - $this->assertEquals(array(), $requestContext->getParameters()); + $this->assertEquals([], $requestContext->getParameters()); - $requestContext->setParameters(array('foo' => 'bar')); - $this->assertEquals(array('foo' => 'bar'), $requestContext->getParameters()); + $requestContext->setParameters(['foo' => 'bar']); + $this->assertEquals(['foo' => 'bar'], $requestContext->getParameters()); } public function testHasParameter() { $requestContext = new RequestContext(); - $requestContext->setParameters(array('foo' => 'bar')); + $requestContext->setParameters(['foo' => 'bar']); $this->assertTrue($requestContext->hasParameter('foo')); $this->assertFalse($requestContext->hasParameter('baz')); @@ -86,7 +86,7 @@ class RequestContextTest extends TestCase public function testGetParameter() { $requestContext = new RequestContext(); - $requestContext->setParameters(array('foo' => 'bar')); + $requestContext->setParameters(['foo' => 'bar']); $this->assertEquals('bar', $requestContext->getParameter('foo')); $this->assertNull($requestContext->getParameter('baz')); @@ -154,7 +154,7 @@ class RequestContextTest extends TestCase $this->assertSame($requestContext, $requestContext->setQueryString('foo=bar')); $this->assertSame($requestContext, $requestContext->setHttpPort(80)); $this->assertSame($requestContext, $requestContext->setHttpsPort(443)); - $this->assertSame($requestContext, $requestContext->setParameters(array())); + $this->assertSame($requestContext, $requestContext->setParameters([])); $this->assertSame($requestContext, $requestContext->setParameter('foo', 'bar')); } } diff --git a/vendor/symfony/routing/Tests/RouteCollectionBuilderTest.php b/vendor/symfony/routing/Tests/RouteCollectionBuilderTest.php index f6af600bd4221927e42d02281bc981cecc5c299b..f5042749e2ebb9255031cd88dd25c1516f2d4f7e 100644 --- a/vendor/symfony/routing/Tests/RouteCollectionBuilderTest.php +++ b/vendor/symfony/routing/Tests/RouteCollectionBuilderTest.php @@ -28,7 +28,7 @@ class RouteCollectionBuilderTest extends TestCase $resolver->expects($this->once()) ->method('resolve') ->with('admin_routing.yml', 'yaml') - ->will($this->returnValue($resolvedLoader)); + ->willReturn($resolvedLoader); $originalRoute = new Route('/foo/path'); $expectedCollection = new RouteCollection(); @@ -39,12 +39,12 @@ class RouteCollectionBuilderTest extends TestCase ->expects($this->once()) ->method('load') ->with('admin_routing.yml', 'yaml') - ->will($this->returnValue($expectedCollection)); + ->willReturn($expectedCollection); $loader = $this->getMockBuilder('Symfony\Component\Config\Loader\LoaderInterface')->getMock(); $loader->expects($this->any()) ->method('getResolver') - ->will($this->returnValue($resolver)); + ->willReturn($resolver); // import the file! $routes = new RouteCollectionBuilder($loader); @@ -68,18 +68,16 @@ class RouteCollectionBuilderTest extends TestCase public function testImportAddResources() { - $routeCollectionBuilder = new RouteCollectionBuilder(new YamlFileLoader(new FileLocator(array(__DIR__.'/Fixtures/')))); + $routeCollectionBuilder = new RouteCollectionBuilder(new YamlFileLoader(new FileLocator([__DIR__.'/Fixtures/']))); $routeCollectionBuilder->import('file_resource.yml'); $routeCollection = $routeCollectionBuilder->build(); $this->assertCount(1, $routeCollection->getResources()); } - /** - * @expectedException \BadMethodCallException - */ public function testImportWithoutLoaderThrowsException() { + $this->expectException('BadMethodCallException'); $collectionBuilder = new RouteCollectionBuilder(); $collectionBuilder->import('routing.yml'); } @@ -107,11 +105,11 @@ class RouteCollectionBuilderTest extends TestCase // make this loader able to do the import - keeps mocking simple $loader->expects($this->any()) ->method('supports') - ->will($this->returnValue(true)); + ->willReturn(true); $loader ->expects($this->once()) ->method('load') - ->will($this->returnValue($importedCollection)); + ->willReturn($importedCollection); $routes = new RouteCollectionBuilder($loader); @@ -131,13 +129,13 @@ class RouteCollectionBuilderTest extends TestCase $this->assertCount(5, $actualCollection); $actualRouteNames = array_keys($actualCollection->all()); - $this->assertEquals(array( + $this->assertEquals([ 'checkout_route', 'imported_route1', 'imported_route2', 'homepage', 'admin_dashboard', - ), $actualRouteNames); + ], $actualRouteNames); // make sure the defaults were set $checkoutRoute = $actualCollection->get('checkout_route'); @@ -154,18 +152,18 @@ class RouteCollectionBuilderTest extends TestCase $collectionBuilder->add('/admin', 'AppBundle:Admin:dashboard', 'admin_dashboard'); // add an unnamed route $collectionBuilder->add('/blogs', 'AppBundle:Blog:list') - ->setMethods(array('GET')); + ->setMethods(['GET']); // integer route names are allowed - they don't confuse things $collectionBuilder->add('/products', 'AppBundle:Product:list', 100); $actualCollection = $collectionBuilder->build(); $actualRouteNames = array_keys($actualCollection->all()); - $this->assertEquals(array( + $this->assertEquals([ 'admin_dashboard', 'GET_blogs', '100', - ), $actualRouteNames); + ], $actualRouteNames); } public function testFlushSetsDetailsOnChildrenRoutes() @@ -183,8 +181,8 @@ class RouteCollectionBuilderTest extends TestCase ->setOption('fooBar', true) ->setHost('example.com') ->setCondition('request.isSecure()') - ->setSchemes(array('https')) - ->setMethods(array('POST')); + ->setSchemes(['https']) + ->setMethods(['POST']); // a simple route, nothing added to it $routes->add('/blogs/{id}', 'editAction', 'blog_edit'); @@ -201,8 +199,8 @@ class RouteCollectionBuilderTest extends TestCase ->setDefault('_locale', 'fr') ->setRequirement('_locale', 'fr|en') ->setOption('niceRoute', true) - ->setSchemes(array('http')) - ->setMethods(array('GET', 'POST')); + ->setSchemes(['http']) + ->setMethods(['GET', 'POST']); $collection = $routes->build(); $actualListRoute = $collection->get('blog_list'); @@ -216,8 +214,8 @@ class RouteCollectionBuilderTest extends TestCase $this->assertTrue($actualListRoute->getOption('fooBar')); $this->assertEquals('example.com', $actualListRoute->getHost()); $this->assertEquals('request.isSecure()', $actualListRoute->getCondition()); - $this->assertEquals(array('https'), $actualListRoute->getSchemes()); - $this->assertEquals(array('POST'), $actualListRoute->getMethods()); + $this->assertEquals(['https'], $actualListRoute->getSchemes()); + $this->assertEquals(['POST'], $actualListRoute->getMethods()); // inherited from the main collection $this->assertEquals('fr', $actualListRoute->getDefault('_locale')); $this->assertEquals('fr|en', $actualListRoute->getRequirement('_locale')); @@ -227,8 +225,8 @@ class RouteCollectionBuilderTest extends TestCase // inherited from the collection $this->assertEquals('symfony.com', $actualEditRoute->getHost()); $this->assertEquals('request.query.get("page")==1', $actualEditRoute->getCondition()); - $this->assertEquals(array('http'), $actualEditRoute->getSchemes()); - $this->assertEquals(array('GET', 'POST'), $actualEditRoute->getMethods()); + $this->assertEquals(['http'], $actualEditRoute->getSchemes()); + $this->assertEquals(['GET', 'POST'], $actualEditRoute->getMethods()); } /** @@ -250,16 +248,16 @@ class RouteCollectionBuilderTest extends TestCase public function providePrefixTests() { - $tests = array(); + $tests = []; // empty prefix is of course ok - $tests[] = array('', '/foo', '/foo'); + $tests[] = ['', '/foo', '/foo']; // normal prefix - does not matter if it's a wildcard - $tests[] = array('/{admin}', '/foo', '/{admin}/foo'); + $tests[] = ['/{admin}', '/foo', '/{admin}/foo']; // shows that a prefix will always be given the starting slash - $tests[] = array('0', '/foo', '/0/foo'); + $tests[] = ['0', '/foo', '/0/foo']; // spaces are ok, and double slahses at the end are cleaned - $tests[] = array('/ /', '/foo', '/ /foo'); + $tests[] = ['/ /', '/foo', '/ /foo']; return $tests; } @@ -296,11 +294,11 @@ class RouteCollectionBuilderTest extends TestCase // make this loader able to do the import - keeps mocking simple $loader->expects($this->any()) ->method('supports') - ->will($this->returnValue(true)); + ->willReturn(true); $loader ->expects($this->any()) ->method('load') - ->will($this->returnValue($importedCollection)); + ->willReturn($importedCollection); // import this from the /admin route builder $adminRoutes->import('admin.yml', '/imported'); @@ -323,10 +321,10 @@ class RouteCollectionBuilderTest extends TestCase $accountRoutes = $routes->createBuilder(); // route 2 $accountRoutes->add('/dashboard', '') - ->setMethods(array('GET')); + ->setMethods(['GET']); // route 3 $accountRoutes->add('/dashboard', '') - ->setMethods(array('POST')); + ->setMethods(['POST']); $routes->mount('/admin', $adminRoutes); $routes->mount('/account', $accountRoutes); @@ -347,17 +345,17 @@ class RouteCollectionBuilderTest extends TestCase $loader = $this->getMockBuilder('Symfony\Component\Config\Loader\LoaderInterface')->getMock(); $loader->expects($this->any()) ->method('supports') - ->will($this->returnValue(true)); + ->willReturn(true); $loader ->expects($this->any()) ->method('load') - ->will($this->returnValue(array($firstCollection, $secondCollection))); + ->willReturn([$firstCollection, $secondCollection]); $routeCollectionBuilder = new RouteCollectionBuilder($loader); $routeCollectionBuilder->import('/directory/recurse/*', '/other/', 'glob'); $routes = $routeCollectionBuilder->build()->all(); - $this->assertEquals(2, count($routes)); + $this->assertCount(2, $routes); $this->assertEquals('/other/a', $routes['a']->getPath()); $this->assertEquals('/other/b', $routes['b']->getPath()); } diff --git a/vendor/symfony/routing/Tests/RouteCollectionTest.php b/vendor/symfony/routing/Tests/RouteCollectionTest.php index 83457ff14a7bfee791a243e612f5778abe9961a7..f310d4e5269e1fa1750ce33e47a8f3b1f697d8ac 100644 --- a/vendor/symfony/routing/Tests/RouteCollectionTest.php +++ b/vendor/symfony/routing/Tests/RouteCollectionTest.php @@ -12,9 +12,9 @@ namespace Symfony\Component\Routing\Tests; use PHPUnit\Framework\TestCase; -use Symfony\Component\Routing\RouteCollection; -use Symfony\Component\Routing\Route; use Symfony\Component\Config\Resource\FileResource; +use Symfony\Component\Routing\Route; +use Symfony\Component\Routing\RouteCollection; class RouteCollectionTest extends TestCase { @@ -23,7 +23,7 @@ class RouteCollectionTest extends TestCase $collection = new RouteCollection(); $route = new Route('/foo'); $collection->add('foo', $route); - $this->assertEquals(array('foo' => $route), $collection->all(), '->add() adds a route'); + $this->assertEquals(['foo' => $route], $collection->all(), '->add() adds a route'); $this->assertEquals($route, $collection->get('foo'), '->get() returns a route by name'); $this->assertNull($collection->get('bar'), '->get() returns null if a route does not exist'); } @@ -67,7 +67,7 @@ class RouteCollectionTest extends TestCase $collection->add('last', $last = new Route('/last')); $this->assertInstanceOf('\ArrayIterator', $collection->getIterator()); - $this->assertSame(array('bar' => $bar, 'foo' => $foo, 'last' => $last), $collection->getIterator()->getArrayCopy()); + $this->assertSame(['bar' => $bar, 'foo' => $foo, 'last' => $last], $collection->getIterator()->getArrayCopy()); } public function testCount() @@ -98,7 +98,7 @@ class RouteCollectionTest extends TestCase $collection->addCollection($collection1); $collection->add('last', $last = new Route('/last')); - $this->assertSame(array('bar' => $bar, 'foo' => $foo, 'grandchild' => $grandchild, 'last' => $last), $collection->all(), + $this->assertSame(['bar' => $bar, 'foo' => $foo, 'grandchild' => $grandchild, 'last' => $last], $collection->all(), '->addCollection() imports routes of another collection, overrides if necessary and adds them at the end'); } @@ -109,7 +109,7 @@ class RouteCollectionTest extends TestCase $collection1 = new RouteCollection(); $collection1->addResource($foo1 = new FileResource(__DIR__.'/Fixtures/foo1.xml')); $collection->addCollection($collection1); - $this->assertEquals(array($foo, $foo1), $collection->getResources(), '->addCollection() merges resources'); + $this->assertEquals([$foo, $foo1], $collection->getResources(), '->addCollection() merges resources'); } public function testAddDefaultsAndRequirementsAndOptions() @@ -118,23 +118,23 @@ class RouteCollectionTest extends TestCase $collection->add('foo', new Route('/{placeholder}')); $collection1 = new RouteCollection(); $collection1->add('bar', new Route('/{placeholder}', - array('_controller' => 'fixed', 'placeholder' => 'default'), array('placeholder' => '.+'), array('option' => 'value')) + ['_controller' => 'fixed', 'placeholder' => 'default'], ['placeholder' => '.+'], ['option' => 'value']) ); $collection->addCollection($collection1); - $collection->addDefaults(array('placeholder' => 'new-default')); - $this->assertEquals(array('placeholder' => 'new-default'), $collection->get('foo')->getDefaults(), '->addDefaults() adds defaults to all routes'); - $this->assertEquals(array('_controller' => 'fixed', 'placeholder' => 'new-default'), $collection->get('bar')->getDefaults(), + $collection->addDefaults(['placeholder' => 'new-default']); + $this->assertEquals(['placeholder' => 'new-default'], $collection->get('foo')->getDefaults(), '->addDefaults() adds defaults to all routes'); + $this->assertEquals(['_controller' => 'fixed', 'placeholder' => 'new-default'], $collection->get('bar')->getDefaults(), '->addDefaults() adds defaults to all routes and overwrites existing ones'); - $collection->addRequirements(array('placeholder' => '\d+')); - $this->assertEquals(array('placeholder' => '\d+'), $collection->get('foo')->getRequirements(), '->addRequirements() adds requirements to all routes'); - $this->assertEquals(array('placeholder' => '\d+'), $collection->get('bar')->getRequirements(), + $collection->addRequirements(['placeholder' => '\d+']); + $this->assertEquals(['placeholder' => '\d+'], $collection->get('foo')->getRequirements(), '->addRequirements() adds requirements to all routes'); + $this->assertEquals(['placeholder' => '\d+'], $collection->get('bar')->getRequirements(), '->addRequirements() adds requirements to all routes and overwrites existing ones'); - $collection->addOptions(array('option' => 'new-value')); + $collection->addOptions(['option' => 'new-value']); $this->assertEquals( - array('option' => 'new-value', 'compiler_class' => 'Symfony\\Component\\Routing\\RouteCompiler'), + ['option' => 'new-value', 'compiler_class' => 'Symfony\\Component\\Routing\\RouteCompiler'], $collection->get('bar')->getOptions(), '->addOptions() adds options to all routes and overwrites existing ones' ); } @@ -148,13 +148,13 @@ class RouteCollectionTest extends TestCase $collection->addCollection($collection2); $collection->addPrefix(' / '); $this->assertSame('/foo', $collection->get('foo')->getPath(), '->addPrefix() trims the prefix and a single slash has no effect'); - $collection->addPrefix('/{admin}', array('admin' => 'admin'), array('admin' => '\d+')); + $collection->addPrefix('/{admin}', ['admin' => 'admin'], ['admin' => '\d+']); $this->assertEquals('/{admin}/foo', $collection->get('foo')->getPath(), '->addPrefix() adds a prefix to all routes'); $this->assertEquals('/{admin}/bar', $collection->get('bar')->getPath(), '->addPrefix() adds a prefix to all routes'); - $this->assertEquals(array('admin' => 'admin'), $collection->get('foo')->getDefaults(), '->addPrefix() adds defaults to all routes'); - $this->assertEquals(array('admin' => 'admin'), $collection->get('bar')->getDefaults(), '->addPrefix() adds defaults to all routes'); - $this->assertEquals(array('admin' => '\d+'), $collection->get('foo')->getRequirements(), '->addPrefix() adds requirements to all routes'); - $this->assertEquals(array('admin' => '\d+'), $collection->get('bar')->getRequirements(), '->addPrefix() adds requirements to all routes'); + $this->assertEquals(['admin' => 'admin'], $collection->get('foo')->getDefaults(), '->addPrefix() adds defaults to all routes'); + $this->assertEquals(['admin' => 'admin'], $collection->get('bar')->getDefaults(), '->addPrefix() adds defaults to all routes'); + $this->assertEquals(['admin' => '\d+'], $collection->get('foo')->getRequirements(), '->addPrefix() adds requirements to all routes'); + $this->assertEquals(['admin' => '\d+'], $collection->get('bar')->getRequirements(), '->addPrefix() adds requirements to all routes'); $collection->addPrefix('0'); $this->assertEquals('/0/{admin}/foo', $collection->get('foo')->getPath(), '->addPrefix() ensures a prefix must start with a slash and must not end with a slash'); $collection->addPrefix('/ /'); @@ -166,8 +166,8 @@ class RouteCollectionTest extends TestCase { $collection = new RouteCollection(); $collection->add('foo', $foo = new Route('/foo.{_format}')); - $collection->add('bar', $bar = new Route('/bar.{_format}', array(), array('_format' => 'json'))); - $collection->addPrefix('/admin', array(), array('_format' => 'html')); + $collection->add('bar', $bar = new Route('/bar.{_format}', [], ['_format' => 'json'])); + $collection->addPrefix('/admin', [], ['_format' => 'html']); $this->assertEquals('html', $collection->get('foo')->getRequirement('_format'), '->addPrefix() overrides existing requirements'); $this->assertEquals('html', $collection->get('bar')->getRequirement('_format'), '->addPrefix() overrides existing requirements'); @@ -180,7 +180,7 @@ class RouteCollectionTest extends TestCase $collection->addResource($bar = new FileResource(__DIR__.'/Fixtures/bar.xml')); $collection->addResource(new FileResource(__DIR__.'/Fixtures/foo.xml')); - $this->assertEquals(array($foo, $bar), $collection->getResources(), + $this->assertEquals([$foo, $bar], $collection->getResources(), '->addResource() adds a resource and getResources() only returns unique ones by comparing the string representation'); } @@ -227,16 +227,16 @@ class RouteCollectionTest extends TestCase $collection->add('last', $last = new Route('/last')); $collection->remove('foo'); - $this->assertSame(array('bar' => $bar, 'last' => $last), $collection->all(), '->remove() can remove a single route'); - $collection->remove(array('bar', 'last')); - $this->assertSame(array(), $collection->all(), '->remove() accepts an array and can remove multiple routes at once'); + $this->assertSame(['bar' => $bar, 'last' => $last], $collection->all(), '->remove() can remove a single route'); + $collection->remove(['bar', 'last']); + $this->assertSame([], $collection->all(), '->remove() accepts an array and can remove multiple routes at once'); } public function testSetHost() { $collection = new RouteCollection(); $routea = new Route('/a'); - $routeb = new Route('/b', array(), array(), array(), '{locale}.example.net'); + $routeb = new Route('/b', [], [], [], '{locale}.example.net'); $collection->add('a', $routea); $collection->add('b', $routeb); @@ -250,7 +250,7 @@ class RouteCollectionTest extends TestCase { $collection = new RouteCollection(); $routea = new Route('/a'); - $routeb = new Route('/b', array(), array(), array(), '{locale}.example.net', array(), array(), 'context.getMethod() == "GET"'); + $routeb = new Route('/b', [], [], [], '{locale}.example.net', [], [], 'context.getMethod() == "GET"'); $collection->add('a', $routea); $collection->add('b', $routeb); @@ -264,7 +264,7 @@ class RouteCollectionTest extends TestCase { $collection = new RouteCollection(); $collection->add('a', new Route('/a')); - $collection->add('b', new Route('/b', array('placeholder' => 'default'), array('placeholder' => '.+'))); + $collection->add('b', new Route('/b', ['placeholder' => 'default'], ['placeholder' => '.+'])); $clonedCollection = clone $collection; @@ -278,28 +278,56 @@ class RouteCollectionTest extends TestCase public function testSetSchemes() { $collection = new RouteCollection(); - $routea = new Route('/a', array(), array(), array(), '', 'http'); + $routea = new Route('/a', [], [], [], '', 'http'); $routeb = new Route('/b'); $collection->add('a', $routea); $collection->add('b', $routeb); - $collection->setSchemes(array('http', 'https')); + $collection->setSchemes(['http', 'https']); - $this->assertEquals(array('http', 'https'), $routea->getSchemes()); - $this->assertEquals(array('http', 'https'), $routeb->getSchemes()); + $this->assertEquals(['http', 'https'], $routea->getSchemes()); + $this->assertEquals(['http', 'https'], $routeb->getSchemes()); } public function testSetMethods() { $collection = new RouteCollection(); - $routea = new Route('/a', array(), array(), array(), '', array(), array('GET', 'POST')); + $routea = new Route('/a', [], [], [], '', [], ['GET', 'POST']); $routeb = new Route('/b'); $collection->add('a', $routea); $collection->add('b', $routeb); $collection->setMethods('PUT'); - $this->assertEquals(array('PUT'), $routea->getMethods()); - $this->assertEquals(array('PUT'), $routeb->getMethods()); + $this->assertEquals(['PUT'], $routea->getMethods()); + $this->assertEquals(['PUT'], $routeb->getMethods()); + } + + public function testAddNamePrefix() + { + $collection = new RouteCollection(); + $collection->add('foo', $foo = new Route('/foo')); + $collection->add('bar', $bar = new Route('/bar')); + $collection->add('api_foo', $apiFoo = new Route('/api/foo')); + $collection->addNamePrefix('api_'); + + $this->assertEquals($foo, $collection->get('api_foo')); + $this->assertEquals($bar, $collection->get('api_bar')); + $this->assertEquals($apiFoo, $collection->get('api_api_foo')); + $this->assertNull($collection->get('foo')); + $this->assertNull($collection->get('bar')); + } + + public function testAddNamePrefixCanonicalRouteName() + { + $collection = new RouteCollection(); + $collection->add('foo', new Route('/foo', ['_canonical_route' => 'foo'])); + $collection->add('bar', new Route('/bar', ['_canonical_route' => 'bar'])); + $collection->add('api_foo', new Route('/api/foo', ['_canonical_route' => 'api_foo'])); + $collection->addNamePrefix('api_'); + + $this->assertEquals('api_foo', $collection->get('api_foo')->getDefault('_canonical_route')); + $this->assertEquals('api_bar', $collection->get('api_bar')->getDefault('_canonical_route')); + $this->assertEquals('api_api_foo', $collection->get('api_api_foo')->getDefault('_canonical_route')); } } diff --git a/vendor/symfony/routing/Tests/RouteCompilerTest.php b/vendor/symfony/routing/Tests/RouteCompilerTest.php index 54006d7edfadf162821d933686429e32bcf904f4..a54e18b58383421a9205c6b176d9097070e02a23 100644 --- a/vendor/symfony/routing/Tests/RouteCompilerTest.php +++ b/vendor/symfony/routing/Tests/RouteCompilerTest.php @@ -34,162 +34,161 @@ class RouteCompilerTest extends TestCase public function provideCompileData() { - return array( - array( + return [ + [ 'Static route', - array('/foo'), - '/foo', '#^/foo$#s', array(), array( - array('text', '/foo'), - ), - ), + ['/foo'], + '/foo', '#^/foo$#sD', [], [ + ['text', '/foo'], + ], + ], - array( + [ 'Route with a variable', - array('/foo/{bar}'), - '/foo', '#^/foo/(?P<bar>[^/]++)$#s', array('bar'), array( - array('variable', '/', '[^/]++', 'bar'), - array('text', '/foo'), - ), - ), - - array( + ['/foo/{bar}'], + '/foo', '#^/foo/(?P<bar>[^/]++)$#sD', ['bar'], [ + ['variable', '/', '[^/]++', 'bar'], + ['text', '/foo'], + ], + ], + + [ 'Route with a variable that has a default value', - array('/foo/{bar}', array('bar' => 'bar')), - '/foo', '#^/foo(?:/(?P<bar>[^/]++))?$#s', array('bar'), array( - array('variable', '/', '[^/]++', 'bar'), - array('text', '/foo'), - ), - ), - - array( + ['/foo/{bar}', ['bar' => 'bar']], + '/foo', '#^/foo(?:/(?P<bar>[^/]++))?$#sD', ['bar'], [ + ['variable', '/', '[^/]++', 'bar'], + ['text', '/foo'], + ], + ], + + [ 'Route with several variables', - array('/foo/{bar}/{foobar}'), - '/foo', '#^/foo/(?P<bar>[^/]++)/(?P<foobar>[^/]++)$#s', array('bar', 'foobar'), array( - array('variable', '/', '[^/]++', 'foobar'), - array('variable', '/', '[^/]++', 'bar'), - array('text', '/foo'), - ), - ), - - array( + ['/foo/{bar}/{foobar}'], + '/foo', '#^/foo/(?P<bar>[^/]++)/(?P<foobar>[^/]++)$#sD', ['bar', 'foobar'], [ + ['variable', '/', '[^/]++', 'foobar'], + ['variable', '/', '[^/]++', 'bar'], + ['text', '/foo'], + ], + ], + + [ 'Route with several variables that have default values', - array('/foo/{bar}/{foobar}', array('bar' => 'bar', 'foobar' => '')), - '/foo', '#^/foo(?:/(?P<bar>[^/]++)(?:/(?P<foobar>[^/]++))?)?$#s', array('bar', 'foobar'), array( - array('variable', '/', '[^/]++', 'foobar'), - array('variable', '/', '[^/]++', 'bar'), - array('text', '/foo'), - ), - ), - - array( + ['/foo/{bar}/{foobar}', ['bar' => 'bar', 'foobar' => '']], + '/foo', '#^/foo(?:/(?P<bar>[^/]++)(?:/(?P<foobar>[^/]++))?)?$#sD', ['bar', 'foobar'], [ + ['variable', '/', '[^/]++', 'foobar'], + ['variable', '/', '[^/]++', 'bar'], + ['text', '/foo'], + ], + ], + + [ 'Route with several variables but some of them have no default values', - array('/foo/{bar}/{foobar}', array('bar' => 'bar')), - '/foo', '#^/foo/(?P<bar>[^/]++)/(?P<foobar>[^/]++)$#s', array('bar', 'foobar'), array( - array('variable', '/', '[^/]++', 'foobar'), - array('variable', '/', '[^/]++', 'bar'), - array('text', '/foo'), - ), - ), - - array( + ['/foo/{bar}/{foobar}', ['bar' => 'bar']], + '/foo', '#^/foo/(?P<bar>[^/]++)/(?P<foobar>[^/]++)$#sD', ['bar', 'foobar'], [ + ['variable', '/', '[^/]++', 'foobar'], + ['variable', '/', '[^/]++', 'bar'], + ['text', '/foo'], + ], + ], + + [ 'Route with an optional variable as the first segment', - array('/{bar}', array('bar' => 'bar')), - '', '#^/(?P<bar>[^/]++)?$#s', array('bar'), array( - array('variable', '/', '[^/]++', 'bar'), - ), - ), + ['/{bar}', ['bar' => 'bar']], + '', '#^/(?P<bar>[^/]++)?$#sD', ['bar'], [ + ['variable', '/', '[^/]++', 'bar'], + ], + ], - array( + [ 'Route with a requirement of 0', - array('/{bar}', array('bar' => null), array('bar' => '0')), - '', '#^/(?P<bar>0)?$#s', array('bar'), array( - array('variable', '/', '0', 'bar'), - ), - ), + ['/{bar}', ['bar' => null], ['bar' => '0']], + '', '#^/(?P<bar>0)?$#sD', ['bar'], [ + ['variable', '/', '0', 'bar'], + ], + ], - array( + [ 'Route with an optional variable as the first segment with requirements', - array('/{bar}', array('bar' => 'bar'), array('bar' => '(foo|bar)')), - '', '#^/(?P<bar>(foo|bar))?$#s', array('bar'), array( - array('variable', '/', '(foo|bar)', 'bar'), - ), - ), + ['/{bar}', ['bar' => 'bar'], ['bar' => '(foo|bar)']], + '', '#^/(?P<bar>(?:foo|bar))?$#sD', ['bar'], [ + ['variable', '/', '(?:foo|bar)', 'bar'], + ], + ], - array( + [ 'Route with only optional variables', - array('/{foo}/{bar}', array('foo' => 'foo', 'bar' => 'bar')), - '', '#^/(?P<foo>[^/]++)?(?:/(?P<bar>[^/]++))?$#s', array('foo', 'bar'), array( - array('variable', '/', '[^/]++', 'bar'), - array('variable', '/', '[^/]++', 'foo'), - ), - ), - - array( + ['/{foo}/{bar}', ['foo' => 'foo', 'bar' => 'bar']], + '', '#^/(?P<foo>[^/]++)?(?:/(?P<bar>[^/]++))?$#sD', ['foo', 'bar'], [ + ['variable', '/', '[^/]++', 'bar'], + ['variable', '/', '[^/]++', 'foo'], + ], + ], + + [ 'Route with a variable in last position', - array('/foo-{bar}'), - '/foo-', '#^/foo\-(?P<bar>[^/]++)$#s', array('bar'), array( - array('variable', '-', '[^/]++', 'bar'), - array('text', '/foo'), - ), - ), - - array( + ['/foo-{bar}'], + '/foo-', '#^/foo\-(?P<bar>[^/]++)$#sD', ['bar'], [ + ['variable', '-', '[^/]++', 'bar'], + ['text', '/foo'], + ], + ], + + [ 'Route with nested placeholders', - array('/{static{var}static}'), - '/{static', '#^/\{static(?P<var>[^/]+)static\}$#s', array('var'), array( - array('text', 'static}'), - array('variable', '', '[^/]+', 'var'), - array('text', '/{static'), - ), - ), - - array( + ['/{static{var}static}'], + '/{static', '#^/\{static(?P<var>[^/]+)static\}$#sD', ['var'], [ + ['text', 'static}'], + ['variable', '', '[^/]+', 'var'], + ['text', '/{static'], + ], + ], + + [ 'Route without separator between variables', - array('/{w}{x}{y}{z}.{_format}', array('z' => 'default-z', '_format' => 'html'), array('y' => '(y|Y)')), - '', '#^/(?P<w>[^/\.]+)(?P<x>[^/\.]+)(?P<y>(y|Y))(?:(?P<z>[^/\.]++)(?:\.(?P<_format>[^/]++))?)?$#s', array('w', 'x', 'y', 'z', '_format'), array( - array('variable', '.', '[^/]++', '_format'), - array('variable', '', '[^/\.]++', 'z'), - array('variable', '', '(y|Y)', 'y'), - array('variable', '', '[^/\.]+', 'x'), - array('variable', '/', '[^/\.]+', 'w'), - ), - ), - - array( + ['/{w}{x}{y}{z}.{_format}', ['z' => 'default-z', '_format' => 'html'], ['y' => '(y|Y)']], + '', '#^/(?P<w>[^/\.]+)(?P<x>[^/\.]+)(?P<y>(?:y|Y))(?:(?P<z>[^/\.]++)(?:\.(?P<_format>[^/]++))?)?$#sD', ['w', 'x', 'y', 'z', '_format'], [ + ['variable', '.', '[^/]++', '_format'], + ['variable', '', '[^/\.]++', 'z'], + ['variable', '', '(?:y|Y)', 'y'], + ['variable', '', '[^/\.]+', 'x'], + ['variable', '/', '[^/\.]+', 'w'], + ], + ], + + [ 'Route with a format', - array('/foo/{bar}.{_format}'), - '/foo', '#^/foo/(?P<bar>[^/\.]++)\.(?P<_format>[^/]++)$#s', array('bar', '_format'), array( - array('variable', '.', '[^/]++', '_format'), - array('variable', '/', '[^/\.]++', 'bar'), - array('text', '/foo'), - ), - ), - - array( + ['/foo/{bar}.{_format}'], + '/foo', '#^/foo/(?P<bar>[^/\.]++)\.(?P<_format>[^/]++)$#sD', ['bar', '_format'], [ + ['variable', '.', '[^/]++', '_format'], + ['variable', '/', '[^/\.]++', 'bar'], + ['text', '/foo'], + ], + ], + + [ 'Static non UTF-8 route', - array("/fo\xE9"), - "/fo\xE9", "#^/fo\xE9$#s", array(), array( - array('text', "/fo\xE9"), - ), - ), + ["/fo\xE9"], + "/fo\xE9", "#^/fo\xE9$#sD", [], [ + ['text', "/fo\xE9"], + ], + ], - array( + [ 'Route with an explicit UTF-8 requirement', - array('/{bar}', array('bar' => null), array('bar' => '.'), array('utf8' => true)), - '', '#^/(?P<bar>.)?$#su', array('bar'), array( - array('variable', '/', '.', 'bar', true), - ), - ), - ); + ['/{bar}', ['bar' => null], ['bar' => '.'], ['utf8' => true]], + '', '#^/(?P<bar>.)?$#sDu', ['bar'], [ + ['variable', '/', '.', 'bar', true], + ], + ], + ]; } /** - * @group legacy * @dataProvider provideCompileImplicitUtf8Data - * @expectedDeprecation Using UTF-8 route %s without setting the "utf8" option is deprecated %s. */ public function testCompileImplicitUtf8Data($name, $arguments, $prefix, $regex, $variables, $tokens, $deprecationType) { + $this->expectException('LogicException'); $r = new \ReflectionClass('Symfony\\Component\\Routing\\Route'); $route = $r->newInstanceArgs($arguments); @@ -202,82 +201,74 @@ class RouteCompilerTest extends TestCase public function provideCompileImplicitUtf8Data() { - return array( - array( + return [ + [ 'Static UTF-8 route', - array('/foé'), - '/foé', '#^/foé$#su', array(), array( - array('text', '/foé'), - ), + ['/foé'], + '/foé', '#^/foé$#sDu', [], [ + ['text', '/foé'], + ], 'patterns', - ), + ], - array( + [ 'Route with an implicit UTF-8 requirement', - array('/{bar}', array('bar' => null), array('bar' => 'é')), - '', '#^/(?P<bar>é)?$#su', array('bar'), array( - array('variable', '/', 'é', 'bar', true), - ), + ['/{bar}', ['bar' => null], ['bar' => 'é']], + '', '#^/(?P<bar>é)?$#sDu', ['bar'], [ + ['variable', '/', 'é', 'bar', true], + ], 'requirements', - ), + ], - array( + [ 'Route with a UTF-8 class requirement', - array('/{bar}', array('bar' => null), array('bar' => '\pM')), - '', '#^/(?P<bar>\pM)?$#su', array('bar'), array( - array('variable', '/', '\pM', 'bar', true), - ), + ['/{bar}', ['bar' => null], ['bar' => '\pM']], + '', '#^/(?P<bar>\pM)?$#sDu', ['bar'], [ + ['variable', '/', '\pM', 'bar', true], + ], 'requirements', - ), + ], - array( + [ 'Route with a UTF-8 separator', - array('/foo/{bar}§{_format}', array(), array(), array('compiler_class' => Utf8RouteCompiler::class)), - '/foo', '#^/foo/(?P<bar>[^/§]++)§(?P<_format>[^/]++)$#su', array('bar', '_format'), array( - array('variable', '§', '[^/]++', '_format', true), - array('variable', '/', '[^/§]++', 'bar', true), - array('text', '/foo'), - ), + ['/foo/{bar}§{_format}', [], [], ['compiler_class' => Utf8RouteCompiler::class]], + '/foo', '#^/foo/(?P<bar>[^/§]++)§(?P<_format>[^/]++)$#sDu', ['bar', '_format'], [ + ['variable', '§', '[^/]++', '_format', true], + ['variable', '/', '[^/§]++', 'bar', true], + ['text', '/foo'], + ], 'patterns', - ), - ); + ], + ]; } - /** - * @expectedException \LogicException - */ public function testRouteWithSameVariableTwice() { + $this->expectException('LogicException'); $route = new Route('/{name}/{name}'); $compiled = $route->compile(); } - /** - * @expectedException \LogicException - */ public function testRouteCharsetMismatch() { - $route = new Route("/\xE9/{bar}", array(), array('bar' => '.'), array('utf8' => true)); + $this->expectException('LogicException'); + $route = new Route("/\xE9/{bar}", [], ['bar' => '.'], ['utf8' => true]); $compiled = $route->compile(); } - /** - * @expectedException \LogicException - */ public function testRequirementCharsetMismatch() { - $route = new Route('/foo/{bar}', array(), array('bar' => "\xE9"), array('utf8' => true)); + $this->expectException('LogicException'); + $route = new Route('/foo/{bar}', [], ['bar' => "\xE9"], ['utf8' => true]); $compiled = $route->compile(); } - /** - * @expectedException \InvalidArgumentException - */ public function testRouteWithFragmentAsPathParameter() { + $this->expectException('InvalidArgumentException'); $route = new Route('/{_fragment}'); $compiled = $route->compile(); @@ -285,21 +276,21 @@ class RouteCompilerTest extends TestCase /** * @dataProvider getVariableNamesStartingWithADigit - * @expectedException \DomainException */ public function testRouteWithVariableNameStartingWithADigit($name) { + $this->expectException('DomainException'); $route = new Route('/{'.$name.'}'); $route->compile(); } public function getVariableNamesStartingWithADigit() { - return array( - array('09'), - array('123'), - array('1e2'), - ); + return [ + ['09'], + ['123'], + ['1e2'], + ]; } /** @@ -312,75 +303,93 @@ class RouteCompilerTest extends TestCase $compiled = $route->compile(); $this->assertEquals($prefix, $compiled->getStaticPrefix(), $name.' (static prefix)'); - $this->assertEquals($regex, str_replace(array("\n", ' '), '', $compiled->getRegex()), $name.' (regex)'); + $this->assertEquals($regex, str_replace(["\n", ' '], '', $compiled->getRegex()), $name.' (regex)'); $this->assertEquals($variables, $compiled->getVariables(), $name.' (variables)'); $this->assertEquals($pathVariables, $compiled->getPathVariables(), $name.' (path variables)'); $this->assertEquals($tokens, $compiled->getTokens(), $name.' (tokens)'); - $this->assertEquals($hostRegex, str_replace(array("\n", ' '), '', $compiled->getHostRegex()), $name.' (host regex)'); + $this->assertEquals($hostRegex, str_replace(["\n", ' '], '', $compiled->getHostRegex()), $name.' (host regex)'); $this->assertEquals($hostVariables, $compiled->getHostVariables(), $name.' (host variables)'); $this->assertEquals($hostTokens, $compiled->getHostTokens(), $name.' (host tokens)'); } public function provideCompileWithHostData() { - return array( - array( + return [ + [ 'Route with host pattern', - array('/hello', array(), array(), array(), 'www.example.com'), - '/hello', '#^/hello$#s', array(), array(), array( - array('text', '/hello'), - ), - '#^www\.example\.com$#si', array(), array( - array('text', 'www.example.com'), - ), - ), - array( + ['/hello', [], [], [], 'www.example.com'], + '/hello', '#^/hello$#sD', [], [], [ + ['text', '/hello'], + ], + '#^www\.example\.com$#sDi', [], [ + ['text', 'www.example.com'], + ], + ], + [ 'Route with host pattern and some variables', - array('/hello/{name}', array(), array(), array(), 'www.example.{tld}'), - '/hello', '#^/hello/(?P<name>[^/]++)$#s', array('tld', 'name'), array('name'), array( - array('variable', '/', '[^/]++', 'name'), - array('text', '/hello'), - ), - '#^www\.example\.(?P<tld>[^\.]++)$#si', array('tld'), array( - array('variable', '.', '[^\.]++', 'tld'), - array('text', 'www.example'), - ), - ), - array( + ['/hello/{name}', [], [], [], 'www.example.{tld}'], + '/hello', '#^/hello/(?P<name>[^/]++)$#sD', ['tld', 'name'], ['name'], [ + ['variable', '/', '[^/]++', 'name'], + ['text', '/hello'], + ], + '#^www\.example\.(?P<tld>[^\.]++)$#sDi', ['tld'], [ + ['variable', '.', '[^\.]++', 'tld'], + ['text', 'www.example'], + ], + ], + [ 'Route with variable at beginning of host', - array('/hello', array(), array(), array(), '{locale}.example.{tld}'), - '/hello', '#^/hello$#s', array('locale', 'tld'), array(), array( - array('text', '/hello'), - ), - '#^(?P<locale>[^\.]++)\.example\.(?P<tld>[^\.]++)$#si', array('locale', 'tld'), array( - array('variable', '.', '[^\.]++', 'tld'), - array('text', '.example'), - array('variable', '', '[^\.]++', 'locale'), - ), - ), - array( + ['/hello', [], [], [], '{locale}.example.{tld}'], + '/hello', '#^/hello$#sD', ['locale', 'tld'], [], [ + ['text', '/hello'], + ], + '#^(?P<locale>[^\.]++)\.example\.(?P<tld>[^\.]++)$#sDi', ['locale', 'tld'], [ + ['variable', '.', '[^\.]++', 'tld'], + ['text', '.example'], + ['variable', '', '[^\.]++', 'locale'], + ], + ], + [ 'Route with host variables that has a default value', - array('/hello', array('locale' => 'a', 'tld' => 'b'), array(), array(), '{locale}.example.{tld}'), - '/hello', '#^/hello$#s', array('locale', 'tld'), array(), array( - array('text', '/hello'), - ), - '#^(?P<locale>[^\.]++)\.example\.(?P<tld>[^\.]++)$#si', array('locale', 'tld'), array( - array('variable', '.', '[^\.]++', 'tld'), - array('text', '.example'), - array('variable', '', '[^\.]++', 'locale'), - ), - ), - ); + ['/hello', ['locale' => 'a', 'tld' => 'b'], [], [], '{locale}.example.{tld}'], + '/hello', '#^/hello$#sD', ['locale', 'tld'], [], [ + ['text', '/hello'], + ], + '#^(?P<locale>[^\.]++)\.example\.(?P<tld>[^\.]++)$#sDi', ['locale', 'tld'], [ + ['variable', '.', '[^\.]++', 'tld'], + ['text', '.example'], + ['variable', '', '[^\.]++', 'locale'], + ], + ], + ]; } - /** - * @expectedException \DomainException - */ public function testRouteWithTooLongVariableName() { + $this->expectException('DomainException'); $route = new Route(sprintf('/{%s}', str_repeat('a', RouteCompiler::VARIABLE_MAXIMUM_LENGTH + 1))); $route->compile(); } + + /** + * @dataProvider provideRemoveCapturingGroup + */ + public function testRemoveCapturingGroup($regex, $requirement) + { + $route = new Route('/{foo}', [], ['foo' => $requirement]); + + $this->assertSame($regex, $route->compile()->getRegex()); + } + + public function provideRemoveCapturingGroup() + { + yield ['#^/(?P<foo>a(?:b|c)(?:d|e)f)$#sD', 'a(b|c)(d|e)f']; + yield ['#^/(?P<foo>a\(b\)c)$#sD', 'a\(b\)c']; + yield ['#^/(?P<foo>(?:b))$#sD', '(?:b)']; + yield ['#^/(?P<foo>(?(b)b))$#sD', '(?(b)b)']; + yield ['#^/(?P<foo>(*F))$#sD', '(*F)']; + yield ['#^/(?P<foo>(?:(?:foo)))$#sD', '((foo))']; + } } class Utf8RouteCompiler extends RouteCompiler diff --git a/vendor/symfony/routing/Tests/RouteTest.php b/vendor/symfony/routing/Tests/RouteTest.php index ff7e320c5fc95961c62b51eba4bc2d106c475040..6add1337ed369f603becc389228f12f453512e37 100644 --- a/vendor/symfony/routing/Tests/RouteTest.php +++ b/vendor/symfony/routing/Tests/RouteTest.php @@ -18,21 +18,21 @@ class RouteTest extends TestCase { public function testConstructor() { - $route = new Route('/{foo}', array('foo' => 'bar'), array('foo' => '\d+'), array('foo' => 'bar'), '{locale}.example.com'); + $route = new Route('/{foo}', ['foo' => 'bar'], ['foo' => '\d+'], ['foo' => 'bar'], '{locale}.example.com'); $this->assertEquals('/{foo}', $route->getPath(), '__construct() takes a path as its first argument'); - $this->assertEquals(array('foo' => 'bar'), $route->getDefaults(), '__construct() takes defaults as its second argument'); - $this->assertEquals(array('foo' => '\d+'), $route->getRequirements(), '__construct() takes requirements as its third argument'); + $this->assertEquals(['foo' => 'bar'], $route->getDefaults(), '__construct() takes defaults as its second argument'); + $this->assertEquals(['foo' => '\d+'], $route->getRequirements(), '__construct() takes requirements as its third argument'); $this->assertEquals('bar', $route->getOption('foo'), '__construct() takes options as its fourth argument'); $this->assertEquals('{locale}.example.com', $route->getHost(), '__construct() takes a host pattern as its fifth argument'); - $route = new Route('/', array(), array(), array(), '', array('Https'), array('POST', 'put'), 'context.getMethod() == "GET"'); - $this->assertEquals(array('https'), $route->getSchemes(), '__construct() takes schemes as its sixth argument and lowercases it'); - $this->assertEquals(array('POST', 'PUT'), $route->getMethods(), '__construct() takes methods as its seventh argument and uppercases it'); + $route = new Route('/', [], [], [], '', ['Https'], ['POST', 'put'], 'context.getMethod() == "GET"'); + $this->assertEquals(['https'], $route->getSchemes(), '__construct() takes schemes as its sixth argument and lowercases it'); + $this->assertEquals(['POST', 'PUT'], $route->getMethods(), '__construct() takes methods as its seventh argument and uppercases it'); $this->assertEquals('context.getMethod() == "GET"', $route->getCondition(), '__construct() takes a condition as its eight argument'); - $route = new Route('/', array(), array(), array(), '', 'Https', 'Post'); - $this->assertEquals(array('https'), $route->getSchemes(), '__construct() takes a single scheme as its sixth argument'); - $this->assertEquals(array('POST'), $route->getMethods(), '__construct() takes a single method as its seventh argument'); + $route = new Route('/', [], [], [], '', 'Https', 'Post'); + $this->assertEquals(['https'], $route->getSchemes(), '__construct() takes a single scheme as its sixth argument'); + $this->assertEquals(['POST'], $route->getMethods(), '__construct() takes a single method as its seventh argument'); } public function testPath() @@ -52,16 +52,16 @@ class RouteTest extends TestCase public function testOptions() { $route = new Route('/{foo}'); - $route->setOptions(array('foo' => 'bar')); - $this->assertEquals(array_merge(array( + $route->setOptions(['foo' => 'bar']); + $this->assertEquals(array_merge([ 'compiler_class' => 'Symfony\\Component\\Routing\\RouteCompiler', - ), array('foo' => 'bar')), $route->getOptions(), '->setOptions() sets the options'); - $this->assertEquals($route, $route->setOptions(array()), '->setOptions() implements a fluent interface'); + ], ['foo' => 'bar']), $route->getOptions(), '->setOptions() sets the options'); + $this->assertEquals($route, $route->setOptions([]), '->setOptions() implements a fluent interface'); - $route->setOptions(array('foo' => 'foo')); - $route->addOptions(array('bar' => 'bar')); - $this->assertEquals($route, $route->addOptions(array()), '->addOptions() implements a fluent interface'); - $this->assertEquals(array('foo' => 'foo', 'bar' => 'bar', 'compiler_class' => 'Symfony\\Component\\Routing\\RouteCompiler'), $route->getOptions(), '->addDefaults() keep previous defaults'); + $route->setOptions(['foo' => 'foo']); + $route->addOptions(['bar' => 'bar']); + $this->assertEquals($route, $route->addOptions([]), '->addOptions() implements a fluent interface'); + $this->assertEquals(['foo' => 'foo', 'bar' => 'bar', 'compiler_class' => 'Symfony\\Component\\Routing\\RouteCompiler'], $route->getOptions(), '->addDefaults() keep previous defaults'); } public function testOption() @@ -76,9 +76,9 @@ class RouteTest extends TestCase public function testDefaults() { $route = new Route('/{foo}'); - $route->setDefaults(array('foo' => 'bar')); - $this->assertEquals(array('foo' => 'bar'), $route->getDefaults(), '->setDefaults() sets the defaults'); - $this->assertEquals($route, $route->setDefaults(array()), '->setDefaults() implements a fluent interface'); + $route->setDefaults(['foo' => 'bar']); + $this->assertEquals(['foo' => 'bar'], $route->getDefaults(), '->setDefaults() sets the defaults'); + $this->assertEquals($route, $route->setDefaults([]), '->setDefaults() implements a fluent interface'); $route->setDefault('foo', 'bar'); $this->assertEquals('bar', $route->getDefault('foo'), '->setDefault() sets a default value'); @@ -90,27 +90,27 @@ class RouteTest extends TestCase $route->setDefault('_controller', $closure = function () { return 'Hello'; }); $this->assertEquals($closure, $route->getDefault('_controller'), '->setDefault() sets a default value'); - $route->setDefaults(array('foo' => 'foo')); - $route->addDefaults(array('bar' => 'bar')); - $this->assertEquals($route, $route->addDefaults(array()), '->addDefaults() implements a fluent interface'); - $this->assertEquals(array('foo' => 'foo', 'bar' => 'bar'), $route->getDefaults(), '->addDefaults() keep previous defaults'); + $route->setDefaults(['foo' => 'foo']); + $route->addDefaults(['bar' => 'bar']); + $this->assertEquals($route, $route->addDefaults([]), '->addDefaults() implements a fluent interface'); + $this->assertEquals(['foo' => 'foo', 'bar' => 'bar'], $route->getDefaults(), '->addDefaults() keep previous defaults'); } public function testRequirements() { $route = new Route('/{foo}'); - $route->setRequirements(array('foo' => '\d+')); - $this->assertEquals(array('foo' => '\d+'), $route->getRequirements(), '->setRequirements() sets the requirements'); + $route->setRequirements(['foo' => '\d+']); + $this->assertEquals(['foo' => '\d+'], $route->getRequirements(), '->setRequirements() sets the requirements'); $this->assertEquals('\d+', $route->getRequirement('foo'), '->getRequirement() returns a requirement'); $this->assertNull($route->getRequirement('bar'), '->getRequirement() returns null if a requirement is not defined'); - $route->setRequirements(array('foo' => '^\d+$')); + $route->setRequirements(['foo' => '^\d+$']); $this->assertEquals('\d+', $route->getRequirement('foo'), '->getRequirement() removes ^ and $ from the path'); - $this->assertEquals($route, $route->setRequirements(array()), '->setRequirements() implements a fluent interface'); + $this->assertEquals($route, $route->setRequirements([]), '->setRequirements() implements a fluent interface'); - $route->setRequirements(array('foo' => '\d+')); - $route->addRequirements(array('bar' => '\d+')); - $this->assertEquals($route, $route->addRequirements(array()), '->addRequirements() implements a fluent interface'); - $this->assertEquals(array('foo' => '\d+', 'bar' => '\d+'), $route->getRequirements(), '->addRequirement() keep previous requirements'); + $route->setRequirements(['foo' => '\d+']); + $route->addRequirements(['bar' => '\d+']); + $this->assertEquals($route, $route->addRequirements([]), '->addRequirements() implements a fluent interface'); + $this->assertEquals(['foo' => '\d+', 'bar' => '\d+'], $route->getRequirements(), '->addRequirement() keep previous requirements'); } public function testRequirement() @@ -124,23 +124,23 @@ class RouteTest extends TestCase /** * @dataProvider getInvalidRequirements - * @expectedException \InvalidArgumentException */ public function testSetInvalidRequirement($req) { + $this->expectException('InvalidArgumentException'); $route = new Route('/{foo}'); $route->setRequirement('foo', $req); } public function getInvalidRequirements() { - return array( - array(''), - array(array()), - array('^$'), - array('^'), - array('$'), - ); + return [ + [''], + [[]], + ['^$'], + ['^'], + ['$'], + ]; } public function testHost() @@ -153,14 +153,14 @@ class RouteTest extends TestCase public function testScheme() { $route = new Route('/'); - $this->assertEquals(array(), $route->getSchemes(), 'schemes is initialized with array()'); + $this->assertEquals([], $route->getSchemes(), 'schemes is initialized with []'); $this->assertFalse($route->hasScheme('http')); $route->setSchemes('hTTp'); - $this->assertEquals(array('http'), $route->getSchemes(), '->setSchemes() accepts a single scheme string and lowercases it'); + $this->assertEquals(['http'], $route->getSchemes(), '->setSchemes() accepts a single scheme string and lowercases it'); $this->assertTrue($route->hasScheme('htTp')); $this->assertFalse($route->hasScheme('httpS')); - $route->setSchemes(array('HttpS', 'hTTp')); - $this->assertEquals(array('https', 'http'), $route->getSchemes(), '->setSchemes() accepts an array of schemes and lowercases them'); + $route->setSchemes(['HttpS', 'hTTp']); + $this->assertEquals(['https', 'http'], $route->getSchemes(), '->setSchemes() accepts an array of schemes and lowercases them'); $this->assertTrue($route->hasScheme('htTp')); $this->assertTrue($route->hasScheme('httpS')); } @@ -168,11 +168,11 @@ class RouteTest extends TestCase public function testMethod() { $route = new Route('/'); - $this->assertEquals(array(), $route->getMethods(), 'methods is initialized with array()'); + $this->assertEquals([], $route->getMethods(), 'methods is initialized with []'); $route->setMethods('gEt'); - $this->assertEquals(array('GET'), $route->getMethods(), '->setMethods() accepts a single method string and uppercases it'); - $route->setMethods(array('gEt', 'PosT')); - $this->assertEquals(array('GET', 'POST'), $route->getMethods(), '->setMethods() accepts an array of methods and uppercases them'); + $this->assertEquals(['GET'], $route->getMethods(), '->setMethods() accepts a single method string and uppercases it'); + $route->setMethods(['gEt', 'PosT']); + $this->assertEquals(['GET', 'POST'], $route->getMethods(), '->setMethods() accepts an array of methods and uppercases them'); } public function testCondition() @@ -194,7 +194,7 @@ class RouteTest extends TestCase public function testSerialize() { - $route = new Route('/prefix/{foo}', array('foo' => 'default'), array('foo' => '\d+')); + $route = new Route('/prefix/{foo}', ['foo' => 'default'], ['foo' => '\d+']); $serialized = serialize($route); $unserialized = unserialize($serialized); @@ -203,13 +203,29 @@ class RouteTest extends TestCase $this->assertNotSame($route, $unserialized); } + public function testInlineDefaultAndRequirement() + { + $this->assertEquals((new Route('/foo/{bar}'))->setDefault('bar', null), new Route('/foo/{bar?}')); + $this->assertEquals((new Route('/foo/{bar}'))->setDefault('bar', 'baz'), new Route('/foo/{bar?baz}')); + $this->assertEquals((new Route('/foo/{bar}'))->setDefault('bar', 'baz<buz>'), new Route('/foo/{bar?baz<buz>}')); + $this->assertEquals((new Route('/foo/{bar}'))->setDefault('bar', 'baz'), new Route('/foo/{bar?}', ['bar' => 'baz'])); + + $this->assertEquals((new Route('/foo/{bar}'))->setRequirement('bar', '.*'), new Route('/foo/{bar<.*>}')); + $this->assertEquals((new Route('/foo/{bar}'))->setRequirement('bar', '>'), new Route('/foo/{bar<>>}')); + $this->assertEquals((new Route('/foo/{bar}'))->setRequirement('bar', '\d+'), new Route('/foo/{bar<.*>}', [], ['bar' => '\d+'])); + $this->assertEquals((new Route('/foo/{bar}'))->setRequirement('bar', '[a-z]{2}'), new Route('/foo/{bar<[a-z]{2}>}')); + + $this->assertEquals((new Route('/foo/{bar}'))->setDefault('bar', null)->setRequirement('bar', '.*'), new Route('/foo/{bar<.*>?}')); + $this->assertEquals((new Route('/foo/{bar}'))->setDefault('bar', '<>')->setRequirement('bar', '>'), new Route('/foo/{bar<>>?<>}')); + } + /** * Tests that the compiled version is also serialized to prevent the overhead * of compiling it again after unserialize. */ public function testSerializeWhenCompiled() { - $route = new Route('/prefix/{foo}', array('foo' => 'default'), array('foo' => '\d+')); + $route = new Route('/prefix/{foo}', ['foo' => 'default'], ['foo' => '\d+']); $route->setHost('{locale}.example.net'); $route->compile(); @@ -226,7 +242,7 @@ class RouteTest extends TestCase */ public function testSerializeWhenCompiledWithClass() { - $route = new Route('/', array(), array(), array('compiler_class' => '\Symfony\Component\Routing\Tests\Fixtures\CustomRouteCompiler')); + $route = new Route('/', [], [], ['compiler_class' => '\Symfony\Component\Routing\Tests\Fixtures\CustomRouteCompiler']); $this->assertInstanceOf('\Symfony\Component\Routing\Tests\Fixtures\CustomCompiledRoute', $route->compile(), '->compile() returned a proper route'); $serialized = serialize($route); @@ -245,10 +261,10 @@ class RouteTest extends TestCase */ public function testSerializedRepresentationKeepsWorking() { - $serialized = 'C:31:"Symfony\Component\Routing\Route":934:{a:8:{s:4:"path";s:13:"/prefix/{foo}";s:4:"host";s:20:"{locale}.example.net";s:8:"defaults";a:1:{s:3:"foo";s:7:"default";}s:12:"requirements";a:1:{s:3:"foo";s:3:"\d+";}s:7:"options";a:1:{s:14:"compiler_class";s:39:"Symfony\Component\Routing\RouteCompiler";}s:7:"schemes";a:0:{}s:7:"methods";a:0:{}s:8:"compiled";C:39:"Symfony\Component\Routing\CompiledRoute":569:{a:8:{s:4:"vars";a:2:{i:0;s:6:"locale";i:1;s:3:"foo";}s:11:"path_prefix";s:7:"/prefix";s:10:"path_regex";s:30:"#^/prefix(?:/(?P<foo>\d+))?$#s";s:11:"path_tokens";a:2:{i:0;a:4:{i:0;s:8:"variable";i:1;s:1:"/";i:2;s:3:"\d+";i:3;s:3:"foo";}i:1;a:2:{i:0;s:4:"text";i:1;s:7:"/prefix";}}s:9:"path_vars";a:1:{i:0;s:3:"foo";}s:10:"host_regex";s:39:"#^(?P<locale>[^\.]++)\.example\.net$#si";s:11:"host_tokens";a:2:{i:0;a:2:{i:0;s:4:"text";i:1;s:12:".example.net";}i:1;a:4:{i:0;s:8:"variable";i:1;s:0:"";i:2;s:7:"[^\.]++";i:3;s:6:"locale";}}s:9:"host_vars";a:1:{i:0;s:6:"locale";}}}}}'; + $serialized = 'C:31:"Symfony\Component\Routing\Route":936:{a:8:{s:4:"path";s:13:"/prefix/{foo}";s:4:"host";s:20:"{locale}.example.net";s:8:"defaults";a:1:{s:3:"foo";s:7:"default";}s:12:"requirements";a:1:{s:3:"foo";s:3:"\d+";}s:7:"options";a:1:{s:14:"compiler_class";s:39:"Symfony\Component\Routing\RouteCompiler";}s:7:"schemes";a:0:{}s:7:"methods";a:0:{}s:8:"compiled";C:39:"Symfony\Component\Routing\CompiledRoute":571:{a:8:{s:4:"vars";a:2:{i:0;s:6:"locale";i:1;s:3:"foo";}s:11:"path_prefix";s:7:"/prefix";s:10:"path_regex";s:31:"#^/prefix(?:/(?P<foo>\d+))?$#sD";s:11:"path_tokens";a:2:{i:0;a:4:{i:0;s:8:"variable";i:1;s:1:"/";i:2;s:3:"\d+";i:3;s:3:"foo";}i:1;a:2:{i:0;s:4:"text";i:1;s:7:"/prefix";}}s:9:"path_vars";a:1:{i:0;s:3:"foo";}s:10:"host_regex";s:40:"#^(?P<locale>[^\.]++)\.example\.net$#sDi";s:11:"host_tokens";a:2:{i:0;a:2:{i:0;s:4:"text";i:1;s:12:".example.net";}i:1;a:4:{i:0;s:8:"variable";i:1;s:0:"";i:2;s:7:"[^\.]++";i:3;s:6:"locale";}}s:9:"host_vars";a:1:{i:0;s:6:"locale";}}}}}'; $unserialized = unserialize($serialized); - $route = new Route('/prefix/{foo}', array('foo' => 'default'), array('foo' => '\d+')); + $route = new Route('/prefix/{foo}', ['foo' => 'default'], ['foo' => '\d+']); $route->setHost('{locale}.example.net'); $route->compile(); diff --git a/vendor/symfony/routing/Tests/RouterTest.php b/vendor/symfony/routing/Tests/RouterTest.php index 409959eec07dc7e6b4f7e69be6a78701772f9056..fa0a2f5399aca2a5f45a26046b67dcc99c1df9e0 100644 --- a/vendor/symfony/routing/Tests/RouterTest.php +++ b/vendor/symfony/routing/Tests/RouterTest.php @@ -12,8 +12,9 @@ namespace Symfony\Component\Routing\Tests; use PHPUnit\Framework\TestCase; -use Symfony\Component\Routing\Router; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\Routing\RouteCollection; +use Symfony\Component\Routing\Router; class RouterTest extends TestCase { @@ -21,7 +22,7 @@ class RouterTest extends TestCase private $loader = null; - protected function setUp() + protected function setUp(): void { $this->loader = $this->getMockBuilder('Symfony\Component\Config\Loader\LoaderInterface')->getMock(); $this->router = new Router($this->loader, 'routing.yml'); @@ -29,29 +30,27 @@ class RouterTest extends TestCase public function testSetOptionsWithSupportedOptions() { - $this->router->setOptions(array( + $this->router->setOptions([ 'cache_dir' => './cache', 'debug' => true, 'resource_type' => 'ResourceType', - )); + ]); $this->assertSame('./cache', $this->router->getOption('cache_dir')); $this->assertTrue($this->router->getOption('debug')); $this->assertSame('ResourceType', $this->router->getOption('resource_type')); } - /** - * @expectedException \InvalidArgumentException - * @expectedExceptionMessage The Router does not support the following options: "option_foo", "option_bar" - */ public function testSetOptionsWithUnsupportedOptions() { - $this->router->setOptions(array( + $this->expectException('InvalidArgumentException'); + $this->expectExceptionMessage('The Router does not support the following options: "option_foo", "option_bar"'); + $this->router->setOptions([ 'cache_dir' => './cache', 'option_foo' => true, 'option_bar' => 'baz', 'resource_type' => 'ResourceType', - )); + ]); } public function testSetOptionWithSupportedOption() @@ -61,21 +60,17 @@ class RouterTest extends TestCase $this->assertSame('./cache', $this->router->getOption('cache_dir')); } - /** - * @expectedException \InvalidArgumentException - * @expectedExceptionMessage The Router does not support the "option_foo" option - */ public function testSetOptionWithUnsupportedOption() { + $this->expectException('InvalidArgumentException'); + $this->expectExceptionMessage('The Router does not support the "option_foo" option'); $this->router->setOption('option_foo', true); } - /** - * @expectedException \InvalidArgumentException - * @expectedExceptionMessage The Router does not support the "option_foo" option - */ public function testGetOptionWithUnsupportedOption() { + $this->expectException('InvalidArgumentException'); + $this->expectExceptionMessage('The Router does not support the "option_foo" option'); $this->router->getOption('option_foo', true); } @@ -83,59 +78,37 @@ class RouterTest extends TestCase { $this->router->setOption('resource_type', 'ResourceType'); - $routeCollection = $this->getMockBuilder('Symfony\Component\Routing\RouteCollection')->getMock(); + $routeCollection = new RouteCollection(); $this->loader->expects($this->once()) ->method('load')->with('routing.yml', 'ResourceType') - ->will($this->returnValue($routeCollection)); + ->willReturn($routeCollection); $this->assertSame($routeCollection, $this->router->getRouteCollection()); } - /** - * @dataProvider provideMatcherOptionsPreventingCaching - */ - public function testMatcherIsCreatedIfCacheIsNotConfigured($option) + public function testMatcherIsCreatedIfCacheIsNotConfigured() { - $this->router->setOption($option, null); + $this->router->setOption('cache_dir', null); $this->loader->expects($this->once()) ->method('load')->with('routing.yml', null) - ->will($this->returnValue($this->getMockBuilder('Symfony\Component\Routing\RouteCollection')->getMock())); + ->willReturn(new RouteCollection()); $this->assertInstanceOf('Symfony\\Component\\Routing\\Matcher\\UrlMatcher', $this->router->getMatcher()); } - public function provideMatcherOptionsPreventingCaching() - { - return array( - array('cache_dir'), - array('matcher_cache_class'), - ); - } - - /** - * @dataProvider provideGeneratorOptionsPreventingCaching - */ - public function testGeneratorIsCreatedIfCacheIsNotConfigured($option) + public function testGeneratorIsCreatedIfCacheIsNotConfigured() { - $this->router->setOption($option, null); + $this->router->setOption('cache_dir', null); $this->loader->expects($this->once()) ->method('load')->with('routing.yml', null) - ->will($this->returnValue($this->getMockBuilder('Symfony\Component\Routing\RouteCollection')->getMock())); + ->willReturn(new RouteCollection()); $this->assertInstanceOf('Symfony\\Component\\Routing\\Generator\\UrlGenerator', $this->router->getGenerator()); } - public function provideGeneratorOptionsPreventingCaching() - { - return array( - array('cache_dir'), - array('generator_cache_class'), - ); - } - public function testMatchRequestWithUrlMatcherInterface() { $matcher = $this->getMockBuilder('Symfony\Component\Routing\Matcher\UrlMatcherInterface')->getMock(); diff --git a/vendor/symfony/routing/composer.json b/vendor/symfony/routing/composer.json index 2ad746ec53c245b975a12d86c4046f515332e72e..77d7ce981c82e34ce076ea203f8e91bb2109e1f8 100644 --- a/vendor/symfony/routing/composer.json +++ b/vendor/symfony/routing/composer.json @@ -16,21 +16,20 @@ } ], "require": { - "php": "^5.5.9|>=7.0.8" + "php": "^7.1.3" }, "require-dev": { - "symfony/config": "~2.8|~3.0|~4.0", - "symfony/http-foundation": "~2.8|~3.0|~4.0", + "symfony/config": "~4.2", + "symfony/http-foundation": "~3.4|~4.0", "symfony/yaml": "~3.4|~4.0", - "symfony/expression-language": "~2.8|~3.0|~4.0", - "symfony/dependency-injection": "~3.3|~4.0", - "doctrine/annotations": "~1.0", - "doctrine/common": "~2.2", + "symfony/expression-language": "~3.4|~4.0", + "symfony/dependency-injection": "~3.4|~4.0", + "doctrine/annotations": "~1.2", "psr/log": "~1.0" }, "conflict": { - "symfony/config": "<2.8", - "symfony/dependency-injection": "<3.3", + "symfony/config": "<4.2", + "symfony/dependency-injection": "<3.4", "symfony/yaml": "<3.4" }, "suggest": { @@ -38,8 +37,7 @@ "symfony/config": "For using the all-in-one router or any loader", "symfony/yaml": "For using the YAML loader", "symfony/expression-language": "For using expression matching", - "doctrine/annotations": "For using the annotation loader", - "symfony/dependency-injection": "For loading routes from a service" + "doctrine/annotations": "For using the annotation loader" }, "autoload": { "psr-4": { "Symfony\\Component\\Routing\\": "" }, @@ -50,7 +48,7 @@ "minimum-stability": "dev", "extra": { "branch-alias": { - "dev-master": "3.4-dev" + "dev-master": "4.3-dev" } } } diff --git a/vendor/symfony/routing/phpunit.xml.dist b/vendor/symfony/routing/phpunit.xml.dist index bcc0959522cb6c77e12956bcec9b30beb077fa2b..df742eab0033133b1fabeb16564ca165e37f7c1c 100644 --- a/vendor/symfony/routing/phpunit.xml.dist +++ b/vendor/symfony/routing/phpunit.xml.dist @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="UTF-8"?> <phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/4.1/phpunit.xsd" + xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/5.2/phpunit.xsd" backupGlobals="false" colors="true" bootstrap="vendor/autoload.php" diff --git a/vendor/symfony/twig-bridge/AppVariable.php b/vendor/symfony/twig-bridge/AppVariable.php index 54a785c0a433631a12d4b35b217e97dd75c73637..eb9cec6dd9101da18cb8be6a02e70b6d52b0a1fc 100644 --- a/vendor/symfony/twig-bridge/AppVariable.php +++ b/vendor/symfony/twig-bridge/AppVariable.php @@ -68,7 +68,7 @@ class AppVariable /** * Returns the current user. * - * @return mixed + * @return object|null * * @see TokenInterface::getUser() */ @@ -79,13 +79,12 @@ class AppVariable } if (!$token = $tokenStorage->getToken()) { - return; + return null; } $user = $token->getUser(); - if (is_object($user)) { - return $user; - } + + return \is_object($user) ? $user : null; } /** @@ -113,9 +112,7 @@ class AppVariable throw new \RuntimeException('The "app.session" variable is not available.'); } - if ($request = $this->getRequest()) { - return $request->getSession(); - } + return ($request = $this->getRequest()) ? $request->getSession() : null; } /** @@ -150,7 +147,7 @@ class AppVariable * Returns some or all the existing flash messages: * * getFlashes() returns all the flash messages * * getFlashes('notice') returns a simple array with flash messages of that type - * * getFlashes(array('notice', 'error')) returns a nested array of type => messages. + * * getFlashes(['notice', 'error']) returns a nested array of type => messages. * * @return array */ @@ -159,21 +156,21 @@ class AppVariable try { $session = $this->getSession(); if (null === $session) { - return array(); + return []; } } catch (\RuntimeException $e) { - return array(); + return []; } - if (null === $types || '' === $types || array() === $types) { + if (null === $types || '' === $types || [] === $types) { return $session->getFlashBag()->all(); } - if (is_string($types)) { + if (\is_string($types)) { return $session->getFlashBag()->get($types); } - $result = array(); + $result = []; foreach ($types as $type) { $result[$type] = $session->getFlashBag()->get($type); } diff --git a/vendor/symfony/twig-bridge/CHANGELOG.md b/vendor/symfony/twig-bridge/CHANGELOG.md index 8d5d6f56b6771db9d82a34ae3dced5ffc54d025e..4ccde3894715d5d3e8291d7a736cf8cd29eb5196 100644 --- a/vendor/symfony/twig-bridge/CHANGELOG.md +++ b/vendor/symfony/twig-bridge/CHANGELOG.md @@ -33,7 +33,7 @@ CHANGELOG use Symfony\Bridge\Twig\Form\TwigRendererEngine; // ... - $rendererEngine = new TwigRendererEngine(array('form_div_layout.html.twig')); + $rendererEngine = new TwigRendererEngine(['form_div_layout.html.twig']); $rendererEngine->setEnvironment($twig); $twig->addExtension(new FormExtension(new TwigRenderer($rendererEngine, $csrfTokenManager))); ``` @@ -42,13 +42,13 @@ CHANGELOG ```php // ... - $rendererEngine = new TwigRendererEngine(array('form_div_layout.html.twig'), $twig); + $rendererEngine = new TwigRendererEngine(['form_div_layout.html.twig'], $twig); // require Twig 1.30+ - $twig->addRuntimeLoader(new \Twig\RuntimeLoader\FactoryRuntimeLoader(array( + $twig->addRuntimeLoader(new \Twig\RuntimeLoader\FactoryRuntimeLoader([ TwigRenderer::class => function () use ($rendererEngine, $csrfTokenManager) { return new TwigRenderer($rendererEngine, $csrfTokenManager); }, - ))); + ])); $twig->addExtension(new FormExtension()); ``` * Deprecated the `TwigRendererEngineInterface` interface. diff --git a/vendor/symfony/twig-bridge/Command/DebugCommand.php b/vendor/symfony/twig-bridge/Command/DebugCommand.php index 1e45cf4d285af20e61de0aba24d8524aba6a0c2c..b45b580ee4b468116ab6165ca1bd998768312a91 100644 --- a/vendor/symfony/twig-bridge/Command/DebugCommand.php +++ b/vendor/symfony/twig-bridge/Command/DebugCommand.php @@ -12,9 +12,10 @@ namespace Symfony\Bridge\Twig\Command; use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Formatter\OutputFormatter; use Symfony\Component\Console\Input\InputArgument; -use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Input\InputInterface; +use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Style\SymfonyStyle; use Twig\Environment; @@ -39,7 +40,7 @@ class DebugCommand extends Command public function __construct($twig = null, $projectDir = null) { if (!$twig instanceof Environment) { - @trigger_error(sprintf('Passing a command name as the first argument of "%s" is deprecated since Symfony 3.4 and will be removed in 4.0. If the command was registered by convention, make it a service instead.', __METHOD__), E_USER_DEPRECATED); + @trigger_error(sprintf('Passing a command name as the first argument of "%s()" is deprecated since Symfony 3.4 and support for it will be removed in 4.0. If the command was registered by convention, make it a service instead.', __METHOD__), E_USER_DEPRECATED); parent::__construct($twig); @@ -54,7 +55,7 @@ class DebugCommand extends Command public function setTwigEnvironment(Environment $twig) { - @trigger_error(sprintf('Method "%s" is deprecated since Symfony 3.4 and will be removed in 4.0.', __METHOD__), E_USER_DEPRECATED); + @trigger_error(sprintf('The "%s()" method is deprecated since Symfony 3.4 and will be removed in 4.0.', __METHOD__), E_USER_DEPRECATED); $this->twig = $twig; } @@ -64,7 +65,7 @@ class DebugCommand extends Command */ protected function getTwigEnvironment() { - @trigger_error(sprintf('Method "%s" is deprecated since Symfony 3.4 and will be removed in 4.0.', __METHOD__), E_USER_DEPRECATED); + @trigger_error(sprintf('The "%s()" method is deprecated since Symfony 3.4 and will be removed in 4.0.', __METHOD__), E_USER_DEPRECATED); return $this->twig; } @@ -72,10 +73,10 @@ class DebugCommand extends Command protected function configure() { $this - ->setDefinition(array( + ->setDefinition([ new InputArgument('filter', InputArgument::OPTIONAL, 'Show details for all entries matching this filter'), new InputOption('format', null, InputOption::VALUE_REQUIRED, 'The output format (text or json)', 'text'), - )) + ]) ->setDescription('Shows a list of twig functions, filters, globals and tests') ->setHelp(<<<'EOF' The <info>%command.name%</info> command outputs a list of twig functions, @@ -100,12 +101,13 @@ EOF protected function execute(InputInterface $input, OutputInterface $output) { $io = new SymfonyStyle($input, $output); + $decorated = $io->isDecorated(); // BC to be removed in 4.0 - if (__CLASS__ !== get_class($this)) { + if (__CLASS__ !== \get_class($this)) { $r = new \ReflectionMethod($this, 'getTwigEnvironment'); if (__CLASS__ !== $r->getDeclaringClass()->getName()) { - @trigger_error(sprintf('Usage of method "%s" is deprecated since Symfony 3.4 and will no longer be supported in 4.0. Construct the command with its required arguments instead.', get_class($this).'::getTwigEnvironment'), E_USER_DEPRECATED); + @trigger_error(sprintf('Usage of method "%s" is deprecated since Symfony 3.4 and will no longer be supported in 4.0. Construct the command with its required arguments instead.', \get_class($this).'::getTwigEnvironment'), E_USER_DEPRECATED); $this->twig = $this->getTwigEnvironment(); } @@ -114,29 +116,35 @@ EOF throw new \RuntimeException('The Twig environment needs to be set.'); } - $types = array('functions', 'filters', 'tests', 'globals'); + $filter = $input->getArgument('filter'); + $types = ['functions', 'filters', 'tests', 'globals']; if ('json' === $input->getOption('format')) { - $data = array(); + $data = []; foreach ($types as $type) { foreach ($this->twig->{'get'.ucfirst($type)}() as $name => $entity) { - $data[$type][$name] = $this->getMetadata($type, $entity); + if (!$filter || false !== strpos($name, $filter)) { + $data[$type][$name] = $this->getMetadata($type, $entity); + } } } - $data['tests'] = array_keys($data['tests']); + + if (isset($data['tests'])) { + $data['tests'] = array_keys($data['tests']); + } + $data['loader_paths'] = $this->getLoaderPaths(); - $io->writeln(json_encode($data)); + $data = json_encode($data, JSON_PRETTY_PRINT); + $io->writeln($decorated ? OutputFormatter::escape($data) : $data); return 0; } - $filter = $input->getArgument('filter'); - foreach ($types as $index => $type) { - $items = array(); + $items = []; foreach ($this->twig->{'get'.ucfirst($type)}() as $name => $entity) { if (!$filter || false !== strpos($name, $filter)) { - $items[$name] = $name.$this->getPrettyMetadata($type, $entity); + $items[$name] = $name.$this->getPrettyMetadata($type, $entity, $decorated); } } @@ -150,22 +158,30 @@ EOF $io->listing($items); } - $rows = array(); + $rows = []; + $firstNamespace = true; + $prevHasSeparator = false; foreach ($this->getLoaderPaths() as $namespace => $paths) { - if (count($paths) > 1) { - $rows[] = array('', ''); + if (!$firstNamespace && !$prevHasSeparator && \count($paths) > 1) { + $rows[] = ['', '']; } + $firstNamespace = false; foreach ($paths as $path) { - $rows[] = array($namespace, '- '.$path); + $rows[] = [$namespace, $path.\DIRECTORY_SEPARATOR]; $namespace = ''; } - if (count($paths) > 1) { - $rows[] = array('', ''); + if (\count($paths) > 1) { + $rows[] = ['', '']; + $prevHasSeparator = true; + } else { + $prevHasSeparator = false; } } - array_pop($rows); + if ($prevHasSeparator) { + array_pop($rows); + } $io->section('Loader Paths'); - $io->table(array('Namespace', 'Paths'), $rows); + $io->table(['Namespace', 'Paths'], $rows); return 0; } @@ -173,14 +189,14 @@ EOF private function getLoaderPaths() { if (!($loader = $this->twig->getLoader()) instanceof FilesystemLoader) { - return array(); + return []; } - $loaderPaths = array(); + $loaderPaths = []; foreach ($loader->getNamespaces() as $namespace) { $paths = array_map(function ($path) { if (null !== $this->projectDir && 0 === strpos($path, $this->projectDir)) { - $path = ltrim(substr($path, strlen($this->projectDir)), DIRECTORY_SEPARATOR); + $path = ltrim(substr($path, \strlen($this->projectDir)), \DIRECTORY_SEPARATOR); } return $path; @@ -204,23 +220,23 @@ EOF return $entity; } if ('tests' === $type) { - return; + return null; } if ('functions' === $type || 'filters' === $type) { $cb = $entity->getCallable(); if (null === $cb) { - return; + return null; } - if (is_array($cb)) { + if (\is_array($cb)) { if (!method_exists($cb[0], $cb[1])) { - return; + return null; } $refl = new \ReflectionMethod($cb[0], $cb[1]); - } elseif (is_object($cb) && method_exists($cb, '__invoke')) { + } elseif (\is_object($cb) && method_exists($cb, '__invoke')) { $refl = new \ReflectionMethod($cb, '__invoke'); - } elseif (function_exists($cb)) { + } elseif (\function_exists($cb)) { $refl = new \ReflectionFunction($cb); - } elseif (is_string($cb) && preg_match('{^(.+)::(.+)$}', $cb, $m) && method_exists($m[1], $m[2])) { + } elseif (\is_string($cb) && preg_match('{^(.+)::(.+)$}', $cb, $m) && method_exists($m[1], $m[2])) { $refl = new \ReflectionMethod($m[1], $m[2]); } else { throw new \UnexpectedValueException('Unsupported callback type'); @@ -252,9 +268,11 @@ EOF return $args; } + + return null; } - private function getPrettyMetadata($type, $entity) + private function getPrettyMetadata($type, $entity, $decorated) { if ('tests' === $type) { return ''; @@ -266,15 +284,17 @@ EOF return '(unknown?)'; } } catch (\UnexpectedValueException $e) { - return ' <error>'.$e->getMessage().'</error>'; + return sprintf(' <error>%s</error>', $decorated ? OutputFormatter::escape($e->getMessage()) : $e->getMessage()); } if ('globals' === $type) { - if (is_object($meta)) { - return ' = object('.get_class($meta).')'; + if (\is_object($meta)) { + return ' = object('.\get_class($meta).')'; } - return ' = '.substr(@json_encode($meta), 0, 50); + $description = substr(@json_encode($meta), 0, 50); + + return sprintf(' = %s', $decorated ? OutputFormatter::escape($description) : $description); } if ('functions' === $type) { @@ -284,5 +304,7 @@ EOF if ('filters' === $type) { return $meta ? '('.implode(', ', $meta).')' : ''; } + + return null; } } diff --git a/vendor/symfony/twig-bridge/Command/LintCommand.php b/vendor/symfony/twig-bridge/Command/LintCommand.php index afb1d1bf31cf2132255c712e6d120d79bfb90eb5..c8b5bb5ba2a05c07dbaaee497fbe4a95ff9b2e06 100644 --- a/vendor/symfony/twig-bridge/Command/LintCommand.php +++ b/vendor/symfony/twig-bridge/Command/LintCommand.php @@ -12,6 +12,8 @@ namespace Symfony\Bridge\Twig\Command; use Symfony\Component\Console\Command\Command; +use Symfony\Component\Console\Exception\InvalidArgumentException; +use Symfony\Component\Console\Exception\RuntimeException; use Symfony\Component\Console\Input\InputArgument; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; @@ -41,7 +43,7 @@ class LintCommand extends Command public function __construct($twig = null) { if (!$twig instanceof Environment) { - @trigger_error(sprintf('Passing a command name as the first argument of "%s" is deprecated since Symfony 3.4 and will be removed in 4.0. If the command was registered by convention, make it a service instead.', __METHOD__), E_USER_DEPRECATED); + @trigger_error(sprintf('Passing a command name as the first argument of "%s()" is deprecated since Symfony 3.4 and support for it will be removed in 4.0. If the command was registered by convention, make it a service instead.', __METHOD__), E_USER_DEPRECATED); parent::__construct($twig); @@ -55,7 +57,7 @@ class LintCommand extends Command public function setTwigEnvironment(Environment $twig) { - @trigger_error(sprintf('Method "%s" is deprecated since Symfony 3.4 and will be removed in 4.0.', __METHOD__), E_USER_DEPRECATED); + @trigger_error(sprintf('The "%s()" method is deprecated since Symfony 3.4 and will be removed in 4.0.', __METHOD__), E_USER_DEPRECATED); $this->twig = $twig; } @@ -65,7 +67,7 @@ class LintCommand extends Command */ protected function getTwigEnvironment() { - @trigger_error(sprintf('Method "%s" is deprecated since Symfony 3.4 and will be removed in 4.0.', __METHOD__), E_USER_DEPRECATED); + @trigger_error(sprintf('The "%s()" method is deprecated since Symfony 3.4 and will be removed in 4.0.', __METHOD__), E_USER_DEPRECATED); return $this->twig; } @@ -103,10 +105,10 @@ EOF $io = new SymfonyStyle($input, $output); // BC to be removed in 4.0 - if (__CLASS__ !== get_class($this)) { + if (__CLASS__ !== \get_class($this)) { $r = new \ReflectionMethod($this, 'getTwigEnvironment'); if (__CLASS__ !== $r->getDeclaringClass()->getName()) { - @trigger_error(sprintf('Usage of method "%s" is deprecated since Symfony 3.4 and will no longer be supported in 4.0. Construct the command with its required arguments instead.', get_class($this).'::getTwigEnvironment'), E_USER_DEPRECATED); + @trigger_error(sprintf('Usage of method "%s" is deprecated since Symfony 3.4 and will no longer be supported in 4.0. Construct the command with its required arguments instead.', \get_class($this).'::getTwigEnvironment'), E_USER_DEPRECATED); $this->twig = $this->getTwigEnvironment(); } @@ -117,9 +119,9 @@ EOF $filenames = $input->getArgument('filename'); - if (0 === count($filenames)) { + if (0 === \count($filenames)) { if (0 !== ftell(STDIN)) { - throw new \RuntimeException('Please provide a filename or pipe template content to STDIN.'); + throw new RuntimeException('Please provide a filename or pipe template content to STDIN.'); } $template = ''; @@ -127,7 +129,7 @@ EOF $template .= fread(STDIN, 1024); } - return $this->display($input, $output, $io, array($this->validate($template, uniqid('sf_', true)))); + return $this->display($input, $output, $io, [$this->validate($template, uniqid('sf_', true))]); } $filesInfo = $this->getFilesInfo($filenames); @@ -137,7 +139,7 @@ EOF private function getFilesInfo(array $filenames) { - $filesInfo = array(); + $filesInfo = []; foreach ($filenames as $filename) { foreach ($this->findFiles($filename) as $file) { $filesInfo[] = $this->validate(file_get_contents($file), $file); @@ -150,19 +152,19 @@ EOF protected function findFiles($filename) { if (is_file($filename)) { - return array($filename); + return [$filename]; } elseif (is_dir($filename)) { return Finder::create()->files()->in($filename)->name('*.twig'); } - throw new \RuntimeException(sprintf('File or directory "%s" is not readable', $filename)); + throw new RuntimeException(sprintf('File or directory "%s" is not readable', $filename)); } private function validate($template, $file) { $realLoader = $this->twig->getLoader(); try { - $temporaryLoader = new ArrayLoader(array((string) $file => $template)); + $temporaryLoader = new ArrayLoader([(string) $file => $template]); $this->twig->setLoader($temporaryLoader); $nodeTree = $this->twig->parse($this->twig->tokenize(new Source($template, (string) $file))); $this->twig->compile($nodeTree); @@ -170,10 +172,10 @@ EOF } catch (Error $e) { $this->twig->setLoader($realLoader); - return array('template' => $template, 'file' => $file, 'line' => $e->getTemplateLine(), 'valid' => false, 'exception' => $e); + return ['template' => $template, 'file' => $file, 'line' => $e->getTemplateLine(), 'valid' => false, 'exception' => $e]; } - return array('template' => $template, 'file' => $file, 'valid' => true); + return ['template' => $template, 'file' => $file, 'valid' => true]; } private function display(InputInterface $input, OutputInterface $output, SymfonyStyle $io, $files) @@ -184,7 +186,7 @@ EOF case 'json': return $this->displayJson($output, $files); default: - throw new \InvalidArgumentException(sprintf('The format "%s" is not supported.', $input->getOption('format'))); + throw new InvalidArgumentException(sprintf('The format "%s" is not supported.', $input->getOption('format'))); } } @@ -202,9 +204,9 @@ EOF } if (0 === $errors) { - $io->success(sprintf('All %d Twig files contain valid syntax.', count($filesInfo))); + $io->success(sprintf('All %d Twig files contain valid syntax.', \count($filesInfo))); } else { - $io->warning(sprintf('%d Twig files have valid syntax and %d contain errors.', count($filesInfo) - $errors, $errors)); + $io->warning(sprintf('%d Twig files have valid syntax and %d contain errors.', \count($filesInfo) - $errors, $errors)); } return min($errors, 1); @@ -257,9 +259,9 @@ EOF $lines = explode("\n", $template); $position = max(0, $line - $context); - $max = min(count($lines), $line - 1 + $context); + $max = min(\count($lines), $line - 1 + $context); - $result = array(); + $result = []; while ($position < $max) { $result[$position + 1] = $lines[$position]; ++$position; diff --git a/vendor/symfony/twig-bridge/DataCollector/TwigDataCollector.php b/vendor/symfony/twig-bridge/DataCollector/TwigDataCollector.php index ee48f39b8fa91d5d0f20eb6f6a36e2ee4c7704c1..80e36e0491efce60303ce5065d36307c75f2e103 100644 --- a/vendor/symfony/twig-bridge/DataCollector/TwigDataCollector.php +++ b/vendor/symfony/twig-bridge/DataCollector/TwigDataCollector.php @@ -11,11 +11,12 @@ namespace Symfony\Bridge\Twig\DataCollector; -use Symfony\Component\HttpKernel\DataCollector\DataCollector; -use Symfony\Component\HttpKernel\DataCollector\LateDataCollectorInterface; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpKernel\DataCollector\DataCollector; +use Symfony\Component\HttpKernel\DataCollector\LateDataCollectorInterface; use Twig\Environment; +use Twig\Error\LoaderError; use Twig\Markup; use Twig\Profiler\Dumper\HtmlDumper; use Twig\Profiler\Profile; @@ -51,7 +52,7 @@ class TwigDataCollector extends DataCollector implements LateDataCollectorInterf { $this->profile->reset(); $this->computed = null; - $this->data = array(); + $this->data = []; } /** @@ -60,7 +61,7 @@ class TwigDataCollector extends DataCollector implements LateDataCollectorInterf public function lateCollect() { $this->data['profile'] = serialize($this->profile); - $this->data['template_paths'] = array(); + $this->data['template_paths'] = []; if (null === $this->twig) { return; @@ -70,7 +71,7 @@ class TwigDataCollector extends DataCollector implements LateDataCollectorInterf if ($profile->isTemplate()) { try { $template = $this->twig->load($name = $profile->getName()); - } catch (\Twig_Error_Loader $e) { + } catch (LoaderError $e) { $template = null; } @@ -122,15 +123,15 @@ class TwigDataCollector extends DataCollector implements LateDataCollectorInterf $dump = $dumper->dump($this->getProfile()); // needed to remove the hardcoded CSS styles - $dump = str_replace(array( + $dump = str_replace([ '<span style="background-color: #ffd">', '<span style="color: #d44">', '<span style="background-color: #dfd">', - ), array( + ], [ '<span class="status-warning">', '<span class="status-error">', '<span class="status-success">', - ), $dump); + ], $dump); return new Markup($dump, 'UTF-8'); } @@ -139,7 +140,7 @@ class TwigDataCollector extends DataCollector implements LateDataCollectorInterf { if (null === $this->profile) { if (\PHP_VERSION_ID >= 70000) { - $this->profile = unserialize($this->data['profile'], array('allowed_classes' => array('Twig_Profiler_Profile', 'Twig\Profiler\Profile'))); + $this->profile = unserialize($this->data['profile'], ['allowed_classes' => ['Twig_Profiler_Profile', 'Twig\Profiler\Profile']]); } else { $this->profile = unserialize($this->data['profile']); } @@ -159,13 +160,13 @@ class TwigDataCollector extends DataCollector implements LateDataCollectorInterf private function computeData(Profile $profile) { - $data = array( + $data = [ 'template_count' => 0, 'block_count' => 0, 'macro_count' => 0, - ); + ]; - $templates = array(); + $templates = []; foreach ($profile as $p) { $d = $this->computeData($p); diff --git a/vendor/symfony/twig-bridge/Extension/AssetExtension.php b/vendor/symfony/twig-bridge/Extension/AssetExtension.php index d5d70fb397f699a629908837178b3a4b50fbc367..cc2cdb268e5b5c614219b141a450039b1d9c0347 100644 --- a/vendor/symfony/twig-bridge/Extension/AssetExtension.php +++ b/vendor/symfony/twig-bridge/Extension/AssetExtension.php @@ -34,10 +34,10 @@ class AssetExtension extends AbstractExtension */ public function getFunctions() { - return array( - new TwigFunction('asset', array($this, 'getAssetUrl')), - new TwigFunction('asset_version', array($this, 'getAssetVersion')), - ); + return [ + new TwigFunction('asset', [$this, 'getAssetUrl']), + new TwigFunction('asset_version', [$this, 'getAssetVersion']), + ]; } /** diff --git a/vendor/symfony/twig-bridge/Extension/CodeExtension.php b/vendor/symfony/twig-bridge/Extension/CodeExtension.php index e47772481bdb7e1e6905b939ed6b17e50b4516c7..717d4de6979865f7eeabe369f0d38673e57def76 100644 --- a/vendor/symfony/twig-bridge/Extension/CodeExtension.php +++ b/vendor/symfony/twig-bridge/Extension/CodeExtension.php @@ -34,7 +34,7 @@ class CodeExtension extends AbstractExtension public function __construct($fileLinkFormat, $rootDir, $charset) { $this->fileLinkFormat = $fileLinkFormat ?: ini_get('xdebug.file_link_format') ?: get_cfg_var('xdebug.file_link_format'); - $this->rootDir = str_replace('/', DIRECTORY_SEPARATOR, dirname($rootDir)).DIRECTORY_SEPARATOR; + $this->rootDir = str_replace('/', \DIRECTORY_SEPARATOR, \dirname($rootDir)).\DIRECTORY_SEPARATOR; $this->charset = $charset; } @@ -43,17 +43,17 @@ class CodeExtension extends AbstractExtension */ public function getFilters() { - return array( - new TwigFilter('abbr_class', array($this, 'abbrClass'), array('is_safe' => array('html'))), - new TwigFilter('abbr_method', array($this, 'abbrMethod'), array('is_safe' => array('html'))), - new TwigFilter('format_args', array($this, 'formatArgs'), array('is_safe' => array('html'))), - new TwigFilter('format_args_as_text', array($this, 'formatArgsAsText')), - new TwigFilter('file_excerpt', array($this, 'fileExcerpt'), array('is_safe' => array('html'))), - new TwigFilter('format_file', array($this, 'formatFile'), array('is_safe' => array('html'))), - new TwigFilter('format_file_from_text', array($this, 'formatFileFromText'), array('is_safe' => array('html'))), - new TwigFilter('format_log_message', array($this, 'formatLogMessage'), array('is_safe' => array('html'))), - new TwigFilter('file_link', array($this, 'getFileLink')), - ); + return [ + new TwigFilter('abbr_class', [$this, 'abbrClass'], ['is_safe' => ['html']]), + new TwigFilter('abbr_method', [$this, 'abbrMethod'], ['is_safe' => ['html']]), + new TwigFilter('format_args', [$this, 'formatArgs'], ['is_safe' => ['html']]), + new TwigFilter('format_args_as_text', [$this, 'formatArgsAsText']), + new TwigFilter('file_excerpt', [$this, 'fileExcerpt'], ['is_safe' => ['html']]), + new TwigFilter('format_file', [$this, 'formatFile'], ['is_safe' => ['html']]), + new TwigFilter('format_file_from_text', [$this, 'formatFileFromText'], ['is_safe' => ['html']]), + new TwigFilter('format_log_message', [$this, 'formatLogMessage'], ['is_safe' => ['html']]), + new TwigFilter('file_link', [$this, 'getFileLink']), + ]; } public function abbrClass($class) @@ -87,14 +87,14 @@ class CodeExtension extends AbstractExtension */ public function formatArgs($args) { - $result = array(); + $result = []; foreach ($args as $key => $item) { if ('object' === $item[0]) { $parts = explode('\\', $item[1]); $short = array_pop($parts); $formattedValue = sprintf('<em>object</em>(<abbr title="%s">%s</abbr>)', $item[1], $short); } elseif ('array' === $item[0]) { - $formattedValue = sprintf('<em>array</em>(%s)', is_array($item[1]) ? $this->formatArgs($item[1]) : $item[1]); + $formattedValue = sprintf('<em>array</em>(%s)', \is_array($item[1]) ? $this->formatArgs($item[1]) : $item[1]); } elseif ('null' === $item[0]) { $formattedValue = '<em>null</em>'; } elseif ('boolean' === $item[0]) { @@ -105,7 +105,7 @@ class CodeExtension extends AbstractExtension $formattedValue = str_replace("\n", '', htmlspecialchars(var_export($item[1], true), ENT_COMPAT | ENT_SUBSTITUTE, $this->charset)); } - $result[] = is_int($key) ? $formattedValue : sprintf("'%s' => %s", $key, $formattedValue); + $result[] = \is_int($key) ? $formattedValue : sprintf("'%s' => %s", $key, $formattedValue); } return implode(', ', $result); @@ -134,9 +134,9 @@ class CodeExtension extends AbstractExtension */ public function fileExcerpt($file, $line, $srcContext = 3) { - if (is_readable($file)) { + if (is_file($file) && is_readable($file)) { // highlight_file could throw warnings - // see https://bugs.php.net/bug.php?id=25725 + // see https://bugs.php.net/25725 $code = @highlight_file($file, true); // remove main code/span tags $code = preg_replace('#^<code.*?>\s*<span.*?>(.*)</span>\s*</code>#s', '\\1', $code); @@ -146,17 +146,19 @@ class CodeExtension extends AbstractExtension }, $code); $content = explode('<br />', $code); - $lines = array(); + $lines = []; if (0 > $srcContext) { - $srcContext = count($content); + $srcContext = \count($content); } - for ($i = max($line - $srcContext, 1), $max = min($line + $srcContext, count($content)); $i <= $max; ++$i) { + for ($i = max($line - $srcContext, 1), $max = min($line + $srcContext, \count($content)); $i <= $max; ++$i) { $lines[] = '<li'.($i == $line ? ' class="selected"' : '').'><a class="anchor" name="line'.$i.'"></a><code>'.self::fixCodeMarkup($content[$i - 1]).'</code></li>'; } return '<ol start="'.max($line - $srcContext, 1).'">'.implode("\n", $lines).'</ol>'; } + + return null; } /** @@ -173,15 +175,17 @@ class CodeExtension extends AbstractExtension $file = trim($file); if (null === $text) { - $text = str_replace('/', DIRECTORY_SEPARATOR, $file); + $text = str_replace('/', \DIRECTORY_SEPARATOR, $file); if (0 === strpos($text, $this->rootDir)) { - $text = substr($text, strlen($this->rootDir)); - $text = explode(DIRECTORY_SEPARATOR, $text, 2); - $text = sprintf('<abbr title="%s%2$s">%s</abbr>%s', $this->rootDir, $text[0], isset($text[1]) ? DIRECTORY_SEPARATOR.$text[1] : ''); + $text = substr($text, \strlen($this->rootDir)); + $text = explode(\DIRECTORY_SEPARATOR, $text, 2); + $text = sprintf('<abbr title="%s%2$s">%s</abbr>%s', $this->rootDir, $text[0], isset($text[1]) ? \DIRECTORY_SEPARATOR.$text[1] : ''); } } - $text = "$text at line $line"; + if (0 < $line) { + $text .= ' at line '.$line; + } if (false !== $link = $this->getFileLink($file, $line)) { return sprintf('<a href="%s" title="Click to open this file" class="file_link">%s</a>', htmlspecialchars($link, ENT_COMPAT | ENT_SUBSTITUTE, $this->charset), $text); @@ -201,7 +205,7 @@ class CodeExtension extends AbstractExtension public function getFileLink($file, $line) { if ($fmt = $this->fileLinkFormat) { - return is_string($fmt) ? strtr($fmt, array('%f' => $file, '%l' => $line)) : $fmt->format($file, $line); + return \is_string($fmt) ? strtr($fmt, ['%f' => $file, '%l' => $line]) : $fmt->format($file, $line); } return false; @@ -220,7 +224,7 @@ class CodeExtension extends AbstractExtension public function formatLogMessage($message, array $context) { if ($context && false !== strpos($message, '{')) { - $replacements = array(); + $replacements = []; foreach ($context as $key => $val) { if (is_scalar($val)) { $replacements['{'.$key.'}'] = $val; @@ -259,6 +263,6 @@ class CodeExtension extends AbstractExtension $line .= '</span>'; } - return $line; + return trim($line); } } diff --git a/vendor/symfony/twig-bridge/Extension/DumpExtension.php b/vendor/symfony/twig-bridge/Extension/DumpExtension.php index 2cc3f1a4b04401c330ede912559256e45803209e..2be1056234d5f2d63ddf06ee19e336d336e4ba05 100644 --- a/vendor/symfony/twig-bridge/Extension/DumpExtension.php +++ b/vendor/symfony/twig-bridge/Extension/DumpExtension.php @@ -37,14 +37,14 @@ class DumpExtension extends AbstractExtension public function getFunctions() { - return array( - new TwigFunction('dump', array($this, 'dump'), array('is_safe' => array('html'), 'needs_context' => true, 'needs_environment' => true)), - ); + return [ + new TwigFunction('dump', [$this, 'dump'], ['is_safe' => ['html'], 'needs_context' => true, 'needs_environment' => true]), + ]; } public function getTokenParsers() { - return array(new DumpTokenParser()); + return [new DumpTokenParser()]; } public function getName() @@ -55,20 +55,20 @@ class DumpExtension extends AbstractExtension public function dump(Environment $env, $context) { if (!$env->isDebug()) { - return; + return null; } - if (2 === func_num_args()) { - $vars = array(); + if (2 === \func_num_args()) { + $vars = []; foreach ($context as $key => $value) { if (!$value instanceof Template) { $vars[$key] = $value; } } - $vars = array($vars); + $vars = [$vars]; } else { - $vars = func_get_args(); + $vars = \func_get_args(); unset($vars[0], $vars[1]); } diff --git a/vendor/symfony/twig-bridge/Extension/ExpressionExtension.php b/vendor/symfony/twig-bridge/Extension/ExpressionExtension.php index fc64fa3e3775d9ffac72e75895c3fef06dc3c671..21f6be4d6ec6d45940077800a8952cb06ddb0283 100644 --- a/vendor/symfony/twig-bridge/Extension/ExpressionExtension.php +++ b/vendor/symfony/twig-bridge/Extension/ExpressionExtension.php @@ -27,9 +27,9 @@ class ExpressionExtension extends AbstractExtension */ public function getFunctions() { - return array( - new TwigFunction('expression', array($this, 'createExpression')), - ); + return [ + new TwigFunction('expression', [$this, 'createExpression']), + ]; } public function createExpression($expression) diff --git a/vendor/symfony/twig-bridge/Extension/FormExtension.php b/vendor/symfony/twig-bridge/Extension/FormExtension.php index e63203f39bd5bdb2399e40ff832d4c582335f01b..1314e6544200f1e6259fa5e64c108506665116e5 100644 --- a/vendor/symfony/twig-bridge/Extension/FormExtension.php +++ b/vendor/symfony/twig-bridge/Extension/FormExtension.php @@ -11,14 +11,13 @@ namespace Symfony\Bridge\Twig\Extension; -use Symfony\Bridge\Twig\TokenParser\FormThemeTokenParser; use Symfony\Bridge\Twig\Form\TwigRendererInterface; +use Symfony\Bridge\Twig\TokenParser\FormThemeTokenParser; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\Form\ChoiceList\View\ChoiceView; use Symfony\Component\Form\FormView; use Twig\Environment; use Twig\Extension\AbstractExtension; -use Twig\Extension\InitRuntimeInterface; use Twig\TwigFilter; use Twig\TwigFunction; use Twig\TwigTest; @@ -40,8 +39,8 @@ class FormExtension extends AbstractExtension implements InitRuntimeInterface { if ($renderer instanceof TwigRendererInterface) { @trigger_error(sprintf('Passing a Twig Form Renderer to the "%s" constructor is deprecated since Symfony 3.2 and won\'t be possible in 4.0. Pass the Twig\Environment to the TwigRendererEngine constructor instead.', static::class), E_USER_DEPRECATED); - } elseif (null !== $renderer && !(is_array($renderer) && isset($renderer[0], $renderer[1]) && $renderer[0] instanceof ContainerInterface)) { - throw new \InvalidArgumentException(sprintf('Passing any arguments the constructor of %s is reserved for internal use.', __CLASS__)); + } elseif (null !== $renderer && !(\is_array($renderer) && isset($renderer[0], $renderer[1]) && $renderer[0] instanceof ContainerInterface)) { + throw new \InvalidArgumentException(sprintf('Passing any arguments to the constructor of %s is reserved for internal use.', __CLASS__)); } $this->renderer = $renderer; } @@ -55,7 +54,7 @@ class FormExtension extends AbstractExtension implements InitRuntimeInterface { if ($this->renderer instanceof TwigRendererInterface) { $this->renderer->setEnvironment($environment); - } elseif (is_array($this->renderer)) { + } elseif (\is_array($this->renderer)) { $this->renderer[2] = $environment; } } @@ -65,10 +64,10 @@ class FormExtension extends AbstractExtension implements InitRuntimeInterface */ public function getTokenParsers() { - return array( + return [ // {% form_theme form "SomeBundle::widgets.twig" %} new FormThemeTokenParser(), - ); + ]; } /** @@ -76,17 +75,17 @@ class FormExtension extends AbstractExtension implements InitRuntimeInterface */ public function getFunctions() { - return array( - new TwigFunction('form_widget', null, array('node_class' => 'Symfony\Bridge\Twig\Node\SearchAndRenderBlockNode', 'is_safe' => array('html'))), - new TwigFunction('form_errors', null, array('node_class' => 'Symfony\Bridge\Twig\Node\SearchAndRenderBlockNode', 'is_safe' => array('html'))), - new TwigFunction('form_label', null, array('node_class' => 'Symfony\Bridge\Twig\Node\SearchAndRenderBlockNode', 'is_safe' => array('html'))), - new TwigFunction('form_row', null, array('node_class' => 'Symfony\Bridge\Twig\Node\SearchAndRenderBlockNode', 'is_safe' => array('html'))), - new TwigFunction('form_rest', null, array('node_class' => 'Symfony\Bridge\Twig\Node\SearchAndRenderBlockNode', 'is_safe' => array('html'))), - new TwigFunction('form', null, array('node_class' => 'Symfony\Bridge\Twig\Node\RenderBlockNode', 'is_safe' => array('html'))), - new TwigFunction('form_start', null, array('node_class' => 'Symfony\Bridge\Twig\Node\RenderBlockNode', 'is_safe' => array('html'))), - new TwigFunction('form_end', null, array('node_class' => 'Symfony\Bridge\Twig\Node\RenderBlockNode', 'is_safe' => array('html'))), - new TwigFunction('csrf_token', array('Symfony\Component\Form\FormRenderer', 'renderCsrfToken')), - ); + return [ + new TwigFunction('form_widget', null, ['node_class' => 'Symfony\Bridge\Twig\Node\SearchAndRenderBlockNode', 'is_safe' => ['html']]), + new TwigFunction('form_errors', null, ['node_class' => 'Symfony\Bridge\Twig\Node\SearchAndRenderBlockNode', 'is_safe' => ['html']]), + new TwigFunction('form_label', null, ['node_class' => 'Symfony\Bridge\Twig\Node\SearchAndRenderBlockNode', 'is_safe' => ['html']]), + new TwigFunction('form_row', null, ['node_class' => 'Symfony\Bridge\Twig\Node\SearchAndRenderBlockNode', 'is_safe' => ['html']]), + new TwigFunction('form_rest', null, ['node_class' => 'Symfony\Bridge\Twig\Node\SearchAndRenderBlockNode', 'is_safe' => ['html']]), + new TwigFunction('form', null, ['node_class' => 'Symfony\Bridge\Twig\Node\RenderBlockNode', 'is_safe' => ['html']]), + new TwigFunction('form_start', null, ['node_class' => 'Symfony\Bridge\Twig\Node\RenderBlockNode', 'is_safe' => ['html']]), + new TwigFunction('form_end', null, ['node_class' => 'Symfony\Bridge\Twig\Node\RenderBlockNode', 'is_safe' => ['html']]), + new TwigFunction('csrf_token', ['Symfony\Component\Form\FormRenderer', 'renderCsrfToken']), + ]; } /** @@ -94,9 +93,10 @@ class FormExtension extends AbstractExtension implements InitRuntimeInterface */ public function getFilters() { - return array( - new TwigFilter('humanize', array('Symfony\Component\Form\FormRenderer', 'humanize')), - ); + return [ + new TwigFilter('humanize', ['Symfony\Component\Form\FormRenderer', 'humanize']), + new TwigFilter('form_encode_currency', ['Symfony\Component\Form\FormRenderer', 'encodeCurrency'], ['is_safe' => ['html'], 'needs_environment' => true]), + ]; } /** @@ -104,10 +104,10 @@ class FormExtension extends AbstractExtension implements InitRuntimeInterface */ public function getTests() { - return array( + return [ new TwigTest('selectedchoice', 'Symfony\Bridge\Twig\Extension\twig_is_selected_choice'), new TwigTest('rootform', 'Symfony\Bridge\Twig\Extension\twig_is_root_form'), - ); + ]; } /** @@ -118,7 +118,7 @@ class FormExtension extends AbstractExtension implements InitRuntimeInterface if ('renderer' === $name) { @trigger_error(sprintf('Using the "%s::$renderer" property is deprecated since Symfony 3.2 as it will be removed in 4.0.', __CLASS__), E_USER_DEPRECATED); - if (is_array($this->renderer)) { + if (\is_array($this->renderer)) { $renderer = $this->renderer[0]->get($this->renderer[1]); if (isset($this->renderer[2]) && $renderer instanceof TwigRendererInterface) { $renderer->setEnvironment($this->renderer[2]); @@ -188,8 +188,8 @@ class FormExtension extends AbstractExtension implements InitRuntimeInterface */ function twig_is_selected_choice(ChoiceView $choice, $selectedValue) { - if (is_array($selectedValue)) { - return in_array($choice->value, $selectedValue, true); + if (\is_array($selectedValue)) { + return \in_array($choice->value, $selectedValue, true); } return $choice->value === $selectedValue; diff --git a/vendor/symfony/twig-bridge/Extension/HttpFoundationExtension.php b/vendor/symfony/twig-bridge/Extension/HttpFoundationExtension.php index 0dad40cfa0a3f5c6127ec46abfd09d69208c70b5..82b9a92f7516c4173a826b8cbca41d363d8bb45a 100644 --- a/vendor/symfony/twig-bridge/Extension/HttpFoundationExtension.php +++ b/vendor/symfony/twig-bridge/Extension/HttpFoundationExtension.php @@ -11,8 +11,8 @@ namespace Symfony\Bridge\Twig\Extension; -use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\Routing\RequestContext; use Twig\Extension\AbstractExtension; use Twig\TwigFunction; @@ -38,10 +38,10 @@ class HttpFoundationExtension extends AbstractExtension */ public function getFunctions() { - return array( - new TwigFunction('absolute_url', array($this, 'generateAbsoluteUrl')), - new TwigFunction('relative_path', array($this, 'generateRelativePath')), - ); + return [ + new TwigFunction('absolute_url', [$this, 'generateAbsoluteUrl']), + new TwigFunction('relative_path', [$this, 'generateRelativePath']), + ]; } /** @@ -97,7 +97,7 @@ class HttpFoundationExtension extends AbstractExtension if (!$path || '/' !== $path[0]) { $prefix = $request->getPathInfo(); - $last = strlen($prefix) - 1; + $last = \strlen($prefix) - 1; if ($last !== $pos = strrpos($prefix, '/')) { $prefix = substr($prefix, 0, $pos).'/'; } diff --git a/vendor/symfony/twig-bridge/Extension/HttpKernelExtension.php b/vendor/symfony/twig-bridge/Extension/HttpKernelExtension.php index 45142e7402a671317aa8840225c60f304bd930c9..f8b93ada15475ea75e22c08b505ed7352b1b9c70 100644 --- a/vendor/symfony/twig-bridge/Extension/HttpKernelExtension.php +++ b/vendor/symfony/twig-bridge/Extension/HttpKernelExtension.php @@ -24,14 +24,14 @@ class HttpKernelExtension extends AbstractExtension { public function getFunctions() { - return array( - new TwigFunction('render', array(HttpKernelRuntime::class, 'renderFragment'), array('is_safe' => array('html'))), - new TwigFunction('render_*', array(HttpKernelRuntime::class, 'renderFragmentStrategy'), array('is_safe' => array('html'))), + return [ + new TwigFunction('render', [HttpKernelRuntime::class, 'renderFragment'], ['is_safe' => ['html']]), + new TwigFunction('render_*', [HttpKernelRuntime::class, 'renderFragmentStrategy'], ['is_safe' => ['html']]), new TwigFunction('controller', static::class.'::controller'), - ); + ]; } - public static function controller($controller, $attributes = array(), $query = array()) + public static function controller($controller, $attributes = [], $query = []) { return new ControllerReference($controller, $attributes, $query); } diff --git a/vendor/symfony/twig-bridge/Extension/HttpKernelRuntime.php b/vendor/symfony/twig-bridge/Extension/HttpKernelRuntime.php index 3c1f1a015e10f9a1aa14581d50c45ea68b4e3170..fcd7c24416fbe5e28fc670b3446d9b298a95edaf 100644 --- a/vendor/symfony/twig-bridge/Extension/HttpKernelRuntime.php +++ b/vendor/symfony/twig-bridge/Extension/HttpKernelRuntime.php @@ -11,8 +11,8 @@ namespace Symfony\Bridge\Twig\Extension; -use Symfony\Component\HttpKernel\Fragment\FragmentHandler; use Symfony\Component\HttpKernel\Controller\ControllerReference; +use Symfony\Component\HttpKernel\Fragment\FragmentHandler; /** * Provides integration with the HttpKernel component. @@ -38,7 +38,7 @@ class HttpKernelRuntime * * @see FragmentHandler::render() */ - public function renderFragment($uri, $options = array()) + public function renderFragment($uri, $options = []) { $strategy = isset($options['strategy']) ? $options['strategy'] : 'inline'; unset($options['strategy']); @@ -57,7 +57,7 @@ class HttpKernelRuntime * * @see FragmentHandler::render() */ - public function renderFragmentStrategy($strategy, $uri, $options = array()) + public function renderFragmentStrategy($strategy, $uri, $options = []) { return $this->handler->render($uri, $strategy, $options); } diff --git a/vendor/symfony/twig-bridge/Extension/InitRuntimeInterface.php b/vendor/symfony/twig-bridge/Extension/InitRuntimeInterface.php new file mode 100644 index 0000000000000000000000000000000000000000..5ba5e5570259347b9168a50fe3b9374dc545c919 --- /dev/null +++ b/vendor/symfony/twig-bridge/Extension/InitRuntimeInterface.php @@ -0,0 +1,23 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\Twig\Extension; + +use Twig\Extension\InitRuntimeInterface as TwigInitRuntimeInterface; + +/** + * @deprecated to be removed in 4.x + * + * @internal to be removed in 4.x + */ +interface InitRuntimeInterface extends TwigInitRuntimeInterface +{ +} diff --git a/vendor/symfony/twig-bridge/Extension/LogoutUrlExtension.php b/vendor/symfony/twig-bridge/Extension/LogoutUrlExtension.php index 17abb779899ac5b6cdb19797014fb53f68b06dfd..e8bc6190cd65ae5dfc8a820bedccceb3f6a282e5 100644 --- a/vendor/symfony/twig-bridge/Extension/LogoutUrlExtension.php +++ b/vendor/symfony/twig-bridge/Extension/LogoutUrlExtension.php @@ -34,10 +34,10 @@ class LogoutUrlExtension extends AbstractExtension */ public function getFunctions() { - return array( - new TwigFunction('logout_url', array($this, 'getLogoutUrl')), - new TwigFunction('logout_path', array($this, 'getLogoutPath')), - ); + return [ + new TwigFunction('logout_url', [$this, 'getLogoutUrl']), + new TwigFunction('logout_path', [$this, 'getLogoutPath']), + ]; } /** diff --git a/vendor/symfony/twig-bridge/Extension/RoutingExtension.php b/vendor/symfony/twig-bridge/Extension/RoutingExtension.php index 92a520eda3fb539ab76cfdce4642db301c7d9786..936c2d9985b66f89156ec056f8b88bc06510c03d 100644 --- a/vendor/symfony/twig-bridge/Extension/RoutingExtension.php +++ b/vendor/symfony/twig-bridge/Extension/RoutingExtension.php @@ -33,16 +33,14 @@ class RoutingExtension extends AbstractExtension } /** - * Returns a list of functions to add to the existing list. - * - * @return array An array of functions + * {@inheritdoc} */ public function getFunctions() { - return array( - new TwigFunction('url', array($this, 'getUrl'), array('is_safe_callback' => array($this, 'isUrlGenerationSafe'))), - new TwigFunction('path', array($this, 'getPath'), array('is_safe_callback' => array($this, 'isUrlGenerationSafe'))), - ); + return [ + new TwigFunction('url', [$this, 'getUrl'], ['is_safe_callback' => [$this, 'isUrlGenerationSafe']]), + new TwigFunction('path', [$this, 'getPath'], ['is_safe_callback' => [$this, 'isUrlGenerationSafe']]), + ]; } /** @@ -52,7 +50,7 @@ class RoutingExtension extends AbstractExtension * * @return string */ - public function getPath($name, $parameters = array(), $relative = false) + public function getPath($name, $parameters = [], $relative = false) { return $this->generator->generate($name, $parameters, $relative ? UrlGeneratorInterface::RELATIVE_PATH : UrlGeneratorInterface::ABSOLUTE_PATH); } @@ -64,7 +62,7 @@ class RoutingExtension extends AbstractExtension * * @return string */ - public function getUrl($name, $parameters = array(), $schemeRelative = false) + public function getUrl($name, $parameters = [], $schemeRelative = false) { return $this->generator->generate($name, $parameters, $schemeRelative ? UrlGeneratorInterface::NETWORK_PATH : UrlGeneratorInterface::ABSOLUTE_URL); } @@ -100,13 +98,13 @@ class RoutingExtension extends AbstractExtension $argsNode->hasNode(1) ? $argsNode->getNode(1) : null ); - if (null === $paramsNode || $paramsNode instanceof ArrayExpression && count($paramsNode) <= 2 && + if (null === $paramsNode || $paramsNode instanceof ArrayExpression && \count($paramsNode) <= 2 && (!$paramsNode->hasNode(1) || $paramsNode->getNode(1) instanceof ConstantExpression) ) { - return array('html'); + return ['html']; } - return array(); + return []; } /** diff --git a/vendor/symfony/twig-bridge/Extension/SecurityExtension.php b/vendor/symfony/twig-bridge/Extension/SecurityExtension.php index 193726a684371cacabb8d7c5d96636f392f26011..439c31aad3df26a5e3f29f18629213b523dcc549 100644 --- a/vendor/symfony/twig-bridge/Extension/SecurityExtension.php +++ b/vendor/symfony/twig-bridge/Extension/SecurityExtension.php @@ -53,9 +53,9 @@ class SecurityExtension extends AbstractExtension */ public function getFunctions() { - return array( - new TwigFunction('is_granted', array($this, 'isGranted')), - ); + return [ + new TwigFunction('is_granted', [$this, 'isGranted']), + ]; } /** diff --git a/vendor/symfony/twig-bridge/Extension/StopwatchExtension.php b/vendor/symfony/twig-bridge/Extension/StopwatchExtension.php index 48d99b8c7eac3c0d5e4e37e63dc5390be7fdef26..45b65d4e64d66cbaef2ba3c01e59a8866c6a57b3 100644 --- a/vendor/symfony/twig-bridge/Extension/StopwatchExtension.php +++ b/vendor/symfony/twig-bridge/Extension/StopwatchExtension.php @@ -11,8 +11,8 @@ namespace Symfony\Bridge\Twig\Extension; -use Symfony\Component\Stopwatch\Stopwatch; use Symfony\Bridge\Twig\TokenParser\StopwatchTokenParser; +use Symfony\Component\Stopwatch\Stopwatch; use Twig\Extension\AbstractExtension; /** @@ -38,14 +38,14 @@ class StopwatchExtension extends AbstractExtension public function getTokenParsers() { - return array( + return [ /* * {% stopwatch foo %} * Some stuff which will be recorded on the timeline * {% endstopwatch %} */ new StopwatchTokenParser(null !== $this->stopwatch && $this->enabled), - ); + ]; } public function getName() diff --git a/vendor/symfony/twig-bridge/Extension/TranslationExtension.php b/vendor/symfony/twig-bridge/Extension/TranslationExtension.php index f1131c52df61404bd1947cb7fc265b6538cebf98..4538f771981e775b7e97fb9c9657e948fd8e5c70 100644 --- a/vendor/symfony/twig-bridge/Extension/TranslationExtension.php +++ b/vendor/symfony/twig-bridge/Extension/TranslationExtension.php @@ -11,12 +11,12 @@ namespace Symfony\Bridge\Twig\Extension; -use Symfony\Bridge\Twig\TokenParser\TransTokenParser; +use Symfony\Bridge\Twig\NodeVisitor\TranslationDefaultDomainNodeVisitor; +use Symfony\Bridge\Twig\NodeVisitor\TranslationNodeVisitor; use Symfony\Bridge\Twig\TokenParser\TransChoiceTokenParser; use Symfony\Bridge\Twig\TokenParser\TransDefaultDomainTokenParser; +use Symfony\Bridge\Twig\TokenParser\TransTokenParser; use Symfony\Component\Translation\TranslatorInterface; -use Symfony\Bridge\Twig\NodeVisitor\TranslationNodeVisitor; -use Symfony\Bridge\Twig\NodeVisitor\TranslationDefaultDomainNodeVisitor; use Twig\Extension\AbstractExtension; use Twig\NodeVisitor\NodeVisitorInterface; use Twig\TokenParser\AbstractTokenParser; @@ -48,10 +48,10 @@ class TranslationExtension extends AbstractExtension */ public function getFilters() { - return array( - new TwigFilter('trans', array($this, 'trans')), - new TwigFilter('transchoice', array($this, 'transchoice')), - ); + return [ + new TwigFilter('trans', [$this, 'trans']), + new TwigFilter('transchoice', [$this, 'transchoice']), + ]; } /** @@ -61,7 +61,7 @@ class TranslationExtension extends AbstractExtension */ public function getTokenParsers() { - return array( + return [ // {% trans %}Symfony is great!{% endtrans %} new TransTokenParser(), @@ -72,7 +72,7 @@ class TranslationExtension extends AbstractExtension // {% trans_default_domain "foobar" %} new TransDefaultDomainTokenParser(), - ); + ]; } /** @@ -80,7 +80,7 @@ class TranslationExtension extends AbstractExtension */ public function getNodeVisitors() { - return array($this->getTranslationNodeVisitor(), new TranslationDefaultDomainNodeVisitor()); + return [$this->getTranslationNodeVisitor(), new TranslationDefaultDomainNodeVisitor()]; } public function getTranslationNodeVisitor() @@ -88,7 +88,7 @@ class TranslationExtension extends AbstractExtension return $this->translationNodeVisitor ?: $this->translationNodeVisitor = new TranslationNodeVisitor(); } - public function trans($message, array $arguments = array(), $domain = null, $locale = null) + public function trans($message, array $arguments = [], $domain = null, $locale = null) { if (null === $this->translator) { return strtr($message, $arguments); @@ -97,13 +97,13 @@ class TranslationExtension extends AbstractExtension return $this->translator->trans($message, $arguments, $domain, $locale); } - public function transchoice($message, $count, array $arguments = array(), $domain = null, $locale = null) + public function transchoice($message, $count, array $arguments = [], $domain = null, $locale = null) { if (null === $this->translator) { return strtr($message, $arguments); } - return $this->translator->transChoice($message, $count, array_merge(array('%count%' => $count), $arguments), $domain, $locale); + return $this->translator->transChoice($message, $count, array_merge(['%count%' => $count], $arguments), $domain, $locale); } /** diff --git a/vendor/symfony/twig-bridge/Extension/WebLinkExtension.php b/vendor/symfony/twig-bridge/Extension/WebLinkExtension.php index 3d90c3bf21c7449749468385966994664f17088c..0ca519ee72423ecb7970a3c2b558443967317eb2 100644 --- a/vendor/symfony/twig-bridge/Extension/WebLinkExtension.php +++ b/vendor/symfony/twig-bridge/Extension/WebLinkExtension.php @@ -36,14 +36,14 @@ class WebLinkExtension extends AbstractExtension */ public function getFunctions() { - return array( - new TwigFunction('link', array($this, 'link')), - new TwigFunction('preload', array($this, 'preload')), - new TwigFunction('dns_prefetch', array($this, 'dnsPrefetch')), - new TwigFunction('preconnect', array($this, 'preconnect')), - new TwigFunction('prefetch', array($this, 'prefetch')), - new TwigFunction('prerender', array($this, 'prerender')), - ); + return [ + new TwigFunction('link', [$this, 'link']), + new TwigFunction('preload', [$this, 'preload']), + new TwigFunction('dns_prefetch', [$this, 'dnsPrefetch']), + new TwigFunction('preconnect', [$this, 'preconnect']), + new TwigFunction('prefetch', [$this, 'prefetch']), + new TwigFunction('prerender', [$this, 'prerender']), + ]; } /** @@ -51,11 +51,11 @@ class WebLinkExtension extends AbstractExtension * * @param string $uri The relation URI * @param string $rel The relation type (e.g. "preload", "prefetch", "prerender" or "dns-prefetch") - * @param array $attributes The attributes of this link (e.g. "array('as' => true)", "array('pr' => 0.5)") + * @param array $attributes The attributes of this link (e.g. "['as' => true]", "['pr' => 0.5]") * * @return string The relation URI */ - public function link($uri, $rel, array $attributes = array()) + public function link($uri, $rel, array $attributes = []) { if (!$request = $this->requestStack->getMasterRequest()) { return $uri; @@ -76,11 +76,11 @@ class WebLinkExtension extends AbstractExtension * Preloads a resource. * * @param string $uri A public path - * @param array $attributes The attributes of this link (e.g. "array('as' => true)", "array('crossorigin' => 'use-credentials')") + * @param array $attributes The attributes of this link (e.g. "['as' => true]", "['crossorigin' => 'use-credentials']") * * @return string The path of the asset */ - public function preload($uri, array $attributes = array()) + public function preload($uri, array $attributes = []) { return $this->link($uri, 'preload', $attributes); } @@ -89,11 +89,11 @@ class WebLinkExtension extends AbstractExtension * Resolves a resource origin as early as possible. * * @param string $uri A public path - * @param array $attributes The attributes of this link (e.g. "array('as' => true)", "array('pr' => 0.5)") + * @param array $attributes The attributes of this link (e.g. "['as' => true]", "['pr' => 0.5]") * * @return string The path of the asset */ - public function dnsPrefetch($uri, array $attributes = array()) + public function dnsPrefetch($uri, array $attributes = []) { return $this->link($uri, 'dns-prefetch', $attributes); } @@ -102,11 +102,11 @@ class WebLinkExtension extends AbstractExtension * Initiates a early connection to a resource (DNS resolution, TCP handshake, TLS negotiation). * * @param string $uri A public path - * @param array $attributes The attributes of this link (e.g. "array('as' => true)", "array('pr' => 0.5)") + * @param array $attributes The attributes of this link (e.g. "['as' => true]", "['pr' => 0.5]") * * @return string The path of the asset */ - public function preconnect($uri, array $attributes = array()) + public function preconnect($uri, array $attributes = []) { return $this->link($uri, 'preconnect', $attributes); } @@ -115,11 +115,11 @@ class WebLinkExtension extends AbstractExtension * Indicates to the client that it should prefetch this resource. * * @param string $uri A public path - * @param array $attributes The attributes of this link (e.g. "array('as' => true)", "array('pr' => 0.5)") + * @param array $attributes The attributes of this link (e.g. "['as' => true]", "['pr' => 0.5]") * * @return string The path of the asset */ - public function prefetch($uri, array $attributes = array()) + public function prefetch($uri, array $attributes = []) { return $this->link($uri, 'prefetch', $attributes); } @@ -128,11 +128,11 @@ class WebLinkExtension extends AbstractExtension * Indicates to the client that it should prerender this resource . * * @param string $uri A public path - * @param array $attributes The attributes of this link (e.g. "array('as' => true)", "array('pr' => 0.5)") + * @param array $attributes The attributes of this link (e.g. "['as' => true]", "['pr' => 0.5]") * * @return string The path of the asset */ - public function prerender($uri, array $attributes = array()) + public function prerender($uri, array $attributes = []) { return $this->link($uri, 'prerender', $attributes); } diff --git a/vendor/symfony/twig-bridge/Extension/WorkflowExtension.php b/vendor/symfony/twig-bridge/Extension/WorkflowExtension.php index 54c12f16d4cb5b4157fc633c8fa08b11c75e70ba..6ff5fad9c0313b67757d75953887d473c13dbe79 100644 --- a/vendor/symfony/twig-bridge/Extension/WorkflowExtension.php +++ b/vendor/symfony/twig-bridge/Extension/WorkflowExtension.php @@ -32,12 +32,12 @@ class WorkflowExtension extends AbstractExtension public function getFunctions() { - return array( - new TwigFunction('workflow_can', array($this, 'canTransition')), - new TwigFunction('workflow_transitions', array($this, 'getEnabledTransitions')), - new TwigFunction('workflow_has_marked_place', array($this, 'hasMarkedPlace')), - new TwigFunction('workflow_marked_places', array($this, 'getMarkedPlaces')), - ); + return [ + new TwigFunction('workflow_can', [$this, 'canTransition']), + new TwigFunction('workflow_transitions', [$this, 'getEnabledTransitions']), + new TwigFunction('workflow_has_marked_place', [$this, 'hasMarkedPlace']), + new TwigFunction('workflow_marked_places', [$this, 'getMarkedPlaces']), + ]; } /** diff --git a/vendor/symfony/twig-bridge/Extension/YamlExtension.php b/vendor/symfony/twig-bridge/Extension/YamlExtension.php index 164b5383e7407875636d1392301e4c4c2b6d1c53..bb8d5a12bd62e8dfdee8288320a34786a7f6bc46 100644 --- a/vendor/symfony/twig-bridge/Extension/YamlExtension.php +++ b/vendor/symfony/twig-bridge/Extension/YamlExtension.php @@ -28,10 +28,10 @@ class YamlExtension extends AbstractExtension */ public function getFilters() { - return array( - new TwigFilter('yaml_encode', array($this, 'encode')), - new TwigFilter('yaml_dump', array($this, 'dump')), - ); + return [ + new TwigFilter('yaml_encode', [$this, 'encode']), + new TwigFilter('yaml_dump', [$this, 'dump']), + ]; } public function encode($input, $inline = 0, $dumpObjects = 0) @@ -42,8 +42,8 @@ class YamlExtension extends AbstractExtension $dumper = new YamlDumper(); } - if (defined('Symfony\Component\Yaml\Yaml::DUMP_OBJECT')) { - if (is_bool($dumpObjects)) { + if (\defined('Symfony\Component\Yaml\Yaml::DUMP_OBJECT')) { + if (\is_bool($dumpObjects)) { @trigger_error('Passing a boolean flag to toggle object support is deprecated since Symfony 3.1 and will be removed in 4.0. Use the Yaml::DUMP_OBJECT flag instead.', E_USER_DEPRECATED); $flags = $dumpObjects ? Yaml::DUMP_OBJECT : 0; @@ -59,12 +59,12 @@ class YamlExtension extends AbstractExtension public function dump($value, $inline = 0, $dumpObjects = false) { - if (is_resource($value)) { + if (\is_resource($value)) { return '%Resource%'; } - if (is_array($value) || is_object($value)) { - return '%'.gettype($value).'% '.$this->encode($value, $inline, $dumpObjects); + if (\is_array($value) || \is_object($value)) { + return '%'.\gettype($value).'% '.$this->encode($value, $inline, $dumpObjects); } return $this->encode($value, $inline, $dumpObjects); diff --git a/vendor/symfony/twig-bridge/Form/TwigRendererEngine.php b/vendor/symfony/twig-bridge/Form/TwigRendererEngine.php index 711291db2f752b0a058a3d720f12b42af8672407..73e7bc4c887e3c485eb6ef02e854d6a9fa82498f 100644 --- a/vendor/symfony/twig-bridge/Form/TwigRendererEngine.php +++ b/vendor/symfony/twig-bridge/Form/TwigRendererEngine.php @@ -31,7 +31,7 @@ class TwigRendererEngine extends AbstractRendererEngine implements TwigRendererE */ private $template; - public function __construct(array $defaultThemes = array(), Environment $environment = null) + public function __construct(array $defaultThemes = [], Environment $environment = null) { if (null === $environment) { @trigger_error(sprintf('Not passing a Twig Environment as the second argument for "%s" constructor is deprecated since Symfony 3.2 and won\'t be possible in 4.0.', static::class), E_USER_DEPRECATED); @@ -58,7 +58,7 @@ class TwigRendererEngine extends AbstractRendererEngine implements TwigRendererE /** * {@inheritdoc} */ - public function renderBlock(FormView $view, $resource, $blockName, array $variables = array()) + public function renderBlock(FormView $view, $resource, $blockName, array $variables = []) { $cacheKey = $view->vars[self::CACHE_KEY_VAR]; @@ -116,7 +116,7 @@ class TwigRendererEngine extends AbstractRendererEngine implements TwigRendererE // Check each theme whether it contains the searched block if (isset($this->themes[$cacheKey])) { - for ($i = count($this->themes[$cacheKey]) - 1; $i >= 0; --$i) { + for ($i = \count($this->themes[$cacheKey]) - 1; $i >= 0; --$i) { $this->loadResourcesFromTheme($cacheKey, $this->themes[$cacheKey][$i]); // CONTINUE LOADING (see doc comment) } @@ -125,7 +125,7 @@ class TwigRendererEngine extends AbstractRendererEngine implements TwigRendererE // Check the default themes once we reach the root view without success if (!$view->parent) { if (!isset($this->useDefaultThemes[$cacheKey]) || $this->useDefaultThemes[$cacheKey]) { - for ($i = count($this->defaultThemes) - 1; $i >= 0; --$i) { + for ($i = \count($this->defaultThemes) - 1; $i >= 0; --$i) { $this->loadResourcesFromTheme($cacheKey, $this->defaultThemes[$i]); // CONTINUE LOADING (see doc comment) } @@ -187,7 +187,7 @@ class TwigRendererEngine extends AbstractRendererEngine implements TwigRendererE // theme is a reference and we don't want to change it. $currentTheme = $theme; - $context = $this->environment->mergeGlobals(array()); + $context = $this->environment->mergeGlobals([]); // The do loop takes care of template inheritance. // Add blocks from all templates in the inheritance tree, but avoid diff --git a/vendor/symfony/twig-bridge/LICENSE b/vendor/symfony/twig-bridge/LICENSE index 21d7fb9e2f29b50caca3a76f0647e94e2cc8ddc1..a677f43763ca467472898351b328aee41e2edd7c 100644 --- a/vendor/symfony/twig-bridge/LICENSE +++ b/vendor/symfony/twig-bridge/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-2018 Fabien Potencier +Copyright (c) 2004-2019 Fabien Potencier Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/vendor/symfony/twig-bridge/Node/DumpNode.php b/vendor/symfony/twig-bridge/Node/DumpNode.php index d820d75cc7db9e064c53b248653c3557937bde01..387f826434f2db4debd400f32ac72adf306339dd 100644 --- a/vendor/symfony/twig-bridge/Node/DumpNode.php +++ b/vendor/symfony/twig-bridge/Node/DumpNode.php @@ -23,12 +23,12 @@ class DumpNode extends Node public function __construct($varPrefix, Node $values = null, $lineno, $tag = null) { - $nodes = array(); + $nodes = []; if (null !== $values) { $nodes['values'] = $values; } - parent::__construct($nodes, array(), $lineno, $tag); + parent::__construct($nodes, [], $lineno, $tag); $this->varPrefix = $varPrefix; } @@ -44,7 +44,7 @@ class DumpNode extends Node if (!$this->hasNode('values')) { // remove embedded templates (macros) from the context $compiler - ->write(sprintf('$%svars = array();'."\n", $this->varPrefix)) + ->write(sprintf('$%svars = [];'."\n", $this->varPrefix)) ->write(sprintf('foreach ($context as $%1$skey => $%1$sval) {'."\n", $this->varPrefix)) ->indent() ->write(sprintf('if (!$%sval instanceof \Twig\Template) {'."\n", $this->varPrefix)) @@ -65,7 +65,7 @@ class DumpNode extends Node } else { $compiler ->addDebugInfo($this) - ->write('\Symfony\Component\VarDumper\VarDumper::dump(array('."\n") + ->write('\Symfony\Component\VarDumper\VarDumper::dump(['."\n") ->indent(); foreach ($values as $node) { $compiler->write(''); @@ -80,7 +80,7 @@ class DumpNode extends Node } $compiler ->outdent() - ->write("));\n"); + ->write("]);\n"); } $compiler diff --git a/vendor/symfony/twig-bridge/Node/FormThemeNode.php b/vendor/symfony/twig-bridge/Node/FormThemeNode.php index 8fcd9380a620a7d81b2bf1bc32ed07b5d8ee4c49..2ab4c35a3fb153664e44253f7031c13d54ffacda 100644 --- a/vendor/symfony/twig-bridge/Node/FormThemeNode.php +++ b/vendor/symfony/twig-bridge/Node/FormThemeNode.php @@ -24,7 +24,7 @@ class FormThemeNode extends Node { public function __construct(Node $form, Node $resources, $lineno, $tag = null, $only = false) { - parent::__construct(array('form' => $form, 'resources' => $resources), array('only' => (bool) $only), $lineno, $tag); + parent::__construct(['form' => $form, 'resources' => $resources], ['only' => (bool) $only], $lineno, $tag); } public function compile(Compiler $compiler) diff --git a/vendor/symfony/twig-bridge/Node/SearchAndRenderBlockNode.php b/vendor/symfony/twig-bridge/Node/SearchAndRenderBlockNode.php index 224e1d60e0aada7923f7f384fd91d8f5a79e02b8..612bec14e532928654b952526e59f7435548fe6b 100644 --- a/vendor/symfony/twig-bridge/Node/SearchAndRenderBlockNode.php +++ b/vendor/symfony/twig-bridge/Node/SearchAndRenderBlockNode.php @@ -53,7 +53,7 @@ class SearchAndRenderBlockNode extends FunctionExpression // Only insert the label into the array if it is not empty if (!twig_test_empty($label->getAttribute('value'))) { $originalVariables = $variables; - $variables = new ArrayExpression(array(), $lineno); + $variables = new ArrayExpression([], $lineno); $labelKey = new ConstantExpression('label', $lineno); if (null !== $originalVariables) { @@ -100,7 +100,7 @@ class SearchAndRenderBlockNode extends FunctionExpression // If not, add it to the array at runtime. $compiler->raw('(twig_test_empty($_label_ = '); $compiler->subcompile($label); - $compiler->raw(') ? array() : array("label" => $_label_))'); + $compiler->raw(') ? [] : ["label" => $_label_])'); } } } diff --git a/vendor/symfony/twig-bridge/Node/StopwatchNode.php b/vendor/symfony/twig-bridge/Node/StopwatchNode.php index fac770c2499bacbe03e1056a64121c6b0a489820..538c22bb792389d04445ad2b107a2efd6b61cdfb 100644 --- a/vendor/symfony/twig-bridge/Node/StopwatchNode.php +++ b/vendor/symfony/twig-bridge/Node/StopwatchNode.php @@ -24,7 +24,7 @@ class StopwatchNode extends Node { public function __construct(Node $name, Node $body, AssignNameExpression $var, $lineno = 0, $tag = null) { - parent::__construct(array('body' => $body, 'name' => $name, 'var' => $var), array(), $lineno, $tag); + parent::__construct(['body' => $body, 'name' => $name, 'var' => $var], [], $lineno, $tag); } public function compile(Compiler $compiler) diff --git a/vendor/symfony/twig-bridge/Node/TransDefaultDomainNode.php b/vendor/symfony/twig-bridge/Node/TransDefaultDomainNode.php index c9c82b33e541c3c7edaddb08c9a3cf0e2ad73a86..294718ba1f1faead4b842af275de6ce6b4aa3477 100644 --- a/vendor/symfony/twig-bridge/Node/TransDefaultDomainNode.php +++ b/vendor/symfony/twig-bridge/Node/TransDefaultDomainNode.php @@ -22,7 +22,7 @@ class TransDefaultDomainNode extends Node { public function __construct(AbstractExpression $expr, $lineno = 0, $tag = null) { - parent::__construct(array('expr' => $expr), array(), $lineno, $tag); + parent::__construct(['expr' => $expr], [], $lineno, $tag); } public function compile(Compiler $compiler) diff --git a/vendor/symfony/twig-bridge/Node/TransNode.php b/vendor/symfony/twig-bridge/Node/TransNode.php index 020810f7b7c55d4013c637476a70d568ffbde68d..1b02b9c3d7da1b6e8bbdce6dd84d5d62960b6d2e 100644 --- a/vendor/symfony/twig-bridge/Node/TransNode.php +++ b/vendor/symfony/twig-bridge/Node/TransNode.php @@ -29,7 +29,7 @@ class TransNode extends Node { public function __construct(Node $body, Node $domain = null, AbstractExpression $count = null, AbstractExpression $vars = null, AbstractExpression $locale = null, $lineno = 0, $tag = null) { - $nodes = array('body' => $body); + $nodes = ['body' => $body]; if (null !== $domain) { $nodes['domain'] = $domain; } @@ -43,14 +43,14 @@ class TransNode extends Node $nodes['locale'] = $locale; } - parent::__construct($nodes, array(), $lineno, $tag); + parent::__construct($nodes, [], $lineno, $tag); } public function compile(Compiler $compiler) { $compiler->addDebugInfo($this); - $defaults = new ArrayExpression(array(), -1); + $defaults = new ArrayExpression([], -1); if ($this->hasNode('vars') && ($vars = $this->getNode('vars')) instanceof ArrayExpression) { $defaults = $this->getNode('vars'); $vars = null; @@ -109,7 +109,7 @@ class TransNode extends Node } elseif ($body instanceof TextNode) { $msg = $body->getAttribute('data'); } else { - return array($body, $vars); + return [$body, $vars]; } preg_match_all('/(?<!%)%([^%]+)%/', $msg, $matches); @@ -127,6 +127,6 @@ class TransNode extends Node } } - return array(new ConstantExpression(str_replace('%%', '%', trim($msg)), $body->getTemplateLine()), $vars); + return [new ConstantExpression(str_replace('%%', '%', trim($msg)), $body->getTemplateLine()), $vars]; } } diff --git a/vendor/symfony/twig-bridge/NodeVisitor/Scope.php b/vendor/symfony/twig-bridge/NodeVisitor/Scope.php index 1c3451bbebf460a5da5d744dfaa85564a5b45216..642623f2a693ce900e7a5ea20b8592ece828330e 100644 --- a/vendor/symfony/twig-bridge/NodeVisitor/Scope.php +++ b/vendor/symfony/twig-bridge/NodeVisitor/Scope.php @@ -17,10 +17,10 @@ namespace Symfony\Bridge\Twig\NodeVisitor; class Scope { private $parent; - private $data = array(); + private $data = []; private $left = false; - public function __construct(Scope $parent = null) + public function __construct(self $parent = null) { $this->parent = $parent; } @@ -77,7 +77,7 @@ class Scope */ public function has($key) { - if (array_key_exists($key, $this->data)) { + if (\array_key_exists($key, $this->data)) { return true; } @@ -98,7 +98,7 @@ class Scope */ public function get($key, $default = null) { - if (array_key_exists($key, $this->data)) { + if (\array_key_exists($key, $this->data)) { return $this->data[$key]; } diff --git a/vendor/symfony/twig-bridge/NodeVisitor/TranslationDefaultDomainNodeVisitor.php b/vendor/symfony/twig-bridge/NodeVisitor/TranslationDefaultDomainNodeVisitor.php index 1a60e67a2f945ead0503d0a786ffbdb67f647b89..be08d0d1d13041e2495bce2f03bcb6da1fb04e53 100644 --- a/vendor/symfony/twig-bridge/NodeVisitor/TranslationDefaultDomainNodeVisitor.php +++ b/vendor/symfony/twig-bridge/NodeVisitor/TranslationDefaultDomainNodeVisitor.php @@ -11,8 +11,8 @@ namespace Symfony\Bridge\Twig\NodeVisitor; -use Symfony\Bridge\Twig\Node\TransNode; use Symfony\Bridge\Twig\Node\TransDefaultDomainNode; +use Symfony\Bridge\Twig\Node\TransNode; use Twig\Environment; use Twig\Node\BlockNode; use Twig\Node\Expression\ArrayExpression; @@ -56,7 +56,7 @@ class TranslationDefaultDomainNodeVisitor extends AbstractNodeVisitor $name = new AssignNameExpression($var, $node->getTemplateLine()); $this->scope->set('domain', new NameExpression($var, $node->getTemplateLine())); - return new SetNode(false, new Node(array($name)), new Node(array($node->getNode('expr'))), $node->getTemplateLine()); + return new SetNode(false, new Node([$name]), new Node([$node->getNode('expr')]), $node->getTemplateLine()); } } @@ -64,7 +64,7 @@ class TranslationDefaultDomainNodeVisitor extends AbstractNodeVisitor return $node; } - if ($node instanceof FilterExpression && in_array($node->getNode('filter')->getAttribute('value'), array('trans', 'transchoice'))) { + if ($node instanceof FilterExpression && \in_array($node->getNode('filter')->getAttribute('value'), ['trans', 'transchoice'])) { $arguments = $node->getNode('arguments'); $ind = 'trans' === $node->getNode('filter')->getAttribute('value') ? 1 : 2; if ($this->isNamedArguments($arguments)) { @@ -74,7 +74,7 @@ class TranslationDefaultDomainNodeVisitor extends AbstractNodeVisitor } else { if (!$arguments->hasNode($ind)) { if (!$arguments->hasNode($ind - 1)) { - $arguments->setNode($ind - 1, new ArrayExpression(array(), $node->getTemplateLine())); + $arguments->setNode($ind - 1, new ArrayExpression([], $node->getTemplateLine())); } $arguments->setNode($ind, $this->scope->get('domain')); @@ -95,7 +95,7 @@ class TranslationDefaultDomainNodeVisitor extends AbstractNodeVisitor protected function doLeaveNode(Node $node, Environment $env) { if ($node instanceof TransDefaultDomainNode) { - return false; + return null; } if ($node instanceof BlockNode || $node instanceof ModuleNode) { @@ -107,6 +107,8 @@ class TranslationDefaultDomainNodeVisitor extends AbstractNodeVisitor /** * {@inheritdoc} + * + * @return int */ public function getPriority() { @@ -119,7 +121,7 @@ class TranslationDefaultDomainNodeVisitor extends AbstractNodeVisitor private function isNamedArguments($arguments) { foreach ($arguments as $name => $node) { - if (!is_int($name)) { + if (!\is_int($name)) { return true; } } diff --git a/vendor/symfony/twig-bridge/NodeVisitor/TranslationNodeVisitor.php b/vendor/symfony/twig-bridge/NodeVisitor/TranslationNodeVisitor.php index 1fbce9c6af811ffa374784e4ea14445de34097d1..1a399ce8ba3d413afebd4c7018c4c6fa47837bee 100644 --- a/vendor/symfony/twig-bridge/NodeVisitor/TranslationNodeVisitor.php +++ b/vendor/symfony/twig-bridge/NodeVisitor/TranslationNodeVisitor.php @@ -28,18 +28,18 @@ class TranslationNodeVisitor extends AbstractNodeVisitor const UNDEFINED_DOMAIN = '_undefined'; private $enabled = false; - private $messages = array(); + private $messages = []; public function enable() { $this->enabled = true; - $this->messages = array(); + $this->messages = []; } public function disable() { $this->enabled = false; - $this->messages = array(); + $this->messages = []; } public function getMessages() @@ -62,26 +62,26 @@ class TranslationNodeVisitor extends AbstractNodeVisitor $node->getNode('node') instanceof ConstantExpression ) { // extract constant nodes with a trans filter - $this->messages[] = array( + $this->messages[] = [ $node->getNode('node')->getAttribute('value'), $this->getReadDomainFromArguments($node->getNode('arguments'), 1), - ); + ]; } elseif ( $node instanceof FilterExpression && 'transchoice' === $node->getNode('filter')->getAttribute('value') && $node->getNode('node') instanceof ConstantExpression ) { // extract constant nodes with a trans filter - $this->messages[] = array( + $this->messages[] = [ $node->getNode('node')->getAttribute('value'), $this->getReadDomainFromArguments($node->getNode('arguments'), 2), - ); + ]; } elseif ($node instanceof TransNode) { // extract trans nodes - $this->messages[] = array( + $this->messages[] = [ $node->getNode('body')->getAttribute('data'), $node->hasNode('domain') ? $this->getReadDomainFromNode($node->getNode('domain')) : null, - ); + ]; } return $node; @@ -97,6 +97,8 @@ class TranslationNodeVisitor extends AbstractNodeVisitor /** * {@inheritdoc} + * + * @return int */ public function getPriority() { @@ -104,8 +106,7 @@ class TranslationNodeVisitor extends AbstractNodeVisitor } /** - * @param Node $arguments - * @param int $index + * @param int $index * * @return string|null */ @@ -116,7 +117,7 @@ class TranslationNodeVisitor extends AbstractNodeVisitor } elseif ($arguments->hasNode($index)) { $argument = $arguments->getNode($index); } else { - return; + return null; } return $this->getReadDomainFromNode($argument); diff --git a/vendor/symfony/twig-bridge/README.md b/vendor/symfony/twig-bridge/README.md index eb084147c37f852261a9348bafeeb53ea29d96ff..602f5a54c3dd608568a56e13257887cba558c745 100644 --- a/vendor/symfony/twig-bridge/README.md +++ b/vendor/symfony/twig-bridge/README.md @@ -1,7 +1,7 @@ Twig Bridge =========== -Provides integration for [Twig](http://twig.sensiolabs.org/) with various +Provides integration for [Twig](https://twig.symfony.com/) with various Symfony components. Resources diff --git a/vendor/symfony/twig-bridge/Resources/views/Form/bootstrap_3_horizontal_layout.html.twig b/vendor/symfony/twig-bridge/Resources/views/Form/bootstrap_3_horizontal_layout.html.twig index f0c4626daf45ea66055f25c030fd917e7d27d7c4..d6b08f76375c48dcfca25bf4620c82c7eac4bf78 100644 --- a/vendor/symfony/twig-bridge/Resources/views/Form/bootstrap_3_horizontal_layout.html.twig +++ b/vendor/symfony/twig-bridge/Resources/views/Form/bootstrap_3_horizontal_layout.html.twig @@ -62,4 +62,4 @@ col-sm-10 {{- form_errors(form) -}} </div>{#--#} </div> -{%- endblock checkbox_row %} \ No newline at end of file +{%- endblock checkbox_row %} diff --git a/vendor/symfony/twig-bridge/Resources/views/Form/bootstrap_3_layout.html.twig b/vendor/symfony/twig-bridge/Resources/views/Form/bootstrap_3_layout.html.twig index 0e198aa517cae23bc03a926b088c3c226c71ce18..708e149bce82be433b7900993f49312715a9912c 100644 --- a/vendor/symfony/twig-bridge/Resources/views/Form/bootstrap_3_layout.html.twig +++ b/vendor/symfony/twig-bridge/Resources/views/Form/bootstrap_3_layout.html.twig @@ -14,6 +14,24 @@ {{- parent() -}} {%- endblock button_widget %} +{% block money_widget -%} + {% set prepend = not (money_pattern starts with '{{') %} + {% set append = not (money_pattern ends with '}}') %} + {% if prepend or append %} + <div class="input-group"> + {% if prepend %} + <span class="input-group-addon">{{ money_pattern|form_encode_currency }}</span> + {% endif %} + {{- block('form_widget_simple') -}} + {% if append %} + <span class="input-group-addon">{{ money_pattern|form_encode_currency }}</span> + {% endif %} + </div> + {% else %} + {{- block('form_widget_simple') -}} + {% endif %} +{%- endblock money_widget %} + {% block checkbox_widget -%} {%- set parent_label_class = parent_label_class|default(label_attr.class|default('')) -%} {% if 'checkbox-inline' in parent_label_class %} @@ -80,7 +98,7 @@ {% set label = name|humanize %} {%- endif -%} {%- endif -%} - <label{% for attrname, attrvalue in label_attr %} {{ attrname }}="{{ attrvalue }}"{% endfor %}> + <label{% with { attr: label_attr } %}{{ block('attributes') }}{% endwith %}> {{- widget|raw }} {{ label is not same as(false) ? (translation_domain is same as(false) ? label : label|trans({}, translation_domain)) -}} </label> {%- endif -%} @@ -90,10 +108,10 @@ {% block form_row -%} <div class="form-group{% if (not compound or force_error|default(false)) and not valid %} has-error{% endif %}"> - {{- form_label(form) -}} - {{- form_widget(form) -}} - {{- form_errors(form) -}} - </div> + {{- form_label(form) }} {# -#} + {{ form_widget(form) }} {# -#} + {{ form_errors(form) }} {# -#} + </div> {# -#} {%- endblock form_row %} {% block button_row -%} diff --git a/vendor/symfony/twig-bridge/Resources/views/Form/bootstrap_4_horizontal_layout.html.twig b/vendor/symfony/twig-bridge/Resources/views/Form/bootstrap_4_horizontal_layout.html.twig index e236d12cb709a84d97b0d9e8dcfeb742570a14e8..e23e6f8a29d09ce51d32b1d29dd02e6063b36b43 100644 --- a/vendor/symfony/twig-bridge/Resources/views/Form/bootstrap_4_horizontal_layout.html.twig +++ b/vendor/symfony/twig-bridge/Resources/views/Form/bootstrap_4_horizontal_layout.html.twig @@ -28,7 +28,6 @@ col-sm-2 {{- form_label(form) -}} <div class="{{ block('form_group_class') }}"> {{- form_widget(form) -}} - {{- form_errors(form) -}} </div> {##}</div> {%- endif -%} @@ -40,7 +39,6 @@ col-sm-2 {{- form_label(form) -}} <div class="{{ block('form_group_class') }}"> {{- form_widget(form) -}} - {{- form_errors(form) -}} </div> </div> {##}</fieldset> diff --git a/vendor/symfony/twig-bridge/Resources/views/Form/bootstrap_4_layout.html.twig b/vendor/symfony/twig-bridge/Resources/views/Form/bootstrap_4_layout.html.twig index 15413f1c9a0fea7ff521a26e23ba5aa4ba35aef6..b13d7ed9cacdf47b469e3f73d4f6712bf6b38838 100644 --- a/vendor/symfony/twig-bridge/Resources/views/Form/bootstrap_4_layout.html.twig +++ b/vendor/symfony/twig-bridge/Resources/views/Form/bootstrap_4_layout.html.twig @@ -3,11 +3,25 @@ {# Widgets #} {% block money_widget -%} - {% if not valid %} - {% set group_class = ' form-control is-invalid' %} - {% set valid = true %} - {% endif %} - {{- parent() -}} + {%- set prepend = not (money_pattern starts with '{{') -%} + {%- set append = not (money_pattern ends with '}}') -%} + {%- if prepend or append -%} + <div class="input-group{{ group_class|default('') }}"> + {%- if prepend -%} + <div class="input-group-prepend"> + <span class="input-group-text">{{ money_pattern|form_encode_currency }}</span> + </div> + {%- endif -%} + {{- block('form_widget_simple') -}} + {%- if append -%} + <div class="input-group-append"> + <span class="input-group-text">{{ money_pattern|form_encode_currency }}</span> + </div> + {%- endif -%} + </div> + {%- else -%} + {{- block('form_widget_simple') -}} + {%- endif -%} {%- endblock money_widget %} {% block datetime_widget -%} @@ -39,14 +53,64 @@ {% set attr = attr|merge({class: (attr.class|default('') ~ ' form-control is-invalid')|trim}) -%} {% set valid = true %} {%- endif -%} - {{- parent() -}} + {%- if widget == 'single_text' -%} + {{- block('form_widget_simple') -}} + {%- else -%} + {%- set attr = attr|merge({class: (attr.class|default('') ~ ' form-inline')|trim}) -%} + <div {{ block('widget_container_attributes') }}> + {%- if with_years -%} + <div class="col-auto"> + {{ form_label(form.years) }} + {{ form_widget(form.years) }} + </div> + {%- endif -%} + {%- if with_months -%} + <div class="col-auto"> + {{ form_label(form.months) }} + {{ form_widget(form.months) }} + </div> + {%- endif -%} + {%- if with_weeks -%} + <div class="col-auto"> + {{ form_label(form.weeks) }} + {{ form_widget(form.weeks) }} + </div> + {%- endif -%} + {%- if with_days -%} + <div class="col-auto"> + {{ form_label(form.days) }} + {{ form_widget(form.days) }} + </div> + {%- endif -%} + {%- if with_hours -%} + <div class="col-auto"> + {{ form_label(form.hours) }} + {{ form_widget(form.hours) }} + </div> + {%- endif -%} + {%- if with_minutes -%} + <div class="col-auto"> + {{ form_label(form.minutes) }} + {{ form_widget(form.minutes) }} + </div> + {%- endif -%} + {%- if with_seconds -%} + <div class="col-auto"> + {{ form_label(form.seconds) }} + {{ form_widget(form.seconds) }} + </div> + {%- endif -%} + {%- if with_invert %}{{ form_widget(form.invert) }}{% endif -%} + </div> + {%- endif -%} {%- endblock dateinterval_widget %} {% block percent_widget -%} - <div class="input-group{{ not valid ? ' form-control is-invalid' }}"> - {% set valid = true %} + <div class="input-group"> {{- block('form_widget_simple') -}} - <span class="input-group-addon">%</span> + <div class="input-group-append"> + <span class="input-group-text">%</span> + </div> </div> {%- endblock percent_widget %} @@ -54,12 +118,16 @@ {% if type is not defined or type != 'hidden' %} {%- set attr = attr|merge({class: (attr.class|default('') ~ ' form-control' ~ (type|default('') == 'file' ? '-file' : ''))|trim}) -%} {% endif %} + {%- if type is defined and (type == 'range' or type == 'color') %} + {# Attribute "required" is not supported #} + {%- set required = false -%} + {% endif %} {{- parent() -}} {%- endblock form_widget_simple %} {%- block widget_attributes -%} {%- if not valid %} - {% set attr = attr|merge({class: (attr.class|default('') ~ ' form-control is-invalid')|trim}) %} + {% set attr = attr|merge({class: (attr.class|default('') ~ ' is-invalid')|trim}) %} {% endif -%} {{ parent() }} {%- endblock widget_attributes -%} @@ -69,17 +137,21 @@ {{- parent() -}} {%- endblock button_widget %} +{% block submit_widget -%} + {%- set attr = attr|merge({class: (attr.class|default('btn-primary'))|trim}) -%} + {{- parent() -}} +{%- endblock submit_widget %} + {% block checkbox_widget -%} {%- set parent_label_class = parent_label_class|default(label_attr.class|default('')) -%} - {%- set attr = attr|merge({class: (attr.class|default('') ~ ' form-check-input')|trim}) -%} - {% if 'checkbox-inline' in parent_label_class %} - {{- form_label(form, null, { widget: parent() }) -}} - {% elseif 'form-check-inline' in parent_label_class %} - <div class="form-check{{ not valid ? ' form-control is-invalid' }} form-check-inline"> + {%- if 'checkbox-custom' in parent_label_class -%} + {%- set attr = attr|merge({class: (attr.class|default('') ~ ' custom-control-input')|trim}) -%} + <div class="custom-control custom-checkbox{{ 'checkbox-inline' in parent_label_class ? ' custom-control-inline' }}"> {{- form_label(form, null, { widget: parent() }) -}} </div> - {% else -%} - <div class="form-check{{ not valid ? ' form-control is-invalid' }}"> + {%- else -%} + {%- set attr = attr|merge({class: (attr.class|default('') ~ ' form-check-input')|trim}) -%} + <div class="form-check{{ 'checkbox-inline' in parent_label_class ? ' form-check-inline' }}"> {{- form_label(form, null, { widget: parent() }) -}} </div> {%- endif -%} @@ -87,18 +159,21 @@ {% block radio_widget -%} {%- set parent_label_class = parent_label_class|default(label_attr.class|default('')) -%} - {%- set attr = attr|merge({class: (attr.class|default('') ~ ' form-check-input')|trim}) -%} - {%- if 'radio-inline' in parent_label_class -%} - {{- form_label(form, null, { widget: parent() }) -}} + {%- if 'radio-custom' in parent_label_class -%} + {%- set attr = attr|merge({class: (attr.class|default('') ~ ' custom-control-input')|trim}) -%} + <div class="custom-control custom-radio{{ 'radio-inline' in parent_label_class ? ' custom-control-inline' }}"> + {{- form_label(form, null, { widget: parent() }) -}} + </div> {%- else -%} - <div class="form-check{{ not valid ? ' form-control is-invalid' }}"> + {%- set attr = attr|merge({class: (attr.class|default('') ~ ' form-check-input')|trim}) -%} + <div class="form-check{{ 'radio-inline' in parent_label_class ? ' form-check-inline' }}"> {{- form_label(form, null, { widget: parent() }) -}} </div> {%- endif -%} {%- endblock radio_widget %} {% block choice_widget_expanded -%} - {% if '-inline' in label_attr.class|default('') -%} + <div {{ block('widget_container_attributes') }}> {%- for child in form %} {{- form_widget(child, { parent_label_class: label_attr.class|default(''), @@ -106,43 +181,60 @@ valid: valid, }) -}} {% endfor -%} - {%- else -%} - {%- if not valid -%} - {%- set attr = attr|merge({class: (attr.class|default('') ~ ' form-control is-invalid')|trim}) %} - {%- endif -%} - <div {{ block('widget_container_attributes') }}> - {%- for child in form %} - {{- form_widget(child, { - parent_label_class: label_attr.class|default(''), - translation_domain: choice_translation_domain, - valid: true, - }) -}} - {% endfor -%} - </div> - {%- endif %} + </div> {%- endblock choice_widget_expanded %} {# Labels #} {% block form_label -%} - {%- if compound is defined and compound -%} - {%- set element = 'legend' -%} - {%- set label_attr = label_attr|merge({class: (label_attr.class|default('') ~ ' col-form-legend')|trim}) -%} + {% if label is not same as(false) -%} + {%- if compound is defined and compound -%} + {%- set element = 'legend' -%} + {%- set label_attr = label_attr|merge({class: (label_attr.class|default('') ~ ' col-form-label')|trim}) -%} + {%- else -%} + {%- set label_attr = label_attr|merge({for: id}) -%} + {%- endif -%} + {% if required -%} + {% set label_attr = label_attr|merge({class: (label_attr.class|default('') ~ ' required')|trim}) %} + {%- endif -%} + {% if label is empty -%} + {%- if label_format is not empty -%} + {% set label = label_format|replace({ + '%name%': name, + '%id%': id, + }) %} + {%- else -%} + {% set label = name|humanize %} + {%- endif -%} + {%- endif -%} + <{{ element|default('label') }}{% if label_attr %}{% with { attr: label_attr } %}{{ block('attributes') }}{% endwith %}{% endif %}>{{ translation_domain is same as(false) ? label : label|trans({}, translation_domain) }}{% block form_label_errors %}{{- form_errors(form) -}}{% endblock form_label_errors %}</{{ element|default('label') }}> {%- else -%} - {%- set label_attr = label_attr|merge({class: (label_attr.class|default('') ~ ' form-control-label')|trim}) -%} + {%- if errors|length > 0 -%} + <div id="{{ id }}_errors" class="mb-2"> + {{- form_errors(form) -}} + </div> + {%- endif -%} {%- endif -%} - {{- parent() -}} {%- endblock form_label %} {% block checkbox_radio_label -%} {#- Do not display the label if widget is not defined in order to prevent double label rendering -#} {%- if widget is defined -%} - {%- set label_attr = label_attr|merge({class: (label_attr.class|default('') ~ ' form-check-label')|trim}) -%} + {% set is_parent_custom = parent_label_class is defined and ('checkbox-custom' in parent_label_class or 'radio-custom' in parent_label_class) %} + {% set is_custom = label_attr.class is defined and ('checkbox-custom' in label_attr.class or 'radio-custom' in label_attr.class) %} + {%- if is_parent_custom or is_custom -%} + {%- set label_attr = label_attr|merge({class: (label_attr.class|default('') ~ ' custom-control-label')|trim}) -%} + {%- else %} + {%- set label_attr = label_attr|merge({class: (label_attr.class|default('') ~ ' form-check-label')|trim}) -%} + {%- endif %} + {%- if not compound -%} + {% set label_attr = label_attr|merge({'for': id}) %} + {%- endif -%} {%- if required -%} {%- set label_attr = label_attr|merge({class: (label_attr.class|default('') ~ ' required')|trim}) -%} {%- endif -%} {%- if parent_label_class is defined -%} - {%- set label_attr = label_attr|merge({class: (label_attr.class|default('') ~ ' ' ~ parent_label_class)|trim}) -%} + {%- set label_attr = label_attr|merge({class: (label_attr.class|default('') ~ ' ' ~ parent_label_class)|replace({'checkbox-inline': '', 'radio-inline': '', 'checkbox-custom': '', 'radio-custom': ''})|trim}) -%} {%- endif -%} {%- if label is not same as(false) and label is empty -%} {%- if label_format is not empty -%} @@ -154,8 +246,11 @@ {%- set label = name|humanize -%} {%- endif -%} {%- endif -%} - <label{% for attrname, attrvalue in label_attr %} {{ attrname }}="{{ attrvalue }}"{% endfor %}> - {{- widget|raw }} {{ label is not same as(false) ? (translation_domain is same as(false) ? label : label|trans({}, translation_domain)) -}} + + {{ widget|raw }} + <label{% with { attr: label_attr } %}{{ block('attributes') }}{% endwith %}> + {{- label is not same as(false) ? (translation_domain is same as(false) ? label : label|trans({}, translation_domain)) -}} + {{- form_errors(form) -}} </label> {%- endif -%} {%- endblock checkbox_radio_label %} @@ -169,7 +264,6 @@ <{{ element|default('div') }} class="form-group"> {{- form_label(form) -}} {{- form_widget(form) -}} - {{- form_errors(form) -}} </{{ element|default('div') }}> {%- endblock form_row %} @@ -177,12 +271,12 @@ {% block form_errors -%} {%- if errors|length > 0 -%} - <div class="{% if form is not rootform %}invalid-feedback{% else %}alert alert-danger{% endif %}"> - <ul class="list-unstyled mb-0"> + <span class="{% if form is not rootform %}invalid-feedback{% else %}alert alert-danger{% endif %} d-block"> {%- for error in errors -%} - <li>{{ error.message }}</li> + <span class="d-block"> + <span class="form-error-icon badge badge-danger text-uppercase">{{ 'Error'|trans({}, 'validators') }}</span> <span class="form-error-message">{{ error.message }}</span> + </span> {%- endfor -%} - </ul> - </div> + </span> {%- endif %} {%- endblock form_errors %} diff --git a/vendor/symfony/twig-bridge/Resources/views/Form/bootstrap_base_layout.html.twig b/vendor/symfony/twig-bridge/Resources/views/Form/bootstrap_base_layout.html.twig index d57978220f330bac1e2f8f9ae3bfdf243111e2a1..2630803573ec73dca44135cf639ba04222c253f8 100644 --- a/vendor/symfony/twig-bridge/Resources/views/Form/bootstrap_base_layout.html.twig +++ b/vendor/symfony/twig-bridge/Resources/views/Form/bootstrap_base_layout.html.twig @@ -13,11 +13,11 @@ {% if prepend or append %} <div class="input-group{{ group_class|default('') }}"> {% if prepend %} - <span class="input-group-addon">{{ money_pattern|replace({ '{{ widget }}':''}) }}</span> + <span class="input-group-addon">{{ money_pattern|form_encode_currency }}</span> {% endif %} {{- block('form_widget_simple') -}} {% if append %} - <span class="input-group-addon">{{ money_pattern|replace({ '{{ widget }}':''}) }}</span> + <span class="input-group-addon">{{ money_pattern|form_encode_currency }}</span> {% endif %} </div> {% else %} @@ -40,6 +40,16 @@ <div {{ block('widget_container_attributes') }}> {{- form_errors(form.date) -}} {{- form_errors(form.time) -}} + + <div class="sr-only"> + {%- if form.date.year is defined %}{{ form_label(form.date.year) }}{% endif -%} + {%- if form.date.month is defined %}{{ form_label(form.date.month) }}{% endif -%} + {%- if form.date.day is defined %}{{ form_label(form.date.day) }}{% endif -%} + {%- if form.time.hour is defined %}{{ form_label(form.time.hour) }}{% endif -%} + {%- if form.time.minute is defined %}{{ form_label(form.time.minute) }}{% endif -%} + {%- if form.time.second is defined %}{{ form_label(form.time.second) }}{% endif -%} + </div> + {{- form_widget(form.date, { datetime: true } ) -}} {{- form_widget(form.time, { datetime: true } ) -}} </div> @@ -54,6 +64,12 @@ {%- if datetime is not defined or not datetime -%} <div {{ block('widget_container_attributes') -}}> {%- endif %} + <div class="sr-only"> + {{ form_label(form.year) }} + {{ form_label(form.month) }} + {{ form_label(form.day) }} + </div> + {{- date_pattern|replace({ '{{ year }}': form_widget(form.year), '{{ month }}': form_widget(form.month), @@ -73,7 +89,10 @@ {%- if datetime is not defined or false == datetime -%} <div {{ block('widget_container_attributes') -}}> {%- endif -%} - {{- form_widget(form.hour) }}{% if with_minutes %}:{{ form_widget(form.minute) }}{% endif %}{% if with_seconds %}:{{ form_widget(form.second) }}{% endif %} + <div class="sr-only">{{ form_label(form.hour) }}</div> + {{- form_widget(form.hour) -}} + {%- if with_minutes -%}:<div class="sr-only">{{ form_label(form.minute) }}</div>{{ form_widget(form.minute) }}{%- endif -%} + {%- if with_seconds -%}:<div class="sr-only">{{ form_label(form.second) }}</div>{{ form_widget(form.second) }}{%- endif -%} {%- if datetime is not defined or false == datetime -%} </div> {%- endif -%} @@ -88,7 +107,7 @@ <div {{ block('widget_container_attributes') }}> {{- form_errors(form) -}} <div class="table-responsive"> - <table class="table {{ table_class|default('table-bordered table-condensed table-striped') }}"> + <table class="table {{ table_class|default('table-bordered table-condensed table-striped') }}" role="presentation"> <thead> <tr> {%- if with_years %}<th>{{ form_label(form.years) }}</th>{% endif -%} @@ -147,7 +166,7 @@ {% block choice_label -%} {# remove the checkbox-inline and radio-inline class, it's only useful for embed labels #} - {%- set label_attr = label_attr|merge({class: label_attr.class|default('')|replace({'checkbox-inline': '', 'radio-inline': ''})|trim}) -%} + {%- set label_attr = label_attr|merge({class: label_attr.class|default('')|replace({'checkbox-inline': '', 'radio-inline': '', 'checkbox-custom': '', 'radio-custom': ''})|trim}) -%} {{- block('form_label') -}} {% endblock choice_label %} diff --git a/vendor/symfony/twig-bridge/Resources/views/Form/form_div_layout.html.twig b/vendor/symfony/twig-bridge/Resources/views/Form/form_div_layout.html.twig index f85aad1c68b9a8dfac5f01d96a43d46010a1ef0b..ad4477cba5dea2c63c64d0b3e904d83c435de31b 100644 --- a/vendor/symfony/twig-bridge/Resources/views/Form/form_div_layout.html.twig +++ b/vendor/symfony/twig-bridge/Resources/views/Form/form_div_layout.html.twig @@ -24,7 +24,7 @@ {%- endblock form_widget_compound -%} {%- block collection_widget -%} - {% if prototype is defined %} + {% if prototype is defined and not prototype.rendered %} {%- set attr = attr|merge({'data-prototype': form_row(prototype) }) -%} {% endif %} {{- block('form_widget') -}} @@ -136,7 +136,7 @@ {%- else -%} <div {{ block('widget_container_attributes') }}> {{- form_errors(form) -}} - <table class="{{ table_class|default('') }}"> + <table class="{{ table_class|default('') }}" role="presentation"> <thead> <tr> {%- if with_years %}<th>{{ form_label(form.years) }}</th>{% endif -%} @@ -177,7 +177,7 @@ {%- endblock integer_widget -%} {%- block money_widget -%} - {{ money_pattern|replace({ '{{ widget }}': block('form_widget_simple') })|raw }} + {{ money_pattern|form_encode_currency(block('form_widget_simple')) }} {%- endblock money_widget -%} {%- block url_widget -%} @@ -271,7 +271,13 @@ {% set label = name|humanize %} {%- endif -%} {%- endif -%} - <{{ element|default('label') }}{% if label_attr %}{% with { attr: label_attr } %}{{ block('attributes') }}{% endwith %}{% endif %}>{{ translation_domain is same as(false) ? label : label|trans({}, translation_domain) }}</{{ element|default('label') }}> + <{{ element|default('label') }}{% if label_attr %}{% with { attr: label_attr } %}{{ block('attributes') }}{% endwith %}{% endif %}> + {%- if translation_domain is same as(false) -%} + {{- label -}} + {%- else -%} + {{- label|trans({}, translation_domain) -}} + {%- endif -%} + </{{ element|default('label') }}> {%- endif -%} {%- endblock form_label -%} @@ -321,7 +327,7 @@ {%- else -%} {% set form_method = "POST" %} {%- endif -%} - <form name="{{ name }}" method="{{ form_method|lower }}"{% if action != '' %} action="{{ action }}"{% endif %}{% for attrname, attrvalue in attr %} {{ attrname }}="{{ attrvalue }}"{% endfor %}{% if multipart %} enctype="multipart/form-data"{% endif %}> + <form{% if name != '' %} name="{{ name }}"{% endif %} method="{{ form_method|lower }}"{% if action != '' %} action="{{ action }}"{% endif %}{{ block('attributes') }}{% if multipart %} enctype="multipart/form-data"{% endif %}> {%- if form_method != method -%} <input type="hidden" name="_method" value="{{ method }}" /> {%- endif -%} diff --git a/vendor/symfony/twig-bridge/Resources/views/Form/foundation_5_layout.html.twig b/vendor/symfony/twig-bridge/Resources/views/Form/foundation_5_layout.html.twig index 3035689cc9dffc388d99ba4a12f62085969d4046..7876be3e43391425524f75ace0f94d44ceda19ee 100644 --- a/vendor/symfony/twig-bridge/Resources/views/Form/foundation_5_layout.html.twig +++ b/vendor/symfony/twig-bridge/Resources/views/Form/foundation_5_layout.html.twig @@ -27,7 +27,7 @@ {% set prepend = '{{' == money_pattern[0:2] %} {% if not prepend %} <div class="small-3 large-2 columns"> - <span class="prefix">{{ money_pattern|replace({ '{{ widget }}':''}) }}</span> + <span class="prefix">{{ money_pattern|form_encode_currency }}</span> </div> {% endif %} <div class="small-9 large-10 columns"> @@ -35,7 +35,7 @@ </div> {% if prepend %} <div class="small-3 large-2 columns"> - <span class="postfix">{{ money_pattern|replace({ '{{ widget }}':''}) }}</span> + <span class="postfix">{{ money_pattern|form_encode_currency }}</span> </div> {% endif %} </div> @@ -258,7 +258,7 @@ {% set label = name|humanize %} {%- endif -%} {% endif %} - <label{% for attrname, attrvalue in label_attr %} {{ attrname }}="{{ attrvalue }}"{% endfor %}> + <label{% with { attr: label_attr } %}{{ block('attributes') }}{% endwith %}> {{ widget|raw }} {{ translation_domain is same as(false) ? label : label|trans({}, translation_domain) }} </label> diff --git a/vendor/symfony/twig-bridge/Tests/AppVariableTest.php b/vendor/symfony/twig-bridge/Tests/AppVariableTest.php index 27eca0c44a74ac27ad8d7c63198f85dfb2b37d90..4a3f04fddef18580e25f0645402e92de3cc6ac2f 100644 --- a/vendor/symfony/twig-bridge/Tests/AppVariableTest.php +++ b/vendor/symfony/twig-bridge/Tests/AppVariableTest.php @@ -32,10 +32,10 @@ class AppVariableTest extends TestCase public function debugDataProvider() { - return array( - 'debug on' => array(true), - 'debug off' => array(false), - ); + return [ + 'debug on' => [true], + 'debug off' => [false], + ]; } public function testEnvironment() @@ -114,51 +114,39 @@ class AppVariableTest extends TestCase $this->assertNull($this->appVariable->getUser()); } - /** - * @expectedException \RuntimeException - */ public function testEnvironmentNotSet() { + $this->expectException('RuntimeException'); $this->appVariable->getEnvironment(); } - /** - * @expectedException \RuntimeException - */ public function testDebugNotSet() { + $this->expectException('RuntimeException'); $this->appVariable->getDebug(); } - /** - * @expectedException \RuntimeException - */ public function testGetTokenWithTokenStorageNotSet() { + $this->expectException('RuntimeException'); $this->appVariable->getToken(); } - /** - * @expectedException \RuntimeException - */ public function testGetUserWithTokenStorageNotSet() { + $this->expectException('RuntimeException'); $this->appVariable->getUser(); } - /** - * @expectedException \RuntimeException - */ public function testGetRequestWithRequestStackNotSet() { + $this->expectException('RuntimeException'); $this->appVariable->getRequest(); } - /** - * @expectedException \RuntimeException - */ public function testGetSessionWithRequestStackNotSet() { + $this->expectException('RuntimeException'); $this->appVariable->getSession(); } @@ -166,7 +154,7 @@ class AppVariableTest extends TestCase { $this->setRequestStack(null); - $this->assertEquals(array(), $this->appVariable->getFlashes()); + $this->assertEquals([], $this->appVariable->getFlashes()); } /** @@ -190,15 +178,15 @@ class AppVariableTest extends TestCase $this->assertEquals($flashMessages, $this->appVariable->getFlashes('')); $flashMessages = $this->setFlashMessages(); - $this->assertEquals($flashMessages, $this->appVariable->getFlashes(array())); + $this->assertEquals($flashMessages, $this->appVariable->getFlashes([])); $flashMessages = $this->setFlashMessages(); - $this->assertEquals(array(), $this->appVariable->getFlashes('this-does-not-exist')); + $this->assertEquals([], $this->appVariable->getFlashes('this-does-not-exist')); $flashMessages = $this->setFlashMessages(); $this->assertEquals( - array('this-does-not-exist' => array()), - $this->appVariable->getFlashes(array('this-does-not-exist')) + ['this-does-not-exist' => []], + $this->appVariable->getFlashes(['this-does-not-exist']) ); $flashMessages = $this->setFlashMessages(); @@ -206,31 +194,31 @@ class AppVariableTest extends TestCase $flashMessages = $this->setFlashMessages(); $this->assertEquals( - array('notice' => $flashMessages['notice']), - $this->appVariable->getFlashes(array('notice')) + ['notice' => $flashMessages['notice']], + $this->appVariable->getFlashes(['notice']) ); $flashMessages = $this->setFlashMessages(); $this->assertEquals( - array('notice' => $flashMessages['notice'], 'this-does-not-exist' => array()), - $this->appVariable->getFlashes(array('notice', 'this-does-not-exist')) + ['notice' => $flashMessages['notice'], 'this-does-not-exist' => []], + $this->appVariable->getFlashes(['notice', 'this-does-not-exist']) ); $flashMessages = $this->setFlashMessages(); $this->assertEquals( - array('notice' => $flashMessages['notice'], 'error' => $flashMessages['error']), - $this->appVariable->getFlashes(array('notice', 'error')) + ['notice' => $flashMessages['notice'], 'error' => $flashMessages['error']], + $this->appVariable->getFlashes(['notice', 'error']) ); $this->assertEquals( - array('warning' => $flashMessages['warning']), - $this->appVariable->getFlashes(array('warning')), + ['warning' => $flashMessages['warning']], + $this->appVariable->getFlashes(['warning']), 'After getting some flash types (e.g. "notice" and "error"), the rest of flash messages must remain (e.g. "warning").' ); $this->assertEquals( - array('this-does-not-exist' => array()), - $this->appVariable->getFlashes(array('this-does-not-exist')) + ['this-does-not-exist' => []], + $this->appVariable->getFlashes(['this-does-not-exist']) ); } @@ -255,11 +243,11 @@ class AppVariableTest extends TestCase private function setFlashMessages($sessionHasStarted = true) { - $flashMessages = array( - 'notice' => array('Notice #1 message'), - 'warning' => array('Warning #1 message'), - 'error' => array('Error #1 message', 'Error #2 message'), - ); + $flashMessages = [ + 'notice' => ['Notice #1 message'], + 'warning' => ['Warning #1 message'], + 'error' => ['Error #1 message', 'Error #2 message'], + ]; $flashBag = new FlashBag(); $flashBag->initialize($flashMessages); diff --git a/vendor/symfony/twig-bridge/Tests/Command/DebugCommandTest.php b/vendor/symfony/twig-bridge/Tests/Command/DebugCommandTest.php new file mode 100644 index 0000000000000000000000000000000000000000..7eb96018a355bded2f6bc083b468d934b7d5da02 --- /dev/null +++ b/vendor/symfony/twig-bridge/Tests/Command/DebugCommandTest.php @@ -0,0 +1,125 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\Twig\Tests\Command; + +use PHPUnit\Framework\TestCase; +use Symfony\Bridge\Twig\Command\DebugCommand; +use Symfony\Component\Console\Application; +use Symfony\Component\Console\Tester\CommandTester; +use Twig\Environment; +use Twig\Loader\FilesystemLoader; + +class DebugCommandTest extends TestCase +{ + public function testDebugCommand() + { + $tester = $this->createCommandTester(); + $ret = $tester->execute([], ['decorated' => false]); + + $this->assertEquals(0, $ret, 'Returns 0 in case of success'); + $this->assertStringContainsString('Functions', trim($tester->getDisplay())); + } + + public function testLineSeparatorInLoaderPaths() + { + // these paths aren't realistic, + // they're configured to force the line separator + $tester = $this->createCommandTester([ + 'Acme' => ['extractor', 'extractor'], + '!Acme' => ['extractor', 'extractor'], + FilesystemLoader::MAIN_NAMESPACE => ['extractor', 'extractor'], + ]); + $ret = $tester->execute([], ['decorated' => false]); + $ds = \DIRECTORY_SEPARATOR; + $loaderPaths = <<<TXT +Loader Paths +------------ + + ----------- ------------ + Namespace Paths + ----------- ------------ + @Acme extractor$ds + extractor$ds + + @!Acme extractor$ds + extractor$ds + + (None) extractor$ds + extractor$ds + ----------- ------------ +TXT; + + $this->assertEquals(0, $ret, 'Returns 0 in case of success'); + $this->assertStringContainsString($loaderPaths, trim($tester->getDisplay(true))); + } + + public function testWithGlobals() + { + $message = '<error>foo</error>'; + $tester = $this->createCommandTester([], ['message' => $message]); + $tester->execute([], ['decorated' => true]); + + $display = $tester->getDisplay(); + + $this->assertStringContainsString(json_encode($message), $display); + } + + public function testWithGlobalsJson() + { + $globals = ['message' => '<error>foo</error>']; + + $tester = $this->createCommandTester([], $globals); + $tester->execute(['--format' => 'json'], ['decorated' => true]); + + $display = $tester->getDisplay(); + $display = json_decode($display, true); + + $this->assertSame($globals, $display['globals']); + } + + public function testWithFilter() + { + $tester = $this->createCommandTester([]); + $tester->execute(['--format' => 'json'], ['decorated' => false]); + $display = $tester->getDisplay(); + $display1 = json_decode($display, true); + + $tester->execute(['filter' => 'date', '--format' => 'json'], ['decorated' => false]); + $display = $tester->getDisplay(); + $display2 = json_decode($display, true); + + $this->assertNotSame($display1, $display2); + } + + private function createCommandTester(array $paths = [], array $globals = []) + { + $filesystemLoader = new FilesystemLoader([], \dirname(__DIR__).'/Fixtures'); + foreach ($paths as $namespace => $relDirs) { + foreach ($relDirs as $relDir) { + $filesystemLoader->addPath($relDir, $namespace); + } + } + + $environment = new Environment($filesystemLoader); + foreach ($globals as $name => $value) { + $environment->addGlobal($name, $value); + } + + $command = new DebugCommand($environment); + + $application = new Application(); + $application->add($command); + $command = $application->find('debug:twig'); + + return new CommandTester($command); + } +} diff --git a/vendor/symfony/twig-bridge/Tests/Command/LintCommandTest.php b/vendor/symfony/twig-bridge/Tests/Command/LintCommandTest.php index 9ef18640684f90044c16ef02bcc93024fe052cf6..db10ccb6c0904ddff35d13af0af1947f14f7012b 100644 --- a/vendor/symfony/twig-bridge/Tests/Command/LintCommandTest.php +++ b/vendor/symfony/twig-bridge/Tests/Command/LintCommandTest.php @@ -16,8 +16,8 @@ use Symfony\Bridge\Twig\Command\LintCommand; use Symfony\Component\Console\Application; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Tester\CommandTester; -use Twig\Loader\FilesystemLoader; use Twig\Environment; +use Twig\Loader\FilesystemLoader; class LintCommandTest extends TestCase { @@ -28,10 +28,10 @@ class LintCommandTest extends TestCase $tester = $this->createCommandTester(); $filename = $this->createFile('{{ foo }}'); - $ret = $tester->execute(array('filename' => array($filename)), array('verbosity' => OutputInterface::VERBOSITY_VERBOSE, 'decorated' => false)); + $ret = $tester->execute(['filename' => [$filename]], ['verbosity' => OutputInterface::VERBOSITY_VERBOSE, 'decorated' => false]); $this->assertEquals(0, $ret, 'Returns 0 in case of success'); - $this->assertContains('OK in', trim($tester->getDisplay())); + $this->assertStringContainsString('OK in', trim($tester->getDisplay())); } public function testLintIncorrectFile() @@ -39,22 +39,20 @@ class LintCommandTest extends TestCase $tester = $this->createCommandTester(); $filename = $this->createFile('{{ foo'); - $ret = $tester->execute(array('filename' => array($filename)), array('decorated' => false)); + $ret = $tester->execute(['filename' => [$filename]], ['decorated' => false]); $this->assertEquals(1, $ret, 'Returns 1 in case of error'); $this->assertRegExp('/ERROR in \S+ \(line /', trim($tester->getDisplay())); } - /** - * @expectedException \RuntimeException - */ public function testLintFileNotReadable() { + $this->expectException('RuntimeException'); $tester = $this->createCommandTester(); $filename = $this->createFile(''); unlink($filename); - $ret = $tester->execute(array('filename' => array($filename)), array('decorated' => false)); + $ret = $tester->execute(['filename' => [$filename]], ['decorated' => false]); } public function testLintFileCompileTimeException() @@ -62,7 +60,7 @@ class LintCommandTest extends TestCase $tester = $this->createCommandTester(); $filename = $this->createFile("{{ 2|number_format(2, decimal_point='.', ',') }}"); - $ret = $tester->execute(array('filename' => array($filename)), array('decorated' => false)); + $ret = $tester->execute(['filename' => [$filename]], ['decorated' => false]); $this->assertEquals(1, $ret, 'Returns 1 in case of error'); $this->assertRegExp('/ERROR in \S+ \(line /', trim($tester->getDisplay())); @@ -70,12 +68,12 @@ class LintCommandTest extends TestCase /** * @group legacy - * @expectedDeprecation Passing a command name as the first argument of "Symfony\Bridge\Twig\Command\LintCommand::__construct" is deprecated since Symfony 3.4 and will be removed in 4.0. If the command was registered by convention, make it a service instead. - * @expectedException \RuntimeException - * @expectedExceptionMessage The Twig environment needs to be set. + * @expectedDeprecation Passing a command name as the first argument of "Symfony\Bridge\Twig\Command\LintCommand::__construct()" is deprecated since Symfony 3.4 and support for it will be removed in 4.0. If the command was registered by convention, make it a service instead. */ public function testLegacyLintCommand() { + $this->expectException('RuntimeException'); + $this->expectExceptionMessage('The Twig environment needs to be set.'); $command = new LintCommand(); $application = new Application(); @@ -83,7 +81,7 @@ class LintCommandTest extends TestCase $command = $application->find('lint:twig'); $tester = new CommandTester($command); - $tester->execute(array()); + $tester->execute([]); } /** @@ -115,7 +113,7 @@ class LintCommandTest extends TestCase protected function setUp() { - $this->files = array(); + $this->files = []; } protected function tearDown() diff --git a/vendor/symfony/twig-bridge/Tests/Extension/AbstractBootstrap3HorizontalLayoutTest.php b/vendor/symfony/twig-bridge/Tests/Extension/AbstractBootstrap3HorizontalLayoutTest.php new file mode 100644 index 0000000000000000000000000000000000000000..9131216182a3d964963c34a454165ceb87ad93c3 --- /dev/null +++ b/vendor/symfony/twig-bridge/Tests/Extension/AbstractBootstrap3HorizontalLayoutTest.php @@ -0,0 +1,166 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\Twig\Tests\Extension; + +abstract class AbstractBootstrap3HorizontalLayoutTest extends AbstractBootstrap3LayoutTest +{ + public function testLabelOnForm() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\DateType'); + $view = $form->createView(); + $this->renderWidget($view, ['label' => 'foo']); + $html = $this->renderLabel($view); + + $this->assertMatchesXpath($html, +'/label + [@class="col-sm-2 control-label required"] + [.="[trans]Name[/trans]"] +' + ); + } + + public function testLabelDoesNotRenderFieldAttributes() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\TextType'); + $html = $this->renderLabel($form->createView(), null, [ + 'attr' => [ + 'class' => 'my&class', + ], + ]); + + $this->assertMatchesXpath($html, +'/label + [@for="name"] + [@class="col-sm-2 control-label required"] +' + ); + } + + public function testLabelWithCustomAttributesPassedDirectly() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\TextType'); + $html = $this->renderLabel($form->createView(), null, [ + 'label_attr' => [ + 'class' => 'my&class', + ], + ]); + + $this->assertMatchesXpath($html, +'/label + [@for="name"] + [@class="my&class col-sm-2 control-label required"] +' + ); + } + + public function testLabelWithCustomTextAndCustomAttributesPassedDirectly() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\TextType'); + $html = $this->renderLabel($form->createView(), 'Custom label', [ + 'label_attr' => [ + 'class' => 'my&class', + ], + ]); + + $this->assertMatchesXpath($html, +'/label + [@for="name"] + [@class="my&class col-sm-2 control-label required"] + [.="[trans]Custom label[/trans]"] +' + ); + } + + public function testLabelWithCustomTextAsOptionAndCustomAttributesPassedDirectly() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\TextType', null, [ + 'label' => 'Custom label', + ]); + $html = $this->renderLabel($form->createView(), null, [ + 'label_attr' => [ + 'class' => 'my&class', + ], + ]); + + $this->assertMatchesXpath($html, +'/label + [@for="name"] + [@class="my&class col-sm-2 control-label required"] + [.="[trans]Custom label[/trans]"] +' + ); + } + + public function testStartTag() + { + $form = $this->factory->create('Symfony\Component\Form\Extension\Core\Type\FormType', null, [ + 'method' => 'get', + 'action' => 'http://example.com/directory', + ]); + + $html = $this->renderStart($form->createView()); + + $this->assertSame('<form name="form" method="get" action="http://example.com/directory" class="form-horizontal">', $html); + } + + public function testStartTagWithOverriddenVars() + { + $form = $this->factory->create('Symfony\Component\Form\Extension\Core\Type\FormType', null, [ + 'method' => 'put', + 'action' => 'http://example.com/directory', + ]); + + $html = $this->renderStart($form->createView(), [ + 'method' => 'post', + 'action' => 'http://foo.com/directory', + ]); + + $this->assertSame('<form name="form" method="post" action="http://foo.com/directory" class="form-horizontal">', $html); + } + + public function testStartTagForMultipartForm() + { + $form = $this->factory->createBuilder('Symfony\Component\Form\Extension\Core\Type\FormType', null, [ + 'method' => 'get', + 'action' => 'http://example.com/directory', + ]) + ->add('file', 'Symfony\Component\Form\Extension\Core\Type\FileType') + ->getForm(); + + $html = $this->renderStart($form->createView()); + + $this->assertSame('<form name="form" method="get" action="http://example.com/directory" class="form-horizontal" enctype="multipart/form-data">', $html); + } + + public function testStartTagWithExtraAttributes() + { + $form = $this->factory->create('Symfony\Component\Form\Extension\Core\Type\FormType', null, [ + 'method' => 'get', + 'action' => 'http://example.com/directory', + ]); + + $html = $this->renderStart($form->createView(), [ + 'attr' => ['class' => 'foobar'], + ]); + + $this->assertSame('<form name="form" method="get" action="http://example.com/directory" class="foobar form-horizontal">', $html); + } + + public function testCheckboxRow() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\CheckboxType'); + $view = $form->createView(); + $html = $this->renderRow($view, ['label' => 'foo']); + + $this->assertMatchesXpath($html, '/div[@class="form-group"]/div[@class="col-sm-2" or @class="col-sm-10"]', 2); + } +} diff --git a/vendor/symfony/twig-bridge/Tests/Extension/AbstractBootstrap3LayoutTest.php b/vendor/symfony/twig-bridge/Tests/Extension/AbstractBootstrap3LayoutTest.php new file mode 100644 index 0000000000000000000000000000000000000000..f04372c5423b0babf66c6e6555cd78f9504d08f8 --- /dev/null +++ b/vendor/symfony/twig-bridge/Tests/Extension/AbstractBootstrap3LayoutTest.php @@ -0,0 +1,2546 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\Twig\Tests\Extension; + +use Symfony\Component\Form\FormError; +use Symfony\Component\Form\Tests\AbstractLayoutTest; + +abstract class AbstractBootstrap3LayoutTest extends AbstractLayoutTest +{ + protected static $supportedFeatureSetVersion = 304; + + public function testLabelOnForm() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\DateType'); + $view = $form->createView(); + $this->renderWidget($view, ['label' => 'foo']); + $html = $this->renderLabel($view); + + $this->assertMatchesXpath($html, +'/label + [@class="control-label required"] + [.="[trans]Name[/trans]"] +' + ); + } + + public function testLabelDoesNotRenderFieldAttributes() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\TextType'); + $html = $this->renderLabel($form->createView(), null, [ + 'attr' => [ + 'class' => 'my&class', + ], + ]); + + $this->assertMatchesXpath($html, +'/label + [@for="name"] + [@class="control-label required"] +' + ); + } + + public function testLabelWithCustomAttributesPassedDirectly() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\TextType'); + $html = $this->renderLabel($form->createView(), null, [ + 'label_attr' => [ + 'class' => 'my&class', + ], + ]); + + $this->assertMatchesXpath($html, +'/label + [@for="name"] + [@class="my&class control-label required"] +' + ); + } + + public function testLabelWithCustomTextAndCustomAttributesPassedDirectly() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\TextType'); + $html = $this->renderLabel($form->createView(), 'Custom label', [ + 'label_attr' => [ + 'class' => 'my&class', + ], + ]); + + $this->assertMatchesXpath($html, +'/label + [@for="name"] + [@class="my&class control-label required"] + [.="[trans]Custom label[/trans]"] +' + ); + } + + public function testLabelWithCustomTextAsOptionAndCustomAttributesPassedDirectly() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\TextType', null, [ + 'label' => 'Custom label', + ]); + $html = $this->renderLabel($form->createView(), null, [ + 'label_attr' => [ + 'class' => 'my&class', + ], + ]); + + $this->assertMatchesXpath($html, +'/label + [@for="name"] + [@class="my&class control-label required"] + [.="[trans]Custom label[/trans]"] +' + ); + } + + public function testErrors() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\TextType'); + $form->addError(new FormError('[trans]Error 1[/trans]')); + $form->addError(new FormError('[trans]Error 2[/trans]')); + $view = $form->createView(); + $html = $this->renderErrors($view); + + $this->assertMatchesXpath($html, +'/div + [@class="alert alert-danger"] + [ + ./ul + [@class="list-unstyled"] + [ + ./li + [.=" [trans]Error 1[/trans]"] + [ + ./span[@class="glyphicon glyphicon-exclamation-sign"] + ] + /following-sibling::li + [.=" [trans]Error 2[/trans]"] + [ + ./span[@class="glyphicon glyphicon-exclamation-sign"] + ] + ] + [count(./li)=2] + ] +' + ); + } + + public function testOverrideWidgetBlock() + { + // see custom_widgets.html.twig + $form = $this->factory->createNamed('text_id', 'Symfony\Component\Form\Extension\Core\Type\TextType'); + $html = $this->renderWidget($form->createView()); + + $this->assertMatchesXpath($html, +'/div + [ + ./input + [@type="text"] + [@id="text_id"] + [@class="form-control"] + ] + [@id="container"] +' + ); + } + + public function testCheckedCheckbox() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\CheckboxType', true); + + $this->assertWidgetMatchesXpath($form->createView(), ['id' => 'my&id', 'attr' => ['class' => 'my&class']], +'/div + [@class="checkbox"] + [ + ./label + [.=" [trans]Name[/trans]"] + [ + ./input[@type="checkbox"][@name="name"][@id="my&id"][@class="my&class"][@checked="checked"][@value="1"] + ] + ] +' + ); + } + + public function testUncheckedCheckbox() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\CheckboxType', false); + + $this->assertWidgetMatchesXpath($form->createView(), ['id' => 'my&id', 'attr' => ['class' => 'my&class']], +'/div + [@class="checkbox"] + [ + ./label + [.=" [trans]Name[/trans]"] + [ + ./input[@type="checkbox"][@name="name"][@id="my&id"][@class="my&class"][not(@checked)] + ] + ] +' + ); + } + + public function testCheckboxWithValue() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\CheckboxType', false, [ + 'value' => 'foo&bar', + ]); + + $this->assertWidgetMatchesXpath($form->createView(), ['id' => 'my&id', 'attr' => ['class' => 'my&class']], +'/div + [@class="checkbox"] + [ + ./label + [.=" [trans]Name[/trans]"] + [ + ./input[@type="checkbox"][@name="name"][@id="my&id"][@class="my&class"][@value="foo&bar"] + ] + ] +' + ); + } + + public function testSingleChoice() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', '&a', [ + 'choices' => ['Choice&A' => '&a', 'Choice&B' => '&b'], + 'multiple' => false, + 'expanded' => false, + ]); + + $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'my&class']], +'/select + [@name="name"] + [@class="my&class form-control"] + [not(@required)] + [ + ./option[@value="&a"][@selected="selected"][.="[trans]Choice&A[/trans]"] + /following-sibling::option[@value="&b"][not(@selected)][.="[trans]Choice&B[/trans]"] + ] + [count(./option)=2] +' + ); + } + + public function testSingleChoiceAttributesWithMainAttributes() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', '&a', [ + 'choices' => ['Choice&A' => '&a', 'Choice&B' => '&b'], + 'multiple' => false, + 'expanded' => false, + 'attr' => ['class' => 'bar&baz'], + ]); + + $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'bar&baz']], +'/select + [@name="name"] + [@class="bar&baz form-control"] + [not(@required)] + [ + ./option[@value="&a"][@selected="selected"][.="[trans]Choice&A[/trans]"] + /following-sibling::option[@value="&b"][not(@selected)][.="[trans]Choice&B[/trans]"] + ] + [count(./option)=2] +' + ); + } + + public function testSingleExpandedChoiceAttributesWithMainAttributes() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', '&a', [ + 'choices' => ['Choice&A' => '&a', 'Choice&B' => '&b'], + 'multiple' => false, + 'expanded' => true, + 'attr' => ['class' => 'bar&baz'], + ]); + + $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'bar&baz']], +'/div + [@class="bar&baz"] + [ + ./div + [@class="radio"] + [ + ./label + [.=" [trans]Choice&A[/trans]"] + [ + ./input[@type="radio"][@name="name"][@id="name_0"][@value="&a"][@checked] + ] + ] + /following-sibling::div + [@class="radio"] + [ + ./label + [.=" [trans]Choice&B[/trans]"] + [ + ./input[@type="radio"][@name="name"][@id="name_1"][@value="&b"][not(@checked)] + ] + ] + /following-sibling::input[@type="hidden"][@id="name__token"] + ] +' + ); + } + + public function testSelectWithSizeBiggerThanOneCanBeRequired() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', null, [ + 'choices' => ['a', 'b'], + 'multiple' => false, + 'expanded' => false, + 'attr' => ['size' => 2], + ]); + + $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => '']], +'/select + [@name="name"] + [@required="required"] + [@size="2"] + [count(./option)=2] +' + ); + } + + public function testSingleChoiceWithoutTranslation() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', '&a', [ + 'choices' => ['Choice&A' => '&a', 'Choice&B' => '&b'], + 'multiple' => false, + 'expanded' => false, + 'choice_translation_domain' => false, + ]); + + $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'my&class']], +'/select + [@name="name"] + [@class="my&class form-control"] + [not(@required)] + [ + ./option[@value="&a"][@selected="selected"][.="Choice&A"] + /following-sibling::option[@value="&b"][not(@selected)][.="Choice&B"] + ] + [count(./option)=2] +' + ); + } + + public function testSingleChoiceWithPlaceholderWithoutTranslation() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', '&a', [ + 'choices' => ['Choice&A' => '&a', 'Choice&B' => '&b'], + 'multiple' => false, + 'expanded' => false, + 'required' => false, + 'translation_domain' => false, + 'placeholder' => 'Placeholder&Not&Translated', + ]); + + $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'my&class']], +'/select + [@name="name"] + [@class="my&class form-control"] + [not(@required)] + [ + ./option[@value=""][not(@selected)][not(@disabled)][.="Placeholder&Not&Translated"] + /following-sibling::option[@value="&a"][@selected="selected"][.="Choice&A"] + /following-sibling::option[@value="&b"][not(@selected)][.="Choice&B"] + ] + [count(./option)=3] +' + ); + } + + public function testSingleChoiceAttributes() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', '&a', [ + 'choices' => ['Choice&A' => '&a', 'Choice&B' => '&b'], + 'choice_attr' => ['Choice&B' => ['class' => 'foo&bar']], + 'multiple' => false, + 'expanded' => false, + ]); + + $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'my&class']], +'/select + [@name="name"] + [@class="my&class form-control"] + [not(@required)] + [ + ./option[@value="&a"][@selected="selected"][.="[trans]Choice&A[/trans]"] + /following-sibling::option[@value="&b"][@class="foo&bar"][not(@selected)][.="[trans]Choice&B[/trans]"] + ] + [count(./option)=2] +' + ); + } + + public function testSingleChoiceWithPreferred() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', '&a', [ + 'choices' => ['Choice&A' => '&a', 'Choice&B' => '&b'], + 'preferred_choices' => ['&b'], + 'multiple' => false, + 'expanded' => false, + ]); + + $this->assertWidgetMatchesXpath($form->createView(), ['separator' => '-- sep --', 'attr' => ['class' => 'my&class']], +'/select + [@name="name"] + [@class="my&class form-control"] + [not(@required)] + [ + ./option[@value="&b"][not(@selected)][.="[trans]Choice&B[/trans]"] + /following-sibling::option[@disabled="disabled"][not(@selected)][.="-- sep --"] + /following-sibling::option[@value="&a"][@selected="selected"][.="[trans]Choice&A[/trans]"] + ] +' + ); + } + + public function testSingleChoiceWithPreferredAndNoSeparator() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', '&a', [ + 'choices' => ['Choice&A' => '&a', 'Choice&B' => '&b'], + 'preferred_choices' => ['&b'], + 'multiple' => false, + 'expanded' => false, + ]); + + $this->assertWidgetMatchesXpath($form->createView(), ['separator' => null, 'attr' => ['class' => 'my&class']], +'/select + [@name="name"] + [@class="my&class form-control"] + [not(@required)] + [ + ./option[@value="&b"][not(@selected)][.="[trans]Choice&B[/trans]"] + /following-sibling::option[@value="&a"][@selected="selected"][.="[trans]Choice&A[/trans]"] + ] +' + ); + } + + public function testSingleChoiceWithPreferredAndBlankSeparator() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', '&a', [ + 'choices' => ['Choice&A' => '&a', 'Choice&B' => '&b'], + 'preferred_choices' => ['&b'], + 'multiple' => false, + 'expanded' => false, + ]); + + $this->assertWidgetMatchesXpath($form->createView(), ['separator' => '', 'attr' => ['class' => 'my&class']], +'/select + [@name="name"] + [@class="my&class form-control"] + [not(@required)] + [ + ./option[@value="&b"][not(@selected)][.="[trans]Choice&B[/trans]"] + /following-sibling::option[@disabled="disabled"][not(@selected)][.=""] + /following-sibling::option[@value="&a"][@selected="selected"][.="[trans]Choice&A[/trans]"] + ] +' + ); + } + + public function testChoiceWithOnlyPreferred() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', '&a', [ + 'choices' => ['Choice&A' => '&a', 'Choice&B' => '&b'], + 'preferred_choices' => ['&a', '&b'], + 'multiple' => false, + 'expanded' => false, + ]); + + $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'my&class']], +'/select + [@class="my&class form-control"] +' + ); + } + + public function testSingleChoiceNonRequired() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', '&a', [ + 'choices' => ['Choice&A' => '&a', 'Choice&B' => '&b'], + 'required' => false, + 'multiple' => false, + 'expanded' => false, + ]); + + $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'my&class']], +'/select + [@name="name"] + [@class="my&class form-control"] + [not(@required)] + [ + ./option[@value=""][.=""] + /following-sibling::option[@value="&a"][@selected="selected"][.="[trans]Choice&A[/trans]"] + /following-sibling::option[@value="&b"][not(@selected)][.="[trans]Choice&B[/trans]"] + ] + [count(./option)=3] +' + ); + } + + public function testSingleChoiceNonRequiredNoneSelected() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', null, [ + 'choices' => ['Choice&A' => '&a', 'Choice&B' => '&b'], + 'required' => false, + 'multiple' => false, + 'expanded' => false, + ]); + + $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'my&class']], +'/select + [@name="name"] + [@class="my&class form-control"] + [not(@required)] + [ + ./option[@value=""][.=""] + /following-sibling::option[@value="&a"][not(@selected)][.="[trans]Choice&A[/trans]"] + /following-sibling::option[@value="&b"][not(@selected)][.="[trans]Choice&B[/trans]"] + ] + [count(./option)=3] +' + ); + } + + public function testSingleChoiceNonRequiredWithPlaceholder() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', '&a', [ + 'choices' => ['Choice&A' => '&a', 'Choice&B' => '&b'], + 'multiple' => false, + 'expanded' => false, + 'required' => false, + 'placeholder' => 'Select&Anything&Not&Me', + ]); + + $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'my&class']], +'/select + [@name="name"] + [@class="my&class form-control"] + [not(@required)] + [ + ./option[@value=""][not(@selected)][not(@disabled)][.="[trans]Select&Anything&Not&Me[/trans]"] + /following-sibling::option[@value="&a"][@selected="selected"][.="[trans]Choice&A[/trans]"] + /following-sibling::option[@value="&b"][not(@selected)][.="[trans]Choice&B[/trans]"] + ] + [count(./option)=3] +' + ); + } + + public function testSingleChoiceRequiredWithPlaceholder() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', '&a', [ + 'choices' => ['Choice&A' => '&a', 'Choice&B' => '&b'], + 'required' => true, + 'multiple' => false, + 'expanded' => false, + 'placeholder' => 'Test&Me', + ]); + + $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'my&class']], +'/select + [@name="name"] + [@class="my&class form-control"] + [@required="required"] + [ + ./option[@value=""][not(@selected)][not(@disabled)][.="[trans]Test&Me[/trans]"] + /following-sibling::option[@value="&a"][@selected="selected"][.="[trans]Choice&A[/trans]"] + /following-sibling::option[@value="&b"][not(@selected)][.="[trans]Choice&B[/trans]"] + ] + [count(./option)=3] +' + ); + } + + public function testSingleChoiceRequiredWithPlaceholderViaView() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', '&a', [ + 'choices' => ['Choice&A' => '&a', 'Choice&B' => '&b'], + 'required' => true, + 'multiple' => false, + 'expanded' => false, + ]); + + $this->assertWidgetMatchesXpath($form->createView(), ['placeholder' => '', 'attr' => ['class' => 'my&class']], +'/select + [@name="name"] + [@class="my&class form-control"] + [@required="required"] + [ + ./option[@value=""][not(@selected)][not(@disabled)][.=""] + /following-sibling::option[@value="&a"][@selected="selected"][.="[trans]Choice&A[/trans]"] + /following-sibling::option[@value="&b"][not(@selected)][.="[trans]Choice&B[/trans]"] + ] + [count(./option)=3] +' + ); + } + + public function testSingleChoiceGrouped() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', '&a', [ + 'choices' => [ + 'Group&1' => ['Choice&A' => '&a', 'Choice&B' => '&b'], + 'Group&2' => ['Choice&C' => '&c'], + ], + 'multiple' => false, + 'expanded' => false, + ]); + + $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'my&class']], +'/select + [@name="name"] + [@class="my&class form-control"] + [./optgroup[@label="[trans]Group&1[/trans]"] + [ + ./option[@value="&a"][@selected="selected"][.="[trans]Choice&A[/trans]"] + /following-sibling::option[@value="&b"][not(@selected)][.="[trans]Choice&B[/trans]"] + ] + [count(./option)=2] + ] + [./optgroup[@label="[trans]Group&2[/trans]"] + [./option[@value="&c"][not(@selected)][.="[trans]Choice&C[/trans]"]] + [count(./option)=1] + ] + [count(./optgroup)=2] +' + ); + } + + public function testMultipleChoice() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', ['&a'], [ + 'choices' => ['Choice&A' => '&a', 'Choice&B' => '&b'], + 'required' => true, + 'multiple' => true, + 'expanded' => false, + ]); + + $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'my&class']], +'/select + [@name="name[]"] + [@class="my&class form-control"] + [@required="required"] + [@multiple="multiple"] + [ + ./option[@value="&a"][@selected="selected"][.="[trans]Choice&A[/trans]"] + /following-sibling::option[@value="&b"][not(@selected)][.="[trans]Choice&B[/trans]"] + ] + [count(./option)=2] +' + ); + } + + public function testMultipleChoiceAttributes() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', ['&a'], [ + 'choices' => ['Choice&A' => '&a', 'Choice&B' => '&b'], + 'choice_attr' => ['Choice&B' => ['class' => 'foo&bar']], + 'required' => true, + 'multiple' => true, + 'expanded' => false, + ]); + + $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'my&class']], +'/select + [@name="name[]"] + [@class="my&class form-control"] + [@required="required"] + [@multiple="multiple"] + [ + ./option[@value="&a"][@selected="selected"][.="[trans]Choice&A[/trans]"] + /following-sibling::option[@value="&b"][@class="foo&bar"][not(@selected)][.="[trans]Choice&B[/trans]"] + ] + [count(./option)=2] +' + ); + } + + public function testMultipleChoiceSkipsPlaceholder() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', ['&a'], [ + 'choices' => ['Choice&A' => '&a', 'Choice&B' => '&b'], + 'multiple' => true, + 'expanded' => false, + 'placeholder' => 'Test&Me', + ]); + + $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'my&class']], +'/select + [@name="name[]"] + [@class="my&class form-control"] + [@multiple="multiple"] + [ + ./option[@value="&a"][@selected="selected"][.="[trans]Choice&A[/trans]"] + /following-sibling::option[@value="&b"][not(@selected)][.="[trans]Choice&B[/trans]"] + ] + [count(./option)=2] +' + ); + } + + public function testMultipleChoiceNonRequired() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', ['&a'], [ + 'choices' => ['Choice&A' => '&a', 'Choice&B' => '&b'], + 'required' => false, + 'multiple' => true, + 'expanded' => false, + ]); + + $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'my&class']], +'/select + [@name="name[]"] + [@class="my&class form-control"] + [@multiple="multiple"] + [ + ./option[@value="&a"][@selected="selected"][.="[trans]Choice&A[/trans]"] + /following-sibling::option[@value="&b"][not(@selected)][.="[trans]Choice&B[/trans]"] + ] + [count(./option)=2] +' + ); + } + + public function testSingleChoiceExpanded() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', '&a', [ + 'choices' => ['Choice&A' => '&a', 'Choice&B' => '&b'], + 'multiple' => false, + 'expanded' => true, + ]); + + $this->assertWidgetMatchesXpath($form->createView(), [], +'/div + [ + ./div + [@class="radio"] + [ + ./label + [.=" [trans]Choice&A[/trans]"] + [ + ./input[@type="radio"][@name="name"][@id="name_0"][@value="&a"][@checked] + ] + ] + /following-sibling::div + [@class="radio"] + [ + ./label + [.=" [trans]Choice&B[/trans]"] + [ + ./input[@type="radio"][@name="name"][@id="name_1"][@value="&b"][not(@checked)] + ] + ] + /following-sibling::input[@type="hidden"][@id="name__token"] + ] +' + ); + } + + public function testSingleChoiceExpandedWithLabelsAsFalse() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', '&a', [ + 'choices' => ['Choice&A' => '&a', 'Choice&B' => '&b'], + 'choice_label' => false, + 'multiple' => false, + 'expanded' => true, + ]); + + $this->assertWidgetMatchesXpath($form->createView(), [], +'/div + [ + ./div + [@class="radio"] + [ + ./label + [ + ./input[@type="radio"][@name="name"][@id="name_0"][@value="&a"][@checked] + ] + ] + /following-sibling::div + [@class="radio"] + [ + ./label + [ + ./input[@type="radio"][@name="name"][@id="name_1"][@value="&b"][not(@checked)] + ] + ] + /following-sibling::input[@type="hidden"][@id="name__token"] + ] +' + ); + } + + public function testSingleChoiceExpandedWithLabelsSetByCallable() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', '&a', [ + 'choices' => ['Choice&A' => '&a', 'Choice&B' => '&b', 'Choice&C' => '&c'], + 'choice_label' => function ($choice, $label, $value) { + if ('&b' === $choice) { + return false; + } + + return 'label.'.$value; + }, + 'multiple' => false, + 'expanded' => true, + ]); + + $this->assertWidgetMatchesXpath($form->createView(), [], +'/div + [ + ./div + [@class="radio"] + [ + ./label + [.=" [trans]label.&a[/trans]"] + [ + ./input[@type="radio"][@name="name"][@id="name_0"][@value="&a"][@checked] + ] + ] + /following-sibling::div + [@class="radio"] + [ + ./label + [ + ./input[@type="radio"][@name="name"][@id="name_1"][@value="&b"][not(@checked)] + ] + ] + /following-sibling::div + [@class="radio"] + [ + ./label + [.=" [trans]label.&c[/trans]"] + [ + ./input[@type="radio"][@name="name"][@id="name_2"][@value="&c"][not(@checked)] + ] + ] + /following-sibling::input[@type="hidden"][@id="name__token"] + ] +' + ); + } + + public function testSingleChoiceExpandedWithLabelsSetFalseByCallable() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', '&a', [ + 'choices' => ['Choice&A' => '&a', 'Choice&B' => '&b'], + 'choice_label' => function () { + return false; + }, + 'multiple' => false, + 'expanded' => true, + ]); + + $this->assertWidgetMatchesXpath($form->createView(), [], +'/div + [ + ./div + [@class="radio"] + [ + ./label + [ + ./input[@type="radio"][@name="name"][@id="name_0"][@value="&a"][@checked] + ] + ] + /following-sibling::div + [@class="radio"] + [ + ./label + [ + ./input[@type="radio"][@name="name"][@id="name_1"][@value="&b"][not(@checked)] + ] + ] + /following-sibling::input[@type="hidden"][@id="name__token"] + ] +' + ); + } + + public function testSingleChoiceExpandedWithoutTranslation() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', '&a', [ + 'choices' => ['Choice&A' => '&a', 'Choice&B' => '&b'], + 'multiple' => false, + 'expanded' => true, + 'choice_translation_domain' => false, + ]); + + $this->assertWidgetMatchesXpath($form->createView(), [], +'/div + [ + ./div + [@class="radio"] + [ + ./label + [.=" Choice&A"] + [ + ./input[@type="radio"][@name="name"][@id="name_0"][@value="&a"][@checked] + ] + ] + /following-sibling::div + [@class="radio"] + [ + ./label + [.=" Choice&B"] + [ + ./input[@type="radio"][@name="name"][@id="name_1"][@value="&b"][not(@checked)] + ] + ] + /following-sibling::input[@type="hidden"][@id="name__token"] + ] +' + ); + } + + public function testSingleChoiceExpandedAttributes() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', '&a', [ + 'choices' => ['Choice&A' => '&a', 'Choice&B' => '&b'], + 'choice_attr' => ['Choice&B' => ['class' => 'foo&bar']], + 'multiple' => false, + 'expanded' => true, + ]); + + $this->assertWidgetMatchesXpath($form->createView(), [], +'/div + [ + ./div + [@class="radio"] + [ + ./label + [.=" [trans]Choice&A[/trans]"] + [ + ./input[@type="radio"][@name="name"][@id="name_0"][@value="&a"][@checked] + ] + ] + /following-sibling::div + [@class="radio"] + [ + ./label + [.=" [trans]Choice&B[/trans]"] + [ + ./input[@type="radio"][@name="name"][@id="name_1"][@value="&b"][not(@checked)][@class="foo&bar"] + ] + ] + /following-sibling::input[@type="hidden"][@id="name__token"] + ] +' + ); + } + + public function testSingleChoiceExpandedWithPlaceholder() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', '&a', [ + 'choices' => ['Choice&A' => '&a', 'Choice&B' => '&b'], + 'multiple' => false, + 'expanded' => true, + 'placeholder' => 'Test&Me', + 'required' => false, + ]); + + $this->assertWidgetMatchesXpath($form->createView(), [], +'/div + [ + ./div + [@class="radio"] + [ + ./label + [.=" [trans]Test&Me[/trans]"] + [ + ./input[@type="radio"][@name="name"][@id="name_placeholder"][not(@checked)] + ] + ] + /following-sibling::div + [@class="radio"] + [ + ./label + [.=" [trans]Choice&A[/trans]"] + [ + ./input[@type="radio"][@name="name"][@id="name_0"][@checked] + ] + ] + /following-sibling::div + [@class="radio"] + [ + ./label + [.=" [trans]Choice&B[/trans]"] + [ + ./input[@type="radio"][@name="name"][@id="name_1"][not(@checked)] + ] + ] + /following-sibling::input[@type="hidden"][@id="name__token"] + ] +' + ); + } + + public function testSingleChoiceExpandedWithPlaceholderWithoutTranslation() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', '&a', [ + 'choices' => ['Choice&A' => '&a', 'Choice&B' => '&b'], + 'multiple' => false, + 'expanded' => true, + 'required' => false, + 'choice_translation_domain' => false, + 'placeholder' => 'Placeholder&Not&Translated', + ]); + + $this->assertWidgetMatchesXpath($form->createView(), [], +'/div + [ + ./div + [@class="radio"] + [ + ./label + [.=" Placeholder&Not&Translated"] + [ + ./input[@type="radio"][@name="name"][@id="name_placeholder"][not(@checked)] + ] + ] + /following-sibling::div + [@class="radio"] + [ + ./label + [.=" Choice&A"] + [ + ./input[@type="radio"][@name="name"][@id="name_0"][@checked] + ] + ] + /following-sibling::div + [@class="radio"] + [ + ./label + [.=" Choice&B"] + [ + ./input[@type="radio"][@name="name"][@id="name_1"][not(@checked)] + ] + ] + /following-sibling::input[@type="hidden"][@id="name__token"] + ] +' + ); + } + + public function testSingleChoiceExpandedWithBooleanValue() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', true, [ + 'choices' => ['Choice&A' => '1', 'Choice&B' => '0'], + 'multiple' => false, + 'expanded' => true, + ]); + + $this->assertWidgetMatchesXpath($form->createView(), [], +'/div + [ + ./div + [@class="radio"] + [ + ./label + [.=" [trans]Choice&A[/trans]"] + [ + ./input[@type="radio"][@name="name"][@id="name_0"][@checked] + ] + ] + /following-sibling::div + [@class="radio"] + [ + ./label + [.=" [trans]Choice&B[/trans]"] + [ + ./input[@type="radio"][@name="name"][@id="name_1"][not(@checked)] + ] + ] + /following-sibling::input[@type="hidden"][@id="name__token"] + ] +' + ); + } + + public function testMultipleChoiceExpanded() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', ['&a', '&c'], [ + 'choices' => ['Choice&A' => '&a', 'Choice&B' => '&b', 'Choice&C' => '&c'], + 'multiple' => true, + 'expanded' => true, + 'required' => true, + ]); + + $this->assertWidgetMatchesXpath($form->createView(), [], +'/div + [ + ./div + [@class="checkbox"] + [ + ./label + [.=" [trans]Choice&A[/trans]"] + [ + ./input[@type="checkbox"][@name="name[]"][@id="name_0"][@checked][not(@required)] + ] + ] + /following-sibling::div + [@class="checkbox"] + [ + ./label + [.=" [trans]Choice&B[/trans]"] + [ + ./input[@type="checkbox"][@name="name[]"][@id="name_1"][not(@checked)][not(@required)] + ] + ] + /following-sibling::div + [@class="checkbox"] + [ + ./label + [.=" [trans]Choice&C[/trans]"] + [ + ./input[@type="checkbox"][@name="name[]"][@id="name_2"][@checked][not(@required)] + ] + ] + /following-sibling::input[@type="hidden"][@id="name__token"] + ] +' + ); + } + + public function testMultipleChoiceExpandedWithLabelsAsFalse() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', ['&a'], [ + 'choices' => ['Choice&A' => '&a', 'Choice&B' => '&b'], + 'choice_label' => false, + 'multiple' => true, + 'expanded' => true, + ]); + + $this->assertWidgetMatchesXpath($form->createView(), [], +'/div + [ + ./div + [@class="checkbox"] + [ + ./label + [ + ./input[@type="checkbox"][@name="name[]"][@id="name_0"][@value="&a"][@checked] + ] + ] + /following-sibling::div + [@class="checkbox"] + [ + ./label + [ + ./input[@type="checkbox"][@name="name[]"][@id="name_1"][@value="&b"][not(@checked)] + ] + ] + /following-sibling::input[@type="hidden"][@id="name__token"] + ] +' + ); + } + + public function testMultipleChoiceExpandedWithLabelsSetByCallable() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', ['&a'], [ + 'choices' => ['Choice&A' => '&a', 'Choice&B' => '&b', 'Choice&C' => '&c'], + 'choice_label' => function ($choice, $label, $value) { + if ('&b' === $choice) { + return false; + } + + return 'label.'.$value; + }, + 'multiple' => true, + 'expanded' => true, + ]); + + $this->assertWidgetMatchesXpath($form->createView(), [], + '/div + [ + ./div + [@class="checkbox"] + [ + ./label + [.=" [trans]label.&a[/trans]"] + [ + ./input[@type="checkbox"][@name="name[]"][@id="name_0"][@value="&a"][@checked] + ] + ] + /following-sibling::div + [@class="checkbox"] + [ + ./label + [ + ./input[@type="checkbox"][@name="name[]"][@id="name_1"][@value="&b"][not(@checked)] + ] + ] + /following-sibling::div + [@class="checkbox"] + [ + ./label + [.=" [trans]label.&c[/trans]"] + [ + ./input[@type="checkbox"][@name="name[]"][@id="name_2"][@value="&c"][not(@checked)] + ] + ] + /following-sibling::input[@type="hidden"][@id="name__token"] + ] +' + ); + } + + public function testMultipleChoiceExpandedWithLabelsSetFalseByCallable() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', ['&a'], [ + 'choices' => ['Choice&A' => '&a', 'Choice&B' => '&b'], + 'choice_label' => function () { + return false; + }, + 'multiple' => true, + 'expanded' => true, + ]); + + $this->assertWidgetMatchesXpath($form->createView(), [], +'/div + [ + ./div + [@class="checkbox"] + [ + ./label + [ + ./input[@type="checkbox"][@name="name[]"][@id="name_0"][@value="&a"][@checked] + ] + ] + /following-sibling::div + [@class="checkbox"] + [ + ./label + [ + ./input[@type="checkbox"][@name="name[]"][@id="name_1"][@value="&b"][not(@checked)] + ] + ] + /following-sibling::input[@type="hidden"][@id="name__token"] + ] +' + ); + } + + public function testMultipleChoiceExpandedWithoutTranslation() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', ['&a', '&c'], [ + 'choices' => ['Choice&A' => '&a', 'Choice&B' => '&b', 'Choice&C' => '&c'], + 'multiple' => true, + 'expanded' => true, + 'required' => true, + 'choice_translation_domain' => false, + ]); + + $this->assertWidgetMatchesXpath($form->createView(), [], +'/div + [ + ./div + [@class="checkbox"] + [ + ./label + [.=" Choice&A"] + [ + ./input[@type="checkbox"][@name="name[]"][@id="name_0"][@checked][not(@required)] + ] + ] + /following-sibling::div + [@class="checkbox"] + [ + ./label + [.=" Choice&B"] + [ + ./input[@type="checkbox"][@name="name[]"][@id="name_1"][not(@checked)][not(@required)] + ] + ] + /following-sibling::div + [@class="checkbox"] + [ + ./label + [.=" Choice&C"] + [ + ./input[@type="checkbox"][@name="name[]"][@id="name_2"][@checked][not(@required)] + ] + ] + /following-sibling::input[@type="hidden"][@id="name__token"] + ] +' + ); + } + + public function testMultipleChoiceExpandedAttributes() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', ['&a', '&c'], [ + 'choices' => ['Choice&A' => '&a', 'Choice&B' => '&b', 'Choice&C' => '&c'], + 'choice_attr' => ['Choice&B' => ['class' => 'foo&bar']], + 'multiple' => true, + 'expanded' => true, + 'required' => true, + ]); + + $this->assertWidgetMatchesXpath($form->createView(), [], +'/div + [ + ./div + [@class="checkbox"] + [ + ./label + [.=" [trans]Choice&A[/trans]"] + [ + ./input[@type="checkbox"][@name="name[]"][@id="name_0"][@checked][not(@required)] + ] + ] + /following-sibling::div + [@class="checkbox"] + [ + ./label + [.=" [trans]Choice&B[/trans]"] + [ + ./input[@type="checkbox"][@name="name[]"][@id="name_1"][not(@checked)][not(@required)][@class="foo&bar"] + ] + ] + /following-sibling::div + [@class="checkbox"] + [ + ./label + [.=" [trans]Choice&C[/trans]"] + [ + ./input[@type="checkbox"][@name="name[]"][@id="name_2"][@checked][not(@required)] + ] + ] + /following-sibling::input[@type="hidden"][@id="name__token"] + ] +' + ); + } + + public function testCountry() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\CountryType', 'AT'); + + $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'my&class']], +'/select + [@name="name"] + [@class="my&class form-control"] + [./option[@value="AT"][@selected="selected"][.="Austria"]] + [count(./option)>200] +' + ); + } + + public function testCountryWithPlaceholder() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\CountryType', 'AT', [ + 'placeholder' => 'Select&Country', + 'required' => false, + ]); + + $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'my&class']], +'/select + [@name="name"] + [@class="my&class form-control"] + [./option[@value=""][not(@selected)][not(@disabled)][.="[trans]Select&Country[/trans]"]] + [./option[@value="AT"][@selected="selected"][.="Austria"]] + [count(./option)>201] +' + ); + } + + public function testDateTime() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\DateTimeType', date('Y').'-02-03 04:05:06', [ + 'input' => 'string', + 'with_seconds' => false, + ]); + + $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'my&class']], +'/div + [ + ./select + [@id="name_date_month"] + [@class="form-control"] + [./option[@value="2"][@selected="selected"]] + /following-sibling::select + [@id="name_date_day"] + [@class="form-control"] + [./option[@value="3"][@selected="selected"]] + /following-sibling::select + [@id="name_date_year"] + [@class="form-control"] + [./option[@value="'.date('Y').'"][@selected="selected"]] + /following-sibling::select + [@id="name_time_hour"] + [@class="form-control"] + [./option[@value="4"][@selected="selected"]] + /following-sibling::select + [@id="name_time_minute"] + [@class="form-control"] + [./option[@value="5"][@selected="selected"]] + ] + [count(.//select)=5] +' + ); + } + + public function testDateTimeWithPlaceholderGlobal() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\DateTimeType', null, [ + 'input' => 'string', + 'placeholder' => 'Change&Me', + 'required' => false, + ]); + + $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'my&class']], +'/div + [@class="my&class form-inline"] + [ + ./select + [@id="name_date_month"] + [@class="form-control"] + [./option[@value=""][not(@selected)][not(@disabled)][.="[trans]Change&Me[/trans]"]] + /following-sibling::select + [@id="name_date_day"] + [@class="form-control"] + [./option[@value=""][not(@selected)][not(@disabled)][.="[trans]Change&Me[/trans]"]] + /following-sibling::select + [@id="name_date_year"] + [@class="form-control"] + [./option[@value=""][not(@selected)][not(@disabled)][.="[trans]Change&Me[/trans]"]] + /following-sibling::select + [@id="name_time_hour"] + [@class="form-control"] + [./option[@value=""][.="[trans]Change&Me[/trans]"]] + /following-sibling::select + [@id="name_time_minute"] + [@class="form-control"] + [./option[@value=""][.="[trans]Change&Me[/trans]"]] + ] + [count(.//select)=5] +' + ); + } + + public function testDateTimeWithHourAndMinute() + { + $data = ['year' => date('Y'), 'month' => '2', 'day' => '3', 'hour' => '4', 'minute' => '5']; + + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\DateTimeType', $data, [ + 'input' => 'array', + 'required' => false, + ]); + + $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'my&class']], +'/div + [@class="my&class form-inline"] + [ + ./select + [@id="name_date_month"] + [@class="form-control"] + [./option[@value="2"][@selected="selected"]] + /following-sibling::select + [@id="name_date_day"] + [@class="form-control"] + [./option[@value="3"][@selected="selected"]] + /following-sibling::select + [@id="name_date_year"] + [@class="form-control"] + [./option[@value="'.date('Y').'"][@selected="selected"]] + /following-sibling::select + [@id="name_time_hour"] + [@class="form-control"] + [./option[@value="4"][@selected="selected"]] + /following-sibling::select + [@id="name_time_minute"] + [@class="form-control"] + [./option[@value="5"][@selected="selected"]] + ] + [count(.//select)=5] +' + ); + } + + public function testDateTimeWithSeconds() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\DateTimeType', date('Y').'-02-03 04:05:06', [ + 'input' => 'string', + 'with_seconds' => true, + ]); + + $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'my&class']], +'/div + [@class="my&class form-inline"] + [ + ./select + [@id="name_date_month"] + [@class="form-control"] + [./option[@value="2"][@selected="selected"]] + /following-sibling::select + [@id="name_date_day"] + [@class="form-control"] + [./option[@value="3"][@selected="selected"]] + /following-sibling::select + [@id="name_date_year"] + [@class="form-control"] + [./option[@value="'.date('Y').'"][@selected="selected"]] + /following-sibling::select + [@id="name_time_hour"] + [@class="form-control"] + [./option[@value="4"][@selected="selected"]] + /following-sibling::select + [@id="name_time_minute"] + [@class="form-control"] + [./option[@value="5"][@selected="selected"]] + /following-sibling::select + [@id="name_time_second"] + [@class="form-control"] + [./option[@value="6"][@selected="selected"]] + ] + [count(.//select)=6] +' + ); + } + + public function testDateTimeSingleText() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\DateTimeType', '2011-02-03 04:05:06', [ + 'input' => 'string', + 'date_widget' => 'single_text', + 'time_widget' => 'single_text', + ]); + + $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'my&class']], +'/div + [@class="my&class form-inline"] + [ + ./input + [@type="date"] + [@id="name_date"] + [@name="name[date]"] + [@class="form-control"] + [@value="2011-02-03"] + /following-sibling::input + [@type="time"] + [@id="name_time"] + [@name="name[time]"] + [@class="form-control"] + [@value="04:05"] + ] +' + ); + } + + public function testDateTimeWithWidgetSingleText() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\DateTimeType', '2011-02-03 04:05:06', [ + 'input' => 'string', + 'widget' => 'single_text', + 'model_timezone' => 'UTC', + 'view_timezone' => 'UTC', + ]); + + $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'my&class']], +'/input + [@type="datetime-local"] + [@name="name"] + [@class="my&class form-control"] + [@value="2011-02-03T04:05:06"] +' + ); + } + + public function testDateTimeWithWidgetSingleTextIgnoreDateAndTimeWidgets() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\DateTimeType', '2011-02-03 04:05:06', [ + 'input' => 'string', + 'date_widget' => 'choice', + 'time_widget' => 'choice', + 'widget' => 'single_text', + 'model_timezone' => 'UTC', + 'view_timezone' => 'UTC', + ]); + + $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'my&class']], +'/input + [@type="datetime-local"] + [@name="name"] + [@class="my&class form-control"] + [@value="2011-02-03T04:05:06"] +' + ); + } + + public function testDateChoice() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\DateType', date('Y').'-02-03', [ + 'input' => 'string', + 'widget' => 'choice', + ]); + + $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'my&class']], +'/div + [@class="my&class form-inline"] + [ + ./select + [@id="name_month"] + [@class="form-control"] + [./option[@value="2"][@selected="selected"]] + /following-sibling::select + [@id="name_day"] + [@class="form-control"] + [./option[@value="3"][@selected="selected"]] + /following-sibling::select + [@id="name_year"] + [@class="form-control"] + [./option[@value="'.date('Y').'"][@selected="selected"]] + ] + [count(./select)=3] +' + ); + } + + public function testDateChoiceWithPlaceholderGlobal() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\DateType', null, [ + 'input' => 'string', + 'widget' => 'choice', + 'placeholder' => 'Change&Me', + 'required' => false, + ]); + + $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'my&class']], +'/div + [@class="my&class form-inline"] + [ + ./select + [@id="name_month"] + [@class="form-control"] + [./option[@value=""][not(@selected)][not(@disabled)][.="[trans]Change&Me[/trans]"]] + /following-sibling::select + [@id="name_day"] + [@class="form-control"] + [./option[@value=""][not(@selected)][not(@disabled)][.="[trans]Change&Me[/trans]"]] + /following-sibling::select + [@id="name_year"] + [@class="form-control"] + [./option[@value=""][not(@selected)][not(@disabled)][.="[trans]Change&Me[/trans]"]] + ] + [count(./select)=3] +' + ); + } + + public function testDateChoiceWithPlaceholderOnYear() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\DateType', null, [ + 'input' => 'string', + 'widget' => 'choice', + 'required' => false, + 'placeholder' => ['year' => 'Change&Me'], + ]); + + $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'my&class']], +'/div + [@class="my&class form-inline"] + [ + ./select + [@id="name_month"] + [@class="form-control"] + [./option[@value="1"]] + /following-sibling::select + [@id="name_day"] + [@class="form-control"] + [./option[@value="1"]] + /following-sibling::select + [@id="name_year"] + [@class="form-control"] + [./option[@value=""][not(@selected)][not(@disabled)][.="[trans]Change&Me[/trans]"]] + ] + [count(./select)=3] +' + ); + } + + public function testDateText() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\DateType', '2011-02-03', [ + 'input' => 'string', + 'widget' => 'text', + ]); + + $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'my&class']], +'/div + [@class="my&class form-inline"] + [ + ./input + [@id="name_month"] + [@type="text"] + [@class="form-control"] + [@value="2"] + /following-sibling::input + [@id="name_day"] + [@type="text"] + [@class="form-control"] + [@value="3"] + /following-sibling::input + [@id="name_year"] + [@type="text"] + [@class="form-control"] + [@value="2011"] + ] + [count(./input)=3] +' + ); + } + + public function testDateSingleText() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\DateType', '2011-02-03', [ + 'input' => 'string', + 'widget' => 'single_text', + ]); + + $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'my&class']], +'/input + [@type="date"] + [@name="name"] + [@class="my&class form-control"] + [@value="2011-02-03"] +' + ); + } + + public function testBirthDay() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\BirthdayType', '2000-02-03', [ + 'input' => 'string', + ]); + + $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'my&class']], +'/div + [@class="my&class form-inline"] + [ + ./select + [@id="name_month"] + [@class="form-control"] + [./option[@value="2"][@selected="selected"]] + /following-sibling::select + [@id="name_day"] + [@class="form-control"] + [./option[@value="3"][@selected="selected"]] + /following-sibling::select + [@id="name_year"] + [@class="form-control"] + [./option[@value="2000"][@selected="selected"]] + ] + [count(./select)=3] +' + ); + } + + public function testBirthDayWithPlaceholder() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\BirthdayType', '1950-01-01', [ + 'input' => 'string', + 'placeholder' => '', + 'required' => false, + ]); + + $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'my&class']], +'/div + [@class="my&class form-inline"] + [ + ./select + [@id="name_month"] + [@class="form-control"] + [./option[@value=""][not(@selected)][not(@disabled)][.=""]] + [./option[@value="1"][@selected="selected"]] + /following-sibling::select + [@id="name_day"] + [@class="form-control"] + [./option[@value=""][not(@selected)][not(@disabled)][.=""]] + [./option[@value="1"][@selected="selected"]] + /following-sibling::select + [@id="name_year"] + [@class="form-control"] + [./option[@value=""][not(@selected)][not(@disabled)][.=""]] + [./option[@value="1950"][@selected="selected"]] + ] + [count(./select)=3] +' + ); + } + + public function testEmail() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\EmailType', 'foo&bar'); + + $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'my&class']], +'/input + [@type="email"] + [@name="name"] + [@class="my&class form-control"] + [@value="foo&bar"] + [not(@maxlength)] +' + ); + } + + public function testEmailWithMaxLength() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\EmailType', 'foo&bar', [ + 'attr' => ['maxlength' => 123], + ]); + + $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'my&class']], +'/input + [@type="email"] + [@name="name"] + [@class="my&class form-control"] + [@value="foo&bar"] + [@maxlength="123"] +' + ); + } + + public function testHidden() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\HiddenType', 'foo&bar'); + + $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'my&class']], +'/input + [@type="hidden"] + [@name="name"] + [@class="my&class"] + [@value="foo&bar"] +' + ); + } + + public function testDisabled() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\TextType', null, [ + 'disabled' => true, + ]); + + $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'my&class']], +'/input + [@type="text"] + [@name="name"] + [@class="my&class form-control"] + [@disabled="disabled"] +' + ); + } + + public function testInteger() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\IntegerType', 123); + + $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'my&class']], +'/input + [@type="number"] + [@name="name"] + [@class="my&class form-control"] + [@value="123"] +' + ); + } + + public function testIntegerTypeWithGroupingRendersAsTextInput() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\IntegerType', 123, [ + 'grouping' => true, + ]); + + $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'my&class']], +'/input + [@type="text"] + [@name="name"] + [@class="my&class form-control"] + [@value="123"] +' + ); + } + + public function testLanguage() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\LanguageType', 'de'); + + $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'my&class']], +'/select + [@name="name"] + [@class="my&class form-control"] + [./option[@value="de"][@selected="selected"][.="German"]] + [count(./option)>200] +' + ); + } + + public function testLocale() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\LocaleType', 'de_AT'); + + $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'my&class']], +'/select + [@name="name"] + [@class="my&class form-control"] + [./option[@value="de_AT"][@selected="selected"][.="German (Austria)"]] + [count(./option)>200] +' + ); + } + + public function testMoney() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\MoneyType', 1234.56, [ + 'currency' => 'EUR', + ]); + + $this->assertWidgetMatchesXpath($form->createView(), ['id' => 'my&id', 'attr' => ['class' => 'my&class']], +'/div + [@class="input-group"] + [ + ./span + [@class="input-group-addon"] + [contains(.., "€")] + /following-sibling::input + [@id="my&id"] + [@type="text"] + [@name="name"] + [@class="my&class form-control"] + [@value="1234.56"] + ] +' + ); + } + + public function testMoneyWithoutCurrency() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\MoneyType', 1234.56, [ + 'currency' => false, + ]); + + $this->assertWidgetMatchesXpath($form->createView(), ['id' => 'my&id', 'attr' => ['class' => 'my&class']], +'/input + [@id="my&id"] + [@type="text"] + [@name="name"] + [@class="my&class form-control"] + [@value="1234.56"] + [not(preceding-sibling::*)] + [not(following-sibling::*)] +' + ); + } + + public function testNumber() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\NumberType', 1234.56); + + $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'my&class']], +'/input + [@type="text"] + [@name="name"] + [@class="my&class form-control"] + [@value="1234.56"] +' + ); + } + + public function testPassword() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\PasswordType', 'foo&bar'); + + $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'my&class']], +'/input + [@type="password"] + [@name="name"] + [@class="my&class form-control"] +' + ); + } + + public function testPasswordSubmittedWithNotAlwaysEmpty() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\PasswordType', null, [ + 'always_empty' => false, + ]); + $form->submit('foo&bar'); + + $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'my&class']], +'/input + [@type="password"] + [@name="name"] + [@class="my&class form-control"] + [@value="foo&bar"] +' + ); + } + + public function testPasswordWithMaxLength() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\PasswordType', 'foo&bar', [ + 'attr' => ['maxlength' => 123], + ]); + + $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'my&class']], +'/input + [@type="password"] + [@name="name"] + [@class="my&class form-control"] + [@maxlength="123"] +' + ); + } + + public function testPercent() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\PercentType', 0.1); + + $this->assertWidgetMatchesXpath($form->createView(), ['id' => 'my&id', 'attr' => ['class' => 'my&class']], +'/div + [@class="input-group"] + [ + ./input + [@id="my&id"] + [@type="text"] + [@name="name"] + [@class="my&class form-control"] + [@value="10"] + /following-sibling::span + [@class="input-group-addon"] + [contains(.., "%")] + ] +' + ); + } + + public function testCheckedRadio() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\RadioType', true); + + $this->assertWidgetMatchesXpath($form->createView(), ['id' => 'my&id', 'attr' => ['class' => 'my&class']], +'/div + [@class="radio"] + [ + ./label + [@class="required"] + [ + ./input + [@id="my&id"] + [@type="radio"] + [@name="name"] + [@class="my&class"] + [@checked="checked"] + [@value="1"] + ] + ] +' + ); + } + + public function testUncheckedRadio() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\RadioType', false); + + $this->assertWidgetMatchesXpath($form->createView(), ['id' => 'my&id', 'attr' => ['class' => 'my&class']], +'/div + [@class="radio"] + [ + ./label + [@class="required"] + [ + ./input + [@id="my&id"] + [@type="radio"] + [@name="name"] + [@class="my&class"] + [not(@checked)] + ] + ] +' + ); + } + + public function testRadioWithValue() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\RadioType', false, [ + 'value' => 'foo&bar', + ]); + + $this->assertWidgetMatchesXpath($form->createView(), ['id' => 'my&id', 'attr' => ['class' => 'my&class']], +'/div + [@class="radio"] + [ + ./label + [@class="required"] + [ + ./input + [@id="my&id"] + [@type="radio"] + [@name="name"] + [@class="my&class"] + [@value="foo&bar"] + ] + ] +' + ); + } + + public function testRange() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\RangeType', 42, ['attr' => ['min' => 5]]); + + $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'my&class']], +'/input + [@type="range"] + [@name="name"] + [@value="42"] + [@min="5"] + [@class="my&class form-control"] +' + ); + } + + public function testRangeWithMinMaxValues() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\RangeType', 42, ['attr' => ['min' => 5, 'max' => 57]]); + + $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'my&class']], +'/input + [@type="range"] + [@name="name"] + [@value="42"] + [@min="5"] + [@max="57"] + [@class="my&class form-control"] +' + ); + } + + public function testTextarea() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\TextareaType', 'foo&bar', [ + 'attr' => ['pattern' => 'foo'], + ]); + + $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'my&class']], +'/textarea + [@name="name"] + [@pattern="foo"] + [@class="my&class form-control"] + [.="foo&bar"] +' + ); + } + + public function testText() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\TextType', 'foo&bar'); + + $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'my&class']], +'/input + [@type="text"] + [@name="name"] + [@class="my&class form-control"] + [@value="foo&bar"] + [not(@maxlength)] +' + ); + } + + public function testTextWithMaxLength() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\TextType', 'foo&bar', [ + 'attr' => ['maxlength' => 123], + ]); + + $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'my&class']], +'/input + [@type="text"] + [@name="name"] + [@class="my&class form-control"] + [@value="foo&bar"] + [@maxlength="123"] +' + ); + } + + public function testSearch() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\SearchType', 'foo&bar'); + + $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'my&class']], +'/input + [@type="search"] + [@name="name"] + [@class="my&class form-control"] + [@value="foo&bar"] + [not(@maxlength)] +' + ); + } + + public function testTime() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\TimeType', '04:05:06', [ + 'input' => 'string', + 'with_seconds' => false, + ]); + + $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'my&class']], +'/div + [@class="my&class form-inline"] + [ + ./select + [@id="name_hour"] + [@class="form-control"] + [not(@size)] + [./option[@value="4"][@selected="selected"]] + /following-sibling::select + [@id="name_minute"] + [@class="form-control"] + [not(@size)] + [./option[@value="5"][@selected="selected"]] + ] + [count(./select)=2] +' + ); + } + + public function testTimeWithSeconds() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\TimeType', '04:05:06', [ + 'input' => 'string', + 'with_seconds' => true, + ]); + + $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'my&class']], +'/div + [@class="my&class form-inline"] + [ + ./select + [@id="name_hour"] + [@class="form-control"] + [not(@size)] + [./option[@value="4"][@selected="selected"]] + [count(./option)>23] + /following-sibling::select + [@id="name_minute"] + [@class="form-control"] + [not(@size)] + [./option[@value="5"][@selected="selected"]] + [count(./option)>59] + /following-sibling::select + [@id="name_second"] + [@class="form-control"] + [not(@size)] + [./option[@value="6"][@selected="selected"]] + [count(./option)>59] + ] + [count(./select)=3] +' + ); + } + + public function testTimeText() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\TimeType', '04:05:06', [ + 'input' => 'string', + 'widget' => 'text', + ]); + + $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'my&class']], +'/div + [@class="my&class form-inline"] + [ + ./input + [@type="text"] + [@id="name_hour"] + [@name="name[hour]"] + [@class="form-control"] + [@value="04"] + [@required="required"] + [not(@size)] + /following-sibling::input + [@type="text"] + [@id="name_minute"] + [@name="name[minute]"] + [@class="form-control"] + [@value="05"] + [@required="required"] + [not(@size)] + ] + [count(./input)=2] +' + ); + } + + public function testTimeSingleText() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\TimeType', '04:05:06', [ + 'input' => 'string', + 'widget' => 'single_text', + ]); + + $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'my&class']], +'/input + [@type="time"] + [@name="name"] + [@class="my&class form-control"] + [@value="04:05"] + [not(@size)] +' + ); + } + + public function testTimeWithPlaceholderGlobal() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\TimeType', null, [ + 'input' => 'string', + 'placeholder' => 'Change&Me', + 'required' => false, + ]); + + $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'my&class']], +'/div + [@class="my&class form-inline"] + [ + ./select + [@id="name_hour"] + [@class="form-control"] + [./option[@value=""][not(@selected)][not(@disabled)][.="[trans]Change&Me[/trans]"]] + [count(./option)>24] + /following-sibling::select + [@id="name_minute"] + [./option[@value=""][not(@selected)][not(@disabled)][.="[trans]Change&Me[/trans]"]] + [count(./option)>60] + ] + [count(./select)=2] +' + ); + } + + public function testTimeWithPlaceholderOnYear() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\TimeType', null, [ + 'input' => 'string', + 'required' => false, + 'placeholder' => ['hour' => 'Change&Me'], + ]); + + $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'my&class']], +'/div + [@class="my&class form-inline"] + [ + ./select + [@id="name_hour"] + [@class="form-control"] + [./option[@value=""][not(@selected)][not(@disabled)][.="[trans]Change&Me[/trans]"]] + [count(./option)>24] + /following-sibling::select + [@id="name_minute"] + [./option[@value="1"]] + [count(./option)>59] + ] + [count(./select)=2] +' + ); + } + + public function testTimezone() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\TimezoneType', 'Europe/Vienna'); + + $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'my&class']], +'/select + [@name="name"] + [@class="my&class form-control"] + [not(@required)] + [.//option[@value="Europe/Vienna"][@selected="selected"]] + [count(.//option)>200] +' + ); + } + + public function testTimezoneWithPlaceholder() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\TimezoneType', null, [ + 'placeholder' => 'Select&Timezone', + 'required' => false, + ]); + + $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'my&class']], +'/select + [@class="my&class form-control"] + [./option[@value=""][not(@selected)][not(@disabled)][.="[trans]Select&Timezone[/trans]"]] + [count(.//option)>201] +' + ); + } + + public function testUrlWithDefaultProtocol() + { + $url = 'http://www.example.com?foo1=bar1&foo2=bar2'; + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\UrlType', $url, ['default_protocol' => 'http']); + + $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'my&class']], +'/input + [@type="text"] + [@name="name"] + [@class="my&class form-control"] + [@value="http://www.example.com?foo1=bar1&foo2=bar2"] + [@inputmode="url"] +' + ); + } + + public function testUrlWithoutDefaultProtocol() + { + $url = 'http://www.example.com?foo1=bar1&foo2=bar2'; + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\UrlType', $url, ['default_protocol' => null]); + + $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'my&class']], + '/input + [@type="url"] + [@name="name"] + [@class="my&class form-control"] + [@value="http://www.example.com?foo1=bar1&foo2=bar2"] +' + ); + } + + public function testButton() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\ButtonType'); + + $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'my&class']], + '/button[@type="button"][@name="name"][.="[trans]Name[/trans]"][@class="my&class btn"]' + ); + } + + public function testButtonlabelWithoutTranslation() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\ButtonType', null, [ + 'translation_domain' => false, + ]); + + $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'my&class']], + '/button[@type="button"][@name="name"][.="Name"][@class="my&class btn"]' + ); + } + + public function testSubmit() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\SubmitType'); + + $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'my&class']], + '/button[@type="submit"][@name="name"][@class="my&class btn"]' + ); + } + + public function testReset() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\ResetType'); + + $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'my&class']], + '/button[@type="reset"][@name="name"][@class="my&class btn"]' + ); + } + + public function testWidgetAttributes() + { + $form = $this->factory->createNamed('text', 'Symfony\Component\Form\Extension\Core\Type\TextType', 'value', [ + 'required' => true, + 'disabled' => true, + 'attr' => ['readonly' => true, 'maxlength' => 10, 'pattern' => '\d+', 'class' => 'foobar', 'data-foo' => 'bar'], + ]); + + $html = $this->renderWidget($form->createView()); + + // compare plain HTML to check the whitespace + $this->assertSame('<input type="text" id="text" name="text" disabled="disabled" required="required" readonly="readonly" maxlength="10" pattern="\d+" class="foobar form-control" data-foo="bar" value="value" />', $html); + } + + public function testWidgetAttributeNameRepeatedIfTrue() + { + $form = $this->factory->createNamed('text', 'Symfony\Component\Form\Extension\Core\Type\TextType', 'value', [ + 'attr' => ['foo' => true], + ]); + + $html = $this->renderWidget($form->createView()); + + // foo="foo" + $this->assertSame('<input type="text" id="text" name="text" required="required" foo="foo" class="form-control" value="value" />', $html); + } + + public function testButtonAttributes() + { + $form = $this->factory->createNamed('button', 'Symfony\Component\Form\Extension\Core\Type\ButtonType', null, [ + 'disabled' => true, + 'attr' => ['class' => 'foobar', 'data-foo' => 'bar'], + ]); + + $html = $this->renderWidget($form->createView()); + + // compare plain HTML to check the whitespace + $this->assertSame('<button type="button" id="button" name="button" disabled="disabled" class="foobar btn" data-foo="bar">[trans]Button[/trans]</button>', $html); + } + + public function testButtonAttributeNameRepeatedIfTrue() + { + $form = $this->factory->createNamed('button', 'Symfony\Component\Form\Extension\Core\Type\ButtonType', null, [ + 'attr' => ['foo' => true], + ]); + + $html = $this->renderWidget($form->createView()); + + // foo="foo" + $this->assertSame('<button type="button" id="button" name="button" foo="foo" class="btn-default btn">[trans]Button[/trans]</button>', $html); + } + + public function testTel() + { + $tel = '0102030405'; + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\TelType', $tel); + + $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'my&class']], + '/input + [@type="tel"] + [@name="name"] + [@class="my&class form-control"] + [@value="0102030405"] +' + ); + } + + public function testColor() + { + $color = '#0000ff'; + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\ColorType', $color); + + $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'my&class']], + '/input + [@type="color"] + [@name="name"] + [@class="my&class form-control"] + [@value="#0000ff"] +' + ); + } +} diff --git a/vendor/symfony/twig-bridge/Tests/Extension/AbstractBootstrap4HorizontalLayoutTest.php b/vendor/symfony/twig-bridge/Tests/Extension/AbstractBootstrap4HorizontalLayoutTest.php new file mode 100644 index 0000000000000000000000000000000000000000..51a1360f63f4dfba6b7426c0ceb20156abf51f65 --- /dev/null +++ b/vendor/symfony/twig-bridge/Tests/Extension/AbstractBootstrap4HorizontalLayoutTest.php @@ -0,0 +1,217 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\Twig\Tests\Extension; + +use Symfony\Component\Form\FormError; + +/** + * Abstract class providing test cases for the Bootstrap 4 horizontal Twig form theme. + * + * @author Hidde Wieringa <hidde@hiddewieringa.nl> + */ +abstract class AbstractBootstrap4HorizontalLayoutTest extends AbstractBootstrap4LayoutTest +{ + public function testRow() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\TextType'); + $form->addError(new FormError('[trans]Error![/trans]')); + $view = $form->createView(); + $html = $this->renderRow($view); + + $this->assertMatchesXpath($html, + '/div + [ + ./label[@for="name"] + [ + ./span[@class="alert alert-danger d-block"] + [./span[@class="d-block"] + [./span[.="[trans]Error[/trans]"]] + [./span[.="[trans]Error![/trans]"]] + ] + [count(./span)=1] + ] + /following-sibling::div[./input[@id="name"]] + ] +' + ); + } + + public function testLabelOnForm() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\DateType'); + $view = $form->createView(); + $this->renderWidget($view, ['label' => 'foo']); + $html = $this->renderLabel($view); + + $this->assertMatchesXpath($html, +'/legend + [@class="col-form-label col-sm-2 col-form-label required"] + [.="[trans]Name[/trans]"] +' + ); + } + + public function testLabelDoesNotRenderFieldAttributes() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\TextType'); + $html = $this->renderLabel($form->createView(), null, [ + 'attr' => [ + 'class' => 'my&class', + ], + ]); + + $this->assertMatchesXpath($html, +'/label + [@for="name"] + [@class="col-form-label col-sm-2 required"] +' + ); + } + + public function testLabelWithCustomAttributesPassedDirectly() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\TextType'); + $html = $this->renderLabel($form->createView(), null, [ + 'label_attr' => [ + 'class' => 'my&class', + ], + ]); + + $this->assertMatchesXpath($html, +'/label + [@for="name"] + [@class="my&class col-form-label col-sm-2 required"] +' + ); + } + + public function testLabelWithCustomTextAndCustomAttributesPassedDirectly() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\TextType'); + $html = $this->renderLabel($form->createView(), 'Custom label', [ + 'label_attr' => [ + 'class' => 'my&class', + ], + ]); + + $this->assertMatchesXpath($html, +'/label + [@for="name"] + [@class="my&class col-form-label col-sm-2 required"] + [.="[trans]Custom label[/trans]"] +' + ); + } + + public function testLabelWithCustomTextAsOptionAndCustomAttributesPassedDirectly() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\TextType', null, [ + 'label' => 'Custom label', + ]); + $html = $this->renderLabel($form->createView(), null, [ + 'label_attr' => [ + 'class' => 'my&class', + ], + ]); + + $this->assertMatchesXpath($html, +'/label + [@for="name"] + [@class="my&class col-form-label col-sm-2 required"] + [.="[trans]Custom label[/trans]"] +' + ); + } + + public function testLegendOnExpandedType() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\ChoiceType', null, [ + 'label' => 'Custom label', + 'expanded' => true, + 'choices' => ['Choice&A' => '&a', 'Choice&B' => '&b'], + ]); + $view = $form->createView(); + $this->renderWidget($view); + $html = $this->renderLabel($view); + + $this->assertMatchesXpath($html, +'/legend + [@class="col-sm-2 col-form-label required"] + [.="[trans]Custom label[/trans]"] +' + ); + } + + public function testStartTag() + { + $form = $this->factory->create('Symfony\Component\Form\Extension\Core\Type\FormType', null, [ + 'method' => 'get', + 'action' => 'http://example.com/directory', + ]); + + $html = $this->renderStart($form->createView()); + + $this->assertSame('<form name="form" method="get" action="http://example.com/directory">', $html); + } + + public function testStartTagWithOverriddenVars() + { + $form = $this->factory->create('Symfony\Component\Form\Extension\Core\Type\FormType', null, [ + 'method' => 'put', + 'action' => 'http://example.com/directory', + ]); + + $html = $this->renderStart($form->createView(), [ + 'method' => 'post', + 'action' => 'http://foo.com/directory', + ]); + + $this->assertSame('<form name="form" method="post" action="http://foo.com/directory">', $html); + } + + public function testStartTagForMultipartForm() + { + $form = $this->factory->createBuilder('Symfony\Component\Form\Extension\Core\Type\FormType', null, [ + 'method' => 'get', + 'action' => 'http://example.com/directory', + ]) + ->add('file', 'Symfony\Component\Form\Extension\Core\Type\FileType') + ->getForm(); + + $html = $this->renderStart($form->createView()); + + $this->assertSame('<form name="form" method="get" action="http://example.com/directory" enctype="multipart/form-data">', $html); + } + + public function testStartTagWithExtraAttributes() + { + $form = $this->factory->create('Symfony\Component\Form\Extension\Core\Type\FormType', null, [ + 'method' => 'get', + 'action' => 'http://example.com/directory', + ]); + + $html = $this->renderStart($form->createView(), [ + 'attr' => ['class' => 'foobar'], + ]); + + $this->assertSame('<form name="form" method="get" action="http://example.com/directory" class="foobar">', $html); + } + + public function testCheckboxRow() + { + $form = $this->factory->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\CheckboxType'); + $view = $form->createView(); + $html = $this->renderRow($view, ['label' => 'foo']); + + $this->assertMatchesXpath($html, '/div[@class="form-group row"]/div[@class="col-sm-2" or @class="col-sm-10"]', 2); + } +} diff --git a/vendor/symfony/twig-bridge/Tests/Extension/AbstractBootstrap4LayoutTest.php b/vendor/symfony/twig-bridge/Tests/Extension/AbstractBootstrap4LayoutTest.php new file mode 100644 index 0000000000000000000000000000000000000000..30b5ea10e571c770efffe4a2a70094a903ae58ac --- /dev/null +++ b/vendor/symfony/twig-bridge/Tests/Extension/AbstractBootstrap4LayoutTest.php @@ -0,0 +1,986 @@ +<?php + +/* + * This file is part of the Symfony package. + * + * (c) Fabien Potencier <fabien@symfony.com> + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bridge\Twig\Tests\Extension; + +use Symfony\Component\Form\Extension\Core\Type\ButtonType; +use Symfony\Component\Form\Extension\Core\Type\CheckboxType; +use Symfony\Component\Form\Extension\Core\Type\ChoiceType; +use Symfony\Component\Form\Extension\Core\Type\DateType; +use Symfony\Component\Form\Extension\Core\Type\FileType; +use Symfony\Component\Form\Extension\Core\Type\MoneyType; +use Symfony\Component\Form\Extension\Core\Type\PercentType; +use Symfony\Component\Form\Extension\Core\Type\RadioType; +use Symfony\Component\Form\Extension\Core\Type\TextType; +use Symfony\Component\Form\FormError; + +/** + * Abstract class providing test cases for the Bootstrap 4 Twig form theme. + * + * @author Hidde Wieringa <hidde@hiddewieringa.nl> + */ +abstract class AbstractBootstrap4LayoutTest extends AbstractBootstrap3LayoutTest +{ + public function testRow() + { + $form = $this->factory->createNamed('name', TextType::class); + $form->addError(new FormError('[trans]Error![/trans]')); + $view = $form->createView(); + $html = $this->renderRow($view); + + $this->assertMatchesXpath($html, + '/div + [ + ./label[@for="name"] + [ + ./span[@class="alert alert-danger d-block"] + [./span[@class="d-block"] + [./span[.="[trans]Error[/trans]"]] + [./span[.="[trans]Error![/trans]"]] + ] + [count(./span)=1] + ] + /following-sibling::input[@id="name"] + ] +' + ); + } + + public function testLabelOnForm() + { + $form = $this->factory->createNamed('name', DateType::class); + $view = $form->createView(); + $this->renderWidget($view, ['label' => 'foo']); + $html = $this->renderLabel($view); + + $this->assertMatchesXpath($html, +'/legend + [@class="col-form-label required"] + [.="[trans]Name[/trans]"] +' + ); + } + + public function testLabelDoesNotRenderFieldAttributes() + { + $form = $this->factory->createNamed('name', TextType::class); + $html = $this->renderLabel($form->createView(), null, [ + 'attr' => [ + 'class' => 'my&class', + ], + ]); + + $this->assertMatchesXpath($html, +'/label + [@for="name"] + [@class="required"] +' + ); + } + + public function testLabelWithCustomAttributesPassedDirectly() + { + $form = $this->factory->createNamed('name', TextType::class); + $html = $this->renderLabel($form->createView(), null, [ + 'label_attr' => [ + 'class' => 'my&class', + ], + ]); + + $this->assertMatchesXpath($html, +'/label + [@for="name"] + [@class="my&class required"] +' + ); + } + + public function testLabelWithCustomTextAndCustomAttributesPassedDirectly() + { + $form = $this->factory->createNamed('name', TextType::class); + $html = $this->renderLabel($form->createView(), 'Custom label', [ + 'label_attr' => [ + 'class' => 'my&class', + ], + ]); + + $this->assertMatchesXpath($html, +'/label + [@for="name"] + [@class="my&class required"] + [.="[trans]Custom label[/trans]"] +' + ); + } + + public function testLabelWithCustomTextAsOptionAndCustomAttributesPassedDirectly() + { + $form = $this->factory->createNamed('name', TextType::class, null, [ + 'label' => 'Custom label', + ]); + $html = $this->renderLabel($form->createView(), null, [ + 'label_attr' => [ + 'class' => 'my&class', + ], + ]); + + $this->assertMatchesXpath($html, +'/label + [@for="name"] + [@class="my&class required"] + [.="[trans]Custom label[/trans]"] +' + ); + } + + public function testLegendOnExpandedType() + { + $form = $this->factory->createNamed('name', ChoiceType::class, null, [ + 'label' => 'Custom label', + 'expanded' => true, + 'choices' => ['Choice&A' => '&a', 'Choice&B' => '&b'], + ]); + $view = $form->createView(); + $this->renderWidget($view); + $html = $this->renderLabel($view); + + $this->assertMatchesXpath($html, +'/legend + [@class="col-form-label required"] + [.="[trans]Custom label[/trans]"] +' + ); + } + + public function testErrors() + { + $form = $this->factory->createNamed('name', TextType::class); + $form->addError(new FormError('[trans]Error 1[/trans]')); + $form->addError(new FormError('[trans]Error 2[/trans]')); + $view = $form->createView(); + $html = $this->renderErrors($view); + + $this->assertMatchesXpath($html, +'/span + [@class="alert alert-danger d-block"] + [ + ./span[@class="d-block"] + [./span[.="[trans]Error[/trans]"]] + [./span[.="[trans]Error 1[/trans]"]] + + /following-sibling::span[@class="d-block"] + [./span[.="[trans]Error[/trans]"]] + [./span[.="[trans]Error 2[/trans]"]] + ] + [count(./span)=2] +' + ); + } + + public function testErrorWithNoLabel() + { + $form = $this->factory->createNamed('name', TextType::class, ['label' => false]); + $form->addError(new FormError('[trans]Error 1[/trans]')); + $view = $form->createView(); + $html = $this->renderLabel($view); + + $this->assertMatchesXpath($html, '//span[.="[trans]Error[/trans]"]'); + } + + public function testCheckedCheckbox() + { + $form = $this->factory->createNamed('name', CheckboxType::class, true); + + $this->assertWidgetMatchesXpath($form->createView(), ['id' => 'my&id', 'attr' => ['class' => 'my&class']], +'/div + [@class="form-check"] + [ + ./input[@type="checkbox"][@name="name"][@id="my&id"][@class="my&class form-check-input"][@checked="checked"][@value="1"] + /following-sibling::label + [.="[trans]Name[/trans]"] + [@class="form-check-label required"] + ] +' + ); + } + + public function testSingleChoiceAttributesWithMainAttributes() + { + $form = $this->factory->createNamed('name', ChoiceType::class, '&a', [ + 'choices' => ['Choice&A' => '&a', 'Choice&B' => '&b'], + 'multiple' => false, + 'expanded' => false, + 'attr' => ['class' => 'bar&baz'], + ]); + + $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'bar&baz']], +'/select + [@name="name"] + [@class="bar&baz form-control"] + [not(@required)] + [ + ./option[@value="&a"][@selected="selected"][.="[trans]Choice&A[/trans]"] + /following-sibling::option[@value="&b"][not(@selected)][.="[trans]Choice&B[/trans]"] + ] + [count(./option)=2] +' + ); + } + + public function testSingleExpandedChoiceAttributesWithMainAttributes() + { + $form = $this->factory->createNamed('name', ChoiceType::class, '&a', [ + 'choices' => ['Choice&A' => '&a', 'Choice&B' => '&b'], + 'multiple' => false, + 'expanded' => true, + 'attr' => ['class' => 'bar&baz'], + ]); + + $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'bar&baz']], +'/div + [@class="bar&baz"] + [ + ./div + [@class="form-check"] + [ + ./input[@type="radio"][@name="name"][@id="name_0"][@value="&a"][@checked] + /following-sibling::label + [.="[trans]Choice&A[/trans]"] + ] + /following-sibling::div + [@class="form-check"] + [ + ./input[@type="radio"][@name="name"][@id="name_1"][@value="&b"][not(@checked)] + /following-sibling::label + [.="[trans]Choice&B[/trans]"] + ] + /following-sibling::input[@type="hidden"][@id="name__token"] + ] +' + ); + } + + public function testUncheckedCheckbox() + { + $form = $this->factory->createNamed('name', CheckboxType::class, false); + + $this->assertWidgetMatchesXpath($form->createView(), ['id' => 'my&id', 'attr' => ['class' => 'my&class']], +'/div + [@class="form-check"] + [ + ./input[@type="checkbox"][@name="name"][@id="my&id"][@class="my&class form-check-input"][not(@checked)] + /following-sibling::label + [.="[trans]Name[/trans]"] + ] +' + ); + } + + public function testCheckboxWithValue() + { + $form = $this->factory->createNamed('name', CheckboxType::class, false, [ + 'value' => 'foo&bar', + ]); + + $this->assertWidgetMatchesXpath($form->createView(), ['id' => 'my&id', 'attr' => ['class' => 'my&class']], +'/div + [@class="form-check"] + [ + ./input[@type="checkbox"][@name="name"][@id="my&id"][@class="my&class form-check-input"][@value="foo&bar"] + /following-sibling::label + [.="[trans]Name[/trans]"] + ] +' + ); + } + + public function testSingleChoiceExpanded() + { + $form = $this->factory->createNamed('name', ChoiceType::class, '&a', [ + 'choices' => ['Choice&A' => '&a', 'Choice&B' => '&b'], + 'multiple' => false, + 'expanded' => true, + ]); + + $this->assertWidgetMatchesXpath($form->createView(), [], +'/div + [ + ./div + [@class="form-check"] + [ + ./input[@type="radio"][@name="name"][@id="name_0"][@value="&a"][@checked] + /following-sibling::label + [.="[trans]Choice&A[/trans]"] + ] + /following-sibling::div + [@class="form-check"] + [ + ./input[@type="radio"][@name="name"][@id="name_1"][@value="&b"][not(@checked)] + /following-sibling::label + [.="[trans]Choice&B[/trans]"] + ] + /following-sibling::input[@type="hidden"][@id="name__token"] + ] +' + ); + } + + public function testSingleChoiceExpandedWithLabelsAsFalse() + { + $form = $this->factory->createNamed('name', ChoiceType::class, '&a', [ + 'choices' => ['Choice&A' => '&a', 'Choice&B' => '&b'], + 'choice_label' => false, + 'multiple' => false, + 'expanded' => true, + ]); + + $this->assertWidgetMatchesXpath($form->createView(), [], +'/div + [ + ./div + [@class="form-check"] + [ + ./input[@type="radio"][@name="name"][@id="name_0"][@value="&a"][@checked] + /following-sibling::label + ] + /following-sibling::div + [@class="form-check"] + [ + ./input[@type="radio"][@name="name"][@id="name_1"][@value="&b"][not(@checked)] + /following-sibling::label + ] + /following-sibling::input[@type="hidden"][@id="name__token"] + ] +' + ); + } + + public function testSingleChoiceExpandedWithLabelsSetByCallable() + { + $form = $this->factory->createNamed('name', ChoiceType::class, '&a', [ + 'choices' => ['Choice&A' => '&a', 'Choice&B' => '&b', 'Choice&C' => '&c'], + 'choice_label' => function ($choice, $label, $value) { + if ('&b' === $choice) { + return false; + } + + return 'label.'.$value; + }, + 'multiple' => false, + 'expanded' => true, + ]); + + $this->assertWidgetMatchesXpath($form->createView(), [], +'/div + [ + ./div + [@class="form-check"] + [ + ./input[@type="radio"][@name="name"][@id="name_0"][@value="&a"][@checked] + /following-sibling::label + [.="[trans]label.&a[/trans]"] + ] + /following-sibling::div + [@class="form-check"] + [ + ./input[@type="radio"][@name="name"][@id="name_1"][@value="&b"][not(@checked)] + /following-sibling::label + ] + /following-sibling::div + [@class="form-check"] + [ + ./input[@type="radio"][@name="name"][@id="name_2"][@value="&c"][not(@checked)] + /following-sibling::label + [.="[trans]label.&c[/trans]"] + ] + /following-sibling::input[@type="hidden"][@id="name__token"] + ] +' + ); + } + + public function testSingleChoiceExpandedWithLabelsSetFalseByCallable() + { + $form = $this->factory->createNamed('name', ChoiceType::class, '&a', [ + 'choices' => ['Choice&A' => '&a', 'Choice&B' => '&b'], + 'choice_label' => function () { + return false; + }, + 'multiple' => false, + 'expanded' => true, + ]); + + $this->assertWidgetMatchesXpath($form->createView(), [], +'/div + [ + ./div + [@class="form-check"] + [ + ./input[@type="radio"][@name="name"][@id="name_0"][@value="&a"][@checked] + /following-sibling::label + ] + /following-sibling::div + [@class="form-check"] + [ + ./input[@type="radio"][@name="name"][@id="name_1"][@value="&b"][not(@checked)] + /following-sibling::label + ] + /following-sibling::input[@type="hidden"][@id="name__token"] + ] +' + ); + } + + public function testSingleChoiceExpandedWithoutTranslation() + { + $form = $this->factory->createNamed('name', ChoiceType::class, '&a', [ + 'choices' => ['Choice&A' => '&a', 'Choice&B' => '&b'], + 'multiple' => false, + 'expanded' => true, + 'choice_translation_domain' => false, + ]); + + $this->assertWidgetMatchesXpath($form->createView(), [], +'/div + [ + ./div + [@class="form-check"] + [ + ./input[@type="radio"][@name="name"][@id="name_0"][@value="&a"][@checked] + /following-sibling::label + [.="Choice&A"] + ] + /following-sibling::div + [@class="form-check"] + [ + ./input[@type="radio"][@name="name"][@id="name_1"][@value="&b"][not(@checked)] + /following-sibling::label + [.="Choice&B"] + ] + /following-sibling::input[@type="hidden"][@id="name__token"] + ] +' + ); + } + + public function testSingleChoiceExpandedAttributes() + { + $form = $this->factory->createNamed('name', ChoiceType::class, '&a', [ + 'choices' => ['Choice&A' => '&a', 'Choice&B' => '&b'], + 'choice_attr' => ['Choice&B' => ['class' => 'foo&bar']], + 'multiple' => false, + 'expanded' => true, + ]); + + $this->assertWidgetMatchesXpath($form->createView(), [], +'/div + [ + ./div + [@class="form-check"] + [ + ./input[@type="radio"][@name="name"][@id="name_0"][@value="&a"][@checked] + /following-sibling::label + [.="[trans]Choice&A[/trans]"] + ] + /following-sibling::div + [@class="form-check"] + [ + ./input[@type="radio"][@name="name"][@id="name_1"][@value="&b"][not(@checked)][@class="foo&bar form-check-input"] + /following-sibling::label + [.="[trans]Choice&B[/trans]"] + ] + /following-sibling::input[@type="hidden"][@id="name__token"] + ] +' + ); + } + + public function testSingleChoiceExpandedWithPlaceholder() + { + $form = $this->factory->createNamed('name', ChoiceType::class, '&a', [ + 'choices' => ['Choice&A' => '&a', 'Choice&B' => '&b'], + 'multiple' => false, + 'expanded' => true, + 'placeholder' => 'Test&Me', + 'required' => false, + ]); + + $this->assertWidgetMatchesXpath($form->createView(), [], +'/div + [ + ./div + [@class="form-check"] + [ + ./input[@type="radio"][@name="name"][@id="name_placeholder"][not(@checked)] + /following-sibling::label + [.="[trans]Test&Me[/trans]"] + ] + /following-sibling::div + [@class="form-check"] + [ + ./input[@type="radio"][@name="name"][@id="name_0"][@checked] + /following-sibling::label + [.="[trans]Choice&A[/trans]"] + ] + /following-sibling::div + [@class="form-check"] + [ + ./input[@type="radio"][@name="name"][@id="name_1"][not(@checked)] + /following-sibling::label + [.="[trans]Choice&B[/trans]"] + ] + /following-sibling::input[@type="hidden"][@id="name__token"] + ] +' + ); + } + + public function testSingleChoiceExpandedWithPlaceholderWithoutTranslation() + { + $form = $this->factory->createNamed('name', ChoiceType::class, '&a', [ + 'choices' => ['Choice&A' => '&a', 'Choice&B' => '&b'], + 'multiple' => false, + 'expanded' => true, + 'required' => false, + 'choice_translation_domain' => false, + 'placeholder' => 'Placeholder&Not&Translated', + ]); + + $this->assertWidgetMatchesXpath($form->createView(), [], +'/div + [ + ./div + [@class="form-check"] + [ + ./input[@type="radio"][@name="name"][@id="name_placeholder"][not(@checked)] + /following-sibling::label + [.="Placeholder&Not&Translated"] + ] + /following-sibling::div + [@class="form-check"] + [ + ./input[@type="radio"][@name="name"][@id="name_0"][@checked] + /following-sibling::label + [.="Choice&A"] + ] + /following-sibling::div + [@class="form-check"] + [ + ./input[@type="radio"][@name="name"][@id="name_1"][not(@checked)] + /following-sibling::label + [.="Choice&B"] + ] + /following-sibling::input[@type="hidden"][@id="name__token"] + ] +' + ); + } + + public function testSingleChoiceExpandedWithBooleanValue() + { + $form = $this->factory->createNamed('name', ChoiceType::class, true, [ + 'choices' => ['Choice&A' => '1', 'Choice&B' => '0'], + 'multiple' => false, + 'expanded' => true, + ]); + + $this->assertWidgetMatchesXpath($form->createView(), [], +'/div + [ + ./div + [@class="form-check"] + [ + ./input[@type="radio"][@name="name"][@id="name_0"][@checked] + /following-sibling::label + [.="[trans]Choice&A[/trans]"] + ] + /following-sibling::div + [@class="form-check"] + [ + ./input[@type="radio"][@name="name"][@id="name_1"][not(@checked)] + /following-sibling::label + [.="[trans]Choice&B[/trans]"] + ] + /following-sibling::input[@type="hidden"][@id="name__token"] + ] +' + ); + } + + public function testMultipleChoiceExpanded() + { + $form = $this->factory->createNamed('name', ChoiceType::class, ['&a', '&c'], [ + 'choices' => ['Choice&A' => '&a', 'Choice&B' => '&b', 'Choice&C' => '&c'], + 'multiple' => true, + 'expanded' => true, + 'required' => true, + ]); + + $this->assertWidgetMatchesXpath($form->createView(), [], +'/div + [ + ./div + [@class="form-check"] + [ + ./input[@type="checkbox"][@name="name[]"][@id="name_0"][@checked][not(@required)] + /following-sibling::label + [.="[trans]Choice&A[/trans]"] + ] + /following-sibling::div + [@class="form-check"] + [ + ./input[@type="checkbox"][@name="name[]"][@id="name_1"][not(@checked)][not(@required)] + /following-sibling::label + [.="[trans]Choice&B[/trans]"] + ] + /following-sibling::div + [@class="form-check"] + [ + ./input[@type="checkbox"][@name="name[]"][@id="name_2"][@checked][not(@required)] + /following-sibling::label + [.="[trans]Choice&C[/trans]"] + ] + /following-sibling::input[@type="hidden"][@id="name__token"] + ] +' + ); + } + + public function testMultipleChoiceExpandedWithLabelsAsFalse() + { + $form = $this->factory->createNamed('name', ChoiceType::class, ['&a'], [ + 'choices' => ['Choice&A' => '&a', 'Choice&B' => '&b'], + 'choice_label' => false, + 'multiple' => true, + 'expanded' => true, + ]); + + $this->assertWidgetMatchesXpath($form->createView(), [], +'/div + [ + ./div + [@class="form-check"] + [ + ./input[@type="checkbox"][@name="name[]"][@id="name_0"][@value="&a"][@checked] + /following-sibling::label + ] + /following-sibling::div + [@class="form-check"] + [ + ./input[@type="checkbox"][@name="name[]"][@id="name_1"][@value="&b"][not(@checked)] + /following-sibling::label + ] + /following-sibling::input[@type="hidden"][@id="name__token"] + ] +' + ); + } + + public function testMultipleChoiceExpandedWithLabelsSetByCallable() + { + $form = $this->factory->createNamed('name', ChoiceType::class, ['&a'], [ + 'choices' => ['Choice&A' => '&a', 'Choice&B' => '&b', 'Choice&C' => '&c'], + 'choice_label' => function ($choice, $label, $value) { + if ('&b' === $choice) { + return false; + } + + return 'label.'.$value; + }, + 'multiple' => true, + 'expanded' => true, + ]); + + $this->assertWidgetMatchesXpath($form->createView(), [], + '/div + [ + ./div + [@class="form-check"] + [ + ./input[@type="checkbox"][@name="name[]"][@id="name_0"][@value="&a"][@checked] + /following-sibling::label + [.="[trans]label.&a[/trans]"] + ] + /following-sibling::div + [@class="form-check"] + [ + ./input[@type="checkbox"][@name="name[]"][@id="name_1"][@value="&b"][not(@checked)] + /following-sibling::label + ] + /following-sibling::div + [@class="form-check"] + [ + ./input[@type="checkbox"][@name="name[]"][@id="name_2"][@value="&c"][not(@checked)] + /following-sibling::label + [.="[trans]label.&c[/trans]"] + ] + /following-sibling::input[@type="hidden"][@id="name__token"] + ] +' + ); + } + + public function testMultipleChoiceExpandedWithLabelsSetFalseByCallable() + { + $form = $this->factory->createNamed('name', ChoiceType::class, ['&a'], [ + 'choices' => ['Choice&A' => '&a', 'Choice&B' => '&b'], + 'choice_label' => function () { + return false; + }, + 'multiple' => true, + 'expanded' => true, + ]); + + $this->assertWidgetMatchesXpath($form->createView(), [], +'/div + [ + ./div + [@class="form-check"] + [ + ./input[@type="checkbox"][@name="name[]"][@id="name_0"][@value="&a"][@checked] + /following-sibling::label + ] + /following-sibling::div + [@class="form-check"] + [ + ./input[@type="checkbox"][@name="name[]"][@id="name_1"][@value="&b"][not(@checked)] + /following-sibling::label + ] + /following-sibling::input[@type="hidden"][@id="name__token"] + ] +' + ); + } + + public function testMultipleChoiceExpandedWithoutTranslation() + { + $form = $this->factory->createNamed('name', ChoiceType::class, ['&a', '&c'], [ + 'choices' => ['Choice&A' => '&a', 'Choice&B' => '&b', 'Choice&C' => '&c'], + 'multiple' => true, + 'expanded' => true, + 'required' => true, + 'choice_translation_domain' => false, + ]); + + $this->assertWidgetMatchesXpath($form->createView(), [], +'/div + [ + ./div + [@class="form-check"] + [ + ./input[@type="checkbox"][@name="name[]"][@id="name_0"][@checked][not(@required)] + /following-sibling::label + [.="Choice&A"] + ] + /following-sibling::div + [@class="form-check"] + [ + ./input[@type="checkbox"][@name="name[]"][@id="name_1"][not(@checked)][not(@required)] + /following-sibling::label + [.="Choice&B"] + ] + /following-sibling::div + [@class="form-check"] + [ + ./input[@type="checkbox"][@name="name[]"][@id="name_2"][@checked][not(@required)] + /following-sibling::label + [.="Choice&C"] + ] + /following-sibling::input[@type="hidden"][@id="name__token"] + ] +' + ); + } + + public function testMultipleChoiceExpandedAttributes() + { + $form = $this->factory->createNamed('name', ChoiceType::class, ['&a', '&c'], [ + 'choices' => ['Choice&A' => '&a', 'Choice&B' => '&b', 'Choice&C' => '&c'], + 'choice_attr' => ['Choice&B' => ['class' => 'foo&bar']], + 'multiple' => true, + 'expanded' => true, + 'required' => true, + ]); + + $this->assertWidgetMatchesXpath($form->createView(), [], +'/div + [ + ./div + [@class="form-check"] + [ + ./input[@type="checkbox"][@name="name[]"][@id="name_0"][@checked][not(@required)] + /following-sibling::label + [.="[trans]Choice&A[/trans]"] + ] + /following-sibling::div + [@class="form-check"] + [ + ./input[@type="checkbox"][@name="name[]"][@id="name_1"][not(@checked)][not(@required)][@class="foo&bar form-check-input"] + /following-sibling::label + [.="[trans]Choice&B[/trans]"] + ] + /following-sibling::div + [@class="form-check"] + [ + ./input[@type="checkbox"][@name="name[]"][@id="name_2"][@checked][not(@required)] + /following-sibling::label + [.="[trans]Choice&C[/trans]"] + ] + /following-sibling::input[@type="hidden"][@id="name__token"] + ] +' + ); + } + + public function testCheckedRadio() + { + $form = $this->factory->createNamed('name', RadioType::class, true); + + $this->assertWidgetMatchesXpath($form->createView(), ['id' => 'my&id', 'attr' => ['class' => 'my&class']], +'/div + [@class="form-check"] + [ + ./input + [@id="my&id"] + [@type="radio"] + [@name="name"] + [@class="my&class form-check-input"] + [@checked="checked"] + [@value="1"] + /following-sibling::label + [@class="form-check-label required"] + ] +' + ); + } + + public function testUncheckedRadio() + { + $form = $this->factory->createNamed('name', RadioType::class, false); + + $this->assertWidgetMatchesXpath($form->createView(), ['id' => 'my&id', 'attr' => ['class' => 'my&class']], +'/div + [@class="form-check"] + [ + ./input + [@id="my&id"] + [@type="radio"] + [@name="name"] + [@class="my&class form-check-input"] + [not(@checked)] + /following-sibling::label + [@class="form-check-label required"] + ] +' + ); + } + + public function testRadioWithValue() + { + $form = $this->factory->createNamed('name', RadioType::class, false, [ + 'value' => 'foo&bar', + ]); + + $this->assertWidgetMatchesXpath($form->createView(), ['id' => 'my&id', 'attr' => ['class' => 'my&class']], +'/div + [@class="form-check"] + [ + ./input + [@id="my&id"] + [@type="radio"] + [@name="name"] + [@class="my&class form-check-input"] + [@value="foo&bar"] + /following-sibling::label + [@class="form-check-label required"] + [@for="my&id"] + ] +' + ); + } + + public function testButtonAttributeNameRepeatedIfTrue() + { + $form = $this->factory->createNamed('button', ButtonType::class, null, [ + 'attr' => ['foo' => true], + ]); + + $html = $this->renderWidget($form->createView()); + + // foo="foo" + $this->assertSame('<button type="button" id="button" name="button" foo="foo" class="btn-secondary btn">[trans]Button[/trans]</button>', $html); + } + + public function testFile() + { + $form = $this->factory->createNamed('name', FileType::class); + + $this->assertWidgetMatchesXpath($form->createView(), ['attr' => ['class' => 'my&class form-control-file']], +'/input + [@type="file"] +' + ); + } + + public function testMoney() + { + $form = $this->factory->createNamed('name', MoneyType::class, 1234.56, [ + 'currency' => 'EUR', + ]); + + $this->assertWidgetMatchesXpath($form->createView(), ['id' => 'my&id', 'attr' => ['class' => 'my&class']], + '/div + [@class="input-group"] + [ + ./div + [@class="input-group-prepend"] + [ + ./span + [@class="input-group-text"] + [contains(.., "€")] + ] + /following-sibling::input + [@id="my&id"] + [@type="text"] + [@name="name"] + [@class="my&class form-control"] + [@value="1234.56"] + ] +' + ); + } + + public function testPercent() + { + $form = $this->factory->createNamed('name', PercentType::class, 0.1); + + $this->assertWidgetMatchesXpath($form->createView(), ['id' => 'my&id', 'attr' => ['class' => 'my&class']], + '/div + [@class="input-group"] + [ + ./input + [@id="my&id"] + [@type="text"] + [@name="name"] + [@class="my&class form-control"] + [@value="10"] + /following-sibling::div + [@class="input-group-append"] + [ + ./span + [@class="input-group-text"] + [contains(.., "%")] + ] + ] +' + ); + } +} diff --git a/vendor/symfony/twig-bridge/Tests/Extension/CodeExtensionTest.php b/vendor/symfony/twig-bridge/Tests/Extension/CodeExtensionTest.php index 336991c6ca9f2816676f7a68a2ea5798306474cd..a637117f0933f1cadde118d7a03e6f73b1698b41 100644 --- a/vendor/symfony/twig-bridge/Tests/Extension/CodeExtensionTest.php +++ b/vendor/symfony/twig-bridge/Tests/Extension/CodeExtensionTest.php @@ -41,20 +41,20 @@ class CodeExtensionTest extends TestCase public function getClassNameProvider() { - return array( - array('F\Q\N\Foo', '<abbr title="F\Q\N\Foo">Foo</abbr>'), - array('Bare', '<abbr title="Bare">Bare</abbr>'), - ); + return [ + ['F\Q\N\Foo', '<abbr title="F\Q\N\Foo">Foo</abbr>'], + ['Bare', '<abbr title="Bare">Bare</abbr>'], + ]; } public function getMethodNameProvider() { - return array( - array('F\Q\N\Foo::Method', '<abbr title="F\Q\N\Foo">Foo</abbr>::Method()'), - array('Bare::Method', '<abbr title="Bare">Bare</abbr>::Method()'), - array('Closure', '<abbr title="Closure">Closure</abbr>'), - array('Method', '<abbr title="Method">Method</abbr>()'), - ); + return [ + ['F\Q\N\Foo::Method', '<abbr title="F\Q\N\Foo">Foo</abbr>::Method()'], + ['Bare::Method', '<abbr title="Bare">Bare</abbr>::Method()'], + ['Closure', '<abbr title="Closure">Closure</abbr>'], + ['Method', '<abbr title="Method">Method</abbr>()'], + ]; } public function testGetName() diff --git a/vendor/symfony/twig-bridge/Tests/Extension/DumpExtensionTest.php b/vendor/symfony/twig-bridge/Tests/Extension/DumpExtensionTest.php index ce80418c83ba73f55cebeae5fbd6e6c542e70272..273ca922d6fe85a00d7a6b0a8364c34e67dc36f5 100644 --- a/vendor/symfony/twig-bridge/Tests/Extension/DumpExtensionTest.php +++ b/vendor/symfony/twig-bridge/Tests/Extension/DumpExtensionTest.php @@ -13,9 +13,9 @@ namespace Symfony\Bridge\Twig\Tests\Extension; use PHPUnit\Framework\TestCase; use Symfony\Bridge\Twig\Extension\DumpExtension; +use Symfony\Component\VarDumper\Cloner\VarCloner; use Symfony\Component\VarDumper\Dumper\HtmlDumper; use Symfony\Component\VarDumper\VarDumper; -use Symfony\Component\VarDumper\Cloner\VarCloner; use Twig\Environment; use Twig\Loader\ArrayLoader; @@ -27,11 +27,11 @@ class DumpExtensionTest extends TestCase public function testDumpTag($template, $debug, $expectedOutput, $expectedDumped) { $extension = new DumpExtension(new VarCloner()); - $twig = new Environment(new ArrayLoader(array('template' => $template)), array( + $twig = new Environment(new ArrayLoader(['template' => $template]), [ 'debug' => $debug, 'cache' => false, 'optimizations' => 0, - )); + ]); $twig->addExtension($extension); $dumped = null; @@ -54,11 +54,11 @@ class DumpExtensionTest extends TestCase public function getDumpTags() { - return array( - array('A{% dump %}B', true, 'AB', array()), - array('A{% set foo="bar"%}B{% dump %}C', true, 'ABC', array('foo' => 'bar')), - array('A{% dump %}B', false, 'AB', null), - ); + return [ + ['A{% dump %}B', true, 'AB', []], + ['A{% set foo="bar"%}B{% dump %}C', true, 'ABC', ['foo' => 'bar']], + ['A{% dump %}B', false, 'AB', null], + ]; } /** @@ -67,16 +67,16 @@ class DumpExtensionTest extends TestCase public function testDump($context, $args, $expectedOutput, $debug = true) { $extension = new DumpExtension(new VarCloner()); - $twig = new Environment($this->getMockBuilder('Twig\Loader\LoaderInterface')->getMock(), array( + $twig = new Environment($this->getMockBuilder('Twig\Loader\LoaderInterface')->getMock(), [ 'debug' => $debug, 'cache' => false, 'optimizations' => 0, - )); + ]); array_unshift($args, $context); array_unshift($args, $twig); - $dump = call_user_func_array(array($extension, 'dump'), $args); + $dump = \call_user_func_array([$extension, 'dump'], $args); if ($debug) { $this->assertStringStartsWith('<script>', $dump); @@ -88,24 +88,24 @@ class DumpExtensionTest extends TestCase public function getDumpArgs() { - return array( - array(array(), array(), '', false), - array(array(), array(), "<pre class=sf-dump id=sf-dump data-indent-pad=\" \">[]\n</pre><script>Sfdump(\"sf-dump\")</script>\n"), - array( - array(), - array(123, 456), + return [ + [[], [], '', false], + [[], [], "<pre class=sf-dump id=sf-dump data-indent-pad=\" \">[]\n</pre><script>Sfdump(\"sf-dump\")</script>\n"], + [ + [], + [123, 456], "<pre class=sf-dump id=sf-dump data-indent-pad=\" \"><span class=sf-dump-num>123</span>\n</pre><script>Sfdump(\"sf-dump\")</script>\n" ."<pre class=sf-dump id=sf-dump data-indent-pad=\" \"><span class=sf-dump-num>456</span>\n</pre><script>Sfdump(\"sf-dump\")</script>\n", - ), - array( - array('foo' => 'bar'), - array(), + ], + [ + ['foo' => 'bar'], + [], "<pre class=sf-dump id=sf-dump data-indent-pad=\" \"><span class=sf-dump-note>array:1</span> [<samp>\n" ." \"<span class=sf-dump-key>foo</span>\" => \"<span class=sf-dump-str title=\"3 characters\">bar</span>\"\n" ."</samp>]\n" ."</pre><script>Sfdump(\"sf-dump\")</script>\n", - ), - ); + ], + ]; } public function testCustomDumper() @@ -123,13 +123,13 @@ class DumpExtensionTest extends TestCase '</pre><script>Sfdump("%s")</script>' ); $extension = new DumpExtension(new VarCloner(), $dumper); - $twig = new Environment($this->getMockBuilder('Twig\Loader\LoaderInterface')->getMock(), array( + $twig = new Environment($this->getMockBuilder('Twig\Loader\LoaderInterface')->getMock(), [ 'debug' => true, 'cache' => false, 'optimizations' => 0, - )); + ]); - $dump = $extension->dump($twig, array(), 'foo'); + $dump = $extension->dump($twig, [], 'foo'); $dump = preg_replace('/sf-dump-\d+/', 'sf-dump', $dump); $this->assertEquals( diff --git a/vendor/symfony/twig-bridge/Tests/Extension/ExpressionExtensionTest.php b/vendor/symfony/twig-bridge/Tests/Extension/ExpressionExtensionTest.php index b2ee22c6a969b5b7b09a91188fe8596376323fcc..bfb9c578bbc958da71ae8d1c503a1afffd3b6b24 100644 --- a/vendor/symfony/twig-bridge/Tests/Extension/ExpressionExtensionTest.php +++ b/vendor/symfony/twig-bridge/Tests/Extension/ExpressionExtensionTest.php @@ -21,7 +21,7 @@ class ExpressionExtensionTest extends TestCase public function testExpressionCreation() { $template = "{{ expression('1 == 1') }}"; - $twig = new Environment(new ArrayLoader(array('template' => $template)), array('debug' => true, 'cache' => false, 'autoescape' => 'html', 'optimizations' => 0)); + $twig = new Environment(new ArrayLoader(['template' => $template]), ['debug' => true, 'cache' => false, 'autoescape' => 'html', 'optimizations' => 0]); $twig->addExtension(new ExpressionExtension()); $output = $twig->render('template'); diff --git a/vendor/symfony/twig-bridge/Tests/Extension/Fixtures/StubTranslator.php b/vendor/symfony/twig-bridge/Tests/Extension/Fixtures/StubTranslator.php index b7d011b59940fc0de326e5ae7228853743aac03d..5ef9e61b60ec31912712d1121bce47383cc330fc 100644 --- a/vendor/symfony/twig-bridge/Tests/Extension/Fixtures/StubTranslator.php +++ b/vendor/symfony/twig-bridge/Tests/Extension/Fixtures/StubTranslator.php @@ -15,12 +15,12 @@ use Symfony\Component\Translation\TranslatorInterface; class StubTranslator implements TranslatorInterface { - public function trans($id, array $parameters = array(), $domain = null, $locale = null) + public function trans($id, array $parameters = [], $domain = null, $locale = null) { return '[trans]'.$id.'[/trans]'; } - public function transChoice($id, $number, array $parameters = array(), $domain = null, $locale = null) + public function transChoice($id, $number, array $parameters = [], $domain = null, $locale = null) { return '[trans]'.$id.'[/trans]'; } diff --git a/vendor/symfony/twig-bridge/Tests/Extension/Fixtures/templates/form/custom_widgets.html.twig b/vendor/symfony/twig-bridge/Tests/Extension/Fixtures/templates/form/custom_widgets.html.twig index 4eda8d76d37366af81e744ed54faa4744bc75cf5..36e9c702a94cdfc5e6238faa5a0b61e04522dcf1 100644 --- a/vendor/symfony/twig-bridge/Tests/Extension/Fixtures/templates/form/custom_widgets.html.twig +++ b/vendor/symfony/twig-bridge/Tests/Extension/Fixtures/templates/form/custom_widgets.html.twig @@ -1,25 +1,19 @@ -{% block _text_id_widget %} -{% spaceless %} +{% block _text_id_widget -%} <div id="container"> - {{ form_widget(form) }} + {{- form_widget(form) -}} </div> -{% endspaceless %} -{% endblock _text_id_widget %} +{%- endblock _text_id_widget %} -{% block _names_entry_label %} -{% spaceless %} +{% block _names_entry_label -%} {% if label is empty %} - {% set label = name|humanize %} - {% endif %} + {%- set label = name|humanize -%} + {% endif -%} <label>Custom label: {{ label|trans({}, translation_domain) }}</label> -{% endspaceless %} -{% endblock _names_entry_label %} +{%- endblock _names_entry_label %} -{% block _name_c_entry_label %} -{% spaceless %} +{% block _name_c_entry_label -%} {% if label is empty %} - {% set label = name|humanize %} - {% endif %} + {%- set label = name|humanize -%} + {% endif -%} <label>Custom name label: {{ label|trans({}, translation_domain) }}</label> -{% endspaceless %} -{% endblock _name_c_entry_label %} +{%- endblock _name_c_entry_label %} diff --git a/vendor/symfony/twig-bridge/Tests/Extension/Fixtures/templates/form/theme.html.twig b/vendor/symfony/twig-bridge/Tests/Extension/Fixtures/templates/form/theme.html.twig index da1c1b649b62c5ecaf38afa8da386f491d070e47..e8816be96e54ea86b74612767db1c7f398be5c77 100644 --- a/vendor/symfony/twig-bridge/Tests/Extension/Fixtures/templates/form/theme.html.twig +++ b/vendor/symfony/twig-bridge/Tests/Extension/Fixtures/templates/form/theme.html.twig @@ -1,6 +1,4 @@ {% block form_widget_simple %} -{% spaceless %} - {% set type = type|default('text') %} + {%- set type = type|default('text') -%} <input type="{{ type }}" {{ block('widget_attributes') }} value="{{ value }}" rel="theme" /> -{% endspaceless %} -{% endblock form_widget_simple %} +{%- endblock form_widget_simple %} diff --git a/vendor/symfony/twig-bridge/Tests/Extension/Fixtures/templates/form/theme_extends.html.twig b/vendor/symfony/twig-bridge/Tests/Extension/Fixtures/templates/form/theme_extends.html.twig index 8c719867ec5b0107c2e61a9b5315a738c9f88a61..501b555efc59f51b84e9cc88d04edc9994ee8d44 100644 --- a/vendor/symfony/twig-bridge/Tests/Extension/Fixtures/templates/form/theme_extends.html.twig +++ b/vendor/symfony/twig-bridge/Tests/Extension/Fixtures/templates/form/theme_extends.html.twig @@ -1,8 +1,6 @@ {% extends 'form_div_layout.html.twig' %} {% block form_widget_simple %} -{% spaceless %} - {% set type = type|default('text') %} + {%- set type = type|default('text') -%} <input type="{{ type }}" {{ block('widget_attributes') }} value="{{ value }}" rel="theme" /> -{% endspaceless %} -{% endblock form_widget_simple %} +{%- endblock form_widget_simple %} diff --git a/vendor/symfony/twig-bridge/Tests/Extension/Fixtures/templates/form/theme_use.html.twig b/vendor/symfony/twig-bridge/Tests/Extension/Fixtures/templates/form/theme_use.html.twig index d485b8d0e7d7d52923b394609f9333f1f7093e19..37150734a4698f5bccd1aed0645cb28efa8a02d4 100644 --- a/vendor/symfony/twig-bridge/Tests/Extension/Fixtures/templates/form/theme_use.html.twig +++ b/vendor/symfony/twig-bridge/Tests/Extension/Fixtures/templates/form/theme_use.html.twig @@ -1,8 +1,6 @@ {% use 'form_div_layout.html.twig' %} {% block form_widget_simple %} -{% spaceless %} - {% set type = type|default('text') %} + {%- set type = type|default('text') -%} <input type="{{ type }}" {{ block('widget_attributes') }} value="{{ value }}" rel="theme" /> -{% endspaceless %} -{% endblock form_widget_simple %} +{%- endblock form_widget_simple %} diff --git a/vendor/symfony/twig-bridge/Tests/Extension/FormExtensionBootstrap3HorizontalLayoutTest.php b/vendor/symfony/twig-bridge/Tests/Extension/FormExtensionBootstrap3HorizontalLayoutTest.php index e5ee8903efe4a50df2e4e1da1a6d4aa71faf04a0..b11d1720be0ba8869d8a795ae3fec041c117c82e 100644 --- a/vendor/symfony/twig-bridge/Tests/Extension/FormExtensionBootstrap3HorizontalLayoutTest.php +++ b/vendor/symfony/twig-bridge/Tests/Extension/FormExtensionBootstrap3HorizontalLayoutTest.php @@ -12,58 +12,58 @@ namespace Symfony\Bridge\Twig\Tests\Extension; use Symfony\Bridge\Twig\Extension\FormExtension; -use Symfony\Bridge\Twig\Form\TwigRendererEngine; use Symfony\Bridge\Twig\Extension\TranslationExtension; -use Symfony\Bridge\Twig\Tests\Extension\Fixtures\StubTranslator; +use Symfony\Bridge\Twig\Form\TwigRendererEngine; use Symfony\Bridge\Twig\Tests\Extension\Fixtures\StubFilesystemLoader; +use Symfony\Bridge\Twig\Tests\Extension\Fixtures\StubTranslator; use Symfony\Component\Form\FormRenderer; use Symfony\Component\Form\FormView; -use Symfony\Component\Form\Tests\AbstractBootstrap3HorizontalLayoutTest; use Twig\Environment; class FormExtensionBootstrap3HorizontalLayoutTest extends AbstractBootstrap3HorizontalLayoutTest { use RuntimeLoaderProvider; - protected $testableFeatures = array( + protected $testableFeatures = [ 'choice_attr', - ); + ]; /** * @var FormRenderer */ private $renderer; - protected function setUp() + /** + * @before + */ + public function doSetUp() { - parent::setUp(); - - $loader = new StubFilesystemLoader(array( + $loader = new StubFilesystemLoader([ __DIR__.'/../../Resources/views/Form', __DIR__.'/Fixtures/templates/form', - )); + ]); - $environment = new Environment($loader, array('strict_variables' => true)); + $environment = new Environment($loader, ['strict_variables' => true]); $environment->addExtension(new TranslationExtension(new StubTranslator())); $environment->addExtension(new FormExtension()); - $rendererEngine = new TwigRendererEngine(array( + $rendererEngine = new TwigRendererEngine([ 'bootstrap_3_horizontal_layout.html.twig', 'custom_widgets.html.twig', - ), $environment); + ], $environment); $this->renderer = new FormRenderer($rendererEngine, $this->getMockBuilder('Symfony\Component\Security\Csrf\CsrfTokenManagerInterface')->getMock()); $this->registerTwigRuntimeLoader($environment, $this->renderer); } - protected function renderForm(FormView $view, array $vars = array()) + protected function renderForm(FormView $view, array $vars = []) { return (string) $this->renderer->renderBlock($view, 'form', $vars); } - protected function renderLabel(FormView $view, $label = null, array $vars = array()) + protected function renderLabel(FormView $view, $label = null, array $vars = []) { if (null !== $label) { - $vars += array('label' => $label); + $vars += ['label' => $label]; } return (string) $this->renderer->searchAndRenderBlock($view, 'label', $vars); @@ -74,27 +74,27 @@ class FormExtensionBootstrap3HorizontalLayoutTest extends AbstractBootstrap3Hori return (string) $this->renderer->searchAndRenderBlock($view, 'errors'); } - protected function renderWidget(FormView $view, array $vars = array()) + protected function renderWidget(FormView $view, array $vars = []) { return (string) $this->renderer->searchAndRenderBlock($view, 'widget', $vars); } - protected function renderRow(FormView $view, array $vars = array()) + protected function renderRow(FormView $view, array $vars = []) { return (string) $this->renderer->searchAndRenderBlock($view, 'row', $vars); } - protected function renderRest(FormView $view, array $vars = array()) + protected function renderRest(FormView $view, array $vars = []) { return (string) $this->renderer->searchAndRenderBlock($view, 'rest', $vars); } - protected function renderStart(FormView $view, array $vars = array()) + protected function renderStart(FormView $view, array $vars = []) { return (string) $this->renderer->renderBlock($view, 'form_start', $vars); } - protected function renderEnd(FormView $view, array $vars = array()) + protected function renderEnd(FormView $view, array $vars = []) { return (string) $this->renderer->renderBlock($view, 'form_end', $vars); } diff --git a/vendor/symfony/twig-bridge/Tests/Extension/FormExtensionBootstrap3LayoutTest.php b/vendor/symfony/twig-bridge/Tests/Extension/FormExtensionBootstrap3LayoutTest.php index 5e872b83eb67d1c820b6f6d3d9c02e408996bfc0..0bb5a7b6ce6bc412eb0bbc5076287348579a5d74 100644 --- a/vendor/symfony/twig-bridge/Tests/Extension/FormExtensionBootstrap3LayoutTest.php +++ b/vendor/symfony/twig-bridge/Tests/Extension/FormExtensionBootstrap3LayoutTest.php @@ -12,13 +12,12 @@ namespace Symfony\Bridge\Twig\Tests\Extension; use Symfony\Bridge\Twig\Extension\FormExtension; -use Symfony\Bridge\Twig\Form\TwigRendererEngine; use Symfony\Bridge\Twig\Extension\TranslationExtension; -use Symfony\Bridge\Twig\Tests\Extension\Fixtures\StubTranslator; +use Symfony\Bridge\Twig\Form\TwigRendererEngine; use Symfony\Bridge\Twig\Tests\Extension\Fixtures\StubFilesystemLoader; +use Symfony\Bridge\Twig\Tests\Extension\Fixtures\StubTranslator; use Symfony\Component\Form\FormRenderer; use Symfony\Component\Form\FormView; -use Symfony\Component\Form\Tests\AbstractBootstrap3LayoutTest; use Twig\Environment; class FormExtensionBootstrap3LayoutTest extends AbstractBootstrap3LayoutTest @@ -30,33 +29,34 @@ class FormExtensionBootstrap3LayoutTest extends AbstractBootstrap3LayoutTest */ private $renderer; - protected function setUp() + /** + * @before + */ + public function doSetUp() { - parent::setUp(); - - $loader = new StubFilesystemLoader(array( + $loader = new StubFilesystemLoader([ __DIR__.'/../../Resources/views/Form', __DIR__.'/Fixtures/templates/form', - )); + ]); - $environment = new Environment($loader, array('strict_variables' => true)); + $environment = new Environment($loader, ['strict_variables' => true]); $environment->addExtension(new TranslationExtension(new StubTranslator())); $environment->addExtension(new FormExtension()); - $rendererEngine = new TwigRendererEngine(array( + $rendererEngine = new TwigRendererEngine([ 'bootstrap_3_layout.html.twig', 'custom_widgets.html.twig', - ), $environment); + ], $environment); $this->renderer = new FormRenderer($rendererEngine, $this->getMockBuilder('Symfony\Component\Security\Csrf\CsrfTokenManagerInterface')->getMock()); $this->registerTwigRuntimeLoader($environment, $this->renderer); } public function testStartTagHasNoActionAttributeWhenActionIsEmpty() { - $form = $this->factory->create('Symfony\Component\Form\Extension\Core\Type\FormType', null, array( + $form = $this->factory->create('Symfony\Component\Form\Extension\Core\Type\FormType', null, [ 'method' => 'get', 'action' => '', - )); + ]); $html = $this->renderStart($form->createView()); @@ -65,25 +65,55 @@ class FormExtensionBootstrap3LayoutTest extends AbstractBootstrap3LayoutTest public function testStartTagHasActionAttributeWhenActionIsZero() { - $form = $this->factory->create('Symfony\Component\Form\Extension\Core\Type\FormType', null, array( + $form = $this->factory->create('Symfony\Component\Form\Extension\Core\Type\FormType', null, [ 'method' => 'get', 'action' => '0', - )); + ]); $html = $this->renderStart($form->createView()); $this->assertSame('<form name="form" method="get" action="0">', $html); } - protected function renderForm(FormView $view, array $vars = array()) + public function testMoneyWidgetInIso() + { + $environment = new Environment(new StubFilesystemLoader([ + __DIR__.'/../../Resources/views/Form', + __DIR__.'/Fixtures/templates/form', + ]), ['strict_variables' => true]); + $environment->addExtension(new TranslationExtension(new StubTranslator())); + $environment->addExtension(new FormExtension()); + $environment->setCharset('ISO-8859-1'); + + $rendererEngine = new TwigRendererEngine([ + 'bootstrap_3_layout.html.twig', + 'custom_widgets.html.twig', + ], $environment); + $this->renderer = new FormRenderer($rendererEngine, $this->getMockBuilder('Symfony\Component\Security\Csrf\CsrfTokenManagerInterface')->getMock()); + $this->registerTwigRuntimeLoader($environment, $this->renderer); + + $view = $this->factory + ->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\MoneyType') + ->createView() + ; + + $this->assertSame(<<<'HTML' +<div class="input-group"> + <span class="input-group-addon">€ </span> + <input type="text" id="name" name="name" required="required" class="form-control" /> </div> +HTML + , trim($this->renderWidget($view))); + } + + protected function renderForm(FormView $view, array $vars = []) { return (string) $this->renderer->renderBlock($view, 'form', $vars); } - protected function renderLabel(FormView $view, $label = null, array $vars = array()) + protected function renderLabel(FormView $view, $label = null, array $vars = []) { if (null !== $label) { - $vars += array('label' => $label); + $vars += ['label' => $label]; } return (string) $this->renderer->searchAndRenderBlock($view, 'label', $vars); @@ -94,27 +124,27 @@ class FormExtensionBootstrap3LayoutTest extends AbstractBootstrap3LayoutTest return (string) $this->renderer->searchAndRenderBlock($view, 'errors'); } - protected function renderWidget(FormView $view, array $vars = array()) + protected function renderWidget(FormView $view, array $vars = []) { return (string) $this->renderer->searchAndRenderBlock($view, 'widget', $vars); } - protected function renderRow(FormView $view, array $vars = array()) + protected function renderRow(FormView $view, array $vars = []) { return (string) $this->renderer->searchAndRenderBlock($view, 'row', $vars); } - protected function renderRest(FormView $view, array $vars = array()) + protected function renderRest(FormView $view, array $vars = []) { return (string) $this->renderer->searchAndRenderBlock($view, 'rest', $vars); } - protected function renderStart(FormView $view, array $vars = array()) + protected function renderStart(FormView $view, array $vars = []) { return (string) $this->renderer->renderBlock($view, 'form_start', $vars); } - protected function renderEnd(FormView $view, array $vars = array()) + protected function renderEnd(FormView $view, array $vars = []) { return (string) $this->renderer->renderBlock($view, 'form_end', $vars); } diff --git a/vendor/symfony/twig-bridge/Tests/Extension/FormExtensionBootstrap4HorizontalLayoutTest.php b/vendor/symfony/twig-bridge/Tests/Extension/FormExtensionBootstrap4HorizontalLayoutTest.php index 063edd889aed4c67354d41238ebf7bf7b9780d22..02ab01fc573af35c950d48ea92beef6ae0fe143b 100644 --- a/vendor/symfony/twig-bridge/Tests/Extension/FormExtensionBootstrap4HorizontalLayoutTest.php +++ b/vendor/symfony/twig-bridge/Tests/Extension/FormExtensionBootstrap4HorizontalLayoutTest.php @@ -12,13 +12,13 @@ namespace Symfony\Bridge\Twig\Tests\Extension; use Symfony\Bridge\Twig\Extension\FormExtension; -use Symfony\Bridge\Twig\Form\TwigRendererEngine; use Symfony\Bridge\Twig\Extension\TranslationExtension; -use Symfony\Bridge\Twig\Tests\Extension\Fixtures\StubTranslator; +use Symfony\Bridge\Twig\Form\TwigRendererEngine; use Symfony\Bridge\Twig\Tests\Extension\Fixtures\StubFilesystemLoader; +use Symfony\Bridge\Twig\Tests\Extension\Fixtures\StubTranslator; use Symfony\Component\Form\FormRenderer; use Symfony\Component\Form\FormView; -use Symfony\Component\Form\Tests\AbstractBootstrap4HorizontalLayoutTest; +use Twig\Environment; /** * Class providing test cases for the Bootstrap 4 Twig form theme. @@ -29,42 +29,43 @@ class FormExtensionBootstrap4HorizontalLayoutTest extends AbstractBootstrap4Hori { use RuntimeLoaderProvider; - protected $testableFeatures = array( + protected $testableFeatures = [ 'choice_attr', - ); + ]; private $renderer; - protected function setUp() + /** + * @before + */ + public function doSetUp() { - parent::setUp(); - - $loader = new StubFilesystemLoader(array( + $loader = new StubFilesystemLoader([ __DIR__.'/../../Resources/views/Form', __DIR__.'/Fixtures/templates/form', - )); + ]); - $environment = new \Twig_Environment($loader, array('strict_variables' => true)); + $environment = new Environment($loader, ['strict_variables' => true]); $environment->addExtension(new TranslationExtension(new StubTranslator())); $environment->addExtension(new FormExtension()); - $rendererEngine = new TwigRendererEngine(array( + $rendererEngine = new TwigRendererEngine([ 'bootstrap_4_horizontal_layout.html.twig', 'custom_widgets.html.twig', - ), $environment); + ], $environment); $this->renderer = new FormRenderer($rendererEngine, $this->getMockBuilder('Symfony\Component\Security\Csrf\CsrfTokenManagerInterface')->getMock()); $this->registerTwigRuntimeLoader($environment, $this->renderer); } - protected function renderForm(FormView $view, array $vars = array()) + protected function renderForm(FormView $view, array $vars = []) { return (string) $this->renderer->renderBlock($view, 'form', $vars); } - protected function renderLabel(FormView $view, $label = null, array $vars = array()) + protected function renderLabel(FormView $view, $label = null, array $vars = []) { if (null !== $label) { - $vars += array('label' => $label); + $vars += ['label' => $label]; } return (string) $this->renderer->searchAndRenderBlock($view, 'label', $vars); @@ -75,27 +76,27 @@ class FormExtensionBootstrap4HorizontalLayoutTest extends AbstractBootstrap4Hori return (string) $this->renderer->searchAndRenderBlock($view, 'errors'); } - protected function renderWidget(FormView $view, array $vars = array()) + protected function renderWidget(FormView $view, array $vars = []) { return (string) $this->renderer->searchAndRenderBlock($view, 'widget', $vars); } - protected function renderRow(FormView $view, array $vars = array()) + protected function renderRow(FormView $view, array $vars = []) { return (string) $this->renderer->searchAndRenderBlock($view, 'row', $vars); } - protected function renderRest(FormView $view, array $vars = array()) + protected function renderRest(FormView $view, array $vars = []) { return (string) $this->renderer->searchAndRenderBlock($view, 'rest', $vars); } - protected function renderStart(FormView $view, array $vars = array()) + protected function renderStart(FormView $view, array $vars = []) { return (string) $this->renderer->renderBlock($view, 'form_start', $vars); } - protected function renderEnd(FormView $view, array $vars = array()) + protected function renderEnd(FormView $view, array $vars = []) { return (string) $this->renderer->renderBlock($view, 'form_end', $vars); } diff --git a/vendor/symfony/twig-bridge/Tests/Extension/FormExtensionBootstrap4LayoutTest.php b/vendor/symfony/twig-bridge/Tests/Extension/FormExtensionBootstrap4LayoutTest.php index d3822ee77796aee688a6aef9bccc43f47f9866a4..cb2328b51fd45e49c8a12e26bc14b70d5de34aa6 100644 --- a/vendor/symfony/twig-bridge/Tests/Extension/FormExtensionBootstrap4LayoutTest.php +++ b/vendor/symfony/twig-bridge/Tests/Extension/FormExtensionBootstrap4LayoutTest.php @@ -12,13 +12,13 @@ namespace Symfony\Bridge\Twig\Tests\Extension; use Symfony\Bridge\Twig\Extension\FormExtension; -use Symfony\Bridge\Twig\Form\TwigRendererEngine; use Symfony\Bridge\Twig\Extension\TranslationExtension; -use Symfony\Bridge\Twig\Tests\Extension\Fixtures\StubTranslator; +use Symfony\Bridge\Twig\Form\TwigRendererEngine; use Symfony\Bridge\Twig\Tests\Extension\Fixtures\StubFilesystemLoader; +use Symfony\Bridge\Twig\Tests\Extension\Fixtures\StubTranslator; use Symfony\Component\Form\FormRenderer; use Symfony\Component\Form\FormView; -use Symfony\Component\Form\Tests\AbstractBootstrap4LayoutTest; +use Twig\Environment; /** * Class providing test cases for the Bootstrap 4 horizontal Twig form theme. @@ -29,37 +29,38 @@ class FormExtensionBootstrap4LayoutTest extends AbstractBootstrap4LayoutTest { use RuntimeLoaderProvider; /** - * @var FormRenderer; + * @var FormRenderer */ private $renderer; - protected function setUp() + /** + * @before + */ + public function doSetUp() { - parent::setUp(); - - $loader = new StubFilesystemLoader(array( + $loader = new StubFilesystemLoader([ __DIR__.'/../../Resources/views/Form', __DIR__.'/Fixtures/templates/form', - )); + ]); - $environment = new \Twig_Environment($loader, array('strict_variables' => true)); + $environment = new Environment($loader, ['strict_variables' => true]); $environment->addExtension(new TranslationExtension(new StubTranslator())); $environment->addExtension(new FormExtension()); - $rendererEngine = new TwigRendererEngine(array( + $rendererEngine = new TwigRendererEngine([ 'bootstrap_4_layout.html.twig', 'custom_widgets.html.twig', - ), $environment); + ], $environment); $this->renderer = new FormRenderer($rendererEngine, $this->getMockBuilder('Symfony\Component\Security\Csrf\CsrfTokenManagerInterface')->getMock()); $this->registerTwigRuntimeLoader($environment, $this->renderer); } public function testStartTagHasNoActionAttributeWhenActionIsEmpty() { - $form = $this->factory->create('Symfony\Component\Form\Extension\Core\Type\FormType', null, array( + $form = $this->factory->create('Symfony\Component\Form\Extension\Core\Type\FormType', null, [ 'method' => 'get', 'action' => '', - )); + ]); $html = $this->renderStart($form->createView()); @@ -68,25 +69,55 @@ class FormExtensionBootstrap4LayoutTest extends AbstractBootstrap4LayoutTest public function testStartTagHasActionAttributeWhenActionIsZero() { - $form = $this->factory->create('Symfony\Component\Form\Extension\Core\Type\FormType', null, array( + $form = $this->factory->create('Symfony\Component\Form\Extension\Core\Type\FormType', null, [ 'method' => 'get', 'action' => '0', - )); + ]); $html = $this->renderStart($form->createView()); $this->assertSame('<form name="form" method="get" action="0">', $html); } - protected function renderForm(FormView $view, array $vars = array()) + public function testMoneyWidgetInIso() + { + $environment = new Environment(new StubFilesystemLoader([ + __DIR__.'/../../Resources/views/Form', + __DIR__.'/Fixtures/templates/form', + ]), ['strict_variables' => true]); + $environment->addExtension(new TranslationExtension(new StubTranslator())); + $environment->addExtension(new FormExtension()); + $environment->setCharset('ISO-8859-1'); + + $rendererEngine = new TwigRendererEngine([ + 'bootstrap_4_layout.html.twig', + 'custom_widgets.html.twig', + ], $environment); + $this->renderer = new FormRenderer($rendererEngine, $this->getMockBuilder('Symfony\Component\Security\Csrf\CsrfTokenManagerInterface')->getMock()); + $this->registerTwigRuntimeLoader($environment, $this->renderer); + + $view = $this->factory + ->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\MoneyType') + ->createView() + ; + + $this->assertSame(<<<'HTML' +<div class="input-group"><div class="input-group-prepend"> + <span class="input-group-text">€ </span> + </div><input type="text" id="name" name="name" required="required" class="form-control" /></div> +HTML + , trim($this->renderWidget($view))); + } + + protected function renderForm(FormView $view, array $vars = []) { return (string) $this->renderer->renderBlock($view, 'form', $vars); } - protected function renderLabel(FormView $view, $label = null, array $vars = array()) + protected function renderLabel(FormView $view, $label = null, array $vars = []) { if (null !== $label) { - $vars += array('label' => $label); + $vars += ['label' => $label]; } return (string) $this->renderer->searchAndRenderBlock($view, 'label', $vars); @@ -97,27 +128,27 @@ class FormExtensionBootstrap4LayoutTest extends AbstractBootstrap4LayoutTest return (string) $this->renderer->searchAndRenderBlock($view, 'errors'); } - protected function renderWidget(FormView $view, array $vars = array()) + protected function renderWidget(FormView $view, array $vars = []) { return (string) $this->renderer->searchAndRenderBlock($view, 'widget', $vars); } - protected function renderRow(FormView $view, array $vars = array()) + protected function renderRow(FormView $view, array $vars = []) { return (string) $this->renderer->searchAndRenderBlock($view, 'row', $vars); } - protected function renderRest(FormView $view, array $vars = array()) + protected function renderRest(FormView $view, array $vars = []) { return (string) $this->renderer->searchAndRenderBlock($view, 'rest', $vars); } - protected function renderStart(FormView $view, array $vars = array()) + protected function renderStart(FormView $view, array $vars = []) { return (string) $this->renderer->renderBlock($view, 'form_start', $vars); } - protected function renderEnd(FormView $view, array $vars = array()) + protected function renderEnd(FormView $view, array $vars = []) { return (string) $this->renderer->renderBlock($view, 'form_end', $vars); } diff --git a/vendor/symfony/twig-bridge/Tests/Extension/FormExtensionDivLayoutTest.php b/vendor/symfony/twig-bridge/Tests/Extension/FormExtensionDivLayoutTest.php index 22a1413f38cbcee5a669a36884004a8012219e55..51e587411869f50679f0a67d355124367a65a00a 100644 --- a/vendor/symfony/twig-bridge/Tests/Extension/FormExtensionDivLayoutTest.php +++ b/vendor/symfony/twig-bridge/Tests/Extension/FormExtensionDivLayoutTest.php @@ -12,10 +12,10 @@ namespace Symfony\Bridge\Twig\Tests\Extension; use Symfony\Bridge\Twig\Extension\FormExtension; -use Symfony\Bridge\Twig\Form\TwigRendererEngine; use Symfony\Bridge\Twig\Extension\TranslationExtension; -use Symfony\Bridge\Twig\Tests\Extension\Fixtures\StubTranslator; +use Symfony\Bridge\Twig\Form\TwigRendererEngine; use Symfony\Bridge\Twig\Tests\Extension\Fixtures\StubFilesystemLoader; +use Symfony\Bridge\Twig\Tests\Extension\Fixtures\StubTranslator; use Symfony\Component\Form\ChoiceList\View\ChoiceView; use Symfony\Component\Form\FormRenderer; use Symfony\Component\Form\FormView; @@ -31,26 +31,29 @@ class FormExtensionDivLayoutTest extends AbstractDivLayoutTest */ private $renderer; - protected function setUp() - { - parent::setUp(); + protected static $supportedFeatureSetVersion = 304; - $loader = new StubFilesystemLoader(array( + /** + * @before + */ + public function doSetUp() + { + $loader = new StubFilesystemLoader([ __DIR__.'/../../Resources/views/Form', __DIR__.'/Fixtures/templates/form', - )); + ]); - $environment = new Environment($loader, array('strict_variables' => true)); + $environment = new Environment($loader, ['strict_variables' => true]); $environment->addExtension(new TranslationExtension(new StubTranslator())); $environment->addGlobal('global', ''); // the value can be any template that exists $environment->addGlobal('dynamic_template_name', 'child_label'); $environment->addExtension(new FormExtension()); - $rendererEngine = new TwigRendererEngine(array( + $rendererEngine = new TwigRendererEngine([ 'form_div_layout.html.twig', 'custom_widgets.html.twig', - ), $environment); + ], $environment); $this->renderer = new FormRenderer($rendererEngine, $this->getMockBuilder('Symfony\Component\Security\Csrf\CsrfTokenManagerInterface')->getMock()); $this->registerTwigRuntimeLoader($environment, $this->renderer); } @@ -62,7 +65,7 @@ class FormExtensionDivLayoutTest extends AbstractDivLayoutTest ->createView() ; - $this->setTheme($view, array('theme_use.html.twig')); + $this->setTheme($view, ['theme_use.html.twig']); $this->assertMatchesXpath( $this->renderWidget($view), @@ -77,7 +80,7 @@ class FormExtensionDivLayoutTest extends AbstractDivLayoutTest ->createView() ; - $this->setTheme($view, array('theme_extends.html.twig')); + $this->setTheme($view, ['theme_extends.html.twig']); $this->assertMatchesXpath( $this->renderWidget($view), @@ -92,7 +95,7 @@ class FormExtensionDivLayoutTest extends AbstractDivLayoutTest ->createView() ; - $this->renderer->setTheme($view, array('page_dynamic_extends.html.twig')); + $this->renderer->setTheme($view, ['page_dynamic_extends.html.twig']); $this->assertMatchesXpath( $this->renderer->searchAndRenderBlock($view, 'row'), '/div/label[text()="child"]' @@ -101,18 +104,18 @@ class FormExtensionDivLayoutTest extends AbstractDivLayoutTest public function isSelectedChoiceProvider() { - return array( - array(true, '0', '0'), - array(true, '1', '1'), - array(true, '', ''), - array(true, '1.23', '1.23'), - array(true, 'foo', 'foo'), - array(true, 'foo10', 'foo10'), - array(true, 'foo', array(1, 'foo', 'foo10')), - - array(false, 10, array(1, 'foo', 'foo10')), - array(false, 0, array(1, 'foo', 'foo10')), - ); + return [ + [true, '0', '0'], + [true, '1', '1'], + [true, '', ''], + [true, '1.23', '1.23'], + [true, 'foo', 'foo'], + [true, 'foo10', 'foo10'], + [true, 'foo', [1, 'foo', 'foo10']], + + [false, 10, [1, 'foo', 'foo10']], + [false, 0, [1, 'foo', 'foo10']], + ]; } /** @@ -127,10 +130,10 @@ class FormExtensionDivLayoutTest extends AbstractDivLayoutTest public function testStartTagHasNoActionAttributeWhenActionIsEmpty() { - $form = $this->factory->create('Symfony\Component\Form\Extension\Core\Type\FormType', null, array( + $form = $this->factory->create('Symfony\Component\Form\Extension\Core\Type\FormType', null, [ 'method' => 'get', 'action' => '', - )); + ]); $html = $this->renderStart($form->createView()); @@ -139,10 +142,10 @@ class FormExtensionDivLayoutTest extends AbstractDivLayoutTest public function testStartTagHasActionAttributeWhenActionIsZero() { - $form = $this->factory->create('Symfony\Component\Form\Extension\Core\Type\FormType', null, array( + $form = $this->factory->create('Symfony\Component\Form\Extension\Core\Type\FormType', null, [ 'method' => 'get', 'action' => '0', - )); + ]); $html = $this->renderStart($form->createView()); @@ -151,10 +154,10 @@ class FormExtensionDivLayoutTest extends AbstractDivLayoutTest public function isRootFormProvider() { - return array( - array(true, new FormView()), - array(false, new FormView(new FormView())), - ); + return [ + [true, new FormView()], + [false, new FormView(new FormView())], + ]; } /** @@ -165,15 +168,40 @@ class FormExtensionDivLayoutTest extends AbstractDivLayoutTest $this->assertSame($expected, \Symfony\Bridge\Twig\Extension\twig_is_root_form($formView)); } - protected function renderForm(FormView $view, array $vars = array()) + public function testMoneyWidgetInIso() + { + $environment = new Environment(new StubFilesystemLoader([ + __DIR__.'/../../Resources/views/Form', + __DIR__.'/Fixtures/templates/form', + ]), ['strict_variables' => true]); + $environment->addExtension(new TranslationExtension(new StubTranslator())); + $environment->addExtension(new FormExtension()); + $environment->setCharset('ISO-8859-1'); + + $rendererEngine = new TwigRendererEngine([ + 'form_div_layout.html.twig', + 'custom_widgets.html.twig', + ], $environment); + $this->renderer = new FormRenderer($rendererEngine, $this->getMockBuilder('Symfony\Component\Security\Csrf\CsrfTokenManagerInterface')->getMock()); + $this->registerTwigRuntimeLoader($environment, $this->renderer); + + $view = $this->factory + ->createNamed('name', 'Symfony\Component\Form\Extension\Core\Type\MoneyType') + ->createView() + ; + + $this->assertSame('€ <input type="text" id="name" name="name" required="required" />', $this->renderWidget($view)); + } + + protected function renderForm(FormView $view, array $vars = []) { return (string) $this->renderer->renderBlock($view, 'form', $vars); } - protected function renderLabel(FormView $view, $label = null, array $vars = array()) + protected function renderLabel(FormView $view, $label = null, array $vars = []) { if (null !== $label) { - $vars += array('label' => $label); + $vars += ['label' => $label]; } return (string) $this->renderer->searchAndRenderBlock($view, 'label', $vars); @@ -184,27 +212,27 @@ class FormExtensionDivLayoutTest extends AbstractDivLayoutTest return (string) $this->renderer->searchAndRenderBlock($view, 'errors'); } - protected function renderWidget(FormView $view, array $vars = array()) + protected function renderWidget(FormView $view, array $vars = []) { return (string) $this->renderer->searchAndRenderBlock($view, 'widget', $vars); } - protected function renderRow(FormView $view, array $vars = array()) + protected function renderRow(FormView $view, array $vars = []) { return (string) $this->renderer->searchAndRenderBlock($view, 'row', $vars); } - protected function renderRest(FormView $view, array $vars = array()) + protected function renderRest(FormView $view, array $vars = []) { return (string) $this->renderer->searchAndRenderBlock($view, 'rest', $vars); } - protected function renderStart(FormView $view, array $vars = array()) + protected function renderStart(FormView $view, array $vars = []) { return (string) $this->renderer->renderBlock($view, 'form_start', $vars); } - protected function renderEnd(FormView $view, array $vars = array()) + protected function renderEnd(FormView $view, array $vars = []) { return (string) $this->renderer->renderBlock($view, 'form_end', $vars); } @@ -216,15 +244,15 @@ class FormExtensionDivLayoutTest extends AbstractDivLayoutTest public static function themeBlockInheritanceProvider() { - return array( - array(array('theme.html.twig')), - ); + return [ + [['theme.html.twig']], + ]; } public static function themeInheritanceProvider() { - return array( - array(array('parent_label.html.twig'), array('child_label.html.twig')), - ); + return [ + [['parent_label.html.twig'], ['child_label.html.twig']], + ]; } } diff --git a/vendor/symfony/twig-bridge/Tests/Extension/FormExtensionTableLayoutTest.php b/vendor/symfony/twig-bridge/Tests/Extension/FormExtensionTableLayoutTest.php index 5119480d90e4c87c5bd9a6838d5573d2684d4caf..0676dffd5734178360247e94c471ddb65a4aeaa2 100644 --- a/vendor/symfony/twig-bridge/Tests/Extension/FormExtensionTableLayoutTest.php +++ b/vendor/symfony/twig-bridge/Tests/Extension/FormExtensionTableLayoutTest.php @@ -11,14 +11,14 @@ namespace Symfony\Bridge\Twig\Tests\Extension; -use Symfony\Component\Form\FormRenderer; -use Symfony\Component\Form\FormView; -use Symfony\Bridge\Twig\Form\TwigRendererEngine; use Symfony\Bridge\Twig\Extension\FormExtension; use Symfony\Bridge\Twig\Extension\TranslationExtension; -use Symfony\Component\Form\Tests\AbstractTableLayoutTest; -use Symfony\Bridge\Twig\Tests\Extension\Fixtures\StubTranslator; +use Symfony\Bridge\Twig\Form\TwigRendererEngine; use Symfony\Bridge\Twig\Tests\Extension\Fixtures\StubFilesystemLoader; +use Symfony\Bridge\Twig\Tests\Extension\Fixtures\StubTranslator; +use Symfony\Component\Form\FormRenderer; +use Symfony\Component\Form\FormView; +use Symfony\Component\Form\Tests\AbstractTableLayoutTest; use Twig\Environment; class FormExtensionTableLayoutTest extends AbstractTableLayoutTest @@ -30,34 +30,37 @@ class FormExtensionTableLayoutTest extends AbstractTableLayoutTest */ private $renderer; - protected function setUp() - { - parent::setUp(); + protected static $supportedFeatureSetVersion = 304; - $loader = new StubFilesystemLoader(array( + /** + * @before + */ + public function doSetUp() + { + $loader = new StubFilesystemLoader([ __DIR__.'/../../Resources/views/Form', __DIR__.'/Fixtures/templates/form', - )); + ]); - $environment = new Environment($loader, array('strict_variables' => true)); + $environment = new Environment($loader, ['strict_variables' => true]); $environment->addExtension(new TranslationExtension(new StubTranslator())); $environment->addGlobal('global', ''); $environment->addExtension(new FormExtension()); - $rendererEngine = new TwigRendererEngine(array( + $rendererEngine = new TwigRendererEngine([ 'form_table_layout.html.twig', 'custom_widgets.html.twig', - ), $environment); + ], $environment); $this->renderer = new FormRenderer($rendererEngine, $this->getMockBuilder('Symfony\Component\Security\Csrf\CsrfTokenManagerInterface')->getMock()); $this->registerTwigRuntimeLoader($environment, $this->renderer); } public function testStartTagHasNoActionAttributeWhenActionIsEmpty() { - $form = $this->factory->create('Symfony\Component\Form\Extension\Core\Type\FormType', null, array( + $form = $this->factory->create('Symfony\Component\Form\Extension\Core\Type\FormType', null, [ 'method' => 'get', 'action' => '', - )); + ]); $html = $this->renderStart($form->createView()); @@ -66,25 +69,25 @@ class FormExtensionTableLayoutTest extends AbstractTableLayoutTest public function testStartTagHasActionAttributeWhenActionIsZero() { - $form = $this->factory->create('Symfony\Component\Form\Extension\Core\Type\FormType', null, array( + $form = $this->factory->create('Symfony\Component\Form\Extension\Core\Type\FormType', null, [ 'method' => 'get', 'action' => '0', - )); + ]); $html = $this->renderStart($form->createView()); $this->assertSame('<form name="form" method="get" action="0">', $html); } - protected function renderForm(FormView $view, array $vars = array()) + protected function renderForm(FormView $view, array $vars = []) { return (string) $this->renderer->renderBlock($view, 'form', $vars); } - protected function renderLabel(FormView $view, $label = null, array $vars = array()) + protected function renderLabel(FormView $view, $label = null, array $vars = []) { if (null !== $label) { - $vars += array('label' => $label); + $vars += ['label' => $label]; } return (string) $this->renderer->searchAndRenderBlock($view, 'label', $vars); @@ -95,27 +98,27 @@ class FormExtensionTableLayoutTest extends AbstractTableLayoutTest return (string) $this->renderer->searchAndRenderBlock($view, 'errors'); } - protected function renderWidget(FormView $view, array $vars = array()) + protected function renderWidget(FormView $view, array $vars = []) { return (string) $this->renderer->searchAndRenderBlock($view, 'widget', $vars); } - protected function renderRow(FormView $view, array $vars = array()) + protected function renderRow(FormView $view, array $vars = []) { return (string) $this->renderer->searchAndRenderBlock($view, 'row', $vars); } - protected function renderRest(FormView $view, array $vars = array()) + protected function renderRest(FormView $view, array $vars = []) { return (string) $this->renderer->searchAndRenderBlock($view, 'rest', $vars); } - protected function renderStart(FormView $view, array $vars = array()) + protected function renderStart(FormView $view, array $vars = []) { return (string) $this->renderer->renderBlock($view, 'form_start', $vars); } - protected function renderEnd(FormView $view, array $vars = array()) + protected function renderEnd(FormView $view, array $vars = []) { return (string) $this->renderer->renderBlock($view, 'form_end', $vars); } diff --git a/vendor/symfony/twig-bridge/Tests/Extension/FormExtensionTest.php b/vendor/symfony/twig-bridge/Tests/Extension/FormExtensionTest.php index a4d7350716e648f617e0ed3b73644f5203c441cd..4bdf7877556427b4a25ae71b68644669f024ac47 100644 --- a/vendor/symfony/twig-bridge/Tests/Extension/FormExtensionTest.php +++ b/vendor/symfony/twig-bridge/Tests/Extension/FormExtensionTest.php @@ -49,7 +49,7 @@ class FormExtensionTest extends TestCase $twigRenderer->expects($this->once()) ->method('setEnvironment'); - yield array($twigRenderer, $twigRenderer); + yield [$twigRenderer, $twigRenderer]; $twigRenderer = $this->getMockBuilder(TwigRendererInterface::class)->getMock(); $twigRenderer->expects($this->once()) @@ -61,7 +61,7 @@ class FormExtensionTest extends TestCase ->with('service_id') ->willReturn($twigRenderer); - yield array(array($container, 'service_id'), $twigRenderer); + yield [[$container, 'service_id'], $twigRenderer]; $formRenderer = $this->getMockBuilder(FormRendererInterface::class)->getMock(); @@ -71,6 +71,6 @@ class FormExtensionTest extends TestCase ->with('service_id') ->willReturn($formRenderer); - yield array(array($container, 'service_id'), $formRenderer); + yield [[$container, 'service_id'], $formRenderer]; } } diff --git a/vendor/symfony/twig-bridge/Tests/Extension/HttpFoundationExtensionTest.php b/vendor/symfony/twig-bridge/Tests/Extension/HttpFoundationExtensionTest.php index fcff0c0e1b93b54aaced74731888e00940c68e52..38ee375b94b137c4a533ed4c3294d25027803e34 100644 --- a/vendor/symfony/twig-bridge/Tests/Extension/HttpFoundationExtensionTest.php +++ b/vendor/symfony/twig-bridge/Tests/Extension/HttpFoundationExtensionTest.php @@ -13,8 +13,8 @@ namespace Symfony\Bridge\Twig\Tests\Extension; use PHPUnit\Framework\TestCase; use Symfony\Bridge\Twig\Extension\HttpFoundationExtension; -use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\Routing\RequestContext; class HttpFoundationExtensionTest extends TestCase @@ -33,25 +33,25 @@ class HttpFoundationExtensionTest extends TestCase public function getGenerateAbsoluteUrlData() { - return array( - array('http://localhost/foo.png', '/foo.png', '/foo/bar.html'), - array('http://localhost/foo/foo.png', 'foo.png', '/foo/bar.html'), - array('http://localhost/foo/foo.png', 'foo.png', '/foo/bar'), - array('http://localhost/foo/bar/foo.png', 'foo.png', '/foo/bar/'), - - array('http://example.com/baz', 'http://example.com/baz', '/'), - array('https://example.com/baz', 'https://example.com/baz', '/'), - array('//example.com/baz', '//example.com/baz', '/'), - - array('http://localhost/foo/bar?baz', '?baz', '/foo/bar'), - array('http://localhost/foo/bar?baz=1', '?baz=1', '/foo/bar?foo=1'), - array('http://localhost/foo/baz?baz=1', 'baz?baz=1', '/foo/bar?foo=1'), - - array('http://localhost/foo/bar#baz', '#baz', '/foo/bar'), - array('http://localhost/foo/bar?0#baz', '#baz', '/foo/bar?0'), - array('http://localhost/foo/bar?baz=1#baz', '?baz=1#baz', '/foo/bar?foo=1'), - array('http://localhost/foo/baz?baz=1#baz', 'baz?baz=1#baz', '/foo/bar?foo=1'), - ); + return [ + ['http://localhost/foo.png', '/foo.png', '/foo/bar.html'], + ['http://localhost/foo/foo.png', 'foo.png', '/foo/bar.html'], + ['http://localhost/foo/foo.png', 'foo.png', '/foo/bar'], + ['http://localhost/foo/bar/foo.png', 'foo.png', '/foo/bar/'], + + ['http://example.com/baz', 'http://example.com/baz', '/'], + ['https://example.com/baz', 'https://example.com/baz', '/'], + ['//example.com/baz', '//example.com/baz', '/'], + + ['http://localhost/foo/bar?baz', '?baz', '/foo/bar'], + ['http://localhost/foo/bar?baz=1', '?baz=1', '/foo/bar?foo=1'], + ['http://localhost/foo/baz?baz=1', 'baz?baz=1', '/foo/bar?foo=1'], + + ['http://localhost/foo/bar#baz', '#baz', '/foo/bar'], + ['http://localhost/foo/bar?0#baz', '#baz', '/foo/bar?0'], + ['http://localhost/foo/bar?baz=1#baz', '?baz=1#baz', '/foo/bar?foo=1'], + ['http://localhost/foo/baz?baz=1#baz', 'baz?baz=1#baz', '/foo/bar?foo=1'], + ]; } /** @@ -85,16 +85,16 @@ class HttpFoundationExtensionTest extends TestCase public function getGenerateAbsoluteUrlRequestContextData() { - return array( - array('/foo.png', '/foo', 'localhost', 'http', 80, 443, 'http://localhost/foo.png'), - array('foo.png', '/foo', 'localhost', 'http', 80, 443, 'http://localhost/foo/foo.png'), - array('foo.png', '/foo/bar/', 'localhost', 'http', 80, 443, 'http://localhost/foo/bar/foo.png'), - array('/foo.png', '/foo', 'localhost', 'https', 80, 443, 'https://localhost/foo.png'), - array('foo.png', '/foo', 'localhost', 'https', 80, 443, 'https://localhost/foo/foo.png'), - array('foo.png', '/foo/bar/', 'localhost', 'https', 80, 443, 'https://localhost/foo/bar/foo.png'), - array('/foo.png', '/foo', 'localhost', 'http', 443, 80, 'http://localhost:443/foo.png'), - array('/foo.png', '/foo', 'localhost', 'https', 443, 80, 'https://localhost:80/foo.png'), - ); + return [ + ['/foo.png', '/foo', 'localhost', 'http', 80, 443, 'http://localhost/foo.png'], + ['foo.png', '/foo', 'localhost', 'http', 80, 443, 'http://localhost/foo/foo.png'], + ['foo.png', '/foo/bar/', 'localhost', 'http', 80, 443, 'http://localhost/foo/bar/foo.png'], + ['/foo.png', '/foo', 'localhost', 'https', 80, 443, 'https://localhost/foo.png'], + ['foo.png', '/foo', 'localhost', 'https', 80, 443, 'https://localhost/foo/foo.png'], + ['foo.png', '/foo/bar/', 'localhost', 'https', 80, 443, 'https://localhost/foo/bar/foo.png'], + ['/foo.png', '/foo', 'localhost', 'http', 443, 80, 'http://localhost:443/foo.png'], + ['/foo.png', '/foo', 'localhost', 'https', 443, 80, 'https://localhost:80/foo.png'], + ]; } public function testGenerateAbsoluteUrlWithScriptFileName() @@ -130,14 +130,14 @@ class HttpFoundationExtensionTest extends TestCase public function getGenerateRelativePathData() { - return array( - array('../foo.png', '/foo.png', '/foo/bar.html'), - array('../baz/foo.png', '/baz/foo.png', '/foo/bar.html'), - array('baz/foo.png', 'baz/foo.png', '/foo/bar.html'), - - array('http://example.com/baz', 'http://example.com/baz', '/'), - array('https://example.com/baz', 'https://example.com/baz', '/'), - array('//example.com/baz', '//example.com/baz', '/'), - ); + return [ + ['../foo.png', '/foo.png', '/foo/bar.html'], + ['../baz/foo.png', '/baz/foo.png', '/foo/bar.html'], + ['baz/foo.png', 'baz/foo.png', '/foo/bar.html'], + + ['http://example.com/baz', 'http://example.com/baz', '/'], + ['https://example.com/baz', 'https://example.com/baz', '/'], + ['//example.com/baz', '//example.com/baz', '/'], + ]; } } diff --git a/vendor/symfony/twig-bridge/Tests/Extension/HttpKernelExtensionTest.php b/vendor/symfony/twig-bridge/Tests/Extension/HttpKernelExtensionTest.php index 9f19847eb8824f7bc2de380eebd6ec701c239b57..c635935f3e7ae9dc33e82e297cd072993db4f238 100644 --- a/vendor/symfony/twig-bridge/Tests/Extension/HttpKernelExtensionTest.php +++ b/vendor/symfony/twig-bridge/Tests/Extension/HttpKernelExtensionTest.php @@ -22,11 +22,9 @@ use Twig\Loader\ArrayLoader; class HttpKernelExtensionTest extends TestCase { - /** - * @expectedException \Twig\Error\RuntimeError - */ public function testFragmentWithError() { + $this->expectException('Twig\Error\RuntimeError'); $renderer = $this->getFragmentHandler($this->throwException(new \Exception('foo'))); $this->renderTemplate($renderer); @@ -49,12 +47,8 @@ class HttpKernelExtensionTest extends TestCase ; $renderer = new FragmentHandler($context); - if (method_exists($this, 'expectException')) { - $this->expectException('InvalidArgumentException'); - $this->expectExceptionMessage('The "inline" renderer does not exist.'); - } else { - $this->setExpectedException('InvalidArgumentException', 'The "inline" renderer does not exist.'); - } + $this->expectException('InvalidArgumentException'); + $this->expectExceptionMessage('The "inline" renderer does not exist.'); $renderer->render('/foo'); } @@ -62,7 +56,7 @@ class HttpKernelExtensionTest extends TestCase protected function getFragmentHandler($return) { $strategy = $this->getMockBuilder('Symfony\\Component\\HttpKernel\\Fragment\\FragmentRendererInterface')->getMock(); - $strategy->expects($this->once())->method('getName')->will($this->returnValue('inline')); + $strategy->expects($this->once())->method('getName')->willReturn('inline'); $strategy->expects($this->once())->method('render')->will($return); $context = $this->getMockBuilder('Symfony\\Component\\HttpFoundation\\RequestStack') @@ -70,21 +64,21 @@ class HttpKernelExtensionTest extends TestCase ->getMock() ; - $context->expects($this->any())->method('getCurrentRequest')->will($this->returnValue(Request::create('/'))); + $context->expects($this->any())->method('getCurrentRequest')->willReturn(Request::create('/')); - return new FragmentHandler($context, array($strategy), false); + return new FragmentHandler($context, [$strategy], false); } protected function renderTemplate(FragmentHandler $renderer, $template = '{{ render("foo") }}') { - $loader = new ArrayLoader(array('index' => $template)); - $twig = new Environment($loader, array('debug' => true, 'cache' => false)); + $loader = new ArrayLoader(['index' => $template]); + $twig = new Environment($loader, ['debug' => true, 'cache' => false]); $twig->addExtension(new HttpKernelExtension()); $loader = $this->getMockBuilder('Twig\RuntimeLoader\RuntimeLoaderInterface')->getMock(); - $loader->expects($this->any())->method('load')->will($this->returnValueMap(array( - array('Symfony\Bridge\Twig\Extension\HttpKernelRuntime', new HttpKernelRuntime($renderer)), - ))); + $loader->expects($this->any())->method('load')->willReturnMap([ + ['Symfony\Bridge\Twig\Extension\HttpKernelRuntime', new HttpKernelRuntime($renderer)], + ]); $twig->addRuntimeLoader($loader); return $twig->render('index'); diff --git a/vendor/symfony/twig-bridge/Tests/Extension/RoutingExtensionTest.php b/vendor/symfony/twig-bridge/Tests/Extension/RoutingExtensionTest.php index fdff03985122883bed00ed2868b07b07f3695b39..05f7ad741c7eaee435fda2a5aa49b3f7edf04f1f 100644 --- a/vendor/symfony/twig-bridge/Tests/Extension/RoutingExtensionTest.php +++ b/vendor/symfony/twig-bridge/Tests/Extension/RoutingExtensionTest.php @@ -24,7 +24,7 @@ class RoutingExtensionTest extends TestCase */ public function testEscaping($template, $mustBeEscaped) { - $twig = new Environment($this->getMockBuilder('Twig\Loader\LoaderInterface')->getMock(), array('debug' => true, 'cache' => false, 'autoescape' => 'html', 'optimizations' => 0)); + $twig = new Environment($this->getMockBuilder('Twig\Loader\LoaderInterface')->getMock(), ['debug' => true, 'cache' => false, 'autoescape' => 'html', 'optimizations' => 0]); $twig->addExtension(new RoutingExtension($this->getMockBuilder('Symfony\Component\Routing\Generator\UrlGeneratorInterface')->getMock())); $nodes = $twig->parse($twig->tokenize(new Source($template, ''))); @@ -34,21 +34,21 @@ class RoutingExtensionTest extends TestCase public function getEscapingTemplates() { - return array( - array('{{ path("foo") }}', false), - array('{{ path("foo", {}) }}', false), - array('{{ path("foo", { foo: "foo" }) }}', false), - array('{{ path("foo", foo) }}', true), - array('{{ path("foo", { foo: foo }) }}', true), - array('{{ path("foo", { foo: ["foo", "bar"] }) }}', true), - array('{{ path("foo", { foo: "foo", bar: "bar" }) }}', true), - - array('{{ path(name = "foo", parameters = {}) }}', false), - array('{{ path(name = "foo", parameters = { foo: "foo" }) }}', false), - array('{{ path(name = "foo", parameters = foo) }}', true), - array('{{ path(name = "foo", parameters = { foo: ["foo", "bar"] }) }}', true), - array('{{ path(name = "foo", parameters = { foo: foo }) }}', true), - array('{{ path(name = "foo", parameters = { foo: "foo", bar: "bar" }) }}', true), - ); + return [ + ['{{ path("foo") }}', false], + ['{{ path("foo", {}) }}', false], + ['{{ path("foo", { foo: "foo" }) }}', false], + ['{{ path("foo", foo) }}', true], + ['{{ path("foo", { foo: foo }) }}', true], + ['{{ path("foo", { foo: ["foo", "bar"] }) }}', true], + ['{{ path("foo", { foo: "foo", bar: "bar" }) }}', true], + + ['{{ path(name = "foo", parameters = {}) }}', false], + ['{{ path(name = "foo", parameters = { foo: "foo" }) }}', false], + ['{{ path(name = "foo", parameters = foo) }}', true], + ['{{ path(name = "foo", parameters = { foo: ["foo", "bar"] }) }}', true], + ['{{ path(name = "foo", parameters = { foo: foo }) }}', true], + ['{{ path(name = "foo", parameters = { foo: "foo", bar: "bar" }) }}', true], + ]; } } diff --git a/vendor/symfony/twig-bridge/Tests/Extension/RuntimeLoaderProvider.php b/vendor/symfony/twig-bridge/Tests/Extension/RuntimeLoaderProvider.php index 4934bef87d46730b60d3c041ff7c128e987506cb..0bec8ec6f1aabe94aca0fd60b48720743fa6f623 100644 --- a/vendor/symfony/twig-bridge/Tests/Extension/RuntimeLoaderProvider.php +++ b/vendor/symfony/twig-bridge/Tests/Extension/RuntimeLoaderProvider.php @@ -19,9 +19,9 @@ trait RuntimeLoaderProvider protected function registerTwigRuntimeLoader(Environment $environment, FormRenderer $renderer) { $loader = $this->getMockBuilder('Twig\RuntimeLoader\RuntimeLoaderInterface')->getMock(); - $loader->expects($this->any())->method('load')->will($this->returnValueMap(array( - array('Symfony\Component\Form\FormRenderer', $renderer), - ))); + $loader->expects($this->any())->method('load')->will($this->returnValueMap([ + ['Symfony\Component\Form\FormRenderer', $renderer], + ])); $environment->addRuntimeLoader($loader); } } diff --git a/vendor/symfony/twig-bridge/Tests/Extension/StopwatchExtensionTest.php b/vendor/symfony/twig-bridge/Tests/Extension/StopwatchExtensionTest.php index 25b2e029ee75c8c45739d714c82c2a8b93d62016..2b38122e5641042aa5e061fc54e0800a0d7b22a6 100644 --- a/vendor/symfony/twig-bridge/Tests/Extension/StopwatchExtensionTest.php +++ b/vendor/symfony/twig-bridge/Tests/Extension/StopwatchExtensionTest.php @@ -19,12 +19,10 @@ use Twig\Loader\ArrayLoader; class StopwatchExtensionTest extends TestCase { - /** - * @expectedException \Twig\Error\SyntaxError - */ public function testFailIfStoppingWrongEvent() { - $this->testTiming('{% stopwatch "foo" %}{% endstopwatch "bar" %}', array()); + $this->expectException('Twig\Error\SyntaxError'); + $this->testTiming('{% stopwatch "foo" %}{% endstopwatch "bar" %}', []); } /** @@ -32,7 +30,7 @@ class StopwatchExtensionTest extends TestCase */ public function testTiming($template, $events) { - $twig = new Environment(new ArrayLoader(array('template' => $template)), array('debug' => true, 'cache' => false, 'autoescape' => 'html', 'optimizations' => 0)); + $twig = new Environment(new ArrayLoader(['template' => $template]), ['debug' => true, 'cache' => false, 'autoescape' => 'html', 'optimizations' => 0]); $twig->addExtension(new StopwatchExtension($this->getStopwatch($events))); try { @@ -44,19 +42,19 @@ class StopwatchExtensionTest extends TestCase public function getTimingTemplates() { - return array( - array('{% stopwatch "foo" %}something{% endstopwatch %}', 'foo'), - array('{% stopwatch "foo" %}symfony is fun{% endstopwatch %}{% stopwatch "bar" %}something{% endstopwatch %}', array('foo', 'bar')), - array('{% set foo = "foo" %}{% stopwatch foo %}something{% endstopwatch %}', 'foo'), - array('{% set foo = "foo" %}{% stopwatch foo %}something {% set foo = "bar" %}{% endstopwatch %}', 'foo'), - array('{% stopwatch "foo.bar" %}something{% endstopwatch %}', 'foo.bar'), - array('{% stopwatch "foo" %}something{% endstopwatch %}{% stopwatch "foo" %}something else{% endstopwatch %}', array('foo', 'foo')), - ); + return [ + ['{% stopwatch "foo" %}something{% endstopwatch %}', 'foo'], + ['{% stopwatch "foo" %}symfony is fun{% endstopwatch %}{% stopwatch "bar" %}something{% endstopwatch %}', ['foo', 'bar']], + ['{% set foo = "foo" %}{% stopwatch foo %}something{% endstopwatch %}', 'foo'], + ['{% set foo = "foo" %}{% stopwatch foo %}something {% set foo = "bar" %}{% endstopwatch %}', 'foo'], + ['{% stopwatch "foo.bar" %}something{% endstopwatch %}', 'foo.bar'], + ['{% stopwatch "foo" %}something{% endstopwatch %}{% stopwatch "foo" %}something else{% endstopwatch %}', ['foo', 'foo']], + ]; } - protected function getStopwatch($events = array()) + protected function getStopwatch($events = []) { - $events = is_array($events) ? $events : array($events); + $events = \is_array($events) ? $events : [$events]; $stopwatch = $this->getMockBuilder('Symfony\Component\Stopwatch\Stopwatch')->getMock(); $i = -1; diff --git a/vendor/symfony/twig-bridge/Tests/Extension/TranslationExtensionTest.php b/vendor/symfony/twig-bridge/Tests/Extension/TranslationExtensionTest.php index 88a39b1ea9604b0825c9f8c90a6da1e4fc880bf6..aeb109fd250d36b5c42577d7caffe6d50fd3f7ad 100644 --- a/vendor/symfony/twig-bridge/Tests/Extension/TranslationExtensionTest.php +++ b/vendor/symfony/twig-bridge/Tests/Extension/TranslationExtensionTest.php @@ -13,8 +13,8 @@ namespace Symfony\Bridge\Twig\Tests\Extension; use PHPUnit\Framework\TestCase; use Symfony\Bridge\Twig\Extension\TranslationExtension; -use Symfony\Component\Translation\Translator; use Symfony\Component\Translation\Loader\ArrayLoader; +use Symfony\Component\Translation\Translator; use Twig\Environment; use Twig\Loader\ArrayLoader as TwigArrayLoader; @@ -22,7 +22,7 @@ class TranslationExtensionTest extends TestCase { public function testEscaping() { - $output = $this->getTemplate('{% trans %}Percent: %value%%% (%msg%){% endtrans %}')->render(array('value' => 12, 'msg' => 'approx.')); + $output = $this->getTemplate('{% trans %}Percent: %value%%% (%msg%){% endtrans %}')->render(['value' => 12, 'msg' => 'approx.']); $this->assertEquals('Percent: 12% (approx.)', $output); } @@ -30,12 +30,12 @@ class TranslationExtensionTest extends TestCase /** * @dataProvider getTransTests */ - public function testTrans($template, $expected, array $variables = array()) + public function testTrans($template, $expected, array $variables = []) { if ($expected != $this->getTemplate($template)->render($variables)) { echo $template."\n"; - $loader = new TwigArrayLoader(array('index' => $template)); - $twig = new Environment($loader, array('debug' => true, 'cache' => false)); + $loader = new TwigArrayLoader(['index' => $template]); + $twig = new Environment($loader, ['debug' => true, 'cache' => false]); $twig->addExtension(new TranslationExtension(new Translator('en'))); echo $twig->compile($twig->parse($twig->tokenize($twig->getLoader()->getSourceContext('index'))))."\n\n"; @@ -45,96 +45,90 @@ class TranslationExtensionTest extends TestCase $this->assertEquals($expected, $this->getTemplate($template)->render($variables)); } - /** - * @expectedException \Twig\Error\SyntaxError - * @expectedExceptionMessage Unexpected token. Twig was looking for the "with", "from", or "into" keyword in "index" at line 3. - */ public function testTransUnknownKeyword() { + $this->expectException('Twig\Error\SyntaxError'); + $this->expectExceptionMessage('Unexpected token. Twig was looking for the "with", "from", or "into" keyword in "index" at line 3.'); $output = $this->getTemplate("{% trans \n\nfoo %}{% endtrans %}")->render(); } - /** - * @expectedException \Twig\Error\SyntaxError - * @expectedExceptionMessage A message inside a trans tag must be a simple text in "index" at line 2. - */ public function testTransComplexBody() { + $this->expectException('Twig\Error\SyntaxError'); + $this->expectExceptionMessage('A message inside a trans tag must be a simple text in "index" at line 2.'); $output = $this->getTemplate("{% trans %}\n{{ 1 + 2 }}{% endtrans %}")->render(); } - /** - * @expectedException \Twig\Error\SyntaxError - * @expectedExceptionMessage A message inside a transchoice tag must be a simple text in "index" at line 2. - */ public function testTransChoiceComplexBody() { + $this->expectException('Twig\Error\SyntaxError'); + $this->expectExceptionMessage('A message inside a transchoice tag must be a simple text in "index" at line 2.'); $output = $this->getTemplate("{% transchoice count %}\n{{ 1 + 2 }}{% endtranschoice %}")->render(); } public function getTransTests() { - return array( + return [ // trans tag - array('{% trans %}Hello{% endtrans %}', 'Hello'), - array('{% trans %}%name%{% endtrans %}', 'Symfony', array('name' => 'Symfony')), + ['{% trans %}Hello{% endtrans %}', 'Hello'], + ['{% trans %}%name%{% endtrans %}', 'Symfony', ['name' => 'Symfony']], - array('{% trans from elsewhere %}Hello{% endtrans %}', 'Hello'), + ['{% trans from elsewhere %}Hello{% endtrans %}', 'Hello'], - array('{% trans %}Hello %name%{% endtrans %}', 'Hello Symfony', array('name' => 'Symfony')), - array('{% trans with { \'%name%\': \'Symfony\' } %}Hello %name%{% endtrans %}', 'Hello Symfony'), - array('{% set vars = { \'%name%\': \'Symfony\' } %}{% trans with vars %}Hello %name%{% endtrans %}', 'Hello Symfony'), + ['{% trans %}Hello %name%{% endtrans %}', 'Hello Symfony', ['name' => 'Symfony']], + ['{% trans with { \'%name%\': \'Symfony\' } %}Hello %name%{% endtrans %}', 'Hello Symfony'], + ['{% set vars = { \'%name%\': \'Symfony\' } %}{% trans with vars %}Hello %name%{% endtrans %}', 'Hello Symfony'], - array('{% trans into "fr"%}Hello{% endtrans %}', 'Hello'), + ['{% trans into "fr"%}Hello{% endtrans %}', 'Hello'], // transchoice - array( + [ '{% transchoice count from "messages" %}{0} There is no apples|{1} There is one apple|]1,Inf] There is %count% apples{% endtranschoice %}', 'There is no apples', - array('count' => 0), - ), - array( + ['count' => 0], + ], + [ '{% transchoice count %}{0} There is no apples|{1} There is one apple|]1,Inf] There is %count% apples{% endtranschoice %}', 'There is 5 apples', - array('count' => 5), - ), - array( + ['count' => 5], + ], + [ '{% transchoice count %}{0} There is no apples|{1} There is one apple|]1,Inf] There is %count% apples (%name%){% endtranschoice %}', 'There is 5 apples (Symfony)', - array('count' => 5, 'name' => 'Symfony'), - ), - array( + ['count' => 5, 'name' => 'Symfony'], + ], + [ '{% transchoice count with { \'%name%\': \'Symfony\' } %}{0} There is no apples|{1} There is one apple|]1,Inf] There is %count% apples (%name%){% endtranschoice %}', 'There is 5 apples (Symfony)', - array('count' => 5), - ), - array( + ['count' => 5], + ], + [ '{% transchoice count into "fr"%}{0} There is no apples|{1} There is one apple|]1,Inf] There is %count% apples{% endtranschoice %}', 'There is no apples', - array('count' => 0), - ), - array( + ['count' => 0], + ], + [ '{% transchoice 5 into "fr"%}{0} There is no apples|{1} There is one apple|]1,Inf] There is %count% apples{% endtranschoice %}', 'There is 5 apples', - ), + ], // trans filter - array('{{ "Hello"|trans }}', 'Hello'), - array('{{ name|trans }}', 'Symfony', array('name' => 'Symfony')), - array('{{ hello|trans({ \'%name%\': \'Symfony\' }) }}', 'Hello Symfony', array('hello' => 'Hello %name%')), - array('{% set vars = { \'%name%\': \'Symfony\' } %}{{ hello|trans(vars) }}', 'Hello Symfony', array('hello' => 'Hello %name%')), - array('{{ "Hello"|trans({}, "messages", "fr") }}', 'Hello'), + ['{{ "Hello"|trans }}', 'Hello'], + ['{{ name|trans }}', 'Symfony', ['name' => 'Symfony']], + ['{{ hello|trans({ \'%name%\': \'Symfony\' }) }}', 'Hello Symfony', ['hello' => 'Hello %name%']], + ['{% set vars = { \'%name%\': \'Symfony\' } %}{{ hello|trans(vars) }}', 'Hello Symfony', ['hello' => 'Hello %name%']], + ['{{ "Hello"|trans({}, "messages", "fr") }}', 'Hello'], // transchoice filter - array('{{ "{0} There is no apples|{1} There is one apple|]1,Inf] There is %count% apples"|transchoice(count) }}', 'There is 5 apples', array('count' => 5)), - array('{{ text|transchoice(5, {\'%name%\': \'Symfony\'}) }}', 'There is 5 apples (Symfony)', array('text' => '{0} There is no apples|{1} There is one apple|]1,Inf] There is %count% apples (%name%)')), - array('{{ "{0} There is no apples|{1} There is one apple|]1,Inf] There is %count% apples"|transchoice(count, {}, "messages", "fr") }}', 'There is 5 apples', array('count' => 5)), - ); + ['{{ "{0} There is no apples|{1} There is one apple|]1,Inf] There is %count% apples"|transchoice(count) }}', 'There is 5 apples', ['count' => 5]], + ['{{ text|transchoice(5, {\'%name%\': \'Symfony\'}) }}', 'There is 5 apples (Symfony)', ['text' => '{0} There is no apples|{1} There is one apple|]1,Inf] There is %count% apples (%name%)']], + ['{{ "{0} There is no apples|{1} There is one apple|]1,Inf] There is %count% apples"|transchoice(count, {}, "messages", "fr") }}', 'There is 5 apples', ['count' => 5]], + ]; } public function testDefaultTranslationDomain() { - $templates = array( + $templates = [ 'index' => ' {%- extends "base" %} @@ -153,22 +147,22 @@ class TranslationExtensionTest extends TestCase 'base' => ' {%- block content "" %} ', - ); + ]; $translator = new Translator('en'); $translator->addLoader('array', new ArrayLoader()); - $translator->addResource('array', array('foo' => 'foo (messages)'), 'en'); - $translator->addResource('array', array('foo' => 'foo (custom)'), 'en', 'custom'); - $translator->addResource('array', array('foo' => 'foo (foo)'), 'en', 'foo'); + $translator->addResource('array', ['foo' => 'foo (messages)'], 'en'); + $translator->addResource('array', ['foo' => 'foo (custom)'], 'en', 'custom'); + $translator->addResource('array', ['foo' => 'foo (foo)'], 'en', 'foo'); $template = $this->getTemplate($templates, $translator); - $this->assertEquals('foo (foo)foo (custom)foo (foo)foo (custom)foo (foo)foo (custom)', trim($template->render(array()))); + $this->assertEquals('foo (foo)foo (custom)foo (foo)foo (custom)foo (foo)foo (custom)', trim($template->render([]))); } public function testDefaultTranslationDomainWithNamedArguments() { - $templates = array( + $templates = [ 'index' => ' {%- trans_default_domain "foo" %} @@ -186,18 +180,18 @@ class TranslationExtensionTest extends TestCase 'base' => ' {%- block content "" %} ', - ); + ]; $translator = new Translator('en'); $translator->addLoader('array', new ArrayLoader()); - $translator->addResource('array', array('foo' => 'foo (messages)'), 'en'); - $translator->addResource('array', array('foo' => 'foo (custom)'), 'en', 'custom'); - $translator->addResource('array', array('foo' => 'foo (foo)'), 'en', 'foo'); - $translator->addResource('array', array('foo' => 'foo (fr)'), 'fr', 'custom'); + $translator->addResource('array', ['foo' => 'foo (messages)'], 'en'); + $translator->addResource('array', ['foo' => 'foo (custom)'], 'en', 'custom'); + $translator->addResource('array', ['foo' => 'foo (foo)'], 'en', 'foo'); + $translator->addResource('array', ['foo' => 'foo (fr)'], 'fr', 'custom'); $template = $this->getTemplate($templates, $translator); - $this->assertEquals('foo (custom)foo (foo)foo (custom)foo (custom)foo (fr)foo (custom)foo (fr)', trim($template->render(array()))); + $this->assertEquals('foo (custom)foo (foo)foo (custom)foo (custom)foo (fr)foo (custom)foo (fr)', trim($template->render([]))); } protected function getTemplate($template, $translator = null) @@ -206,12 +200,12 @@ class TranslationExtensionTest extends TestCase $translator = new Translator('en'); } - if (is_array($template)) { + if (\is_array($template)) { $loader = new TwigArrayLoader($template); } else { - $loader = new TwigArrayLoader(array('index' => $template)); + $loader = new TwigArrayLoader(['index' => $template]); } - $twig = new Environment($loader, array('debug' => true, 'cache' => false)); + $twig = new Environment($loader, ['debug' => true, 'cache' => false]); $twig->addExtension(new TranslationExtension($translator)); return $twig->loadTemplate('index'); diff --git a/vendor/symfony/twig-bridge/Tests/Extension/WebLinkExtensionTest.php b/vendor/symfony/twig-bridge/Tests/Extension/WebLinkExtensionTest.php index 3424b58875fbcbe4f41dff7d4b7f65d12f224b45..f49eea396d0d8842ebd4419a304cc0b895653930 100644 --- a/vendor/symfony/twig-bridge/Tests/Extension/WebLinkExtensionTest.php +++ b/vendor/symfony/twig-bridge/Tests/Extension/WebLinkExtensionTest.php @@ -44,49 +44,49 @@ class WebLinkExtensionTest extends TestCase public function testLink() { - $this->assertEquals('/foo.css', $this->extension->link('/foo.css', 'preload', array('as' => 'style', 'nopush' => true))); + $this->assertEquals('/foo.css', $this->extension->link('/foo.css', 'preload', ['as' => 'style', 'nopush' => true])); $link = (new Link('preload', '/foo.css'))->withAttribute('as', 'style')->withAttribute('nopush', true); - $this->assertEquals(array($link), array_values($this->request->attributes->get('_links')->getLinks())); + $this->assertEquals([$link], array_values($this->request->attributes->get('_links')->getLinks())); } public function testPreload() { - $this->assertEquals('/foo.css', $this->extension->preload('/foo.css', array('as' => 'style', 'crossorigin' => true))); + $this->assertEquals('/foo.css', $this->extension->preload('/foo.css', ['as' => 'style', 'crossorigin' => true])); $link = (new Link('preload', '/foo.css'))->withAttribute('as', 'style')->withAttribute('crossorigin', true); - $this->assertEquals(array($link), array_values($this->request->attributes->get('_links')->getLinks())); + $this->assertEquals([$link], array_values($this->request->attributes->get('_links')->getLinks())); } public function testDnsPrefetch() { - $this->assertEquals('/foo.css', $this->extension->dnsPrefetch('/foo.css', array('as' => 'style', 'crossorigin' => true))); + $this->assertEquals('/foo.css', $this->extension->dnsPrefetch('/foo.css', ['as' => 'style', 'crossorigin' => true])); $link = (new Link('dns-prefetch', '/foo.css'))->withAttribute('as', 'style')->withAttribute('crossorigin', true); - $this->assertEquals(array($link), array_values($this->request->attributes->get('_links')->getLinks())); + $this->assertEquals([$link], array_values($this->request->attributes->get('_links')->getLinks())); } public function testPreconnect() { - $this->assertEquals('/foo.css', $this->extension->preconnect('/foo.css', array('as' => 'style', 'crossorigin' => true))); + $this->assertEquals('/foo.css', $this->extension->preconnect('/foo.css', ['as' => 'style', 'crossorigin' => true])); $link = (new Link('preconnect', '/foo.css'))->withAttribute('as', 'style')->withAttribute('crossorigin', true); - $this->assertEquals(array($link), array_values($this->request->attributes->get('_links')->getLinks())); + $this->assertEquals([$link], array_values($this->request->attributes->get('_links')->getLinks())); } public function testPrefetch() { - $this->assertEquals('/foo.css', $this->extension->prefetch('/foo.css', array('as' => 'style', 'crossorigin' => true))); + $this->assertEquals('/foo.css', $this->extension->prefetch('/foo.css', ['as' => 'style', 'crossorigin' => true])); $link = (new Link('prefetch', '/foo.css'))->withAttribute('as', 'style')->withAttribute('crossorigin', true); - $this->assertEquals(array($link), array_values($this->request->attributes->get('_links')->getLinks())); + $this->assertEquals([$link], array_values($this->request->attributes->get('_links')->getLinks())); } public function testPrerender() { - $this->assertEquals('/foo.css', $this->extension->prerender('/foo.css', array('as' => 'style', 'crossorigin' => true))); + $this->assertEquals('/foo.css', $this->extension->prerender('/foo.css', ['as' => 'style', 'crossorigin' => true])); $link = (new Link('prerender', '/foo.css'))->withAttribute('as', 'style')->withAttribute('crossorigin', true); - $this->assertEquals(array($link), array_values($this->request->attributes->get('_links')->getLinks())); + $this->assertEquals([$link], array_values($this->request->attributes->get('_links')->getLinks())); } } diff --git a/vendor/symfony/twig-bridge/Tests/Extension/WorkflowExtensionTest.php b/vendor/symfony/twig-bridge/Tests/Extension/WorkflowExtensionTest.php index 2adf12d99ea882dc636ad40a5096f3b7cc6e6118..20d78bfe3986cd7001fb2b8535172e585b333855 100644 --- a/vendor/symfony/twig-bridge/Tests/Extension/WorkflowExtensionTest.php +++ b/vendor/symfony/twig-bridge/Tests/Extension/WorkflowExtensionTest.php @@ -25,11 +25,11 @@ class WorkflowExtensionTest extends TestCase protected function setUp() { - $places = array('ordered', 'waiting_for_payment', 'processed'); - $transitions = array( + $places = ['ordered', 'waiting_for_payment', 'processed']; + $transitions = [ new Transition('t1', 'ordered', 'waiting_for_payment'), new Transition('t2', 'waiting_for_payment', 'processed'), - ); + ]; $definition = new Definition($places, $transitions); $workflow = new Workflow($definition); @@ -42,7 +42,7 @@ class WorkflowExtensionTest extends TestCase public function testCanTransition() { $subject = new \stdClass(); - $subject->marking = array(); + $subject->marking = []; $this->assertTrue($this->extension->canTransition($subject, 't1')); $this->assertFalse($this->extension->canTransition($subject, 't2')); @@ -51,7 +51,7 @@ class WorkflowExtensionTest extends TestCase public function testGetEnabledTransitions() { $subject = new \stdClass(); - $subject->marking = array(); + $subject->marking = []; $transitions = $this->extension->getEnabledTransitions($subject); @@ -63,8 +63,8 @@ class WorkflowExtensionTest extends TestCase public function testHasMarkedPlace() { $subject = new \stdClass(); - $subject->marking = array(); - $subject->marking = array('ordered' => 1, 'waiting_for_payment' => 1); + $subject->marking = []; + $subject->marking = ['ordered' => 1, 'waiting_for_payment' => 1]; $this->assertTrue($this->extension->hasMarkedPlace($subject, 'ordered')); $this->assertTrue($this->extension->hasMarkedPlace($subject, 'waiting_for_payment')); @@ -74,10 +74,10 @@ class WorkflowExtensionTest extends TestCase public function testGetMarkedPlaces() { $subject = new \stdClass(); - $subject->marking = array(); - $subject->marking = array('ordered' => 1, 'waiting_for_payment' => 1); + $subject->marking = []; + $subject->marking = ['ordered' => 1, 'waiting_for_payment' => 1]; - $this->assertSame(array('ordered', 'waiting_for_payment'), $this->extension->getMarkedPlaces($subject)); + $this->assertSame(['ordered', 'waiting_for_payment'], $this->extension->getMarkedPlaces($subject)); $this->assertSame($subject->marking, $this->extension->getMarkedPlaces($subject, false)); } } diff --git a/vendor/symfony/twig-bridge/Tests/Node/DumpNodeTest.php b/vendor/symfony/twig-bridge/Tests/Node/DumpNodeTest.php index 7f8737a3af6ef95387b06ec6b9934fb5793de562..befc8341dde2033e04e7396d1bbbbb37bb18fe97 100644 --- a/vendor/symfony/twig-bridge/Tests/Node/DumpNodeTest.php +++ b/vendor/symfony/twig-bridge/Tests/Node/DumpNodeTest.php @@ -29,7 +29,7 @@ class DumpNodeTest extends TestCase $expected = <<<'EOTXT' if ($this->env->isDebug()) { - $barvars = array(); + $barvars = []; foreach ($context as $barkey => $barval) { if (!$barval instanceof \Twig\Template) { $barvars[$barkey] = $barval; @@ -53,7 +53,7 @@ EOTXT; $expected = <<<'EOTXT' if ($this->env->isDebug()) { - $barvars = array(); + $barvars = []; foreach ($context as $barkey => $barval) { if (!$barval instanceof \Twig\Template) { $barvars[$barkey] = $barval; @@ -70,9 +70,9 @@ EOTXT; public function testOneVar() { - $vars = new Node(array( + $vars = new Node([ new NameExpression('foo', 7), - )); + ]); $node = new DumpNode('bar', $vars, 7); $env = new Environment($this->getMockBuilder('Twig\Loader\LoaderInterface')->getMock()); @@ -97,10 +97,10 @@ EOTXT; public function testMultiVars() { - $vars = new Node(array( + $vars = new Node([ new NameExpression('foo', 7), new NameExpression('bar', 7), - )); + ]); $node = new DumpNode('bar', $vars, 7); $env = new Environment($this->getMockBuilder('Twig\Loader\LoaderInterface')->getMock()); @@ -109,10 +109,10 @@ EOTXT; $expected = <<<'EOTXT' if ($this->env->isDebug()) { // line 7 - \Symfony\Component\VarDumper\VarDumper::dump(array( + \Symfony\Component\VarDumper\VarDumper::dump([ "foo" => %foo%, "bar" => %bar%, - )); + ]); } EOTXT; diff --git a/vendor/symfony/twig-bridge/Tests/Node/FormThemeTest.php b/vendor/symfony/twig-bridge/Tests/Node/FormThemeTest.php index 1f7f6322bdef0d9788d955e4a0e52135a7cafa4e..39d9f44be8c790baefe418ee507984b37212eb8f 100644 --- a/vendor/symfony/twig-bridge/Tests/Node/FormThemeTest.php +++ b/vendor/symfony/twig-bridge/Tests/Node/FormThemeTest.php @@ -30,10 +30,10 @@ class FormThemeTest extends TestCase public function testConstructor() { $form = new NameExpression('form', 0); - $resources = new Node(array( + $resources = new Node([ new ConstantExpression('tpl1', 0), new ConstantExpression('tpl2', 0), - )); + ]); $node = new FormThemeNode($form, $resources, 0); @@ -45,12 +45,12 @@ class FormThemeTest extends TestCase public function testCompile() { $form = new NameExpression('form', 0); - $resources = new ArrayExpression(array( + $resources = new ArrayExpression([ new ConstantExpression(0, 0), new ConstantExpression('tpl1', 0), new ConstantExpression(1, 0), new ConstantExpression('tpl2', 0), - ), 0); + ], 0); $node = new FormThemeNode($form, $resources, 0); @@ -61,7 +61,7 @@ class FormThemeTest extends TestCase $this->assertEquals( sprintf( - '$this->env->getRuntime("Symfony\\\\Component\\\\Form\\\\FormRenderer")->setTheme(%s, array(0 => "tpl1", 1 => "tpl2"), true);', + '$this->env->getRuntime("Symfony\\\\Component\\\\Form\\\\FormRenderer")->setTheme(%s, [0 => "tpl1", 1 => "tpl2"], true);', $this->getVariableGetter('form') ), trim($compiler->compile($node)->getSource()) @@ -71,7 +71,7 @@ class FormThemeTest extends TestCase $this->assertEquals( sprintf( - '$this->env->getRuntime("Symfony\\\\Component\\\\Form\\\\FormRenderer")->setTheme(%s, array(0 => "tpl1", 1 => "tpl2"), false);', + '$this->env->getRuntime("Symfony\\\\Component\\\\Form\\\\FormRenderer")->setTheme(%s, [0 => "tpl1", 1 => "tpl2"], false);', $this->getVariableGetter('form') ), trim($compiler->compile($node)->getSource()) diff --git a/vendor/symfony/twig-bridge/Tests/Node/SearchAndRenderBlockNodeTest.php b/vendor/symfony/twig-bridge/Tests/Node/SearchAndRenderBlockNodeTest.php index 4f66406a8ae3265aae5fb46a5f0266531feaca13..db160b7c8a089abf879ba04b8eb8730ae387bbc5 100644 --- a/vendor/symfony/twig-bridge/Tests/Node/SearchAndRenderBlockNodeTest.php +++ b/vendor/symfony/twig-bridge/Tests/Node/SearchAndRenderBlockNodeTest.php @@ -25,9 +25,9 @@ class SearchAndRenderBlockNodeTest extends TestCase { public function testCompileWidget() { - $arguments = new Node(array( + $arguments = new Node([ new NameExpression('form', 0), - )); + ]); $node = new SearchAndRenderBlockNode('form_widget', $arguments, 0); @@ -44,13 +44,13 @@ class SearchAndRenderBlockNodeTest extends TestCase public function testCompileWidgetWithVariables() { - $arguments = new Node(array( + $arguments = new Node([ new NameExpression('form', 0), - new ArrayExpression(array( + new ArrayExpression([ new ConstantExpression('foo', 0), new ConstantExpression('bar', 0), - ), 0), - )); + ], 0), + ]); $node = new SearchAndRenderBlockNode('form_widget', $arguments, 0); @@ -58,7 +58,7 @@ class SearchAndRenderBlockNodeTest extends TestCase $this->assertEquals( sprintf( - '$this->env->getRuntime(\'Symfony\Component\Form\FormRenderer\')->searchAndRenderBlock(%s, \'widget\', array("foo" => "bar"))', + '$this->env->getRuntime(\'Symfony\Component\Form\FormRenderer\')->searchAndRenderBlock(%s, \'widget\', ["foo" => "bar"])', $this->getVariableGetter('form') ), trim($compiler->compile($node)->getSource()) @@ -67,10 +67,10 @@ class SearchAndRenderBlockNodeTest extends TestCase public function testCompileLabelWithLabel() { - $arguments = new Node(array( + $arguments = new Node([ new NameExpression('form', 0), new ConstantExpression('my label', 0), - )); + ]); $node = new SearchAndRenderBlockNode('form_label', $arguments, 0); @@ -78,7 +78,7 @@ class SearchAndRenderBlockNodeTest extends TestCase $this->assertEquals( sprintf( - '$this->env->getRuntime(\'Symfony\Component\Form\FormRenderer\')->searchAndRenderBlock(%s, \'label\', array("label" => "my label"))', + '$this->env->getRuntime(\'Symfony\Component\Form\FormRenderer\')->searchAndRenderBlock(%s, \'label\', ["label" => "my label"])', $this->getVariableGetter('form') ), trim($compiler->compile($node)->getSource()) @@ -87,10 +87,10 @@ class SearchAndRenderBlockNodeTest extends TestCase public function testCompileLabelWithNullLabel() { - $arguments = new Node(array( + $arguments = new Node([ new NameExpression('form', 0), new ConstantExpression(null, 0), - )); + ]); $node = new SearchAndRenderBlockNode('form_label', $arguments, 0); @@ -109,10 +109,10 @@ class SearchAndRenderBlockNodeTest extends TestCase public function testCompileLabelWithEmptyStringLabel() { - $arguments = new Node(array( + $arguments = new Node([ new NameExpression('form', 0), new ConstantExpression('', 0), - )); + ]); $node = new SearchAndRenderBlockNode('form_label', $arguments, 0); @@ -131,9 +131,9 @@ class SearchAndRenderBlockNodeTest extends TestCase public function testCompileLabelWithDefaultLabel() { - $arguments = new Node(array( + $arguments = new Node([ new NameExpression('form', 0), - )); + ]); $node = new SearchAndRenderBlockNode('form_label', $arguments, 0); @@ -150,14 +150,14 @@ class SearchAndRenderBlockNodeTest extends TestCase public function testCompileLabelWithAttributes() { - $arguments = new Node(array( + $arguments = new Node([ new NameExpression('form', 0), new ConstantExpression(null, 0), - new ArrayExpression(array( + new ArrayExpression([ new ConstantExpression('foo', 0), new ConstantExpression('bar', 0), - ), 0), - )); + ], 0), + ]); $node = new SearchAndRenderBlockNode('form_label', $arguments, 0); @@ -168,7 +168,7 @@ class SearchAndRenderBlockNodeTest extends TestCase // https://github.com/symfony/symfony/issues/5029 $this->assertEquals( sprintf( - '$this->env->getRuntime(\'Symfony\Component\Form\FormRenderer\')->searchAndRenderBlock(%s, \'label\', array("foo" => "bar"))', + '$this->env->getRuntime(\'Symfony\Component\Form\FormRenderer\')->searchAndRenderBlock(%s, \'label\', ["foo" => "bar"])', $this->getVariableGetter('form') ), trim($compiler->compile($node)->getSource()) @@ -177,16 +177,16 @@ class SearchAndRenderBlockNodeTest extends TestCase public function testCompileLabelWithLabelAndAttributes() { - $arguments = new Node(array( + $arguments = new Node([ new NameExpression('form', 0), new ConstantExpression('value in argument', 0), - new ArrayExpression(array( + new ArrayExpression([ new ConstantExpression('foo', 0), new ConstantExpression('bar', 0), new ConstantExpression('label', 0), new ConstantExpression('value in attributes', 0), - ), 0), - )); + ], 0), + ]); $node = new SearchAndRenderBlockNode('form_label', $arguments, 0); @@ -194,7 +194,7 @@ class SearchAndRenderBlockNodeTest extends TestCase $this->assertEquals( sprintf( - '$this->env->getRuntime(\'Symfony\Component\Form\FormRenderer\')->searchAndRenderBlock(%s, \'label\', array("foo" => "bar", "label" => "value in argument"))', + '$this->env->getRuntime(\'Symfony\Component\Form\FormRenderer\')->searchAndRenderBlock(%s, \'label\', ["foo" => "bar", "label" => "value in argument"])', $this->getVariableGetter('form') ), trim($compiler->compile($node)->getSource()) @@ -203,7 +203,7 @@ class SearchAndRenderBlockNodeTest extends TestCase public function testCompileLabelWithLabelThatEvaluatesToNull() { - $arguments = new Node(array( + $arguments = new Node([ new NameExpression('form', 0), new ConditionalExpression( // if @@ -214,7 +214,7 @@ class SearchAndRenderBlockNodeTest extends TestCase new ConstantExpression(null, 0), 0 ), - )); + ]); $node = new SearchAndRenderBlockNode('form_label', $arguments, 0); @@ -225,7 +225,7 @@ class SearchAndRenderBlockNodeTest extends TestCase // https://github.com/symfony/symfony/issues/5029 $this->assertEquals( sprintf( - '$this->env->getRuntime(\'Symfony\Component\Form\FormRenderer\')->searchAndRenderBlock(%s, \'label\', (twig_test_empty($_label_ = ((true) ? (null) : (null))) ? array() : array("label" => $_label_)))', + '$this->env->getRuntime(\'Symfony\Component\Form\FormRenderer\')->searchAndRenderBlock(%s, \'label\', (twig_test_empty($_label_ = ((true) ? (null) : (null))) ? [] : ["label" => $_label_]))', $this->getVariableGetter('form') ), trim($compiler->compile($node)->getSource()) @@ -234,7 +234,7 @@ class SearchAndRenderBlockNodeTest extends TestCase public function testCompileLabelWithLabelThatEvaluatesToNullAndAttributes() { - $arguments = new Node(array( + $arguments = new Node([ new NameExpression('form', 0), new ConditionalExpression( // if @@ -245,13 +245,13 @@ class SearchAndRenderBlockNodeTest extends TestCase new ConstantExpression(null, 0), 0 ), - new ArrayExpression(array( + new ArrayExpression([ new ConstantExpression('foo', 0), new ConstantExpression('bar', 0), new ConstantExpression('label', 0), new ConstantExpression('value in attributes', 0), - ), 0), - )); + ], 0), + ]); $node = new SearchAndRenderBlockNode('form_label', $arguments, 0); @@ -262,7 +262,7 @@ class SearchAndRenderBlockNodeTest extends TestCase // https://github.com/symfony/symfony/issues/5029 $this->assertEquals( sprintf( - '$this->env->getRuntime(\'Symfony\Component\Form\FormRenderer\')->searchAndRenderBlock(%s, \'label\', array("foo" => "bar", "label" => "value in attributes") + (twig_test_empty($_label_ = ((true) ? (null) : (null))) ? array() : array("label" => $_label_)))', + '$this->env->getRuntime(\'Symfony\Component\Form\FormRenderer\')->searchAndRenderBlock(%s, \'label\', ["foo" => "bar", "label" => "value in attributes"] + (twig_test_empty($_label_ = ((true) ? (null) : (null))) ? [] : ["label" => $_label_]))', $this->getVariableGetter('form') ), trim($compiler->compile($node)->getSource()) diff --git a/vendor/symfony/twig-bridge/Tests/Node/TransNodeTest.php b/vendor/symfony/twig-bridge/Tests/Node/TransNodeTest.php index 4c873862535a8899431d0b9966a10fe0ba5cda99..3008f43f6f4bc97b798c3c698aaf08cdf4fb69eb 100644 --- a/vendor/symfony/twig-bridge/Tests/Node/TransNodeTest.php +++ b/vendor/symfony/twig-bridge/Tests/Node/TransNodeTest.php @@ -29,12 +29,12 @@ class TransNodeTest extends TestCase $vars = new NameExpression('foo', 0); $node = new TransNode($body, null, null, $vars); - $env = new Environment($this->getMockBuilder('Twig\Loader\LoaderInterface')->getMock(), array('strict_variables' => true)); + $env = new Environment($this->getMockBuilder('Twig\Loader\LoaderInterface')->getMock(), ['strict_variables' => true]); $compiler = new Compiler($env); $this->assertEquals( sprintf( - 'echo $this->env->getExtension(\'Symfony\Bridge\Twig\Extension\TranslationExtension\')->getTranslator()->trans("trans %%var%%", array_merge(array("%%var%%" => %s), %s), "messages");', + 'echo $this->env->getExtension(\'Symfony\Bridge\Twig\Extension\TranslationExtension\')->getTranslator()->trans("trans %%var%%", array_merge(["%%var%%" => %s], %s), "messages");', $this->getVariableGetterWithoutStrictCheck('var'), $this->getVariableGetterWithStrictCheck('foo') ), @@ -54,7 +54,7 @@ class TransNodeTest extends TestCase protected function getVariableGetterWithStrictCheck($name) { if (Environment::MAJOR_VERSION >= 2) { - return sprintf('(isset($context["%s"]) || array_key_exists("%1$s", $context) ? $context["%1$s"] : (function () { throw new Twig_Error_Runtime(\'Variable "%1$s" does not exist.\', 0, $this->getSourceContext()); })())', $name); + return sprintf('(isset($context["%1$s"]) || array_key_exists("%1$s", $context) ? $context["%1$s"] : (function () { throw new %2$s(\'Variable "%1$s" does not exist.\', 0, $this->source); })())', $name, Environment::VERSION_ID >= 20700 ? 'RuntimeError' : 'Twig_Error_Runtime'); } if (\PHP_VERSION_ID >= 70000) { diff --git a/vendor/symfony/twig-bridge/Tests/NodeVisitor/TranslationDefaultDomainNodeVisitorTest.php b/vendor/symfony/twig-bridge/Tests/NodeVisitor/TranslationDefaultDomainNodeVisitorTest.php index eb4c9a83e86d76ba957c621206fd7dcc679472b7..5abfe1e92a6caaccc188a4375b7c08f2517ab548 100644 --- a/vendor/symfony/twig-bridge/Tests/NodeVisitor/TranslationDefaultDomainNodeVisitorTest.php +++ b/vendor/symfony/twig-bridge/Tests/NodeVisitor/TranslationDefaultDomainNodeVisitorTest.php @@ -26,7 +26,7 @@ class TranslationDefaultDomainNodeVisitorTest extends TestCase /** @dataProvider getDefaultDomainAssignmentTestData */ public function testDefaultDomainAssignment(Node $node) { - $env = new Environment($this->getMockBuilder('Twig\Loader\LoaderInterface')->getMock(), array('cache' => false, 'autoescape' => false, 'optimizations' => 0)); + $env = new Environment($this->getMockBuilder('Twig\Loader\LoaderInterface')->getMock(), ['cache' => false, 'autoescape' => false, 'optimizations' => 0]); $visitor = new TranslationDefaultDomainNodeVisitor(); // visit trans_default_domain tag @@ -46,13 +46,13 @@ class TranslationDefaultDomainNodeVisitorTest extends TestCase $visitor->enterNode($node, $env); $visitor->leaveNode($node, $env); - $this->assertEquals(array(array(self::$message, self::$domain)), $visitor->getMessages()); + $this->assertEquals([[self::$message, self::$domain]], $visitor->getMessages()); } /** @dataProvider getDefaultDomainAssignmentTestData */ public function testNewModuleWithoutDefaultDomainTag(Node $node) { - $env = new Environment($this->getMockBuilder('Twig\Loader\LoaderInterface')->getMock(), array('cache' => false, 'autoescape' => false, 'optimizations' => 0)); + $env = new Environment($this->getMockBuilder('Twig\Loader\LoaderInterface')->getMock(), ['cache' => false, 'autoescape' => false, 'optimizations' => 0]); $visitor = new TranslationDefaultDomainNodeVisitor(); // visit trans_default_domain tag @@ -72,22 +72,22 @@ class TranslationDefaultDomainNodeVisitorTest extends TestCase $visitor->enterNode($node, $env); $visitor->leaveNode($node, $env); - $this->assertEquals(array(array(self::$message, null)), $visitor->getMessages()); + $this->assertEquals([[self::$message, null]], $visitor->getMessages()); } public function getDefaultDomainAssignmentTestData() { - return array( - array(TwigNodeProvider::getTransFilter(self::$message)), - array(TwigNodeProvider::getTransChoiceFilter(self::$message)), - array(TwigNodeProvider::getTransTag(self::$message)), + return [ + [TwigNodeProvider::getTransFilter(self::$message)], + [TwigNodeProvider::getTransChoiceFilter(self::$message)], + [TwigNodeProvider::getTransTag(self::$message)], // with named arguments - array(TwigNodeProvider::getTransFilter(self::$message, null, array( - 'arguments' => new ArrayExpression(array(), 0), - ))), - array(TwigNodeProvider::getTransChoiceFilter(self::$message), null, array( - 'arguments' => new ArrayExpression(array(), 0), - )), - ); + [TwigNodeProvider::getTransFilter(self::$message, null, [ + 'arguments' => new ArrayExpression([], 0), + ])], + [TwigNodeProvider::getTransChoiceFilter(self::$message), null, [ + 'arguments' => new ArrayExpression([], 0), + ]], + ]; } } diff --git a/vendor/symfony/twig-bridge/Tests/NodeVisitor/TranslationNodeVisitorTest.php b/vendor/symfony/twig-bridge/Tests/NodeVisitor/TranslationNodeVisitorTest.php index 9c2d0ab9e40e5b0286069a4517d3c3a39f674047..11d16e4cd674461704330928d60e8d8a7d07b26c 100644 --- a/vendor/symfony/twig-bridge/Tests/NodeVisitor/TranslationNodeVisitorTest.php +++ b/vendor/symfony/twig-bridge/Tests/NodeVisitor/TranslationNodeVisitorTest.php @@ -25,7 +25,7 @@ class TranslationNodeVisitorTest extends TestCase /** @dataProvider getMessagesExtractionTestData */ public function testMessagesExtraction(Node $node, array $expectedMessages) { - $env = new Environment($this->getMockBuilder('Twig\Loader\LoaderInterface')->getMock(), array('cache' => false, 'autoescape' => false, 'optimizations' => 0)); + $env = new Environment($this->getMockBuilder('Twig\Loader\LoaderInterface')->getMock(), ['cache' => false, 'autoescape' => false, 'optimizations' => 0]); $visitor = new TranslationNodeVisitor(); $visitor->enable(); $visitor->enterNode($node, $env); @@ -40,14 +40,14 @@ class TranslationNodeVisitorTest extends TestCase $node = new FilterExpression( new ConstantExpression($message, 0), new ConstantExpression('trans', 0), - new Node(array( - new ArrayExpression(array(), 0), + new Node([ + new ArrayExpression([], 0), new NameExpression('variable', 0), - )), + ]), 0 ); - $this->testMessagesExtraction($node, array(array($message, TranslationNodeVisitor::UNDEFINED_DOMAIN))); + $this->testMessagesExtraction($node, [[$message, TranslationNodeVisitor::UNDEFINED_DOMAIN]]); } public function getMessagesExtractionTestData() @@ -55,13 +55,13 @@ class TranslationNodeVisitorTest extends TestCase $message = 'new key'; $domain = 'domain'; - return array( - array(TwigNodeProvider::getTransFilter($message), array(array($message, null))), - array(TwigNodeProvider::getTransChoiceFilter($message), array(array($message, null))), - array(TwigNodeProvider::getTransTag($message), array(array($message, null))), - array(TwigNodeProvider::getTransFilter($message, $domain), array(array($message, $domain))), - array(TwigNodeProvider::getTransChoiceFilter($message, $domain), array(array($message, $domain))), - array(TwigNodeProvider::getTransTag($message, $domain), array(array($message, $domain))), - ); + return [ + [TwigNodeProvider::getTransFilter($message), [[$message, null]]], + [TwigNodeProvider::getTransChoiceFilter($message), [[$message, null]]], + [TwigNodeProvider::getTransTag($message), [[$message, null]]], + [TwigNodeProvider::getTransFilter($message, $domain), [[$message, $domain]]], + [TwigNodeProvider::getTransChoiceFilter($message, $domain), [[$message, $domain]]], + [TwigNodeProvider::getTransTag($message, $domain), [[$message, $domain]]], + ]; } } diff --git a/vendor/symfony/twig-bridge/Tests/NodeVisitor/TwigNodeProvider.php b/vendor/symfony/twig-bridge/Tests/NodeVisitor/TwigNodeProvider.php index 49eac23e8aedaed22c6472bc3aa16a23d0c9cc52..5147724675817f2f626a12974b96b050375b8f82 100644 --- a/vendor/symfony/twig-bridge/Tests/NodeVisitor/TwigNodeProvider.php +++ b/vendor/symfony/twig-bridge/Tests/NodeVisitor/TwigNodeProvider.php @@ -28,9 +28,9 @@ class TwigNodeProvider return new ModuleNode( new ConstantExpression($content, 0), null, - new ArrayExpression(array(), 0), - new ArrayExpression(array(), 0), - new ArrayExpression(array(), 0), + new ArrayExpression([], 0), + new ArrayExpression([], 0), + new ArrayExpression([], 0), null, new Source('', '') ); @@ -39,10 +39,10 @@ class TwigNodeProvider public static function getTransFilter($message, $domain = null, $arguments = null) { if (!$arguments) { - $arguments = $domain ? array( - new ArrayExpression(array(), 0), + $arguments = $domain ? [ + new ArrayExpression([], 0), new ConstantExpression($domain, 0), - ) : array(); + ] : []; } return new FilterExpression( @@ -56,11 +56,11 @@ class TwigNodeProvider public static function getTransChoiceFilter($message, $domain = null, $arguments = null) { if (!$arguments) { - $arguments = $domain ? array( + $arguments = $domain ? [ new ConstantExpression(0, 0), - new ArrayExpression(array(), 0), + new ArrayExpression([], 0), new ConstantExpression($domain, 0), - ) : array(); + ] : []; } return new FilterExpression( @@ -74,7 +74,7 @@ class TwigNodeProvider public static function getTransTag($message, $domain = null) { return new TransNode( - new BodyNode(array(), array('data' => $message)), + new BodyNode([], ['data' => $message]), $domain ? new ConstantExpression($domain, 0) : null ); } diff --git a/vendor/symfony/twig-bridge/Tests/TokenParser/FormThemeTokenParserTest.php b/vendor/symfony/twig-bridge/Tests/TokenParser/FormThemeTokenParserTest.php index cd9a34cab67b908c202956621105a1a2bbbe8c47..ce1980eb16403b407ca33eda96bd617692e6446f 100644 --- a/vendor/symfony/twig-bridge/Tests/TokenParser/FormThemeTokenParserTest.php +++ b/vendor/symfony/twig-bridge/Tests/TokenParser/FormThemeTokenParserTest.php @@ -12,8 +12,8 @@ namespace Symfony\Bridge\Twig\Tests\TokenParser; use PHPUnit\Framework\TestCase; -use Symfony\Bridge\Twig\TokenParser\FormThemeTokenParser; use Symfony\Bridge\Twig\Node\FormThemeNode; +use Symfony\Bridge\Twig\TokenParser\FormThemeTokenParser; use Twig\Environment; use Twig\Node\Expression\ArrayExpression; use Twig\Node\Expression\ConstantExpression; @@ -28,44 +28,47 @@ class FormThemeTokenParserTest extends TestCase */ public function testCompile($source, $expected) { - $env = new Environment($this->getMockBuilder('Twig\Loader\LoaderInterface')->getMock(), array('cache' => false, 'autoescape' => false, 'optimizations' => 0)); + $env = new Environment($this->getMockBuilder('Twig\Loader\LoaderInterface')->getMock(), ['cache' => false, 'autoescape' => false, 'optimizations' => 0]); $env->addTokenParser(new FormThemeTokenParser()); - $stream = $env->tokenize(new Source($source, '')); + $source = new Source($source, ''); + $stream = $env->tokenize($source); $parser = new Parser($env); + $expected->setSourceContext($source); + $this->assertEquals($expected, $parser->parse($stream)->getNode('body')->getNode(0)); } public function getTestsForFormTheme() { - return array( - array( + return [ + [ '{% form_theme form "tpl1" %}', new FormThemeNode( new NameExpression('form', 1), - new ArrayExpression(array( + new ArrayExpression([ new ConstantExpression(0, 1), new ConstantExpression('tpl1', 1), - ), 1), + ], 1), 1, 'form_theme' ), - ), - array( + ], + [ '{% form_theme form "tpl1" "tpl2" %}', new FormThemeNode( new NameExpression('form', 1), - new ArrayExpression(array( + new ArrayExpression([ new ConstantExpression(0, 1), new ConstantExpression('tpl1', 1), new ConstantExpression(1, 1), new ConstantExpression('tpl2', 1), - ), 1), + ], 1), 1, 'form_theme' ), - ), - array( + ], + [ '{% form_theme form with "tpl1" %}', new FormThemeNode( new NameExpression('form', 1), @@ -73,48 +76,48 @@ class FormThemeTokenParserTest extends TestCase 1, 'form_theme' ), - ), - array( + ], + [ '{% form_theme form with ["tpl1"] %}', new FormThemeNode( new NameExpression('form', 1), - new ArrayExpression(array( + new ArrayExpression([ new ConstantExpression(0, 1), new ConstantExpression('tpl1', 1), - ), 1), + ], 1), 1, 'form_theme' ), - ), - array( + ], + [ '{% form_theme form with ["tpl1", "tpl2"] %}', new FormThemeNode( new NameExpression('form', 1), - new ArrayExpression(array( + new ArrayExpression([ new ConstantExpression(0, 1), new ConstantExpression('tpl1', 1), new ConstantExpression(1, 1), new ConstantExpression('tpl2', 1), - ), 1), + ], 1), 1, 'form_theme' ), - ), - array( + ], + [ '{% form_theme form with ["tpl1", "tpl2"] only %}', new FormThemeNode( new NameExpression('form', 1), - new ArrayExpression(array( + new ArrayExpression([ new ConstantExpression(0, 1), new ConstantExpression('tpl1', 1), new ConstantExpression(1, 1), new ConstantExpression('tpl2', 1), - ), 1), + ], 1), 1, 'form_theme', true ), - ), - ); + ], + ]; } } diff --git a/vendor/symfony/twig-bridge/Tests/Translation/TwigExtractorTest.php b/vendor/symfony/twig-bridge/Tests/Translation/TwigExtractorTest.php index 013598a40b17fc7523839fa7903f4a969e0882b1..82d72983657ba90ede5815b0c37fae3cc7908cf3 100644 --- a/vendor/symfony/twig-bridge/Tests/Translation/TwigExtractorTest.php +++ b/vendor/symfony/twig-bridge/Tests/Translation/TwigExtractorTest.php @@ -27,12 +27,12 @@ class TwigExtractorTest extends TestCase public function testExtract($template, $messages) { $loader = $this->getMockBuilder('Twig\Loader\LoaderInterface')->getMock(); - $twig = new Environment($loader, array( + $twig = new Environment($loader, [ 'strict_variables' => true, 'debug' => true, 'cache' => false, 'autoescape' => false, - )); + ]); $twig->addExtension(new TranslationExtension($this->getMockBuilder('Symfony\Component\Translation\TranslatorInterface')->getMock())); $extractor = new TwigExtractor($twig); @@ -51,36 +51,36 @@ class TwigExtractorTest extends TestCase public function getExtractData() { - return array( - array('{{ "new key" | trans() }}', array('new key' => 'messages')), - array('{{ "new key" | trans() | upper }}', array('new key' => 'messages')), - array('{{ "new key" | trans({}, "domain") }}', array('new key' => 'domain')), - array('{{ "new key" | transchoice(1) }}', array('new key' => 'messages')), - array('{{ "new key" | transchoice(1) | upper }}', array('new key' => 'messages')), - array('{{ "new key" | transchoice(1, {}, "domain") }}', array('new key' => 'domain')), - array('{% trans %}new key{% endtrans %}', array('new key' => 'messages')), - array('{% trans %} new key {% endtrans %}', array('new key' => 'messages')), - array('{% trans from "domain" %}new key{% endtrans %}', array('new key' => 'domain')), - array('{% set foo = "new key" | trans %}', array('new key' => 'messages')), - array('{{ 1 ? "new key" | trans : "another key" | trans }}', array('new key' => 'messages', 'another key' => 'messages')), + return [ + ['{{ "new key" | trans() }}', ['new key' => 'messages']], + ['{{ "new key" | trans() | upper }}', ['new key' => 'messages']], + ['{{ "new key" | trans({}, "domain") }}', ['new key' => 'domain']], + ['{{ "new key" | transchoice(1) }}', ['new key' => 'messages']], + ['{{ "new key" | transchoice(1) | upper }}', ['new key' => 'messages']], + ['{{ "new key" | transchoice(1, {}, "domain") }}', ['new key' => 'domain']], + ['{% trans %}new key{% endtrans %}', ['new key' => 'messages']], + ['{% trans %} new key {% endtrans %}', ['new key' => 'messages']], + ['{% trans from "domain" %}new key{% endtrans %}', ['new key' => 'domain']], + ['{% set foo = "new key" | trans %}', ['new key' => 'messages']], + ['{{ 1 ? "new key" | trans : "another key" | trans }}', ['new key' => 'messages', 'another key' => 'messages']], // make sure 'trans_default_domain' tag is supported - array('{% trans_default_domain "domain" %}{{ "new key"|trans }}', array('new key' => 'domain')), - array('{% trans_default_domain "domain" %}{{ "new key"|transchoice }}', array('new key' => 'domain')), - array('{% trans_default_domain "domain" %}{% trans %}new key{% endtrans %}', array('new key' => 'domain')), + ['{% trans_default_domain "domain" %}{{ "new key"|trans }}', ['new key' => 'domain']], + ['{% trans_default_domain "domain" %}{{ "new key"|transchoice }}', ['new key' => 'domain']], + ['{% trans_default_domain "domain" %}{% trans %}new key{% endtrans %}', ['new key' => 'domain']], // make sure this works with twig's named arguments - array('{{ "new key" | trans(domain="domain") }}', array('new key' => 'domain')), - array('{{ "new key" | transchoice(domain="domain", count=1) }}', array('new key' => 'domain')), - ); + ['{{ "new key" | trans(domain="domain") }}', ['new key' => 'domain']], + ['{{ "new key" | transchoice(domain="domain", count=1) }}', ['new key' => 'domain']], + ]; } /** - * @expectedException \Twig\Error\Error * @dataProvider resourcesWithSyntaxErrorsProvider */ public function testExtractSyntaxError($resources) { + $this->expectException('Twig\Error\Error'); $twig = new Environment($this->getMockBuilder('Twig\Loader\LoaderInterface')->getMock()); $twig->addExtension(new TranslationExtension($this->getMockBuilder('Symfony\Component\Translation\TranslatorInterface')->getMock())); @@ -89,13 +89,10 @@ class TwigExtractorTest extends TestCase try { $extractor->extract($resources, new MessageCatalogue('en')); } catch (Error $e) { - if (method_exists($e, 'getSourceContext')) { - $this->assertSame(dirname(__DIR__).strtr('/Fixtures/extractor/syntax_error.twig', '/', DIRECTORY_SEPARATOR), $e->getFile()); - $this->assertSame(1, $e->getLine()); - $this->assertSame('Unclosed "block".', $e->getMessage()); - } else { - $this->expectExceptionMessageRegExp('/Unclosed "block" in ".*extractor(\\/|\\\\)syntax_error\\.twig" at line 1/'); - } + $this->assertSame(\dirname(__DIR__).strtr('/Fixtures/extractor/syntax_error.twig', '/', \DIRECTORY_SEPARATOR), $e->getFile()); + $this->assertSame(1, $e->getLine()); + $this->assertSame('Unclosed "block".', $e->getMessage()); + throw $e; } } @@ -105,11 +102,11 @@ class TwigExtractorTest extends TestCase */ public function resourcesWithSyntaxErrorsProvider() { - return array( - array(__DIR__.'/../Fixtures'), - array(__DIR__.'/../Fixtures/extractor/syntax_error.twig'), - array(new \SplFileInfo(__DIR__.'/../Fixtures/extractor/syntax_error.twig')), - ); + return [ + [__DIR__.'/../Fixtures'], + [__DIR__.'/../Fixtures/extractor/syntax_error.twig'], + [new \SplFileInfo(__DIR__.'/../Fixtures/extractor/syntax_error.twig')], + ]; } /** @@ -117,13 +114,13 @@ class TwigExtractorTest extends TestCase */ public function testExtractWithFiles($resource) { - $loader = new ArrayLoader(array()); - $twig = new Environment($loader, array( + $loader = new ArrayLoader([]); + $twig = new Environment($loader, [ 'strict_variables' => true, 'debug' => true, 'cache' => false, 'autoescape' => false, - )); + ]); $twig->addExtension(new TranslationExtension($this->getMockBuilder('Symfony\Component\Translation\TranslatorInterface')->getMock())); $extractor = new TwigExtractor($twig); @@ -141,12 +138,12 @@ class TwigExtractorTest extends TestCase { $directory = __DIR__.'/../Fixtures/extractor/'; - return array( - array($directory.'with_translations.html.twig'), - array(array($directory.'with_translations.html.twig')), - array(array(new \SplFileInfo($directory.'with_translations.html.twig'))), - array(new \ArrayObject(array($directory.'with_translations.html.twig'))), - array(new \ArrayObject(array(new \SplFileInfo($directory.'with_translations.html.twig')))), - ); + return [ + [$directory.'with_translations.html.twig'], + [[$directory.'with_translations.html.twig']], + [[new \SplFileInfo($directory.'with_translations.html.twig')]], + [new \ArrayObject([$directory.'with_translations.html.twig'])], + [new \ArrayObject([new \SplFileInfo($directory.'with_translations.html.twig')])], + ]; } } diff --git a/vendor/symfony/twig-bridge/Tests/TwigEngineTest.php b/vendor/symfony/twig-bridge/Tests/TwigEngineTest.php index a74c59e8d28c9555afcfea754c7ff242a3918e9d..e136d0c763c6609c02931fcf697d6e9c14ac5d22 100644 --- a/vendor/symfony/twig-bridge/Tests/TwigEngineTest.php +++ b/vendor/symfony/twig-bridge/Tests/TwigEngineTest.php @@ -23,7 +23,7 @@ class TwigEngineTest extends TestCase { $engine = $this->getTwig(); - $this->assertTrue($engine->exists($this->getMockForAbstractClass('Twig\Template', array(), '', false))); + $this->assertTrue($engine->exists($this->getMockForAbstractClass('Twig\Template', [], '', false))); } public function testExistsWithNonExistentTemplates() @@ -58,11 +58,9 @@ class TwigEngineTest extends TestCase $this->assertSame('foo', $engine->render(new TemplateReference('index'))); } - /** - * @expectedException \Twig\Error\SyntaxError - */ public function testRenderWithError() { + $this->expectException('Twig\Error\SyntaxError'); $engine = $this->getTwig(); $engine->render(new TemplateReference('error')); @@ -70,10 +68,10 @@ class TwigEngineTest extends TestCase protected function getTwig() { - $twig = new Environment(new ArrayLoader(array( + $twig = new Environment(new ArrayLoader([ 'index' => 'foo', 'error' => '{{ foo }', - ))); + ])); $parser = $this->getMockBuilder('Symfony\Component\Templating\TemplateNameParserInterface')->getMock(); return new TwigEngine($twig, $parser); diff --git a/vendor/symfony/twig-bridge/TokenParser/DumpTokenParser.php b/vendor/symfony/twig-bridge/TokenParser/DumpTokenParser.php index 7cdbb77b4349b4dafddb53d268c1846aa3384c53..a4d7d6f6900781e6168ad1a404b5c80954f6b9b5 100644 --- a/vendor/symfony/twig-bridge/TokenParser/DumpTokenParser.php +++ b/vendor/symfony/twig-bridge/TokenParser/DumpTokenParser.php @@ -19,11 +19,10 @@ use Twig\TokenParser\AbstractTokenParser; * Token Parser for the 'dump' tag. * * Dump variables with: - * <pre> - * {% dump %} - * {% dump foo %} - * {% dump foo, bar %} - * </pre> + * + * {% dump %} + * {% dump foo %} + * {% dump foo, bar %} * * @author Julien Galenski <julien.galenski@gmail.com> */ diff --git a/vendor/symfony/twig-bridge/TokenParser/FormThemeTokenParser.php b/vendor/symfony/twig-bridge/TokenParser/FormThemeTokenParser.php index 2388cc56623beaf9ba90432ed6737422c0e2a2c8..ffef9e9859277f1da09e14bbba09444f8433bb34 100644 --- a/vendor/symfony/twig-bridge/TokenParser/FormThemeTokenParser.php +++ b/vendor/symfony/twig-bridge/TokenParser/FormThemeTokenParser.php @@ -45,7 +45,7 @@ class FormThemeTokenParser extends AbstractTokenParser $only = true; } } else { - $resources = new ArrayExpression(array(), $stream->getCurrent()->getLine()); + $resources = new ArrayExpression([], $stream->getCurrent()->getLine()); do { $resources->addElement($this->parser->getExpressionParser()->parseExpression()); } while (!$stream->test(Token::BLOCK_END_TYPE)); diff --git a/vendor/symfony/twig-bridge/TokenParser/StopwatchTokenParser.php b/vendor/symfony/twig-bridge/TokenParser/StopwatchTokenParser.php index 82c58d40bbf8d3f95c1657073ec6831d3b02fd8e..4cf4ffcd7e9c56a7e6221817126769d1b8188041 100644 --- a/vendor/symfony/twig-bridge/TokenParser/StopwatchTokenParser.php +++ b/vendor/symfony/twig-bridge/TokenParser/StopwatchTokenParser.php @@ -41,7 +41,7 @@ class StopwatchTokenParser extends AbstractTokenParser $stream->expect(Token::BLOCK_END_TYPE); // {% endstopwatch %} - $body = $this->parser->subparse(array($this, 'decideStopwatchEnd'), true); + $body = $this->parser->subparse([$this, 'decideStopwatchEnd'], true); $stream->expect(Token::BLOCK_END_TYPE); if ($this->stopwatchIsAvailable) { diff --git a/vendor/symfony/twig-bridge/TokenParser/TransChoiceTokenParser.php b/vendor/symfony/twig-bridge/TokenParser/TransChoiceTokenParser.php index 5261d7ad52cee172c46d683b9b4178e2c3093fb1..b1c8a39b3a7ea9754b0eec0eb3393ab3fec4ef9b 100644 --- a/vendor/symfony/twig-bridge/TokenParser/TransChoiceTokenParser.php +++ b/vendor/symfony/twig-bridge/TokenParser/TransChoiceTokenParser.php @@ -15,7 +15,6 @@ use Symfony\Bridge\Twig\Node\TransNode; use Twig\Error\SyntaxError; use Twig\Node\Expression\AbstractExpression; use Twig\Node\Expression\ArrayExpression; -use Twig\Node\Node; use Twig\Node\TextNode; use Twig\Token; @@ -27,18 +26,14 @@ use Twig\Token; class TransChoiceTokenParser extends TransTokenParser { /** - * Parses a token and returns a node. - * - * @return Node - * - * @throws SyntaxError + * {@inheritdoc} */ public function parse(Token $token) { $lineno = $token->getLine(); $stream = $this->parser->getStream(); - $vars = new ArrayExpression(array(), $lineno); + $vars = new ArrayExpression([], $lineno); $count = $this->parser->getExpressionParser()->parseExpression(); @@ -65,10 +60,10 @@ class TransChoiceTokenParser extends TransTokenParser $stream->expect(Token::BLOCK_END_TYPE); - $body = $this->parser->subparse(array($this, 'decideTransChoiceFork'), true); + $body = $this->parser->subparse([$this, 'decideTransChoiceFork'], true); if (!$body instanceof TextNode && !$body instanceof AbstractExpression) { - throw new SyntaxError('A message inside a transchoice tag must be a simple text.', $body->getTemplateLine(), $stream->getSourceContext()->getName()); + throw new SyntaxError('A message inside a transchoice tag must be a simple text.', $body->getTemplateLine(), $stream->getSourceContext()); } $stream->expect(Token::BLOCK_END_TYPE); @@ -78,13 +73,11 @@ class TransChoiceTokenParser extends TransTokenParser public function decideTransChoiceFork($token) { - return $token->test(array('endtranschoice')); + return $token->test(['endtranschoice']); } /** - * Gets the tag name associated with this token parser. - * - * @return string The tag name + * {@inheritdoc} */ public function getTag() { diff --git a/vendor/symfony/twig-bridge/TokenParser/TransDefaultDomainTokenParser.php b/vendor/symfony/twig-bridge/TokenParser/TransDefaultDomainTokenParser.php index ee546e05f01257900095fa818916bfd73ddae993..72fbda77b8e485a2d28ee8c5dc9ae7f68b1cafbf 100644 --- a/vendor/symfony/twig-bridge/TokenParser/TransDefaultDomainTokenParser.php +++ b/vendor/symfony/twig-bridge/TokenParser/TransDefaultDomainTokenParser.php @@ -12,7 +12,6 @@ namespace Symfony\Bridge\Twig\TokenParser; use Symfony\Bridge\Twig\Node\TransDefaultDomainNode; -use Twig\Node\Node; use Twig\Token; use Twig\TokenParser\AbstractTokenParser; @@ -24,9 +23,7 @@ use Twig\TokenParser\AbstractTokenParser; class TransDefaultDomainTokenParser extends AbstractTokenParser { /** - * Parses a token and returns a node. - * - * @return Node + * {@inheritdoc} */ public function parse(Token $token) { @@ -38,9 +35,7 @@ class TransDefaultDomainTokenParser extends AbstractTokenParser } /** - * Gets the tag name associated with this token parser. - * - * @return string The tag name + * {@inheritdoc} */ public function getTag() { diff --git a/vendor/symfony/twig-bridge/TokenParser/TransTokenParser.php b/vendor/symfony/twig-bridge/TokenParser/TransTokenParser.php index 76c8dc06100c1b604e5a8ab024bdec5c82cc3ec0..5f1e19acb9bddd32a4fb567d6f0ee144604a4919 100644 --- a/vendor/symfony/twig-bridge/TokenParser/TransTokenParser.php +++ b/vendor/symfony/twig-bridge/TokenParser/TransTokenParser.php @@ -15,7 +15,6 @@ use Symfony\Bridge\Twig\Node\TransNode; use Twig\Error\SyntaxError; use Twig\Node\Expression\AbstractExpression; use Twig\Node\Expression\ArrayExpression; -use Twig\Node\Node; use Twig\Node\TextNode; use Twig\Token; use Twig\TokenParser\AbstractTokenParser; @@ -28,18 +27,14 @@ use Twig\TokenParser\AbstractTokenParser; class TransTokenParser extends AbstractTokenParser { /** - * Parses a token and returns a node. - * - * @return Node - * - * @throws SyntaxError + * {@inheritdoc} */ public function parse(Token $token) { $lineno = $token->getLine(); $stream = $this->parser->getStream(); - $vars = new ArrayExpression(array(), $lineno); + $vars = new ArrayExpression([], $lineno); $domain = null; $locale = null; if (!$stream->test(Token::BLOCK_END_TYPE)) { @@ -60,16 +55,16 @@ class TransTokenParser extends AbstractTokenParser $stream->next(); $locale = $this->parser->getExpressionParser()->parseExpression(); } elseif (!$stream->test(Token::BLOCK_END_TYPE)) { - throw new SyntaxError('Unexpected token. Twig was looking for the "with", "from", or "into" keyword.', $stream->getCurrent()->getLine(), $stream->getSourceContext()->getName()); + throw new SyntaxError('Unexpected token. Twig was looking for the "with", "from", or "into" keyword.', $stream->getCurrent()->getLine(), $stream->getSourceContext()); } } // {% trans %}message{% endtrans %} $stream->expect(Token::BLOCK_END_TYPE); - $body = $this->parser->subparse(array($this, 'decideTransFork'), true); + $body = $this->parser->subparse([$this, 'decideTransFork'], true); if (!$body instanceof TextNode && !$body instanceof AbstractExpression) { - throw new SyntaxError('A message inside a trans tag must be a simple text.', $body->getTemplateLine(), $stream->getSourceContext()->getName()); + throw new SyntaxError('A message inside a trans tag must be a simple text.', $body->getTemplateLine(), $stream->getSourceContext()); } $stream->expect(Token::BLOCK_END_TYPE); @@ -79,13 +74,11 @@ class TransTokenParser extends AbstractTokenParser public function decideTransFork($token) { - return $token->test(array('endtrans')); + return $token->test(['endtrans']); } /** - * Gets the tag name associated with this token parser. - * - * @return string The tag name + * {@inheritdoc} */ public function getTag() { diff --git a/vendor/symfony/twig-bridge/Translation/TwigExtractor.php b/vendor/symfony/twig-bridge/Translation/TwigExtractor.php index db388ab70ba9102ec909b71b92453ea9ae02dd42..b7c787226656f47b65eaf5bd83703dcf65172b4f 100644 --- a/vendor/symfony/twig-bridge/Translation/TwigExtractor.php +++ b/vendor/symfony/twig-bridge/Translation/TwigExtractor.php @@ -54,19 +54,14 @@ class TwigExtractor extends AbstractFileExtractor implements ExtractorInterface */ public function extract($resource, MessageCatalogue $catalogue) { - $files = $this->extractFiles($resource); - foreach ($files as $file) { + foreach ($this->extractFiles($resource) as $file) { try { $this->extractTemplate(file_get_contents($file->getPathname()), $catalogue); } catch (Error $e) { if ($file instanceof \SplFileInfo) { $path = $file->getRealPath() ?: $file->getPathname(); $name = $file instanceof SplFileInfo ? $file->getRelativePathname() : $path; - if (method_exists($e, 'setSourceContext')) { - $e->setSourceContext(new Source('', $name, $path)); - } else { - $e->setTemplateName($name); - } + $e->setSourceContext(new Source('', $name, $path)); } throw $e; @@ -107,9 +102,7 @@ class TwigExtractor extends AbstractFileExtractor implements ExtractorInterface } /** - * @param string|array $directory - * - * @return array + * {@inheritdoc} */ protected function extractFromDirectory($directory) { diff --git a/vendor/symfony/twig-bridge/TwigEngine.php b/vendor/symfony/twig-bridge/TwigEngine.php index bc0a4fecc9af5151b9a38c4ba2ec3d9c4760ca1b..cfbb5d8f4e440200288d44faf504c5e1200fac73 100644 --- a/vendor/symfony/twig-bridge/TwigEngine.php +++ b/vendor/symfony/twig-bridge/TwigEngine.php @@ -19,6 +19,7 @@ use Twig\Environment; use Twig\Error\Error; use Twig\Error\LoaderError; use Twig\Loader\ExistsLoaderInterface; +use Twig\Loader\SourceContextLoaderInterface; use Twig\Template; /** @@ -44,7 +45,7 @@ class TwigEngine implements EngineInterface, StreamingEngineInterface * * @throws Error if something went wrong like a thrown exception while rendering the template */ - public function render($name, array $parameters = array()) + public function render($name, array $parameters = []) { return $this->load($name)->render($parameters); } @@ -56,7 +57,7 @@ class TwigEngine implements EngineInterface, StreamingEngineInterface * * @throws Error if something went wrong like a thrown exception while rendering the template */ - public function stream($name, array $parameters = array()) + public function stream($name, array $parameters = []) { $this->load($name)->display($parameters); } @@ -74,19 +75,24 @@ class TwigEngine implements EngineInterface, StreamingEngineInterface $loader = $this->environment->getLoader(); - if ($loader instanceof ExistsLoaderInterface || method_exists($loader, 'exists')) { - return $loader->exists((string) $name); - } + if (1 === Environment::MAJOR_VERSION && !$loader instanceof ExistsLoaderInterface) { + try { + // cast possible TemplateReferenceInterface to string because the + // EngineInterface supports them but LoaderInterface does not + if ($loader instanceof SourceContextLoaderInterface) { + $loader->getSourceContext((string) $name); + } else { + $loader->getSource((string) $name); + } + + return true; + } catch (LoaderError $e) { + } - try { - // cast possible TemplateReferenceInterface to string because the - // EngineInterface supports them but LoaderInterface does not - $loader->getSourceContext((string) $name)->getCode(); - } catch (LoaderError $e) { return false; } - return true; + return $loader->exists((string) $name); } /** diff --git a/vendor/symfony/twig-bridge/UndefinedCallableHandler.php b/vendor/symfony/twig-bridge/UndefinedCallableHandler.php index 77c78ce38f530ab9e4aa34ea6203680c8c8462a0..43cac82bcbca5c8c518703662d11aaa0a5bde984 100644 --- a/vendor/symfony/twig-bridge/UndefinedCallableHandler.php +++ b/vendor/symfony/twig-bridge/UndefinedCallableHandler.php @@ -11,6 +11,7 @@ namespace Symfony\Bridge\Twig; +use Symfony\Bundle\FullStack; use Twig\Error\SyntaxError; /** @@ -18,15 +19,15 @@ use Twig\Error\SyntaxError; */ class UndefinedCallableHandler { - private static $filterComponents = array( + private static $filterComponents = [ 'humanize' => 'form', 'trans' => 'translation', 'transchoice' => 'translation', 'yaml_encode' => 'yaml', 'yaml_dump' => 'yaml', - ); + ]; - private static $functionComponents = array( + private static $functionComponents = [ 'asset' => 'asset', 'asset_version' => 'asset', 'dump' => 'debug-bundle', @@ -53,7 +54,15 @@ class UndefinedCallableHandler 'workflow_transitions' => 'workflow', 'workflow_has_marked_place' => 'workflow', 'workflow_marked_places' => 'workflow', - ); + ]; + + private static $fullStackEnable = [ + 'form' => 'enable "framework.form"', + 'security-core' => 'add the "SecurityBundle"', + 'security-http' => 'add the "SecurityBundle"', + 'web-link' => 'enable "framework.web_link"', + 'workflow' => 'enable "framework.workflows"', + ]; public static function onUndefinedFilter($name) { @@ -61,8 +70,9 @@ class UndefinedCallableHandler return false; } - // Twig will append the source context to the message, so that it will end up being like "[...] Unknown filter "%s" in foo.html.twig on line 123." - throw new SyntaxError(sprintf('Did you forget to run "composer require symfony/%s"? Unknown filter "%s".', self::$filterComponents[$name], $name)); + self::onUndefined($name, 'filter', self::$filterComponents[$name]); + + return true; } public static function onUndefinedFunction($name) @@ -71,6 +81,17 @@ class UndefinedCallableHandler return false; } - throw new SyntaxError(sprintf('Did you forget to run "composer require symfony/%s"? Unknown function "%s".', self::$functionComponents[$name], $name)); + self::onUndefined($name, 'function', self::$functionComponents[$name]); + + return true; + } + + private static function onUndefined($name, $type, $component) + { + if (class_exists(FullStack::class) && isset(self::$fullStackEnable[$component])) { + throw new SyntaxError(sprintf('Did you forget to %s? Unknown %s "%s".', self::$fullStackEnable[$component], $type, $name)); + } + + throw new SyntaxError(sprintf('Did you forget to run "composer require symfony/%s"? Unknown %s "%s".', $component, $type, $name)); } } diff --git a/vendor/symfony/twig-bridge/composer.json b/vendor/symfony/twig-bridge/composer.json index aea0d10a67791e3e9fbf84ae699be16abf275900..f4fb1c98a4f1bb91463d923f3f473170128a2394 100644 --- a/vendor/symfony/twig-bridge/composer.json +++ b/vendor/symfony/twig-bridge/composer.json @@ -17,13 +17,14 @@ ], "require": { "php": "^5.5.9|>=7.0.8", - "twig/twig": "^1.35|^2.4.4" + "twig/twig": "^1.41|^2.10" }, "require-dev": { + "fig/link-util": "^1.0", "symfony/asset": "~2.8|~3.0|~4.0", "symfony/dependency-injection": "~2.8|~3.0|~4.0", "symfony/finder": "~2.8|~3.0|~4.0", - "symfony/form": "~3.4|~4.0", + "symfony/form": "^3.4.31|^4.3.4", "symfony/http-foundation": "^3.3.11|~4.0", "symfony/http-kernel": "~3.2|~4.0", "symfony/polyfill-intl-icu": "~1.0", @@ -31,7 +32,7 @@ "symfony/templating": "~2.8|~3.0|~4.0", "symfony/translation": "~2.8|~3.0|~4.0", "symfony/yaml": "~2.8|~3.0|~4.0", - "symfony/security": "~2.8|~3.0|~4.0", + "symfony/security": "^2.8.31|^3.3.13|~4.0", "symfony/security-acl": "~2.8|~3.0", "symfony/stopwatch": "~2.8|~3.0|~4.0", "symfony/console": "~3.4|~4.0", @@ -41,7 +42,7 @@ "symfony/workflow": "~3.3|~4.0" }, "conflict": { - "symfony/form": "<3.4", + "symfony/form": "<3.4.31|>=4.0,<4.3.4", "symfony/console": "<3.4" }, "suggest": { diff --git a/vendor/symfony/twig-bridge/phpunit.xml.dist b/vendor/symfony/twig-bridge/phpunit.xml.dist index 642b7d19d8b7039bc637cf4c380828563dc2946a..6e1ada1b3981a8eb59420a4aef7b34a15fabe364 100644 --- a/vendor/symfony/twig-bridge/phpunit.xml.dist +++ b/vendor/symfony/twig-bridge/phpunit.xml.dist @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="UTF-8"?> <phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" - xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/4.1/phpunit.xsd" + xsi:noNamespaceSchemaLocation="http://schema.phpunit.de/5.2/phpunit.xsd" backupGlobals="false" colors="true" bootstrap="vendor/autoload.php" diff --git a/vendor/twig/twig/.gitignore b/vendor/twig/twig/.gitignore index 31103621c67c483ce9313f9c2a261638daeb0b84..8a29959e2a1e0fbe848bd3e64ca51b0c601c7743 100644 --- a/vendor/twig/twig/.gitignore +++ b/vendor/twig/twig/.gitignore @@ -3,3 +3,4 @@ /ext/twig/autom4te.cache/ /phpunit.xml /vendor +.phpunit.result.cache diff --git a/vendor/twig/twig/.php_cs.dist b/vendor/twig/twig/.php_cs.dist index d249ffbe46ad5be6f874d5096468743c1a6deaea..b81882fbf2ccd84fc7ef1f338d4901dd03217a08 100644 --- a/vendor/twig/twig/.php_cs.dist +++ b/vendor/twig/twig/.php_cs.dist @@ -1,16 +1,20 @@ <?php return PhpCsFixer\Config::create() - ->setRules(array( + ->setRules([ '@Symfony' => true, '@Symfony:risky' => true, - 'array_syntax' => array('syntax' => 'long'), - 'php_unit_fqcn_annotation' => false, + '@PHPUnit75Migration:risky' => true, + 'php_unit_dedicate_assert' => ['target' => '5.6'], + 'array_syntax' => ['syntax' => 'short'], + 'php_unit_fqcn_annotation' => true, 'no_unreachable_default_argument_value' => false, - 'braces' => array('allow_single_line_closure' => true), + 'braces' => ['allow_single_line_closure' => true], 'heredoc_to_nowdoc' => false, - 'dir_constant' => false, - )) + 'ordered_imports' => true, + 'phpdoc_types_order' => ['null_adjustment' => 'always_last', 'sort_algorithm' => 'none'], + 'native_function_invocation' => ['include' => ['@compiler_optimized'], 'scope' => 'all'], + ]) ->setRiskyAllowed(true) ->setFinder(PhpCsFixer\Finder::create()->in(__DIR__)) ; diff --git a/vendor/twig/twig/.travis.yml b/vendor/twig/twig/.travis.yml index 147eb7df3f3327e6a2476ef83ca89ab39d7f89dc..ff6132b358d36d8773135c94634dc75fdc434919 100644 --- a/vendor/twig/twig/.travis.yml +++ b/vendor/twig/twig/.travis.yml @@ -1,5 +1,7 @@ language: php +dist: trusty + sudo: false cache: @@ -7,21 +9,13 @@ cache: - vendor - $HOME/.composer/cache/files -php: - - 5.3 - - 5.4 - - 5.5 - - 5.6 - - 7.0 - - 7.1 - - nightly env: - - TWIG_EXT=no - - TWIG_EXT=yes + global: + - TWIG_EXT=no + - SYMFONY_PHPUNIT_REMOVE_RETURN_TYPEHINT=1 before_install: - # turn off XDebug - phpenv config-rm xdebug.ini || return 0 install: @@ -31,19 +25,22 @@ before_script: - if [ "$TWIG_EXT" == "yes" ]; then sh -c "cd ext/twig && phpize && ./configure --enable-twig && make && make install"; fi - if [ "$TWIG_EXT" == "yes" ]; then echo "extension=twig.so" >> `php --ini | grep "Loaded Configuration" | sed -e "s|.*:\s*||"`; fi -script: | - if [[ $TRAVIS_PHP_VERSION = 7.* || $TRAVIS_PHP_VERSION = nightly ]]; then - SYMFONY_PHPUNIT_VERSION=6.1 ./vendor/bin/simple-phpunit - else - ./vendor/bin/simple-phpunit - fi +script: ./vendor/bin/simple-phpunit -matrix: +jobs: fast_finish: true - exclude: - - php: 7.0 - env: TWIG_EXT=yes - - php: 7.1 + include: + - php: 5.5 + - php: 5.5 env: TWIG_EXT=yes - - php: nightly + - php: 5.6 + - php: 5.6 env: TWIG_EXT=yes + - php: 7.0 + - php: 7.1 + - php: 7.2 + - php: 7.3 + - php: 7.4snapshot + - stage: integration tests + php: 7.3 + script: ./drupal_test.sh diff --git a/vendor/twig/twig/CHANGELOG b/vendor/twig/twig/CHANGELOG index f738c841ccd200a83d452f9c6284503f91275986..6ca3d45a1c7e389382b521f339d75cfb774a73ed 100644 --- a/vendor/twig/twig/CHANGELOG +++ b/vendor/twig/twig/CHANGELOG @@ -1,3 +1,148 @@ +* 1.42.3 (2019-08-24) + + * fixed the "split" filter when the delimiter is "0" + * fixed the "empty" test on Traversable instances + * fixed cache when opcache is installed but disabled + * fixed PHP 7.4 compatibility + * bumped the minimal PHP version to 5.5 + +* 1.42.2 (2019-06-18) + + * Display partial output (PHP buffer) when an error occurs in debug mode + +* 1.42.1 (2019-06-04) + + * added support for "Twig\Markup" instances in the "in" test (again) + * allowed string operators as variables names in assignments + +* 1.42.0 (2019-05-31) + + * fixed the "filter" filter when the argument is \Traversable but does not implement \Iterator (\SimpleXmlElement for instance) + * fixed a PHP fatal error when calling a macro imported in a block in a nested block + * fixed a PHP fatal error when calling a macro imported in the template in another macro + * fixed wrong error message on "import" and "from" + +* 1.41.0 (2019-05-14) + + * fixed support for PHP 7.4 + * added "filter", "map", and "reduce" filters (and support for arrow functions) + * fixed partial output leak when a PHP fatal error occurs + * optimized context access on PHP 7.4 + +* 1.40.1 (2019-04-29) + +* fixed regression in NodeTraverser + +* 1.40.0 (2019-04-28) + + * allowed Twig\NodeVisitor\NodeVisitorInterface::leaveNode() to return "null" instead of "false" (same meaning) + * added the "apply" tag as a replacement for the "filter" tag + * allowed Twig\Loader\FilesystemLoader::findTemplate() to return "null" instead of "false" (same meaning) + * added support for "Twig\Markup" instances in the "in" test + * fixed Lexer when using custom options containing the # char + * fixed "import" when macros are stored in a template string + +* 1.39.1 (2019-04-16) + + * fixed EscaperNodeVisitor + +* 1.39.0 (2019-04-16) + + * added Traversable support for the length filter + * fixed some wrong location in error messages + * made exception creation faster + * made escaping on ternary expressions (?: and ??) more fine-grained + * added the possibility to give a nice name to string templates (template_from_string function) + * fixed the "with" behavior to always include the globals (for consistency with the "include" and "embed" tags) + * fixed "include" with "ignore missing" when an error loading occurs in the included template + * added support for a new whitespace trimming option ({%~ ~%}, {{~ ~}}, {#~ ~#}) + +* 1.38.4 (2019-03-23) + + * fixed CheckToStringNode implementation (broken when a function/filter is variadic) + +* 1.38.3 (2019-03-21) + + * fixed the spaceless filter so that it behaves like the spaceless tag + * fixed BC break on Environment::resolveTemplate() + * fixed the bundled Autoloader to also load namespaced classes + * allowed Traversable objects to be used in the "with" tag + * allowed Traversable objects to be used in the "with" argument of the "include" and "embed" tags + +* 1.38.2 (2019-03-12) + + * added TemplateWrapper::getTemplateName() + +* 1.38.1 (2019-03-12) + + * fixed class aliases + +* 1.38.0 (2019-03-12) + + * fixed sandbox security issue (under some circumstances, calling the + __toString() method on an object was possible even if not allowed by the + security policy) + * fixed batch filter clobbers array keys when fill parameter is used + * added preserveKeys support for the batch filter + * fixed "embed" support when used from "template_from_string" + * added the possibility to pass a TemplateWrapper to Twig\Environment::load() + * improved the performance of the sandbox + * added a spaceless filter + * added max value to the "random" function + * made namespace classes the default classes (PSR-0 ones are aliases now) + * removed duplicated directory separator in FilesystemLoader + * added Twig\Loader\ChainLoader::getLoaders() + * changed internal code to use the namespaced classes as much as possible + +* 1.37.1 (2019-01-14) + + * fixed regression (key exists check for non ArrayObject objects) + * fixed logic in TemplateWrapper + +* 1.37.0 (2019-01-14) + + * fixed ArrayObject access with a null value + * fixed embedded templates starting with a BOM + * fixed using a Twig_TemplateWrapper instance as an argument to extends + * switched generated code to use the PHP short array notation + * dropped PHP 5.3 support + * fixed float representation in compiled templates + * added a second argument to the join filter (last separator configuration) + +* 1.36.0 (2018-12-16) + + * made sure twig_include returns a string + * fixed multi-byte UFT-8 in escape('html_attr') + * added the "deprecated" tag + * added support for dynamically named tests + * fixed GlobalsInterface extended class + * fixed filesystem loader throwing an exception instead of returning false + +* 1.35.4 (2018-07-13) + + * ensured that syntax errors are triggered with the right line + * added the Symfony ctype polyfill as a dependency + * "js" filter now produces valid JSON + +* 1.35.3 (2018-03-20) + + * fixed block names unicity + * fixed counting children of SimpleXMLElement objects + * added missing else clause to avoid infinite loops + * fixed .. (range operator) in sandbox policy + +* 1.35.2 (2018-03-03) + + * fixed a regression in the way the profiler is registered in templates + +* 1.35.1 (2018-03-02) + + * added an exception when using "===" instead of "same as" + * fixed possible array to string conversion concealing actual error + * made variable names deterministic in compiled templates + * fixed length filter when passing an instance of IteratorAggregate + * fixed Environment::resolveTemplate to accept instances of TemplateWrapper + * 1.35.0 (2017-09-27) * added Twig_Profiler_Profile::reset() diff --git a/vendor/twig/twig/LICENSE b/vendor/twig/twig/LICENSE index b6e17a1a6d96172bcd8e34debfe357f4dce26a1b..d06ced2a39c59b2112fb5524ddde48234fc7cee4 100644 --- a/vendor/twig/twig/LICENSE +++ b/vendor/twig/twig/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2009-2017 by the Twig Team. +Copyright (c) 2009-2019 by the Twig Team. Some rights reserved. diff --git a/vendor/twig/twig/README.rst b/vendor/twig/twig/README.rst index 81737b0b2c2b6981325e762a43518c56dc0ca3e8..d896ff500a411bb03bb66931e86e346db07f56c3 100644 --- a/vendor/twig/twig/README.rst +++ b/vendor/twig/twig/README.rst @@ -7,9 +7,18 @@ and documentation). Twig uses a syntax similar to the Django and Jinja template languages which inspired the Twig runtime environment. +Sponsors +-------- + +.. raw:: html + + <a href="https://blackfire.io/docs/introduction?utm_source=twig&utm_medium=github_readme&utm_campaign=logo"> + <img src="https://static.blackfire.io/assets/intemporals/logo/png/blackfire-io_secondary_horizontal_transparent.png?1" width="255px" alt="Blackfire.io"> + </a> + More Information ---------------- Read the `documentation`_ for more information. -.. _documentation: http://twig.sensiolabs.org/documentation +.. _documentation: https://twig.symfony.com/documentation diff --git a/vendor/twig/twig/composer.json b/vendor/twig/twig/composer.json index 09c1ea5e9f7422d6359da72b24abb5697f9bd237..9807aa7711b96176b9710723130c8d76905a4f7a 100644 --- a/vendor/twig/twig/composer.json +++ b/vendor/twig/twig/composer.json @@ -3,7 +3,7 @@ "type": "library", "description": "Twig, the flexible, fast, and secure template language for PHP", "keywords": ["templating"], - "homepage": "http://twig.sensiolabs.org", + "homepage": "https://twig.symfony.com", "license": "BSD-3-Clause", "authors": [ { @@ -14,7 +14,7 @@ }, { "name": "Twig Team", - "homepage": "http://twig.sensiolabs.org/contributors", + "homepage": "https://twig.symfony.com/contributors", "role": "Contributors" }, { @@ -23,15 +23,13 @@ "role": "Project Founder" } ], - "support": { - "forum": "https://groups.google.com/forum/#!forum/twig-users" - }, "require": { - "php": ">=5.3.3" + "php": ">=5.5.0", + "symfony/polyfill-ctype": "^1.8" }, "require-dev": { - "symfony/phpunit-bridge": "~3.3@dev", - "symfony/debug": "~2.7", + "symfony/phpunit-bridge": "^4.4@dev|^5.0", + "symfony/debug": "^3.4|^4.2", "psr/container": "^1.0" }, "autoload": { @@ -42,9 +40,14 @@ "Twig\\" : "src/" } }, + "autoload-dev": { + "psr-4" : { + "Twig\\Tests\\" : "tests" + } + }, "extra": { "branch-alias": { - "dev-master": "1.35-dev" + "dev-master": "1.42-dev" } } } diff --git a/vendor/twig/twig/doc/advanced.rst b/vendor/twig/twig/doc/advanced.rst index d86db501e52514bc6e5892b4fb79063ec376043e..e253294191dab84c3c46424ca816f970f62a6ddf 100644 --- a/vendor/twig/twig/doc/advanced.rst +++ b/vendor/twig/twig/doc/advanced.rst @@ -13,10 +13,10 @@ itself with node visitors. .. note:: - The first section of this chapter describes how to extend Twig easily. If - you want to reuse your changes in different projects or if you want to - share them with others, you should then create an extension as described - in the following section. + The first section of this chapter describes how to extend Twig. If you want + to reuse your changes in different projects or if you want to share them + with others, you should then create an extension as described in the + following section. .. caution:: @@ -40,7 +40,7 @@ generate). You can use a ``lipsum`` *tag*: -.. code-block:: jinja +.. code-block:: twig {% lipsum 40 %} @@ -51,43 +51,42 @@ three main reasons: * The tag outputs something; * The tag is not flexible as you cannot use it in an expression: - .. code-block:: jinja + .. code-block:: twig {{ 'some text' ~ {% lipsum 40 %} ~ 'some more text' }} In fact, you rarely need to create tags; and that's good news because tags are -the most complex extension point of Twig. +the most complex extension point. Now, let's use a ``lipsum`` *filter*: -.. code-block:: jinja +.. code-block:: twig {{ 40|lipsum }} -Again, it works, but it looks weird. A filter transforms the passed value to -something else but here we use the value to indicate the number of words to -generate (so, ``40`` is an argument of the filter, not the value we want to -transform). +Again, it works. But a filter should transform the passed value to something +else. Here, we use the value to indicate the number of words to generate (so, +``40`` is an argument of the filter, not the value we want to transform). Next, let's use a ``lipsum`` *function*: -.. code-block:: jinja +.. code-block:: twig {{ lipsum(40) }} Here we go. For this specific example, the creation of a function is the extension point to use. And you can use it anywhere an expression is accepted: -.. code-block:: jinja +.. code-block:: twig {{ 'some text' ~ lipsum(40) ~ 'some more text' }} {% set lipsum = lipsum(40) %} -Last but not the least, you can also use a *global* object with a method able -to generate lorem ipsum text: +Lastly, you can also use a *global* object with a method able to generate lorem +ipsum text: -.. code-block:: jinja +.. code-block:: twig {{ text.lipsum(40) }} @@ -99,13 +98,13 @@ Keep in mind the following when you want to extend Twig: ========== ========================== ========== ========================= What? Implementation difficulty? How often? When? ========== ========================== ========== ========================= -*macro* trivial frequent Content generation -*global* trivial frequent Helper object -*function* trivial frequent Content generation -*filter* trivial frequent Value transformation +*macro* simple frequent Content generation +*global* simple frequent Helper object +*function* simple frequent Content generation +*filter* simple frequent Value transformation *tag* complex rare DSL language construct -*test* trivial rare Boolean decision -*operator* trivial rare Values transformation +*test* simple rare Boolean decision +*operator* simple rare Values transformation ========== ========================== ========== ========================= Globals @@ -114,49 +113,49 @@ Globals A global variable is like any other template variable, except that it's available in all templates and macros:: - $twig = new Twig_Environment($loader); + $twig = new \Twig\Environment($loader); $twig->addGlobal('text', new Text()); You can then use the ``text`` variable anywhere in a template: -.. code-block:: jinja +.. code-block:: twig {{ text.lipsum(40) }} Filters ------- -Creating a filter is as simple as associating a name with a PHP callable:: +Creating a filter consists of associating a name with a PHP callable:: // an anonymous function - $filter = new Twig_SimpleFilter('rot13', function ($string) { + $filter = new \Twig\TwigFilter('rot13', function ($string) { return str_rot13($string); }); // or a simple PHP function - $filter = new Twig_SimpleFilter('rot13', 'str_rot13'); + $filter = new \Twig\TwigFilter('rot13', 'str_rot13'); // or a class static method - $filter = new Twig_SimpleFilter('rot13', array('SomeClass', 'rot13Filter')); - $filter = new Twig_SimpleFilter('rot13', 'SomeClass::rot13Filter'); + $filter = new \Twig\TwigFilter('rot13', ['SomeClass', 'rot13Filter']); + $filter = new \Twig\TwigFilter('rot13', 'SomeClass::rot13Filter'); // or a class method - $filter = new Twig_SimpleFilter('rot13', array($this, 'rot13Filter')); + $filter = new \Twig\TwigFilter('rot13', [$this, 'rot13Filter']); // the one below needs a runtime implementation (see below for more information) - $filter = new Twig_SimpleFilter('rot13', array('SomeClass', 'rot13Filter')); + $filter = new \Twig\TwigFilter('rot13', ['SomeClass', 'rot13Filter']); -The first argument passed to the ``Twig_SimpleFilter`` constructor is the name +The first argument passed to the ``\Twig\TwigFilter`` constructor is the name of the filter you will use in templates and the second one is the PHP callable to associate with it. -Then, add the filter to your Twig environment:: +Then, add the filter to the Twig environment:: - $twig = new Twig_Environment($loader); + $twig = new \Twig\Environment($loader); $twig->addFilter($filter); And here is how to use it in a template: -.. code-block:: jinja +.. code-block:: twig {{ 'Twig'|rot13 }} @@ -168,7 +167,7 @@ to the filter (within parentheses ``()``) as extra arguments. For instance, the following code: -.. code-block:: jinja +.. code-block:: twig {{ 'TWIG'|lower }} {{ now|date('d/m/Y') }} @@ -178,10 +177,10 @@ is compiled to something like the following:: <?php echo strtolower('TWIG') ?> <?php echo twig_date_format_filter($now, 'd/m/Y') ?> -The ``Twig_SimpleFilter`` class takes an array of options as its last +The ``\Twig\TwigFilter`` class takes an array of options as its last argument:: - $filter = new Twig_SimpleFilter('rot13', 'str_rot13', $options); + $filter = new \Twig\TwigFilter('rot13', 'str_rot13', $options); Environment-aware Filters ~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -190,12 +189,12 @@ If you want to access the current environment instance in your filter, set the ``needs_environment`` option to ``true``; Twig will pass the current environment as the first argument to the filter call:: - $filter = new Twig_SimpleFilter('rot13', function (Twig_Environment $env, $string) { + $filter = new \Twig\TwigFilter('rot13', function (Twig_Environment $env, $string) { // get the current charset for instance $charset = $env->getCharset(); return str_rot13($string); - }, array('needs_environment' => true)); + }, ['needs_environment' => true]); Context-aware Filters ~~~~~~~~~~~~~~~~~~~~~ @@ -205,13 +204,13 @@ If you want to access the current context in your filter, set the the first argument to the filter call (or the second one if ``needs_environment`` is also set to ``true``):: - $filter = new Twig_SimpleFilter('rot13', function ($context, $string) { + $filter = new \Twig\TwigFilter('rot13', function ($context, $string) { // ... - }, array('needs_context' => true)); + }, ['needs_context' => true]); - $filter = new Twig_SimpleFilter('rot13', function (Twig_Environment $env, $context, $string) { + $filter = new \Twig\TwigFilter('rot13', function (Twig_Environment $env, $context, $string) { // ... - }, array('needs_context' => true, 'needs_environment' => true)); + }, ['needs_context' => true, 'needs_environment' => true]); Automatic Escaping ~~~~~~~~~~~~~~~~~~ @@ -221,14 +220,14 @@ before printing. If your filter acts as an escaper (or explicitly outputs HTML or JavaScript code), you will want the raw output to be printed. In such a case, set the ``is_safe`` option:: - $filter = new Twig_SimpleFilter('nl2br', 'nl2br', array('is_safe' => array('html'))); + $filter = new \Twig\TwigFilter('nl2br', 'nl2br', ['is_safe' => ['html']]); Some filters may need to work on input that is already escaped or safe, for example when adding (safe) HTML tags to originally unsafe output. In such a case, set the ``pre_escape`` option to escape the input data before it is run through your filter:: - $filter = new Twig_SimpleFilter('somefilter', 'somefilter', array('pre_escape' => 'html', 'is_safe' => array('html'))); + $filter = new \Twig\TwigFilter('somefilter', 'somefilter', ['pre_escape' => 'html', 'is_safe' => ['html']]); Variadic Filters ~~~~~~~~~~~~~~~~ @@ -240,38 +239,39 @@ When a filter should accept an arbitrary number of arguments, set the ``is_variadic`` option to ``true``; Twig will pass the extra arguments as the last argument to the filter call as an array:: - $filter = new Twig_SimpleFilter('thumbnail', function ($file, array $options = array()) { + $filter = new \Twig\TwigFilter('thumbnail', function ($file, array $options = []) { // ... - }, array('is_variadic' => true)); + }, ['is_variadic' => true]); -Be warned that named arguments passed to a variadic filter cannot be checked -for validity as they will automatically end up in the option array. +Be warned that :ref:`named arguments <named-arguments>` passed to a variadic +filter cannot be checked for validity as they will automatically end up in the +option array. Dynamic Filters ~~~~~~~~~~~~~~~ -A filter name containing the special ``*`` character is a dynamic filter as -the ``*`` can be any string:: +A filter name containing the special ``*`` character is a dynamic filter and +the ``*`` part will match any string:: - $filter = new Twig_SimpleFilter('*_path', function ($name, $arguments) { + $filter = new \Twig\TwigFilter('*_path', function ($name, $arguments) { // ... }); -The following filters will be matched by the above defined dynamic filter: +The following filters are matched by the above defined dynamic filter: * ``product_path`` * ``category_path`` A dynamic filter can define more than one dynamic parts:: - $filter = new Twig_SimpleFilter('*_path_*', function ($name, $suffix, $arguments) { + $filter = new \Twig\TwigFilter('*_path_*', function ($name, $suffix, $arguments) { // ... }); -The filter will receive all dynamic part values before the normal filter -arguments, but after the environment and the context. For instance, a call to -``'foo'|a_path_b()`` will result in the following arguments to be passed to -the filter: ``('a', 'b', 'foo')``. +The filter receives all dynamic part values before the normal filter arguments, +but after the environment and the context. For instance, a call to +``'foo'|a_path_b()`` will result in the following arguments to be passed to the +filter: ``('a', 'b', 'foo')``. Deprecated Filters ~~~~~~~~~~~~~~~~~~ @@ -283,9 +283,9 @@ You can mark a filter as being deprecated by setting the ``deprecated`` option to ``true``. You can also give an alternative filter that replaces the deprecated one when that makes sense:: - $filter = new Twig_SimpleFilter('obsolete', function () { + $filter = new \Twig\TwigFilter('obsolete', function () { // ... - }, array('deprecated' => true, 'alternative' => 'new_one')); + }, ['deprecated' => true, 'alternative' => 'new_one']); When a filter is deprecated, Twig emits a deprecation notice when compiling a template using it. See :ref:`deprecation-notices` for more information. @@ -294,10 +294,10 @@ Functions --------- Functions are defined in the exact same way as filters, but you need to create -an instance of ``Twig_SimpleFunction``:: +an instance of ``\Twig\TwigFunction``:: - $twig = new Twig_Environment($loader); - $function = new Twig_SimpleFunction('function_name', function () { + $twig = new \Twig\Environment($loader); + $function = new \Twig\TwigFunction('function_name', function () { // ... }); $twig->addFunction($function); @@ -309,10 +309,10 @@ Tests ----- Tests are defined in the exact same way as filters and functions, but you need -to create an instance of ``Twig_SimpleTest``:: +to create an instance of ``\Twig\TwigTest``:: - $twig = new Twig_Environment($loader); - $test = new Twig_SimpleTest('test_name', function () { + $twig = new \Twig\Environment($loader); + $test = new \Twig\TwigTest('test_name', function () { // ... }); $twig->addTest($test); @@ -321,8 +321,8 @@ Tests allow you to create custom application specific logic for evaluating boolean conditions. As a simple example, let's create a Twig test that checks if objects are 'red':: - $twig = new Twig_Environment($loader); - $test = new Twig_SimpleTest('red', function ($value) { + $twig = new \Twig\Environment($loader); + $test = new \Twig\TwigTest('red', function ($value) { if (isset($value->color) && $value->color == 'red') { return true; } @@ -333,22 +333,22 @@ objects are 'red':: }); $twig->addTest($test); -Test functions should always return true/false. +Test functions must always return ``true``/``false``. When creating tests you can use the ``node_class`` option to provide custom test compilation. This is useful if your test can be compiled into PHP primitives. This is used by many of the tests built into Twig:: - $twig = new Twig_Environment($loader); - $test = new Twig_SimpleTest( + $twig = new \Twig\Environment($loader); + $test = new \Twig\TwigTest( 'odd', null, - array('node_class' => 'Twig_Node_Expression_Test_Odd')); + ['node_class' => '\Twig\Node\Expression\Test\OddTest']); $twig->addTest($test); - class Twig_Node_Expression_Test_Odd extends Twig_Node_Expression_Test + class Twig_Node_Expression_Test_Odd extends \Twig\Node\Expression\TestExpression { - public function compile(Twig_Compiler $compiler) + public function compile(\Twig\Compiler $compiler) { $compiler ->raw('(') @@ -359,11 +359,11 @@ This is used by many of the tests built into Twig:: } } -The above example shows how you can create tests that use a node class. The -node class has access to one sub-node called 'node'. This sub-node contains the +The above example shows how you can create tests that use a node class. The node +class has access to one sub-node called ``node``. This sub-node contains the value that is being tested. When the ``odd`` filter is used in code such as: -.. code-block:: jinja +.. code-block:: twig {% if my_value is odd %} @@ -371,21 +371,67 @@ The ``node`` sub-node will contain an expression of ``my_value``. Node-based tests also have access to the ``arguments`` node. This node will contain the various other arguments that have been provided to your test. +.. versionadded:: 1.36 + Dynamic tests support was added in Twig 1.36. + If you want to pass a variable number of positional or named arguments to the -test, set the ``is_variadic`` option to ``true``. Tests also support dynamic -name feature as filters and functions. +test, set the ``is_variadic`` option to ``true``. Tests support dynamic +names (see dynamic filters for the syntax). Tags ---- One of the most exciting features of a template engine like Twig is the -possibility to define new language constructs. This is also the most complex +possibility to define new **language constructs**. This is also the most complex feature as you need to understand how Twig's internals work. -Let's create a simple ``set`` tag that allows the definition of simple -variables from within a template. The tag can be used like follows: +Most of the time though, a tag is not needed: + +* If your tag generates some output, use a **function** instead. + +* If your tag modifies some content and returns it, use a **filter** instead. + + For instance, if you want to create a tag that converts a Markdown formatted + text to HTML, create a ``markdown`` filter instead: + + .. code-block:: twig + + {{ '**markdown** text'|markdown }} + + If you want use this filter on large amounts of text, wrap it with the + :doc:`apply <tags/apply>` tag: + + .. code-block:: twig + + {% apply markdown %} + Title + ===== + + Much better than creating a tag as you can **compose** filters. + {% endapply %} + + .. note:: + + The ``apply`` tag was introduced in Twig 1.40; use the ``filter`` tag with + previous versions. + +* If your tag does not output anything, but only exists because of a side + effect, create a **function** that returns nothing and call it via the + :doc:`filter <tags/do>` tag. + + For instance, if you want to create a tag that logs text, create a ``log`` + function instead and call it via the :doc:`do <tags/do>` tag: + + .. code-block:: twig + + {% do log('Log some things') %} + +If you still want to create a tag for a new language construct, great! + +Let's create a ``set`` tag that allows the definition of simple variables from +within a template. The tag can be used like follows: -.. code-block:: jinja +.. code-block:: twig {% set name = "value" %} @@ -397,8 +443,7 @@ variables from within a template. The tag can be used like follows: The ``set`` tag is part of the Core extension and as such is always available. The built-in version is slightly more powerful and supports - multiple assignments by default (cf. the template designers chapter for - more information). + multiple assignments by default. Three steps are needed to define a new tag: @@ -411,10 +456,10 @@ Three steps are needed to define a new tag: Registering a new tag ~~~~~~~~~~~~~~~~~~~~~ -Adding a tag is as simple as calling the ``addTokenParser`` method on the -``Twig_Environment`` instance:: +Add a tag by calling the ``addTokenParser`` method on the ``\Twig\Environment`` +instance:: - $twig = new Twig_Environment($loader); + $twig = new \Twig\Environment($loader); $twig->addTokenParser(new Project_Set_TokenParser()); Defining a Token Parser @@ -422,17 +467,17 @@ Defining a Token Parser Now, let's see the actual code of this class:: - class Project_Set_TokenParser extends Twig_TokenParser + class Project_Set_TokenParser extends \Twig\TokenParser\AbstractTokenParser { - public function parse(Twig_Token $token) + public function parse(\Twig\Token $token) { $parser = $this->parser; $stream = $parser->getStream(); - $name = $stream->expect(Twig_Token::NAME_TYPE)->getValue(); - $stream->expect(Twig_Token::OPERATOR_TYPE, '='); + $name = $stream->expect(\Twig\Token::NAME_TYPE)->getValue(); + $stream->expect(\Twig\Token::OPERATOR_TYPE, '='); $value = $parser->getExpressionParser()->parseExpression(); - $stream->expect(Twig_Token::BLOCK_END_TYPE); + $stream->expect(\Twig\Token::BLOCK_END_TYPE); return new Project_Set_Node($name, $value, $token->getLine(), $this->getTag()); } @@ -446,7 +491,7 @@ Now, let's see the actual code of this class:: The ``getTag()`` method must return the tag we want to parse, here ``set``. The ``parse()`` method is invoked whenever the parser encounters a ``set`` -tag. It should return a ``Twig_Node`` instance that represents the node (the +tag. It should return a ``\Twig\Node\Node`` instance that represents the node (the ``Project_Set_Node`` calls creating is explained in the next section). The parsing process is simplified thanks to a bunch of methods you can call @@ -477,16 +522,16 @@ the ``set`` tag. Defining a Node ~~~~~~~~~~~~~~~ -The ``Project_Set_Node`` class itself is rather simple:: +The ``Project_Set_Node`` class itself is quite short:: - class Project_Set_Node extends Twig_Node + class Project_Set_Node extends \Twig\Node\Node { - public function __construct($name, Twig_Node_Expression $value, $line, $tag = null) + public function __construct($name, \Twig\Node\Expression\AbstractExpression $value, $line, $tag = null) { - parent::__construct(array('value' => $value), array('name' => $name), $line, $tag); + parent::__construct(['value' => $value], ['name' => $name], $line, $tag); } - public function compile(Twig_Compiler $compiler) + public function compile(\Twig\Compiler $compiler) { $compiler ->addDebugInfo($this) @@ -510,15 +555,15 @@ developer generate beautiful and readable PHP code: * ``string()``: Writes a quoted string. * ``repr()``: Writes a PHP representation of a given value (see - ``Twig_Node_For`` for a usage example). + ``\Twig\Node\ForNode`` for a usage example). * ``addDebugInfo()``: Adds the line of the original template file related to the current node as a comment. -* ``indent()``: Indents the generated code (see ``Twig_Node_Block`` for a +* ``indent()``: Indents the generated code (see ``\Twig\Node\BlockNode`` for a usage example). -* ``outdent()``: Outdents the generated code (see ``Twig_Node_Block`` for a +* ``outdent()``: Outdents the generated code (see ``\Twig\Node\BlockNode`` for a usage example). .. _creating_extensions: @@ -528,8 +573,7 @@ Creating an Extension The main motivation for writing an extension is to move often used code into a reusable class like adding support for internationalization. An extension can -define tags, filters, tests, operators, global variables, functions, and node -visitors. +define tags, filters, tests, operators, functions, and node visitors. Most of the time, it is useful to create a single extension for your project, to host all the specific tags and filters you want to add to Twig. @@ -543,7 +587,7 @@ to host all the specific tags and filters you want to add to Twig. .. note:: Before writing your own extensions, have a look at the Twig official - extension repository: http://github.com/twigphp/Twig-extensions. + extension repository: https://github.com/twigphp/Twig-extensions. An extension is a class that implements the following interface:: @@ -554,9 +598,9 @@ An extension is a class that implements the following interface:: * * This is where you can load some file that contains filter functions for instance. * - * @deprecated since 1.23 (to be removed in 2.0), implement Twig_Extension_InitRuntimeInterface instead + * @deprecated since 1.23 (to be removed in 2.0), implement \Twig\Extension\InitRuntimeInterface instead */ - function initRuntime(Twig_Environment $environment); + function initRuntime(\Twig\Environment $environment); /** * Returns the token parser instances to add to the existing list. @@ -568,28 +612,28 @@ An extension is a class that implements the following interface:: /** * Returns the node visitor instances to add to the existing list. * - * @return Twig_NodeVisitorInterface[] + * @return \Twig\NodeVisitor\NodeVisitorInterface[] */ function getNodeVisitors(); /** * Returns a list of filters to add to the existing list. * - * @return Twig_SimpleFilter[] + * @return \Twig\TwigFilter[] */ function getFilters(); /** * Returns a list of tests to add to the existing list. * - * @return Twig_SimpleTest[] + * @return \Twig\TwigTest[] */ function getTests(); /** * Returns a list of functions to add to the existing list. * - * @return Twig_SimpleFunction[] + * @return \Twig\TwigFunction[] */ function getFunctions(); @@ -605,7 +649,7 @@ An extension is a class that implements the following interface:: * * @return array An array of global variables * - * @deprecated since 1.23 (to be removed in 2.0), implement Twig_Extension_GlobalsInterface instead + * @deprecated since 1.23 (to be removed in 2.0), implement \Twig\Extension\GlobalsInterface instead */ function getGlobals(); @@ -620,28 +664,27 @@ An extension is a class that implements the following interface:: } To keep your extension class clean and lean, inherit from the built-in -``Twig_Extension`` class instead of implementing the interface as it provides +``\Twig\Extension\AbstractExtension`` class instead of implementing the interface as it provides empty implementations for all methods: - class Project_Twig_Extension extends Twig_Extension + class Project_Twig_Extension extends \Twig\Extension\AbstractExtension { } -Of course, this extension does nothing for now. We will customize it in the -next sections. +This extension does nothing for now. We will customize it in the next sections. .. note:: Prior to Twig 1.26, you must implement the ``getName()`` method which must return a unique identifier for the extension. -Twig does not care where you save your extension on the filesystem, as all -extensions must be registered explicitly to be available in your templates. +You can save your extension anywhere on the filesystem, as all extensions must +be registered explicitly to be available in your templates. You can register an extension by using the ``addExtension()`` method on your main ``Environment`` object:: - $twig = new Twig_Environment($loader); + $twig = new \Twig\Environment($loader); $twig->addExtension(new Project_Twig_Extension()); .. tip:: @@ -654,13 +697,13 @@ Globals Global variables can be registered in an extension via the ``getGlobals()`` method:: - class Project_Twig_Extension extends Twig_Extension implements Twig_Extension_GlobalsInterface + class Project_Twig_Extension extends \Twig\Extension\AbstractExtension implements \Twig\Extension\GlobalsInterface { public function getGlobals() { - return array( + return [ 'text' => new Text(), - ); + ]; } // ... @@ -672,13 +715,13 @@ Functions Functions can be registered in an extension via the ``getFunctions()`` method:: - class Project_Twig_Extension extends Twig_Extension + class Project_Twig_Extension extends \Twig\Extension\AbstractExtension { public function getFunctions() { - return array( - new Twig_SimpleFunction('lipsum', 'generate_lipsum'), - ); + return [ + new \Twig\TwigFunction('lipsum', 'generate_lipsum'), + ]; } // ... @@ -691,13 +734,13 @@ To add a filter to an extension, you need to override the ``getFilters()`` method. This method must return an array of filters to add to the Twig environment:: - class Project_Twig_Extension extends Twig_Extension + class Project_Twig_Extension extends \Twig\Extension\AbstractExtension { public function getFilters() { - return array( - new Twig_SimpleFilter('rot13', 'str_rot13'), - ); + return [ + new \Twig\TwigFilter('rot13', 'str_rot13'), + ]; } // ... @@ -710,11 +753,11 @@ Adding a tag in an extension can be done by overriding the ``getTokenParsers()`` method. This method must return an array of tags to add to the Twig environment:: - class Project_Twig_Extension extends Twig_Extension + class Project_Twig_Extension extends \Twig\Extension\AbstractExtension { public function getTokenParsers() { - return array(new Project_Set_TokenParser()); + return [new Project_Set_TokenParser()]; } // ... @@ -728,21 +771,21 @@ Operators ~~~~~~~~~ The ``getOperators()`` methods lets you add new operators. Here is how to add -``!``, ``||``, and ``&&`` operators:: +the ``!``, ``||``, and ``&&`` operators:: - class Project_Twig_Extension extends Twig_Extension + class Project_Twig_Extension extends \Twig\Extension\AbstractExtension { public function getOperators() { - return array( - array( - '!' => array('precedence' => 50, 'class' => 'Twig_Node_Expression_Unary_Not'), - ), - array( - '||' => array('precedence' => 10, 'class' => 'Twig_Node_Expression_Binary_Or', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT), - '&&' => array('precedence' => 15, 'class' => 'Twig_Node_Expression_Binary_And', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT), - ), - ); + return [ + [ + '!' => ['precedence' => 50, 'class' => '\Twig\Node\Expression\Unary\NotUnary'], + ], + [ + '||' => ['precedence' => 10, 'class' => '\Twig\Node\Expression\Binary\OrBinary', 'associativity' => \Twig\ExpressionParser::OPERATOR_LEFT], + '&&' => ['precedence' => 15, 'class' => '\Twig\Node\Expression\Binary\AndBinary', 'associativity' => \Twig\ExpressionParser::OPERATOR_LEFT], + ], + ]; } // ... @@ -753,13 +796,13 @@ Tests The ``getTests()`` method lets you add new test functions:: - class Project_Twig_Extension extends Twig_Extension + class Project_Twig_Extension extends \Twig\Extension\AbstractExtension { public function getTests() { - return array( - new Twig_SimpleTest('even', 'twig_test_even'), - ); + return [ + new \Twig\TwigTest('even', 'twig_test_even'), + ]; } // ... @@ -782,7 +825,7 @@ any valid PHP callable: The simplest way to use methods is to define them on the extension itself:: - class Project_Twig_Extension extends Twig_Extension + class Project_Twig_Extension extends \Twig\Extension\AbstractExtension { private $rot13Provider; @@ -793,14 +836,14 @@ The simplest way to use methods is to define them on the extension itself:: public function getFunctions() { - return array( - new Twig_SimpleFunction('rot13', array($this, 'rot13')), - ); + return [ + new \Twig\TwigFunction('rot13', [$this, 'rot13']), + ]; } public function rot13($value) { - return $rot13Provider->rot13($value); + return $this->rot13Provider->rot13($value); } } @@ -808,12 +851,12 @@ This is very convenient but not recommended as it makes template compilation depend on runtime dependencies even if they are not needed (think for instance as a dependency that connects to a database engine). -As of Twig 1.26, you can easily decouple the extension definitions from their -runtime implementations by registering a ``Twig_RuntimeLoaderInterface`` +As of Twig 1.26, you can decouple the extension definitions from their +runtime implementations by registering a ``\Twig\RuntimeLoader\RuntimeLoaderInterface`` instance on the environment that knows how to instantiate such runtime classes (runtime classes must be autoload-able):: - class RuntimeLoader implements Twig_RuntimeLoaderInterface + class RuntimeLoader implements \Twig\RuntimeLoader\RuntimeLoaderInterface { public function load($class) { @@ -833,7 +876,7 @@ instance on the environment that knows how to instantiate such runtime classes .. note:: As of Twig 1.32, Twig comes with a PSR-11 compatible runtime loader - (``Twig_ContainerRuntimeLoader``) that works on PHP 5.3+. + (``\Twig\RuntimeLoader\ContainerRuntimeLoader``). It is now possible to move the runtime logic to a new ``Project_Twig_RuntimeExtension`` class and use it directly in the extension:: @@ -849,73 +892,30 @@ It is now possible to move the runtime logic to a new public function rot13($value) { - return $rot13Provider->rot13($value); + return $this->rot13Provider->rot13($value); } } - class Project_Twig_Extension extends Twig_Extension + class Project_Twig_Extension extends \Twig\Extension\AbstractExtension { public function getFunctions() { - return array( - new Twig_SimpleFunction('rot13', array('Project_Twig_RuntimeExtension', 'rot13')), + return [ + new \Twig\TwigFunction('rot13', ['Project_Twig_RuntimeExtension', 'rot13']), // or - new Twig_SimpleFunction('rot13', 'Project_Twig_RuntimeExtension::rot13'), - ); + new \Twig\TwigFunction('rot13', 'Project_Twig_RuntimeExtension::rot13'), + ]; } } -Overloading ------------ - -To overload an already defined filter, test, operator, global variable, or -function, re-define it in an extension and register it **as late as -possible** (order matters):: - - class MyCoreExtension extends Twig_Extension - { - public function getFilters() - { - return array( - new Twig_SimpleFilter('date', array($this, 'dateFilter')), - ); - } - - public function dateFilter($timestamp, $format = 'F j, Y H:i') - { - // do something different from the built-in date filter - } - } - - $twig = new Twig_Environment($loader); - $twig->addExtension(new MyCoreExtension()); - -Here, we have overloaded the built-in ``date`` filter with a custom one. - -If you do the same on the ``Twig_Environment`` itself, beware that it takes -precedence over any other registered extensions:: - - $twig = new Twig_Environment($loader); - $twig->addFilter(new Twig_SimpleFilter('date', function ($timestamp, $format = 'F j, Y H:i') { - // do something different from the built-in date filter - })); - // the date filter will come from the above registration, not - // from the registered extension below - $twig->addExtension(new MyCoreExtension()); - -.. caution:: - - Note that overloading the built-in Twig elements is not recommended as it - might be confusing. - Testing an Extension -------------------- Functional Tests ~~~~~~~~~~~~~~~~ -You can create functional tests for extensions simply by creating the -following file structure in your test directory:: +You can create functional tests for extensions by creating the following file +structure in your test directory:: Fixtures/ filters/ @@ -931,19 +931,19 @@ following file structure in your test directory:: The ``IntegrationTest.php`` file should look like this:: - class Project_Tests_IntegrationTest extends Twig_Test_IntegrationTestCase + class Project_Tests_IntegrationTest extends \Twig\Test\IntegrationTestCase { public function getExtensions() { - return array( + return [ new Project_Twig_Extension1(), new Project_Twig_Extension2(), - ); + ]; } public function getFixturesDir() { - return dirname(__FILE__).'/Fixtures/'; + return __DIR__.'/Fixtures/'; } } @@ -954,9 +954,9 @@ Node Tests ~~~~~~~~~~ Testing the node visitors can be complex, so extend your test cases from -``Twig_Test_NodeTestCase``. Examples can be found in the Twig repository +``\Twig\Test\NodeTestCase``. Examples can be found in the Twig repository `tests/Twig/Node`_ directory. -.. _`rot13`: http://www.php.net/manual/en/function.str-rot13.php -.. _`tests/Twig/Fixtures`: https://github.com/twigphp/Twig/tree/master/test/Twig/Tests/Fixtures -.. _`tests/Twig/Node`: https://github.com/twigphp/Twig/tree/master/test/Twig/Tests/Node +.. _`rot13`: https://secure.php.net/manual/en/function.str-rot13.php +.. _`tests/Twig/Fixtures`: https://github.com/twigphp/Twig/tree/1.x/tests/Fixtures +.. _`tests/Twig/Node`: https://github.com/twigphp/Twig/tree/1.x/tests/Node diff --git a/vendor/twig/twig/doc/advanced_legacy.rst b/vendor/twig/twig/doc/advanced_legacy.rst index 33e9f45a4cc3f12bf470dc6c1abf1520b0342394..cc87b9c9e8435ad170c6034d82dfee934ef46f8c 100644 --- a/vendor/twig/twig/doc/advanced_legacy.rst +++ b/vendor/twig/twig/doc/advanced_legacy.rst @@ -13,7 +13,7 @@ itself with node visitors. .. note:: - The first section of this chapter describes how to extend Twig easily. If + The first section of this chapter describes how to extend Twig. If you want to reuse your changes in different projects or if you want to share them with others, you should then create an extension as described in the following section. @@ -41,7 +41,7 @@ generate). You can use a ``lipsum`` *tag*: -.. code-block:: jinja +.. code-block:: twig {% lipsum 40 %} @@ -52,7 +52,7 @@ three main reasons: * The tag outputs something; * The tag is not flexible as you cannot use it in an expression: - .. code-block:: jinja + .. code-block:: twig {{ 'some text' ~ {% lipsum 40 %} ~ 'some more text' }} @@ -61,7 +61,7 @@ the most complex extension point of Twig. Now, let's use a ``lipsum`` *filter*: -.. code-block:: jinja +.. code-block:: twig {{ 40|lipsum }} @@ -72,14 +72,14 @@ transform). Next, let's use a ``lipsum`` *function*: -.. code-block:: jinja +.. code-block:: twig {{ lipsum(40) }} Here we go. For this specific example, the creation of a function is the extension point to use. And you can use it anywhere an expression is accepted: -.. code-block:: jinja +.. code-block:: twig {{ 'some text' ~ ipsum(40) ~ 'some more text' }} @@ -88,7 +88,7 @@ extension point to use. And you can use it anywhere an expression is accepted: Last but not the least, you can also use a *global* object with a method able to generate lorem ipsum text: -.. code-block:: jinja +.. code-block:: twig {{ text.lipsum(40) }} @@ -115,12 +115,12 @@ Globals A global variable is like any other template variable, except that it's available in all templates and macros:: - $twig = new Twig_Environment($loader); + $twig = new \Twig\Environment($loader); $twig->addGlobal('text', new Text()); You can then use the ``text`` variable anywhere in a template: -.. code-block:: jinja +.. code-block:: twig {{ text.lipsum(40) }} @@ -134,13 +134,13 @@ arguments passed to the filter (within parentheses ``()``) as extra arguments. Defining a filter is as easy as associating the filter name with a PHP callable. For instance, let's say you have the following code in a template: -.. code-block:: jinja +.. code-block:: twig {{ 'TWIG'|lower }} When compiling this template to PHP, Twig looks for the PHP callable associated with the ``lower`` filter. The ``lower`` filter is a built-in Twig -filter, and it is simply mapped to the PHP ``strtolower()`` function. After +filter, and it is mapped directly to the PHP ``strtolower()`` function. After compilation, the generated PHP code is roughly equivalent to: .. code-block:: html+php @@ -152,7 +152,7 @@ function. A filter can also take extra arguments like in the following example: -.. code-block:: jinja +.. code-block:: twig {{ now|date('d/m/Y') }} @@ -169,16 +169,16 @@ In this section, we will create a ``rot13`` filter, which should return the `rot13`_ transformation of a string. Here is an example of its usage and the expected output: -.. code-block:: jinja +.. code-block:: twig {{ "Twig"|rot13 }} {# should displays Gjvt #} Adding a filter is as simple as calling the ``addFilter()`` method on the -``Twig_Environment`` instance:: +``\Twig\Environment`` instance:: - $twig = new Twig_Environment($loader); + $twig = new \Twig\Environment($loader); $twig->addFilter('rot13', new Twig_Filter_Function('str_rot13')); The second argument of ``addFilter()`` is an instance of ``Twig_Filter``. @@ -188,7 +188,7 @@ of the PHP function to call, here ``str_rot13``, a native PHP function. Let's say I now want to be able to add a prefix before the converted string: -.. code-block:: jinja +.. code-block:: twig {{ "Twig"|rot13('prefix_') }} @@ -227,12 +227,12 @@ The ``Twig_Filter`` classes take options as their last argument. For instance, if you want access to the current environment instance in your filter, set the ``needs_environment`` option to ``true``:: - $filter = new Twig_Filter_Function('str_rot13', array('needs_environment' => true)); + $filter = new Twig_Filter_Function('str_rot13', ['needs_environment' => true]); Twig will then pass the current environment as the first argument to the filter call:: - function twig_compute_rot13(Twig_Environment $env, $string) + function twig_compute_rot13(\Twig\Environment $env, $string) { // get the current charset for instance $charset = $env->getCharset(); @@ -248,14 +248,14 @@ before printing. If your filter acts as an escaper (or explicitly outputs HTML or JavaScript code), you will want the raw output to be printed. In such a case, set the ``is_safe`` option:: - $filter = new Twig_Filter_Function('nl2br', array('is_safe' => array('html'))); + $filter = new Twig_Filter_Function('nl2br', ['is_safe' => ['html']]); Some filters may need to work on input that is already escaped or safe, for example when adding (safe) HTML tags to originally unsafe output. In such a case, set the ``pre_escape`` option to escape the input data before it is run through your filter:: - $filter = new Twig_Filter_Function('somefilter', array('pre_escape' => 'html', 'is_safe' => array('html'))); + $filter = new Twig_Filter_Function('somefilter', ['pre_escape' => 'html', 'is_safe' => ['html']]); Dynamic Filters ~~~~~~~~~~~~~~~ @@ -297,13 +297,13 @@ Functions A function is a regular PHP function or an object method that can be called from templates. -.. code-block:: jinja +.. code-block:: twig {{ constant("DATE_W3C") }} When compiling this template to PHP, Twig looks for the PHP callable associated with the ``constant`` function. The ``constant`` function is a built-in Twig -function, and it is simply mapped to the PHP ``constant()`` function. After +function, and it is mapped directly to the PHP ``constant()`` function. After compilation, the generated PHP code is roughly equivalent to: .. code-block:: html+php @@ -311,15 +311,15 @@ compilation, the generated PHP code is roughly equivalent to: <?php echo constant('DATE_W3C') ?> Adding a function is similar to adding a filter. This can be done by calling the -``addFunction()`` method on the ``Twig_Environment`` instance:: +``addFunction()`` method on the ``\Twig\Environment`` instance:: - $twig = new Twig_Environment($loader); + $twig = new \Twig\Environment($loader); $twig->addFunction('functionName', new Twig_Function_Function('someFunction')); You can also expose extension methods as functions in your templates:: - // $this is an object that implements Twig_ExtensionInterface. - $twig = new Twig_Environment($loader); + // $this is an object that implements \Twig\Extension\ExtensionInterface. + $twig = new \Twig\Environment($loader); $twig->addFunction('otherFunction', new Twig_Function_Method($this, 'someMethod')); Functions also support ``needs_environment`` and ``is_safe`` parameters. @@ -368,7 +368,7 @@ feature as you need to understand how Twig's internals work. Let's create a simple ``set`` tag that allows the definition of simple variables from within a template. The tag can be used like follows: -.. code-block:: jinja +.. code-block:: twig {% set name = "value" %} @@ -395,9 +395,9 @@ Registering a new tag ~~~~~~~~~~~~~~~~~~~~~ Adding a tag is as simple as calling the ``addTokenParser`` method on the -``Twig_Environment`` instance:: +``\Twig\Environment`` instance:: - $twig = new Twig_Environment($loader); + $twig = new \Twig\Environment($loader); $twig->addTokenParser(new Project_Set_TokenParser()); Defining a Token Parser @@ -405,16 +405,16 @@ Defining a Token Parser Now, let's see the actual code of this class:: - class Project_Set_TokenParser extends Twig_TokenParser + class Project_Set_TokenParser extends \Twig\TokenParser\AbstractTokenParser { - public function parse(Twig_Token $token) + public function parse(\Twig\Token $token) { $lineno = $token->getLine(); - $name = $this->parser->getStream()->expect(Twig_Token::NAME_TYPE)->getValue(); - $this->parser->getStream()->expect(Twig_Token::OPERATOR_TYPE, '='); + $name = $this->parser->getStream()->expect(\Twig\Token::NAME_TYPE)->getValue(); + $this->parser->getStream()->expect(\Twig\Token::OPERATOR_TYPE, '='); $value = $this->parser->getExpressionParser()->parseExpression(); - $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE); + $this->parser->getStream()->expect(\Twig\Token::BLOCK_END_TYPE); return new Project_Set_Node($name, $value, $lineno, $this->getTag()); } @@ -428,7 +428,7 @@ Now, let's see the actual code of this class:: The ``getTag()`` method must return the tag we want to parse, here ``set``. The ``parse()`` method is invoked whenever the parser encounters a ``set`` -tag. It should return a ``Twig_Node`` instance that represents the node (the +tag. It should return a ``\Twig\Node\Node`` instance that represents the node (the ``Project_Set_Node`` calls creating is explained in the next section). The parsing process is simplified thanks to a bunch of methods you can call @@ -461,14 +461,14 @@ Defining a Node The ``Project_Set_Node`` class itself is rather simple:: - class Project_Set_Node extends Twig_Node + class Project_Set_Node extends \Twig\Node\Node { - public function __construct($name, Twig_Node_Expression $value, $lineno, $tag = null) + public function __construct($name, \Twig\Node\Expression\AbstractExpression $value, $lineno, $tag = null) { - parent::__construct(array('value' => $value), array('name' => $name), $lineno, $tag); + parent::__construct(['value' => $value], ['name' => $name], $lineno, $tag); } - public function compile(Twig_Compiler $compiler) + public function compile(\Twig\Compiler $compiler) { $compiler ->addDebugInfo($this) @@ -492,19 +492,17 @@ developer generate beautiful and readable PHP code: * ``string()``: Writes a quoted string. * ``repr()``: Writes a PHP representation of a given value (see - ``Twig_Node_For`` for a usage example). + ``\Twig\Node\ForNode`` for a usage example). * ``addDebugInfo()``: Adds the line of the original template file related to the current node as a comment. -* ``indent()``: Indents the generated code (see ``Twig_Node_Block`` for a +* ``indent()``: Indents the generated code (see ``\Twig\Node\BlockNode`` for a usage example). -* ``outdent()``: Outdents the generated code (see ``Twig_Node_Block`` for a +* ``outdent()``: Outdents the generated code (see ``\Twig\Node\BlockNode`` for a usage example). -.. _creating_extensions: - Creating an Extension --------------------- @@ -529,7 +527,7 @@ to host all the specific tags and filters you want to add to Twig. .. note:: Before writing your own extensions, have a look at the Twig official - extension repository: http://github.com/twigphp/Twig-extensions. + extension repository: https://github.com/twigphp/Twig-extensions. An extension is a class that implements the following interface:: @@ -540,7 +538,7 @@ An extension is a class that implements the following interface:: * * This is where you can load some file that contains filter functions for instance. */ - function initRuntime(Twig_Environment $environment); + function initRuntime(\Twig\Environment $environment); /** * Returns the token parser instances to add to the existing list. @@ -552,28 +550,28 @@ An extension is a class that implements the following interface:: /** * Returns the node visitor instances to add to the existing list. * - * @return Twig_NodeVisitorInterface[] + * @return \Twig\NodeVisitor\NodeVisitorInterface[] */ function getNodeVisitors(); /** * Returns a list of filters to add to the existing list. * - * @return Twig_SimpleFilter[] + * @return \Twig\TwigFilter[] */ function getFilters(); /** * Returns a list of tests to add to the existing list. * - * @return Twig_SimpleTest[] + * @return \Twig\TwigTest[] */ function getTests(); /** * Returns a list of functions to add to the existing list. * - * @return Twig_SimpleFunction[] + * @return \Twig\TwigFunction[] */ function getFunctions(); @@ -600,16 +598,16 @@ An extension is a class that implements the following interface:: } To keep your extension class clean and lean, it can inherit from the built-in -``Twig_Extension`` class instead of implementing the whole interface. That +``\Twig\Extension\AbstractExtension`` class instead of implementing the whole interface. That way, you just need to implement the ``getName()`` method as the -``Twig_Extension`` provides empty implementations for all other methods. +``\Twig\Extension\AbstractExtension`` provides empty implementations for all other methods. The ``getName()`` method must return a unique identifier for your extension. Now, with this information in mind, let's create the most basic extension possible:: - class Project_Twig_Extension extends Twig_Extension + class Project_Twig_Extension extends \Twig\Extension\AbstractExtension { public function getName() { @@ -619,8 +617,7 @@ possible:: .. note:: - Of course, this extension does nothing for now. We will customize it in - the next sections. + This extension does nothing for now. We will customize it in the next sections. Twig does not care where you save your extension on the filesystem, as all extensions must be registered explicitly to be available in your templates. @@ -628,11 +625,11 @@ extensions must be registered explicitly to be available in your templates. You can register an extension by using the ``addExtension()`` method on your main ``Environment`` object:: - $twig = new Twig_Environment($loader); + $twig = new \Twig\Environment($loader); $twig->addExtension(new Project_Twig_Extension()); -Of course, you need to first load the extension file by either using -``require_once()`` or by using an autoloader (see `spl_autoload_register()`_). +Don't forget to load first the extension file by either using ``require_once()`` +or by using an autoloader (see `spl_autoload_register()`_). .. tip:: @@ -644,13 +641,13 @@ Globals Global variables can be registered in an extension via the ``getGlobals()`` method:: - class Project_Twig_Extension extends Twig_Extension + class Project_Twig_Extension extends \Twig\Extension\AbstractExtension { public function getGlobals() { - return array( + return [ 'text' => new Text(), - ); + ]; } // ... @@ -662,13 +659,13 @@ Functions Functions can be registered in an extension via the ``getFunctions()`` method:: - class Project_Twig_Extension extends Twig_Extension + class Project_Twig_Extension extends \Twig\Extension\AbstractExtension { public function getFunctions() { - return array( + return [ 'lipsum' => new Twig_Function_Function('generate_lipsum'), - ); + ]; } // ... @@ -681,13 +678,13 @@ To add a filter to an extension, you need to override the ``getFilters()`` method. This method must return an array of filters to add to the Twig environment:: - class Project_Twig_Extension extends Twig_Extension + class Project_Twig_Extension extends \Twig\Extension\AbstractExtension { public function getFilters() { - return array( + return [ 'rot13' => new Twig_Filter_Function('str_rot13'), - ); + ]; } // ... @@ -705,13 +702,13 @@ $twig->addFilter('rot13', new Twig_Filter_Function('Project_Twig_Extension::rot1 You can also use ``Twig_Filter_Method`` instead of ``Twig_Filter_Function`` when defining a filter to use a method:: - class Project_Twig_Extension extends Twig_Extension + class Project_Twig_Extension extends \Twig\Extension\AbstractExtension { public function getFilters() { - return array( + return [ 'rot13' => new Twig_Filter_Method($this, 'rot13Filter'), - ); + ]; } public function rot13Filter($string) @@ -733,18 +730,18 @@ at the cost of a small overhead. Overriding default Filters .......................... -If some default core filters do not suit your needs, you can easily override +If some default core filters do not suit your needs, you can override them by creating your own extension. Just use the same names as the one you want to override:: - class MyCoreExtension extends Twig_Extension + class MyCoreExtension extends \Twig\Extension\AbstractExtension { public function getFilters() { - return array( + return [ 'date' => new Twig_Filter_Method($this, 'dateFilter'), // ... - ); + ]; } public function dateFilter($timestamp, $format = 'F j, Y H:i') @@ -762,7 +759,7 @@ Here, we override the ``date`` filter with a custom one. Using this extension is as simple as registering the ``MyCoreExtension`` extension by calling the ``addExtension()`` method on the environment instance:: - $twig = new Twig_Environment($loader); + $twig = new \Twig\Environment($loader); $twig->addExtension(new MyCoreExtension()); Tags @@ -772,11 +769,11 @@ Adding a tag in an extension can be done by overriding the ``getTokenParsers()`` method. This method must return an array of tags to add to the Twig environment:: - class Project_Twig_Extension extends Twig_Extension + class Project_Twig_Extension extends \Twig\Extension\AbstractExtension { public function getTokenParsers() { - return array(new Project_Set_TokenParser()); + return [new Project_Set_TokenParser()]; } // ... @@ -792,19 +789,19 @@ Operators The ``getOperators()`` methods allows to add new operators. Here is how to add ``!``, ``||``, and ``&&`` operators:: - class Project_Twig_Extension extends Twig_Extension + class Project_Twig_Extension extends \Twig\Extension\AbstractExtension { public function getOperators() { - return array( - array( - '!' => array('precedence' => 50, 'class' => 'Twig_Node_Expression_Unary_Not'), - ), - array( - '||' => array('precedence' => 10, 'class' => 'Twig_Node_Expression_Binary_Or', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT), - '&&' => array('precedence' => 15, 'class' => 'Twig_Node_Expression_Binary_And', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT), + return [ + [ + '!' => ['precedence' => 50, 'class' => '\Twig\Node\Expression\Unary\NotUnary'], ), - ); + [ + '||' => ['precedence' => 10, 'class' => '\Twig\Node\Expression\Binary\OrBinary', 'associativity' => \Twig\ExpressionParser::OPERATOR_LEFT], + '&&' => ['precedence' => 15, 'class' => '\Twig\Node\Expression\Binary\AndBinary', 'associativity' => \Twig\ExpressionParser::OPERATOR_LEFT], + ], + ]; } // ... @@ -815,13 +812,13 @@ Tests The ``getTests()`` methods allows to add new test functions:: - class Project_Twig_Extension extends Twig_Extension + class Project_Twig_Extension extends \Twig\Extension\AbstractExtension { public function getTests() { - return array( + return [ 'even' => new Twig_Test_Function('twig_test_even'), - ); + ]; } // ... @@ -836,7 +833,7 @@ Testing an Extension Functional Tests ~~~~~~~~~~~~~~~~ -You can create functional tests for extensions simply by creating the +You can create functional tests for extensions by creating the following file structure in your test directory:: Fixtures/ @@ -853,19 +850,19 @@ following file structure in your test directory:: The ``IntegrationTest.php`` file should look like this:: - class Project_Tests_IntegrationTest extends Twig_Test_IntegrationTestCase + class Project_Tests_IntegrationTest extends \Twig\Test\IntegrationTestCase { public function getExtensions() { - return array( + return [ new Project_Twig_Extension1(), new Project_Twig_Extension2(), - ); + ]; } public function getFixturesDir() { - return dirname(__FILE__).'/Fixtures/'; + return __DIR__.'/Fixtures/'; } } @@ -876,10 +873,10 @@ Node Tests ~~~~~~~~~~ Testing the node visitors can be complex, so extend your test cases from -``Twig_Test_NodeTestCase``. Examples can be found in the Twig repository +``\Twig\Test\NodeTestCase``. Examples can be found in the Twig repository `tests/Twig/Node`_ directory. -.. _`spl_autoload_register()`: http://www.php.net/spl_autoload_register -.. _`rot13`: http://www.php.net/manual/en/function.str-rot13.php -.. _`tests/Twig/Fixtures`: https://github.com/twigphp/Twig/tree/master/test/Twig/Tests/Fixtures -.. _`tests/Twig/Node`: https://github.com/twigphp/Twig/tree/master/test/Twig/Tests/Node +.. _`spl_autoload_register()`: https://secure.php.net/spl_autoload_register +.. _`rot13`: https://secure.php.net/manual/en/function.str-rot13.php +.. _`tests/Twig/Fixtures`: https://github.com/twigphp/Twig/tree/1.x/tests/Fixtures +.. _`tests/Twig/Node`: https://github.com/twigphp/Twig/tree/1.x/tests/Node diff --git a/vendor/twig/twig/doc/api.rst b/vendor/twig/twig/doc/api.rst index 8be2b8af8ecb85c59d9cbb15aeceaa42c3262663..b96b0d4e7f3e4fa96178f48e25f7211009666be6 100644 --- a/vendor/twig/twig/doc/api.rst +++ b/vendor/twig/twig/doc/api.rst @@ -9,28 +9,26 @@ Basics ------ Twig uses a central object called the **environment** (of class -``Twig_Environment``). Instances of this class are used to store the -configuration and extensions, and are used to load templates from the file -system or other locations. +``\Twig\Environment``). Instances of this class are used to store the +configuration and extensions, and are used to load templates. -Most applications will create one ``Twig_Environment`` object on application -initialization and use that to load templates. In some cases it's however -useful to have multiple environments side by side, if different configurations -are in use. +Most applications create one ``\Twig\Environment`` object on application +initialization and use that to load templates. In some cases, it might be useful +to have multiple environments side by side, with different configurations. -The simplest way to configure Twig to load templates for your application -looks roughly like this:: +The typical way to configure Twig to load templates for an application looks +roughly like this:: require_once '/path/to/lib/Twig/Autoloader.php'; Twig_Autoloader::register(); - $loader = new Twig_Loader_Filesystem('/path/to/templates'); - $twig = new Twig_Environment($loader, array( + $loader = new \Twig\Loader\FilesystemLoader('/path/to/templates'); + $twig = new \Twig\Environment($loader, [ 'cache' => '/path/to/compilation_cache', - )); + ]); -This will create a template environment with the default settings and a loader -that looks up the templates in the ``/path/to/templates/`` folder. Different +This creates a template environment with a default configuration and a loader +that looks up templates in the ``/path/to/templates/`` directory. Different loaders are available and you can also write your own if you want to load templates from a database or other resources. @@ -47,26 +45,26 @@ Rendering Templates ------------------- To load a template from a Twig environment, call the ``load()`` method which -returns a ``Twig_TemplateWrapper`` instance:: +returns a ``\Twig\TemplateWrapper`` instance:: $template = $twig->load('index.html'); .. note:: - Before Twig 1.28, you should use ``loadTemplate()`` instead which returns a - ``Twig_Template`` instance. + Before Twig 1.28, use ``loadTemplate()`` instead which returns a + ``\Twig\Template`` instance. To render the template with some variables, call the ``render()`` method:: - echo $template->render(array('the' => 'variables', 'go' => 'here')); + echo $template->render(['the' => 'variables', 'go' => 'here']); .. note:: - The ``display()`` method is a shortcut to output the template directly. + The ``display()`` method is a shortcut to output the rendered template. You can also load and render the template in one fell swoop:: - echo $twig->render('index.html', array('the' => 'variables', 'go' => 'here')); + echo $twig->render('index.html', ['the' => 'variables', 'go' => 'here']); .. versionadded:: 1.28 The possibility to render blocks from the API was added in Twig 1.28. @@ -74,17 +72,17 @@ You can also load and render the template in one fell swoop:: If a template defines blocks, they can be rendered individually via the ``renderBlock()`` call:: - echo $template->renderBlock('block_name', array('the' => 'variables', 'go' => 'here')); + echo $template->renderBlock('block_name', ['the' => 'variables', 'go' => 'here']); .. _environment_options: Environment Options ------------------- -When creating a new ``Twig_Environment`` instance, you can pass an array of +When creating a new ``\Twig\Environment`` instance, you can pass an array of options as the constructor second argument:: - $twig = new Twig_Environment($loader, array('debug' => true)); + $twig = new \Twig\Environment($loader, ['debug' => true]); The following options are available: @@ -98,7 +96,7 @@ The following options are available: The charset used by the templates. -* ``base_template_class`` *string* (defaults to ``Twig_Template``) +* ``base_template_class`` *string* (defaults to ``\Twig\Template``) The base template class to use for generated templates. @@ -157,17 +155,17 @@ Compilation Cache All template loaders can cache the compiled templates on the filesystem for future reuse. It speeds up Twig a lot as templates are only compiled once; and -the performance boost is even larger if you use a PHP accelerator such as APC. -See the ``cache`` and ``auto_reload`` options of ``Twig_Environment`` above -for more information. +the performance boost is even larger if you use a PHP accelerator such as +OPCache. See the ``cache`` and ``auto_reload`` options of ``\Twig\Environment`` +above for more information. Built-in Loaders ~~~~~~~~~~~~~~~~ -Here is a list of the built-in loaders Twig provides: +Here is a list of the built-in loaders: -``Twig_Loader_Filesystem`` -.......................... +``\Twig\Loader\FilesystemLoader`` +................................. .. versionadded:: 1.10 The ``prependPath()`` and support for namespaces were added in Twig 1.10. @@ -175,15 +173,15 @@ Here is a list of the built-in loaders Twig provides: .. versionadded:: 1.27 Relative paths support was added in Twig 1.27. -``Twig_Loader_Filesystem`` loads templates from the file system. This loader +``\Twig\Loader\FilesystemLoader`` loads templates from the file system. This loader can find templates in folders on the file system and is the preferred way to load them:: - $loader = new Twig_Loader_Filesystem($templateDir); + $loader = new \Twig\Loader\FilesystemLoader($templateDir); It can also look for templates in an array of directories:: - $loader = new Twig_Loader_Filesystem(array($templateDir1, $templateDir2)); + $loader = new \Twig\Loader\FilesystemLoader([$templateDir1, $templateDir2]); With such a configuration, Twig will first look for templates in ``$templateDir1`` and if they do not exist, it will fallback to look for them @@ -207,68 +205,65 @@ methods act on the "main" namespace):: Namespaced templates can be accessed via the special ``@namespace_name/template_path`` notation:: - $twig->render('@admin/index.html', array()); + $twig->render('@admin/index.html', []); -``Twig_Loader_Filesystem`` support absolute and relative paths. Using relative +``\Twig\Loader\FilesystemLoader`` support absolute and relative paths. Using relative paths is preferred as it makes the cache keys independent of the project root directory (for instance, it allows warming the cache from a build server where the directory might be different from the one used on production servers):: - $loader = new Twig_Loader_Filesystem('templates', getcwd().'/..'); + $loader = new \Twig\Loader\FilesystemLoader('templates', getcwd().'/..'); .. note:: When not passing the root path as a second argument, Twig uses ``getcwd()`` for relative paths. -``Twig_Loader_Array`` -..................... +``\Twig\Loader\ArrayLoader`` +............................ -``Twig_Loader_Array`` loads a template from a PHP array. It's passed an array -of strings bound to template names:: +``\Twig\Loader\ArrayLoader`` loads a template from a PHP array. It is passed an +array of strings bound to template names:: - $loader = new Twig_Loader_Array(array( + $loader = new \Twig\Loader\ArrayLoader([ 'index.html' => 'Hello {{ name }}!', - )); - $twig = new Twig_Environment($loader); + ]); + $twig = new \Twig\Environment($loader); - echo $twig->render('index.html', array('name' => 'Fabien')); + echo $twig->render('index.html', ['name' => 'Fabien']); This loader is very useful for unit testing. It can also be used for small projects where storing all templates in a single PHP file might make sense. .. tip:: - When using the ``Array`` or ``String`` loaders with a cache mechanism, you - should know that a new cache key is generated each time a template content - "changes" (the cache key being the source code of the template). If you - don't want to see your cache grows out of control, you need to take care - of clearing the old cache file by yourself. + When using the ``Array`` loaders with a cache mechanism, you should know + that a new cache key is generated each time a template content "changes" + (the cache key being the source code of the template). If you don't want to + see your cache grows out of control, you need to take care of clearing the + old cache file by yourself. -``Twig_Loader_Chain`` -..................... +``\Twig\Loader\ChainLoader`` +............................ -``Twig_Loader_Chain`` delegates the loading of templates to other loaders:: +``\Twig\Loader\ChainLoader`` delegates the loading of templates to other loaders:: - $loader1 = new Twig_Loader_Array(array( + $loader1 = new \Twig\Loader\ArrayLoader([ 'base.html' => '{% block content %}{% endblock %}', - )); - $loader2 = new Twig_Loader_Array(array( + ]); + $loader2 = new \Twig\Loader\ArrayLoader([ 'index.html' => '{% extends "base.html" %}{% block content %}Hello {{ name }}{% endblock %}', 'base.html' => 'Will never be loaded', - )); + ]); - $loader = new Twig_Loader_Chain(array($loader1, $loader2)); + $loader = new \Twig\Loader\ChainLoader([$loader1, $loader2]); - $twig = new Twig_Environment($loader); + $twig = new \Twig\Environment($loader); -When looking for a template, Twig will try each loader in turn and it will -return as soon as the template is found. When rendering the ``index.html`` -template from the above example, Twig will load it with ``$loader2`` but the -``base.html`` template will be loaded from ``$loader1``. - -``Twig_Loader_Chain`` accepts any loader that implements -``Twig_LoaderInterface``. +When looking for a template, Twig tries each loader in turn and returns as soon +as the template is found. When rendering the ``index.html`` template from the +above example, Twig will load it with ``$loader2`` but the ``base.html`` +template will be loaded from ``$loader1``. .. note:: @@ -277,7 +272,7 @@ template from the above example, Twig will load it with ``$loader2`` but the Create your own Loader ~~~~~~~~~~~~~~~~~~~~~~ -All loaders implement the ``Twig_LoaderInterface``:: +All loaders implement the ``\Twig\Loader\LoaderInterface``:: interface Twig_LoaderInterface { @@ -288,7 +283,7 @@ All loaders implement the ``Twig_LoaderInterface``:: * * @return string The template source code * - * @deprecated since 1.27 (to be removed in 2.0), implement Twig_SourceContextLoaderInterface + * @deprecated since 1.27 (to be removed in 2.0), implement \Twig\Loader\SourceContextLoaderInterface */ function getSource($name); @@ -316,38 +311,44 @@ is still fresh, given the last modification time, or ``false`` otherwise. .. note:: As of Twig 1.27, you should also implement - ``Twig_SourceContextLoaderInterface`` to avoid deprecation notices. + ``\Twig\Loader\SourceContextLoaderInterface`` to avoid deprecation notices. .. tip:: - As of Twig 1.11.0, you can also implement ``Twig_ExistsLoaderInterface`` + As of Twig 1.11.0, you can also implement ``\Twig\Loader\ExistsLoaderInterface`` to make your loader faster when used with the chain loader. Using Extensions ---------------- -Twig extensions are packages that add new features to Twig. Using an -extension is as simple as using the ``addExtension()`` method:: +Twig extensions are packages that add new features to Twig. Register an +extension via the ``addExtension()`` method:: - $twig->addExtension(new Twig_Extension_Sandbox()); + $twig->addExtension(new \Twig\Extension\SandboxExtension()); Twig comes bundled with the following extensions: -* *Twig_Extension_Core*: Defines all the core features of Twig. +* *Twig\Extension\CoreExtension*: Defines all the core features of Twig. + +* *Twig\Extension\DebugExtension*: Defines the ``dump`` function to help debug + template variables. -* *Twig_Extension_Escaper*: Adds automatic output-escaping and the possibility - to escape/unescape blocks of code. +* *Twig\Extension\EscaperExtension*: Adds automatic output-escaping and the + possibility to escape/unescape blocks of code. -* *Twig_Extension_Sandbox*: Adds a sandbox mode to the default Twig +* *Twig\Extension\SandboxExtension*: Adds a sandbox mode to the default Twig environment, making it safe to evaluate untrusted code. -* *Twig_Extension_Profiler*: Enabled the built-in Twig profiler (as of Twig - 1.18). +* *Twig\Extension\ProfilerExtension*: Enabled the built-in Twig profiler (as of + Twig 1.18). -* *Twig_Extension_Optimizer*: Optimizes the node tree before compilation. +* *Twig\Extension\OptimizerExtension*: Optimizes the node tree before + compilation. -The core, escaper, and optimizer extensions do not need to be added to the -Twig environment, as they are registered by default. +* *Twig\Extension\StringLoaderExtension*: Defined the ``template_from_string`` + function to allow loading templates from string in a template. + +The Core, Escaper, and Optimizer extensions are registered by default. Built-in Extensions ------------------- @@ -378,13 +379,13 @@ tag, ``autoescape``, and a filter, ``raw``. When creating the escaper extension, you can switch on or off the global output escaping strategy:: - $escaper = new Twig_Extension_Escaper('html'); + $escaper = new \Twig\Extension\EscaperExtension('html'); $twig->addExtension($escaper); If set to ``html``, all variables in templates are escaped (using the ``html`` escaping strategy), except those using the ``raw`` filter: -.. code-block:: jinja +.. code-block:: twig {{ article.to_html|raw }} @@ -392,7 +393,7 @@ You can also change the escaping mode locally by using the ``autoescape`` tag (see the :doc:`autoescape<tags/autoescape>` doc for the syntax used before Twig 1.8): -.. code-block:: jinja +.. code-block:: twig {% autoescape 'html' %} {{ var }} @@ -409,7 +410,7 @@ The escaping rules are implemented as follows: * Literals (integers, booleans, arrays, ...) used in the template directly as variables or filter arguments are never automatically escaped: - .. code-block:: jinja + .. code-block:: twig {{ "Twig<br />" }} {# won't be escaped #} @@ -419,7 +420,7 @@ The escaping rules are implemented as follows: * Expressions which the result is always a literal or a variable marked safe are never automatically escaped: - .. code-block:: jinja + .. code-block:: twig {{ foo ? "Twig<br />" : "<br />Twig" }} {# won't be escaped #} @@ -434,13 +435,13 @@ The escaping rules are implemented as follows: * Escaping is applied before printing, after any other filter is applied: - .. code-block:: jinja + .. code-block:: twig {{ var|upper }} {# is equivalent to {{ var|upper|escape }} #} * The `raw` filter should only be used at the end of the filter chain: - .. code-block:: jinja + .. code-block:: twig {{ var|raw|upper }} {# will be escaped #} @@ -451,7 +452,7 @@ The escaping rules are implemented as follows: ``escape('html')`` are marked safe for HTML, ``escape('js')`` is marked safe for JavaScript, ``raw`` is marked safe for everything. - .. code-block:: jinja + .. code-block:: twig {% autoescape 'js' %} {{ var|escape('html') }} {# will be escaped for HTML and JavaScript #} @@ -473,35 +474,35 @@ Sandbox Extension The ``sandbox`` extension can be used to evaluate untrusted code. Access to unsafe attributes and methods is prohibited. The sandbox security is managed by a policy instance. By default, Twig comes with one policy class: -``Twig_Sandbox_SecurityPolicy``. This class allows you to white-list some +``\Twig\Sandbox\SecurityPolicy``. This class allows you to white-list some tags, filters, properties, and methods:: - $tags = array('if'); - $filters = array('upper'); - $methods = array( - 'Article' => array('getTitle', 'getBody'), - ); - $properties = array( - 'Article' => array('title', 'body'), - ); - $functions = array('range'); - $policy = new Twig_Sandbox_SecurityPolicy($tags, $filters, $methods, $properties, $functions); + $tags = ['if']; + $filters = ['upper']; + $methods = [ + 'Article' => ['getTitle', 'getBody'], + ]; + $properties = [ + 'Article' => ['title', 'body'], + ]; + $functions = ['range']; + $policy = new \Twig\Sandbox\SecurityPolicy($tags, $filters, $methods, $properties, $functions); With the previous configuration, the security policy will only allow usage of the ``if`` tag, and the ``upper`` filter. Moreover, the templates will only be able to call the ``getTitle()`` and ``getBody()`` methods on ``Article`` objects, and the ``title`` and ``body`` public properties. Everything else -won't be allowed and will generate a ``Twig_Sandbox_SecurityError`` exception. +won't be allowed and will generate a ``\Twig\Sandbox\SecurityError`` exception. The policy object is the first argument of the sandbox constructor:: - $sandbox = new Twig_Extension_Sandbox($policy); + $sandbox = new \Twig\Extension\SandboxExtension($policy); $twig->addExtension($sandbox); By default, the sandbox mode is disabled and should be enabled when including untrusted template code by using the ``sandbox`` tag: -.. code-block:: jinja +.. code-block:: twig {% sandbox %} {% include 'user.html' %} @@ -510,7 +511,7 @@ untrusted template code by using the ``sandbox`` tag: You can sandbox all templates by passing ``true`` as the second argument of the extension constructor:: - $sandbox = new Twig_Extension_Sandbox($policy, true); + $sandbox = new \Twig\Extension\SandboxExtension($policy, true); Profiler Extension ~~~~~~~~~~~~~~~~~~ @@ -521,10 +522,10 @@ Profiler Extension The ``profiler`` extension enables a profiler for Twig templates; it should only be used on your development machines as it adds some overhead:: - $profile = new Twig_Profiler_Profile(); - $twig->addExtension(new Twig_Extension_Profiler($profile)); + $profile = new \Twig\Profiler\Profile(); + $twig->addExtension(new \Twig\Extension\ProfilerExtension($profile)); - $dumper = new Twig_Profiler_Dumper_Text(); + $dumper = new \Twig\Profiler\Dumper\TextDumper(); echo $dumper->dump($profile); A profile contains information about time and memory consumption for template, @@ -533,11 +534,12 @@ block, and macro executions. You can also dump the data in a `Blackfire.io <https://blackfire.io/>`_ compatible format:: - $dumper = new Twig_Profiler_Dumper_Blackfire(); + $dumper = new \Twig\Profiler\Dumper\BlackfireDumper(); file_put_contents('/path/to/profile.prof', $dumper->dump($profile)); Upload the profile to visualize it (create a `free account -<https://blackfire.io/signup>`_ first): +<https://blackfire.io/signup?utm_source=twig&utm_medium=doc&utm_campaign=profiler>`_ +first): .. code-block:: sh @@ -548,27 +550,31 @@ Optimizer Extension The ``optimizer`` extension optimizes the node tree before compilation:: - $twig->addExtension(new Twig_Extension_Optimizer()); + $twig->addExtension(new \Twig\Extension\OptimizerExtension()); By default, all optimizations are turned on. You can select the ones you want to enable by passing them to the constructor:: - $optimizer = new Twig_Extension_Optimizer(Twig_NodeVisitor_Optimizer::OPTIMIZE_FOR); + $optimizer = new \Twig\Extension\OptimizerExtension(\Twig\NodeVisitor\OptimizerNodeVisitor::OPTIMIZE_FOR); $twig->addExtension($optimizer); Twig supports the following optimizations: -* ``Twig_NodeVisitor_Optimizer::OPTIMIZE_ALL``, enables all optimizations +* ``\Twig\NodeVisitor\OptimizerNodeVisitor::OPTIMIZE_ALL``, enables all optimizations (this is the default value). -* ``Twig_NodeVisitor_Optimizer::OPTIMIZE_NONE``, disables all optimizations. + +* ``\Twig\NodeVisitor\OptimizerNodeVisitor::OPTIMIZE_NONE``, disables all optimizations. This reduces the compilation time, but it can increase the execution time and the consumed memory. -* ``Twig_NodeVisitor_Optimizer::OPTIMIZE_FOR``, optimizes the ``for`` tag by + +* ``\Twig\NodeVisitor\OptimizerNodeVisitor::OPTIMIZE_FOR``, optimizes the ``for`` tag by removing the ``loop`` variable creation whenever possible. -* ``Twig_NodeVisitor_Optimizer::OPTIMIZE_RAW_FILTER``, removes the ``raw`` + +* ``\Twig\NodeVisitor\OptimizerNodeVisitor::OPTIMIZE_RAW_FILTER``, removes the ``raw`` filter whenever possible. -* ``Twig_NodeVisitor_Optimizer::OPTIMIZE_VAR_ACCESS``, simplifies the creation + +* ``\Twig\NodeVisitor\OptimizerNodeVisitor::OPTIMIZE_VAR_ACCESS``, simplifies the creation and access of variables in the compiled templates whenever possible. Exceptions @@ -576,15 +582,15 @@ Exceptions Twig can throw exceptions: -* ``Twig_Error``: The base exception for all errors. +* ``\Twig\Error\Error``: The base exception for all errors. -* ``Twig_Error_Syntax``: Thrown to tell the user that there is a problem with +* ``\Twig\Error\SyntaxError``: Thrown to tell the user that there is a problem with the template syntax. -* ``Twig_Error_Runtime``: Thrown when an error occurs at runtime (when a filter +* ``\Twig\Error\RuntimeError``: Thrown when an error occurs at runtime (when a filter does not exist for instance). -* ``Twig_Error_Loader``: Thrown when an error occurs during template loading. +* ``\Twig\Error\LoaderError``: Thrown when an error occurs during template loading. -* ``Twig_Sandbox_SecurityError``: Thrown when an unallowed tag, filter, or +* ``\Twig\Sandbox\SecurityError``: Thrown when an unallowed tag, filter, or method is called in a sandboxed template. diff --git a/vendor/twig/twig/doc/coding_standards.rst b/vendor/twig/twig/doc/coding_standards.rst index bf8ea91a49c507aa8d58f4ef8a7e631e5f803d36..721b0f13aaf967ab038d31b0f2c4cc1b69c8aec0 100644 --- a/vendor/twig/twig/doc/coding_standards.rst +++ b/vendor/twig/twig/doc/coding_standards.rst @@ -7,7 +7,7 @@ standards: * Put one (and only one) space after the start of a delimiter (``{{``, ``{%``, and ``{#``) and before the end of a delimiter (``}}``, ``%}``, and ``#}``): - .. code-block:: jinja + .. code-block:: twig {{ foo }} {# comment #} @@ -16,7 +16,7 @@ standards: When using the whitespace control character, do not put any spaces between it and the delimiter: - .. code-block:: jinja + .. code-block:: twig {{- foo -}} {#- comment -#} @@ -28,7 +28,7 @@ standards: operators (``not``, ``and``, ``or``), ``~``, ``is``, ``in``, and the ternary operator (``?:``): - .. code-block:: jinja + .. code-block:: twig {{ 1 + 2 }} {{ foo ~ bar }} @@ -37,7 +37,7 @@ standards: * Put one (and only one) space after the ``:`` sign in hashes and ``,`` in arrays and hashes: - .. code-block:: jinja + .. code-block:: twig {{ [1, 2, 3] }} {{ {'foo': 'bar'} }} @@ -45,13 +45,13 @@ standards: * Do not put any spaces after an opening parenthesis and before a closing parenthesis in expressions: - .. code-block:: jinja + .. code-block:: twig {{ 1 + (2 * 3) }} * Do not put any spaces before and after string delimiters: - .. code-block:: jinja + .. code-block:: twig {{ 'foo' }} {{ "foo" }} @@ -59,7 +59,7 @@ standards: * Do not put any spaces before and after the following operators: ``|``, ``.``, ``..``, ``[]``: - .. code-block:: jinja + .. code-block:: twig {{ foo|upper|lower }} {{ user.name }} @@ -69,7 +69,7 @@ standards: * Do not put any spaces before and after the parenthesis used for filter and function calls: - .. code-block:: jinja + .. code-block:: twig {{ foo|default('foo') }} {{ range(1..10) }} @@ -77,14 +77,14 @@ standards: * Do not put any spaces before and after the opening and the closing of arrays and hashes: - .. code-block:: jinja + .. code-block:: twig {{ [1, 2, 3] }} {{ {'foo': 'bar'} }} * Use lower cased and underscored variable names: - .. code-block:: jinja + .. code-block:: twig {% set foo = 'foo' %} {% set foo_bar = 'foo' %} @@ -92,7 +92,7 @@ standards: * Indent your code inside tags (use the same indentation as the one used for the target language of the rendered template): - .. code-block:: jinja + .. code-block:: twig {% block foo %} {% if true %} diff --git a/vendor/twig/twig/doc/deprecated.rst b/vendor/twig/twig/doc/deprecated.rst index 8b25cc4104e4426413af089303cf7a43137f51e1..1d01fcc14f544277726589bb7f60b824c8b6bf69 100644 --- a/vendor/twig/twig/doc/deprecated.rst +++ b/vendor/twig/twig/doc/deprecated.rst @@ -27,29 +27,29 @@ Token Parsers * ``Twig_TokenParserBrokerInterface`` * ``Twig_TokenParserBroker`` -* As of Twig 1.27, ``Twig_Parser::getFilename()`` is deprecated. From a token +* As of Twig 1.27, ``\Twig\Parser::getFilename()`` is deprecated. From a token parser, use ``$this->parser->getStream()->getSourceContext()->getPath()`` instead. -* As of Twig 1.27, ``Twig_Parser::getEnvironment()`` is deprecated. +* As of Twig 1.27, ``\Twig\Parser::getEnvironment()`` is deprecated. Extensions ---------- * As of Twig 1.x, the ability to remove an extension is deprecated and the - ``Twig_Environment::removeExtension()`` method will be removed in 2.0. + ``\Twig\Environment::removeExtension()`` method will be removed in 2.0. -* As of Twig 1.23, the ``Twig_ExtensionInterface::initRuntime()`` method is +* As of Twig 1.23, the ``\Twig\Extension\ExtensionInterface::initRuntime()`` method is deprecated. You have two options to avoid the deprecation notice: if you implement this method to store the environment for your custom filters, functions, or tests, use the ``needs_environment`` option instead; if you have more complex needs, explicitly implement - ``Twig_Extension_InitRuntimeInterface`` (not recommended). + ``\Twig\Extension\InitRuntimeInterface`` (not recommended). -* As of Twig 1.23, the ``Twig_ExtensionInterface::getGlobals()`` method is - deprecated. Implement ``Twig_Extension_GlobalsInterface`` to avoid +* As of Twig 1.23, the ``\Twig\Extension\ExtensionInterface::getGlobals()`` method is + deprecated. Implement ``\Twig\Extension\GlobalsInterface`` to avoid deprecation notices. -* As of Twig 1.26, the ``Twig_ExtensionInterface::getName()`` method is +* As of Twig 1.26, the ``\Twig\Extension\ExtensionInterface::getName()`` method is deprecated and it is not used internally anymore. PEAR @@ -61,7 +61,7 @@ provided anymore. Use Composer instead. Filters ------- -* As of Twig 1.x, use ``Twig_SimpleFilter`` to add a filter. The following +* As of Twig 1.x, use ``\Twig\TwigFilter`` to add a filter. The following classes and interfaces will be removed in 2.0: * ``Twig_FilterInterface`` @@ -72,13 +72,13 @@ Filters * ``Twig_Filter_Node`` * As of Twig 2.x, the ``Twig_SimpleFilter`` class is deprecated and will be - removed in Twig 3.x (use ``Twig_Filter`` instead). In Twig 2.x, - ``Twig_SimpleFilter`` is just an alias for ``Twig_Filter``. + removed in Twig 3.x (use ``\Twig\TwigFilter`` instead). In Twig 2.x, + ``Twig_SimpleFilter`` is just an alias for ``\Twig\TwigFilter``. Functions --------- -* As of Twig 1.x, use ``Twig_SimpleFunction`` to add a function. The following +* As of Twig 1.x, use ``\Twig\TwigFunction`` to add a function. The following classes and interfaces will be removed in 2.0: * ``Twig_FunctionInterface`` @@ -89,13 +89,13 @@ Functions * ``Twig_Function_Node`` * As of Twig 2.x, the ``Twig_SimpleFunction`` class is deprecated and will be - removed in Twig 3.x (use ``Twig_Function`` instead). In Twig 2.x, - ``Twig_SimpleFunction`` is just an alias for ``Twig_Function``. + removed in Twig 3.x (use ``\Twig\TwigFunction`` instead). In Twig 2.x, + ``Twig_SimpleFunction`` is just an alias for ``\Twig\TwigFunction``. Tests ----- -* As of Twig 1.x, use ``Twig_SimpleTest`` to add a test. The following classes +* As of Twig 1.x, use ``\Twig\TwigTest`` to add a test. The following classes and interfaces will be removed in 2.0: * ``Twig_TestInterface`` @@ -106,8 +106,8 @@ Tests * ``Twig_Test_Node`` * As of Twig 2.x, the ``Twig_SimpleTest`` class is deprecated and will be - removed in Twig 3.x (use ``Twig_Test`` instead). In Twig 2.x, - ``Twig_SimpleTest`` is just an alias for ``Twig_Test``. + removed in Twig 3.x (use ``\Twig\TwigTest`` instead). In Twig 2.x, + ``Twig_SimpleTest`` is just an alias for ``\Twig\TwigTest``. * The ``sameas`` and ``divisibleby`` tests are deprecated in favor of ``same as`` and ``divisible by`` respectively. @@ -124,16 +124,16 @@ Nodes * As of Twig 1.x, ``Node::toXml()`` is deprecated and will be removed in Twig 2.0. -* As of Twig 1.26, ``Node::$nodes`` should only contains ``Twig_Node`` +* As of Twig 1.26, ``Node::$nodes`` should only contains ``\Twig\Node\Node`` instances, storing a ``null`` value is deprecated and won't be possible in Twig 2.x. -* As of Twig 1.27, the ``filename`` attribute on ``Twig_Node_Module`` is +* As of Twig 1.27, the ``filename`` attribute on ``\Twig\Node\ModuleNode`` is deprecated. Use ``getName()`` instead. -* As of Twig 1.27, the ``Twig_Node::getFilename()/Twig_Node::getLine()`` +* As of Twig 1.27, the ``\Twig\Node\Node::getFilename()/\Twig\Node\Node::getLine()`` methods are deprecated, use - ``Twig_Node::getTemplateName()/Twig_Node::getTemplateLine()`` instead. + ``\Twig\Node\Node::getTemplateName()/\Twig\Node\Node::getTemplateLine()`` instead. Interfaces ---------- @@ -141,40 +141,40 @@ Interfaces * As of Twig 2.x, the following interfaces are deprecated and empty (they will be removed in Twig 3.0): -* ``Twig_CompilerInterface`` (use ``Twig_Compiler`` instead) -* ``Twig_LexerInterface`` (use ``Twig_Lexer`` instead) -* ``Twig_NodeInterface`` (use ``Twig_Node`` instead) -* ``Twig_ParserInterface`` (use ``Twig_Parser`` instead) -* ``Twig_ExistsLoaderInterface`` (merged with ``Twig_LoaderInterface``) -* ``Twig_SourceContextLoaderInterface`` (merged with ``Twig_LoaderInterface``) -* ``Twig_TemplateInterface`` (use ``Twig_Template`` instead, and use - those constants Twig_Template::ANY_CALL, Twig_Template::ARRAY_CALL, - Twig_Template::METHOD_CALL) +* ``Twig_CompilerInterface`` (use ``\Twig\Compiler`` instead) +* ``Twig_LexerInterface`` (use ``\Twig\Lexer`` instead) +* ``Twig_NodeInterface`` (use ``\Twig\Node\Node`` instead) +* ``Twig_ParserInterface`` (use ``\Twig\Parser`` instead) +* ``\Twig\Loader\ExistsLoaderInterface`` (merged with ``\Twig\Loader\LoaderInterface``) +* ``\Twig\Loader\SourceContextLoaderInterface`` (merged with ``\Twig\Loader\LoaderInterface``) +* ``Twig_TemplateInterface`` (use ``\Twig\Template`` instead, and use + those constants \Twig\Template::ANY_CALL, \Twig\Template::ARRAY_CALL, + \Twig\Template::METHOD_CALL) Compiler -------- -* As of Twig 1.26, the ``Twig_Compiler::getFilename()`` has been deprecated. +* As of Twig 1.26, the ``\Twig\Compiler::getFilename()`` has been deprecated. You should not use it anyway as its values is not reliable. -* As of Twig 1.27, the ``Twig_Compiler::addIndentation()`` has been deprecated. - Use ``Twig_Compiler::write('')`` instead. +* As of Twig 1.27, the ``\Twig\Compiler::addIndentation()`` has been deprecated. + Use ``\Twig\Compiler::write('')`` instead. Loaders ------- * As of Twig 1.x, ``Twig_Loader_String`` is deprecated and will be removed in - 2.0. You can render a string via ``Twig_Environment::createTemplate()``. + 2.0. You can render a string via ``\Twig\Environment::createTemplate()``. -* As of Twig 1.27, ``Twig_LoaderInterface::getSource()`` is deprecated. - Implement ``Twig_SourceContextLoaderInterface`` instead and use +* As of Twig 1.27, ``\Twig\Loader\LoaderInterface::getSource()`` is deprecated. + Implement ``\Twig\Loader\SourceContextLoaderInterface`` instead and use ``getSourceContext()``. Node Visitors ------------- * Because of the removal of ``Twig_NodeInterface`` in 2.0, you need to extend - ``Twig_BaseNodeVisitor`` instead of implementing ``Twig_NodeVisitorInterface`` + ``\Twig\NodeVisitor\AbstractNodeVisitor`` instead of implementing ``\Twig\NodeVisitor\NodeVisitorInterface`` directly to make your node visitors compatible with both Twig 1.x and 2.x. Globals @@ -185,40 +185,40 @@ Globals changing the value of an already registered global is possible). * As of Twig 1.x, using the ``_self`` global variable to get access to the - current ``Twig_Template`` instance is deprecated; most usages only need the + current ``\Twig\Template`` instance is deprecated; most usages only need the current template name, which will continue to work in Twig 2.0. In Twig 2.0, ``_self`` returns the current template name instead of the current - ``Twig_Template`` instance. If you are using ``{{ _self.templateName }}``, + ``\Twig\Template`` instance. If you are using ``{{ _self.templateName }}``, just replace it with ``{{ _self }}``. Miscellaneous ------------- -* As of Twig 1.x, ``Twig_Environment::clearTemplateCache()``, - ``Twig_Environment::writeCacheFile()``, - ``Twig_Environment::clearCacheFiles()``, - ``Twig_Environment::getCacheFilename()``, - ``Twig_Environment::getTemplateClassPrefix()``, - ``Twig_Environment::getLexer()``, ``Twig_Environment::getParser()``, and - ``Twig_Environment::getCompiler()`` are deprecated and will be removed in 2.0. +* As of Twig 1.x, ``\Twig\Environment::clearTemplateCache()``, + ``\Twig\Environment::writeCacheFile()``, + ``\Twig\Environment::clearCacheFiles()``, + ``\Twig\Environment::getCacheFilename()``, + ``\Twig\Environment::getTemplateClassPrefix()``, + ``\Twig\Environment::getLexer()``, ``\Twig\Environment::getParser()``, and + ``\Twig\Environment::getCompiler()`` are deprecated and will be removed in 2.0. -* As of Twig 1.x, ``Twig_Template::getEnvironment()`` and +* As of Twig 1.x, ``\Twig\Template::getEnvironment()`` and ``Twig_TemplateInterface::getEnvironment()`` are deprecated and will be removed in 2.0. * As of Twig 1.21, setting the environment option ``autoescape`` to ``true`` is deprecated and will be removed in 2.0. Use ``"html"`` instead. -* As of Twig 1.27, ``Twig_Error::getTemplateFile()`` and - ``Twig_Error::setTemplateFile()`` are deprecated. Use - ``Twig_Error::getTemplateName()`` and ``Twig_Error::setTemplateName()`` +* As of Twig 1.27, ``\Twig\Error\Error::getTemplateFile()`` and + ``\Twig\Error\Error::setTemplateFile()`` are deprecated. Use + ``\Twig\Error\Error::getTemplateName()`` and ``\Twig\Error\Error::setTemplateName()`` instead. -* As of Twig 1.27, ``Twig_Template::getSource()`` is deprecated. Use - ``Twig_Template::getSourceContext()`` instead. +* As of Twig 1.27, ``\Twig\Template::getSource()`` is deprecated. Use + ``\Twig\Template::getSourceContext()`` instead. -* As of Twig 1.27, ``Twig_Parser::addHandler()`` and - ``Twig_Parser::addNodeVisitor()`` are deprecated and will be removed in 2.0. +* As of Twig 1.27, ``\Twig\Parser::addHandler()`` and + ``\Twig\Parser::addNodeVisitor()`` are deprecated and will be removed in 2.0. * As of Twig 1.29, some classes are marked as being final via the `@final` annotation. Those classes will be marked as final in 2.0. diff --git a/vendor/twig/twig/doc/filters/abs.rst b/vendor/twig/twig/doc/filters/abs.rst index 22fa59d0369fc3cbb0edbf199e22af245da4c01c..77d5cf05495958361eeda9dcea722c71caf4dc6e 100644 --- a/vendor/twig/twig/doc/filters/abs.rst +++ b/vendor/twig/twig/doc/filters/abs.rst @@ -3,7 +3,7 @@ The ``abs`` filter returns the absolute value. -.. code-block:: jinja +.. code-block:: twig {# number = -5 #} @@ -15,4 +15,4 @@ The ``abs`` filter returns the absolute value. Internally, Twig uses the PHP `abs`_ function. -.. _`abs`: http://php.net/abs +.. _`abs`: https://secure.php.net/abs diff --git a/vendor/twig/twig/doc/filters/batch.rst b/vendor/twig/twig/doc/filters/batch.rst index f8b6fa9d484d9e8664b4dfce0e0ab7bd21b22ce1..cc50ec8e8570be22b6aefa45a11966d83a5b822b 100644 --- a/vendor/twig/twig/doc/filters/batch.rst +++ b/vendor/twig/twig/doc/filters/batch.rst @@ -8,7 +8,7 @@ The ``batch`` filter "batches" items by returning a list of lists with the given number of items. A second parameter can be provided and used to fill in missing items: -.. code-block:: jinja +.. code-block:: twig {% set items = ['a', 'b', 'c', 'd', 'e', 'f', 'g'] %} @@ -24,7 +24,7 @@ missing items: The above example will be rendered as: -.. code-block:: jinja +.. code-block:: twig <table> <tr> diff --git a/vendor/twig/twig/doc/filters/capitalize.rst b/vendor/twig/twig/doc/filters/capitalize.rst index 10546a1f3ec8292d27435c619abc05e1aa7f7e77..2353658bf157f311b8b9b7e34b68e62170d79372 100644 --- a/vendor/twig/twig/doc/filters/capitalize.rst +++ b/vendor/twig/twig/doc/filters/capitalize.rst @@ -4,7 +4,7 @@ The ``capitalize`` filter capitalizes a value. The first character will be uppercase, all others lowercase: -.. code-block:: jinja +.. code-block:: twig {{ 'my first car'|capitalize }} diff --git a/vendor/twig/twig/doc/filters/convert_encoding.rst b/vendor/twig/twig/doc/filters/convert_encoding.rst index f4ebe5807d96c648e037c0780f08559134ac402a..28fde826dc0584878b11edce86864122185d39a0 100644 --- a/vendor/twig/twig/doc/filters/convert_encoding.rst +++ b/vendor/twig/twig/doc/filters/convert_encoding.rst @@ -8,7 +8,7 @@ The ``convert_encoding`` filter converts a string from one encoding to another. The first argument is the expected output charset and the second one is the input charset: -.. code-block:: jinja +.. code-block:: twig {{ data|convert_encoding('UTF-8', 'iso-2022-jp') }} @@ -24,5 +24,5 @@ Arguments * ``to``: The output charset * ``from``: The input charset -.. _`iconv`: http://php.net/iconv -.. _`mbstring`: http://php.net/mbstring +.. _`iconv`: https://secure.php.net/iconv +.. _`mbstring`: https://secure.php.net/mbstring diff --git a/vendor/twig/twig/doc/filters/date.rst b/vendor/twig/twig/doc/filters/date.rst index 99a17ab75a6dc75b947b2563f666f6307936b470..b36a77325657bc627af87ee8d0c2de457927a043 100644 --- a/vendor/twig/twig/doc/filters/date.rst +++ b/vendor/twig/twig/doc/filters/date.rst @@ -15,7 +15,7 @@ The ``date`` filter formats a date to a given format: -.. code-block:: jinja +.. code-block:: twig {{ post.published_at|date("m/d/Y") }} @@ -27,14 +27,14 @@ The ``date`` filter accepts strings (it must be in a format supported by the `strtotime`_ function), `DateTime`_ instances, or `DateInterval`_ instances. For instance, to display the current date, filter the word "now": -.. code-block:: jinja +.. code-block:: twig {{ "now"|date("m/d/Y") }} To escape words and characters in the date format use ``\\`` in front of each character: -.. code-block:: jinja +.. code-block:: twig {{ post.published_at|date("F jS \\a\\t g:ia") }} @@ -42,19 +42,19 @@ If the value passed to the ``date`` filter is ``null``, it will return the current date by default. If an empty string is desired instead of the current date, use a ternary operator: -.. code-block:: jinja +.. code-block:: twig {{ post.published_at is empty ? "" : post.published_at|date("m/d/Y") }} If no format is provided, Twig will use the default one: ``F j, Y H:i``. This -default can be easily changed by calling the ``setDateFormat()`` method on the +default can be changed by calling the ``setDateFormat()`` method on the ``core`` extension instance. The first argument is the default format for dates and the second one is the default format for date intervals: .. code-block:: php - $twig = new Twig_Environment($loader); - $twig->getExtension('Twig_Extension_Core')->setDateFormat('d/m/Y', '%d days'); + $twig = new \Twig\Environment($loader); + $twig->getExtension('\Twig\Extension\CoreExtension')->setDateFormat('d/m/Y', '%d days'); // before Twig 1.26 $twig->getExtension('core')->setDateFormat('d/m/Y', '%d days'); @@ -66,14 +66,14 @@ By default, the date is displayed by applying the default timezone (the one specified in php.ini or declared in Twig -- see below), but you can override it by explicitly specifying a timezone: -.. code-block:: jinja +.. code-block:: twig {{ post.published_at|date("m/d/Y", "Europe/Paris") }} If the date is already a DateTime object, and if you want to keep its current timezone, pass ``false`` as the timezone value: -.. code-block:: jinja +.. code-block:: twig {{ post.published_at|date("m/d/Y", false) }} @@ -81,8 +81,8 @@ The default timezone can also be set globally by calling ``setTimezone()``: .. code-block:: php - $twig = new Twig_Environment($loader); - $twig->getExtension('Twig_Extension_Core')->setTimezone('Europe/Paris'); + $twig = new \Twig\Environment($loader); + $twig->getExtension('\Twig\Extension\CoreExtension')->setTimezone('Europe/Paris'); // before Twig 1.26 $twig->getExtension('core')->setTimezone('Europe/Paris'); @@ -93,8 +93,8 @@ Arguments * ``format``: The date format * ``timezone``: The date timezone -.. _`strtotime`: http://www.php.net/strtotime -.. _`DateTime`: http://www.php.net/DateTime -.. _`DateInterval`: http://www.php.net/DateInterval -.. _`date`: http://www.php.net/date -.. _`DateInterval::format`: http://www.php.net/DateInterval.format +.. _`strtotime`: https://secure.php.net/strtotime +.. _`DateTime`: https://secure.php.net/DateTime +.. _`DateInterval`: https://secure.php.net/DateInterval +.. _`date`: https://secure.php.net/date +.. _`DateInterval::format`: https://secure.php.net/DateInterval.format diff --git a/vendor/twig/twig/doc/filters/date_modify.rst b/vendor/twig/twig/doc/filters/date_modify.rst index add40b56b01c607d9685d1bb07758dcf3a838293..e4217d59fefc33b9ec96b80a3a7b49b61bbc692b 100644 --- a/vendor/twig/twig/doc/filters/date_modify.rst +++ b/vendor/twig/twig/doc/filters/date_modify.rst @@ -6,12 +6,12 @@ The ``date_modify`` filter modifies a date with a given modifier string: -.. code-block:: jinja +.. code-block:: twig {{ post.published_at|date_modify("+1 day")|date("m/d/Y") }} The ``date_modify`` filter accepts strings (it must be in a format supported -by the `strtotime`_ function) or `DateTime`_ instances. You can easily combine +by the `strtotime`_ function) or `DateTime`_ instances. You can combine it with the :doc:`date<date>` filter for formatting. Arguments @@ -19,5 +19,5 @@ Arguments * ``modifier``: The modifier -.. _`strtotime`: http://www.php.net/strtotime -.. _`DateTime`: http://www.php.net/DateTime +.. _`strtotime`: https://secure.php.net/strtotime +.. _`DateTime`: https://secure.php.net/DateTime diff --git a/vendor/twig/twig/doc/filters/default.rst b/vendor/twig/twig/doc/filters/default.rst index 641ac6e756fac85beb192fd5b3e7ea63ccc551f6..c4ccb56a5002905dbc07f56ae343bd17c107121b 100644 --- a/vendor/twig/twig/doc/filters/default.rst +++ b/vendor/twig/twig/doc/filters/default.rst @@ -4,7 +4,7 @@ The ``default`` filter returns the passed default value if the value is undefined or empty, otherwise the value of the variable: -.. code-block:: jinja +.. code-block:: twig {{ var|default('var is not defined') }} @@ -18,7 +18,7 @@ When using the ``default`` filter on an expression that uses variables in some method calls, be sure to use the ``default`` filter whenever a variable can be undefined: -.. code-block:: jinja +.. code-block:: twig {{ var.method(foo|default('foo'))|default('foo') }} diff --git a/vendor/twig/twig/doc/filters/escape.rst b/vendor/twig/twig/doc/filters/escape.rst index 21491343b6b8893a0b03ce11a9892edbb0c69d93..8ae95b93da3ba9c5cc7c81cf76ec77635fe9f014 100644 --- a/vendor/twig/twig/doc/filters/escape.rst +++ b/vendor/twig/twig/doc/filters/escape.rst @@ -8,26 +8,29 @@ .. versionadded:: 1.14.0 The ability to define custom escapers was added in Twig 1.14.0. -The ``escape`` filter escapes a string for safe insertion into the final -output. It supports different escaping strategies depending on the template +The ``escape`` filter escapes a string using strategies that depend on the context. By default, it uses the HTML escaping strategy: -.. code-block:: jinja +.. code-block:: html+twig - {{ user.username|escape }} + <p> + {{ user.username|escape }} + </p> For convenience, the ``e`` filter is defined as an alias: -.. code-block:: jinja +.. code-block:: html+twig - {{ user.username|e }} + <p> + {{ user.username|e }} + </p> The ``escape`` filter can also be used in other contexts than HTML thanks to an optional argument which defines the escaping strategy to use: -.. code-block:: jinja +.. code-block:: twig {{ user.username|e }} {# is equivalent to #} @@ -35,26 +38,33 @@ an optional argument which defines the escaping strategy to use: And here is how to escape variables included in JavaScript code: -.. code-block:: jinja +.. code-block:: twig {{ user.username|escape('js') }} {{ user.username|e('js') }} -The ``escape`` filter supports the following escaping strategies: +The ``escape`` filter supports the following escaping strategies for HTML +documents: * ``html``: escapes a string for the **HTML body** context. -* ``js``: escapes a string for the **JavaScript context**. +* ``js``: escapes a string for the **JavaScript** context. -* ``css``: escapes a string for the **CSS context**. CSS escaping can be +* ``css``: escapes a string for the **CSS** context. CSS escaping can be applied to any string being inserted into CSS and escapes everything except alphanumerics. -* ``url``: escapes a string for the **URI or parameter contexts**. This should +* ``url``: escapes a string for the **URI or parameter** contexts. This should not be used to escape an entire URI; only a subcomponent being inserted. * ``html_attr``: escapes a string for the **HTML attribute** context. +Note that doing contextual escaping in HTML documents is hard and choosing the +right escaping strategy depends on a lot of factors. Please, read related +documentation like `the OWASP prevention cheat sheet +<https://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets/Cross_Site_Scripting_Prevention_Cheat_Sheet.md>`_ +to learn more about this topic. + .. note:: Internally, ``escape`` uses the PHP native `htmlspecialchars`_ function @@ -67,7 +77,7 @@ The ``escape`` filter supports the following escaping strategies: escape filter; but that does not work when using a variable as the escaping strategy: - .. code-block:: jinja + .. code-block:: twig {% set strategy = 'html' %} @@ -79,7 +89,7 @@ The ``escape`` filter supports the following escaping strategies: When using a variable as the escaping strategy, you should disable automatic escaping: - .. code-block:: jinja + .. code-block:: twig {% set strategy = 'html' %} @@ -96,8 +106,8 @@ used in the ``escape`` call) and the second one must be a valid PHP callable: .. code-block:: php - $twig = new Twig_Environment($loader); - $twig->getExtension('Twig_Extension_Core')->setEscaper('csv', 'csv_escaper'); + $twig = new \Twig\Environment($loader); + $twig->getExtension('\Twig\Extension\CoreExtension')->setEscaper('csv', 'csv_escaper'); // before Twig 1.26 $twig->getExtension('core')->setEscaper('csv', 'csv_escaper'); @@ -107,8 +117,8 @@ string to escape, and the charset. .. note:: - Built-in escapers cannot be overridden mainly they should be considered as - the final implementation and also for better performance. + Built-in escapers cannot be overridden mainly because they should be + considered as the final implementation and also for better performance. Arguments --------- @@ -116,4 +126,4 @@ Arguments * ``strategy``: The escaping strategy * ``charset``: The string charset -.. _`htmlspecialchars`: http://php.net/htmlspecialchars +.. _`htmlspecialchars`: https://secure.php.net/htmlspecialchars diff --git a/vendor/twig/twig/doc/filters/filter.rst b/vendor/twig/twig/doc/filters/filter.rst new file mode 100644 index 0000000000000000000000000000000000000000..310e63a73e499cdd63488f47d3660fa284e28ab6 --- /dev/null +++ b/vendor/twig/twig/doc/filters/filter.rst @@ -0,0 +1,58 @@ +``filter`` +========= + +.. versionadded:: 1.41 + The ``filter`` filter was added in Twig 1.41 and 2.10. + +The ``filter`` filter filters elements of a sequence or a mapping using an arrow +function. The arrow function receives the value of the sequence or mapping: + +.. code-block:: twig + + {% set sizes = [34, 36, 38, 40, 42] %} + + {{ sizes|filter(v => v > 38)|join(', ') }} + {# output 40, 42 #} + +Combined with the ``for`` tag, it allows to filter the items to iterate over: + +.. code-block:: twig + + {% for v in sizes|filter(v => v > 38) -%} + {{ v }} + {% endfor %} + {# output 40 42 #} + +It also works with mappings: + +.. code-block:: twig + + {% set sizes = { + xs: 34, + s: 36, + m: 38, + l: 40, + xl: 42, + } %} + + {% for k, v in sizes|filter(v => v > 38) -%} + {{ k }} = {{ v }} + {% endfor %} + {# output l = 40 xl = 42 #} + +The arrow function also receives the key as a second argument: + +.. code-block:: twig + + {% for k, v in sizes|filter((v, k) => v > 38 and k != "xl") -%} + {{ k }} = {{ v }} + {% endfor %} + {# output l = 40 #} + +Note that the arrow function has access to the current context. + +Arguments +--------- + +* ``array``: The sequence or mapping +* ``arrow``: The arrow function diff --git a/vendor/twig/twig/doc/filters/first.rst b/vendor/twig/twig/doc/filters/first.rst index 674c1f9ed1215c5821ab7d47869fa821e77267d7..f87fe5942782e302d9a0c51dae291e5be00cf7fe 100644 --- a/vendor/twig/twig/doc/filters/first.rst +++ b/vendor/twig/twig/doc/filters/first.rst @@ -7,7 +7,7 @@ The ``first`` filter returns the first "element" of a sequence, a mapping, or a string: -.. code-block:: jinja +.. code-block:: twig {{ [1, 2, 3, 4]|first }} {# outputs 1 #} @@ -22,4 +22,4 @@ a string: It also works with objects implementing the `Traversable`_ interface. -.. _`Traversable`: http://php.net/manual/en/class.traversable.php +.. _`Traversable`: https://secure.php.net/manual/en/class.traversable.php diff --git a/vendor/twig/twig/doc/filters/format.rst b/vendor/twig/twig/doc/filters/format.rst index f8effd9a94081c65683b9348fc4b21c5f63a92b7..c0c96ee3f5405bf340d312f644f8f1218ce58d2a 100644 --- a/vendor/twig/twig/doc/filters/format.rst +++ b/vendor/twig/twig/doc/filters/format.rst @@ -4,13 +4,13 @@ The ``format`` filter formats a given string by replacing the placeholders (placeholders follows the `sprintf`_ notation): -.. code-block:: jinja +.. code-block:: twig {{ "I like %s and %s."|format(foo, "bar") }} {# outputs I like foo and bar if the foo parameter equals to the foo string. #} -.. _`sprintf`: http://www.php.net/sprintf +.. _`sprintf`: https://secure.php.net/sprintf .. seealso:: :doc:`replace<replace>` diff --git a/vendor/twig/twig/doc/filters/index.rst b/vendor/twig/twig/doc/filters/index.rst index 8daa961183871de164b5451223913de2671d8136..8524fc03c49473cd70c580220944415e736754bb 100644 --- a/vendor/twig/twig/doc/filters/index.rst +++ b/vendor/twig/twig/doc/filters/index.rst @@ -12,6 +12,7 @@ Filters date_modify default escape + filter first format join @@ -20,15 +21,18 @@ Filters last length lower + map merge nl2br number_format raw + reduce replace reverse round slice sort + spaceless split striptags title diff --git a/vendor/twig/twig/doc/filters/join.rst b/vendor/twig/twig/doc/filters/join.rst index 2fab94528ad099c8bef98b8b46c4b85ecd9b64f0..3f9079eab89edef5ed4d2ef79d04398c5b96b74a 100644 --- a/vendor/twig/twig/doc/filters/join.rst +++ b/vendor/twig/twig/doc/filters/join.rst @@ -1,10 +1,13 @@ ``join`` ======== +.. versionadded:: 1.37 and 2.6.1 + The ``and`` argument was added in Twig 1.37 and 2.6.1. + The ``join`` filter returns a string which is the concatenation of the items of a sequence: -.. code-block:: jinja +.. code-block:: twig {{ [1, 2, 3]|join }} {# returns 123 #} @@ -12,12 +15,21 @@ of a sequence: The separator between elements is an empty string per default, but you can define it with the optional first parameter: -.. code-block:: jinja +.. code-block:: twig {{ [1, 2, 3]|join('|') }} {# outputs 1|2|3 #} +A second parameter can also be provided that will be the separator used between +the last two items of the sequence: + +.. code-block:: twig + + {{ [1, 2, 3]|join(', ', ' and ') }} + {# outputs 1, 2 and 3 #} + Arguments --------- * ``glue``: The separator +* ``and``: The separator for the last pair of input items diff --git a/vendor/twig/twig/doc/filters/json_encode.rst b/vendor/twig/twig/doc/filters/json_encode.rst index a39bb476eaec35a7fd4ae32eb34a7641158b3c21..434e2f17832511664395a5e7a2134a572646993f 100644 --- a/vendor/twig/twig/doc/filters/json_encode.rst +++ b/vendor/twig/twig/doc/filters/json_encode.rst @@ -3,7 +3,7 @@ The ``json_encode`` filter returns the JSON representation of a value: -.. code-block:: jinja +.. code-block:: twig {{ data|json_encode() }} @@ -14,8 +14,10 @@ The ``json_encode`` filter returns the JSON representation of a value: Arguments --------- -* ``options``: A bitmask of `json_encode options`_ (``{{ - data|json_encode(constant('JSON_PRETTY_PRINT')) }}``) +* ``options``: A bitmask of `json_encode options`_: ``{{ + data|json_encode(constant('JSON_PRETTY_PRINT')) }}``. + Combine constants using :ref:`bitwise operators<template_logic>`: + ``{{ data|json_encode(constant('JSON_PRETTY_PRINT') b-or constant('JSON_HEX_QUOT')) }}`` -.. _`json_encode`: http://php.net/json_encode -.. _`json_encode options`: http://www.php.net/manual/en/json.constants.php +.. _`json_encode`: https://secure.php.net/json_encode +.. _`json_encode options`: https://secure.php.net/manual/en/json.constants.php diff --git a/vendor/twig/twig/doc/filters/keys.rst b/vendor/twig/twig/doc/filters/keys.rst index e4f090c6b7a490fe2360a13a364393379f64c0c3..586094717203ca43b08da819d7e61b0337162d2e 100644 --- a/vendor/twig/twig/doc/filters/keys.rst +++ b/vendor/twig/twig/doc/filters/keys.rst @@ -4,7 +4,7 @@ The ``keys`` filter returns the keys of an array. It is useful when you want to iterate over the keys of an array: -.. code-block:: jinja +.. code-block:: twig {% for key in array|keys %} ... diff --git a/vendor/twig/twig/doc/filters/last.rst b/vendor/twig/twig/doc/filters/last.rst index 345b6573d73173d136628cfb68f50f4619c0d532..0eb2b84ffc399e57376935b6748236ead2a9d430 100644 --- a/vendor/twig/twig/doc/filters/last.rst +++ b/vendor/twig/twig/doc/filters/last.rst @@ -7,7 +7,7 @@ The ``last`` filter returns the last "element" of a sequence, a mapping, or a string: -.. code-block:: jinja +.. code-block:: twig {{ [1, 2, 3, 4]|last }} {# outputs 4 #} @@ -22,4 +22,4 @@ a string: It also works with objects implementing the `Traversable`_ interface. -.. _`Traversable`: http://php.net/manual/en/class.traversable.php +.. _`Traversable`: https://secure.php.net/manual/en/class.traversable.php diff --git a/vendor/twig/twig/doc/filters/length.rst b/vendor/twig/twig/doc/filters/length.rst index 5620f3b3c4d6f16eb6f32a13e5db290400855c93..8b504ed258fbad507286945dcd5aa60750b06a16 100644 --- a/vendor/twig/twig/doc/filters/length.rst +++ b/vendor/twig/twig/doc/filters/length.rst @@ -14,7 +14,9 @@ return value of the ``count()`` method. For objects that implement the ``__toString()`` magic method (and not ``Countable``), it will return the length of the string provided by that method. -.. code-block:: jinja +For objects that implement the ``IteratorAggregate`` interface, ``length`` will use the return value of the ``iterator_count()`` method. + +.. code-block:: twig {% if users|length > 10 %} ... diff --git a/vendor/twig/twig/doc/filters/lower.rst b/vendor/twig/twig/doc/filters/lower.rst index ef9faa90a31606d1c8ec7eac3ec6e0da4e11ac44..c0a0e0cddf4eb2ba87ba2b8eb7e54fdb28092e87 100644 --- a/vendor/twig/twig/doc/filters/lower.rst +++ b/vendor/twig/twig/doc/filters/lower.rst @@ -3,7 +3,7 @@ The ``lower`` filter converts a value to lowercase: -.. code-block:: jinja +.. code-block:: twig {{ 'WELCOME'|lower }} diff --git a/vendor/twig/twig/doc/filters/map.rst b/vendor/twig/twig/doc/filters/map.rst new file mode 100644 index 0000000000000000000000000000000000000000..9b1f5d738ec972101e020f731230f0c2b298eae0 --- /dev/null +++ b/vendor/twig/twig/doc/filters/map.rst @@ -0,0 +1,38 @@ +``map`` +======= + +.. versionadded:: 1.41 + The ``map`` filter was added in Twig 1.41 and 2.10. + +The ``map`` filter applies an arrow function to the elements of a sequence or a +mapping. The arrow function receives the value of the sequence or mapping: + +.. code-block:: twig + + {% set people = [ + {first: "Bob", last: "Smith"}, + {first: "Alice", last: "Dupond"}, + ] %} + + {{ people|map(p => "#{p.first} #{p.last}")|join(', ') }} + {# outputs Bob Smith, Alice Dupond #} + +The arrow function also receives the key as a second argument: + +.. code-block:: twig + + {% set people = { + "Bob": "Smith", + "Alice": "Dupond", + } %} + + {{ people|map((last, first) => "#{first} #{last}")|join(', ') }} + {# outputs Bob Smith, Alice Dupond #} + +Note that the arrow function has access to the current context. + +Arguments +--------- + +* ``array``: The sequence or mapping +* ``arrow``: The arrow function diff --git a/vendor/twig/twig/doc/filters/merge.rst b/vendor/twig/twig/doc/filters/merge.rst index 88780dd6ff63c5f461a316e84862d842e4016353..e26e51c242bf9783ecf7140fbd75ef9f9a197654 100644 --- a/vendor/twig/twig/doc/filters/merge.rst +++ b/vendor/twig/twig/doc/filters/merge.rst @@ -3,7 +3,7 @@ The ``merge`` filter merges an array with another array: -.. code-block:: jinja +.. code-block:: twig {% set values = [1, 2] %} @@ -15,7 +15,7 @@ New values are added at the end of the existing ones. The ``merge`` filter also works on hashes: -.. code-block:: jinja +.. code-block:: twig {% set items = { 'apple': 'fruit', 'orange': 'fruit', 'peugeot': 'unknown' } %} @@ -32,7 +32,7 @@ overridden. If you want to ensure that some values are defined in an array (by given default values), reverse the two elements in the call: - .. code-block:: jinja + .. code-block:: twig {% set items = { 'apple': 'fruit', 'orange': 'fruit' } %} @@ -45,4 +45,4 @@ overridden. Internally, Twig uses the PHP `array_merge`_ function. It supports Traversable objects by transforming those to arrays. -.. _`array_merge`: http://php.net/array_merge +.. _`array_merge`: https://secure.php.net/array_merge diff --git a/vendor/twig/twig/doc/filters/nl2br.rst b/vendor/twig/twig/doc/filters/nl2br.rst index 5c923e143aab48bf5d76f58a676d5cb9f522cd42..3ad8d856bb8c31a87edbd38ac8da17c8a686cb98 100644 --- a/vendor/twig/twig/doc/filters/nl2br.rst +++ b/vendor/twig/twig/doc/filters/nl2br.rst @@ -6,7 +6,7 @@ The ``nl2br`` filter inserts HTML line breaks before all newlines in a string: -.. code-block:: jinja +.. code-block:: twig {{ "I like Twig.\nYou will like it too."|nl2br }} {# outputs diff --git a/vendor/twig/twig/doc/filters/number_format.rst b/vendor/twig/twig/doc/filters/number_format.rst index f9d6705e72b5425534b4d14bb402f6fcd106cc7a..83366da98da76088f6f9b4f5b7e103d1363c1de9 100644 --- a/vendor/twig/twig/doc/filters/number_format.rst +++ b/vendor/twig/twig/doc/filters/number_format.rst @@ -7,21 +7,21 @@ The ``number_format`` filter formats numbers. It is a wrapper around PHP's `number_format`_ function: -.. code-block:: jinja +.. code-block:: twig {{ 200.35|number_format }} You can control the number of decimal places, decimal point, and thousands separator using the additional arguments: -.. code-block:: jinja +.. code-block:: twig {{ 9800.333|number_format(2, '.', ',') }} To format negative numbers, wrap the number with parentheses (needed because of Twig's :ref:`precedence of operators <twig-expressions>`: -.. code-block:: jinja +.. code-block:: twig {{ -9800.333|number_format(2, '.', ',') }} {# outputs : -9 #} {{ (-9800.333)|number_format(2, '.', ',') }} {# outputs : -9,800.33 #} @@ -33,12 +33,12 @@ options of: * ``.`` as the decimal point. * ``,`` as the thousands separator. -These defaults can be easily changed through the core extension: +These defaults can be changed through the core extension: .. code-block:: php - $twig = new Twig_Environment($loader); - $twig->getExtension('Twig_Extension_Core')->setNumberFormat(3, '.', ','); + $twig = new \Twig\Environment($loader); + $twig->getExtension('\Twig\Extension\CoreExtension')->setNumberFormat(3, '.', ','); // before Twig 1.26 $twig->getExtension('core')->setNumberFormat(3, '.', ','); @@ -53,4 +53,4 @@ Arguments * ``decimal_point``: The character(s) to use for the decimal point * ``thousand_sep``: The character(s) to use for the thousands separator -.. _`number_format`: http://php.net/number_format +.. _`number_format`: https://secure.php.net/number_format diff --git a/vendor/twig/twig/doc/filters/raw.rst b/vendor/twig/twig/doc/filters/raw.rst index e5e5b12ecd77d2e2c136a9bbd7350aeada696523..ad74a52aee10cc56566f1d216b3a3b6172c2d8a9 100644 --- a/vendor/twig/twig/doc/filters/raw.rst +++ b/vendor/twig/twig/doc/filters/raw.rst @@ -5,7 +5,7 @@ The ``raw`` filter marks the value as being "safe", which means that in an environment with automatic escaping enabled this variable will not be escaped if ``raw`` is the last filter applied to it: -.. code-block:: jinja +.. code-block:: twig {% autoescape %} {{ var|raw }} {# var won't be escaped #} @@ -13,9 +13,11 @@ if ``raw`` is the last filter applied to it: .. note:: + **This note only applies to Twig before versions 1.39 and 2.8**. + Be careful when using the ``raw`` filter inside expressions: - .. code-block:: jinja + .. code-block:: twig {% autoescape %} {% set hello = '<strong>Hello</strong>' %} diff --git a/vendor/twig/twig/doc/filters/reduce.rst b/vendor/twig/twig/doc/filters/reduce.rst new file mode 100644 index 0000000000000000000000000000000000000000..7d04d6c7b086026fe0397f9e3424f4f54e053a48 --- /dev/null +++ b/vendor/twig/twig/doc/filters/reduce.rst @@ -0,0 +1,33 @@ +``reduce`` +========= + +.. versionadded:: 1.41 + The ``reduce`` filter was added in Twig 1.41 and 2.10. + +The ``reduce`` filter iteratively reduces a sequence or a mapping to a single +value using an arrow function, so as to reduce it to a single value. The arrow +function receives the return value of the previous iteration and the current +value of the sequence or mapping: + +.. code-block:: twig + + {% set numbers = [1, 2, 3] %} + + {{ numbers|reduce((carry, v) => carry + v) }} + {# output 6 #} + +The ``reduce`` filter takes an ``initial`` value as a second argument: + +.. code-block:: twig + + {{ numbers|reduce((carry, v) => carry + v, 10) }} + {# output 16 #} + +Note that the arrow function has access to the current context. + +Arguments +--------- + +* ``array``: The sequence or mapping +* ``arrow``: The arrow function +* ``initial``: The initial value diff --git a/vendor/twig/twig/doc/filters/replace.rst b/vendor/twig/twig/doc/filters/replace.rst index 8dbb745939b7b2f1e91fe1c68330a1ea895dbcb9..ceb6c0097155022c5ff992610167168b24988f0d 100644 --- a/vendor/twig/twig/doc/filters/replace.rst +++ b/vendor/twig/twig/doc/filters/replace.rst @@ -4,13 +4,19 @@ The ``replace`` filter formats a given string by replacing the placeholders (placeholders are free-form): -.. code-block:: jinja +.. code-block:: twig {{ "I like %this% and %that%."|replace({'%this%': foo, '%that%': "bar"}) }} {# outputs I like foo and bar if the foo parameter equals to the foo string. #} + {# using % as a delimiter is purely conventional and optional #} + + {{ "I like this and --that--."|replace({'this': foo, '--that--': "bar"}) }} + + {# outputs I like foo and bar #} + Arguments --------- diff --git a/vendor/twig/twig/doc/filters/reverse.rst b/vendor/twig/twig/doc/filters/reverse.rst index 76fd2c1abd8a4dc07885cc0f640911e3d57adfc3..b2218c99d58ac602eb0ddfe92537a35001f1de3e 100644 --- a/vendor/twig/twig/doc/filters/reverse.rst +++ b/vendor/twig/twig/doc/filters/reverse.rst @@ -6,7 +6,7 @@ The ``reverse`` filter reverses a sequence, a mapping, or a string: -.. code-block:: jinja +.. code-block:: twig {% for user in users|reverse %} ... @@ -21,7 +21,7 @@ The ``reverse`` filter reverses a sequence, a mapping, or a string: For sequences and mappings, numeric keys are not preserved. To reverse them as well, pass ``true`` as an argument to the ``reverse`` filter: - .. code-block:: jinja + .. code-block:: twig {% for key, value in {1: "a", 2: "b", 3: "c"}|reverse %} {{ key }}: {{ value }} @@ -44,4 +44,4 @@ Arguments * ``preserve_keys``: Preserve keys when reversing a mapping or a sequence. -.. _`Traversable`: http://php.net/Traversable +.. _`Traversable`: https://secure.php.net/Traversable diff --git a/vendor/twig/twig/doc/filters/round.rst b/vendor/twig/twig/doc/filters/round.rst index 2521cf16aabc8babdd72fda19b780addc029a511..590c71f02708b2cee64d3f9e75f4e62c41c0ed6a 100644 --- a/vendor/twig/twig/doc/filters/round.rst +++ b/vendor/twig/twig/doc/filters/round.rst @@ -6,7 +6,7 @@ The ``round`` filter rounds a number to a given precision: -.. code-block:: jinja +.. code-block:: twig {{ 42.55|round }} {# outputs 43 #} diff --git a/vendor/twig/twig/doc/filters/slice.rst b/vendor/twig/twig/doc/filters/slice.rst index 70bf139e633d671374c6f2b814b28d4fb3f30d62..9a3ca360477875dd44875c6c23c1fca623370740 100644 --- a/vendor/twig/twig/doc/filters/slice.rst +++ b/vendor/twig/twig/doc/filters/slice.rst @@ -6,7 +6,7 @@ The ``slice`` filter extracts a slice of a sequence, a mapping, or a string: -.. code-block:: jinja +.. code-block:: twig {% for i in [1, 2, 3, 4, 5]|slice(1, 2) %} {# will iterate over 2 and 3 #} @@ -18,7 +18,7 @@ The ``slice`` filter extracts a slice of a sequence, a mapping, or a string: You can use any valid expression for both the start and the length: -.. code-block:: jinja +.. code-block:: twig {% for i in [1, 2, 3, 4, 5]|slice(start, length) %} {# ... #} @@ -26,7 +26,7 @@ You can use any valid expression for both the start and the length: As syntactic sugar, you can also use the ``[]`` notation: -.. code-block:: jinja +.. code-block:: twig {% for i in [1, 2, 3, 4, 5][start:length] %} {# ... #} @@ -65,7 +65,7 @@ Arguments * ``length``: The size of the slice * ``preserve_keys``: Whether to preserve key or not (when the input is an array) -.. _`Traversable`: http://php.net/manual/en/class.traversable.php -.. _`array_slice`: http://php.net/array_slice -.. _`mb_substr` : http://php.net/mb-substr -.. _`substr`: http://php.net/substr +.. _`Traversable`: https://secure.php.net/manual/en/class.traversable.php +.. _`array_slice`: https://secure.php.net/array_slice +.. _`mb_substr` : https://secure.php.net/mb-substr +.. _`substr`: https://secure.php.net/substr diff --git a/vendor/twig/twig/doc/filters/sort.rst b/vendor/twig/twig/doc/filters/sort.rst index 350207f8e02b5155c17beda11609570e84d18998..f7c0329fe23e7bea3d46075a9000057e2eddaf68 100644 --- a/vendor/twig/twig/doc/filters/sort.rst +++ b/vendor/twig/twig/doc/filters/sort.rst @@ -3,7 +3,7 @@ The ``sort`` filter sorts an array: -.. code-block:: jinja +.. code-block:: twig {% for user in users|sort %} ... @@ -15,4 +15,4 @@ The ``sort`` filter sorts an array: association. It supports Traversable objects by transforming those to arrays. -.. _`asort`: http://php.net/asort +.. _`asort`: https://secure.php.net/asort diff --git a/vendor/twig/twig/doc/filters/spaceless.rst b/vendor/twig/twig/doc/filters/spaceless.rst new file mode 100644 index 0000000000000000000000000000000000000000..bfc547eac66e16e50ac52e7253d466387b9d3edb --- /dev/null +++ b/vendor/twig/twig/doc/filters/spaceless.rst @@ -0,0 +1,65 @@ +``spaceless`` +============= + +.. versionadded:: 1.38 + + The ``spaceless`` filter was added in Twig 1.38. + +Use the ``spaceless`` filter to remove whitespace *between HTML tags*, not +whitespace within HTML tags or whitespace in plain text: + +.. code-block:: twig + + {{ + "<div> + <strong>foo</strong> + </div> + "|spaceless }} + + {# output will be <div><strong>foo</strong></div> #} + +You can combine ``spaceless`` with the ``apply`` tag to apply the transformation +on large amounts of HTML: + +.. code-block:: twig + + {% apply spaceless %} + <div> + <strong>foo</strong> + </div> + {% endapply %} + + {# output will be <div><strong>foo</strong></div> #} + +.. note:: + + The ``apply`` tag was introduced in Twig 1.40; use the ``filter`` tag with + previous versions. + +This tag is not meant to "optimize" the size of the generated HTML content but +merely to avoid extra whitespace between HTML tags to avoid browser rendering +quirks under some circumstances. + +.. caution:: + + As the filter uses a regular expression behind the scenes, its performance + is directly related to the text size you are working on (remember that + filters are executed at runtime). + +.. tip:: + + If you want to optimize the size of the generated HTML content, gzip + compress the output instead. + +.. tip:: + + If you want to create a tag that actually removes all extra whitespace in + an HTML string, be warned that this is not as easy as it seems to be + (think of ``textarea`` or ``pre`` tags for instance). Using a third-party + library like Tidy is probably a better idea. + +.. tip:: + + For more information on whitespace control, read the + :ref:`dedicated section <templates-whitespace-control>` of the documentation and learn how + you can also use the whitespace control modifier on your tags. diff --git a/vendor/twig/twig/doc/filters/split.rst b/vendor/twig/twig/doc/filters/split.rst index bbc6d798f28688b5638a9e1576529631002526fe..92eedff269b9ed6b721c6ee8ef135f5e876807b7 100644 --- a/vendor/twig/twig/doc/filters/split.rst +++ b/vendor/twig/twig/doc/filters/split.rst @@ -7,22 +7,22 @@ The ``split`` filter splits a string by the given delimiter and returns a list of strings: -.. code-block:: jinja +.. code-block:: twig {% set foo = "one,two,three"|split(',') %} {# foo contains ['one', 'two', 'three'] #} You can also pass a ``limit`` argument: - * If ``limit`` is positive, the returned array will contain a maximum of - limit elements with the last element containing the rest of string; +* If ``limit`` is positive, the returned array will contain a maximum of + limit elements with the last element containing the rest of string; - * If ``limit`` is negative, all components except the last -limit are - returned; +* If ``limit`` is negative, all components except the last -limit are + returned; - * If ``limit`` is zero, then this is treated as 1. +* If ``limit`` is zero, then this is treated as 1. -.. code-block:: jinja +.. code-block:: twig {% set foo = "one,two,three,four,five"|split(',', 3) %} {# foo contains ['one', 'two', 'three,four,five'] #} @@ -30,7 +30,7 @@ You can also pass a ``limit`` argument: If the ``delimiter`` is an empty string, then value will be split by equal chunks. Length is set by the ``limit`` argument (one character by default). -.. code-block:: jinja +.. code-block:: twig {% set foo = "123"|split('') %} {# foo contains ['1', '2', '3'] #} @@ -49,5 +49,5 @@ Arguments * ``delimiter``: The delimiter * ``limit``: The limit argument -.. _`explode`: http://php.net/explode -.. _`str_split`: http://php.net/str_split +.. _`explode`: https://secure.php.net/explode +.. _`str_split`: https://secure.php.net/str_split diff --git a/vendor/twig/twig/doc/filters/striptags.rst b/vendor/twig/twig/doc/filters/striptags.rst index 82953b7b65b35974b50fcc576d8b0b329eee7f2e..62b2a7b3c13662109ba75f95538e45e03ec3ff52 100644 --- a/vendor/twig/twig/doc/filters/striptags.rst +++ b/vendor/twig/twig/doc/filters/striptags.rst @@ -4,13 +4,13 @@ The ``striptags`` filter strips SGML/XML tags and replace adjacent whitespace by one space: -.. code-block:: jinja +.. code-block:: twig {{ some_html|striptags }} You can also provide tags which should not be stripped: -.. code-block:: jinja +.. code-block:: twig {{ some_html|striptags('<br><p>') }} @@ -26,4 +26,4 @@ Arguments * ``allowable_tags``: Tags which should not be stripped -.. _`strip_tags`: http://php.net/strip_tags +.. _`strip_tags`: https://secure.php.net/strip_tags diff --git a/vendor/twig/twig/doc/filters/title.rst b/vendor/twig/twig/doc/filters/title.rst index c5a318e85d2ce9066aa989d2d4fb1b58720f3ef2..dd0311ca3dcd882e8e79dd48c5c0d1e358e86cbd 100644 --- a/vendor/twig/twig/doc/filters/title.rst +++ b/vendor/twig/twig/doc/filters/title.rst @@ -4,7 +4,7 @@ The ``title`` filter returns a titlecased version of the value. Words will start with uppercase letters, all remaining characters are lowercase: -.. code-block:: jinja +.. code-block:: twig {{ 'my first car'|title }} diff --git a/vendor/twig/twig/doc/filters/trim.rst b/vendor/twig/twig/doc/filters/trim.rst index b598363c272b890ec166874cd01f3886dc973ec5..96ce403d3bdb950d7987b5cc30689fad8e9ed811 100644 --- a/vendor/twig/twig/doc/filters/trim.rst +++ b/vendor/twig/twig/doc/filters/trim.rst @@ -10,7 +10,7 @@ The ``trim`` filter strips whitespace (or other characters) from the beginning and end of a string: -.. code-block:: jinja +.. code-block:: twig {{ ' I like Twig. '|trim }} @@ -40,6 +40,6 @@ Arguments * ``side``: The default is to strip from the left and the right (`both`) sides, but `left` and `right` will strip from either the left side or right side only -.. _`trim`: http://php.net/trim -.. _`ltrim`: http://php.net/ltrim -.. _`rtrim`: http://php.net/rtrim +.. _`trim`: https://secure.php.net/trim +.. _`ltrim`: https://secure.php.net/ltrim +.. _`rtrim`: https://secure.php.net/rtrim diff --git a/vendor/twig/twig/doc/filters/upper.rst b/vendor/twig/twig/doc/filters/upper.rst index 561cebe330914af1b87d6832a177bb34b6bfa02f..01c9fbb0b53691a657fa4c3c0b34d8abf1587118 100644 --- a/vendor/twig/twig/doc/filters/upper.rst +++ b/vendor/twig/twig/doc/filters/upper.rst @@ -3,7 +3,7 @@ The ``upper`` filter converts a value to uppercase: -.. code-block:: jinja +.. code-block:: twig {{ 'welcome'|upper }} diff --git a/vendor/twig/twig/doc/filters/url_encode.rst b/vendor/twig/twig/doc/filters/url_encode.rst index 5944e59cd5bb7c9dc205e0db8db87f61837e6e44..df2c1f07b6793e2b9b479f452d738862bac8dbfd 100644 --- a/vendor/twig/twig/doc/filters/url_encode.rst +++ b/vendor/twig/twig/doc/filters/url_encode.rst @@ -11,7 +11,7 @@ The ``url_encode`` filter percent encodes a given string as URL segment or an array as query string: -.. code-block:: jinja +.. code-block:: twig {{ "path-seg*ment"|url_encode }} {# outputs "path-seg%2Ament" #} @@ -29,6 +29,6 @@ or an array as query string: that as of Twig 1.16.0, ``urlencode`` **always** uses ``rawurlencode`` (the ``raw`` argument was removed.) -.. _`urlencode`: http://php.net/urlencode -.. _`rawurlencode`: http://php.net/rawurlencode -.. _`http_build_query`: http://php.net/http_build_query +.. _`urlencode`: https://secure.php.net/urlencode +.. _`rawurlencode`: https://secure.php.net/rawurlencode +.. _`http_build_query`: https://secure.php.net/http_build_query diff --git a/vendor/twig/twig/doc/functions/attribute.rst b/vendor/twig/twig/doc/functions/attribute.rst index ceba96b05ba853bfbb7f4ef48e9472bd5ec0498a..99c08d8bc9be254d398b7f65110f6c8a0ee05ffc 100644 --- a/vendor/twig/twig/doc/functions/attribute.rst +++ b/vendor/twig/twig/doc/functions/attribute.rst @@ -7,7 +7,7 @@ The ``attribute`` function can be used to access a "dynamic" attribute of a variable: -.. code-block:: jinja +.. code-block:: twig {{ attribute(object, method) }} {{ attribute(object, method, arguments) }} @@ -16,7 +16,7 @@ variable: In addition, the ``defined`` test can check for the existence of a dynamic attribute: -.. code-block:: jinja +.. code-block:: twig {{ attribute(object, method) is defined ? 'Method exists' : 'Method does not exist' }} diff --git a/vendor/twig/twig/doc/functions/block.rst b/vendor/twig/twig/doc/functions/block.rst index f5d683c73da628bdabade470f10c354ac5304297..c62614822a6aad0d3c2dcaa0b870fd411269a244 100644 --- a/vendor/twig/twig/doc/functions/block.rst +++ b/vendor/twig/twig/doc/functions/block.rst @@ -10,7 +10,7 @@ When a template uses inheritance and if you want to print a block multiple times, use the ``block`` function: -.. code-block:: jinja +.. code-block:: twig <title>{% block title %}{% endblock %}</title> @@ -18,17 +18,17 @@ times, use the ``block`` function: {% block body %}{% endblock %} -The ``block`` function can also be used to display one block of another +The ``block`` function can also be used to display one block from another template: -.. code-block:: jinja +.. code-block:: twig {{ block("title", "common_blocks.twig") }} Use the ``defined`` test to check if a block exists in the context of the current template: -.. code-block:: jinja +.. code-block:: twig {% if block("footer") is defined %} ... diff --git a/vendor/twig/twig/doc/functions/constant.rst b/vendor/twig/twig/doc/functions/constant.rst index 97aa5c8f3164e1565dc78aa80ee38feffc0d7021..f9d836cd1c6aec17dfc0357ca341af21a110205b 100644 --- a/vendor/twig/twig/doc/functions/constant.rst +++ b/vendor/twig/twig/doc/functions/constant.rst @@ -9,20 +9,20 @@ ``constant`` returns the constant value for a given string: -.. code-block:: jinja +.. code-block:: twig {{ some_date|date(constant('DATE_W3C')) }} {{ constant('Namespace\\Classname::CONSTANT_NAME') }} As of 1.12.1 you can read constants from object instances as well: -.. code-block:: jinja +.. code-block:: twig {{ constant('RSS', date) }} Use the ``defined`` test to check if a constant is defined: -.. code-block:: jinja +.. code-block:: twig {% if constant('SOME_CONST') is defined %} ... diff --git a/vendor/twig/twig/doc/functions/cycle.rst b/vendor/twig/twig/doc/functions/cycle.rst index e34349323a2bb31a078337b6a5dffc7fba282834..84cff6a1d5a2d0e3794938389bac92880da54dae 100644 --- a/vendor/twig/twig/doc/functions/cycle.rst +++ b/vendor/twig/twig/doc/functions/cycle.rst @@ -3,7 +3,7 @@ The ``cycle`` function cycles on an array of values: -.. code-block:: jinja +.. code-block:: twig {% set start_year = date() | date('Y') %} {% set end_year = start_year + 5 %} @@ -14,7 +14,7 @@ The ``cycle`` function cycles on an array of values: The array can contain any number of values: -.. code-block:: jinja +.. code-block:: twig {% set fruits = ['apple', 'orange', 'citrus'] %} diff --git a/vendor/twig/twig/doc/functions/date.rst b/vendor/twig/twig/doc/functions/date.rst index 158dd6a65452630316d66753fb1d52afe51caf60..b88f66935c30d13f2df7c960cb03b75b5a2e54ce 100644 --- a/vendor/twig/twig/doc/functions/date.rst +++ b/vendor/twig/twig/doc/functions/date.rst @@ -9,7 +9,7 @@ Converts an argument to a date to allow date comparison: -.. code-block:: jinja +.. code-block:: twig {% if date(user.created_at) < date('-2days') %} {# do something #} @@ -19,7 +19,7 @@ The argument must be in one of PHP’s supported `date and time formats`_. You can pass a timezone as the second argument: -.. code-block:: jinja +.. code-block:: twig {% if date(user.created_at) < date('-2days', 'Europe/Paris') %} {# do something #} @@ -27,7 +27,7 @@ You can pass a timezone as the second argument: If no argument is passed, the function returns the current date: -.. code-block:: jinja +.. code-block:: twig {% if date(user.created_at) < date() %} {# always! #} @@ -40,8 +40,8 @@ If no argument is passed, the function returns the current date: .. code-block:: php - $twig = new Twig_Environment($loader); - $twig->getExtension('Twig_Extension_Core')->setTimezone('Europe/Paris'); + $twig = new \Twig\Environment($loader); + $twig->getExtension('\Twig\Extension\CoreExtension')->setTimezone('Europe/Paris'); // before Twig 1.26 $twig->getExtension('core')->setTimezone('Europe/Paris'); @@ -52,4 +52,4 @@ Arguments * ``date``: The date * ``timezone``: The timezone -.. _`date and time formats`: http://php.net/manual/en/datetime.formats.php +.. _`date and time formats`: https://secure.php.net/manual/en/datetime.formats.php diff --git a/vendor/twig/twig/doc/functions/dump.rst b/vendor/twig/twig/doc/functions/dump.rst index a231f089e25a880c76c02bc631634ddb9e65024e..b7c01e7e3418aea6813abeb1efa43b2e57f36856 100644 --- a/vendor/twig/twig/doc/functions/dump.rst +++ b/vendor/twig/twig/doc/functions/dump.rst @@ -8,21 +8,21 @@ The ``dump`` function dumps information about a template variable. This is mostly useful to debug a template that does not behave as expected by introspecting its variables: -.. code-block:: jinja +.. code-block:: twig {{ dump(user) }} .. note:: The ``dump`` function is not available by default. You must add the - ``Twig_Extension_Debug`` extension explicitly when creating your Twig + ``\Twig\Extension\DebugExtension`` extension explicitly when creating your Twig environment:: - $twig = new Twig_Environment($loader, array( + $twig = new \Twig\Environment($loader, [ 'debug' => true, // ... - )); - $twig->addExtension(new Twig_Extension_Debug()); + ]); + $twig->addExtension(new \Twig\Extension\DebugExtension()); Even when enabled, the ``dump`` function won't display anything if the ``debug`` option on the environment is not enabled (to avoid leaking debug @@ -31,7 +31,7 @@ introspecting its variables: In an HTML context, wrap the output with a ``pre`` tag to make it easier to read: -.. code-block:: jinja +.. code-block:: twig <pre> {{ dump(user) }} @@ -45,14 +45,14 @@ read: You can debug several variables by passing them as additional arguments: -.. code-block:: jinja +.. code-block:: twig {{ dump(user, categories) }} If you don't pass any value, all variables from the current context are dumped: -.. code-block:: jinja +.. code-block:: twig {{ dump() }} @@ -65,5 +65,5 @@ Arguments * ``context``: The context to dump -.. _`XDebug`: http://xdebug.org/docs/display -.. _`var_dump`: http://php.net/var_dump +.. _`XDebug`: https://xdebug.org/docs/display +.. _`var_dump`: https://secure.php.net/var_dump diff --git a/vendor/twig/twig/doc/functions/include.rst b/vendor/twig/twig/doc/functions/include.rst index 2f88ed77608129d40f61df15a216bcfc1f935547..8af4790b3cda47692242d008e58dc4b517d1bb3e 100644 --- a/vendor/twig/twig/doc/functions/include.rst +++ b/vendor/twig/twig/doc/functions/include.rst @@ -6,7 +6,7 @@ The ``include`` function returns the rendered content of a template: -.. code-block:: jinja +.. code-block:: twig {{ include('template.html') }} {{ include(some_var) }} @@ -19,7 +19,7 @@ paths defined by it. The context is passed by default to the template but you can also pass additional variables: -.. code-block:: jinja +.. code-block:: twig {# template.html will have access to the variables from the current context and the additional ones provided #} {{ include('template.html', {foo: 'bar'}) }} @@ -27,18 +27,18 @@ additional variables: You can disable access to the context by setting ``with_context`` to ``false``: -.. code-block:: jinja +.. code-block:: twig {# only the foo variable will be accessible #} {{ include('template.html', {foo: 'bar'}, with_context = false) }} -.. code-block:: jinja +.. code-block:: twig {# no variables will be accessible #} {{ include('template.html', with_context = false) }} -And if the expression evaluates to a ``Twig_Template`` or a -``Twig_TemplateWrapper`` instance, Twig will use it directly:: +And if the expression evaluates to a ``\Twig\Template`` or a +``\Twig\TemplateWrapper`` instance, Twig will use it directly:: // {{ include(template) }} @@ -48,19 +48,19 @@ And if the expression evaluates to a ``Twig_Template`` or a // as of Twig 1.28 $template = $twig->load('some_template.twig'); - $twig->display('template.twig', array('template' => $template)); + $twig->display('template.twig', ['template' => $template]); When you set the ``ignore_missing`` flag, Twig will return an empty string if the template does not exist: -.. code-block:: jinja +.. code-block:: twig {{ include('sidebar.html', ignore_missing = true) }} You can also provide a list of templates that are checked for existence before inclusion. The first template that exists will be rendered: -.. code-block:: jinja +.. code-block:: twig {{ include(['page_detailed.html', 'page.html']) }} @@ -70,7 +70,7 @@ of the templates exist, otherwise it will throw an exception. When including a template created by an end user, you should consider sandboxing it: -.. code-block:: jinja +.. code-block:: twig {{ include('page.html', sandboxed = true) }} diff --git a/vendor/twig/twig/doc/functions/max.rst b/vendor/twig/twig/doc/functions/max.rst index 6f3cfc535233bfba4399b720f2ac6c3f09d65a8f..f271e666dce8887df2bc32d64060c50e28015eec 100644 --- a/vendor/twig/twig/doc/functions/max.rst +++ b/vendor/twig/twig/doc/functions/max.rst @@ -6,14 +6,14 @@ ``max`` returns the biggest value of a sequence or a set of values: -.. code-block:: jinja +.. code-block:: twig {{ max(1, 3, 2) }} {{ max([1, 3, 2]) }} When called with a mapping, max ignores keys and only compares values: -.. code-block:: jinja +.. code-block:: twig {{ max({2: "e", 1: "a", 3: "b", 5: "d", 4: "c"}) }} {# returns "e" #} diff --git a/vendor/twig/twig/doc/functions/min.rst b/vendor/twig/twig/doc/functions/min.rst index 7b6a65e103316c5e205ee27159fb8f2a05aebcb2..362b0f945d411d75e66c6b162ad660b1ecfbfd3d 100644 --- a/vendor/twig/twig/doc/functions/min.rst +++ b/vendor/twig/twig/doc/functions/min.rst @@ -6,14 +6,14 @@ ``min`` returns the lowest value of a sequence or a set of values: -.. code-block:: jinja +.. code-block:: twig {{ min(1, 3, 2) }} {{ min([1, 3, 2]) }} When called with a mapping, min ignores keys and only compares values: -.. code-block:: jinja +.. code-block:: twig {{ min({2: "e", 3: "a", 1: "b", 5: "d", 4: "c"}) }} {# returns "a" #} diff --git a/vendor/twig/twig/doc/functions/parent.rst b/vendor/twig/twig/doc/functions/parent.rst index f5bd200106ecd6a9ab35db11678d794eed44484a..9beb5d21cf97233f5f41b08143033f2c998aecd2 100644 --- a/vendor/twig/twig/doc/functions/parent.rst +++ b/vendor/twig/twig/doc/functions/parent.rst @@ -4,7 +4,7 @@ When a template uses inheritance, it's possible to render the contents of the parent block when overriding a block by using the ``parent`` function: -.. code-block:: jinja +.. code-block:: twig {% extends "base.html" %} diff --git a/vendor/twig/twig/doc/functions/random.rst b/vendor/twig/twig/doc/functions/random.rst index 168e74f8f7dcd63b6874119a7a089c309b423879..45e6fa797687eaa2e14de529ffa4526c1282f0ec 100644 --- a/vendor/twig/twig/doc/functions/random.rst +++ b/vendor/twig/twig/doc/functions/random.rst @@ -7,23 +7,30 @@ .. versionadded:: 1.6 String and integer handling was added in Twig 1.6. +.. versionadded:: 1.38 + The "max" argument was added in Twig 1.38. + The ``random`` function returns a random value depending on the supplied parameter type: * a random item from a sequence; * a random character from a string; * a random integer between 0 and the integer parameter (inclusive). +* a random integer between the integer parameter (when negative) and 0 (inclusive). +* a random integer between the first integer and the second integer parameter (inclusive). -.. code-block:: jinja +.. code-block:: twig {{ random(['apple', 'orange', 'citrus']) }} {# example output: orange #} {{ random('ABC') }} {# example output: C #} {{ random() }} {# example output: 15386094 (works as the native PHP mt_rand function) #} {{ random(5) }} {# example output: 3 #} + {{ random(50, 100) }} {# example output: 63 #} Arguments --------- * ``values``: The values +* ``max``: The max value when values is an integer -.. _`mt_rand`: http://php.net/mt_rand +.. _`mt_rand`: https://secure.php.net/mt_rand diff --git a/vendor/twig/twig/doc/functions/range.rst b/vendor/twig/twig/doc/functions/range.rst index 5c9db08928dd62e601feaad47d6e2bf14dcc1a85..a1f0e7c097d5ed4afe937a181cc95754406f5514 100644 --- a/vendor/twig/twig/doc/functions/range.rst +++ b/vendor/twig/twig/doc/functions/range.rst @@ -3,7 +3,7 @@ Returns a list containing an arithmetic progression of integers: -.. code-block:: jinja +.. code-block:: twig {% for i in range(0, 3) %} {{ i }}, @@ -14,7 +14,7 @@ Returns a list containing an arithmetic progression of integers: When step is given (as the third parameter), it specifies the increment (or decrement for negative values): -.. code-block:: jinja +.. code-block:: twig {% for i in range(0, 6, 2) %} {{ i }}, @@ -27,7 +27,7 @@ decrement for negative values): Note that if the start is greater than the end, ``range`` assumes a step of ``-1``: - .. code-block:: jinja + .. code-block:: twig {% for i in range(3, 0) %} {{ i }}, @@ -38,7 +38,7 @@ decrement for negative values): The Twig built-in ``..`` operator is just syntactic sugar for the ``range`` function (with a step of ``1``, or ``-1`` if the start is greater than the end): -.. code-block:: jinja +.. code-block:: twig {% for i in 0..3 %} {{ i }}, @@ -55,4 +55,4 @@ Arguments * ``high``: The highest possible value of the sequence. * ``step``: The increment between elements of the sequence. -.. _`range`: http://php.net/range +.. _`range`: https://secure.php.net/range diff --git a/vendor/twig/twig/doc/functions/source.rst b/vendor/twig/twig/doc/functions/source.rst index 3c921b1cf983b954b329b8eb4a83a810ce269a9a..571fea27fc7b2546670f3b29737538202febbf80 100644 --- a/vendor/twig/twig/doc/functions/source.rst +++ b/vendor/twig/twig/doc/functions/source.rst @@ -9,7 +9,7 @@ The ``source`` function returns the content of a template without rendering it: -.. code-block:: jinja +.. code-block:: twig {{ source('template.html') }} {{ source(some_var) }} @@ -17,7 +17,7 @@ The ``source`` function returns the content of a template without rendering it: When you set the ``ignore_missing`` flag, Twig will return an empty string if the template does not exist: -.. code-block:: jinja +.. code-block:: twig {{ source('template.html', ignore_missing = true) }} diff --git a/vendor/twig/twig/doc/functions/template_from_string.rst b/vendor/twig/twig/doc/functions/template_from_string.rst index ce6a60dc0b8d7b5f6f7ce50fba91fda95200908c..b26f5664bc995b3156314b6a71c2aa766558c02f 100644 --- a/vendor/twig/twig/doc/functions/template_from_string.rst +++ b/vendor/twig/twig/doc/functions/template_from_string.rst @@ -4,21 +4,31 @@ .. versionadded:: 1.11 The ``template_from_string`` function was added in Twig 1.11. +.. versionadded:: 1.39 + The name argument was added in Twig 1.39. + The ``template_from_string`` function loads a template from a string: -.. code-block:: jinja +.. code-block:: twig {{ include(template_from_string("Hello {{ name }}")) }} {{ include(template_from_string(page.template)) }} +To ease debugging, you can also give the template a name that will be part of +any related error message: + +.. code-block:: twig + + {{ include(template_from_string(page.template, "template for page " ~ page.name)) }} + .. note:: The ``template_from_string`` function is not available by default. You - must add the ``Twig_Extension_StringLoader`` extension explicitly when + must add the ``\Twig\Extension\StringLoaderExtension`` extension explicitly when creating your Twig environment:: - $twig = new Twig_Environment(...); - $twig->addExtension(new Twig_Extension_StringLoader()); + $twig = new \Twig\Environment(...); + $twig->addExtension(new \Twig\Extension\StringLoaderExtension()); .. note:: @@ -30,3 +40,4 @@ Arguments --------- * ``template``: The template +* ``name``: A name for the template diff --git a/vendor/twig/twig/doc/installation.rst b/vendor/twig/twig/doc/installation.rst index afdcf16593b23ea37e050dd4b34a8a3be7679e47..362d3177978fe9d20e71ff8c541d866d02bf5444 100644 --- a/vendor/twig/twig/doc/installation.rst +++ b/vendor/twig/twig/doc/installation.rst @@ -6,42 +6,11 @@ You have multiple ways to install Twig. Installing the Twig PHP package ------------------------------- -Installing via Composer (recommended) -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -Install `Composer`_ and run the following command to get the latest version: - -.. code-block:: bash - - composer require twig/twig:~1.0 - -Installing from the tarball release -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -1. Download the most recent tarball from the `download page`_ -2. Verify the integrity of the tarball http://fabien.potencier.org/article/73/signing-project-releases -3. Unpack the tarball -4. Move the files somewhere in your project - -Installing the development version -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. code-block:: bash - - git clone git://github.com/twigphp/Twig.git - -Installing the PEAR package -~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -.. note:: - - Using PEAR for installing Twig is deprecated and Twig 1.15.1 was the last - version published on the PEAR channel; use Composer instead. +Install `Composer`_ and run the following command: .. code-block:: bash - pear channel-discover pear.twig-project.org - pear install twig/Twig + composer require "twig/twig:^1.0" Installing the C extension -------------------------- @@ -49,15 +18,16 @@ Installing the C extension .. versionadded:: 1.4 The C extension was added in Twig 1.4. -.. note:: +Twig comes with an **optional** C extension that improves the performance of the +Twig runtime engine. + +Note that this extension does not replace the PHP code but only provides an +optimized version of the ``\Twig\Template::getAttribute()`` method; you must +still install the regular PHP code - The C extension is **optional** but it brings some nice performance - improvements. Note that the extension is not a replacement for the PHP - code; it only implements a small part of the PHP code to improve the - performance at runtime; you must still install the regular PHP code. +The C extension is only compatible and useful for **PHP5**. -Twig comes with a C extension that enhances the performance of the Twig -runtime engine; install it like any other PHP extensions: +Install it like any other PHP extensions: .. code-block:: bash @@ -67,17 +37,6 @@ runtime engine; install it like any other PHP extensions: make make install -.. note:: - - You can also install the C extension via PEAR (note that this method is - deprecated and newer versions of Twig are not available on the PEAR - channel): - - .. code-block:: bash - - pear channel-discover pear.twig-project.org - pear install twig/CTwig - For Windows: 1. Setup the build environment following the `PHP documentation`_ @@ -102,15 +61,13 @@ Finally, enable the extension in your ``php.ini`` configuration file: .. code-block:: ini - extension=twig.so #For Unix systems - extension=php_twig.dll #For Windows systems + extension=twig.so # For Unix systems + extension=php_twig.dll # For Windows systems And from now on, Twig will automatically compile your templates to take -advantage of the C extension. Note that this extension does not replace the -PHP code but only provides an optimized version of the -``Twig_Template::getAttribute()`` method. +advantage of the C extension. .. _`download page`: https://github.com/twigphp/Twig/tags .. _`Composer`: https://getcomposer.org/download/ .. _`PHP documentation`: https://wiki.php.net/internals/windows/stepbystepbuild -.. _`Zend Server FAQ`: http://www.zend.com/en/products/server/faq#faqD6 +.. _`Zend Server FAQ`: https://www.zend.com/en/products/server/faq#faqD6 diff --git a/vendor/twig/twig/doc/internals.rst b/vendor/twig/twig/doc/internals.rst index fec65e00ea6aa340d404acc7972564749413da2c..ba908d496ca863b44be214114ef7601af8e66043 100644 --- a/vendor/twig/twig/doc/internals.rst +++ b/vendor/twig/twig/doc/internals.rst @@ -1,7 +1,7 @@ Twig Internals ============== -Twig is very extensible and you can easily hack it. Keep in mind that you +Twig is very extensible and you can hack it. Keep in mind that you should probably try to create an extension before hacking the core, as most features and enhancements can be handled with extensions. This chapter is also useful for people who want to understand how Twig works under the hood. @@ -16,38 +16,40 @@ The rendering of a Twig template can be summarized into four key steps: * First, the **lexer** tokenizes the template source code into small pieces for easier processing; + * Then, the **parser** converts the token stream into a meaningful tree of nodes (the Abstract Syntax Tree); - * Eventually, the *compiler* transforms the AST into PHP code. -* **Evaluate** the template: It basically means calling the ``display()`` + * Finally, the *compiler* transforms the AST into PHP code. + +* **Evaluate** the template: It means calling the ``display()`` method of the compiled template and passing it the context. The Lexer --------- The lexer tokenizes a template source code into a token stream (each token is -an instance of ``Twig_Token``, and the stream is an instance of -``Twig_TokenStream``). The default lexer recognizes 13 different token types: - -* ``Twig_Token::BLOCK_START_TYPE``, ``Twig_Token::BLOCK_END_TYPE``: Delimiters for blocks (``{% %}``) -* ``Twig_Token::VAR_START_TYPE``, ``Twig_Token::VAR_END_TYPE``: Delimiters for variables (``{{ }}``) -* ``Twig_Token::TEXT_TYPE``: A text outside an expression; -* ``Twig_Token::NAME_TYPE``: A name in an expression; -* ``Twig_Token::NUMBER_TYPE``: A number in an expression; -* ``Twig_Token::STRING_TYPE``: A string in an expression; -* ``Twig_Token::OPERATOR_TYPE``: An operator; -* ``Twig_Token::PUNCTUATION_TYPE``: A punctuation sign; -* ``Twig_Token::INTERPOLATION_START_TYPE``, ``Twig_Token::INTERPOLATION_END_TYPE`` (as of Twig 1.5): Delimiters for string interpolation; -* ``Twig_Token::EOF_TYPE``: Ends of template. +an instance of ``\Twig\Token``, and the stream is an instance of +``\Twig\TokenStream``). The default lexer recognizes 13 different token types: + +* ``\Twig\Token::BLOCK_START_TYPE``, ``\Twig\Token::BLOCK_END_TYPE``: Delimiters for blocks (``{% %}``) +* ``\Twig\Token::VAR_START_TYPE``, ``\Twig\Token::VAR_END_TYPE``: Delimiters for variables (``{{ }}``) +* ``\Twig\Token::TEXT_TYPE``: A text outside an expression; +* ``\Twig\Token::NAME_TYPE``: A name in an expression; +* ``\Twig\Token::NUMBER_TYPE``: A number in an expression; +* ``\Twig\Token::STRING_TYPE``: A string in an expression; +* ``\Twig\Token::OPERATOR_TYPE``: An operator; +* ``\Twig\Token::PUNCTUATION_TYPE``: A punctuation sign; +* ``\Twig\Token::INTERPOLATION_START_TYPE``, ``\Twig\Token::INTERPOLATION_END_TYPE`` (as of Twig 1.5): Delimiters for string interpolation; +* ``\Twig\Token::EOF_TYPE``: Ends of template. You can manually convert a source code into a token stream by calling the ``tokenize()`` method of an environment:: - $stream = $twig->tokenize(new Twig_Source($source, $identifier)); + $stream = $twig->tokenize(new \Twig\Source($source, $identifier)); .. versionadded:: 1.27 - ``Twig_Source`` was introduced in version 1.27, pass the source and the + ``\Twig\Source`` was introduced in version 1.27, pass the source and the identifier directly on previous versions. As the stream has a ``__toString()`` method, you can have a textual @@ -67,7 +69,7 @@ Here is the output for the ``Hello {{ name }}`` template: .. note:: - The default lexer (``Twig_Lexer``) can be changed by calling + The default lexer (``\Twig\Lexer``) can be changed by calling the ``setLexer()`` method:: $twig->setLexer($lexer); @@ -76,7 +78,7 @@ The Parser ---------- The parser converts the token stream into an AST (Abstract Syntax Tree), or a -node tree (an instance of ``Twig_Node_Module``). The core extension defines +node tree (an instance of ``\Twig\Node\ModuleNode``). The core extension defines the basic nodes like: ``for``, ``if``, ... and the expression nodes. You can manually convert a token stream into a node tree by calling the @@ -92,16 +94,16 @@ Here is the output for the ``Hello {{ name }}`` template: .. code-block:: text - Twig_Node_Module( - Twig_Node_Text(Hello ) - Twig_Node_Print( - Twig_Node_Expression_Name(name) + \Twig\Node\ModuleNode( + \Twig\Node\TextNode(Hello ) + \Twig\Node\PrintNode( + \Twig\Node\Expression\NameExpression(name) ) ) .. note:: - The default parser (``Twig_TokenParser``) can be changed by calling the + The default parser (``\Twig\TokenParser\AbstractTokenParser``) can be changed by calling the ``setParser()`` method:: $twig->setParser($parser); @@ -122,9 +124,9 @@ The generated template for a ``Hello {{ name }}`` template reads as follows using):: /* Hello {{ name }} */ - class __TwigTemplate_1121b6f109fe93ebe8c6e22e3712bceb extends Twig_Template + class __TwigTemplate_1121b6f109fe93ebe8c6e22e3712bceb extends \Twig\Template { - protected function doDisplay(array $context, array $blocks = array()) + protected function doDisplay(array $context, array $blocks = []) { // line 1 echo "Hello "; @@ -136,7 +138,7 @@ using):: .. note:: - The default compiler (``Twig_Compiler``) can be changed by calling the + The default compiler (``\Twig\Compiler``) can be changed by calling the ``setCompiler()`` method:: $twig->setCompiler($compiler); diff --git a/vendor/twig/twig/doc/intro.rst b/vendor/twig/twig/doc/intro.rst index d631430f7bff6c2f8412fd57e5eb47a81265cd8c..1f52c80a899eaf20445bced3c10fd7e4c20eb78f 100644 --- a/vendor/twig/twig/doc/intro.rst +++ b/vendor/twig/twig/doc/intro.rst @@ -1,13 +1,11 @@ Introduction ============ -This is the documentation for Twig, the flexible, fast, and secure template +Welcome to the documentation for Twig, the flexible, fast, and secure template engine for PHP. -If you have any exposure to other text-based template languages, such as -Smarty, Django, or Jinja, you should feel right at home with Twig. It's both -designer and developer friendly by sticking to PHP's principles and adding -functionality useful for templating environments. +Twig is both designer and developer friendly by sticking to PHP's principles and +adding functionality useful for templating environments. The key-features are... @@ -22,14 +20,13 @@ The key-features are... developer to define their own custom tags and filters, and to create their own DSL. Twig is used by many Open-Source projects like Symfony, Drupal8, eZPublish, -phpBB, Piwik, OroCRM; and many frameworks have support for it as well like -Slim, Yii, Laravel, Codeigniter and Kohana — just to name a few. +phpBB, Matomo, OroCRM; and many frameworks have support for it as well like +Slim, Yii, Laravel, and Codeigniter — just to name a few. Prerequisites ------------- -Twig needs at least **PHP 5.2.7** to run. As of 1.34, the minimum requirement -was bumped to **PHP 5.3.3**. +Twig needs at least **PHP 5.5.0** to run. Installation ------------ @@ -38,7 +35,7 @@ The recommended way to install Twig is via Composer: .. code-block:: bash - composer require "twig/twig:~1.0" + composer require "twig/twig:^1.0" .. note:: @@ -55,15 +52,15 @@ This section gives you a brief introduction to the PHP API for Twig. require_once '/path/to/vendor/autoload.php'; - $loader = new Twig_Loader_Array(array( + $loader = new \Twig\Loader\ArrayLoader([ 'index' => 'Hello {{ name }}!', - )); - $twig = new Twig_Environment($loader); + ]); + $twig = new \Twig\Environment($loader); - echo $twig->render('index', array('name' => 'Fabien')); + echo $twig->render('index', ['name' => 'Fabien']); -Twig uses a loader (``Twig_Loader_Array``) to locate templates, and an -environment (``Twig_Environment``) to store the configuration. +Twig uses a loader (``\Twig\Loader\ArrayLoader``) to locate templates, and an +environment (``\Twig\Environment``) to store its configuration. The ``render()`` method loads the template passed as a first argument and renders it with the variables passed as a second argument. @@ -71,16 +68,9 @@ renders it with the variables passed as a second argument. As templates are generally stored on the filesystem, Twig also comes with a filesystem loader:: - $loader = new Twig_Loader_Filesystem('/path/to/templates'); - $twig = new Twig_Environment($loader, array( + $loader = new \Twig\Loader\FilesystemLoader('/path/to/templates'); + $twig = new \Twig\Environment($loader, [ 'cache' => '/path/to/compilation_cache', - )); + ]); - echo $twig->render('index.html', array('name' => 'Fabien')); - -.. tip:: - - If you are not using Composer, use the Twig built-in autoloader:: - - require_once '/path/to/lib/Twig/Autoloader.php'; - Twig_Autoloader::register(); + echo $twig->render('index.html', ['name' => 'Fabien']); diff --git a/vendor/twig/twig/doc/recipes.rst b/vendor/twig/twig/doc/recipes.rst index b3ba7f4d7bc60cfb382e1a19d7377d12d6a016c5..7e72b716443edadf40e93666b3cfd5f9952d2fca 100644 --- a/vendor/twig/twig/doc/recipes.rst +++ b/vendor/twig/twig/doc/recipes.rst @@ -13,14 +13,14 @@ Deprecated features generate deprecation notices (via a call to the ``trigger_error()`` PHP function). By default, they are silenced and never displayed nor logged. -To easily remove all deprecated feature usages from your templates, write and -run a script along the lines of the following:: +To remove all deprecated feature usages from your templates, write and run a +script along the lines of the following:: require_once __DIR__.'/vendor/autoload.php'; $twig = create_your_twig_env(); - $deprecations = new Twig_Util_DeprecationCollector($twig); + $deprecations = new \Twig\Util\DeprecationCollector($twig); print_r($deprecations->collectDir(__DIR__.'/templates')); @@ -32,13 +32,13 @@ catches deprecation notices, and return them. If your templates are not stored on the filesystem, use the ``collect()`` method instead. ``collect()`` takes a ``Traversable`` which must return template names as keys and template contents as values (as done by - ``Twig_Util_TemplateDirIterator``). + ``\Twig\Util\TemplateDirIterator``). However, this code won't find all deprecations (like using deprecated some Twig classes). To catch all notices, register a custom error handler like the one below:: - $deprecations = array(); + $deprecations = []; set_error_handler(function ($type, $msg) use (&$deprecations) { if (E_USER_DEPRECATED === $type) { $deprecations[] = $msg; @@ -57,7 +57,7 @@ they won't be generated when templates are already cached. If you want to manage the deprecation notices from your PHPUnit tests, have a look at the `symfony/phpunit-bridge <https://github.com/symfony/phpunit-bridge>`_ package, which eases the - process a lot. + process. Making a Layout conditional --------------------------- @@ -67,7 +67,7 @@ and sometimes decorated with a layout. As Twig layout template names can be any valid expression, you can pass a variable that evaluates to ``true`` when the request is made via Ajax and choose the layout accordingly: -.. code-block:: jinja +.. code-block:: twig {% extends request.ajax ? "base_ajax.html" : "base.html" %} @@ -81,7 +81,7 @@ Making an Include dynamic When including a template, its name does not need to be a string. For instance, the name can depend on the value of a variable: -.. code-block:: jinja +.. code-block:: twig {% include var ~ '_foo.html' %} @@ -91,7 +91,7 @@ rendered. As a matter of fact, the template name can be any valid expression, such as the following: -.. code-block:: jinja +.. code-block:: twig {% include var|default('index') ~ '_foo.html' %} @@ -114,7 +114,7 @@ Let's say that your templates are loaded from both ``.../templates/mysite`` and ``.../templates/default`` in this order. The ``page.twig`` template, stored in ``.../templates/default`` reads as follows: -.. code-block:: jinja +.. code-block:: twig {# page.twig #} {% extends "layout.twig" %} @@ -126,12 +126,12 @@ You can replace this template by putting a file with the same name in ``.../templates/mysite``. And if you want to extend the original template, you might be tempted to write the following: -.. code-block:: jinja +.. code-block:: twig {# page.twig in .../templates/mysite #} {% extends "page.twig" %} {# from .../templates/default #} -Of course, this will not work as Twig will always load the template from +However, this will not work as Twig will always load the template from ``.../templates/mysite``. It turns out it is possible to get this to work, by adding a directory right @@ -142,7 +142,7 @@ time you will use the "normal" paths, but in the special case of wanting to extend a template with an overriding version of itself we can reference its parent's full, unambiguous template path in the extends tag: -.. code-block:: jinja +.. code-block:: twig {# page.twig in .../templates/mysite #} {% extends "default/page.twig" %} {# from .../templates #} @@ -150,50 +150,50 @@ parent's full, unambiguous template path in the extends tag: .. note:: This recipe was inspired by the following Django wiki page: - http://code.djangoproject.com/wiki/ExtendingTemplates + https://code.djangoproject.com/wiki/ExtendingTemplates Customizing the Syntax ---------------------- -Twig allows some syntax customization for the block delimiters. It's not +Twig allows some syntax customization for the block delimiters. It's **not** recommended to use this feature as templates will be tied with your custom syntax. But for specific projects, it can make sense to change the defaults. To change the block delimiters, you need to create your own lexer object:: - $twig = new Twig_Environment(); + $twig = new \Twig\Environment(); - $lexer = new Twig_Lexer($twig, array( - 'tag_comment' => array('{#', '#}'), - 'tag_block' => array('{%', '%}'), - 'tag_variable' => array('{{', '}}'), - 'interpolation' => array('#{', '}'), - )); + $lexer = new \Twig\Lexer($twig, [ + 'tag_comment' => ['{#', '#}'], + 'tag_block' => ['{%', '%}'], + 'tag_variable' => ['{{', '}}'], + 'interpolation' => ['#{', '}'], + ]); $twig->setLexer($lexer); Here are some configuration example that simulates some other template engines syntax:: // Ruby erb syntax - $lexer = new Twig_Lexer($twig, array( - 'tag_comment' => array('<%#', '%>'), - 'tag_block' => array('<%', '%>'), - 'tag_variable' => array('<%=', '%>'), - )); + $lexer = new \Twig\Lexer($twig, [ + 'tag_comment' => ['<%#', '%>'], + 'tag_block' => ['<%', '%>'], + 'tag_variable' => ['<%=', '%>'], + ]); // SGML Comment Syntax - $lexer = new Twig_Lexer($twig, array( - 'tag_comment' => array('<!--#', '-->'), - 'tag_block' => array('<!--', '-->'), - 'tag_variable' => array('${', '}'), - )); + $lexer = new \Twig\Lexer($twig, [ + 'tag_comment' => ['<!--#', '-->'], + 'tag_block' => ['<!--', '-->'], + 'tag_variable' => ['${', '}'], + ]); // Smarty like - $lexer = new Twig_Lexer($twig, array( - 'tag_comment' => array('{*', '*}'), - 'tag_block' => array('{', '}'), - 'tag_variable' => array('{$', '}'), - )); + $lexer = new \Twig\Lexer($twig, [ + 'tag_comment' => ['{*', '*}'], + 'tag_block' => ['{', '}'], + 'tag_variable' => ['{$', '}'], + ]); Using dynamic Object Properties ------------------------------- @@ -202,7 +202,7 @@ When Twig encounters a variable like ``article.title``, it tries to find a ``title`` public property in the ``article`` object. It also works if the property does not exist but is rather defined dynamically -thanks to the magic ``__get()`` method; you just need to also implement the +thanks to the magic ``__get()`` method; you need to also implement the ``__isset()`` magic method like shown in the following snippet of code:: class Article @@ -233,16 +233,16 @@ Sometimes, when using nested loops, you need to access the parent context. The parent context is always accessible via the ``loop.parent`` variable. For instance, if you have the following template data:: - $data = array( - 'topics' => array( - 'topic1' => array('Message 1 of topic 1', 'Message 2 of topic 1'), - 'topic2' => array('Message 1 of topic 2', 'Message 2 of topic 2'), - ), - ); + $data = [ + 'topics' => [ + 'topic1' => ['Message 1 of topic 1', 'Message 2 of topic 1'], + 'topic2' => ['Message 1 of topic 2', 'Message 2 of topic 2'], + ], + ]; And the following template to display all messages in all topics: -.. code-block:: jinja +.. code-block:: twig {% for topic, messages in topics %} * {{ loop.index }}: {{ topic }} @@ -270,7 +270,7 @@ Defining undefined Functions and Filters on the Fly --------------------------------------------------- When a function (or a filter) is not defined, Twig defaults to throw a -``Twig_Error_Syntax`` exception. However, it can also call a `callback`_ (any +``\Twig\Error\SyntaxError`` exception. However, it can also call a `callback`_ (any valid PHP callable) which should return a function (or a filter). For filters, register callbacks with ``registerUndefinedFilterCallback()``. @@ -280,7 +280,7 @@ For functions, use ``registerUndefinedFunctionCallback()``:: // don't try this at home as it's not secure at all! $twig->registerUndefinedFunctionCallback(function ($name) { if (function_exists($name)) { - return new Twig_SimpleFunction($name, $name); + return new \Twig\TwigFunction($name, $name); } return false; @@ -306,10 +306,10 @@ saving it. If the template code is stored in a `$template` variable, here is how you can do it:: try { - $twig->parse($twig->tokenize(new Twig_Source($template))); + $twig->parse($twig->tokenize(new \Twig\Source($template))); // the $template is valid - } catch (Twig_Error_Syntax $e) { + } catch (\Twig\Error\SyntaxError $e) { // $template contains one or more syntax errors } @@ -318,16 +318,16 @@ If you iterate over a set of files, you can pass the filename to the foreach ($files as $file) { try { - $twig->parse($twig->tokenize(new Twig_Source($template, $file->getFilename(), $file))); + $twig->parse($twig->tokenize(new \Twig\Source($template, $file->getFilename(), $file))); // the $template is valid - } catch (Twig_Error_Syntax $e) { + } catch (\Twig\Error\SyntaxError $e) { // $template contains one or more syntax errors } } .. versionadded:: 1.27 - ``Twig_Source`` was introduced in version 1.27, pass the source and the + ``\Twig\Source`` was introduced in version 1.27, pass the source and the identifier directly on previous versions. .. note:: @@ -345,23 +345,23 @@ cache won't update the cache. To get around this, force Twig to invalidate the bytecode cache:: - $twig = new Twig_Environment($loader, array( - 'cache' => new Twig_Cache_Filesystem('/some/cache/path', Twig_Cache_Filesystem::FORCE_BYTECODE_INVALIDATION), + $twig = new \Twig\Environment($loader, [ + 'cache' => new \Twig\Cache\FilesystemCache('/some/cache/path', \Twig\Cache\FilesystemCache::FORCE_BYTECODE_INVALIDATION), // ... - )); + ]); .. note:: - Before Twig 1.22, you should extend ``Twig_Environment`` instead:: + Before Twig 1.22, you should extend ``\Twig\Environment`` instead:: - class OpCacheAwareTwigEnvironment extends Twig_Environment + class OpCacheAwareTwigEnvironment extends \Twig\Environment { protected function writeCacheFile($file, $content) { parent::writeCacheFile($file, $content); // Compile cached file into bytecode cache - if (function_exists('opcache_invalidate')) { + if (function_exists('opcache_invalidate') && filter_var(ini_get('opcache.enable'), FILTER_VALIDATE_BOOLEAN)) { opcache_invalidate($file, true); } elseif (function_exists('apc_compile_file')) { apc_compile_file($file); @@ -372,19 +372,19 @@ To get around this, force Twig to invalidate the bytecode cache:: Reusing a stateful Node Visitor ------------------------------- -When attaching a visitor to a ``Twig_Environment`` instance, Twig uses it to +When attaching a visitor to a ``\Twig\Environment`` instance, Twig uses it to visit *all* templates it compiles. If you need to keep some state information around, you probably want to reset it when visiting a new template. -This can be easily achieved with the following code:: +This can be achieved with the following code:: - protected $someTemplateState = array(); + protected $someTemplateState = []; - public function enterNode(Twig_NodeInterface $node, Twig_Environment $env) + public function enterNode(Twig_NodeInterface $node, \Twig\Environment $env) { - if ($node instanceof Twig_Node_Module) { + if ($node instanceof \Twig\Node\ModuleNode) { // reset the state as we are entering a new template - $this->someTemplateState = array(); + $this->someTemplateState = []; } // ... @@ -409,15 +409,15 @@ First, let's create a temporary in-memory SQLite3 database to work with:: {% block content %}Hello {{ name }}{% endblock %} '; $now = time(); - $dbh->exec("INSERT INTO templates (name, source, last_modified) VALUES ('base.twig', '$base', $now)"); - $dbh->exec("INSERT INTO templates (name, source, last_modified) VALUES ('index.twig', '$index', $now)"); + $dbh->prepare('INSERT INTO templates (name, source, last_modified) VALUES (?, ?, ?)')->execute(['base.twig', $base, $now]); + $dbh->prepare('INSERT INTO templates (name, source, last_modified) VALUES (?, ?, ?)')->execute(['index.twig', $index, $now]); We have created a simple ``templates`` table that hosts two templates: ``base.twig`` and ``index.twig``. Now, let's define a loader able to use this database:: - class DatabaseTwigLoader implements Twig_LoaderInterface, Twig_ExistsLoaderInterface, Twig_SourceContextLoaderInterface + class DatabaseTwigLoader implements \Twig\Loader\LoaderInterface, \Twig\Loader\ExistsLoaderInterface, \Twig\Loader\SourceContextLoaderInterface { protected $dbh; @@ -429,23 +429,23 @@ Now, let's define a loader able to use this database:: public function getSource($name) { if (false === $source = $this->getValue('source', $name)) { - throw new Twig_Error_Loader(sprintf('Template "%s" does not exist.', $name)); + throw new \Twig\Error\LoaderError(sprintf('Template "%s" does not exist.', $name)); } return $source; } - // Twig_SourceContextLoaderInterface as of Twig 1.27 + // \Twig\Loader\SourceContextLoaderInterface as of Twig 1.27 public function getSourceContext($name) { if (false === $source = $this->getValue('source', $name)) { - throw new Twig_Error_Loader(sprintf('Template "%s" does not exist.', $name)); + throw new \Twig\Error\LoaderError(sprintf('Template "%s" does not exist.', $name)); } - return new Twig_Source($source, $name); + return new \Twig\Source($source, $name); } - // Twig_ExistsLoaderInterface as of Twig 1.11 + // \Twig\Loader\ExistsLoaderInterface as of Twig 1.11 public function exists($name) { return $name === $this->getValue('name', $name); @@ -468,7 +468,7 @@ Now, let's define a loader able to use this database:: protected function getValue($column, $name) { $sth = $this->dbh->prepare('SELECT '.$column.' FROM templates WHERE name = :name'); - $sth->execute(array(':name' => (string) $name)); + $sth->execute([':name' => (string) $name]); return $sth->fetchColumn(); } @@ -477,9 +477,9 @@ Now, let's define a loader able to use this database:: Finally, here is an example on how you can use it:: $loader = new DatabaseTwigLoader($dbh); - $twig = new Twig_Environment($loader); + $twig = new \Twig\Environment($loader); - echo $twig->render('index.twig', array('name' => 'Fabien')); + echo $twig->render('index.twig', ['name' => 'Fabien']); Using different Template Sources -------------------------------- @@ -487,7 +487,7 @@ Using different Template Sources This recipe is the continuation of the previous one. Even if you store the contributed templates in a database, you might want to keep the original/base templates on the filesystem. When templates can be loaded from different -sources, you need to use the ``Twig_Loader_Chain`` loader. +sources, you need to use the ``\Twig\Loader\ChainLoader`` loader. As you can see in the previous recipe, we reference the template in the exact same way as we would have done it with a regular filesystem loader. This is @@ -496,14 +496,14 @@ filesystem, or any other loader for that matter: the template name should be a logical name, and not the path from the filesystem:: $loader1 = new DatabaseTwigLoader($dbh); - $loader2 = new Twig_Loader_Array(array( + $loader2 = new \Twig\Loader\ArrayLoader([ 'base.twig' => '{% block content %}{% endblock %}', - )); - $loader = new Twig_Loader_Chain(array($loader1, $loader2)); + ]); + $loader = new \Twig\Loader\ChainLoader([$loader1, $loader2]); - $twig = new Twig_Environment($loader); + $twig = new \Twig\Environment($loader); - echo $twig->render('index.twig', array('name' => 'Fabien')); + echo $twig->render('index.twig', ['name' => 'Fabien']); Now that the ``base.twig`` templates is defined in an array loader, you can remove it from the database, and everything else will still work as before. @@ -511,19 +511,19 @@ remove it from the database, and everything else will still work as before. Loading a Template from a String -------------------------------- -From a template, you can easily load a template stored in a string via the +From a template, you can load a template stored in a string via the ``template_from_string`` function (available as of Twig 1.11 via the -``Twig_Extension_StringLoader`` extension): +``\Twig\Extension\StringLoaderExtension`` extension): -.. code-block:: jinja +.. code-block:: twig {{ include(template_from_string("Hello {{ name }}")) }} From PHP, it's also possible to load a template stored in a string via -``Twig_Environment::createTemplate()`` (available as of Twig 1.18):: +``\Twig\Environment::createTemplate()`` (available as of Twig 1.18):: $template = $twig->createTemplate('hello {{ name }}'); - echo $template->render(array('name' => 'Fabien')); + echo $template->render(['name' => 'Fabien']); .. note:: @@ -561,8 +561,8 @@ include in your templates: .. code-block:: php - $env->setLexer(new Twig_Lexer($env, array( - 'tag_variable' => array('{[', ']}'), - ))); + $env->setLexer(new \Twig\Lexer($env, [ + 'tag_variable' => ['{[', ']}'], + ])); -.. _callback: http://www.php.net/manual/en/function.is-callable.php +.. _callback: https://secure.php.net/manual/en/function.is-callable.php diff --git a/vendor/twig/twig/doc/tags/apply.rst b/vendor/twig/twig/doc/tags/apply.rst new file mode 100644 index 0000000000000000000000000000000000000000..09bc036df6f4757cd5aac0b2814bf073348888d7 --- /dev/null +++ b/vendor/twig/twig/doc/tags/apply.rst @@ -0,0 +1,23 @@ +``apply`` +========= + +.. versionadded:: 1.40 + The ``apply`` tag was added in Twig 1.40. + +The ``apply`` tag allows you to apply Twig filters on a block of template data: + +.. code-block:: twig + + {% apply upper %} + This text becomes uppercase + {% endapply %} + +You can also chain filters and pass arguments to them: + +.. code-block:: twig + + {% apply lower|escape('html') %} + <strong>SOME TEXT</strong> + {% endapply %} + + {# outputs "<strong>some text</strong>" #} diff --git a/vendor/twig/twig/doc/tags/autoescape.rst b/vendor/twig/twig/doc/tags/autoescape.rst index 8aa8c75d14163f9917824f288d307b6ccdb71e4a..0fa34bda85d976f73ed417571bd39c6a242c5e0e 100644 --- a/vendor/twig/twig/doc/tags/autoescape.rst +++ b/vendor/twig/twig/doc/tags/autoescape.rst @@ -4,7 +4,7 @@ Whether automatic escaping is enabled or not, you can mark a section of a template to be escaped or not by using the ``autoescape`` tag: -.. code-block:: jinja +.. code-block:: twig {% autoescape %} Everything will be automatically escaped in this block @@ -29,7 +29,7 @@ template to be escaped or not by using the ``autoescape`` tag: Before Twig 1.8, the syntax was different: - .. code-block:: jinja + .. code-block:: twig {% autoescape true %} Everything will be automatically escaped in this block @@ -49,7 +49,7 @@ When automatic escaping is enabled everything is escaped by default except for values explicitly marked as safe. Those can be marked in the template by using the :doc:`raw<../filters/raw>` filter: -.. code-block:: jinja +.. code-block:: twig {% autoescape %} {{ safe_value|raw }} @@ -67,7 +67,7 @@ Functions returning template data (like :doc:`macros<macro>` and Twig does not escape static expressions: - .. code-block:: jinja + .. code-block:: twig {% set hello = "<strong>Hello</strong>" %} {{ hello }} diff --git a/vendor/twig/twig/doc/tags/deprecated.rst b/vendor/twig/twig/doc/tags/deprecated.rst new file mode 100644 index 0000000000000000000000000000000000000000..95828ac16b0b5970faa97b77fbc067843607d57d --- /dev/null +++ b/vendor/twig/twig/doc/tags/deprecated.rst @@ -0,0 +1,30 @@ +``deprecated`` +============== + +.. versionadded:: 1.36 and 2.6 + The ``deprecated`` tag was added in Twig 1.36 and 2.6. + +Twig generates a deprecation notice (via a call to the ``trigger_error()`` +PHP function) where the ``deprecated`` tag is used in a template: + +.. code-block:: twig + + {# base.twig #} + {% deprecated 'The "base.twig" template is deprecated, use "layout.twig" instead.' %} + {% extends 'layout.twig' %} + +Also you can deprecate a block in the following way: + +.. code-block:: twig + + {% block hey %} + {% deprecated 'The "hey" block is deprecated, use "greet" instead.' %} + {{ block('greet') }} + {% endblock %} + + {% block greet %} + Hey you! + {% endblock %} + +Note that by default, the deprecation notices are silenced and never displayed nor logged. +See :ref:`deprecation-notices` to learn how to handle them. diff --git a/vendor/twig/twig/doc/tags/do.rst b/vendor/twig/twig/doc/tags/do.rst index 1c344e302c63528b83a00d7becbf06d32c9901a2..b5e83ebaefa0e3c204c7021441c9c2b31c9ea2ce 100644 --- a/vendor/twig/twig/doc/tags/do.rst +++ b/vendor/twig/twig/doc/tags/do.rst @@ -7,6 +7,6 @@ The ``do`` tag works exactly like the regular variable expression (``{{ ... }}``) just that it doesn't print anything: -.. code-block:: jinja +.. code-block:: twig {% do 1 + 2 %} diff --git a/vendor/twig/twig/doc/tags/embed.rst b/vendor/twig/twig/doc/tags/embed.rst index 66fc21b5fa7ab226146e761ac3e9c75352e91125..e2796b2a8eef5ae69e684ce3e8b1437f9b453411 100644 --- a/vendor/twig/twig/doc/tags/embed.rst +++ b/vendor/twig/twig/doc/tags/embed.rst @@ -12,7 +12,7 @@ included template, like when extending a template. Think of an embedded template as a "micro layout skeleton". -.. code-block:: jinja +.. code-block:: twig {% embed "teasers_skeleton.twig" %} {# These blocks are defined in "teasers_skeleton.twig" #} @@ -88,26 +88,26 @@ two boxes side by side: Without the ``embed`` tag, you have two ways to design your templates: - * Create two "intermediate" base templates that extend the master layout - template: one with vertically stacked boxes to be used by the "foo" and - "bar" pages and another one with side-by-side boxes for the "boom" and - "baz" pages. +* Create two "intermediate" base templates that extend the master layout + template: one with vertically stacked boxes to be used by the "foo" and + "bar" pages and another one with side-by-side boxes for the "boom" and + "baz" pages. - * Embed the markup for the top/bottom and left/right boxes into each page - template directly. +* Embed the markup for the top/bottom and left/right boxes into each page + template directly. These two solutions do not scale well because they each have a major drawback: - * The first solution may indeed work for this simplified example. But imagine - we add a sidebar, which may again contain different, recurring structures - of content. Now we would need to create intermediate base templates for - all occurring combinations of content structure and sidebar structure... - and so on. +* The first solution may indeed work for this simplified example. But imagine + we add a sidebar, which may again contain different, recurring structures + of content. Now we would need to create intermediate base templates for + all occurring combinations of content structure and sidebar structure... + and so on. - * The second solution involves duplication of common code with all its negative - consequences: any change involves finding and editing all affected copies - of the structure, correctness has to be verified for each copy, copies may - go out of sync by careless modifications etc. +* The second solution involves duplication of common code with all its negative + consequences: any change involves finding and editing all affected copies + of the structure, correctness has to be verified for each copy, copies may + go out of sync by careless modifications etc. In such a situation, the ``embed`` tag comes in handy. The common layout code can live in a single base template, and the two different content structures, @@ -116,7 +116,7 @@ as necessary: Page template ``foo.twig``: -.. code-block:: jinja +.. code-block:: twig {% extends "layout_skeleton.twig" %} @@ -134,7 +134,7 @@ Page template ``foo.twig``: And here is the code for ``vertical_boxes_skeleton.twig``: -.. code-block:: html+jinja +.. code-block:: html+twig <div class="top_box"> {% block top %} @@ -153,7 +153,7 @@ out the HTML markup for the boxes. The ``embed`` tag takes the exact same arguments as the ``include`` tag: -.. code-block:: jinja +.. code-block:: twig {% embed "base" with {'foo': 'bar'} %} ... diff --git a/vendor/twig/twig/doc/tags/extends.rst b/vendor/twig/twig/doc/tags/extends.rst index 8bf29c4f9019d910abb756415b1cd7c4bc66edb9..9de5917835b6bdd030fbd3881088d03b4a0846fa 100644 --- a/vendor/twig/twig/doc/tags/extends.rst +++ b/vendor/twig/twig/doc/tags/extends.rst @@ -12,7 +12,7 @@ The ``extends`` tag can be used to extend a template from another one. Let's define a base template, ``base.html``, which defines a simple HTML skeleton document: -.. code-block:: html+jinja +.. code-block:: html+twig <!DOCTYPE html> <html> @@ -43,7 +43,7 @@ Child Template A child template might look like this: -.. code-block:: jinja +.. code-block:: twig {% extends "base.html" %} @@ -79,7 +79,7 @@ know which one of the blocks' content to use. If you want to print a block multiple times you can however use the ``block`` function: -.. code-block:: jinja +.. code-block:: twig <title>{% block title %}{% endblock %}</title> <h1>{{ block('title') }}</h1> @@ -92,7 +92,7 @@ It's possible to render the contents of the parent block by using the :doc:`parent<../functions/parent>` function. This gives back the results of the parent block: -.. code-block:: jinja +.. code-block:: twig {% block sidebar %} <h3>Table Of Contents</h3> @@ -104,9 +104,9 @@ Named Block End-Tags -------------------- Twig allows you to put the name of the block after the end tag for better -readability: +readability (the name after the ``endblock`` word must match the block name): -.. code-block:: jinja +.. code-block:: twig {% block sidebar %} {% block inner_sidebar %} @@ -114,15 +114,13 @@ readability: {% endblock inner_sidebar %} {% endblock sidebar %} -Of course, the name after the ``endblock`` word must match the block name. - Block Nesting and Scope ----------------------- Blocks can be nested for more complex layouts. Per default, blocks have access to variables from outer scopes: -.. code-block:: jinja +.. code-block:: twig {% for item in seq %} <li>{% block loop_item %}{{ item }}{% endblock %}</li> @@ -134,13 +132,13 @@ Block Shortcuts For blocks with little content, it's possible to use a shortcut syntax. The following constructs do the same thing: -.. code-block:: jinja +.. code-block:: twig {% block title %} {{ page_title|title }} {% endblock %} -.. code-block:: jinja +.. code-block:: twig {% block title page_title|title %} @@ -149,11 +147,11 @@ Dynamic Inheritance Twig supports dynamic inheritance by using a variable as the base template: -.. code-block:: jinja +.. code-block:: twig {% extends some_var %} -If the variable evaluates to a ``Twig_Template`` or a ``Twig_TemplateWrapper`` +If the variable evaluates to a ``\Twig\Template`` or a ``\Twig\TemplateWrapper`` instance, Twig will use it as the parent template:: // {% extends layout %} @@ -164,7 +162,7 @@ instance, Twig will use it as the parent template:: // as of Twig 1.28 $layout = $twig->load('some_layout_template.twig'); - $twig->display('template.twig', array('layout' => $layout)); + $twig->display('template.twig', ['layout' => $layout]); .. versionadded:: 1.2 The possibility to pass an array of templates has been added in Twig 1.2. @@ -172,7 +170,7 @@ instance, Twig will use it as the parent template:: You can also provide a list of templates that are checked for existence. The first template that exists will be used as a parent: -.. code-block:: jinja +.. code-block:: twig {% extends ['layout.html', 'base_layout.html'] %} @@ -182,7 +180,7 @@ Conditional Inheritance As the template name for the parent can be any valid Twig expression, it's possible to make the inheritance mechanism conditional: -.. code-block:: jinja +.. code-block:: twig {% extends standalone ? "minimum.html" : "base.html" %} @@ -199,7 +197,7 @@ but it does not interfere in any way with the logic around it. Let's take the following example to illustrate how a block works and more importantly, how it does not work: -.. code-block:: jinja +.. code-block:: twig {# base.twig #} @@ -214,7 +212,7 @@ If you render this template, the result would be exactly the same with or without the ``block`` tag. The ``block`` inside the ``for`` loop is just a way to make it overridable by a child template: -.. code-block:: jinja +.. code-block:: twig {# child.twig #} @@ -231,7 +229,7 @@ Now, when rendering the child template, the loop is going to use the block defined in the child template instead of the one defined in the base one; the executed template is then equivalent to the following one: -.. code-block:: jinja +.. code-block:: twig {% for post in posts %} <article> @@ -242,7 +240,7 @@ executed template is then equivalent to the following one: Let's take another example: a block included within an ``if`` statement: -.. code-block:: jinja +.. code-block:: twig {% if posts is empty %} {% block head %} @@ -259,7 +257,7 @@ what will be rendered when the condition is ``true``. If you want the output to be displayed conditionally, use the following instead: -.. code-block:: jinja +.. code-block:: twig {% block head %} {{ parent() }} diff --git a/vendor/twig/twig/doc/tags/filter.rst b/vendor/twig/twig/doc/tags/filter.rst index 82ca5c62f0f8532453ca5f44a1cd1647fe6e6f75..a85a6cfbf945376c54a8024f5ccb56815e28635a 100644 --- a/vendor/twig/twig/doc/tags/filter.rst +++ b/vendor/twig/twig/doc/tags/filter.rst @@ -1,20 +1,25 @@ ``filter`` ========== +.. note:: + + As of Twig 1.40, you should use the ``apply`` tag instead which does the + same thing except that the wrapped template data is not scoped. + Filter sections allow you to apply regular Twig filters on a block of template data. Just wrap the code in the special ``filter`` section: -.. code-block:: jinja +.. code-block:: twig {% filter upper %} This text becomes uppercase {% endfilter %} -You can also chain filters: +You can also chain filters and pass arguments to them: -.. code-block:: jinja +.. code-block:: twig - {% filter lower|escape %} + {% filter lower|escape('html') %} <strong>SOME TEXT</strong> {% endfilter %} diff --git a/vendor/twig/twig/doc/tags/flush.rst b/vendor/twig/twig/doc/tags/flush.rst index 55ef593a9216e13432512f6938e032c5a8bf074b..13948b2beb2b1810cdf5b6a6223d48d279d63b7f 100644 --- a/vendor/twig/twig/doc/tags/flush.rst +++ b/vendor/twig/twig/doc/tags/flush.rst @@ -6,7 +6,7 @@ The ``flush`` tag tells Twig to flush the output buffer: -.. code-block:: jinja +.. code-block:: twig {% flush %} @@ -14,4 +14,4 @@ The ``flush`` tag tells Twig to flush the output buffer: Internally, Twig uses the PHP `flush`_ function. -.. _`flush`: http://php.net/flush +.. _`flush`: https://secure.php.net/flush diff --git a/vendor/twig/twig/doc/tags/for.rst b/vendor/twig/twig/doc/tags/for.rst index 0673b5511515837fcc69acb0c4f3ee8cb9c52d21..a55e163327125dd5b12ad867aaaf4e17ebf5fe10 100644 --- a/vendor/twig/twig/doc/tags/for.rst +++ b/vendor/twig/twig/doc/tags/for.rst @@ -4,7 +4,7 @@ Loop over each item in a sequence. For example, to display a list of users provided in a variable called ``users``: -.. code-block:: jinja +.. code-block:: twig <h1>Members</h1> <ul> @@ -21,7 +21,7 @@ provided in a variable called ``users``: If you do need to iterate over a sequence of numbers, you can use the ``..`` operator: -.. code-block:: jinja +.. code-block:: twig {% for i in 0..10 %} * {{ i }} @@ -31,7 +31,7 @@ The above snippet of code would print all numbers from 0 to 10. It can be also useful with letters: -.. code-block:: jinja +.. code-block:: twig {% for letter in 'a'..'z' %} * {{ letter }} @@ -39,7 +39,7 @@ It can be also useful with letters: The ``..`` operator can take any expression at both sides: -.. code-block:: jinja +.. code-block:: twig {% for letter in 'a'|upper..'z'|upper %} * {{ letter }} @@ -68,7 +68,7 @@ Variable Description ``loop.parent`` The parent context ===================== ============================================================= -.. code-block:: jinja +.. code-block:: twig {% for user in users %} {{ loop.index }} - {{ user.username }} @@ -87,11 +87,18 @@ Variable Description Adding a condition ------------------ +.. tip:: + + As of Twig 1.41, use the :doc:`filter <../filters/filter>` filter instead, + or an ``if`` condition inside the ``for`` body (if your condition depends on + a variable updated inside the loop and you are not using the ``loop`` + variable). + Unlike in PHP, it's not possible to ``break`` or ``continue`` in a loop. You can however filter the sequence during iteration which allows you to skip items. The following example skips all the users which are not active: -.. code-block:: jinja +.. code-block:: twig <ul> {% for user in users if user.active %} @@ -117,7 +124,7 @@ The `else` Clause If no iteration took place because the sequence was empty, you can render a replacement block by using ``else``: -.. code-block:: jinja +.. code-block:: twig <ul> {% for user in users %} @@ -133,7 +140,7 @@ Iterating over Keys By default, a loop iterates over the values of the sequence. You can iterate on keys by using the ``keys`` filter: -.. code-block:: jinja +.. code-block:: twig <h1>Members</h1> <ul> @@ -147,7 +154,7 @@ Iterating over Keys and Values You can also access both keys and values: -.. code-block:: jinja +.. code-block:: twig <h1>Members</h1> <ul> @@ -162,7 +169,7 @@ Iterating over a Subset You might want to iterate over a subset of values. This can be achieved using the :doc:`slice <../filters/slice>` filter: -.. code-block:: jinja +.. code-block:: twig <h1>Top Ten Members</h1> <ul> diff --git a/vendor/twig/twig/doc/tags/from.rst b/vendor/twig/twig/doc/tags/from.rst index 39334fdde255293cbf42e87cf900fddde1ecac57..96c439aa74b2b6f3eeae0c9bea8d27b0bcf0876b 100644 --- a/vendor/twig/twig/doc/tags/from.rst +++ b/vendor/twig/twig/doc/tags/from.rst @@ -3,6 +3,4 @@ The ``from`` tag imports :doc:`macro<../tags/macro>` names into the current namespace. The tag is documented in detail in the documentation for the -:doc:`import<../tags/import>` tag. - -.. seealso:: :doc:`macro<../tags/macro>`, :doc:`import<../tags/import>` +:doc:`macro<../tags/macro>` tag. diff --git a/vendor/twig/twig/doc/tags/if.rst b/vendor/twig/twig/doc/tags/if.rst index 12edf980df2ff756a56ab131ecbd26f687c0f8b9..2a1610c822aa63e72844c8ab746cef8af41ca771 100644 --- a/vendor/twig/twig/doc/tags/if.rst +++ b/vendor/twig/twig/doc/tags/if.rst @@ -6,7 +6,7 @@ The ``if`` statement in Twig is comparable with the if statements of PHP. In the simplest form you can use it to test if an expression evaluates to ``true``: -.. code-block:: jinja +.. code-block:: twig {% if online == false %} <p>Our website is in maintenance mode. Please, come back later.</p> @@ -14,7 +14,7 @@ In the simplest form you can use it to test if an expression evaluates to You can also test if an array is not empty: -.. code-block:: jinja +.. code-block:: twig {% if users %} <ul> @@ -31,7 +31,7 @@ You can also test if an array is not empty: You can also use ``not`` to check for values that evaluate to ``false``: -.. code-block:: jinja +.. code-block:: twig {% if not user.subscribed %} <p>You are not subscribed to our mailing list.</p> @@ -39,7 +39,7 @@ You can also use ``not`` to check for values that evaluate to ``false``: For multiple conditions, ``and`` and ``or`` can be used: -.. code-block:: jinja +.. code-block:: twig {% if temperature > 18 and temperature < 27 %} <p>It's a nice day for a walk in the park.</p> @@ -48,14 +48,14 @@ For multiple conditions, ``and`` and ``or`` can be used: For multiple branches ``elseif`` and ``else`` can be used like in PHP. You can use more complex ``expressions`` there too: -.. code-block:: jinja +.. code-block:: twig - {% if kenny.sick %} - Kenny is sick. - {% elseif kenny.dead %} - You killed Kenny! You bastard!!! + {% if product.stock > 10 %} + Available + {% elseif product.stock > 0 %} + Only {{ product.stock }} left! {% else %} - Kenny looks okay --- so far + Sold-out! {% endif %} .. note:: @@ -68,7 +68,10 @@ use more complex ``expressions`` there too: ====================== ==================== empty string false numeric zero false + NAN (Not A Number) true + INF (Infinity) true whitespace-only string true + string "0" or '0' false empty array false null false non-empty array true diff --git a/vendor/twig/twig/doc/tags/import.rst b/vendor/twig/twig/doc/tags/import.rst index 21a1e19803b641b6f610c69b5e79af899df5d1b2..f217479fb38f35ca3e7ca90de5546910c31a80e6 100644 --- a/vendor/twig/twig/doc/tags/import.rst +++ b/vendor/twig/twig/doc/tags/import.rst @@ -1,57 +1,6 @@ ``import`` ========== -Twig supports putting often used code into :doc:`macros<../tags/macro>`. These -macros can go into different templates and get imported from there. - -There are two ways to import templates. You can import the complete template -into a variable or request specific macros from it. - -Imagine we have a helper module that renders forms (called ``forms.html``): - -.. code-block:: jinja - - {% macro input(name, value, type, size) %} - <input type="{{ type|default('text') }}" name="{{ name }}" value="{{ value|e }}" size="{{ size|default(20) }}" /> - {% endmacro %} - - {% macro textarea(name, value, rows, cols) %} - <textarea name="{{ name }}" rows="{{ rows|default(10) }}" cols="{{ cols|default(40) }}">{{ value|e }}</textarea> - {% endmacro %} - -The easiest and most flexible is importing the whole module into a variable. -That way you can access the attributes: - -.. code-block:: jinja - - {% import 'forms.html' as forms %} - - <dl> - <dt>Username</dt> - <dd>{{ forms.input('username') }}</dd> - <dt>Password</dt> - <dd>{{ forms.input('password', null, 'password') }}</dd> - </dl> - <p>{{ forms.textarea('comment') }}</p> - -Alternatively you can import names from the template into the current -namespace: - -.. code-block:: jinja - - {% from 'forms.html' import input as input_field, textarea %} - - <dl> - <dt>Username</dt> - <dd>{{ input_field('username') }}</dd> - <dt>Password</dt> - <dd>{{ input_field('password', '', 'password') }}</dd> - </dl> - <p>{{ textarea('comment') }}</p> - -.. tip:: - - To import macros from the current file, use the special ``_self`` variable - for the source. - -.. seealso:: :doc:`macro<../tags/macro>`, :doc:`from<../tags/from>` +The ``import`` tag imports :doc:`macro<../tags/macro>` names in a local +variable. The tag is documented in detail in the documentation for the +:doc:`macro<../tags/macro>` tag. diff --git a/vendor/twig/twig/doc/tags/include.rst b/vendor/twig/twig/doc/tags/include.rst index 24ff24db69d6779698700911c6bb7acc7345dbfb..661280f92eaa07111b693b8d350a93cdb452d2f1 100644 --- a/vendor/twig/twig/doc/tags/include.rst +++ b/vendor/twig/twig/doc/tags/include.rst @@ -2,14 +2,38 @@ =========== The ``include`` statement includes a template and returns the rendered content -of that file into the current namespace: +of that file: -.. code-block:: jinja +.. code-block:: twig {% include 'header.html' %} Body {% include 'footer.html' %} +.. note:: + + As of Twig 1.12, it is recommended to use the + :doc:`include<../functions/include>` function instead as it provides the + same features with a bit more flexibility: + + * The ``include`` function is semantically more "correct" (including a + template outputs its rendered contents in the current scope; a tag should + not display anything); + + * It's easier to store the rendered template in a variable when using + the ``include`` function: + + .. code-block:: twig + + {% set content %}{% include 'template.html' %}{% endset %} + + {# vs #} + + {% set content = include('template.html') %} + + * The ``include`` function does not impose any specific order for + arguments thanks to :ref:`named arguments <named-arguments>`. + Included templates have access to the variables of the active context. If you are using the filesystem loader, the templates are looked for in the @@ -17,7 +41,7 @@ paths defined by it. You can add additional variables by passing them after the ``with`` keyword: -.. code-block:: jinja +.. code-block:: twig {# template.html will have access to the variables from the current context and the additional ones provided #} {% include 'template.html' with {'foo': 'bar'} %} @@ -27,12 +51,12 @@ You can add additional variables by passing them after the ``with`` keyword: You can disable access to the context by appending the ``only`` keyword: -.. code-block:: jinja +.. code-block:: twig {# only the foo variable will be accessible #} {% include 'template.html' with {'foo': 'bar'} only %} -.. code-block:: jinja +.. code-block:: twig {# no variables will be accessible #} {% include 'template.html' only %} @@ -45,13 +69,13 @@ You can disable access to the context by appending the ``only`` keyword: The template name can be any valid Twig expression: -.. code-block:: jinja +.. code-block:: twig {% include some_var %} {% include ajax ? 'ajax.html' : 'not_ajax.html' %} -And if the expression evaluates to a ``Twig_Template`` or a -``Twig_TemplateWrapper`` instance, Twig will use it directly:: +And if the expression evaluates to a ``\Twig\Template`` or a +``\Twig\TemplateWrapper`` instance, Twig will use it directly:: // {% include template %} @@ -61,7 +85,7 @@ And if the expression evaluates to a ``Twig_Template`` or a // as of Twig 1.28 $template = $twig->load('some_template.twig'); - $twig->display('template.twig', array('template' => $template)); + $twig->display('template.twig', ['template' => $template]); .. versionadded:: 1.2 The ``ignore missing`` feature has been added in Twig 1.2. @@ -70,7 +94,7 @@ You can mark an include with ``ignore missing`` in which case Twig will ignore the statement if the template to be included does not exist. It has to be placed just after the template name. Here some valid examples: -.. code-block:: jinja +.. code-block:: twig {% include 'sidebar.html' ignore missing %} {% include 'sidebar.html' ignore missing with {'foo': 'bar'} %} @@ -82,7 +106,7 @@ placed just after the template name. Here some valid examples: You can also provide a list of templates that are checked for existence before inclusion. The first template that exists will be included: -.. code-block:: jinja +.. code-block:: twig {% include ['page_detailed.html', 'page.html'] %} diff --git a/vendor/twig/twig/doc/tags/index.rst b/vendor/twig/twig/doc/tags/index.rst index dbe2459e30408af0df0eb983b6d3956b224839fb..530f95f10052abd5374e8e9ce0d3b437f92200b2 100644 --- a/vendor/twig/twig/doc/tags/index.rst +++ b/vendor/twig/twig/doc/tags/index.rst @@ -4,8 +4,10 @@ Tags .. toctree:: :maxdepth: 1 + apply autoescape block + deprecated do embed extends diff --git a/vendor/twig/twig/doc/tags/macro.rst b/vendor/twig/twig/doc/tags/macro.rst index a8aa76fd92339eb8b8450207a2c91439f40f5b54..31bca00a5125fc94c5be52b86498f7874ac30542 100644 --- a/vendor/twig/twig/doc/tags/macro.rst +++ b/vendor/twig/twig/doc/tags/macro.rst @@ -1,22 +1,44 @@ ``macro`` ========= +.. versionadded:: 1.12 + + The possibility to define default values for arguments in the macro + signature was added in Twig 1.12. + Macros are comparable with functions in regular programming languages. They -are useful to put often used HTML idioms into reusable elements to not repeat -yourself. +are useful to reuse template fragments to not repeat yourself. -Here is a small example of a macro that renders a form element: +Macros are defined in regular templates. -.. code-block:: jinja +Imagine having a generic helper template that define how to render HTML forms +via macros (called ``forms.html``): - {% macro input(name, value, type, size) %} - <input type="{{ type|default('text') }}" name="{{ name }}" value="{{ value|e }}" size="{{ size|default(20) }}" /> +.. code-block:: twig + + {% macro input(name, value, type = "text", size = 20) %} + <input type="{{ type }}" name="{{ name }}" value="{{ value|e }}" size="{{ size }}" /> {% endmacro %} -Macros differ from native PHP functions in a few ways: + {% macro textarea(name, value, rows = 10, cols = 40) %} + <textarea name="{{ name }}" rows="{{ rows }}" cols="{{ cols }}">{{ value|e }}</textarea> + {% endmacro %} + +Each macro argument can have a default value (here ``text`` is the default value +for ``type`` if not provided in the call). + +.. note:: + + Before Twig 1.12, defining default argument values was done via the + ``default`` filter in the macro body: + + .. code-block:: twig -* Default argument values are defined by using the ``default`` filter in the - macro body; + {% macro input(name, value, type, size) %} + <input type="{{ type|default('text') }}" name="{{ name }}" value="{{ value|e }}" size="{{ size|default(20) }}" /> + {% endmacro %} + +Macros differ from native PHP functions in a few ways: * Arguments of a macro are always optional. @@ -34,45 +56,32 @@ variables. Import ------ -Macros can be defined in any template, and need to be "imported" before being -used (see the documentation for the :doc:`import<../tags/import>` tag for more -information): +There are two ways to import macros. You can import the complete template +containing the macros into a local variable (via the ``import`` tag) or only +import specific macros from the template (via the ``from`` tag). + +To import all macros from a template into a local variable, use the ``import`` +tag: -.. code-block:: jinja +.. code-block:: twig {% import "forms.html" as forms %} -The above ``import`` call imports the "forms.html" file (which can contain only -macros, or a template and some macros), and import the functions as items of -the ``forms`` variable. +The above ``import`` call imports the ``forms.html`` file (which can contain +only macros, or a template and some macros), and import the macros as items of +the ``forms`` local variable. -The macro can then be called at will: +The macros can then be called at will in the *current* template: -.. code-block:: jinja +.. code-block:: twig <p>{{ forms.input('username') }}</p> <p>{{ forms.input('password', null, 'password') }}</p> -If macros are defined and used in the same template, you can use the -special ``_self`` variable to import them: - -.. code-block:: jinja - - {% import _self as forms %} - - <p>{{ forms.input('username') }}</p> - -.. warning:: - - When you define a macro in the template where you are going to use it, you - might be tempted to call the macro directly via ``_self.input()`` instead - of importing it; even if seems to work, this is just a side-effect of the - current implementation and it won't work anymore in Twig 2.x. - When you want to use a macro in another macro from the same file, you need to import it locally: -.. code-block:: jinja +.. code-block:: twig {% macro input(name, value, type, size) %} <input type="{{ type|default('text') }}" name="{{ name }}" value="{{ value|e }}" size="{{ size|default(20) }}" /> @@ -86,18 +95,45 @@ import it locally: </div> {% endmacro %} +Alternatively you can import names from the template into the current namespace +via the ``from`` tag: + +.. code-block:: twig + + {% from 'forms.html' import input as input_field, textarea %} + + <p>{{ input_field('password', '', 'password') }}</p> + <p>{{ textarea('comment') }}</p> + +.. note:: + + Importing macros using ``import`` or ``from`` is **local** to the current + file. The imported macros are not available in included templates or child + templates; you need to explicitly re-import macros in each file. + +.. tip:: + + To import macros from the current file, use the special ``_self`` variable: + + .. code-block:: twig + + {% import _self as forms %} + + <p>{{ forms.input('username') }}</p> + + When you define a macro in the template where you are going to use it, you + might be tempted to call the macro directly via ``_self.input()`` instead of + importing it; even if it seems to work, this is just a side-effect of the + current implementation and it won't work anymore in Twig 2.x. + Named Macro End-Tags -------------------- Twig allows you to put the name of the macro after the end tag for better -readability: +readability (the name after the ``endmacro`` word must match the macro name): -.. code-block:: jinja +.. code-block:: twig {% macro input() %} ... {% endmacro input %} - -Of course, the name after the ``endmacro`` word must match the macro name. - -.. seealso:: :doc:`from<../tags/from>`, :doc:`import<../tags/import>` diff --git a/vendor/twig/twig/doc/tags/sandbox.rst b/vendor/twig/twig/doc/tags/sandbox.rst index e186726c202eb6a79fd0b8cc57c6aaadbd187e4b..b331fdb8e698eef3e7ac516b8230309587ab4655 100644 --- a/vendor/twig/twig/doc/tags/sandbox.rst +++ b/vendor/twig/twig/doc/tags/sandbox.rst @@ -4,7 +4,7 @@ The ``sandbox`` tag can be used to enable the sandboxing mode for an included template, when sandboxing is not enabled globally for the Twig environment: -.. code-block:: jinja +.. code-block:: twig {% sandbox %} {% include 'user.html' %} @@ -21,7 +21,7 @@ template, when sandboxing is not enabled globally for the Twig environment: cannot be used to sandbox a section of a template. The following example won't work: - .. code-block:: jinja + .. code-block:: twig {% sandbox %} {% for i in 1..2 %} diff --git a/vendor/twig/twig/doc/tags/set.rst b/vendor/twig/twig/doc/tags/set.rst index 3eba239a9a773ae33e2f0efb0c4666f37d1904f1..f752fddb67b4a84bb64937c9b05e36cb5d5bf599 100644 --- a/vendor/twig/twig/doc/tags/set.rst +++ b/vendor/twig/twig/doc/tags/set.rst @@ -6,22 +6,22 @@ the ``set`` tag and can have multiple targets. Here is how you can assign the ``bar`` value to the ``foo`` variable: -.. code-block:: jinja +.. code-block:: twig {% set foo = 'bar' %} After the ``set`` call, the ``foo`` variable is available in the template like any other ones: -.. code-block:: jinja +.. code-block:: twig {# displays bar #} {{ foo }} -The assigned value can be any valid :ref:`Twig expressions +The assigned value can be any valid :ref:`Twig expression <twig-expressions>`: -.. code-block:: jinja +.. code-block:: twig {% set foo = [1, 2] %} {% set foo = {'foo': 'bar'} %} @@ -29,7 +29,7 @@ The assigned value can be any valid :ref:`Twig expressions Several variables can be assigned in one block: -.. code-block:: jinja +.. code-block:: twig {% set foo, bar = 'foo', 'bar' %} @@ -40,7 +40,7 @@ Several variables can be assigned in one block: The ``set`` tag can also be used to 'capture' chunks of text: -.. code-block:: jinja +.. code-block:: twig {% set foo %} <div id="pagination"> @@ -58,7 +58,7 @@ The ``set`` tag can also be used to 'capture' chunks of text: Note that loops are scoped in Twig; therefore a variable declared inside a ``for`` loop is not accessible outside the loop itself: - .. code-block:: jinja + .. code-block:: twig {% for item in list %} {% set foo = item %} @@ -68,7 +68,7 @@ The ``set`` tag can also be used to 'capture' chunks of text: If you want to access the variable, just declare it before the loop: - .. code-block:: jinja + .. code-block:: twig {% set foo = "" %} {% for item in list %} diff --git a/vendor/twig/twig/doc/tags/spaceless.rst b/vendor/twig/twig/doc/tags/spaceless.rst index b39cb27efe676b136f89cf1c3c1bf19b8c74516e..2608538aae68b8be80dc54c4fa8367d20c22cf11 100644 --- a/vendor/twig/twig/doc/tags/spaceless.rst +++ b/vendor/twig/twig/doc/tags/spaceless.rst @@ -1,10 +1,14 @@ ``spaceless`` ============= +.. tip:: + + As of Twig 1.38, use the :doc:`spaceless <../filters/spaceless>` filter instead. + Use the ``spaceless`` tag to remove whitespace *between HTML tags*, not whitespace within HTML tags or whitespace in plain text: -.. code-block:: jinja +.. code-block:: twig {% spaceless %} <div> diff --git a/vendor/twig/twig/doc/tags/use.rst b/vendor/twig/twig/doc/tags/use.rst index a6fdefb4630321b29e17c3f3c9c5911c066a124a..b83d1beab91fbd7e0ea66999aec87bbfd3fac748 100644 --- a/vendor/twig/twig/doc/tags/use.rst +++ b/vendor/twig/twig/doc/tags/use.rst @@ -15,7 +15,7 @@ limited to single inheritance; a template can only extend one other template. This limitation makes template inheritance simple to understand and easy to debug: -.. code-block:: jinja +.. code-block:: twig {% extends "base.html" %} @@ -25,7 +25,7 @@ debug: Horizontal reuse is a way to achieve the same goal as multiple inheritance, but without the associated complexity: -.. code-block:: jinja +.. code-block:: twig {% extends "base.html" %} @@ -37,7 +37,7 @@ but without the associated complexity: The ``use`` statement tells Twig to import the blocks defined in ``blocks.html`` into the current template (it's like macros, but for blocks): -.. code-block:: jinja +.. code-block:: twig {# blocks.html #} @@ -47,7 +47,7 @@ In this example, the ``use`` statement imports the ``sidebar`` block into the main template. The code is mostly equivalent to the following one (the imported blocks are not outputted automatically): -.. code-block:: jinja +.. code-block:: twig {% extends "base.html" %} @@ -70,7 +70,7 @@ The main template can also override any imported block. If the template already defines the ``sidebar`` block, then the one defined in ``blocks.html`` is ignored. To avoid name conflicts, you can rename imported blocks: -.. code-block:: jinja +.. code-block:: twig {% extends "base.html" %} @@ -87,7 +87,7 @@ The ``parent()`` function automatically determines the correct inheritance tree, so it can be used when overriding a block defined in an imported template: -.. code-block:: jinja +.. code-block:: twig {% extends "base.html" %} @@ -108,7 +108,7 @@ the ``blocks.html`` template. In Twig 1.2, renaming allows you to simulate inheritance by calling the "parent" block: - .. code-block:: jinja + .. code-block:: twig {% extends "base.html" %} diff --git a/vendor/twig/twig/doc/tags/verbatim.rst b/vendor/twig/twig/doc/tags/verbatim.rst index fe61ca1b0ae7c27d629e9b9e91d2dafe5e6add02..001bbd5153a77961536e21f71f4096e93518e612 100644 --- a/vendor/twig/twig/doc/tags/verbatim.rst +++ b/vendor/twig/twig/doc/tags/verbatim.rst @@ -8,7 +8,7 @@ The ``verbatim`` tag marks sections as being raw text that should not be parsed. For example to put Twig syntax as example into a template you can use this snippet: -.. code-block:: jinja +.. code-block:: twig {% verbatim %} <ul> diff --git a/vendor/twig/twig/doc/tags/with.rst b/vendor/twig/twig/doc/tags/with.rst index 815b069927fcaf9457718e2c0485a35040b399d6..bf9df5d5129a860b8ba2e5c9104eceea1078db1c 100644 --- a/vendor/twig/twig/doc/tags/with.rst +++ b/vendor/twig/twig/doc/tags/with.rst @@ -7,7 +7,7 @@ Use the ``with`` tag to create a new inner scope. Variables set within this scope are not visible outside of the scope: -.. code-block:: jinja +.. code-block:: twig {% with %} {% set foo = 42 %} @@ -19,7 +19,7 @@ Instead of defining variables at the beginning of the scope, you can pass a hash of variables you want to define in the ``with`` tag; the previous example is equivalent to the following one: -.. code-block:: jinja +.. code-block:: twig {% with { foo: 42 } %} {{ foo }} foo is 42 here @@ -35,7 +35,7 @@ is equivalent to the following one: By default, the inner scope has access to the outer scope context; you can disable this behavior by appending the ``only`` keyword: -.. code-block:: jinja +.. code-block:: twig {% set bar = 'bar' %} {% with { foo: 42 } only %} diff --git a/vendor/twig/twig/doc/templates.rst b/vendor/twig/twig/doc/templates.rst index 3d60779a09b2df75051f06aa29651fa6841ec681..168a8f7085a19da7b34886c2e9655c94215bc153 100644 --- a/vendor/twig/twig/doc/templates.rst +++ b/vendor/twig/twig/doc/templates.rst @@ -7,18 +7,18 @@ will be most useful as reference to those creating Twig templates. Synopsis -------- -A template is simply a text file. It can generate any text-based format (HTML, +A template is a regular text file. It can generate any text-based format (HTML, XML, CSV, LaTeX, etc.). It doesn't have a specific extension, ``.html`` or ``.xml`` are just fine. A template contains **variables** or **expressions**, which get replaced with -values when the template is evaluated, and **tags**, which control the logic -of the template. +values when the template is evaluated, and **tags**, which control the +template's logic. Below is a minimal template that illustrates a few basics. We will cover further details later on: -.. code-block:: html+jinja +.. code-block:: html+twig <!DOCTYPE html> <html> @@ -38,8 +38,8 @@ details later on: </html> There are two kinds of delimiters: ``{% ... %}`` and ``{{ ... }}``. The first -one is used to execute statements such as for-loops, the latter prints the -result of an expression to the template. +one is used to execute statements such as for-loops, the latter outputs the +result of an expression. IDEs Integration ---------------- @@ -68,27 +68,16 @@ Variables --------- The application passes variables to the templates for manipulation in the -template. Variables may have attributes or elements you can access, -too. The visual representation of a variable depends heavily on the application providing +template. Variables may have attributes or elements you can access, too. The +visual representation of a variable depends heavily on the application providing it. -You can use a dot (``.``) to access attributes of a variable (methods or -properties of a PHP object, or items of a PHP array), or the so-called -"subscript" syntax (``[]``): +Use a dot (``.``) to access attributes of a variable (methods or properties of a +PHP object, or items of a PHP array): -.. code-block:: jinja +.. code-block:: twig {{ foo.bar }} - {{ foo['bar'] }} - -When the attribute contains special characters (like ``-`` that would be -interpreted as the minus operator), use the ``attribute`` function instead to -access the variable attribute: - -.. code-block:: jinja - - {# equivalent to the non-working foo.data-foo #} - {{ attribute(foo, 'data-foo') }} .. note:: @@ -96,10 +85,6 @@ access the variable attribute: variable but the print statement. When accessing variables inside tags, don't put the braces around them. -If a variable or attribute does not exist, you will receive a ``null`` value -when the ``strict_variables`` option is set to ``false``; alternatively, if ``strict_variables`` -is set, Twig will throw an error (see :ref:`environment options<environment_options>`). - .. sidebar:: Implementation For convenience's sake ``foo.bar`` does the following things on the PHP @@ -113,16 +98,30 @@ is set, Twig will throw an error (see :ref:`environment options<environment_opti * if not, and if ``foo`` is an object, check that ``isBar`` is a valid method; * if not, return a ``null`` value. - ``foo['bar']`` on the other hand only works with PHP arrays: + Twig also supports a specific syntax for accessing items on PHP arrays, + ``foo['bar']``: * check if ``foo`` is an array and ``bar`` a valid element; * if not, return a ``null`` value. +If a variable or attribute does not exist, you will receive a ``null`` value +when the ``strict_variables`` option is set to ``false``; alternatively, if ``strict_variables`` +is set, Twig will throw an error (see :ref:`environment options<environment_options>`). + .. note:: If you want to access a dynamic attribute of a variable, use the :doc:`attribute<functions/attribute>` function instead. + The ``attribute`` function is also useful when the attribute contains + special characters (like ``-`` that would be interpreted as the minus + operator): + + .. code-block:: twig + + {# equivalent to the non-working foo.data-foo #} + {{ attribute(foo, 'data-foo') }} + Global Variables ~~~~~~~~~~~~~~~~ @@ -138,7 +137,7 @@ Setting Variables You can assign values to variables inside code blocks. Assignments use the :doc:`set<tags/set>` tag: -.. code-block:: jinja +.. code-block:: twig {% set foo = 'foo' %} {% set foo = [1, 2] %} @@ -148,36 +147,40 @@ Filters ------- Variables can be modified by **filters**. Filters are separated from the -variable by a pipe symbol (``|``) and may have optional arguments in -parentheses. Multiple filters can be chained. The output of one filter is -applied to the next. +variable by a pipe symbol (``|``). Multiple filters can be chained. The output +of one filter is applied to the next. The following example removes all HTML tags from the ``name`` and title-cases it: -.. code-block:: jinja +.. code-block:: twig {{ name|striptags|title }} Filters that accept arguments have parentheses around the arguments. This -example will join a list by commas: +example joins the elements of a list by commas: -.. code-block:: jinja +.. code-block:: twig {{ list|join(', ') }} -To apply a filter on a section of code, wrap it in the -:doc:`filter<tags/filter>` tag: +To apply a filter on a section of code, wrap it with the +:doc:`apply<tags/apply>` tag: -.. code-block:: jinja +.. code-block:: twig - {% filter upper %} + {% apply upper %} This text becomes uppercase - {% endfilter %} + {% endapply %} Go to the :doc:`filters<filters/index>` page to learn more about built-in filters. +.. note:: + + The ``apply`` tag was introduced in Twig 1.40; use the ``filter`` tag with + previous versions. + Functions --------- @@ -187,7 +190,7 @@ name followed by parentheses (``()``) and may have arguments. For instance, the ``range`` function returns a list containing an arithmetic progression of integers: -.. code-block:: jinja +.. code-block:: twig {% for i in range(0, 3) %} {{ i }}, @@ -196,13 +199,15 @@ progression of integers: Go to the :doc:`functions<functions/index>` page to learn more about the built-in functions. +.. _named-arguments: + Named Arguments --------------- .. versionadded:: 1.12 Support for named arguments was added in Twig 1.12. -.. code-block:: jinja +.. code-block:: twig {% for i in range(low=1, high=10, step=2) %} {{ i }}, @@ -211,7 +216,7 @@ Named Arguments Using named arguments makes your templates more explicit about the meaning of the values you pass as arguments: -.. code-block:: jinja +.. code-block:: twig {{ data|convert_encoding('UTF-8', 'iso-2022-jp') }} @@ -222,7 +227,7 @@ the values you pass as arguments: Named arguments also allow you to skip some arguments for which you don't want to change the default value: -.. code-block:: jinja +.. code-block:: twig {# the first argument is the date format, which defaults to the global date format if null is passed #} {{ "now"|date(null, "Europe/Paris") }} @@ -233,7 +238,7 @@ to change the default value: You can also use both positional and named arguments in one call, in which case positional arguments must always come before named arguments: -.. code-block:: jinja +.. code-block:: twig {{ "now"|date('d/m/Y H:i', timezone="Europe/Paris") }} @@ -253,7 +258,7 @@ blocks. For example, to display a list of users provided in a variable called ``users``, use the :doc:`for<tags/for>` tag: -.. code-block:: jinja +.. code-block:: twig <h1>Members</h1> <ul> @@ -264,7 +269,7 @@ For example, to display a list of users provided in a variable called The :doc:`if<tags/if>` tag can be used to test an expression: -.. code-block:: jinja +.. code-block:: twig {% if users|length > 0 %} <ul> @@ -283,7 +288,7 @@ To comment-out part of a line in a template, use the comment syntax ``{# ... #}``. This is useful for debugging or to add information for other template designers or yourself: -.. code-block:: jinja +.. code-block:: twig {# note: disabled template because we no longer use this {% for user in users %} @@ -297,7 +302,7 @@ Including other Templates The :doc:`include<functions/include>` function is useful to include a template and return the rendered content of that template into the current one: -.. code-block:: jinja +.. code-block:: twig {{ include('sidebar.html') }} @@ -305,7 +310,7 @@ By default, included templates have access to the same context as the template which includes them. This means that any variable defined in the main template will be available in the included template too: -.. code-block:: jinja +.. code-block:: twig {% for box in boxes %} {{ include('render_box.html') }} @@ -313,11 +318,11 @@ will be available in the included template too: The included template ``render_box.html`` is able to access the ``box`` variable. -The filename of the template depends on the template loader. For instance, the -``Twig_Loader_Filesystem`` allows you to access other templates by giving the +The name of the template depends on the template loader. For instance, the +``\Twig\Loader\FilesystemLoader`` allows you to access other templates by giving the filename. You can access templates in subdirectories with a slash: -.. code-block:: jinja +.. code-block:: twig {{ include('sections/articles/sidebar.html') }} @@ -331,13 +336,12 @@ allows you to build a base "skeleton" template that contains all the common elements of your site and defines **blocks** that child templates can override. -Sounds complicated but it is very basic. It's easier to understand it by -starting with an example. +It's easier to understand the concept by starting with an example. -Let's define a base template, ``base.html``, which defines a simple HTML -skeleton document that you might use for a simple two-column page: +Let's define a base template, ``base.html``, which defines an HTML skeleton +document that might be used for a two-column page: -.. code-block:: html+jinja +.. code-block:: html+twig <!DOCTYPE html> <html> @@ -364,7 +368,7 @@ template. A child template might look like this: -.. code-block:: jinja +.. code-block:: twig {% extends "base.html" %} @@ -394,7 +398,7 @@ It's possible to render the contents of the parent block by using the :doc:`parent<functions/parent>` function. This gives back the results of the parent block: -.. code-block:: jinja +.. code-block:: twig {% block sidebar %} <h3>Table Of Contents</h3> @@ -410,9 +414,8 @@ parent block: .. note:: - Twig also supports multiple inheritance with the so called horizontal reuse - with the help of the :doc:`use<tags/use>` tag. This is an advanced feature - hardly ever needed in regular templates. + Twig also supports multiple inheritance via "horizontal reuse" with the help + of the :doc:`use<tags/use>` tag. HTML Escaping ------------- @@ -430,21 +433,19 @@ The automatic escaping strategy can be configured via the Working with Manual Escaping ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -If manual escaping is enabled, it is **your** responsibility to escape -variables if needed. What to escape? Any variable you don't trust. +If manual escaping is enabled, it is **your** responsibility to escape variables +if needed. What to escape? Any variable that comes from an untrusted source. -Escaping works by piping the variable through the -:doc:`escape<filters/escape>` or ``e`` filter: +Escaping works by using the :doc:`escape<filters/escape>` or ``e`` filter: -.. code-block:: jinja +.. code-block:: twig {{ user.username|e }} By default, the ``escape`` filter uses the ``html`` strategy, but depending on -the escaping context, you might want to explicitly use any other available -strategies: +the escaping context, you might want to explicitly use an other strategy: -.. code-block:: jinja +.. code-block:: twig {{ user.username|e('js') }} {{ user.username|e('css') }} @@ -458,7 +459,7 @@ Whether automatic escaping is enabled or not, you can mark a section of a template to be escaped or not by using the :doc:`autoescape<tags/autoescape>` tag: -.. code-block:: jinja +.. code-block:: twig {% autoescape %} Everything will be automatically escaped in this block (using the HTML strategy) @@ -468,7 +469,7 @@ By default, auto-escaping uses the ``html`` escaping strategy. If you output variables in other contexts, you need to explicitly escape them with the appropriate escaping strategy: -.. code-block:: jinja +.. code-block:: twig {% autoescape 'js' %} Everything will be automatically escaped in this block (using the JS strategy) @@ -485,7 +486,7 @@ variable you have to use a trick. The easiest way is to output the variable delimiter (``{{``) by using a variable expression: -.. code-block:: jinja +.. code-block:: twig {{ '{{' }} @@ -498,70 +499,27 @@ Macros .. versionadded:: 1.12 Support for default argument values was added in Twig 1.12. -Macros are comparable with functions in regular programming languages. They -are useful to reuse often used HTML fragments to not repeat yourself. - -A macro is defined via the :doc:`macro<tags/macro>` tag. Here is a small example -(subsequently called ``forms.html``) of a macro that renders a form element: - -.. code-block:: jinja - - {% macro input(name, value, type, size) %} - <input type="{{ type|default('text') }}" name="{{ name }}" value="{{ value|e }}" size="{{ size|default(20) }}" /> - {% endmacro %} - -Macros can be defined in any template, and need to be "imported" via the -:doc:`import<tags/import>` tag before being used: - -.. code-block:: jinja - - {% import "forms.html" as forms %} - - <p>{{ forms.input('username') }}</p> - -Alternatively, you can import individual macro names from a template into the -current namespace via the :doc:`from<tags/from>` tag and optionally alias them: - -.. code-block:: jinja - - {% from 'forms.html' import input as input_field %} - - <dl> - <dt>Username</dt> - <dd>{{ input_field('username') }}</dd> - <dt>Password</dt> - <dd>{{ input_field('password', '', 'password') }}</dd> - </dl> - -A default value can also be defined for macro arguments when not provided in a -macro call: - -.. code-block:: jinja - - {% macro input(name, value = "", type = "text", size = 20) %} - <input type="{{ type }}" name="{{ name }}" value="{{ value|e }}" size="{{ size }}" /> - {% endmacro %} - -If extra positional arguments are passed to a macro call, they end up in the -special ``varargs`` variable as a list of values. +Macros are comparable with functions in regular programming languages. They are +useful to reuse HTML fragments to not repeat yourself. They are described in the +:doc:`macro<tags/macro>` tag documentation. .. _twig-expressions: Expressions ----------- -Twig allows expressions everywhere. These work very similar to regular PHP and -even if you're not working with PHP you should feel comfortable with it. +Twig allows expressions everywhere. .. note:: - The operator precedence is as follows, with the lowest-precedence - operators listed first: ``b-and``, ``b-xor``, ``b-or``, ``or``, ``and``, - ``==``, ``!=``, ``<``, ``>``, ``>=``, ``<=``, ``in``, ``matches``, - ``starts with``, ``ends with``, ``..``, ``+``, ``-``, ``~``, ``*``, ``/``, - ``//``, ``%``, ``is``, ``**``, ``|``, ``[]``, and ``.``: + The operator precedence is as follows, with the lowest-precedence operators + listed first: ``?:`` (ternary operator), ``b-and``, ``b-xor``, ``b-or``, + ``or``, ``and``, ``==``, ``!=``, ``<``, ``>``, ``>=``, ``<=``, ``in``, + ``matches``, ``starts with``, ``ends with``, ``..``, ``+``, ``-``, ``~``, + ``*``, ``/``, ``//``, ``%``, ``is`` (tests), ``**``, ``??``, ``|`` + (filters), ``[]``, and ``.``: - .. code-block:: jinja + .. code-block:: twig {% set greeting = 'Hello ' %} {% set name = 'Fabien' %} @@ -589,7 +547,7 @@ exist: backslash (e.g. ``'c:\Program Files'``) escape it by doubling it (e.g. ``'c:\\Program Files'``). -* ``42`` / ``42.23``: Integers and floating point numbers are created by just +* ``42`` / ``42.23``: Integers and floating point numbers are created by writing the number down. If a dot is present the number is a float, otherwise an integer. @@ -599,7 +557,7 @@ exist: * ``{"foo": "bar"}``: Hashes are defined by a list of keys and values separated by a comma (``,``) and wrapped with curly braces (``{}``): - .. code-block:: jinja + .. code-block:: twig {# keys as string #} { 'foo': 'foo', 'bar': 'bar' } @@ -622,22 +580,22 @@ exist: Arrays and hashes can be nested: -.. code-block:: jinja +.. code-block:: twig {% set foo = [1, {"foo": "bar"}] %} .. tip:: Using double-quoted or single-quoted strings has no impact on performance - but string interpolation is only supported in double-quoted strings. + but :ref:`string interpolation <templates-string-interpolation>` is only + supported in double-quoted strings. Math ~~~~ -Twig allows you to calculate with values. This is rarely useful in templates -but exists for completeness' sake. The following operators are supported: +Twig allows you to do math in templates; the following operators are supported: -* ``+``: Adds two objects together (the operands are casted to numbers). ``{{ +* ``+``: Adds two numbers together (the operands are casted to numbers). ``{{ 1 + 1 }}`` is ``2``. * ``-``: Subtracts the second number from the first one. ``{{ 3 - 2 }}`` is @@ -659,6 +617,8 @@ but exists for completeness' sake. The following operators are supported: * ``**``: Raises the left operand to the power of the right operand. ``{{ 2 ** 3 }}`` would return ``8``. +.. _template_logic: + Logic ~~~~~ @@ -674,7 +634,7 @@ You can combine multiple expressions with the following operators: .. note:: - Twig also support bitwise operators (``b-and``, ``b-xor``, and ``b-or``). + Twig also supports bitwise operators (``b-and``, ``b-xor``, and ``b-or``). .. note:: @@ -689,7 +649,7 @@ The following comparison operators are supported in any expression: ``==``, You can also check if a string ``starts with`` or ``ends with`` another string: -.. code-block:: jinja +.. code-block:: twig {% if 'Fabien' starts with 'F' %} {% endif %} @@ -702,7 +662,7 @@ string: For complex string comparisons, the ``matches`` operator allows you to use `regular expressions`_: - .. code-block:: jinja + .. code-block:: twig {% if phone matches '/^[\\d\\.]+$/' %} {% endif %} @@ -710,11 +670,10 @@ string: Containment Operator ~~~~~~~~~~~~~~~~~~~~ -The ``in`` operator performs containment test. +The ``in`` operator performs containment test. It returns ``true`` if the left +operand is contained in the right: -It returns ``true`` if the left operand is contained in the right: - -.. code-block:: jinja +.. code-block:: twig {# returns true #} @@ -729,7 +688,7 @@ It returns ``true`` if the left operand is contained in the right: To perform a negative test, use the ``not in`` operator: -.. code-block:: jinja +.. code-block:: twig {% if 1 not in [1, 2, 3] %} @@ -742,7 +701,7 @@ Test Operator The ``is`` operator performs tests. Tests can be used to test a variable against a common expression. The right operand is name of the test: -.. code-block:: jinja +.. code-block:: twig {# find out if a variable is odd #} @@ -750,13 +709,13 @@ a common expression. The right operand is name of the test: Tests can accept arguments too: -.. code-block:: jinja +.. code-block:: twig {% if post.status is constant('Post::PUBLISHED') %} Tests can be negated by using the ``is not`` operator: -.. code-block:: jinja +.. code-block:: twig {% if post.status is not constant('Post::PUBLISHED') %} @@ -777,9 +736,9 @@ The following operators don't fit into any of the other categories: * ``|``: Applies a filter. * ``..``: Creates a sequence based on the operand before and after the operator - (this is just syntactic sugar for the :doc:`range<functions/range>` function): + (this is syntactic sugar for the :doc:`range<functions/range>` function): - .. code-block:: jinja + .. code-block:: twig {{ 1..5 }} @@ -789,7 +748,7 @@ The following operators don't fit into any of the other categories: Note that you must use parentheses when combining it with the filter operator due to the :ref:`operator precedence rules <twig-expressions>`: - .. code-block:: jinja + .. code-block:: twig (1..5)|join(', ') @@ -797,11 +756,11 @@ The following operators don't fit into any of the other categories: " ~ name ~ "!" }}`` would return (assuming ``name`` is ``'John'``) ``Hello John!``. -* ``.``, ``[]``: Gets an attribute of an object. +* ``.``, ``[]``: Gets an attribute of a variable. * ``?:``: The ternary operator: - .. code-block:: jinja + .. code-block:: twig {{ foo ? 'yes' : 'no' }} @@ -811,11 +770,13 @@ The following operators don't fit into any of the other categories: * ``??``: The null-coalescing operator: - .. code-block:: jinja + .. code-block:: twig {# returns the value of foo if it is defined and not null, 'no' otherwise #} {{ foo ?? 'no' }} +.. _templates-string-interpolation: + String Interpolation ~~~~~~~~~~~~~~~~~~~~ @@ -826,7 +787,7 @@ String interpolation (``#{expression}``) allows any valid expression to appear within a *double-quoted string*. The result of evaluating that expression is inserted into the string: -.. code-block:: jinja +.. code-block:: twig {{ "foo #{bar} baz" }} {{ "foo #{1 + 2} baz" }} @@ -839,55 +800,73 @@ Whitespace Control .. versionadded:: 1.1 Tag level whitespace control was added in Twig 1.1. -The first newline after a template tag is removed automatically (like in PHP.) +.. versionadded:: 1.39 + Tag level Line whitespace control was added in Twig 1.39. + +The first newline after a template tag is removed automatically (like in PHP). Whitespace is not further modified by the template engine, so each whitespace (spaces, tabs, newlines etc.) is returned unchanged. -Use the ``spaceless`` tag to remove whitespace *between HTML tags*: +You can also control whitespace on a per tag level. By using the whitespace +control modifiers on your tags, you can trim leading and or trailing whitespace. -.. code-block:: jinja +Twig supports two modifiers: - {% spaceless %} - <div> - <strong>foo bar</strong> - </div> - {% endspaceless %} +* *Whitespace trimming* via the ``-`` modifier: Removes all whitespace + (including newlines); - {# output will be <div><strong>foo bar</strong></div> #} +* *Line whitespace trimming* via the ``~`` modifier: Removes all whitespace + (excluding newlines). Using this modifier on the right disables the default + removal of the first newline inherited from PHP. -In addition to the spaceless tag you can also control whitespace on a per tag -level. By using the whitespace control modifier on your tags, you can trim -leading and or trailing whitespace: +The modifiers can be used on either side of the tags like in ``{%-`` or ``-%}`` +and they consume all whitespace for that side of the tag. It is possible to use +the modifiers on one side of a tag or on both sides: -.. code-block:: jinja +.. code-block:: twig {% set value = 'no spaces' %} {#- No leading/trailing whitespace -#} {%- if true -%} {{- value -}} {%- endif -%} - {# output 'no spaces' #} -The above sample shows the default whitespace control modifier, and how you can -use it to remove whitespace around tags. Trimming space will consume all whitespace -for that side of the tag. It is possible to use whitespace trimming on one side -of a tag: + <li> + {{ value }} </li> + {# outputs '<li>\n no spaces </li>' #} -.. code-block:: jinja + <li> + {{- value }} </li> + {# outputs '<li>no spaces </li>' #} - {% set value = 'no spaces' %} - <li> {{- value }} </li> + <li> + {{~ value }} </li> + {# outputs '<li>\nno spaces </li>' #} - {# outputs '<li>no spaces </li>' #} +.. tip:: + + In addition to the whitespace modifiers, Twig also has a ``spaceless`` filter + that removes whitespace **between HTML tags**: + + .. code-block:: twig + + {% apply spaceless %} + <div> + <strong>foo bar</strong> + </div> + {% endapply %} + + {# output will be <div><strong>foo bar</strong></div> #} + + Note that the ``apply`` tag was introduced in Twig 1.40; use the ``filter`` + tag with previous versions. Extensions ---------- -Twig can be easily extended. - -If you are looking for new tags, filters, or functions, have a look at the Twig official -`extension repository`_. +Twig can be extended. If you are looking for new tags, filters, or functions, +have a look at the Twig official `extension repository`_. If you want to create your own, read the :ref:`Creating an Extension<creating_extensions>` chapter. @@ -898,12 +877,12 @@ Extension<creating_extensions>` chapter. .. _`Twig syntax plugin`: http://plugins.netbeans.org/plugin/37069/php-twig .. _`Twig plugin`: https://github.com/pulse00/Twig-Eclipse-Plugin .. _`Twig language definition`: https://github.com/gabrielcorpse/gedit-twig-template-language -.. _`extension repository`: http://github.com/twigphp/Twig-extensions +.. _`extension repository`: https://github.com/twigphp/Twig-extensions .. _`Twig syntax mode`: https://github.com/bobthecow/Twig-HTML.mode .. _`other Twig syntax mode`: https://github.com/muxx/Twig-HTML.mode .. _`Notepad++ Twig Highlighter`: https://github.com/Banane9/notepadplusplus-twig .. _`web-mode.el`: http://web-mode.org/ -.. _`regular expressions`: http://php.net/manual/en/pcre.pattern.php +.. _`regular expressions`: https://secure.php.net/manual/en/pcre.pattern.php .. _`PHP-twig for atom`: https://github.com/reesef/php-twig -.. _`TwigFiddle`: http://twigfiddle.com/ +.. _`TwigFiddle`: https://twigfiddle.com/ .. _`Twig pack`: https://marketplace.visualstudio.com/items?itemName=bajdzis.vscode-twig-pack diff --git a/vendor/twig/twig/doc/tests/constant.rst b/vendor/twig/twig/doc/tests/constant.rst index 8d0724a809da306d5ea39c65c675fb2e2b86de0e..98abf4d45dd7524a78841555febe345190748b26 100644 --- a/vendor/twig/twig/doc/tests/constant.rst +++ b/vendor/twig/twig/doc/tests/constant.rst @@ -7,7 +7,7 @@ ``constant`` checks if a variable has the exact same value as a constant. You can use either global constants or class constants: -.. code-block:: jinja +.. code-block:: twig {% if post.status is constant('Post::PUBLISHED') %} the status attribute is exactly the same as Post::PUBLISHED @@ -15,7 +15,7 @@ can use either global constants or class constants: You can test constants from object instances as well: -.. code-block:: jinja +.. code-block:: twig {% if post.status is constant('PUBLISHED', post) %} the status attribute is exactly the same as Post::PUBLISHED diff --git a/vendor/twig/twig/doc/tests/defined.rst b/vendor/twig/twig/doc/tests/defined.rst index 702ce72565ea333e67c52d1963887d7497d0347a..234a28988a014d65166d8b3c55a9d0cc6e13b362 100644 --- a/vendor/twig/twig/doc/tests/defined.rst +++ b/vendor/twig/twig/doc/tests/defined.rst @@ -4,7 +4,7 @@ ``defined`` checks if a variable is defined in the current context. This is very useful if you use the ``strict_variables`` option: -.. code-block:: jinja +.. code-block:: twig {# defined works with variable names #} {% if foo is defined %} @@ -23,7 +23,7 @@ useful if you use the ``strict_variables`` option: When using the ``defined`` test on an expression that uses variables in some method calls, be sure that they are all defined first: -.. code-block:: jinja +.. code-block:: twig {% if var is defined and foo.method(var) is defined %} ... diff --git a/vendor/twig/twig/doc/tests/divisibleby.rst b/vendor/twig/twig/doc/tests/divisibleby.rst index 6c693b2b47f04202b8ba161abaff8c1538a12364..0beea8a97a40854ace98e682301ea995a9cc9554 100644 --- a/vendor/twig/twig/doc/tests/divisibleby.rst +++ b/vendor/twig/twig/doc/tests/divisibleby.rst @@ -7,7 +7,7 @@ ``divisible by`` checks if a variable is divisible by a number: -.. code-block:: jinja +.. code-block:: twig {% if loop.index is divisible by(3) %} ... diff --git a/vendor/twig/twig/doc/tests/empty.rst b/vendor/twig/twig/doc/tests/empty.rst index 639cdcc39936db3f55e9d2ec3e2aa412fa2ac06c..b630c0ce403aa20583b617d728e6a5d384a49df3 100644 --- a/vendor/twig/twig/doc/tests/empty.rst +++ b/vendor/twig/twig/doc/tests/empty.rst @@ -14,7 +14,7 @@ return value of the ``count()`` method. For objects that implement the ``__toString()`` magic method (and not ``Countable``), it will check if an empty string is returned. -.. code-block:: jinja +.. code-block:: twig {% if foo is empty %} ... diff --git a/vendor/twig/twig/doc/tests/even.rst b/vendor/twig/twig/doc/tests/even.rst index 6ab5cc39a04d93c660546aa0045bd1fc465c97fa..5d9c87694a153533dbc522edbfc29c186769e870 100644 --- a/vendor/twig/twig/doc/tests/even.rst +++ b/vendor/twig/twig/doc/tests/even.rst @@ -3,7 +3,7 @@ ``even`` returns ``true`` if the given number is even: -.. code-block:: jinja +.. code-block:: twig {{ var is even }} diff --git a/vendor/twig/twig/doc/tests/iterable.rst b/vendor/twig/twig/doc/tests/iterable.rst index 89a172f7418eb95817e35162791ba785dbc153c4..f0bfc5fb93752d07cbb4931e84e14be14eef1530 100644 --- a/vendor/twig/twig/doc/tests/iterable.rst +++ b/vendor/twig/twig/doc/tests/iterable.rst @@ -6,7 +6,7 @@ ``iterable`` checks if a variable is an array or a traversable object: -.. code-block:: jinja +.. code-block:: twig {# evaluates to true if the foo variable is iterable #} {% if users is iterable %} diff --git a/vendor/twig/twig/doc/tests/null.rst b/vendor/twig/twig/doc/tests/null.rst index 44eec62e56b07a54855d0737cf8dd3ec927d0212..9ed93f6bb29dd1bf03e448acea5c14e1539f14b6 100644 --- a/vendor/twig/twig/doc/tests/null.rst +++ b/vendor/twig/twig/doc/tests/null.rst @@ -3,7 +3,7 @@ ``null`` returns ``true`` if the variable is ``null``: -.. code-block:: jinja +.. code-block:: twig {{ var is null }} diff --git a/vendor/twig/twig/doc/tests/odd.rst b/vendor/twig/twig/doc/tests/odd.rst index 9eece777623c41a175bf517d2b58487682e8120a..0546f83c5a654ac2d3f733b7534994633ef8b574 100644 --- a/vendor/twig/twig/doc/tests/odd.rst +++ b/vendor/twig/twig/doc/tests/odd.rst @@ -3,7 +3,7 @@ ``odd`` returns ``true`` if the given number is odd: -.. code-block:: jinja +.. code-block:: twig {{ var is odd }} diff --git a/vendor/twig/twig/doc/tests/sameas.rst b/vendor/twig/twig/doc/tests/sameas.rst index 16f904d5c6c1173eb7b6f747940db01e9eaa4e32..4fc267dbcba6ad9266390f19e5cae177858839f2 100644 --- a/vendor/twig/twig/doc/tests/sameas.rst +++ b/vendor/twig/twig/doc/tests/sameas.rst @@ -7,7 +7,7 @@ ``same as`` checks if a variable is the same as another variable. This is the equivalent to ``===`` in PHP: -.. code-block:: jinja +.. code-block:: twig {% if foo.attribute is same as(false) %} the foo attribute really is the 'false' PHP value diff --git a/vendor/twig/twig/drupal_test.sh b/vendor/twig/twig/drupal_test.sh new file mode 100644 index 0000000000000000000000000000000000000000..0374593c209106dc68a6b97b102462d2b9f451da --- /dev/null +++ b/vendor/twig/twig/drupal_test.sh @@ -0,0 +1,51 @@ +#!/bin/bash + +set -x +set -e + +REPO=`pwd` +cd /tmp +rm -rf drupal-twig-test +composer create-project --no-interaction drupal-composer/drupal-project:8.x-dev drupal-twig-test +cd drupal-twig-test +(cd vendor/twig && rm -rf twig && ln -sf $REPO twig) +echo '$config["system.logging"]["error_level"] = "verbose";' >> web/sites/default/settings.php +php ./web/core/scripts/drupal install --no-interaction demo_umami > output +perl -p -i -e 's/^([A-Za-z]+)\: (.+)$/export DRUPAL_\1=\2/' output +source output + +wget https://get.symfony.com/cli/installer -O - | bash +export PATH="$HOME/.symfony/bin:$PATH" +symfony server:start -d --no-tls +ENDPOINT=`symfony server:status -no-ansi | sed -E 's/^.+ http/http/'` + +curl -OLsS https://get.blackfire.io/blackfire-player.phar +chmod +x blackfire-player.phar +cat > drupal-tests.bkf <<EOF +name "Drupal tests" + +scenario + name "homepage" + set name "admin" + set pass "pass" + + visit url('/') + expect status_code() == 200 + click link('Articles') + expect status_code() == 200 + click link('Dairy-free and delicious milk chocolate') + expect body() matches "/Dairy\-free milk chocolate is made in largely the same way as regular chocolate/" + expect status_code() == 200 + click link('Log in') + expect status_code() == 200 + submit button("Log in") + param name name + param pass pass + expect status_code() == 303 + follow + expect status_code() == 200 + click link('Structure') + expect status_code() == 200 +EOF +./blackfire-player.phar run drupal-tests.bkf --endpoint=$ENDPOINT --variable name=$DRUPAL_Username --variable pass=$DRUPAL_Password +symfony server:stop diff --git a/vendor/twig/twig/ext/twig/php_twig.h b/vendor/twig/twig/ext/twig/php_twig.h index 7fc1601e8c1e2576f18644fb2a6ff8f387aa90da..79ac938df534b57217c957e3fffb4f2f30889793 100644 --- a/vendor/twig/twig/ext/twig/php_twig.h +++ b/vendor/twig/twig/ext/twig/php_twig.h @@ -15,7 +15,7 @@ #ifndef PHP_TWIG_H #define PHP_TWIG_H -#define PHP_TWIG_VERSION "1.35.0" +#define PHP_TWIG_VERSION "1.42.3" #include "php.h" diff --git a/vendor/twig/twig/ext/twig/twig.c b/vendor/twig/twig/ext/twig/twig.c index 6173c006728e5fa7cb9852f76ef455dcc074779f..171ed10bb8a57181dfb8a15d48bbd439514e8770 100644 --- a/vendor/twig/twig/ext/twig/twig.c +++ b/vendor/twig/twig/ext/twig/twig.c @@ -733,7 +733,7 @@ PHP_FUNCTION(twig_template_get_attributes) /* // array - if (Twig_Template::METHOD_CALL !== $type) { + if (\Twig\Template::METHOD_CALL !== $type) { $arrayItem = is_bool($item) || is_float($item) ? (int) $item : $item; if ((is_array($object) && array_key_exists($arrayItem, $object)) @@ -771,7 +771,7 @@ PHP_FUNCTION(twig_template_get_attributes) return; } /* - if (Twig_Template::ARRAY_CALL === $type) { + if (\Twig\Template::ARRAY_CALL === $type) { if ($isDefinedTest) { return false; } @@ -799,7 +799,7 @@ PHP_FUNCTION(twig_template_get_attributes) } else { $message = sprintf('Key "%s" for array with keys "%s" does not exist', $arrayItem, implode(', ', array_keys($object))); } - } elseif (Twig_Template::ARRAY_CALL === $type) { + } elseif (\Twig\Template::ARRAY_CALL === $type) { if (null === $object) { $message = sprintf('Impossible to access a key ("%s") on a null variable', $item); } else { @@ -810,7 +810,7 @@ PHP_FUNCTION(twig_template_get_attributes) } else { $message = sprintf('Impossible to access an attribute ("%s") on a %s variable ("%s")', $item, gettype($object), $object); } - throw new Twig_Error_Runtime($message, -1, $this->getTemplateName()); + throw new \Twig\Error\RuntimeError($message, -1, $this->getTemplateName()); } } */ @@ -870,11 +870,13 @@ PHP_FUNCTION(twig_template_get_attributes) if (null === $object) { $message = sprintf('Impossible to invoke a method ("%s") on a null variable', $item); + } elseif (is_array($object)) { + $message = sprintf('Impossible to invoke a method ("%s") on an array.', $item); } else { $message = sprintf('Impossible to invoke a method ("%s") on a %s variable ("%s")', $item, gettype($object), $object); } - throw new Twig_Error_Runtime($message, -1, $this->getTemplateName()); + throw new \Twig\Error\RuntimeError($message, -1, $this->getTemplateName()); } */ if (ignoreStrictCheck || !TWIG_CALL_BOOLEAN(TWIG_PROPERTY_CHAR(template, "env" TSRMLS_CC), "isStrictVariables" TSRMLS_CC)) { @@ -885,9 +887,9 @@ PHP_FUNCTION(twig_template_get_attributes) type_name = zend_zval_type_name(object); Z_ADDREF_P(object); if (Z_TYPE_P(object) == IS_NULL) { - convert_to_string_ex(&object); - - TWIG_RUNTIME_ERROR(template TSRMLS_CC, "Impossible to invoke a method (\"%s\") on a %s variable.", item, type_name); + TWIG_RUNTIME_ERROR(template TSRMLS_CC, "Impossible to invoke a method (\"%s\") on a null variable.", item); + } else if (Z_TYPE_P(object) == IS_ARRAY) { + TWIG_RUNTIME_ERROR(template TSRMLS_CC, "Impossible to invoke a method (\"%s\") on an array.", item); } else { convert_to_string_ex(&object); @@ -914,14 +916,14 @@ PHP_FUNCTION(twig_template_get_attributes) /* // object property - if (Twig_Template::METHOD_CALL !== $type && !$object instanceof Twig_Template) { + if (\Twig\Template::METHOD_CALL !== $type && !$object instanceof \Twig\Template) { if (isset($object->$item) || array_key_exists((string) $item, $object)) { if ($isDefinedTest) { return true; } - if ($this->env->hasExtension('Twig_Extension_Sandbox')) { - $this->env->getExtension('Twig_Extension_Sandbox')->checkPropertyAllowed($object, $item); + if ($this->env->hasExtension('\Twig\Extension\SandboxExtension')) { + $this->env->getExtension('\Twig\Extension\SandboxExtension')->checkPropertyAllowed($object, $item); } return $object->$item; @@ -956,8 +958,8 @@ PHP_FUNCTION(twig_template_get_attributes) // object method if (!isset(self::$cache[$class]['methods'])) { if ($object instanceof self) { - $ref = new ReflectionClass($class); - $methods = array(); + $ref = new \ReflectionClass($class); + $methods = []; foreach ($ref->getMethods(ReflectionMethod::IS_PUBLIC) as $refMethod) { $methodName = strtolower($refMethod->name); @@ -1027,7 +1029,7 @@ PHP_FUNCTION(twig_template_get_attributes) return null; } - throw new Twig_Error_Runtime(sprintf('Method "%s" for object "%s" does not exist.', $item, get_class($object)), -1, $this->getTemplateName()); + throw new \Twig\Error\RuntimeError(sprintf('Method "%s" for object "%s" does not exist.', $item, get_class($object)), -1, $this->getTemplateName()); } if ($isDefinedTest) { @@ -1059,8 +1061,8 @@ PHP_FUNCTION(twig_template_get_attributes) RETURN_TRUE; } /* - if ($this->env->hasExtension('Twig_Extension_Sandbox')) { - $this->env->getExtension('Twig_Extension_Sandbox')->checkMethodAllowed($object, $method); + if ($this->env->hasExtension('\Twig\Extension\SandboxExtension')) { + $this->env->getExtension('\Twig\Extension\SandboxExtension')->checkMethodAllowed($object, $method); } */ MAKE_STD_ZVAL(zmethod); @@ -1079,8 +1081,8 @@ PHP_FUNCTION(twig_template_get_attributes) // Some objects throw exceptions when they have __call, and the method we try // to call is not supported. If ignoreStrictCheck is true, we should return null. try { - $ret = call_user_func_array(array($object, $method), $arguments); - } catch (BadMethodCallException $e) { + $ret = call_user_func_array([$object, $method], $arguments); + } catch (\BadMethodCallException $e) { if ($call && ($ignoreStrictCheck || !$this->env->isStrictVariables())) { return null; } @@ -1115,7 +1117,7 @@ PHP_FUNCTION(twig_template_get_attributes) } @trigger_error($message, E_USER_DEPRECATED); - return $ret === '' ? '' : new Twig_Markup($ret, $this->env->getCharset()); + return $ret === '' ? '' : new \Twig\Markup($ret, $this->env->getCharset()); } return $ret; diff --git a/vendor/twig/twig/lib/Twig/Autoloader.php b/vendor/twig/twig/lib/Twig/Autoloader.php index 212af5445693aae29e8436f4a9d9661e043e0bed..e34e2144fcf5d2efc2254c6af80aba77678f266a 100644 --- a/vendor/twig/twig/lib/Twig/Autoloader.php +++ b/vendor/twig/twig/lib/Twig/Autoloader.php @@ -29,11 +29,7 @@ class Twig_Autoloader { @trigger_error('Using Twig_Autoloader is deprecated since version 1.21. Use Composer instead.', E_USER_DEPRECATED); - if (PHP_VERSION_ID < 50300) { - spl_autoload_register(array(__CLASS__, 'autoload')); - } else { - spl_autoload_register(array(__CLASS__, 'autoload'), true, $prepend); - } + spl_autoload_register([__CLASS__, 'autoload'], true, $prepend); } /** @@ -47,7 +43,9 @@ class Twig_Autoloader return; } - if (is_file($file = dirname(__FILE__).'/../'.str_replace(array('_', "\0"), array('/', ''), $class).'.php')) { + if (is_file($file = __DIR__.'/../'.str_replace(['_', "\0"], ['/', ''], $class).'.php')) { + require $file; + } elseif (is_file($file = __DIR__.'/../../src/'.str_replace(['Twig\\', '\\', "\0"], ['', '/', ''], $class).'.php')) { require $file; } } diff --git a/vendor/twig/twig/lib/Twig/BaseNodeVisitor.php b/vendor/twig/twig/lib/Twig/BaseNodeVisitor.php index d8ef02fb281cb314e3930bbf0f185d184e1458ad..fe99b25889b38b496656c083181609619d7ba9d0 100644 --- a/vendor/twig/twig/lib/Twig/BaseNodeVisitor.php +++ b/vendor/twig/twig/lib/Twig/BaseNodeVisitor.php @@ -1,54 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +use Twig\NodeVisitor\AbstractNodeVisitor; -/** - * Twig_BaseNodeVisitor can be used to make node visitors compatible with Twig 1.x and 2.x. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -abstract class Twig_BaseNodeVisitor implements Twig_NodeVisitorInterface -{ - final public function enterNode(Twig_NodeInterface $node, Twig_Environment $env) - { - if (!$node instanceof Twig_Node) { - throw new LogicException('Twig_BaseNodeVisitor only supports Twig_Node instances.'); - } - - return $this->doEnterNode($node, $env); - } +class_exists('Twig\NodeVisitor\AbstractNodeVisitor'); - final public function leaveNode(Twig_NodeInterface $node, Twig_Environment $env) +if (\false) { + class Twig_BaseNodeVisitor extends AbstractNodeVisitor { - if (!$node instanceof Twig_Node) { - throw new LogicException('Twig_BaseNodeVisitor only supports Twig_Node instances.'); - } - - return $this->doLeaveNode($node, $env); } - - /** - * Called before child nodes are visited. - * - * @return Twig_Node The modified node - */ - abstract protected function doEnterNode(Twig_Node $node, Twig_Environment $env); - - /** - * Called after child nodes are visited. - * - * @return Twig_Node|false The modified node or false if the node must be removed - */ - abstract protected function doLeaveNode(Twig_Node $node, Twig_Environment $env); } - -class_alias('Twig_BaseNodeVisitor', 'Twig\NodeVisitor\AbstractNodeVisitor', false); -class_exists('Twig_Environment'); -class_exists('Twig_Node'); diff --git a/vendor/twig/twig/lib/Twig/Cache/Filesystem.php b/vendor/twig/twig/lib/Twig/Cache/Filesystem.php index 65976282b46c2f11cdb6a31563907a22cfaafaab..ce957583e0f3cbdb6468f61faebebc6d00a3bc45 100644 --- a/vendor/twig/twig/lib/Twig/Cache/Filesystem.php +++ b/vendor/twig/twig/lib/Twig/Cache/Filesystem.php @@ -1,93 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +use Twig\Cache\FilesystemCache; -/** - * Implements a cache on the filesystem. - * - * @author Andrew Tch <andrew@noop.lv> - */ -class Twig_Cache_Filesystem implements Twig_CacheInterface -{ - const FORCE_BYTECODE_INVALIDATION = 1; +class_exists('Twig\Cache\FilesystemCache'); - private $directory; - private $options; - - /** - * @param $directory string The root cache directory - * @param $options int A set of options - */ - public function __construct($directory, $options = 0) - { - $this->directory = rtrim($directory, '\/').'/'; - $this->options = $options; - } - - public function generateKey($name, $className) - { - $hash = hash('sha256', $className); - - return $this->directory.$hash[0].$hash[1].'/'.$hash.'.php'; - } - - public function load($key) - { - if (file_exists($key)) { - @include_once $key; - } - } - - public function write($key, $content) - { - $dir = dirname($key); - if (!is_dir($dir)) { - if (false === @mkdir($dir, 0777, true)) { - if (PHP_VERSION_ID >= 50300) { - clearstatcache(true, $dir); - } - if (!is_dir($dir)) { - throw new RuntimeException(sprintf('Unable to create the cache directory (%s).', $dir)); - } - } - } elseif (!is_writable($dir)) { - throw new RuntimeException(sprintf('Unable to write in the cache directory (%s).', $dir)); - } - - $tmpFile = tempnam($dir, basename($key)); - if (false !== @file_put_contents($tmpFile, $content) && @rename($tmpFile, $key)) { - @chmod($key, 0666 & ~umask()); - - if (self::FORCE_BYTECODE_INVALIDATION == ($this->options & self::FORCE_BYTECODE_INVALIDATION)) { - // Compile cached file into bytecode cache - if (function_exists('opcache_invalidate')) { - opcache_invalidate($key, true); - } elseif (function_exists('apc_compile_file')) { - apc_compile_file($key); - } - } - - return; - } - - throw new RuntimeException(sprintf('Failed to write cache file "%s".', $key)); - } - - public function getTimestamp($key) +if (\false) { + class Twig_Cache_Filesystem extends FilesystemCache { - if (!file_exists($key)) { - return 0; - } - - return (int) @filemtime($key); } } - -class_alias('Twig_Cache_Filesystem', 'Twig\Cache\FilesystemCache', false); diff --git a/vendor/twig/twig/lib/Twig/Cache/Null.php b/vendor/twig/twig/lib/Twig/Cache/Null.php index 69d1d2f98a4e3722445b81a551c6f4e1ff9f52bc..5cfa40ec2946c7ade3d4e77f5ba6de48962fb4a8 100644 --- a/vendor/twig/twig/lib/Twig/Cache/Null.php +++ b/vendor/twig/twig/lib/Twig/Cache/Null.php @@ -1,40 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +use Twig\Cache\NullCache; -/** - * Implements a no-cache strategy. - * - * @final - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class Twig_Cache_Null implements Twig_CacheInterface -{ - public function generateKey($name, $className) - { - return ''; - } - - public function write($key, $content) - { - } +class_exists('Twig\Cache\NullCache'); - public function load($key) +if (\false) { + class Twig_Cache_Null extends NullCache { } - - public function getTimestamp($key) - { - return 0; - } } - -class_alias('Twig_Cache_Null', 'Twig\Cache\NullCache', false); diff --git a/vendor/twig/twig/lib/Twig/CacheInterface.php b/vendor/twig/twig/lib/Twig/CacheInterface.php index 776808bfe33ffd6269eb6f24abd72ecc963b328d..5d251dbd3c99b07aa7ea49d3e559bf6b37f3b1d0 100644 --- a/vendor/twig/twig/lib/Twig/CacheInterface.php +++ b/vendor/twig/twig/lib/Twig/CacheInterface.php @@ -1,58 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +use Twig\Cache\CacheInterface; -/** - * Interface implemented by cache classes. - * - * It is highly recommended to always store templates on the filesystem to - * benefit from the PHP opcode cache. This interface is mostly useful if you - * need to implement a custom strategy for storing templates on the filesystem. - * - * @author Andrew Tch <andrew@noop.lv> - */ -interface Twig_CacheInterface -{ - /** - * Generates a cache key for the given template class name. - * - * @param string $name The template name - * @param string $className The template class name - * - * @return string - */ - public function generateKey($name, $className); +class_exists('Twig\Cache\CacheInterface'); - /** - * Writes the compiled template to cache. - * - * @param string $key The cache key - * @param string $content The template representation as a PHP class - */ - public function write($key, $content); - - /** - * Loads a template from the cache. - * - * @param string $key The cache key - */ - public function load($key); - - /** - * Returns the modification timestamp of a key. - * - * @param string $key The cache key - * - * @return int - */ - public function getTimestamp($key); +if (\false) { + class Twig_CacheInterface extends CacheInterface + { + } } - -class_alias('Twig_CacheInterface', 'Twig\Cache\CacheInterface', false); diff --git a/vendor/twig/twig/lib/Twig/Compiler.php b/vendor/twig/twig/lib/Twig/Compiler.php index e90bc987d7a27bcc95236ad6373894e9d36f2f84..8d3811d2b84407ef906df5a96070a9bf09350460 100644 --- a/vendor/twig/twig/lib/Twig/Compiler.php +++ b/vendor/twig/twig/lib/Twig/Compiler.php @@ -1,284 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * (c) Armin Ronacher - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +use Twig\Compiler; -/** - * Compiles a node to PHP code. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class Twig_Compiler implements Twig_CompilerInterface -{ - protected $lastLine; - protected $source; - protected $indentation; - protected $env; - protected $debugInfo = array(); - protected $sourceOffset; - protected $sourceLine; - protected $filename; +class_exists('Twig\Compiler'); - public function __construct(Twig_Environment $env) +if (\false) { + class Twig_Compiler extends Compiler { - $this->env = $env; - } - - /** - * @deprecated since 1.25 (to be removed in 2.0) - */ - public function getFilename() - { - @trigger_error(sprintf('The %s() method is deprecated since version 1.25 and will be removed in 2.0.', __FUNCTION__), E_USER_DEPRECATED); - - return $this->filename; - } - - /** - * Returns the environment instance related to this compiler. - * - * @return Twig_Environment - */ - public function getEnvironment() - { - return $this->env; - } - - /** - * Gets the current PHP code after compilation. - * - * @return string The PHP code - */ - public function getSource() - { - return $this->source; - } - - /** - * Compiles a node. - * - * @param Twig_NodeInterface $node The node to compile - * @param int $indentation The current indentation - * - * @return $this - */ - public function compile(Twig_NodeInterface $node, $indentation = 0) - { - $this->lastLine = null; - $this->source = ''; - $this->debugInfo = array(); - $this->sourceOffset = 0; - // source code starts at 1 (as we then increment it when we encounter new lines) - $this->sourceLine = 1; - $this->indentation = $indentation; - - if ($node instanceof Twig_Node_Module) { - // to be removed in 2.0 - $this->filename = $node->getTemplateName(); - } - - $node->compile($this); - - return $this; - } - - public function subcompile(Twig_NodeInterface $node, $raw = true) - { - if (false === $raw) { - $this->source .= str_repeat(' ', $this->indentation * 4); - } - - $node->compile($this); - - return $this; - } - - /** - * Adds a raw string to the compiled code. - * - * @param string $string The string - * - * @return $this - */ - public function raw($string) - { - $this->source .= $string; - - return $this; - } - - /** - * Writes a string to the compiled code by adding indentation. - * - * @return $this - */ - public function write() - { - $strings = func_get_args(); - foreach ($strings as $string) { - $this->source .= str_repeat(' ', $this->indentation * 4).$string; - } - - return $this; - } - - /** - * Appends an indentation to the current PHP code after compilation. - * - * @return $this - * - * @deprecated since 1.27 (to be removed in 2.0). - */ - public function addIndentation() - { - @trigger_error('The '.__METHOD__.' method is deprecated since version 1.27 and will be removed in 2.0. Use write(\'\') instead.', E_USER_DEPRECATED); - - $this->source .= str_repeat(' ', $this->indentation * 4); - - return $this; - } - - /** - * Adds a quoted string to the compiled code. - * - * @param string $value The string - * - * @return $this - */ - public function string($value) - { - $this->source .= sprintf('"%s"', addcslashes($value, "\0\t\"\$\\")); - - return $this; - } - - /** - * Returns a PHP representation of a given value. - * - * @param mixed $value The value to convert - * - * @return $this - */ - public function repr($value) - { - if (is_int($value) || is_float($value)) { - if (false !== $locale = setlocale(LC_NUMERIC, '0')) { - setlocale(LC_NUMERIC, 'C'); - } - - $this->raw($value); - - if (false !== $locale) { - setlocale(LC_NUMERIC, $locale); - } - } elseif (null === $value) { - $this->raw('null'); - } elseif (is_bool($value)) { - $this->raw($value ? 'true' : 'false'); - } elseif (is_array($value)) { - $this->raw('array('); - $first = true; - foreach ($value as $key => $v) { - if (!$first) { - $this->raw(', '); - } - $first = false; - $this->repr($key); - $this->raw(' => '); - $this->repr($v); - } - $this->raw(')'); - } else { - $this->string($value); - } - - return $this; - } - - /** - * Adds debugging information. - * - * @return $this - */ - public function addDebugInfo(Twig_NodeInterface $node) - { - if ($node->getTemplateLine() != $this->lastLine) { - $this->write(sprintf("// line %d\n", $node->getTemplateLine())); - - // when mbstring.func_overload is set to 2 - // mb_substr_count() replaces substr_count() - // but they have different signatures! - if (((int) ini_get('mbstring.func_overload')) & 2) { - @trigger_error('Support for having "mbstring.func_overload" different from 0 is deprecated version 1.29 and will be removed in 2.0.', E_USER_DEPRECATED); - - // this is much slower than the "right" version - $this->sourceLine += mb_substr_count(mb_substr($this->source, $this->sourceOffset), "\n"); - } else { - $this->sourceLine += substr_count($this->source, "\n", $this->sourceOffset); - } - $this->sourceOffset = strlen($this->source); - $this->debugInfo[$this->sourceLine] = $node->getTemplateLine(); - - $this->lastLine = $node->getTemplateLine(); - } - - return $this; - } - - public function getDebugInfo() - { - ksort($this->debugInfo); - - return $this->debugInfo; - } - - /** - * Indents the generated code. - * - * @param int $step The number of indentation to add - * - * @return $this - */ - public function indent($step = 1) - { - $this->indentation += $step; - - return $this; - } - - /** - * Outdents the generated code. - * - * @param int $step The number of indentation to remove - * - * @return $this - * - * @throws LogicException When trying to outdent too much so the indentation would become negative - */ - public function outdent($step = 1) - { - // can't outdent by more steps than the current indentation level - if ($this->indentation < $step) { - throw new LogicException('Unable to call outdent() as the indentation would become negative.'); - } - - $this->indentation -= $step; - - return $this; - } - - public function getVarName() - { - return sprintf('__internal_%s', hash('sha256', uniqid(mt_rand(), true), false)); } } - -class_alias('Twig_Compiler', 'Twig\Compiler', false); -class_exists('Twig_Node'); diff --git a/vendor/twig/twig/lib/Twig/ContainerRuntimeLoader.php b/vendor/twig/twig/lib/Twig/ContainerRuntimeLoader.php index 814ab58bc35e158ce08891e28355688ece046186..b1f32f68233e2141a1d33f34a675d2507b59b6c2 100644 --- a/vendor/twig/twig/lib/Twig/ContainerRuntimeLoader.php +++ b/vendor/twig/twig/lib/Twig/ContainerRuntimeLoader.php @@ -1,39 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +use Twig\RuntimeLoader\ContainerRuntimeLoader; -use Psr\Container\ContainerInterface; +class_exists('Twig\RuntimeLoader\ContainerRuntimeLoader'); -/** - * Lazily loads Twig runtime implementations from a PSR-11 container. - * - * Note that the runtime services MUST use their class names as identifiers. - * - * @author Fabien Potencier <fabien@symfony.com> - * @author Robin Chalas <robin.chalas@gmail.com> - */ -class Twig_ContainerRuntimeLoader implements Twig_RuntimeLoaderInterface -{ - private $container; - - public function __construct(ContainerInterface $container) +if (\false) { + class Twig_ContainerRuntimeLoader extends ContainerRuntimeLoader { - $this->container = $container; - } - - public function load($class) - { - if ($this->container->has($class)) { - return $this->container->get($class); - } } } - -class_alias('Twig_ContainerRuntimeLoader', 'Twig\RuntimeLoader\ContainerRuntimeLoader', false); diff --git a/vendor/twig/twig/lib/Twig/Environment.php b/vendor/twig/twig/lib/Twig/Environment.php index 5de2f27fd37333d08d28bb8472ad59392797d2e5..8c056366ead28eae47432c0fcb747bdf485bac43 100644 --- a/vendor/twig/twig/lib/Twig/Environment.php +++ b/vendor/twig/twig/lib/Twig/Environment.php @@ -1,1600 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +use Twig\Environment; -/** - * Stores the Twig configuration. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class Twig_Environment -{ - const VERSION = '1.35.0'; - const VERSION_ID = 13500; - const MAJOR_VERSION = 1; - const MINOR_VERSION = 35; - const RELEASE_VERSION = 0; - const EXTRA_VERSION = ''; +class_exists('Twig\Environment'); - protected $charset; - protected $loader; - protected $debug; - protected $autoReload; - protected $cache; - protected $lexer; - protected $parser; - protected $compiler; - protected $baseTemplateClass; - protected $extensions; - protected $parsers; - protected $visitors; - protected $filters; - protected $tests; - protected $functions; - protected $globals; - protected $runtimeInitialized = false; - protected $extensionInitialized = false; - protected $loadedTemplates; - protected $strictVariables; - protected $unaryOperators; - protected $binaryOperators; - protected $templateClassPrefix = '__TwigTemplate_'; - protected $functionCallbacks = array(); - protected $filterCallbacks = array(); - protected $staging; - - private $originalCache; - private $bcWriteCacheFile = false; - private $bcGetCacheFilename = false; - private $lastModifiedExtension = 0; - private $extensionsByClass = array(); - private $runtimeLoaders = array(); - private $runtimes = array(); - private $optionsHash; - private $loading = array(); - - /** - * Constructor. - * - * Available options: - * - * * debug: When set to true, it automatically set "auto_reload" to true as - * well (default to false). - * - * * charset: The charset used by the templates (default to UTF-8). - * - * * base_template_class: The base template class to use for generated - * templates (default to Twig_Template). - * - * * cache: An absolute path where to store the compiled templates, - * a Twig_Cache_Interface implementation, - * or false to disable compilation cache (default). - * - * * auto_reload: Whether to reload the template if the original source changed. - * If you don't provide the auto_reload option, it will be - * determined automatically based on the debug value. - * - * * strict_variables: Whether to ignore invalid variables in templates - * (default to false). - * - * * autoescape: Whether to enable auto-escaping (default to html): - * * false: disable auto-escaping - * * true: equivalent to html - * * html, js: set the autoescaping to one of the supported strategies - * * name: set the autoescaping strategy based on the template name extension - * * PHP callback: a PHP callback that returns an escaping strategy based on the template "name" - * - * * optimizations: A flag that indicates which optimizations to apply - * (default to -1 which means that all optimizations are enabled; - * set it to 0 to disable). - * - * @param Twig_LoaderInterface $loader - * @param array $options An array of options - */ - public function __construct(Twig_LoaderInterface $loader = null, $options = array()) - { - if (null !== $loader) { - $this->setLoader($loader); - } else { - @trigger_error('Not passing a Twig_LoaderInterface as the first constructor argument of Twig_Environment is deprecated since version 1.21.', E_USER_DEPRECATED); - } - - $options = array_merge(array( - 'debug' => false, - 'charset' => 'UTF-8', - 'base_template_class' => 'Twig_Template', - 'strict_variables' => false, - 'autoescape' => 'html', - 'cache' => false, - 'auto_reload' => null, - 'optimizations' => -1, - ), $options); - - $this->debug = (bool) $options['debug']; - $this->charset = strtoupper($options['charset']); - $this->baseTemplateClass = $options['base_template_class']; - $this->autoReload = null === $options['auto_reload'] ? $this->debug : (bool) $options['auto_reload']; - $this->strictVariables = (bool) $options['strict_variables']; - $this->setCache($options['cache']); - - $this->addExtension(new Twig_Extension_Core()); - $this->addExtension(new Twig_Extension_Escaper($options['autoescape'])); - $this->addExtension(new Twig_Extension_Optimizer($options['optimizations'])); - $this->staging = new Twig_Extension_Staging(); - - // For BC - if (is_string($this->originalCache)) { - $r = new ReflectionMethod($this, 'writeCacheFile'); - if ($r->getDeclaringClass()->getName() !== __CLASS__) { - @trigger_error('The Twig_Environment::writeCacheFile method is deprecated since version 1.22 and will be removed in Twig 2.0.', E_USER_DEPRECATED); - - $this->bcWriteCacheFile = true; - } - - $r = new ReflectionMethod($this, 'getCacheFilename'); - if ($r->getDeclaringClass()->getName() !== __CLASS__) { - @trigger_error('The Twig_Environment::getCacheFilename method is deprecated since version 1.22 and will be removed in Twig 2.0.', E_USER_DEPRECATED); - - $this->bcGetCacheFilename = true; - } - } - } - - /** - * Gets the base template class for compiled templates. - * - * @return string The base template class name - */ - public function getBaseTemplateClass() - { - return $this->baseTemplateClass; - } - - /** - * Sets the base template class for compiled templates. - * - * @param string $class The base template class name - */ - public function setBaseTemplateClass($class) - { - $this->baseTemplateClass = $class; - $this->updateOptionsHash(); - } - - /** - * Enables debugging mode. - */ - public function enableDebug() - { - $this->debug = true; - $this->updateOptionsHash(); - } - - /** - * Disables debugging mode. - */ - public function disableDebug() - { - $this->debug = false; - $this->updateOptionsHash(); - } - - /** - * Checks if debug mode is enabled. - * - * @return bool true if debug mode is enabled, false otherwise - */ - public function isDebug() - { - return $this->debug; - } - - /** - * Enables the auto_reload option. - */ - public function enableAutoReload() - { - $this->autoReload = true; - } - - /** - * Disables the auto_reload option. - */ - public function disableAutoReload() - { - $this->autoReload = false; - } - - /** - * Checks if the auto_reload option is enabled. - * - * @return bool true if auto_reload is enabled, false otherwise - */ - public function isAutoReload() - { - return $this->autoReload; - } - - /** - * Enables the strict_variables option. - */ - public function enableStrictVariables() - { - $this->strictVariables = true; - $this->updateOptionsHash(); - } - - /** - * Disables the strict_variables option. - */ - public function disableStrictVariables() - { - $this->strictVariables = false; - $this->updateOptionsHash(); - } - - /** - * Checks if the strict_variables option is enabled. - * - * @return bool true if strict_variables is enabled, false otherwise - */ - public function isStrictVariables() - { - return $this->strictVariables; - } - - /** - * Gets the current cache implementation. - * - * @param bool $original Whether to return the original cache option or the real cache instance - * - * @return Twig_CacheInterface|string|false A Twig_CacheInterface implementation, - * an absolute path to the compiled templates, - * or false to disable cache - */ - public function getCache($original = true) - { - return $original ? $this->originalCache : $this->cache; - } - - /** - * Sets the current cache implementation. - * - * @param Twig_CacheInterface|string|false $cache A Twig_CacheInterface implementation, - * an absolute path to the compiled templates, - * or false to disable cache - */ - public function setCache($cache) - { - if (is_string($cache)) { - $this->originalCache = $cache; - $this->cache = new Twig_Cache_Filesystem($cache); - } elseif (false === $cache) { - $this->originalCache = $cache; - $this->cache = new Twig_Cache_Null(); - } elseif (null === $cache) { - @trigger_error('Using "null" as the cache strategy is deprecated since version 1.23 and will be removed in Twig 2.0.', E_USER_DEPRECATED); - $this->originalCache = false; - $this->cache = new Twig_Cache_Null(); - } elseif ($cache instanceof Twig_CacheInterface) { - $this->originalCache = $this->cache = $cache; - } else { - throw new LogicException(sprintf('Cache can only be a string, false, or a Twig_CacheInterface implementation.')); - } - } - - /** - * Gets the cache filename for a given template. - * - * @param string $name The template name - * - * @return string|false The cache file name or false when caching is disabled - * - * @deprecated since 1.22 (to be removed in 2.0) - */ - public function getCacheFilename($name) - { - @trigger_error(sprintf('The %s method is deprecated since version 1.22 and will be removed in Twig 2.0.', __METHOD__), E_USER_DEPRECATED); - - $key = $this->cache->generateKey($name, $this->getTemplateClass($name)); - - return !$key ? false : $key; - } - - /** - * Gets the template class associated with the given string. - * - * The generated template class is based on the following parameters: - * - * * The cache key for the given template; - * * The currently enabled extensions; - * * Whether the Twig C extension is available or not; - * * PHP version; - * * Twig version; - * * Options with what environment was created. - * - * @param string $name The name for which to calculate the template class name - * @param int|null $index The index if it is an embedded template - * - * @return string The template class name - */ - public function getTemplateClass($name, $index = null) - { - $key = $this->getLoader()->getCacheKey($name).$this->optionsHash; - - return $this->templateClassPrefix.hash('sha256', $key).(null === $index ? '' : '_'.$index); - } - - /** - * Gets the template class prefix. - * - * @return string The template class prefix - * - * @deprecated since 1.22 (to be removed in 2.0) - */ - public function getTemplateClassPrefix() - { - @trigger_error(sprintf('The %s method is deprecated since version 1.22 and will be removed in Twig 2.0.', __METHOD__), E_USER_DEPRECATED); - - return $this->templateClassPrefix; - } - - /** - * Renders a template. - * - * @param string $name The template name - * @param array $context An array of parameters to pass to the template - * - * @return string The rendered template - * - * @throws Twig_Error_Loader When the template cannot be found - * @throws Twig_Error_Syntax When an error occurred during compilation - * @throws Twig_Error_Runtime When an error occurred during rendering - */ - public function render($name, array $context = array()) - { - return $this->loadTemplate($name)->render($context); - } - - /** - * Displays a template. - * - * @param string $name The template name - * @param array $context An array of parameters to pass to the template - * - * @throws Twig_Error_Loader When the template cannot be found - * @throws Twig_Error_Syntax When an error occurred during compilation - * @throws Twig_Error_Runtime When an error occurred during rendering - */ - public function display($name, array $context = array()) - { - $this->loadTemplate($name)->display($context); - } - - /** - * Loads a template. - * - * @param string|Twig_TemplateWrapper|Twig_Template $name The template name - * - * @throws Twig_Error_Loader When the template cannot be found - * @throws Twig_Error_Runtime When a previously generated cache is corrupted - * @throws Twig_Error_Syntax When an error occurred during compilation - * - * @return Twig_TemplateWrapper - */ - public function load($name) - { - if ($name instanceof Twig_TemplateWrapper) { - return $name; - } - - if ($name instanceof Twig_Template) { - return new Twig_TemplateWrapper($this, $name); - } - - return new Twig_TemplateWrapper($this, $this->loadTemplate($name)); - } - - /** - * Loads a template internal representation. - * - * This method is for internal use only and should never be called - * directly. - * - * @param string $name The template name - * @param int $index The index if it is an embedded template - * - * @return Twig_TemplateInterface A template instance representing the given template name - * - * @throws Twig_Error_Loader When the template cannot be found - * @throws Twig_Error_Runtime When a previously generated cache is corrupted - * @throws Twig_Error_Syntax When an error occurred during compilation - * - * @internal - */ - public function loadTemplate($name, $index = null) - { - $cls = $mainCls = $this->getTemplateClass($name); - if (null !== $index) { - $cls .= '_'.$index; - } - - if (isset($this->loadedTemplates[$cls])) { - return $this->loadedTemplates[$cls]; - } - - if (!class_exists($cls, false)) { - if ($this->bcGetCacheFilename) { - $key = $this->getCacheFilename($name); - } else { - $key = $this->cache->generateKey($name, $mainCls); - } - - if (!$this->isAutoReload() || $this->isTemplateFresh($name, $this->cache->getTimestamp($key))) { - $this->cache->load($key); - } - - if (!class_exists($cls, false)) { - $loader = $this->getLoader(); - if (!$loader instanceof Twig_SourceContextLoaderInterface) { - $source = new Twig_Source($loader->getSource($name), $name); - } else { - $source = $loader->getSourceContext($name); - } - - $content = $this->compileSource($source); - - if ($this->bcWriteCacheFile) { - $this->writeCacheFile($key, $content); - } else { - $this->cache->write($key, $content); - $this->cache->load($key); - } - - if (!class_exists($mainCls, false)) { - /* Last line of defense if either $this->bcWriteCacheFile was used, - * $this->cache is implemented as a no-op or we have a race condition - * where the cache was cleared between the above calls to write to and load from - * the cache. - */ - eval('?>'.$content); - } - } - - if (!class_exists($cls, false)) { - throw new Twig_Error_Runtime(sprintf('Failed to load Twig template "%s", index "%s": cache is corrupted.', $name, $index), -1, $source); - } - } - - if (!$this->runtimeInitialized) { - $this->initRuntime(); - } - - if (isset($this->loading[$cls])) { - throw new Twig_Error_Runtime(sprintf('Circular reference detected for Twig template "%s", path: %s.', $name, implode(' -> ', array_merge($this->loading, array($name))))); - } - - $this->loading[$cls] = $name; - - try { - $this->loadedTemplates[$cls] = new $cls($this); - unset($this->loading[$cls]); - } catch (\Exception $e) { - unset($this->loading[$cls]); - - throw $e; - } - - return $this->loadedTemplates[$cls]; - } - - /** - * Creates a template from source. - * - * This method should not be used as a generic way to load templates. - * - * @param string $template The template name - * - * @return Twig_Template A template instance representing the given template name - * - * @throws Twig_Error_Loader When the template cannot be found - * @throws Twig_Error_Syntax When an error occurred during compilation - */ - public function createTemplate($template) - { - $name = sprintf('__string_template__%s', hash('sha256', $template, false)); - - $loader = new Twig_Loader_Chain(array( - new Twig_Loader_Array(array($name => $template)), - $current = $this->getLoader(), - )); - - $this->setLoader($loader); - try { - $template = $this->loadTemplate($name); - } catch (Exception $e) { - $this->setLoader($current); - - throw $e; - } catch (Throwable $e) { - $this->setLoader($current); - - throw $e; - } - $this->setLoader($current); - - return $template; - } - - /** - * Returns true if the template is still fresh. - * - * Besides checking the loader for freshness information, - * this method also checks if the enabled extensions have - * not changed. - * - * @param string $name The template name - * @param int $time The last modification time of the cached template - * - * @return bool true if the template is fresh, false otherwise - */ - public function isTemplateFresh($name, $time) - { - if (0 === $this->lastModifiedExtension) { - foreach ($this->extensions as $extension) { - $r = new ReflectionObject($extension); - if (file_exists($r->getFileName()) && ($extensionTime = filemtime($r->getFileName())) > $this->lastModifiedExtension) { - $this->lastModifiedExtension = $extensionTime; - } - } - } - - return $this->lastModifiedExtension <= $time && $this->getLoader()->isFresh($name, $time); - } - - /** - * Tries to load a template consecutively from an array. - * - * Similar to loadTemplate() but it also accepts Twig_TemplateInterface instances and an array - * of templates where each is tried to be loaded. - * - * @param string|Twig_Template|array $names A template or an array of templates to try consecutively - * - * @return Twig_Template - * - * @throws Twig_Error_Loader When none of the templates can be found - * @throws Twig_Error_Syntax When an error occurred during compilation - */ - public function resolveTemplate($names) - { - if (!is_array($names)) { - $names = array($names); - } - - foreach ($names as $name) { - if ($name instanceof Twig_Template) { - return $name; - } - - try { - return $this->loadTemplate($name); - } catch (Twig_Error_Loader $e) { - } - } - - if (1 === count($names)) { - throw $e; - } - - throw new Twig_Error_Loader(sprintf('Unable to find one of the following templates: "%s".', implode('", "', $names))); - } - - /** - * Clears the internal template cache. - * - * @deprecated since 1.18.3 (to be removed in 2.0) - */ - public function clearTemplateCache() - { - @trigger_error(sprintf('The %s method is deprecated since version 1.18.3 and will be removed in Twig 2.0.', __METHOD__), E_USER_DEPRECATED); - - $this->loadedTemplates = array(); - } - - /** - * Clears the template cache files on the filesystem. - * - * @deprecated since 1.22 (to be removed in 2.0) - */ - public function clearCacheFiles() - { - @trigger_error(sprintf('The %s method is deprecated since version 1.22 and will be removed in Twig 2.0.', __METHOD__), E_USER_DEPRECATED); - - if (is_string($this->originalCache)) { - foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator($this->originalCache), RecursiveIteratorIterator::LEAVES_ONLY) as $file) { - if ($file->isFile()) { - @unlink($file->getPathname()); - } - } - } - } - - /** - * Gets the Lexer instance. - * - * @return Twig_LexerInterface - * - * @deprecated since 1.25 (to be removed in 2.0) - */ - public function getLexer() - { - @trigger_error(sprintf('The %s() method is deprecated since version 1.25 and will be removed in 2.0.', __FUNCTION__), E_USER_DEPRECATED); - - if (null === $this->lexer) { - $this->lexer = new Twig_Lexer($this); - } - - return $this->lexer; - } - - public function setLexer(Twig_LexerInterface $lexer) - { - $this->lexer = $lexer; - } - - /** - * Tokenizes a source code. - * - * @param string|Twig_Source $source The template source code - * @param string $name The template name (deprecated) - * - * @return Twig_TokenStream - * - * @throws Twig_Error_Syntax When the code is syntactically wrong - */ - public function tokenize($source, $name = null) - { - if (!$source instanceof Twig_Source) { - @trigger_error(sprintf('Passing a string as the $source argument of %s() is deprecated since version 1.27. Pass a Twig_Source instance instead.', __METHOD__), E_USER_DEPRECATED); - $source = new Twig_Source($source, $name); - } - - if (null === $this->lexer) { - $this->lexer = new Twig_Lexer($this); - } - - return $this->lexer->tokenize($source); - } - - /** - * Gets the Parser instance. - * - * @return Twig_ParserInterface - * - * @deprecated since 1.25 (to be removed in 2.0) - */ - public function getParser() - { - @trigger_error(sprintf('The %s() method is deprecated since version 1.25 and will be removed in 2.0.', __FUNCTION__), E_USER_DEPRECATED); - - if (null === $this->parser) { - $this->parser = new Twig_Parser($this); - } - - return $this->parser; - } - - public function setParser(Twig_ParserInterface $parser) - { - $this->parser = $parser; - } - - /** - * Converts a token stream to a node tree. - * - * @return Twig_Node_Module - * - * @throws Twig_Error_Syntax When the token stream is syntactically or semantically wrong - */ - public function parse(Twig_TokenStream $stream) - { - if (null === $this->parser) { - $this->parser = new Twig_Parser($this); - } - - return $this->parser->parse($stream); - } - - /** - * Gets the Compiler instance. - * - * @return Twig_CompilerInterface - * - * @deprecated since 1.25 (to be removed in 2.0) - */ - public function getCompiler() - { - @trigger_error(sprintf('The %s() method is deprecated since version 1.25 and will be removed in 2.0.', __FUNCTION__), E_USER_DEPRECATED); - - if (null === $this->compiler) { - $this->compiler = new Twig_Compiler($this); - } - - return $this->compiler; - } - - public function setCompiler(Twig_CompilerInterface $compiler) - { - $this->compiler = $compiler; - } - - /** - * Compiles a node and returns the PHP code. - * - * @return string The compiled PHP source code - */ - public function compile(Twig_NodeInterface $node) - { - if (null === $this->compiler) { - $this->compiler = new Twig_Compiler($this); - } - - return $this->compiler->compile($node)->getSource(); - } - - /** - * Compiles a template source code. - * - * @param string|Twig_Source $source The template source code - * @param string $name The template name (deprecated) - * - * @return string The compiled PHP source code - * - * @throws Twig_Error_Syntax When there was an error during tokenizing, parsing or compiling - */ - public function compileSource($source, $name = null) - { - if (!$source instanceof Twig_Source) { - @trigger_error(sprintf('Passing a string as the $source argument of %s() is deprecated since version 1.27. Pass a Twig_Source instance instead.', __METHOD__), E_USER_DEPRECATED); - $source = new Twig_Source($source, $name); - } - - try { - return $this->compile($this->parse($this->tokenize($source))); - } catch (Twig_Error $e) { - $e->setSourceContext($source); - throw $e; - } catch (Exception $e) { - throw new Twig_Error_Syntax(sprintf('An exception has been thrown during the compilation of a template ("%s").', $e->getMessage()), -1, $source, $e); - } - } - - public function setLoader(Twig_LoaderInterface $loader) - { - if (!$loader instanceof Twig_SourceContextLoaderInterface && 0 !== strpos(get_class($loader), 'Mock_')) { - @trigger_error(sprintf('Twig loader "%s" should implement Twig_SourceContextLoaderInterface since version 1.27.', get_class($loader)), E_USER_DEPRECATED); - } - - $this->loader = $loader; - } - - /** - * Gets the Loader instance. - * - * @return Twig_LoaderInterface - */ - public function getLoader() - { - if (null === $this->loader) { - throw new LogicException('You must set a loader first.'); - } - - return $this->loader; - } - - /** - * Sets the default template charset. - * - * @param string $charset The default charset - */ - public function setCharset($charset) - { - $this->charset = strtoupper($charset); - } - - /** - * Gets the default template charset. - * - * @return string The default charset - */ - public function getCharset() - { - return $this->charset; - } - - /** - * Initializes the runtime environment. - * - * @deprecated since 1.23 (to be removed in 2.0) - */ - public function initRuntime() - { - $this->runtimeInitialized = true; - - foreach ($this->getExtensions() as $name => $extension) { - if (!$extension instanceof Twig_Extension_InitRuntimeInterface) { - $m = new ReflectionMethod($extension, 'initRuntime'); - - if ('Twig_Extension' !== $m->getDeclaringClass()->getName()) { - @trigger_error(sprintf('Defining the initRuntime() method in the "%s" extension is deprecated since version 1.23. Use the `needs_environment` option to get the Twig_Environment instance in filters, functions, or tests; or explicitly implement Twig_Extension_InitRuntimeInterface if needed (not recommended).', $name), E_USER_DEPRECATED); - } - } - - $extension->initRuntime($this); - } - } - - /** - * Returns true if the given extension is registered. - * - * @param string $class The extension class name - * - * @return bool Whether the extension is registered or not - */ - public function hasExtension($class) - { - $class = ltrim($class, '\\'); - if (!isset($this->extensionsByClass[$class]) && class_exists($class, false)) { - // For BC/FC with namespaced aliases - $class = new ReflectionClass($class); - $class = $class->name; - } - - if (isset($this->extensions[$class])) { - if ($class !== get_class($this->extensions[$class])) { - @trigger_error(sprintf('Referencing the "%s" extension by its name (defined by getName()) is deprecated since 1.26 and will be removed in Twig 2.0. Use the Fully Qualified Extension Class Name instead.', $class), E_USER_DEPRECATED); - } - - return true; - } - - return isset($this->extensionsByClass[$class]); - } - - /** - * Adds a runtime loader. - */ - public function addRuntimeLoader(Twig_RuntimeLoaderInterface $loader) - { - $this->runtimeLoaders[] = $loader; - } - - /** - * Gets an extension by class name. - * - * @param string $class The extension class name - * - * @return Twig_ExtensionInterface - */ - public function getExtension($class) - { - $class = ltrim($class, '\\'); - if (!isset($this->extensionsByClass[$class]) && class_exists($class, false)) { - // For BC/FC with namespaced aliases - $class = new ReflectionClass($class); - $class = $class->name; - } - - if (isset($this->extensions[$class])) { - if ($class !== get_class($this->extensions[$class])) { - @trigger_error(sprintf('Referencing the "%s" extension by its name (defined by getName()) is deprecated since 1.26 and will be removed in Twig 2.0. Use the Fully Qualified Extension Class Name instead.', $class), E_USER_DEPRECATED); - } - - return $this->extensions[$class]; - } - - if (!isset($this->extensionsByClass[$class])) { - throw new Twig_Error_Runtime(sprintf('The "%s" extension is not enabled.', $class)); - } - - return $this->extensionsByClass[$class]; - } - - /** - * Returns the runtime implementation of a Twig element (filter/function/test). - * - * @param string $class A runtime class name - * - * @return object The runtime implementation - * - * @throws Twig_Error_Runtime When the template cannot be found - */ - public function getRuntime($class) - { - if (isset($this->runtimes[$class])) { - return $this->runtimes[$class]; - } - - foreach ($this->runtimeLoaders as $loader) { - if (null !== $runtime = $loader->load($class)) { - return $this->runtimes[$class] = $runtime; - } - } - - throw new Twig_Error_Runtime(sprintf('Unable to load the "%s" runtime.', $class)); - } - - public function addExtension(Twig_ExtensionInterface $extension) - { - if ($this->extensionInitialized) { - throw new LogicException(sprintf('Unable to register extension "%s" as extensions have already been initialized.', $extension->getName())); - } - - $class = get_class($extension); - if ($class !== $extension->getName()) { - if (isset($this->extensions[$extension->getName()])) { - unset($this->extensions[$extension->getName()], $this->extensionsByClass[$class]); - @trigger_error(sprintf('The possibility to register the same extension twice ("%s") is deprecated since version 1.23 and will be removed in Twig 2.0. Use proper PHP inheritance instead.', $extension->getName()), E_USER_DEPRECATED); - } - } - - $this->lastModifiedExtension = 0; - $this->extensionsByClass[$class] = $extension; - $this->extensions[$extension->getName()] = $extension; - $this->updateOptionsHash(); - } - - /** - * Removes an extension by name. - * - * This method is deprecated and you should not use it. - * - * @param string $name The extension name - * - * @deprecated since 1.12 (to be removed in 2.0) - */ - public function removeExtension($name) - { - @trigger_error(sprintf('The %s method is deprecated since version 1.12 and will be removed in Twig 2.0.', __METHOD__), E_USER_DEPRECATED); - - if ($this->extensionInitialized) { - throw new LogicException(sprintf('Unable to remove extension "%s" as extensions have already been initialized.', $name)); - } - - $class = ltrim($name, '\\'); - if (!isset($this->extensionsByClass[$class]) && class_exists($class, false)) { - // For BC/FC with namespaced aliases - $class = new ReflectionClass($class); - $class = $class->name; - } - - if (isset($this->extensions[$class])) { - if ($class !== get_class($this->extensions[$class])) { - @trigger_error(sprintf('Referencing the "%s" extension by its name (defined by getName()) is deprecated since 1.26 and will be removed in Twig 2.0. Use the Fully Qualified Extension Class Name instead.', $class), E_USER_DEPRECATED); - } - - unset($this->extensions[$class]); - } - - unset($this->extensions[$class]); - $this->updateOptionsHash(); - } - - /** - * Registers an array of extensions. - * - * @param array $extensions An array of extensions - */ - public function setExtensions(array $extensions) - { - foreach ($extensions as $extension) { - $this->addExtension($extension); - } - } - - /** - * Returns all registered extensions. - * - * @return Twig_ExtensionInterface[] An array of extensions (keys are for internal usage only and should not be relied on) - */ - public function getExtensions() - { - return $this->extensions; - } - - public function addTokenParser(Twig_TokenParserInterface $parser) - { - if ($this->extensionInitialized) { - throw new LogicException('Unable to add a token parser as extensions have already been initialized.'); - } - - $this->staging->addTokenParser($parser); - } - - /** - * Gets the registered Token Parsers. - * - * @return Twig_TokenParserBrokerInterface - * - * @internal - */ - public function getTokenParsers() - { - if (!$this->extensionInitialized) { - $this->initExtensions(); - } - - return $this->parsers; - } - - /** - * Gets registered tags. - * - * Be warned that this method cannot return tags defined by Twig_TokenParserBrokerInterface classes. - * - * @return Twig_TokenParserInterface[] - * - * @internal - */ - public function getTags() - { - $tags = array(); - foreach ($this->getTokenParsers()->getParsers() as $parser) { - if ($parser instanceof Twig_TokenParserInterface) { - $tags[$parser->getTag()] = $parser; - } - } - - return $tags; - } - - public function addNodeVisitor(Twig_NodeVisitorInterface $visitor) - { - if ($this->extensionInitialized) { - throw new LogicException('Unable to add a node visitor as extensions have already been initialized.'); - } - - $this->staging->addNodeVisitor($visitor); - } - - /** - * Gets the registered Node Visitors. - * - * @return Twig_NodeVisitorInterface[] - * - * @internal - */ - public function getNodeVisitors() - { - if (!$this->extensionInitialized) { - $this->initExtensions(); - } - - return $this->visitors; - } - - /** - * Registers a Filter. - * - * @param string|Twig_SimpleFilter $name The filter name or a Twig_SimpleFilter instance - * @param Twig_FilterInterface|Twig_SimpleFilter $filter - */ - public function addFilter($name, $filter = null) - { - if (!$name instanceof Twig_SimpleFilter && !($filter instanceof Twig_SimpleFilter || $filter instanceof Twig_FilterInterface)) { - throw new LogicException('A filter must be an instance of Twig_FilterInterface or Twig_SimpleFilter.'); - } - - if ($name instanceof Twig_SimpleFilter) { - $filter = $name; - $name = $filter->getName(); - } else { - @trigger_error(sprintf('Passing a name as a first argument to the %s method is deprecated since version 1.21. Pass an instance of "Twig_SimpleFilter" instead when defining filter "%s".', __METHOD__, $name), E_USER_DEPRECATED); - } - - if ($this->extensionInitialized) { - throw new LogicException(sprintf('Unable to add filter "%s" as extensions have already been initialized.', $name)); - } - - $this->staging->addFilter($name, $filter); - } - - /** - * Get a filter by name. - * - * Subclasses may override this method and load filters differently; - * so no list of filters is available. - * - * @param string $name The filter name - * - * @return Twig_Filter|false A Twig_Filter instance or false if the filter does not exist - * - * @internal - */ - public function getFilter($name) - { - if (!$this->extensionInitialized) { - $this->initExtensions(); - } - - if (isset($this->filters[$name])) { - return $this->filters[$name]; - } - - foreach ($this->filters as $pattern => $filter) { - $pattern = str_replace('\\*', '(.*?)', preg_quote($pattern, '#'), $count); - - if ($count) { - if (preg_match('#^'.$pattern.'$#', $name, $matches)) { - array_shift($matches); - $filter->setArguments($matches); - - return $filter; - } - } - } - - foreach ($this->filterCallbacks as $callback) { - if (false !== $filter = call_user_func($callback, $name)) { - return $filter; - } - } - - return false; - } - - public function registerUndefinedFilterCallback($callable) - { - $this->filterCallbacks[] = $callable; - } - - /** - * Gets the registered Filters. - * - * Be warned that this method cannot return filters defined with registerUndefinedFilterCallback. - * - * @return Twig_FilterInterface[] - * - * @see registerUndefinedFilterCallback - * - * @internal - */ - public function getFilters() - { - if (!$this->extensionInitialized) { - $this->initExtensions(); - } - - return $this->filters; - } - - /** - * Registers a Test. - * - * @param string|Twig_SimpleTest $name The test name or a Twig_SimpleTest instance - * @param Twig_TestInterface|Twig_SimpleTest $test A Twig_TestInterface instance or a Twig_SimpleTest instance - */ - public function addTest($name, $test = null) - { - if (!$name instanceof Twig_SimpleTest && !($test instanceof Twig_SimpleTest || $test instanceof Twig_TestInterface)) { - throw new LogicException('A test must be an instance of Twig_TestInterface or Twig_SimpleTest.'); - } - - if ($name instanceof Twig_SimpleTest) { - $test = $name; - $name = $test->getName(); - } else { - @trigger_error(sprintf('Passing a name as a first argument to the %s method is deprecated since version 1.21. Pass an instance of "Twig_SimpleTest" instead when defining test "%s".', __METHOD__, $name), E_USER_DEPRECATED); - } - - if ($this->extensionInitialized) { - throw new LogicException(sprintf('Unable to add test "%s" as extensions have already been initialized.', $name)); - } - - $this->staging->addTest($name, $test); - } - - /** - * Gets the registered Tests. - * - * @return Twig_TestInterface[] - * - * @internal - */ - public function getTests() - { - if (!$this->extensionInitialized) { - $this->initExtensions(); - } - - return $this->tests; - } - - /** - * Gets a test by name. - * - * @param string $name The test name - * - * @return Twig_Test|false A Twig_Test instance or false if the test does not exist - * - * @internal - */ - public function getTest($name) +if (\false) { + class Twig_Environment extends Environment { - if (!$this->extensionInitialized) { - $this->initExtensions(); - } - - if (isset($this->tests[$name])) { - return $this->tests[$name]; - } - - return false; - } - - /** - * Registers a Function. - * - * @param string|Twig_SimpleFunction $name The function name or a Twig_SimpleFunction instance - * @param Twig_FunctionInterface|Twig_SimpleFunction $function - */ - public function addFunction($name, $function = null) - { - if (!$name instanceof Twig_SimpleFunction && !($function instanceof Twig_SimpleFunction || $function instanceof Twig_FunctionInterface)) { - throw new LogicException('A function must be an instance of Twig_FunctionInterface or Twig_SimpleFunction.'); - } - - if ($name instanceof Twig_SimpleFunction) { - $function = $name; - $name = $function->getName(); - } else { - @trigger_error(sprintf('Passing a name as a first argument to the %s method is deprecated since version 1.21. Pass an instance of "Twig_SimpleFunction" instead when defining function "%s".', __METHOD__, $name), E_USER_DEPRECATED); - } - - if ($this->extensionInitialized) { - throw new LogicException(sprintf('Unable to add function "%s" as extensions have already been initialized.', $name)); - } - - $this->staging->addFunction($name, $function); - } - - /** - * Get a function by name. - * - * Subclasses may override this method and load functions differently; - * so no list of functions is available. - * - * @param string $name function name - * - * @return Twig_Function|false A Twig_Function instance or false if the function does not exist - * - * @internal - */ - public function getFunction($name) - { - if (!$this->extensionInitialized) { - $this->initExtensions(); - } - - if (isset($this->functions[$name])) { - return $this->functions[$name]; - } - - foreach ($this->functions as $pattern => $function) { - $pattern = str_replace('\\*', '(.*?)', preg_quote($pattern, '#'), $count); - - if ($count) { - if (preg_match('#^'.$pattern.'$#', $name, $matches)) { - array_shift($matches); - $function->setArguments($matches); - - return $function; - } - } - } - - foreach ($this->functionCallbacks as $callback) { - if (false !== $function = call_user_func($callback, $name)) { - return $function; - } - } - - return false; - } - - public function registerUndefinedFunctionCallback($callable) - { - $this->functionCallbacks[] = $callable; - } - - /** - * Gets registered functions. - * - * Be warned that this method cannot return functions defined with registerUndefinedFunctionCallback. - * - * @return Twig_FunctionInterface[] - * - * @see registerUndefinedFunctionCallback - * - * @internal - */ - public function getFunctions() - { - if (!$this->extensionInitialized) { - $this->initExtensions(); - } - - return $this->functions; - } - - /** - * Registers a Global. - * - * New globals can be added before compiling or rendering a template; - * but after, you can only update existing globals. - * - * @param string $name The global name - * @param mixed $value The global value - */ - public function addGlobal($name, $value) - { - if ($this->extensionInitialized || $this->runtimeInitialized) { - if (null === $this->globals) { - $this->globals = $this->initGlobals(); - } - - if (!array_key_exists($name, $this->globals)) { - // The deprecation notice must be turned into the following exception in Twig 2.0 - @trigger_error(sprintf('Registering global variable "%s" at runtime or when the extensions have already been initialized is deprecated since version 1.21.', $name), E_USER_DEPRECATED); - //throw new LogicException(sprintf('Unable to add global "%s" as the runtime or the extensions have already been initialized.', $name)); - } - } - - if ($this->extensionInitialized || $this->runtimeInitialized) { - // update the value - $this->globals[$name] = $value; - } else { - $this->staging->addGlobal($name, $value); - } - } - - /** - * Gets the registered Globals. - * - * @return array An array of globals - * - * @internal - */ - public function getGlobals() - { - if (!$this->runtimeInitialized && !$this->extensionInitialized) { - return $this->initGlobals(); - } - - if (null === $this->globals) { - $this->globals = $this->initGlobals(); - } - - return $this->globals; - } - - /** - * Merges a context with the defined globals. - * - * @param array $context An array representing the context - * - * @return array The context merged with the globals - */ - public function mergeGlobals(array $context) - { - // we don't use array_merge as the context being generally - // bigger than globals, this code is faster. - foreach ($this->getGlobals() as $key => $value) { - if (!array_key_exists($key, $context)) { - $context[$key] = $value; - } - } - - return $context; - } - - /** - * Gets the registered unary Operators. - * - * @return array An array of unary operators - * - * @internal - */ - public function getUnaryOperators() - { - if (!$this->extensionInitialized) { - $this->initExtensions(); - } - - return $this->unaryOperators; - } - - /** - * Gets the registered binary Operators. - * - * @return array An array of binary operators - * - * @internal - */ - public function getBinaryOperators() - { - if (!$this->extensionInitialized) { - $this->initExtensions(); - } - - return $this->binaryOperators; - } - - /** - * @deprecated since 1.23 (to be removed in 2.0) - */ - public function computeAlternatives($name, $items) - { - @trigger_error(sprintf('The %s method is deprecated since version 1.23 and will be removed in Twig 2.0.', __METHOD__), E_USER_DEPRECATED); - - return Twig_Error_Syntax::computeAlternatives($name, $items); - } - - /** - * @internal - */ - protected function initGlobals() - { - $globals = array(); - foreach ($this->extensions as $name => $extension) { - if (!$extension instanceof Twig_Extension_GlobalsInterface) { - $m = new ReflectionMethod($extension, 'getGlobals'); - - if ('Twig_Extension' !== $m->getDeclaringClass()->getName()) { - @trigger_error(sprintf('Defining the getGlobals() method in the "%s" extension without explicitly implementing Twig_Extension_GlobalsInterface is deprecated since version 1.23.', $name), E_USER_DEPRECATED); - } - } - - $extGlob = $extension->getGlobals(); - if (!is_array($extGlob)) { - throw new UnexpectedValueException(sprintf('"%s::getGlobals()" must return an array of globals.', get_class($extension))); - } - - $globals[] = $extGlob; - } - - $globals[] = $this->staging->getGlobals(); - - return call_user_func_array('array_merge', $globals); - } - - /** - * @internal - */ - protected function initExtensions() - { - if ($this->extensionInitialized) { - return; - } - - $this->parsers = new Twig_TokenParserBroker(array(), array(), false); - $this->filters = array(); - $this->functions = array(); - $this->tests = array(); - $this->visitors = array(); - $this->unaryOperators = array(); - $this->binaryOperators = array(); - - foreach ($this->extensions as $extension) { - $this->initExtension($extension); - } - $this->initExtension($this->staging); - // Done at the end only, so that an exception during initialization does not mark the environment as initialized when catching the exception - $this->extensionInitialized = true; - } - - /** - * @internal - */ - protected function initExtension(Twig_ExtensionInterface $extension) - { - // filters - foreach ($extension->getFilters() as $name => $filter) { - if ($filter instanceof Twig_SimpleFilter) { - $name = $filter->getName(); - } else { - @trigger_error(sprintf('Using an instance of "%s" for filter "%s" is deprecated since version 1.21. Use Twig_SimpleFilter instead.', get_class($filter), $name), E_USER_DEPRECATED); - } - - $this->filters[$name] = $filter; - } - - // functions - foreach ($extension->getFunctions() as $name => $function) { - if ($function instanceof Twig_SimpleFunction) { - $name = $function->getName(); - } else { - @trigger_error(sprintf('Using an instance of "%s" for function "%s" is deprecated since version 1.21. Use Twig_SimpleFunction instead.', get_class($function), $name), E_USER_DEPRECATED); - } - - $this->functions[$name] = $function; - } - - // tests - foreach ($extension->getTests() as $name => $test) { - if ($test instanceof Twig_SimpleTest) { - $name = $test->getName(); - } else { - @trigger_error(sprintf('Using an instance of "%s" for test "%s" is deprecated since version 1.21. Use Twig_SimpleTest instead.', get_class($test), $name), E_USER_DEPRECATED); - } - - $this->tests[$name] = $test; - } - - // token parsers - foreach ($extension->getTokenParsers() as $parser) { - if ($parser instanceof Twig_TokenParserInterface) { - $this->parsers->addTokenParser($parser); - } elseif ($parser instanceof Twig_TokenParserBrokerInterface) { - @trigger_error('Registering a Twig_TokenParserBrokerInterface instance is deprecated since version 1.21.', E_USER_DEPRECATED); - - $this->parsers->addTokenParserBroker($parser); - } else { - throw new LogicException('getTokenParsers() must return an array of Twig_TokenParserInterface or Twig_TokenParserBrokerInterface instances.'); - } - } - - // node visitors - foreach ($extension->getNodeVisitors() as $visitor) { - $this->visitors[] = $visitor; - } - - // operators - if ($operators = $extension->getOperators()) { - if (!is_array($operators)) { - throw new InvalidArgumentException(sprintf('"%s::getOperators()" must return an array with operators, got "%s".', get_class($extension), is_object($operators) ? get_class($operators) : gettype($operators).(is_resource($operators) ? '' : '#'.$operators))); - } - - if (2 !== count($operators)) { - throw new InvalidArgumentException(sprintf('"%s::getOperators()" must return an array of 2 elements, got %d.', get_class($extension), count($operators))); - } - - $this->unaryOperators = array_merge($this->unaryOperators, $operators[0]); - $this->binaryOperators = array_merge($this->binaryOperators, $operators[1]); - } - } - - /** - * @deprecated since 1.22 (to be removed in 2.0) - */ - protected function writeCacheFile($file, $content) - { - $this->cache->write($file, $content); - } - - private function updateOptionsHash() - { - $hashParts = array_merge( - array_keys($this->extensions), - array( - (int) function_exists('twig_template_get_attributes'), - PHP_MAJOR_VERSION, - PHP_MINOR_VERSION, - self::VERSION, - (int) $this->debug, - $this->baseTemplateClass, - (int) $this->strictVariables, - ) - ); - $this->optionsHash = implode(':', $hashParts); } } - -class_alias('Twig_Environment', 'Twig\Environment', false); diff --git a/vendor/twig/twig/lib/Twig/Error.php b/vendor/twig/twig/lib/Twig/Error.php index 787e0d0955658aee0581acbf1eb1120b0b7c56de..887490ce69d3c00ed093cd6860d12714c29465d2 100644 --- a/vendor/twig/twig/lib/Twig/Error.php +++ b/vendor/twig/twig/lib/Twig/Error.php @@ -1,363 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +use Twig\Error\Error; -/** - * Twig base exception. - * - * This exception class and its children must only be used when - * an error occurs during the loading of a template, when a syntax error - * is detected in a template, or when rendering a template. Other - * errors must use regular PHP exception classes (like when the template - * cache directory is not writable for instance). - * - * To help debugging template issues, this class tracks the original template - * name and line where the error occurred. - * - * Whenever possible, you must set these information (original template name - * and line number) yourself by passing them to the constructor. If some or all - * these information are not available from where you throw the exception, then - * this class will guess them automatically (when the line number is set to -1 - * and/or the name is set to null). As this is a costly operation, this - * can be disabled by passing false for both the name and the line number - * when creating a new instance of this class. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class Twig_Error extends Exception -{ - protected $lineno; - // to be renamed to name in 2.0 - protected $filename; - protected $rawMessage; - protected $previous; +class_exists('Twig\Error\Error'); - private $sourcePath; - private $sourceCode; - - /** - * Constructor. - * - * Set both the line number and the name to false to - * disable automatic guessing of the original template name - * and line number. - * - * Set the line number to -1 to enable its automatic guessing. - * Set the name to null to enable its automatic guessing. - * - * By default, automatic guessing is enabled. - * - * @param string $message The error message - * @param int $lineno The template line where the error occurred - * @param Twig_Source|string|null $source The source context where the error occurred - * @param Exception $previous The previous exception - */ - public function __construct($message, $lineno = -1, $source = null, Exception $previous = null) - { - if (null === $source) { - $name = null; - } elseif (!$source instanceof Twig_Source) { - // for compat with the Twig C ext., passing the template name as string is accepted - $name = $source; - } else { - $name = $source->getName(); - $this->sourceCode = $source->getCode(); - $this->sourcePath = $source->getPath(); - } - if (PHP_VERSION_ID < 50300) { - $this->previous = $previous; - parent::__construct(''); - } else { - parent::__construct('', 0, $previous); - } - - $this->lineno = $lineno; - $this->filename = $name; - - if (-1 === $lineno || null === $name || null === $this->sourcePath) { - $this->guessTemplateInfo(); - } - - $this->rawMessage = $message; - - $this->updateRepr(); - } - - /** - * Gets the raw message. - * - * @return string The raw message - */ - public function getRawMessage() - { - return $this->rawMessage; - } - - /** - * Gets the logical name where the error occurred. - * - * @return string The name - * - * @deprecated since 1.27 (to be removed in 2.0). Use getSourceContext() instead. - */ - public function getTemplateFile() - { - @trigger_error(sprintf('The "%s" method is deprecated since version 1.27 and will be removed in 2.0. Use getSourceContext() instead.', __METHOD__), E_USER_DEPRECATED); - - return $this->filename; - } - - /** - * Sets the logical name where the error occurred. - * - * @param string $name The name - * - * @deprecated since 1.27 (to be removed in 2.0). Use setSourceContext() instead. - */ - public function setTemplateFile($name) - { - @trigger_error(sprintf('The "%s" method is deprecated since version 1.27 and will be removed in 2.0. Use setSourceContext() instead.', __METHOD__), E_USER_DEPRECATED); - - $this->filename = $name; - - $this->updateRepr(); - } - - /** - * Gets the logical name where the error occurred. - * - * @return string The name - * - * @deprecated since 1.29 (to be removed in 2.0). Use getSourceContext() instead. - */ - public function getTemplateName() - { - @trigger_error(sprintf('The "%s" method is deprecated since version 1.29 and will be removed in 2.0. Use getSourceContext() instead.', __METHOD__), E_USER_DEPRECATED); - - return $this->filename; - } - - /** - * Sets the logical name where the error occurred. - * - * @param string $name The name - * - * @deprecated since 1.29 (to be removed in 2.0). Use setSourceContext() instead. - */ - public function setTemplateName($name) - { - @trigger_error(sprintf('The "%s" method is deprecated since version 1.29 and will be removed in 2.0. Use setSourceContext() instead.', __METHOD__), E_USER_DEPRECATED); - - $this->filename = $name; - $this->sourceCode = $this->sourcePath = null; - - $this->updateRepr(); - } - - /** - * Gets the template line where the error occurred. - * - * @return int The template line - */ - public function getTemplateLine() - { - return $this->lineno; - } - - /** - * Sets the template line where the error occurred. - * - * @param int $lineno The template line - */ - public function setTemplateLine($lineno) - { - $this->lineno = $lineno; - - $this->updateRepr(); - } - - /** - * Gets the source context of the Twig template where the error occurred. - * - * @return Twig_Source|null - */ - public function getSourceContext() - { - return $this->filename ? new Twig_Source($this->sourceCode, $this->filename, $this->sourcePath) : null; - } - - /** - * Sets the source context of the Twig template where the error occurred. - */ - public function setSourceContext(Twig_Source $source = null) - { - if (null === $source) { - $this->sourceCode = $this->filename = $this->sourcePath = null; - } else { - $this->sourceCode = $source->getCode(); - $this->filename = $source->getName(); - $this->sourcePath = $source->getPath(); - } - - $this->updateRepr(); - } - - public function guess() - { - $this->guessTemplateInfo(); - $this->updateRepr(); - } - - /** - * For PHP < 5.3.0, provides access to the getPrevious() method. - * - * @param string $method The method name - * @param array $arguments The parameters to be passed to the method - * - * @return Exception The previous exception or null - * - * @throws BadMethodCallException - */ - public function __call($method, $arguments) - { - if ('getprevious' == strtolower($method)) { - return $this->previous; - } - - throw new BadMethodCallException(sprintf('Method "Twig_Error::%s()" does not exist.', $method)); - } - - public function appendMessage($rawMessage) - { - $this->rawMessage .= $rawMessage; - $this->updateRepr(); - } - - /** - * @internal - */ - protected function updateRepr() - { - $this->message = $this->rawMessage; - - if ($this->sourcePath && $this->lineno > 0) { - $this->file = $this->sourcePath; - $this->line = $this->lineno; - - return; - } - - $dot = false; - if ('.' === substr($this->message, -1)) { - $this->message = substr($this->message, 0, -1); - $dot = true; - } - - $questionMark = false; - if ('?' === substr($this->message, -1)) { - $this->message = substr($this->message, 0, -1); - $questionMark = true; - } - - if ($this->filename) { - if (is_string($this->filename) || (is_object($this->filename) && method_exists($this->filename, '__toString'))) { - $name = sprintf('"%s"', $this->filename); - } else { - $name = json_encode($this->filename); - } - $this->message .= sprintf(' in %s', $name); - } - - if ($this->lineno && $this->lineno >= 0) { - $this->message .= sprintf(' at line %d', $this->lineno); - } - - if ($dot) { - $this->message .= '.'; - } - - if ($questionMark) { - $this->message .= '?'; - } - } - - /** - * @internal - */ - protected function guessTemplateInfo() +if (\false) { + class Twig_Error extends Error { - $template = null; - $templateClass = null; - - if (PHP_VERSION_ID >= 50306) { - $backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS | DEBUG_BACKTRACE_PROVIDE_OBJECT); - } else { - $backtrace = debug_backtrace(); - } - - foreach ($backtrace as $trace) { - if (isset($trace['object']) && $trace['object'] instanceof Twig_Template && 'Twig_Template' !== get_class($trace['object'])) { - $currentClass = get_class($trace['object']); - $isEmbedContainer = 0 === strpos($templateClass, $currentClass); - if (null === $this->filename || ($this->filename == $trace['object']->getTemplateName() && !$isEmbedContainer)) { - $template = $trace['object']; - $templateClass = get_class($trace['object']); - } - } - } - - // update template name - if (null !== $template && null === $this->filename) { - $this->filename = $template->getTemplateName(); - } - - // update template path if any - if (null !== $template && null === $this->sourcePath) { - $src = $template->getSourceContext(); - $this->sourceCode = $src->getCode(); - $this->sourcePath = $src->getPath(); - } - - if (null === $template || $this->lineno > -1) { - return; - } - - $r = new ReflectionObject($template); - $file = $r->getFileName(); - - $exceptions = array($e = $this); - while (($e instanceof self || method_exists($e, 'getPrevious')) && $e = $e->getPrevious()) { - $exceptions[] = $e; - } - - while ($e = array_pop($exceptions)) { - $traces = $e->getTrace(); - array_unshift($traces, array('file' => $e->getFile(), 'line' => $e->getLine())); - - while ($trace = array_shift($traces)) { - if (!isset($trace['file']) || !isset($trace['line']) || $file != $trace['file']) { - continue; - } - - foreach ($template->getDebugInfo() as $codeLine => $templateLine) { - if ($codeLine <= $trace['line']) { - // update template line - $this->lineno = $templateLine; - - return; - } - } - } - } } } - -class_alias('Twig_Error', 'Twig\Error\Error', false); -class_exists('Twig_Source'); diff --git a/vendor/twig/twig/lib/Twig/Error/Loader.php b/vendor/twig/twig/lib/Twig/Error/Loader.php index df566dd78be2c389d65417a32c77d9eb47480da5..8caca6fd110dcb8eda3042cf9c663fe680402597 100644 --- a/vendor/twig/twig/lib/Twig/Error/Loader.php +++ b/vendor/twig/twig/lib/Twig/Error/Loader.php @@ -1,40 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +use Twig\Error\LoaderError; -/** - * Exception thrown when an error occurs during template loading. - * - * Automatic template information guessing is always turned off as - * if a template cannot be loaded, there is nothing to guess. - * However, when a template is loaded from another one, then, we need - * to find the current context and this is automatically done by - * Twig_Template::displayWithErrorHandling(). - * - * This strategy makes Twig_Environment::resolveTemplate() much faster. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class Twig_Error_Loader extends Twig_Error -{ - public function __construct($message, $lineno = -1, $source = null, Exception $previous = null) +class_exists('Twig\Error\LoaderError'); + +if (\false) { + class Twig_Error_Loader extends LoaderError { - if (PHP_VERSION_ID < 50300) { - $this->previous = $previous; - Exception::__construct(''); - } else { - Exception::__construct('', 0, $previous); - } - $this->appendMessage($message); - $this->setTemplateLine(false); } } - -class_alias('Twig_Error_Loader', 'Twig\Error\LoaderError', false); diff --git a/vendor/twig/twig/lib/Twig/Error/Runtime.php b/vendor/twig/twig/lib/Twig/Error/Runtime.php index 3b24ad3a4c6a3018702090032b573d3e79f84847..d45133b897ea15d36bb5ec92666fc990ffcb1773 100644 --- a/vendor/twig/twig/lib/Twig/Error/Runtime.php +++ b/vendor/twig/twig/lib/Twig/Error/Runtime.php @@ -1,22 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * (c) Armin Ronacher - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +use Twig\Error\RuntimeError; -/** - * Exception thrown when an error occurs at runtime. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class Twig_Error_Runtime extends Twig_Error -{ -} +class_exists('Twig\Error\RuntimeError'); -class_alias('Twig_Error_Runtime', 'Twig\Error\RuntimeError', false); +if (\false) { + class Twig_Error_Runtime extends RuntimeError + { + } +} diff --git a/vendor/twig/twig/lib/Twig/Error/Syntax.php b/vendor/twig/twig/lib/Twig/Error/Syntax.php index 9d09f2179301af2b048a0fdb79730e69bf12b0cb..f5920c6237d3e097258d5660f44c2125767c913d 100644 --- a/vendor/twig/twig/lib/Twig/Error/Syntax.php +++ b/vendor/twig/twig/lib/Twig/Error/Syntax.php @@ -1,55 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * (c) Armin Ronacher - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +use Twig\Error\SyntaxError; -/** - * Exception thrown when a syntax error occurs during lexing or parsing of a template. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class Twig_Error_Syntax extends Twig_Error -{ - /** - * Tweaks the error message to include suggestions. - * - * @param string $name The original name of the item that does not exist - * @param array $items An array of possible items - */ - public function addSuggestions($name, array $items) - { - if (!$alternatives = self::computeAlternatives($name, $items)) { - return; - } - - $this->appendMessage(sprintf(' Did you mean "%s"?', implode('", "', $alternatives))); - } +class_exists('Twig\Error\SyntaxError'); - /** - * @internal - * - * To be merged with the addSuggestions() method in 2.0. - */ - public static function computeAlternatives($name, $items) +if (\false) { + class Twig_Error_Syntax extends SyntaxError { - $alternatives = array(); - foreach ($items as $item) { - $lev = levenshtein($name, $item); - if ($lev <= strlen($name) / 3 || false !== strpos($item, $name)) { - $alternatives[$item] = $lev; - } - } - asort($alternatives); - - return array_keys($alternatives); } } - -class_alias('Twig_Error_Syntax', 'Twig\Error\SyntaxError', false); diff --git a/vendor/twig/twig/lib/Twig/ExistsLoaderInterface.php b/vendor/twig/twig/lib/Twig/ExistsLoaderInterface.php index 968cb21a4cd8fc2cf44d23c0f8a858e383bd231c..3acbf65baa55557242137a2b24707c6531b03a75 100644 --- a/vendor/twig/twig/lib/Twig/ExistsLoaderInterface.php +++ b/vendor/twig/twig/lib/Twig/ExistsLoaderInterface.php @@ -1,31 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +use Twig\Loader\ExistsLoaderInterface; -/** - * Adds an exists() method for loaders. - * - * @author Florin Patan <florinpatan@gmail.com> - * - * @deprecated since 1.12 (to be removed in 3.0) - */ -interface Twig_ExistsLoaderInterface -{ - /** - * Check if we have the source code of a template, given its name. - * - * @param string $name The name of the template to check if we can load - * - * @return bool If the template source code is handled by this loader or not - */ - public function exists($name); -} +class_exists('Twig\Loader\ExistsLoaderInterface'); -class_alias('Twig_ExistsLoaderInterface', 'Twig\Loader\ExistsLoaderInterface', false); +if (\false) { + class Twig_ExistsLoaderInterface extends ExistsLoaderInterface + { + } +} diff --git a/vendor/twig/twig/lib/Twig/ExpressionParser.php b/vendor/twig/twig/lib/Twig/ExpressionParser.php index 4906f903e9eb0c913b652f4c975666d30137bbe7..687404d6c841e205dd6193d5e424f2a4910398f9 100644 --- a/vendor/twig/twig/lib/Twig/ExpressionParser.php +++ b/vendor/twig/twig/lib/Twig/ExpressionParser.php @@ -1,741 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * (c) Armin Ronacher - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +use Twig\ExpressionParser; -/** - * Parses expressions. - * - * This parser implements a "Precedence climbing" algorithm. - * - * @see http://www.engr.mun.ca/~theo/Misc/exp_parsing.htm - * @see http://en.wikipedia.org/wiki/Operator-precedence_parser - * - * @author Fabien Potencier <fabien@symfony.com> - * - * @internal - */ -class Twig_ExpressionParser -{ - const OPERATOR_LEFT = 1; - const OPERATOR_RIGHT = 2; +class_exists('Twig\ExpressionParser'); - protected $parser; - protected $unaryOperators; - protected $binaryOperators; - - private $env; - - public function __construct(Twig_Parser $parser, $env = null) - { - $this->parser = $parser; - - if ($env instanceof Twig_Environment) { - $this->env = $env; - $this->unaryOperators = $env->getUnaryOperators(); - $this->binaryOperators = $env->getBinaryOperators(); - } else { - @trigger_error('Passing the operators as constructor arguments to '.__METHOD__.' is deprecated since version 1.27. Pass the environment instead.', E_USER_DEPRECATED); - - $this->env = $parser->getEnvironment(); - $this->unaryOperators = func_get_arg(1); - $this->binaryOperators = func_get_arg(2); - } - } - - public function parseExpression($precedence = 0) - { - $expr = $this->getPrimary(); - $token = $this->parser->getCurrentToken(); - while ($this->isBinary($token) && $this->binaryOperators[$token->getValue()]['precedence'] >= $precedence) { - $op = $this->binaryOperators[$token->getValue()]; - $this->parser->getStream()->next(); - - if ('is not' === $token->getValue()) { - $expr = $this->parseNotTestExpression($expr); - } elseif ('is' === $token->getValue()) { - $expr = $this->parseTestExpression($expr); - } elseif (isset($op['callable'])) { - $expr = call_user_func($op['callable'], $this->parser, $expr); - } else { - $expr1 = $this->parseExpression(self::OPERATOR_LEFT === $op['associativity'] ? $op['precedence'] + 1 : $op['precedence']); - $class = $op['class']; - $expr = new $class($expr, $expr1, $token->getLine()); - } - - $token = $this->parser->getCurrentToken(); - } - - if (0 === $precedence) { - return $this->parseConditionalExpression($expr); - } - - return $expr; - } - - protected function getPrimary() - { - $token = $this->parser->getCurrentToken(); - - if ($this->isUnary($token)) { - $operator = $this->unaryOperators[$token->getValue()]; - $this->parser->getStream()->next(); - $expr = $this->parseExpression($operator['precedence']); - $class = $operator['class']; - - return $this->parsePostfixExpression(new $class($expr, $token->getLine())); - } elseif ($token->test(Twig_Token::PUNCTUATION_TYPE, '(')) { - $this->parser->getStream()->next(); - $expr = $this->parseExpression(); - $this->parser->getStream()->expect(Twig_Token::PUNCTUATION_TYPE, ')', 'An opened parenthesis is not properly closed'); - - return $this->parsePostfixExpression($expr); - } - - return $this->parsePrimaryExpression(); - } - - protected function parseConditionalExpression($expr) - { - while ($this->parser->getStream()->nextIf(Twig_Token::PUNCTUATION_TYPE, '?')) { - if (!$this->parser->getStream()->nextIf(Twig_Token::PUNCTUATION_TYPE, ':')) { - $expr2 = $this->parseExpression(); - if ($this->parser->getStream()->nextIf(Twig_Token::PUNCTUATION_TYPE, ':')) { - $expr3 = $this->parseExpression(); - } else { - $expr3 = new Twig_Node_Expression_Constant('', $this->parser->getCurrentToken()->getLine()); - } - } else { - $expr2 = $expr; - $expr3 = $this->parseExpression(); - } - - $expr = new Twig_Node_Expression_Conditional($expr, $expr2, $expr3, $this->parser->getCurrentToken()->getLine()); - } - - return $expr; - } - - protected function isUnary(Twig_Token $token) - { - return $token->test(Twig_Token::OPERATOR_TYPE) && isset($this->unaryOperators[$token->getValue()]); - } - - protected function isBinary(Twig_Token $token) - { - return $token->test(Twig_Token::OPERATOR_TYPE) && isset($this->binaryOperators[$token->getValue()]); - } - - public function parsePrimaryExpression() - { - $token = $this->parser->getCurrentToken(); - switch ($token->getType()) { - case Twig_Token::NAME_TYPE: - $this->parser->getStream()->next(); - switch ($token->getValue()) { - case 'true': - case 'TRUE': - $node = new Twig_Node_Expression_Constant(true, $token->getLine()); - break; - - case 'false': - case 'FALSE': - $node = new Twig_Node_Expression_Constant(false, $token->getLine()); - break; - - case 'none': - case 'NONE': - case 'null': - case 'NULL': - $node = new Twig_Node_Expression_Constant(null, $token->getLine()); - break; - - default: - if ('(' === $this->parser->getCurrentToken()->getValue()) { - $node = $this->getFunctionNode($token->getValue(), $token->getLine()); - } else { - $node = new Twig_Node_Expression_Name($token->getValue(), $token->getLine()); - } - } - break; - - case Twig_Token::NUMBER_TYPE: - $this->parser->getStream()->next(); - $node = new Twig_Node_Expression_Constant($token->getValue(), $token->getLine()); - break; - - case Twig_Token::STRING_TYPE: - case Twig_Token::INTERPOLATION_START_TYPE: - $node = $this->parseStringExpression(); - break; - - case Twig_Token::OPERATOR_TYPE: - if (preg_match(Twig_Lexer::REGEX_NAME, $token->getValue(), $matches) && $matches[0] == $token->getValue()) { - // in this context, string operators are variable names - $this->parser->getStream()->next(); - $node = new Twig_Node_Expression_Name($token->getValue(), $token->getLine()); - break; - } elseif (isset($this->unaryOperators[$token->getValue()])) { - $class = $this->unaryOperators[$token->getValue()]['class']; - - $ref = new ReflectionClass($class); - $negClass = 'Twig_Node_Expression_Unary_Neg'; - $posClass = 'Twig_Node_Expression_Unary_Pos'; - if (!(in_array($ref->getName(), array($negClass, $posClass)) || $ref->isSubclassOf($negClass) || $ref->isSubclassOf($posClass))) { - throw new Twig_Error_Syntax(sprintf('Unexpected unary operator "%s".', $token->getValue()), $token->getLine(), $this->parser->getStream()->getSourceContext()); - } - - $this->parser->getStream()->next(); - $expr = $this->parsePrimaryExpression(); - - $node = new $class($expr, $token->getLine()); - break; - } - - default: - if ($token->test(Twig_Token::PUNCTUATION_TYPE, '[')) { - $node = $this->parseArrayExpression(); - } elseif ($token->test(Twig_Token::PUNCTUATION_TYPE, '{')) { - $node = $this->parseHashExpression(); - } else { - throw new Twig_Error_Syntax(sprintf('Unexpected token "%s" of value "%s".', Twig_Token::typeToEnglish($token->getType()), $token->getValue()), $token->getLine(), $this->parser->getStream()->getSourceContext()); - } - } - - return $this->parsePostfixExpression($node); - } - - public function parseStringExpression() - { - $stream = $this->parser->getStream(); - - $nodes = array(); - // a string cannot be followed by another string in a single expression - $nextCanBeString = true; - while (true) { - if ($nextCanBeString && $token = $stream->nextIf(Twig_Token::STRING_TYPE)) { - $nodes[] = new Twig_Node_Expression_Constant($token->getValue(), $token->getLine()); - $nextCanBeString = false; - } elseif ($stream->nextIf(Twig_Token::INTERPOLATION_START_TYPE)) { - $nodes[] = $this->parseExpression(); - $stream->expect(Twig_Token::INTERPOLATION_END_TYPE); - $nextCanBeString = true; - } else { - break; - } - } - - $expr = array_shift($nodes); - foreach ($nodes as $node) { - $expr = new Twig_Node_Expression_Binary_Concat($expr, $node, $node->getTemplateLine()); - } - - return $expr; - } - - public function parseArrayExpression() - { - $stream = $this->parser->getStream(); - $stream->expect(Twig_Token::PUNCTUATION_TYPE, '[', 'An array element was expected'); - - $node = new Twig_Node_Expression_Array(array(), $stream->getCurrent()->getLine()); - $first = true; - while (!$stream->test(Twig_Token::PUNCTUATION_TYPE, ']')) { - if (!$first) { - $stream->expect(Twig_Token::PUNCTUATION_TYPE, ',', 'An array element must be followed by a comma'); - - // trailing ,? - if ($stream->test(Twig_Token::PUNCTUATION_TYPE, ']')) { - break; - } - } - $first = false; - - $node->addElement($this->parseExpression()); - } - $stream->expect(Twig_Token::PUNCTUATION_TYPE, ']', 'An opened array is not properly closed'); - - return $node; - } - - public function parseHashExpression() - { - $stream = $this->parser->getStream(); - $stream->expect(Twig_Token::PUNCTUATION_TYPE, '{', 'A hash element was expected'); - - $node = new Twig_Node_Expression_Array(array(), $stream->getCurrent()->getLine()); - $first = true; - while (!$stream->test(Twig_Token::PUNCTUATION_TYPE, '}')) { - if (!$first) { - $stream->expect(Twig_Token::PUNCTUATION_TYPE, ',', 'A hash value must be followed by a comma'); - - // trailing ,? - if ($stream->test(Twig_Token::PUNCTUATION_TYPE, '}')) { - break; - } - } - $first = false; - - // a hash key can be: - // - // * a number -- 12 - // * a string -- 'a' - // * a name, which is equivalent to a string -- a - // * an expression, which must be enclosed in parentheses -- (1 + 2) - if (($token = $stream->nextIf(Twig_Token::STRING_TYPE)) || ($token = $stream->nextIf(Twig_Token::NAME_TYPE)) || $token = $stream->nextIf(Twig_Token::NUMBER_TYPE)) { - $key = new Twig_Node_Expression_Constant($token->getValue(), $token->getLine()); - } elseif ($stream->test(Twig_Token::PUNCTUATION_TYPE, '(')) { - $key = $this->parseExpression(); - } else { - $current = $stream->getCurrent(); - - throw new Twig_Error_Syntax(sprintf('A hash key must be a quoted string, a number, a name, or an expression enclosed in parentheses (unexpected token "%s" of value "%s".', Twig_Token::typeToEnglish($current->getType()), $current->getValue()), $current->getLine(), $stream->getSourceContext()); - } - - $stream->expect(Twig_Token::PUNCTUATION_TYPE, ':', 'A hash key must be followed by a colon (:)'); - $value = $this->parseExpression(); - - $node->addElement($value, $key); - } - $stream->expect(Twig_Token::PUNCTUATION_TYPE, '}', 'An opened hash is not properly closed'); - - return $node; - } - - public function parsePostfixExpression($node) +if (\false) { + class Twig_ExpressionParser extends ExpressionParser { - while (true) { - $token = $this->parser->getCurrentToken(); - if ($token->getType() == Twig_Token::PUNCTUATION_TYPE) { - if ('.' == $token->getValue() || '[' == $token->getValue()) { - $node = $this->parseSubscriptExpression($node); - } elseif ('|' == $token->getValue()) { - $node = $this->parseFilterExpression($node); - } else { - break; - } - } else { - break; - } - } - - return $node; - } - - public function getFunctionNode($name, $line) - { - switch ($name) { - case 'parent': - $this->parseArguments(); - if (!count($this->parser->getBlockStack())) { - throw new Twig_Error_Syntax('Calling "parent" outside a block is forbidden.', $line, $this->parser->getStream()->getSourceContext()); - } - - if (!$this->parser->getParent() && !$this->parser->hasTraits()) { - throw new Twig_Error_Syntax('Calling "parent" on a template that does not extend nor "use" another template is forbidden.', $line, $this->parser->getStream()->getSourceContext()); - } - - return new Twig_Node_Expression_Parent($this->parser->peekBlockStack(), $line); - case 'block': - $args = $this->parseArguments(); - if (count($args) < 1) { - throw new Twig_Error_Syntax('The "block" function takes one argument (the block name).', $line, $this->parser->getStream()->getSourceContext()); - } - - return new Twig_Node_Expression_BlockReference($args->getNode(0), count($args) > 1 ? $args->getNode(1) : null, $line); - case 'attribute': - $args = $this->parseArguments(); - if (count($args) < 2) { - throw new Twig_Error_Syntax('The "attribute" function takes at least two arguments (the variable and the attributes).', $line, $this->parser->getStream()->getSourceContext()); - } - - return new Twig_Node_Expression_GetAttr($args->getNode(0), $args->getNode(1), count($args) > 2 ? $args->getNode(2) : null, Twig_Template::ANY_CALL, $line); - default: - if (null !== $alias = $this->parser->getImportedSymbol('function', $name)) { - $arguments = new Twig_Node_Expression_Array(array(), $line); - foreach ($this->parseArguments() as $n) { - $arguments->addElement($n); - } - - $node = new Twig_Node_Expression_MethodCall($alias['node'], $alias['name'], $arguments, $line); - $node->setAttribute('safe', true); - - return $node; - } - - $args = $this->parseArguments(true); - $class = $this->getFunctionNodeClass($name, $line); - - return new $class($name, $args, $line); - } - } - - public function parseSubscriptExpression($node) - { - $stream = $this->parser->getStream(); - $token = $stream->next(); - $lineno = $token->getLine(); - $arguments = new Twig_Node_Expression_Array(array(), $lineno); - $type = Twig_Template::ANY_CALL; - if ($token->getValue() == '.') { - $token = $stream->next(); - if ( - $token->getType() == Twig_Token::NAME_TYPE - || - $token->getType() == Twig_Token::NUMBER_TYPE - || - ($token->getType() == Twig_Token::OPERATOR_TYPE && preg_match(Twig_Lexer::REGEX_NAME, $token->getValue())) - ) { - $arg = new Twig_Node_Expression_Constant($token->getValue(), $lineno); - - if ($stream->test(Twig_Token::PUNCTUATION_TYPE, '(')) { - $type = Twig_Template::METHOD_CALL; - foreach ($this->parseArguments() as $n) { - $arguments->addElement($n); - } - } - } else { - throw new Twig_Error_Syntax('Expected name or number.', $lineno, $stream->getSourceContext()); - } - - if ($node instanceof Twig_Node_Expression_Name && null !== $this->parser->getImportedSymbol('template', $node->getAttribute('name'))) { - if (!$arg instanceof Twig_Node_Expression_Constant) { - throw new Twig_Error_Syntax(sprintf('Dynamic macro names are not supported (called on "%s").', $node->getAttribute('name')), $token->getLine(), $stream->getSourceContext()); - } - - $name = $arg->getAttribute('value'); - - if ($this->parser->isReservedMacroName($name)) { - throw new Twig_Error_Syntax(sprintf('"%s" cannot be called as macro as it is a reserved keyword.', $name), $token->getLine(), $stream->getSourceContext()); - } - - $node = new Twig_Node_Expression_MethodCall($node, 'get'.$name, $arguments, $lineno); - $node->setAttribute('safe', true); - - return $node; - } - } else { - $type = Twig_Template::ARRAY_CALL; - - // slice? - $slice = false; - if ($stream->test(Twig_Token::PUNCTUATION_TYPE, ':')) { - $slice = true; - $arg = new Twig_Node_Expression_Constant(0, $token->getLine()); - } else { - $arg = $this->parseExpression(); - } - - if ($stream->nextIf(Twig_Token::PUNCTUATION_TYPE, ':')) { - $slice = true; - } - - if ($slice) { - if ($stream->test(Twig_Token::PUNCTUATION_TYPE, ']')) { - $length = new Twig_Node_Expression_Constant(null, $token->getLine()); - } else { - $length = $this->parseExpression(); - } - - $class = $this->getFilterNodeClass('slice', $token->getLine()); - $arguments = new Twig_Node(array($arg, $length)); - $filter = new $class($node, new Twig_Node_Expression_Constant('slice', $token->getLine()), $arguments, $token->getLine()); - - $stream->expect(Twig_Token::PUNCTUATION_TYPE, ']'); - - return $filter; - } - - $stream->expect(Twig_Token::PUNCTUATION_TYPE, ']'); - } - - return new Twig_Node_Expression_GetAttr($node, $arg, $arguments, $type, $lineno); - } - - public function parseFilterExpression($node) - { - $this->parser->getStream()->next(); - - return $this->parseFilterExpressionRaw($node); - } - - public function parseFilterExpressionRaw($node, $tag = null) - { - while (true) { - $token = $this->parser->getStream()->expect(Twig_Token::NAME_TYPE); - - $name = new Twig_Node_Expression_Constant($token->getValue(), $token->getLine()); - if (!$this->parser->getStream()->test(Twig_Token::PUNCTUATION_TYPE, '(')) { - $arguments = new Twig_Node(); - } else { - $arguments = $this->parseArguments(true); - } - - $class = $this->getFilterNodeClass($name->getAttribute('value'), $token->getLine()); - - $node = new $class($node, $name, $arguments, $token->getLine(), $tag); - - if (!$this->parser->getStream()->test(Twig_Token::PUNCTUATION_TYPE, '|')) { - break; - } - - $this->parser->getStream()->next(); - } - - return $node; - } - - /** - * Parses arguments. - * - * @param bool $namedArguments Whether to allow named arguments or not - * @param bool $definition Whether we are parsing arguments for a function definition - * - * @return Twig_Node - * - * @throws Twig_Error_Syntax - */ - public function parseArguments($namedArguments = false, $definition = false) - { - $args = array(); - $stream = $this->parser->getStream(); - - $stream->expect(Twig_Token::PUNCTUATION_TYPE, '(', 'A list of arguments must begin with an opening parenthesis'); - while (!$stream->test(Twig_Token::PUNCTUATION_TYPE, ')')) { - if (!empty($args)) { - $stream->expect(Twig_Token::PUNCTUATION_TYPE, ',', 'Arguments must be separated by a comma'); - } - - if ($definition) { - $token = $stream->expect(Twig_Token::NAME_TYPE, null, 'An argument must be a name'); - $value = new Twig_Node_Expression_Name($token->getValue(), $this->parser->getCurrentToken()->getLine()); - } else { - $value = $this->parseExpression(); - } - - $name = null; - if ($namedArguments && $token = $stream->nextIf(Twig_Token::OPERATOR_TYPE, '=')) { - if (!$value instanceof Twig_Node_Expression_Name) { - throw new Twig_Error_Syntax(sprintf('A parameter name must be a string, "%s" given.', get_class($value)), $token->getLine(), $stream->getSourceContext()); - } - $name = $value->getAttribute('name'); - - if ($definition) { - $value = $this->parsePrimaryExpression(); - - if (!$this->checkConstantExpression($value)) { - throw new Twig_Error_Syntax(sprintf('A default value for an argument must be a constant (a boolean, a string, a number, or an array).'), $token->getLine(), $stream->getSourceContext()); - } - } else { - $value = $this->parseExpression(); - } - } - - if ($definition) { - if (null === $name) { - $name = $value->getAttribute('name'); - $value = new Twig_Node_Expression_Constant(null, $this->parser->getCurrentToken()->getLine()); - } - $args[$name] = $value; - } else { - if (null === $name) { - $args[] = $value; - } else { - $args[$name] = $value; - } - } - } - $stream->expect(Twig_Token::PUNCTUATION_TYPE, ')', 'A list of arguments must be closed by a parenthesis'); - - return new Twig_Node($args); - } - - public function parseAssignmentExpression() - { - $stream = $this->parser->getStream(); - $targets = array(); - while (true) { - $token = $stream->expect(Twig_Token::NAME_TYPE, null, 'Only variables can be assigned to'); - $value = $token->getValue(); - if (in_array(strtolower($value), array('true', 'false', 'none', 'null'))) { - throw new Twig_Error_Syntax(sprintf('You cannot assign a value to "%s".', $value), $token->getLine(), $stream->getSourceContext()); - } - $targets[] = new Twig_Node_Expression_AssignName($value, $token->getLine()); - - if (!$stream->nextIf(Twig_Token::PUNCTUATION_TYPE, ',')) { - break; - } - } - - return new Twig_Node($targets); - } - - public function parseMultitargetExpression() - { - $targets = array(); - while (true) { - $targets[] = $this->parseExpression(); - if (!$this->parser->getStream()->nextIf(Twig_Token::PUNCTUATION_TYPE, ',')) { - break; - } - } - - return new Twig_Node($targets); - } - - private function parseNotTestExpression(Twig_NodeInterface $node) - { - return new Twig_Node_Expression_Unary_Not($this->parseTestExpression($node), $this->parser->getCurrentToken()->getLine()); - } - - private function parseTestExpression(Twig_NodeInterface $node) - { - $stream = $this->parser->getStream(); - list($name, $test) = $this->getTest($node->getTemplateLine()); - - $class = $this->getTestNodeClass($test); - $arguments = null; - if ($stream->test(Twig_Token::PUNCTUATION_TYPE, '(')) { - $arguments = $this->parser->getExpressionParser()->parseArguments(true); - } - - return new $class($node, $name, $arguments, $this->parser->getCurrentToken()->getLine()); - } - - private function getTest($line) - { - $stream = $this->parser->getStream(); - $name = $stream->expect(Twig_Token::NAME_TYPE)->getValue(); - - if ($test = $this->env->getTest($name)) { - return array($name, $test); - } - - if ($stream->test(Twig_Token::NAME_TYPE)) { - // try 2-words tests - $name = $name.' '.$this->parser->getCurrentToken()->getValue(); - - if ($test = $this->env->getTest($name)) { - $stream->next(); - - return array($name, $test); - } - } - - $e = new Twig_Error_Syntax(sprintf('Unknown "%s" test.', $name), $line, $stream->getSourceContext()); - $e->addSuggestions($name, array_keys($this->env->getTests())); - - throw $e; - } - - private function getTestNodeClass($test) - { - if ($test instanceof Twig_SimpleTest && $test->isDeprecated()) { - $stream = $this->parser->getStream(); - $message = sprintf('Twig Test "%s" is deprecated', $test->getName()); - if (!is_bool($test->getDeprecatedVersion())) { - $message .= sprintf(' since version %s', $test->getDeprecatedVersion()); - } - if ($test->getAlternative()) { - $message .= sprintf('. Use "%s" instead', $test->getAlternative()); - } - $src = $stream->getSourceContext(); - $message .= sprintf(' in %s at line %d.', $src->getPath() ? $src->getPath() : $src->getName(), $stream->getCurrent()->getLine()); - - @trigger_error($message, E_USER_DEPRECATED); - } - - if ($test instanceof Twig_SimpleTest) { - return $test->getNodeClass(); - } - - return $test instanceof Twig_Test_Node ? $test->getClass() : 'Twig_Node_Expression_Test'; - } - - protected function getFunctionNodeClass($name, $line) - { - if (false === $function = $this->env->getFunction($name)) { - $e = new Twig_Error_Syntax(sprintf('Unknown "%s" function.', $name), $line, $this->parser->getStream()->getSourceContext()); - $e->addSuggestions($name, array_keys($this->env->getFunctions())); - - throw $e; - } - - if ($function instanceof Twig_SimpleFunction && $function->isDeprecated()) { - $message = sprintf('Twig Function "%s" is deprecated', $function->getName()); - if (!is_bool($function->getDeprecatedVersion())) { - $message .= sprintf(' since version %s', $function->getDeprecatedVersion()); - } - if ($function->getAlternative()) { - $message .= sprintf('. Use "%s" instead', $function->getAlternative()); - } - $src = $this->parser->getStream()->getSourceContext(); - $message .= sprintf(' in %s at line %d.', $src->getPath() ? $src->getPath() : $src->getName(), $line); - - @trigger_error($message, E_USER_DEPRECATED); - } - - if ($function instanceof Twig_SimpleFunction) { - return $function->getNodeClass(); - } - - return $function instanceof Twig_Function_Node ? $function->getClass() : 'Twig_Node_Expression_Function'; - } - - protected function getFilterNodeClass($name, $line) - { - if (false === $filter = $this->env->getFilter($name)) { - $e = new Twig_Error_Syntax(sprintf('Unknown "%s" filter.', $name), $line, $this->parser->getStream()->getSourceContext()); - $e->addSuggestions($name, array_keys($this->env->getFilters())); - - throw $e; - } - - if ($filter instanceof Twig_SimpleFilter && $filter->isDeprecated()) { - $message = sprintf('Twig Filter "%s" is deprecated', $filter->getName()); - if (!is_bool($filter->getDeprecatedVersion())) { - $message .= sprintf(' since version %s', $filter->getDeprecatedVersion()); - } - if ($filter->getAlternative()) { - $message .= sprintf('. Use "%s" instead', $filter->getAlternative()); - } - $src = $this->parser->getStream()->getSourceContext(); - $message .= sprintf(' in %s at line %d.', $src->getPath() ? $src->getPath() : $src->getName(), $line); - - @trigger_error($message, E_USER_DEPRECATED); - } - - if ($filter instanceof Twig_SimpleFilter) { - return $filter->getNodeClass(); - } - - return $filter instanceof Twig_Filter_Node ? $filter->getClass() : 'Twig_Node_Expression_Filter'; - } - - // checks that the node only contains "constant" elements - protected function checkConstantExpression(Twig_NodeInterface $node) - { - if (!($node instanceof Twig_Node_Expression_Constant || $node instanceof Twig_Node_Expression_Array - || $node instanceof Twig_Node_Expression_Unary_Neg || $node instanceof Twig_Node_Expression_Unary_Pos - )) { - return false; - } - - foreach ($node as $n) { - if (!$this->checkConstantExpression($n)) { - return false; - } - } - - return true; } } - -class_alias('Twig_ExpressionParser', 'Twig\ExpressionParser', false); diff --git a/vendor/twig/twig/lib/Twig/Extension.php b/vendor/twig/twig/lib/Twig/Extension.php index 38084495fa4f99bb435f42a65c05d6154bea5604..1cc8216a5e783827fd00d91e2be3cf2a4b8da8c8 100644 --- a/vendor/twig/twig/lib/Twig/Extension.php +++ b/vendor/twig/twig/lib/Twig/Extension.php @@ -1,69 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +use Twig\Extension\AbstractExtension; -abstract class Twig_Extension implements Twig_ExtensionInterface -{ - /** - * @deprecated since 1.23 (to be removed in 2.0), implement Twig_Extension_InitRuntimeInterface instead - */ - public function initRuntime(Twig_Environment $environment) - { - } - - public function getTokenParsers() - { - return array(); - } - - public function getNodeVisitors() - { - return array(); - } - - public function getFilters() - { - return array(); - } - - public function getTests() - { - return array(); - } - - public function getFunctions() - { - return array(); - } - - public function getOperators() - { - return array(); - } - - /** - * @deprecated since 1.23 (to be removed in 2.0), implement Twig_Extension_GlobalsInterface instead - */ - public function getGlobals() - { - return array(); - } +class_exists('Twig\Extension\AbstractExtension'); - /** - * @deprecated since 1.26 (to be removed in 2.0), not used anymore internally - */ - public function getName() +if (\false) { + class Twig_Extension extends AbstractExtension { - return get_class($this); } } - -class_alias('Twig_Extension', 'Twig\Extension\AbstractExtension', false); -class_exists('Twig_Environment'); diff --git a/vendor/twig/twig/lib/Twig/Extension/Core.php b/vendor/twig/twig/lib/Twig/Extension/Core.php index 34f9ef7d6eadf8cd45123cb19ca739e21160bb45..fb5a75476745ea0b7fa889d38db2c08504507d65 100644 --- a/vendor/twig/twig/lib/Twig/Extension/Core.php +++ b/vendor/twig/twig/lib/Twig/Extension/Core.php @@ -1,1612 +1,11 @@ <?php -if (!defined('ENT_SUBSTITUTE')) { - define('ENT_SUBSTITUTE', 8); -} - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -/** - * @final - */ -class Twig_Extension_Core extends Twig_Extension -{ - protected $dateFormats = array('F j, Y H:i', '%d days'); - protected $numberFormat = array(0, '.', ','); - protected $timezone = null; - protected $escapers = array(); - - /** - * Defines a new escaper to be used via the escape filter. - * - * @param string $strategy The strategy name that should be used as a strategy in the escape call - * @param callable $callable A valid PHP callable - */ - public function setEscaper($strategy, $callable) - { - $this->escapers[$strategy] = $callable; - } - - /** - * Gets all defined escapers. - * - * @return array An array of escapers - */ - public function getEscapers() - { - return $this->escapers; - } - - /** - * Sets the default format to be used by the date filter. - * - * @param string $format The default date format string - * @param string $dateIntervalFormat The default date interval format string - */ - public function setDateFormat($format = null, $dateIntervalFormat = null) - { - if (null !== $format) { - $this->dateFormats[0] = $format; - } - - if (null !== $dateIntervalFormat) { - $this->dateFormats[1] = $dateIntervalFormat; - } - } - - /** - * Gets the default format to be used by the date filter. - * - * @return array The default date format string and the default date interval format string - */ - public function getDateFormat() - { - return $this->dateFormats; - } - - /** - * Sets the default timezone to be used by the date filter. - * - * @param DateTimeZone|string $timezone The default timezone string or a DateTimeZone object - */ - public function setTimezone($timezone) - { - $this->timezone = $timezone instanceof DateTimeZone ? $timezone : new DateTimeZone($timezone); - } - - /** - * Gets the default timezone to be used by the date filter. - * - * @return DateTimeZone The default timezone currently in use - */ - public function getTimezone() - { - if (null === $this->timezone) { - $this->timezone = new DateTimeZone(date_default_timezone_get()); - } - - return $this->timezone; - } - - /** - * Sets the default format to be used by the number_format filter. - * - * @param int $decimal the number of decimal places to use - * @param string $decimalPoint the character(s) to use for the decimal point - * @param string $thousandSep the character(s) to use for the thousands separator - */ - public function setNumberFormat($decimal, $decimalPoint, $thousandSep) - { - $this->numberFormat = array($decimal, $decimalPoint, $thousandSep); - } - - /** - * Get the default format used by the number_format filter. - * - * @return array The arguments for number_format() - */ - public function getNumberFormat() - { - return $this->numberFormat; - } - - public function getTokenParsers() - { - return array( - new Twig_TokenParser_For(), - new Twig_TokenParser_If(), - new Twig_TokenParser_Extends(), - new Twig_TokenParser_Include(), - new Twig_TokenParser_Block(), - new Twig_TokenParser_Use(), - new Twig_TokenParser_Filter(), - new Twig_TokenParser_Macro(), - new Twig_TokenParser_Import(), - new Twig_TokenParser_From(), - new Twig_TokenParser_Set(), - new Twig_TokenParser_Spaceless(), - new Twig_TokenParser_Flush(), - new Twig_TokenParser_Do(), - new Twig_TokenParser_Embed(), - new Twig_TokenParser_With(), - ); - } - - public function getFilters() - { - $filters = array( - // formatting filters - new Twig_SimpleFilter('date', 'twig_date_format_filter', array('needs_environment' => true)), - new Twig_SimpleFilter('date_modify', 'twig_date_modify_filter', array('needs_environment' => true)), - new Twig_SimpleFilter('format', 'sprintf'), - new Twig_SimpleFilter('replace', 'twig_replace_filter'), - new Twig_SimpleFilter('number_format', 'twig_number_format_filter', array('needs_environment' => true)), - new Twig_SimpleFilter('abs', 'abs'), - new Twig_SimpleFilter('round', 'twig_round'), - - // encoding - new Twig_SimpleFilter('url_encode', 'twig_urlencode_filter'), - new Twig_SimpleFilter('json_encode', 'twig_jsonencode_filter'), - new Twig_SimpleFilter('convert_encoding', 'twig_convert_encoding'), - - // string filters - new Twig_SimpleFilter('title', 'twig_title_string_filter', array('needs_environment' => true)), - new Twig_SimpleFilter('capitalize', 'twig_capitalize_string_filter', array('needs_environment' => true)), - new Twig_SimpleFilter('upper', 'strtoupper'), - new Twig_SimpleFilter('lower', 'strtolower'), - new Twig_SimpleFilter('striptags', 'strip_tags'), - new Twig_SimpleFilter('trim', 'twig_trim_filter'), - new Twig_SimpleFilter('nl2br', 'nl2br', array('pre_escape' => 'html', 'is_safe' => array('html'))), - - // array helpers - new Twig_SimpleFilter('join', 'twig_join_filter'), - new Twig_SimpleFilter('split', 'twig_split_filter', array('needs_environment' => true)), - new Twig_SimpleFilter('sort', 'twig_sort_filter'), - new Twig_SimpleFilter('merge', 'twig_array_merge'), - new Twig_SimpleFilter('batch', 'twig_array_batch'), - - // string/array filters - new Twig_SimpleFilter('reverse', 'twig_reverse_filter', array('needs_environment' => true)), - new Twig_SimpleFilter('length', 'twig_length_filter', array('needs_environment' => true)), - new Twig_SimpleFilter('slice', 'twig_slice', array('needs_environment' => true)), - new Twig_SimpleFilter('first', 'twig_first', array('needs_environment' => true)), - new Twig_SimpleFilter('last', 'twig_last', array('needs_environment' => true)), - - // iteration and runtime - new Twig_SimpleFilter('default', '_twig_default_filter', array('node_class' => 'Twig_Node_Expression_Filter_Default')), - new Twig_SimpleFilter('keys', 'twig_get_array_keys_filter'), - - // escaping - new Twig_SimpleFilter('escape', 'twig_escape_filter', array('needs_environment' => true, 'is_safe_callback' => 'twig_escape_filter_is_safe')), - new Twig_SimpleFilter('e', 'twig_escape_filter', array('needs_environment' => true, 'is_safe_callback' => 'twig_escape_filter_is_safe')), - ); - - if (function_exists('mb_get_info')) { - $filters[] = new Twig_SimpleFilter('upper', 'twig_upper_filter', array('needs_environment' => true)); - $filters[] = new Twig_SimpleFilter('lower', 'twig_lower_filter', array('needs_environment' => true)); - } - - return $filters; - } - - public function getFunctions() - { - return array( - new Twig_SimpleFunction('max', 'max'), - new Twig_SimpleFunction('min', 'min'), - new Twig_SimpleFunction('range', 'range'), - new Twig_SimpleFunction('constant', 'twig_constant'), - new Twig_SimpleFunction('cycle', 'twig_cycle'), - new Twig_SimpleFunction('random', 'twig_random', array('needs_environment' => true)), - new Twig_SimpleFunction('date', 'twig_date_converter', array('needs_environment' => true)), - new Twig_SimpleFunction('include', 'twig_include', array('needs_environment' => true, 'needs_context' => true, 'is_safe' => array('all'))), - new Twig_SimpleFunction('source', 'twig_source', array('needs_environment' => true, 'is_safe' => array('all'))), - ); - } - - public function getTests() - { - return array( - new Twig_SimpleTest('even', null, array('node_class' => 'Twig_Node_Expression_Test_Even')), - new Twig_SimpleTest('odd', null, array('node_class' => 'Twig_Node_Expression_Test_Odd')), - new Twig_SimpleTest('defined', null, array('node_class' => 'Twig_Node_Expression_Test_Defined')), - new Twig_SimpleTest('sameas', null, array('node_class' => 'Twig_Node_Expression_Test_Sameas', 'deprecated' => '1.21', 'alternative' => 'same as')), - new Twig_SimpleTest('same as', null, array('node_class' => 'Twig_Node_Expression_Test_Sameas')), - new Twig_SimpleTest('none', null, array('node_class' => 'Twig_Node_Expression_Test_Null')), - new Twig_SimpleTest('null', null, array('node_class' => 'Twig_Node_Expression_Test_Null')), - new Twig_SimpleTest('divisibleby', null, array('node_class' => 'Twig_Node_Expression_Test_Divisibleby', 'deprecated' => '1.21', 'alternative' => 'divisible by')), - new Twig_SimpleTest('divisible by', null, array('node_class' => 'Twig_Node_Expression_Test_Divisibleby')), - new Twig_SimpleTest('constant', null, array('node_class' => 'Twig_Node_Expression_Test_Constant')), - new Twig_SimpleTest('empty', 'twig_test_empty'), - new Twig_SimpleTest('iterable', 'twig_test_iterable'), - ); - } - - public function getOperators() - { - return array( - array( - 'not' => array('precedence' => 50, 'class' => 'Twig_Node_Expression_Unary_Not'), - '-' => array('precedence' => 500, 'class' => 'Twig_Node_Expression_Unary_Neg'), - '+' => array('precedence' => 500, 'class' => 'Twig_Node_Expression_Unary_Pos'), - ), - array( - 'or' => array('precedence' => 10, 'class' => 'Twig_Node_Expression_Binary_Or', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT), - 'and' => array('precedence' => 15, 'class' => 'Twig_Node_Expression_Binary_And', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT), - 'b-or' => array('precedence' => 16, 'class' => 'Twig_Node_Expression_Binary_BitwiseOr', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT), - 'b-xor' => array('precedence' => 17, 'class' => 'Twig_Node_Expression_Binary_BitwiseXor', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT), - 'b-and' => array('precedence' => 18, 'class' => 'Twig_Node_Expression_Binary_BitwiseAnd', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT), - '==' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_Equal', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT), - '!=' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_NotEqual', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT), - '<' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_Less', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT), - '>' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_Greater', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT), - '>=' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_GreaterEqual', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT), - '<=' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_LessEqual', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT), - 'not in' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_NotIn', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT), - 'in' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_In', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT), - 'matches' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_Matches', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT), - 'starts with' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_StartsWith', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT), - 'ends with' => array('precedence' => 20, 'class' => 'Twig_Node_Expression_Binary_EndsWith', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT), - '..' => array('precedence' => 25, 'class' => 'Twig_Node_Expression_Binary_Range', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT), - '+' => array('precedence' => 30, 'class' => 'Twig_Node_Expression_Binary_Add', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT), - '-' => array('precedence' => 30, 'class' => 'Twig_Node_Expression_Binary_Sub', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT), - '~' => array('precedence' => 40, 'class' => 'Twig_Node_Expression_Binary_Concat', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT), - '*' => array('precedence' => 60, 'class' => 'Twig_Node_Expression_Binary_Mul', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT), - '/' => array('precedence' => 60, 'class' => 'Twig_Node_Expression_Binary_Div', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT), - '//' => array('precedence' => 60, 'class' => 'Twig_Node_Expression_Binary_FloorDiv', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT), - '%' => array('precedence' => 60, 'class' => 'Twig_Node_Expression_Binary_Mod', 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT), - 'is' => array('precedence' => 100, 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT), - 'is not' => array('precedence' => 100, 'associativity' => Twig_ExpressionParser::OPERATOR_LEFT), - '**' => array('precedence' => 200, 'class' => 'Twig_Node_Expression_Binary_Power', 'associativity' => Twig_ExpressionParser::OPERATOR_RIGHT), - '??' => array('precedence' => 300, 'class' => 'Twig_Node_Expression_NullCoalesce', 'associativity' => Twig_ExpressionParser::OPERATOR_RIGHT), - ), - ); - } - - public function getName() - { - return 'core'; - } -} - -/** - * Cycles over a value. - * - * @param ArrayAccess|array $values - * @param int $position The cycle position - * - * @return string The next value in the cycle - */ -function twig_cycle($values, $position) -{ - if (!is_array($values) && !$values instanceof ArrayAccess) { - return $values; - } - - return $values[$position % count($values)]; -} - -/** - * Returns a random value depending on the supplied parameter type: - * - a random item from a Traversable or array - * - a random character from a string - * - a random integer between 0 and the integer parameter. - * - * @param Twig_Environment $env - * @param Traversable|array|int|float|string $values The values to pick a random item from - * - * @throws Twig_Error_Runtime when $values is an empty array (does not apply to an empty string which is returned as is) - * - * @return mixed A random value from the given sequence - */ -function twig_random(Twig_Environment $env, $values = null) -{ - if (null === $values) { - return mt_rand(); - } - - if (is_int($values) || is_float($values)) { - return $values < 0 ? mt_rand($values, 0) : mt_rand(0, $values); - } - - if ($values instanceof Traversable) { - $values = iterator_to_array($values); - } elseif (is_string($values)) { - if ('' === $values) { - return ''; - } - if (null !== $charset = $env->getCharset()) { - if ('UTF-8' !== $charset) { - $values = twig_convert_encoding($values, 'UTF-8', $charset); - } - - // unicode version of str_split() - // split at all positions, but not after the start and not before the end - $values = preg_split('/(?<!^)(?!$)/u', $values); - - if ('UTF-8' !== $charset) { - foreach ($values as $i => $value) { - $values[$i] = twig_convert_encoding($value, $charset, 'UTF-8'); - } - } - } else { - return $values[mt_rand(0, strlen($values) - 1)]; - } - } - - if (!is_array($values)) { - return $values; - } - - if (0 === count($values)) { - throw new Twig_Error_Runtime('The random function cannot pick from an empty array.'); - } - - return $values[array_rand($values, 1)]; -} - -/** - * Converts a date to the given format. - * - * <pre> - * {{ post.published_at|date("m/d/Y") }} - * </pre> - * - * @param Twig_Environment $env - * @param DateTime|DateTimeInterface|DateInterval|string $date A date - * @param string|null $format The target format, null to use the default - * @param DateTimeZone|string|null|false $timezone The target timezone, null to use the default, false to leave unchanged - * - * @return string The formatted date - */ -function twig_date_format_filter(Twig_Environment $env, $date, $format = null, $timezone = null) -{ - if (null === $format) { - $formats = $env->getExtension('Twig_Extension_Core')->getDateFormat(); - $format = $date instanceof DateInterval ? $formats[1] : $formats[0]; - } - - if ($date instanceof DateInterval) { - return $date->format($format); - } - - return twig_date_converter($env, $date, $timezone)->format($format); -} - -/** - * Returns a new date object modified. - * - * <pre> - * {{ post.published_at|date_modify("-1day")|date("m/d/Y") }} - * </pre> - * - * @param Twig_Environment $env - * @param DateTime|string $date A date - * @param string $modifier A modifier string - * - * @return DateTime A new date object - */ -function twig_date_modify_filter(Twig_Environment $env, $date, $modifier) -{ - $date = twig_date_converter($env, $date, false); - $resultDate = $date->modify($modifier); - - // This is a hack to ensure PHP 5.2 support and support for DateTimeImmutable - // DateTime::modify does not return the modified DateTime object < 5.3.0 - // and DateTimeImmutable does not modify $date. - return null === $resultDate ? $date : $resultDate; -} - -/** - * Converts an input to a DateTime instance. - * - * <pre> - * {% if date(user.created_at) < date('+2days') %} - * {# do something #} - * {% endif %} - * </pre> - * - * @param Twig_Environment $env - * @param DateTime|DateTimeInterface|string|null $date A date - * @param DateTimeZone|string|null|false $timezone The target timezone, null to use the default, false to leave unchanged - * - * @return DateTime A DateTime instance - */ -function twig_date_converter(Twig_Environment $env, $date = null, $timezone = null) -{ - // determine the timezone - if (false !== $timezone) { - if (null === $timezone) { - $timezone = $env->getExtension('Twig_Extension_Core')->getTimezone(); - } elseif (!$timezone instanceof DateTimeZone) { - $timezone = new DateTimeZone($timezone); - } - } - - // immutable dates - if ($date instanceof DateTimeImmutable) { - return false !== $timezone ? $date->setTimezone($timezone) : $date; - } - - if ($date instanceof DateTime || $date instanceof DateTimeInterface) { - $date = clone $date; - if (false !== $timezone) { - $date->setTimezone($timezone); - } - - return $date; - } - - if (null === $date || 'now' === $date) { - return new DateTime($date, false !== $timezone ? $timezone : $env->getExtension('Twig_Extension_Core')->getTimezone()); - } - - $asString = (string) $date; - if (ctype_digit($asString) || (!empty($asString) && '-' === $asString[0] && ctype_digit(substr($asString, 1)))) { - $date = new DateTime('@'.$date); - } else { - $date = new DateTime($date, $env->getExtension('Twig_Extension_Core')->getTimezone()); - } - - if (false !== $timezone) { - $date->setTimezone($timezone); - } - - return $date; -} - -/** - * Replaces strings within a string. - * - * @param string $str String to replace in - * @param array|Traversable $from Replace values - * @param string|null $to Replace to, deprecated (@see http://php.net/manual/en/function.strtr.php) - * - * @return string - */ -function twig_replace_filter($str, $from, $to = null) -{ - if ($from instanceof Traversable) { - $from = iterator_to_array($from); - } elseif (is_string($from) && is_string($to)) { - @trigger_error('Using "replace" with character by character replacement is deprecated since version 1.22 and will be removed in Twig 2.0', E_USER_DEPRECATED); - - return strtr($str, $from, $to); - } elseif (!is_array($from)) { - throw new Twig_Error_Runtime(sprintf('The "replace" filter expects an array or "Traversable" as replace values, got "%s".', is_object($from) ? get_class($from) : gettype($from))); - } - - return strtr($str, $from); -} - -/** - * Rounds a number. - * - * @param int|float $value The value to round - * @param int|float $precision The rounding precision - * @param string $method The method to use for rounding - * - * @return int|float The rounded number - */ -function twig_round($value, $precision = 0, $method = 'common') -{ - if ('common' == $method) { - return round($value, $precision); - } - - if ('ceil' != $method && 'floor' != $method) { - throw new Twig_Error_Runtime('The round filter only supports the "common", "ceil", and "floor" methods.'); - } - - return $method($value * pow(10, $precision)) / pow(10, $precision); -} - -/** - * Number format filter. - * - * All of the formatting options can be left null, in that case the defaults will - * be used. Supplying any of the parameters will override the defaults set in the - * environment object. - * - * @param Twig_Environment $env - * @param mixed $number A float/int/string of the number to format - * @param int $decimal the number of decimal points to display - * @param string $decimalPoint the character(s) to use for the decimal point - * @param string $thousandSep the character(s) to use for the thousands separator - * - * @return string The formatted number - */ -function twig_number_format_filter(Twig_Environment $env, $number, $decimal = null, $decimalPoint = null, $thousandSep = null) -{ - $defaults = $env->getExtension('Twig_Extension_Core')->getNumberFormat(); - if (null === $decimal) { - $decimal = $defaults[0]; - } - - if (null === $decimalPoint) { - $decimalPoint = $defaults[1]; - } - - if (null === $thousandSep) { - $thousandSep = $defaults[2]; - } - - return number_format((float) $number, $decimal, $decimalPoint, $thousandSep); -} - -/** - * URL encodes (RFC 3986) a string as a path segment or an array as a query string. - * - * @param string|array $url A URL or an array of query parameters - * - * @return string The URL encoded value - */ -function twig_urlencode_filter($url) -{ - if (is_array($url)) { - if (defined('PHP_QUERY_RFC3986')) { - return http_build_query($url, '', '&', PHP_QUERY_RFC3986); - } - - return http_build_query($url, '', '&'); - } - - return rawurlencode($url); -} - -if (PHP_VERSION_ID < 50300) { - /** - * JSON encodes a variable. - * - * @param mixed $value the value to encode - * @param int $options Not used on PHP 5.2.x - * - * @return mixed The JSON encoded value - */ - function twig_jsonencode_filter($value, $options = 0) - { - if ($value instanceof Twig_Markup) { - $value = (string) $value; - } elseif (is_array($value)) { - array_walk_recursive($value, '_twig_markup2string'); - } - - return json_encode($value); - } -} else { - /** - * JSON encodes a variable. - * - * @param mixed $value the value to encode - * @param int $options Bitmask consisting of JSON_HEX_QUOT, JSON_HEX_TAG, JSON_HEX_AMP, JSON_HEX_APOS, JSON_NUMERIC_CHECK, JSON_PRETTY_PRINT, JSON_UNESCAPED_SLASHES, JSON_FORCE_OBJECT - * - * @return mixed The JSON encoded value - */ - function twig_jsonencode_filter($value, $options = 0) - { - if ($value instanceof Twig_Markup) { - $value = (string) $value; - } elseif (is_array($value)) { - array_walk_recursive($value, '_twig_markup2string'); - } - - return json_encode($value, $options); - } -} - -function _twig_markup2string(&$value) -{ - if ($value instanceof Twig_Markup) { - $value = (string) $value; - } -} - -/** - * Merges an array with another one. - * - * <pre> - * {% set items = { 'apple': 'fruit', 'orange': 'fruit' } %} - * - * {% set items = items|merge({ 'peugeot': 'car' }) %} - * - * {# items now contains { 'apple': 'fruit', 'orange': 'fruit', 'peugeot': 'car' } #} - * </pre> - * - * @param array|Traversable $arr1 An array - * @param array|Traversable $arr2 An array - * - * @return array The merged array - */ -function twig_array_merge($arr1, $arr2) -{ - if ($arr1 instanceof Traversable) { - $arr1 = iterator_to_array($arr1); - } elseif (!is_array($arr1)) { - throw new Twig_Error_Runtime(sprintf('The merge filter only works with arrays or "Traversable", got "%s" as first argument.', gettype($arr1))); - } - - if ($arr2 instanceof Traversable) { - $arr2 = iterator_to_array($arr2); - } elseif (!is_array($arr2)) { - throw new Twig_Error_Runtime(sprintf('The merge filter only works with arrays or "Traversable", got "%s" as second argument.', gettype($arr2))); - } - - return array_merge($arr1, $arr2); -} - -/** - * Slices a variable. - * - * @param Twig_Environment $env - * @param mixed $item A variable - * @param int $start Start of the slice - * @param int $length Size of the slice - * @param bool $preserveKeys Whether to preserve key or not (when the input is an array) - * - * @return mixed The sliced variable - */ -function twig_slice(Twig_Environment $env, $item, $start, $length = null, $preserveKeys = false) -{ - if ($item instanceof Traversable) { - while ($item instanceof IteratorAggregate) { - $item = $item->getIterator(); - } - - if ($start >= 0 && $length >= 0 && $item instanceof Iterator) { - try { - return iterator_to_array(new LimitIterator($item, $start, $length === null ? -1 : $length), $preserveKeys); - } catch (OutOfBoundsException $exception) { - return array(); - } - } - - $item = iterator_to_array($item, $preserveKeys); - } - - if (is_array($item)) { - return array_slice($item, $start, $length, $preserveKeys); - } - - $item = (string) $item; - - if (function_exists('mb_get_info') && null !== $charset = $env->getCharset()) { - return (string) mb_substr($item, $start, null === $length ? mb_strlen($item, $charset) - $start : $length, $charset); - } - - return (string) (null === $length ? substr($item, $start) : substr($item, $start, $length)); -} - -/** - * Returns the first element of the item. - * - * @param Twig_Environment $env - * @param mixed $item A variable - * - * @return mixed The first element of the item - */ -function twig_first(Twig_Environment $env, $item) -{ - $elements = twig_slice($env, $item, 0, 1, false); - - return is_string($elements) ? $elements : current($elements); -} - -/** - * Returns the last element of the item. - * - * @param Twig_Environment $env - * @param mixed $item A variable - * - * @return mixed The last element of the item - */ -function twig_last(Twig_Environment $env, $item) -{ - $elements = twig_slice($env, $item, -1, 1, false); - - return is_string($elements) ? $elements : current($elements); -} - -/** - * Joins the values to a string. - * - * The separator between elements is an empty string per default, you can define it with the optional parameter. - * - * <pre> - * {{ [1, 2, 3]|join('|') }} - * {# returns 1|2|3 #} - * - * {{ [1, 2, 3]|join }} - * {# returns 123 #} - * </pre> - * - * @param array $value An array - * @param string $glue The separator - * - * @return string The concatenated string - */ -function twig_join_filter($value, $glue = '') -{ - if ($value instanceof Traversable) { - $value = iterator_to_array($value, false); - } - - return implode($glue, (array) $value); -} - -/** - * Splits the string into an array. - * - * <pre> - * {{ "one,two,three"|split(',') }} - * {# returns [one, two, three] #} - * - * {{ "one,two,three,four,five"|split(',', 3) }} - * {# returns [one, two, "three,four,five"] #} - * - * {{ "123"|split('') }} - * {# returns [1, 2, 3] #} - * - * {{ "aabbcc"|split('', 2) }} - * {# returns [aa, bb, cc] #} - * </pre> - * - * @param Twig_Environment $env - * @param string $value A string - * @param string $delimiter The delimiter - * @param int $limit The limit - * - * @return array The split string as an array - */ -function twig_split_filter(Twig_Environment $env, $value, $delimiter, $limit = null) -{ - if (!empty($delimiter)) { - return null === $limit ? explode($delimiter, $value) : explode($delimiter, $value, $limit); - } - - if (!function_exists('mb_get_info') || null === $charset = $env->getCharset()) { - return str_split($value, null === $limit ? 1 : $limit); - } - - if ($limit <= 1) { - return preg_split('/(?<!^)(?!$)/u', $value); - } - - $length = mb_strlen($value, $charset); - if ($length < $limit) { - return array($value); - } - - $r = array(); - for ($i = 0; $i < $length; $i += $limit) { - $r[] = mb_substr($value, $i, $limit, $charset); - } - - return $r; -} - -// The '_default' filter is used internally to avoid using the ternary operator -// which costs a lot for big contexts (before PHP 5.4). So, on average, -// a function call is cheaper. -/** - * @internal - */ -function _twig_default_filter($value, $default = '') -{ - if (twig_test_empty($value)) { - return $default; - } - - return $value; -} - -/** - * Returns the keys for the given array. - * - * It is useful when you want to iterate over the keys of an array: - * - * <pre> - * {% for key in array|keys %} - * {# ... #} - * {% endfor %} - * </pre> - * - * @param array $array An array - * - * @return array The keys - */ -function twig_get_array_keys_filter($array) -{ - if ($array instanceof Traversable) { - while ($array instanceof IteratorAggregate) { - $array = $array->getIterator(); - } - - if ($array instanceof Iterator) { - $keys = array(); - $array->rewind(); - while ($array->valid()) { - $keys[] = $array->key(); - $array->next(); - } - - return $keys; - } - - $keys = array(); - foreach ($array as $key => $item) { - $keys[] = $key; - } - - return $keys; - } - - if (!is_array($array)) { - return array(); - } - - return array_keys($array); -} - -/** - * Reverses a variable. - * - * @param Twig_Environment $env - * @param array|Traversable|string $item An array, a Traversable instance, or a string - * @param bool $preserveKeys Whether to preserve key or not - * - * @return mixed The reversed input - */ -function twig_reverse_filter(Twig_Environment $env, $item, $preserveKeys = false) -{ - if ($item instanceof Traversable) { - return array_reverse(iterator_to_array($item), $preserveKeys); - } - - if (is_array($item)) { - return array_reverse($item, $preserveKeys); - } - - if (null !== $charset = $env->getCharset()) { - $string = (string) $item; - - if ('UTF-8' !== $charset) { - $item = twig_convert_encoding($string, 'UTF-8', $charset); - } - - preg_match_all('/./us', $item, $matches); - - $string = implode('', array_reverse($matches[0])); - - if ('UTF-8' !== $charset) { - $string = twig_convert_encoding($string, $charset, 'UTF-8'); - } - - return $string; - } - - return strrev((string) $item); -} - -/** - * Sorts an array. - * - * @param array|Traversable $array - * - * @return array - */ -function twig_sort_filter($array) -{ - if ($array instanceof Traversable) { - $array = iterator_to_array($array); - } elseif (!is_array($array)) { - throw new Twig_Error_Runtime(sprintf('The sort filter only works with arrays or "Traversable", got "%s".', gettype($array))); - } - - asort($array); - - return $array; -} - -/** - * @internal - */ -function twig_in_filter($value, $compare) -{ - if (is_array($compare)) { - return in_array($value, $compare, is_object($value) || is_resource($value)); - } elseif (is_string($compare) && (is_string($value) || is_int($value) || is_float($value))) { - return '' === $value || false !== strpos($compare, (string) $value); - } elseif ($compare instanceof Traversable) { - if (is_object($value) || is_resource($value)) { - foreach ($compare as $item) { - if ($item === $value) { - return true; - } - } - } else { - foreach ($compare as $item) { - if ($item == $value) { - return true; - } - } - } - - return false; - } - - return false; -} - -/** - * Returns a trimmed string. - * - * @return string - * - * @throws Twig_Error_Runtime When an invalid trimming side is used (not a string or not 'left', 'right', or 'both') - */ -function twig_trim_filter($string, $characterMask = null, $side = 'both') -{ - if (null === $characterMask) { - $characterMask = " \t\n\r\0\x0B"; - } - - switch ($side) { - case 'both': - return trim($string, $characterMask); - case 'left': - return ltrim($string, $characterMask); - case 'right': - return rtrim($string, $characterMask); - default: - throw new Twig_Error_Runtime('Trimming side must be "left", "right" or "both".'); - } -} - -/** - * Escapes a string. - * - * @param Twig_Environment $env - * @param mixed $string The value to be escaped - * @param string $strategy The escaping strategy - * @param string $charset The charset - * @param bool $autoescape Whether the function is called by the auto-escaping feature (true) or by the developer (false) - * - * @return string - */ -function twig_escape_filter(Twig_Environment $env, $string, $strategy = 'html', $charset = null, $autoescape = false) -{ - if ($autoescape && $string instanceof Twig_Markup) { - return $string; - } - - if (!is_string($string)) { - if (is_object($string) && method_exists($string, '__toString')) { - $string = (string) $string; - } elseif (in_array($strategy, array('html', 'js', 'css', 'html_attr', 'url'))) { - return $string; - } - } - - if (null === $charset) { - $charset = $env->getCharset(); - } - - switch ($strategy) { - case 'html': - // see http://php.net/htmlspecialchars - - // Using a static variable to avoid initializing the array - // each time the function is called. Moving the declaration on the - // top of the function slow downs other escaping strategies. - static $htmlspecialcharsCharsets = array( - 'ISO-8859-1' => true, 'ISO8859-1' => true, - 'ISO-8859-15' => true, 'ISO8859-15' => true, - 'utf-8' => true, 'UTF-8' => true, - 'CP866' => true, 'IBM866' => true, '866' => true, - 'CP1251' => true, 'WINDOWS-1251' => true, 'WIN-1251' => true, - '1251' => true, - 'CP1252' => true, 'WINDOWS-1252' => true, '1252' => true, - 'KOI8-R' => true, 'KOI8-RU' => true, 'KOI8R' => true, - 'BIG5' => true, '950' => true, - 'GB2312' => true, '936' => true, - 'BIG5-HKSCS' => true, - 'SHIFT_JIS' => true, 'SJIS' => true, '932' => true, - 'EUC-JP' => true, 'EUCJP' => true, - 'ISO8859-5' => true, 'ISO-8859-5' => true, 'MACROMAN' => true, - ); - - if (isset($htmlspecialcharsCharsets[$charset])) { - return htmlspecialchars($string, ENT_QUOTES | ENT_SUBSTITUTE, $charset); - } - - if (isset($htmlspecialcharsCharsets[strtoupper($charset)])) { - // cache the lowercase variant for future iterations - $htmlspecialcharsCharsets[$charset] = true; - - return htmlspecialchars($string, ENT_QUOTES | ENT_SUBSTITUTE, $charset); - } - - $string = twig_convert_encoding($string, 'UTF-8', $charset); - $string = htmlspecialchars($string, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'); - - return twig_convert_encoding($string, $charset, 'UTF-8'); - - case 'js': - // escape all non-alphanumeric characters - // into their \xHH or \uHHHH representations - if ('UTF-8' !== $charset) { - $string = twig_convert_encoding($string, 'UTF-8', $charset); - } - - if (0 == strlen($string) ? false : 1 !== preg_match('/^./su', $string)) { - throw new Twig_Error_Runtime('The string to escape is not a valid UTF-8 string.'); - } +use Twig\Extension\CoreExtension; - $string = preg_replace_callback('#[^a-zA-Z0-9,\._]#Su', '_twig_escape_js_callback', $string); +class_exists('Twig\Extension\CoreExtension'); - if ('UTF-8' !== $charset) { - $string = twig_convert_encoding($string, $charset, 'UTF-8'); - } - - return $string; - - case 'css': - if ('UTF-8' !== $charset) { - $string = twig_convert_encoding($string, 'UTF-8', $charset); - } - - if (0 == strlen($string) ? false : 1 !== preg_match('/^./su', $string)) { - throw new Twig_Error_Runtime('The string to escape is not a valid UTF-8 string.'); - } - - $string = preg_replace_callback('#[^a-zA-Z0-9]#Su', '_twig_escape_css_callback', $string); - - if ('UTF-8' !== $charset) { - $string = twig_convert_encoding($string, $charset, 'UTF-8'); - } - - return $string; - - case 'html_attr': - if ('UTF-8' !== $charset) { - $string = twig_convert_encoding($string, 'UTF-8', $charset); - } - - if (0 == strlen($string) ? false : 1 !== preg_match('/^./su', $string)) { - throw new Twig_Error_Runtime('The string to escape is not a valid UTF-8 string.'); - } - - $string = preg_replace_callback('#[^a-zA-Z0-9,\.\-_]#Su', '_twig_escape_html_attr_callback', $string); - - if ('UTF-8' !== $charset) { - $string = twig_convert_encoding($string, $charset, 'UTF-8'); - } - - return $string; - - case 'url': - if (PHP_VERSION_ID < 50300) { - return str_replace('%7E', '~', rawurlencode($string)); - } - - return rawurlencode($string); - - default: - static $escapers; - - if (null === $escapers) { - $escapers = $env->getExtension('Twig_Extension_Core')->getEscapers(); - } - - if (isset($escapers[$strategy])) { - return call_user_func($escapers[$strategy], $env, $string, $charset); - } - - $validStrategies = implode(', ', array_merge(array('html', 'js', 'url', 'css', 'html_attr'), array_keys($escapers))); - - throw new Twig_Error_Runtime(sprintf('Invalid escaping strategy "%s" (valid ones: %s).', $strategy, $validStrategies)); - } -} - -/** - * @internal - */ -function twig_escape_filter_is_safe(Twig_Node $filterArgs) -{ - foreach ($filterArgs as $arg) { - if ($arg instanceof Twig_Node_Expression_Constant) { - return array($arg->getAttribute('value')); - } - - return array(); - } - - return array('html'); -} - -if (function_exists('mb_convert_encoding')) { - function twig_convert_encoding($string, $to, $from) - { - return mb_convert_encoding($string, $to, $from); - } -} elseif (function_exists('iconv')) { - function twig_convert_encoding($string, $to, $from) - { - return iconv($from, $to, $string); - } -} else { - function twig_convert_encoding($string, $to, $from) +if (\false) { + class Twig_Extension_Core extends CoreExtension { - throw new Twig_Error_Runtime('No suitable convert encoding function (use UTF-8 as your encoding or install the iconv or mbstring extension).'); } } - -function _twig_escape_js_callback($matches) -{ - $char = $matches[0]; - - // \xHH - if (!isset($char[1])) { - return '\\x'.strtoupper(substr('00'.bin2hex($char), -2)); - } - - // \uHHHH - $char = twig_convert_encoding($char, 'UTF-16BE', 'UTF-8'); - $char = strtoupper(bin2hex($char)); - - if (4 >= strlen($char)) { - return sprintf('\u%04s', $char); - } - - return sprintf('\u%04s\u%04s', substr($char, 0, -4), substr($char, -4)); -} - -function _twig_escape_css_callback($matches) -{ - $char = $matches[0]; - - // \xHH - if (!isset($char[1])) { - $hex = ltrim(strtoupper(bin2hex($char)), '0'); - if (0 === strlen($hex)) { - $hex = '0'; - } - - return '\\'.$hex.' '; - } - - // \uHHHH - $char = twig_convert_encoding($char, 'UTF-16BE', 'UTF-8'); - - return '\\'.ltrim(strtoupper(bin2hex($char)), '0').' '; -} - -/** - * This function is adapted from code coming from Zend Framework. - * - * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) - * @license http://framework.zend.com/license/new-bsd New BSD License - */ -function _twig_escape_html_attr_callback($matches) -{ - /* - * While HTML supports far more named entities, the lowest common denominator - * has become HTML5's XML Serialisation which is restricted to the those named - * entities that XML supports. Using HTML entities would result in this error: - * XML Parsing Error: undefined entity - */ - static $entityMap = array( - 34 => 'quot', /* quotation mark */ - 38 => 'amp', /* ampersand */ - 60 => 'lt', /* less-than sign */ - 62 => 'gt', /* greater-than sign */ - ); - - $chr = $matches[0]; - $ord = ord($chr); - - /* - * The following replaces characters undefined in HTML with the - * hex entity for the Unicode replacement character. - */ - if (($ord <= 0x1f && $chr != "\t" && $chr != "\n" && $chr != "\r") || ($ord >= 0x7f && $ord <= 0x9f)) { - return '�'; - } - - /* - * Check if the current character to escape has a name entity we should - * replace it with while grabbing the hex value of the character. - */ - if (strlen($chr) == 1) { - $hex = strtoupper(substr('00'.bin2hex($chr), -2)); - } else { - $chr = twig_convert_encoding($chr, 'UTF-16BE', 'UTF-8'); - $hex = strtoupper(substr('0000'.bin2hex($chr), -4)); - } - - $int = hexdec($hex); - if (array_key_exists($int, $entityMap)) { - return sprintf('&%s;', $entityMap[$int]); - } - - /* - * Per OWASP recommendations, we'll use hex entities for any other - * characters where a named entity does not exist. - */ - return sprintf('&#x%s;', $hex); -} - -// add multibyte extensions if possible -if (function_exists('mb_get_info')) { - /** - * Returns the length of a variable. - * - * @param Twig_Environment $env - * @param mixed $thing A variable - * - * @return int The length of the value - */ - function twig_length_filter(Twig_Environment $env, $thing) - { - if (null === $thing) { - return 0; - } - - if (is_scalar($thing)) { - return mb_strlen($thing, $env->getCharset()); - } - - if (is_object($thing) && method_exists($thing, '__toString') && !$thing instanceof \Countable) { - return mb_strlen((string) $thing, $env->getCharset()); - } - - if ($thing instanceof \Countable || is_array($thing)) { - return count($thing); - } - - return 1; - } - - /** - * Converts a string to uppercase. - * - * @param Twig_Environment $env - * @param string $string A string - * - * @return string The uppercased string - */ - function twig_upper_filter(Twig_Environment $env, $string) - { - if (null !== $charset = $env->getCharset()) { - return mb_strtoupper($string, $charset); - } - - return strtoupper($string); - } - - /** - * Converts a string to lowercase. - * - * @param Twig_Environment $env - * @param string $string A string - * - * @return string The lowercased string - */ - function twig_lower_filter(Twig_Environment $env, $string) - { - if (null !== $charset = $env->getCharset()) { - return mb_strtolower($string, $charset); - } - - return strtolower($string); - } - - /** - * Returns a titlecased string. - * - * @param Twig_Environment $env - * @param string $string A string - * - * @return string The titlecased string - */ - function twig_title_string_filter(Twig_Environment $env, $string) - { - if (null !== $charset = $env->getCharset()) { - return mb_convert_case($string, MB_CASE_TITLE, $charset); - } - - return ucwords(strtolower($string)); - } - - /** - * Returns a capitalized string. - * - * @param Twig_Environment $env - * @param string $string A string - * - * @return string The capitalized string - */ - function twig_capitalize_string_filter(Twig_Environment $env, $string) - { - if (null !== $charset = $env->getCharset()) { - return mb_strtoupper(mb_substr($string, 0, 1, $charset), $charset).mb_strtolower(mb_substr($string, 1, mb_strlen($string, $charset), $charset), $charset); - } - - return ucfirst(strtolower($string)); - } -} -// and byte fallback -else { - /** - * Returns the length of a variable. - * - * @param Twig_Environment $env - * @param mixed $thing A variable - * - * @return int The length of the value - */ - function twig_length_filter(Twig_Environment $env, $thing) - { - if (null === $thing) { - return 0; - } - - if (is_scalar($thing)) { - return strlen($thing); - } - - if (is_object($thing) && method_exists($thing, '__toString') && !$thing instanceof \Countable) { - return strlen((string) $thing); - } - - if ($thing instanceof \Countable || is_array($thing)) { - return count($thing); - } - - return 1; - } - - /** - * Returns a titlecased string. - * - * @param Twig_Environment $env - * @param string $string A string - * - * @return string The titlecased string - */ - function twig_title_string_filter(Twig_Environment $env, $string) - { - return ucwords(strtolower($string)); - } - - /** - * Returns a capitalized string. - * - * @param Twig_Environment $env - * @param string $string A string - * - * @return string The capitalized string - */ - function twig_capitalize_string_filter(Twig_Environment $env, $string) - { - return ucfirst(strtolower($string)); - } -} - -/** - * @internal - */ -function twig_ensure_traversable($seq) -{ - if ($seq instanceof Traversable || is_array($seq)) { - return $seq; - } - - return array(); -} - -/** - * Checks if a variable is empty. - * - * <pre> - * {# evaluates to true if the foo variable is null, false, or the empty string #} - * {% if foo is empty %} - * {# ... #} - * {% endif %} - * </pre> - * - * @param mixed $value A variable - * - * @return bool true if the value is empty, false otherwise - */ -function twig_test_empty($value) -{ - if ($value instanceof Countable) { - return 0 == count($value); - } - - if (is_object($value) && method_exists($value, '__toString')) { - return '' === (string) $value; - } - - return '' === $value || false === $value || null === $value || array() === $value; -} - -/** - * Checks if a variable is traversable. - * - * <pre> - * {# evaluates to true if the foo variable is an array or a traversable object #} - * {% if foo is traversable %} - * {# ... #} - * {% endif %} - * </pre> - * - * @param mixed $value A variable - * - * @return bool true if the value is traversable - */ -function twig_test_iterable($value) -{ - return $value instanceof Traversable || is_array($value); -} - -/** - * Renders a template. - * - * @param Twig_Environment $env - * @param array $context - * @param string|array $template The template to render or an array of templates to try consecutively - * @param array $variables The variables to pass to the template - * @param bool $withContext - * @param bool $ignoreMissing Whether to ignore missing templates or not - * @param bool $sandboxed Whether to sandbox the template or not - * - * @return string The rendered template - */ -function twig_include(Twig_Environment $env, $context, $template, $variables = array(), $withContext = true, $ignoreMissing = false, $sandboxed = false) -{ - $alreadySandboxed = false; - $sandbox = null; - if ($withContext) { - $variables = array_merge($context, $variables); - } - - if ($isSandboxed = $sandboxed && $env->hasExtension('Twig_Extension_Sandbox')) { - $sandbox = $env->getExtension('Twig_Extension_Sandbox'); - if (!$alreadySandboxed = $sandbox->isSandboxed()) { - $sandbox->enableSandbox(); - } - } - - $result = null; - try { - $result = $env->resolveTemplate($template)->render($variables); - } catch (Twig_Error_Loader $e) { - if (!$ignoreMissing) { - if ($isSandboxed && !$alreadySandboxed) { - $sandbox->disableSandbox(); - } - - throw $e; - } - } catch (Throwable $e) { - if ($isSandboxed && !$alreadySandboxed) { - $sandbox->disableSandbox(); - } - - throw $e; - } catch (Exception $e) { - if ($isSandboxed && !$alreadySandboxed) { - $sandbox->disableSandbox(); - } - - throw $e; - } - - if ($isSandboxed && !$alreadySandboxed) { - $sandbox->disableSandbox(); - } - - return $result; -} - -/** - * Returns a template content without rendering it. - * - * @param Twig_Environment $env - * @param string $name The template name - * @param bool $ignoreMissing Whether to ignore missing templates or not - * - * @return string The template source - */ -function twig_source(Twig_Environment $env, $name, $ignoreMissing = false) -{ - $loader = $env->getLoader(); - try { - if (!$loader instanceof Twig_SourceContextLoaderInterface) { - return $loader->getSource($name); - } else { - return $loader->getSourceContext($name)->getCode(); - } - } catch (Twig_Error_Loader $e) { - if (!$ignoreMissing) { - throw $e; - } - } -} - -/** - * Provides the ability to get constants from instances as well as class/global constants. - * - * @param string $constant The name of the constant - * @param null|object $object The object to get the constant from - * - * @return string - */ -function twig_constant($constant, $object = null) -{ - if (null !== $object) { - $constant = get_class($object).'::'.$constant; - } - - return constant($constant); -} - -/** - * Checks if a constant exists. - * - * @param string $constant The name of the constant - * @param null|object $object The object to get the constant from - * - * @return bool - */ -function twig_constant_is_defined($constant, $object = null) -{ - if (null !== $object) { - $constant = get_class($object).'::'.$constant; - } - - return defined($constant); -} - -/** - * Batches item. - * - * @param array $items An array of items - * @param int $size The size of the batch - * @param mixed $fill A value used to fill missing items - * - * @return array - */ -function twig_array_batch($items, $size, $fill = null) -{ - if ($items instanceof Traversable) { - $items = iterator_to_array($items, false); - } - - $size = ceil($size); - - $result = array_chunk($items, $size, true); - - if (null !== $fill && !empty($result)) { - $last = count($result) - 1; - if ($fillCount = $size - count($result[$last])) { - $result[$last] = array_merge( - $result[$last], - array_fill(0, $fillCount, $fill) - ); - } - } - - return $result; -} - -class_alias('Twig_Extension_Core', 'Twig\Extension\CoreExtension', false); diff --git a/vendor/twig/twig/lib/Twig/Extension/Debug.php b/vendor/twig/twig/lib/Twig/Extension/Debug.php index d0cd1962be0d902002257b18c538c18360841eb4..bbb44fe5c60af88b4eefb1f9c0879d81098e6bdc 100644 --- a/vendor/twig/twig/lib/Twig/Extension/Debug.php +++ b/vendor/twig/twig/lib/Twig/Extension/Debug.php @@ -1,67 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +use Twig\Extension\DebugExtension; -/** - * @final - */ -class Twig_Extension_Debug extends Twig_Extension -{ - public function getFunctions() - { - // dump is safe if var_dump is overridden by xdebug - $isDumpOutputHtmlSafe = extension_loaded('xdebug') - // false means that it was not set (and the default is on) or it explicitly enabled - && (false === ini_get('xdebug.overload_var_dump') || ini_get('xdebug.overload_var_dump')) - // false means that it was not set (and the default is on) or it explicitly enabled - // xdebug.overload_var_dump produces HTML only when html_errors is also enabled - && (false === ini_get('html_errors') || ini_get('html_errors')) - || 'cli' === PHP_SAPI - ; - - return array( - new Twig_SimpleFunction('dump', 'twig_var_dump', array('is_safe' => $isDumpOutputHtmlSafe ? array('html') : array(), 'needs_context' => true, 'needs_environment' => true)), - ); - } +class_exists('Twig\Extension\DebugExtension'); - public function getName() +if (\false) { + class Twig_Extension_Debug extends DebugExtension { - return 'debug'; - } -} - -function twig_var_dump(Twig_Environment $env, $context) -{ - if (!$env->isDebug()) { - return; } - - ob_start(); - - $count = func_num_args(); - if (2 === $count) { - $vars = array(); - foreach ($context as $key => $value) { - if (!$value instanceof Twig_Template) { - $vars[$key] = $value; - } - } - - var_dump($vars); - } else { - for ($i = 2; $i < $count; ++$i) { - var_dump(func_get_arg($i)); - } - } - - return ob_get_clean(); } - -class_alias('Twig_Extension_Debug', 'Twig\Extension\DebugExtension', false); diff --git a/vendor/twig/twig/lib/Twig/Extension/Escaper.php b/vendor/twig/twig/lib/Twig/Extension/Escaper.php index 46c2d84b6843c78b097f5b25219e5986f758d248..8d15df427974499990ac1f40e8ab041872ee06b4 100644 --- a/vendor/twig/twig/lib/Twig/Extension/Escaper.php +++ b/vendor/twig/twig/lib/Twig/Extension/Escaper.php @@ -1,112 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +use Twig\Extension\EscaperExtension; -/** - * @final - */ -class Twig_Extension_Escaper extends Twig_Extension -{ - protected $defaultStrategy; +class_exists('Twig\Extension\EscaperExtension'); - /** - * @param string|false|callable $defaultStrategy An escaping strategy - * - * @see setDefaultStrategy() - */ - public function __construct($defaultStrategy = 'html') +if (\false) { + class Twig_Extension_Escaper extends EscaperExtension { - $this->setDefaultStrategy($defaultStrategy); - } - - public function getTokenParsers() - { - return array(new Twig_TokenParser_AutoEscape()); - } - - public function getNodeVisitors() - { - return array(new Twig_NodeVisitor_Escaper()); - } - - public function getFilters() - { - return array( - new Twig_SimpleFilter('raw', 'twig_raw_filter', array('is_safe' => array('all'))), - ); - } - - /** - * Sets the default strategy to use when not defined by the user. - * - * The strategy can be a valid PHP callback that takes the template - * name as an argument and returns the strategy to use. - * - * @param string|false|callable $defaultStrategy An escaping strategy - */ - public function setDefaultStrategy($defaultStrategy) - { - // for BC - if (true === $defaultStrategy) { - @trigger_error('Using "true" as the default strategy is deprecated since version 1.21. Use "html" instead.', E_USER_DEPRECATED); - - $defaultStrategy = 'html'; - } - - if ('filename' === $defaultStrategy) { - @trigger_error('Using "filename" as the default strategy is deprecated since version 1.27. Use "name" instead.', E_USER_DEPRECATED); - - $defaultStrategy = 'name'; - } - - if ('name' === $defaultStrategy) { - $defaultStrategy = array('Twig_FileExtensionEscapingStrategy', 'guess'); - } - - $this->defaultStrategy = $defaultStrategy; - } - - /** - * Gets the default strategy to use when not defined by the user. - * - * @param string $name The template name - * - * @return string|false The default strategy to use for the template - */ - public function getDefaultStrategy($name) - { - // disable string callables to avoid calling a function named html or js, - // or any other upcoming escaping strategy - if (!is_string($this->defaultStrategy) && false !== $this->defaultStrategy) { - return call_user_func($this->defaultStrategy, $name); - } - - return $this->defaultStrategy; - } - - public function getName() - { - return 'escaper'; } } - -/** - * Marks a variable as being safe. - * - * @param string $string A PHP variable - * - * @return string - */ -function twig_raw_filter($string) -{ - return $string; -} - -class_alias('Twig_Extension_Escaper', 'Twig\Extension\EscaperExtension', false); diff --git a/vendor/twig/twig/lib/Twig/Extension/GlobalsInterface.php b/vendor/twig/twig/lib/Twig/Extension/GlobalsInterface.php index 922cd2c9338215451bbf16fa205f3d0f9c172821..9bfcca4ede8e7e053caa29d38eb573c73c5e9249 100644 --- a/vendor/twig/twig/lib/Twig/Extension/GlobalsInterface.php +++ b/vendor/twig/twig/lib/Twig/Extension/GlobalsInterface.php @@ -1,24 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +use Twig\Extension\GlobalsInterface; -/** - * Enables usage of the deprecated Twig_Extension::getGlobals() method. - * - * Explicitly implement this interface if you really need to implement the - * deprecated getGlobals() method in your extensions. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -interface Twig_Extension_GlobalsInterface -{ -} +class_exists('Twig\Extension\GlobalsInterface'); -class_alias('Twig_Extension_GlobalsInterface', 'Twig\Extension\GlobalsInterface', false); +if (\false) { + class Twig_Extension_GlobalsInterface extends GlobalsInterface + { + } +} diff --git a/vendor/twig/twig/lib/Twig/Extension/InitRuntimeInterface.php b/vendor/twig/twig/lib/Twig/Extension/InitRuntimeInterface.php index 1549862f4dd7ca92d29520a8a56812b91ad5a47c..6fbf1ba5bf8cd1119c5a1ac09792c8ee76fa3e7f 100644 --- a/vendor/twig/twig/lib/Twig/Extension/InitRuntimeInterface.php +++ b/vendor/twig/twig/lib/Twig/Extension/InitRuntimeInterface.php @@ -1,24 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +use Twig\Extension\InitRuntimeInterface; -/** - * Enables usage of the deprecated Twig_Extension::initRuntime() method. - * - * Explicitly implement this interface if you really need to implement the - * deprecated initRuntime() method in your extensions. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -interface Twig_Extension_InitRuntimeInterface -{ -} +class_exists('Twig\Extension\InitRuntimeInterface'); -class_alias('Twig_Extension_InitRuntimeInterface', 'Twig\Extension\InitRuntimeInterface', false); +if (\false) { + class Twig_Extension_InitRuntimeInterface extends InitRuntimeInterface + { + } +} diff --git a/vendor/twig/twig/lib/Twig/Extension/Optimizer.php b/vendor/twig/twig/lib/Twig/Extension/Optimizer.php index 6c62e3efceaa3da2b1626e0eedf77200ba50576e..14802deb1bcfb79981c8718b44dbf5439516dd31 100644 --- a/vendor/twig/twig/lib/Twig/Extension/Optimizer.php +++ b/vendor/twig/twig/lib/Twig/Extension/Optimizer.php @@ -1,35 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +use Twig\Extension\OptimizerExtension; -/** - * @final - */ -class Twig_Extension_Optimizer extends Twig_Extension -{ - protected $optimizers; +class_exists('Twig\Extension\OptimizerExtension'); - public function __construct($optimizers = -1) +if (\false) { + class Twig_Extension_Optimizer extends OptimizerExtension { - $this->optimizers = $optimizers; - } - - public function getNodeVisitors() - { - return array(new Twig_NodeVisitor_Optimizer($this->optimizers)); - } - - public function getName() - { - return 'optimizer'; } } - -class_alias('Twig_Extension_Optimizer', 'Twig\Extension\OptimizerExtension', false); diff --git a/vendor/twig/twig/lib/Twig/Extension/Profiler.php b/vendor/twig/twig/lib/Twig/Extension/Profiler.php index fcfc002ba5c7a4114ff86efb6b68850fe23223a9..086b34f63d3a08826ceac5401f43446b7f833d43 100644 --- a/vendor/twig/twig/lib/Twig/Extension/Profiler.php +++ b/vendor/twig/twig/lib/Twig/Extension/Profiler.php @@ -1,49 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +use Twig\Extension\ProfilerExtension; -class Twig_Extension_Profiler extends Twig_Extension -{ - private $actives = array(); +class_exists('Twig\Extension\ProfilerExtension'); - public function __construct(Twig_Profiler_Profile $profile) +if (\false) { + class Twig_Extension_Profiler extends ProfilerExtension { - $this->actives[] = $profile; - } - - public function enter(Twig_Profiler_Profile $profile) - { - $this->actives[0]->addProfile($profile); - array_unshift($this->actives, $profile); - } - - public function leave(Twig_Profiler_Profile $profile) - { - $profile->leave(); - array_shift($this->actives); - - if (1 === count($this->actives)) { - $this->actives[0]->leave(); - } - } - - public function getNodeVisitors() - { - return array(new Twig_Profiler_NodeVisitor_Profiler(get_class($this))); - } - - public function getName() - { - return 'profiler'; } } - -class_alias('Twig_Extension_Profiler', 'Twig\Extension\ProfilerExtension', false); -class_exists('Twig_Profiler_Profile'); diff --git a/vendor/twig/twig/lib/Twig/Extension/Sandbox.php b/vendor/twig/twig/lib/Twig/Extension/Sandbox.php index 5cb80a717e7efeb86a36975bcd2430c9dd770939..2b8a1514f0bdc1f2988c73fa62404f8a4b6d4d7a 100644 --- a/vendor/twig/twig/lib/Twig/Extension/Sandbox.php +++ b/vendor/twig/twig/lib/Twig/Extension/Sandbox.php @@ -1,103 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +use Twig\Extension\SandboxExtension; -/** - * @final - */ -class Twig_Extension_Sandbox extends Twig_Extension -{ - protected $sandboxedGlobally; - protected $sandboxed; - protected $policy; +class_exists('Twig\Extension\SandboxExtension'); - public function __construct(Twig_Sandbox_SecurityPolicyInterface $policy, $sandboxed = false) +if (\false) { + class Twig_Extension_Sandbox extends SandboxExtension { - $this->policy = $policy; - $this->sandboxedGlobally = $sandboxed; - } - - public function getTokenParsers() - { - return array(new Twig_TokenParser_Sandbox()); - } - - public function getNodeVisitors() - { - return array(new Twig_NodeVisitor_Sandbox()); - } - - public function enableSandbox() - { - $this->sandboxed = true; - } - - public function disableSandbox() - { - $this->sandboxed = false; - } - - public function isSandboxed() - { - return $this->sandboxedGlobally || $this->sandboxed; - } - - public function isSandboxedGlobally() - { - return $this->sandboxedGlobally; - } - - public function setSecurityPolicy(Twig_Sandbox_SecurityPolicyInterface $policy) - { - $this->policy = $policy; - } - - public function getSecurityPolicy() - { - return $this->policy; - } - - public function checkSecurity($tags, $filters, $functions) - { - if ($this->isSandboxed()) { - $this->policy->checkSecurity($tags, $filters, $functions); - } - } - - public function checkMethodAllowed($obj, $method) - { - if ($this->isSandboxed()) { - $this->policy->checkMethodAllowed($obj, $method); - } - } - - public function checkPropertyAllowed($obj, $method) - { - if ($this->isSandboxed()) { - $this->policy->checkPropertyAllowed($obj, $method); - } - } - - public function ensureToStringAllowed($obj) - { - if ($this->isSandboxed() && is_object($obj)) { - $this->policy->checkMethodAllowed($obj, '__toString'); - } - - return $obj; - } - - public function getName() - { - return 'sandbox'; } } - -class_alias('Twig_Extension_Sandbox', 'Twig\Extension\SandboxExtension', false); diff --git a/vendor/twig/twig/lib/Twig/Extension/Staging.php b/vendor/twig/twig/lib/Twig/Extension/Staging.php index d3a0f9c946daf0800a1e6f892c5e4136d23f9804..7681b4985ae9bc6305dc50aebe2375ede471eb28 100644 --- a/vendor/twig/twig/lib/Twig/Extension/Staging.php +++ b/vendor/twig/twig/lib/Twig/Extension/Staging.php @@ -1,112 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +use Twig\Extension\StagingExtension; -/** - * Internal class. - * - * This class is used by Twig_Environment as a staging area and must not be used directly. - * - * @author Fabien Potencier <fabien@symfony.com> - * - * @internal - */ -class Twig_Extension_Staging extends Twig_Extension -{ - protected $functions = array(); - protected $filters = array(); - protected $visitors = array(); - protected $tokenParsers = array(); - protected $globals = array(); - protected $tests = array(); +class_exists('Twig\Extension\StagingExtension'); - public function addFunction($name, $function) +if (\false) { + class Twig_Extension_Staging extends StagingExtension { - if (isset($this->functions[$name])) { - @trigger_error(sprintf('Overriding function "%s" that is already registered is deprecated since version 1.30 and won\'t be possible anymore in 2.0.', $name), E_USER_DEPRECATED); - } - - $this->functions[$name] = $function; - } - - public function getFunctions() - { - return $this->functions; - } - - public function addFilter($name, $filter) - { - if (isset($this->filters[$name])) { - @trigger_error(sprintf('Overriding filter "%s" that is already registered is deprecated since version 1.30 and won\'t be possible anymore in 2.0.', $name), E_USER_DEPRECATED); - } - - $this->filters[$name] = $filter; - } - - public function getFilters() - { - return $this->filters; - } - - public function addNodeVisitor(Twig_NodeVisitorInterface $visitor) - { - $this->visitors[] = $visitor; - } - - public function getNodeVisitors() - { - return $this->visitors; - } - - public function addTokenParser(Twig_TokenParserInterface $parser) - { - if (isset($this->tokenParsers[$parser->getTag()])) { - @trigger_error(sprintf('Overriding tag "%s" that is already registered is deprecated since version 1.30 and won\'t be possible anymore in 2.0.', $parser->getTag()), E_USER_DEPRECATED); - } - - $this->tokenParsers[$parser->getTag()] = $parser; - } - - public function getTokenParsers() - { - return $this->tokenParsers; - } - - public function addGlobal($name, $value) - { - $this->globals[$name] = $value; - } - - public function getGlobals() - { - return $this->globals; - } - - public function addTest($name, $test) - { - if (isset($this->tests[$name])) { - @trigger_error(sprintf('Overriding test "%s" that is already registered is deprecated since version 1.30 and won\'t be possible anymore in 2.0.', $name), E_USER_DEPRECATED); - } - - $this->tests[$name] = $test; - } - - public function getTests() - { - return $this->tests; - } - - public function getName() - { - return 'staging'; } } - -class_alias('Twig_Extension_Staging', 'Twig\Extension\StagingExtension', false); diff --git a/vendor/twig/twig/lib/Twig/Extension/StringLoader.php b/vendor/twig/twig/lib/Twig/Extension/StringLoader.php index 2ce3c9924935661d73253d58e631506a39726acb..5ce2407e067edec6d020978511b7498348fbb0ea 100644 --- a/vendor/twig/twig/lib/Twig/Extension/StringLoader.php +++ b/vendor/twig/twig/lib/Twig/Extension/StringLoader.php @@ -1,47 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +use Twig\Extension\StringLoaderExtension; -/** - * @final - */ -class Twig_Extension_StringLoader extends Twig_Extension -{ - public function getFunctions() - { - return array( - new Twig_SimpleFunction('template_from_string', 'twig_template_from_string', array('needs_environment' => true)), - ); - } +class_exists('Twig\Extension\StringLoaderExtension'); - public function getName() +if (\false) { + class Twig_Extension_StringLoader extends StringLoaderExtension { - return 'string_loader'; } } - -/** - * Loads a template from a string. - * - * <pre> - * {{ include(template_from_string("Hello {{ name }}")) }} - * </pre> - * - * @param Twig_Environment $env A Twig_Environment instance - * @param string $template A template as a string or object implementing __toString() - * - * @return Twig_Template - */ -function twig_template_from_string(Twig_Environment $env, $template) -{ - return $env->createTemplate((string) $template); -} - -class_alias('Twig_Extension_StringLoader', 'Twig\Extension\StringLoaderExtension', false); diff --git a/vendor/twig/twig/lib/Twig/ExtensionInterface.php b/vendor/twig/twig/lib/Twig/ExtensionInterface.php index 946df500a8c3307cd0b248fe4266fc349b74340c..3ef2ed58688fe75208cb81a71bf8061f9e9304c8 100644 --- a/vendor/twig/twig/lib/Twig/ExtensionInterface.php +++ b/vendor/twig/twig/lib/Twig/ExtensionInterface.php @@ -1,90 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +use Twig\Extension\ExtensionInterface; -/** - * Interface implemented by extension classes. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -interface Twig_ExtensionInterface -{ - /** - * Initializes the runtime environment. - * - * This is where you can load some file that contains filter functions for instance. - * - * @deprecated since 1.23 (to be removed in 2.0), implement Twig_Extension_InitRuntimeInterface instead - */ - public function initRuntime(Twig_Environment $environment); +class_exists('Twig\Extension\ExtensionInterface'); - /** - * Returns the token parser instances to add to the existing list. - * - * @return Twig_TokenParserInterface[] - */ - public function getTokenParsers(); - - /** - * Returns the node visitor instances to add to the existing list. - * - * @return Twig_NodeVisitorInterface[] - */ - public function getNodeVisitors(); - - /** - * Returns a list of filters to add to the existing list. - * - * @return Twig_SimpleFilter[] - */ - public function getFilters(); - - /** - * Returns a list of tests to add to the existing list. - * - * @return Twig_SimpleTest[] - */ - public function getTests(); - - /** - * Returns a list of functions to add to the existing list. - * - * @return Twig_SimpleFunction[] - */ - public function getFunctions(); - - /** - * Returns a list of operators to add to the existing list. - * - * @return array<array> First array of unary operators, second array of binary operators - */ - public function getOperators(); - - /** - * Returns a list of global variables to add to the existing list. - * - * @return array An array of global variables - * - * @deprecated since 1.23 (to be removed in 2.0), implement Twig_Extension_GlobalsInterface instead - */ - public function getGlobals(); - - /** - * Returns the name of the extension. - * - * @return string The extension name - * - * @deprecated since 1.26 (to be removed in 2.0), not used anymore internally - */ - public function getName(); +if (\false) { + class Twig_ExtensionInterface extends ExtensionInterface + { + } } - -class_alias('Twig_ExtensionInterface', 'Twig\Extension\ExtensionInterface', false); -class_exists('Twig_Environment'); diff --git a/vendor/twig/twig/lib/Twig/FactoryRuntimeLoader.php b/vendor/twig/twig/lib/Twig/FactoryRuntimeLoader.php index 2cdaded1d24d18e7385850c16473684b32acf288..6834439db4e88d1483043ef2e65e3a83a54c608b 100644 --- a/vendor/twig/twig/lib/Twig/FactoryRuntimeLoader.php +++ b/vendor/twig/twig/lib/Twig/FactoryRuntimeLoader.php @@ -1,39 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +use Twig\RuntimeLoader\FactoryRuntimeLoader; -/** - * Lazy loads the runtime implementations for a Twig element. - * - * @author Robin Chalas <robin.chalas@gmail.com> - */ -class Twig_FactoryRuntimeLoader implements Twig_RuntimeLoaderInterface -{ - private $map; +class_exists('Twig\RuntimeLoader\FactoryRuntimeLoader'); - /** - * @param array $map An array where keys are class names and values factory callables - */ - public function __construct($map = array()) +if (\false) { + class Twig_FactoryRuntimeLoader extends FactoryRuntimeLoader { - $this->map = $map; - } - - public function load($class) - { - if (isset($this->map[$class])) { - $runtimeFactory = $this->map[$class]; - - return $runtimeFactory(); - } } } - -class_alias('Twig_FactoryRuntimeLoader', 'Twig\RuntimeLoader\FactoryRuntimeLoader', false); diff --git a/vendor/twig/twig/lib/Twig/FileExtensionEscapingStrategy.php b/vendor/twig/twig/lib/Twig/FileExtensionEscapingStrategy.php index 8f8cd2ee5395f6f883f979be2c86a29438d7bd3c..99c2656ff7935925599f3e32c9f991dc5d2d048b 100644 --- a/vendor/twig/twig/lib/Twig/FileExtensionEscapingStrategy.php +++ b/vendor/twig/twig/lib/Twig/FileExtensionEscapingStrategy.php @@ -1,60 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +use Twig\FileExtensionEscapingStrategy; -/** - * Default autoescaping strategy based on file names. - * - * This strategy sets the HTML as the default autoescaping strategy, - * but changes it based on the template name. - * - * Note that there is no runtime performance impact as the - * default autoescaping strategy is set at compilation time. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class Twig_FileExtensionEscapingStrategy -{ - /** - * Guesses the best autoescaping strategy based on the file name. - * - * @param string $name The template name - * - * @return string|false The escaping strategy name to use or false to disable - */ - public static function guess($name) - { - if (in_array(substr($name, -1), array('/', '\\'))) { - return 'html'; // return html for directories - } - - if ('.twig' === substr($name, -5)) { - $name = substr($name, 0, -5); - } - - $extension = pathinfo($name, PATHINFO_EXTENSION); - - switch ($extension) { - case 'js': - return 'js'; +class_exists('Twig\FileExtensionEscapingStrategy'); - case 'css': - return 'css'; - - case 'txt': - return false; - - default: - return 'html'; - } +if (\false) { + class Twig_FileExtensionEscapingStrategy extends FileExtensionEscapingStrategy + { } } - -class_alias('Twig_FileExtensionEscapingStrategy', 'Twig\FileExtensionEscapingStrategy', false); diff --git a/vendor/twig/twig/lib/Twig/Filter.php b/vendor/twig/twig/lib/Twig/Filter.php index 893d75d103fc6e7e3a1161d88c7dd32e2645645b..da4191e31f4c62a5baa73e3ddd84fd825fdfa321 100644 --- a/vendor/twig/twig/lib/Twig/Filter.php +++ b/vendor/twig/twig/lib/Twig/Filter.php @@ -9,12 +9,14 @@ * file that was distributed with this source code. */ -@trigger_error('The Twig_Filter class is deprecated since version 1.12 and will be removed in 2.0. Use Twig_SimpleFilter instead.', E_USER_DEPRECATED); +use Twig\Node\Node; + +@trigger_error('The Twig_Filter class is deprecated since version 1.12 and will be removed in 2.0. Use \Twig\TwigFilter instead.', E_USER_DEPRECATED); /** * Represents a template filter. * - * Use Twig_SimpleFilter instead. + * Use \Twig\TwigFilter instead. * * @author Fabien Potencier <fabien@symfony.com> * @@ -23,17 +25,17 @@ abstract class Twig_Filter implements Twig_FilterInterface, Twig_FilterCallableInterface { protected $options; - protected $arguments = array(); + protected $arguments = []; - public function __construct(array $options = array()) + public function __construct(array $options = []) { - $this->options = array_merge(array( + $this->options = array_merge([ 'needs_environment' => false, 'needs_context' => false, 'pre_escape' => null, 'preserves_safety' => null, 'callable' => null, - ), $options); + ], $options); } public function setArguments($arguments) @@ -56,14 +58,14 @@ abstract class Twig_Filter implements Twig_FilterInterface, Twig_FilterCallableI return $this->options['needs_context']; } - public function getSafe(Twig_Node $filterArgs) + public function getSafe(Node $filterArgs) { if (isset($this->options['is_safe'])) { return $this->options['is_safe']; } if (isset($this->options['is_safe_callback'])) { - return call_user_func($this->options['is_safe_callback'], $filterArgs); + return \call_user_func($this->options['is_safe_callback'], $filterArgs); } } diff --git a/vendor/twig/twig/lib/Twig/Filter/Function.php b/vendor/twig/twig/lib/Twig/Filter/Function.php index 71b16554e04f7a97bc548898e800106c90d0a76e..011d4ccf4600b99c1d18c1cedc466d9f5f0f34e1 100644 --- a/vendor/twig/twig/lib/Twig/Filter/Function.php +++ b/vendor/twig/twig/lib/Twig/Filter/Function.php @@ -9,12 +9,12 @@ * file that was distributed with this source code. */ -@trigger_error('The Twig_Filter_Function class is deprecated since version 1.12 and will be removed in 2.0. Use Twig_SimpleFilter instead.', E_USER_DEPRECATED); +@trigger_error('The Twig_Filter_Function class is deprecated since version 1.12 and will be removed in 2.0. Use \Twig\TwigFilter instead.', E_USER_DEPRECATED); /** * Represents a function template filter. * - * Use Twig_SimpleFilter instead. + * Use \Twig\TwigFilter instead. * * @author Fabien Potencier <fabien@symfony.com> * @@ -24,7 +24,7 @@ class Twig_Filter_Function extends Twig_Filter { protected $function; - public function __construct($function, array $options = array()) + public function __construct($function, array $options = []) { $options['callable'] = $function; diff --git a/vendor/twig/twig/lib/Twig/Filter/Method.php b/vendor/twig/twig/lib/Twig/Filter/Method.php index 1b75676c59f61dcb8a2266b6a1e1d97e82ccfb7b..5cd06282248ee53ee0706dce2b4b1d9496974241 100644 --- a/vendor/twig/twig/lib/Twig/Filter/Method.php +++ b/vendor/twig/twig/lib/Twig/Filter/Method.php @@ -9,12 +9,14 @@ * file that was distributed with this source code. */ -@trigger_error('The Twig_Filter_Method class is deprecated since version 1.12 and will be removed in 2.0. Use Twig_SimpleFilter instead.', E_USER_DEPRECATED); +use Twig\Extension\ExtensionInterface; + +@trigger_error('The Twig_Filter_Method class is deprecated since version 1.12 and will be removed in 2.0. Use \Twig\TwigFilter instead.', E_USER_DEPRECATED); /** * Represents a method template filter. * - * Use Twig_SimpleFilter instead. + * Use \Twig\TwigFilter instead. * * @author Fabien Potencier <fabien@symfony.com> * @@ -25,9 +27,9 @@ class Twig_Filter_Method extends Twig_Filter protected $extension; protected $method; - public function __construct(Twig_ExtensionInterface $extension, $method, array $options = array()) + public function __construct(ExtensionInterface $extension, $method, array $options = []) { - $options['callable'] = array($extension, $method); + $options['callable'] = [$extension, $method]; parent::__construct($options); @@ -37,6 +39,6 @@ class Twig_Filter_Method extends Twig_Filter public function compile() { - return sprintf('$this->env->getExtension(\'%s\')->%s', get_class($this->extension), $this->method); + return sprintf('$this->env->getExtension(\'%s\')->%s', \get_class($this->extension), $this->method); } } diff --git a/vendor/twig/twig/lib/Twig/Filter/Node.php b/vendor/twig/twig/lib/Twig/Filter/Node.php index 3e6b12eff2ae03e849ae1ac1babfef2a6e338634..8bb2899c52e965b8e59025fa20af928499256689 100644 --- a/vendor/twig/twig/lib/Twig/Filter/Node.php +++ b/vendor/twig/twig/lib/Twig/Filter/Node.php @@ -9,12 +9,12 @@ * file that was distributed with this source code. */ -@trigger_error('The Twig_Filter_Node class is deprecated since version 1.12 and will be removed in 2.0. Use Twig_SimpleFilter instead.', E_USER_DEPRECATED); +@trigger_error('The Twig_Filter_Node class is deprecated since version 1.12 and will be removed in 2.0. Use \Twig\TwigFilter instead.', E_USER_DEPRECATED); /** * Represents a template filter as a node. * - * Use Twig_SimpleFilter instead. + * Use \Twig\TwigFilter instead. * * @author Fabien Potencier <fabien@symfony.com> * @@ -24,7 +24,7 @@ class Twig_Filter_Node extends Twig_Filter { protected $class; - public function __construct($class, array $options = array()) + public function __construct($class, array $options = []) { parent::__construct($options); diff --git a/vendor/twig/twig/lib/Twig/FilterCallableInterface.php b/vendor/twig/twig/lib/Twig/FilterCallableInterface.php index 21b028c4eaa337ae749e535ba22f32c623cad06f..091ca97454e5f78e37963832679931c947d543b2 100644 --- a/vendor/twig/twig/lib/Twig/FilterCallableInterface.php +++ b/vendor/twig/twig/lib/Twig/FilterCallableInterface.php @@ -12,7 +12,7 @@ /** * Represents a callable template filter. * - * Use Twig_SimpleFilter instead. + * Use \Twig\TwigFilter instead. * * @author Fabien Potencier <fabien@symfony.com> * diff --git a/vendor/twig/twig/lib/Twig/FilterInterface.php b/vendor/twig/twig/lib/Twig/FilterInterface.php index 9d7e9ab6ac19fd7c44e7ddb61a8e3b6a0572a5bf..9b85f9760d6184bb2145d9c88f53f7445068189f 100644 --- a/vendor/twig/twig/lib/Twig/FilterInterface.php +++ b/vendor/twig/twig/lib/Twig/FilterInterface.php @@ -9,10 +9,12 @@ * file that was distributed with this source code. */ +use Twig\Node\Node; + /** * Represents a template filter. * - * Use Twig_SimpleFilter instead. + * Use \Twig\TwigFilter instead. * * @author Fabien Potencier <fabien@symfony.com> * @@ -31,7 +33,7 @@ interface Twig_FilterInterface public function needsContext(); - public function getSafe(Twig_Node $filterArgs); + public function getSafe(Node $filterArgs); public function getPreservesSafety(); diff --git a/vendor/twig/twig/lib/Twig/Function.php b/vendor/twig/twig/lib/Twig/Function.php index 9dc16e90820c1a2fa3a31c383bc94c693f9e5a7e..6646e746f5be67ca7ea5f49c6e0998c35146333b 100644 --- a/vendor/twig/twig/lib/Twig/Function.php +++ b/vendor/twig/twig/lib/Twig/Function.php @@ -9,12 +9,14 @@ * file that was distributed with this source code. */ -@trigger_error('The Twig_Function class is deprecated since version 1.12 and will be removed in 2.0. Use Twig_SimpleFunction instead.', E_USER_DEPRECATED); +use Twig\Node\Node; + +@trigger_error('The Twig_Function class is deprecated since version 1.12 and will be removed in 2.0. Use \Twig\TwigFunction instead.', E_USER_DEPRECATED); /** * Represents a template function. * - * Use Twig_SimpleFunction instead. + * Use \Twig\TwigFunction instead. * * @author Fabien Potencier <fabien@symfony.com> * @@ -23,15 +25,15 @@ abstract class Twig_Function implements Twig_FunctionInterface, Twig_FunctionCallableInterface { protected $options; - protected $arguments = array(); + protected $arguments = []; - public function __construct(array $options = array()) + public function __construct(array $options = []) { - $this->options = array_merge(array( + $this->options = array_merge([ 'needs_environment' => false, 'needs_context' => false, 'callable' => null, - ), $options); + ], $options); } public function setArguments($arguments) @@ -54,17 +56,17 @@ abstract class Twig_Function implements Twig_FunctionInterface, Twig_FunctionCal return $this->options['needs_context']; } - public function getSafe(Twig_Node $functionArgs) + public function getSafe(Node $functionArgs) { if (isset($this->options['is_safe'])) { return $this->options['is_safe']; } if (isset($this->options['is_safe_callback'])) { - return call_user_func($this->options['is_safe_callback'], $functionArgs); + return \call_user_func($this->options['is_safe_callback'], $functionArgs); } - return array(); + return []; } public function getCallable() diff --git a/vendor/twig/twig/lib/Twig/Function/Function.php b/vendor/twig/twig/lib/Twig/Function/Function.php index 97c0eb77f74a524cde278e12825c03b2588324a9..605d8d335ede7d08a928fe13fb52cd5a1c0794ea 100644 --- a/vendor/twig/twig/lib/Twig/Function/Function.php +++ b/vendor/twig/twig/lib/Twig/Function/Function.php @@ -10,12 +10,12 @@ * file that was distributed with this source code. */ -@trigger_error('The Twig_Function_Function class is deprecated since version 1.12 and will be removed in 2.0. Use Twig_SimpleFunction instead.', E_USER_DEPRECATED); +@trigger_error('The Twig_Function_Function class is deprecated since version 1.12 and will be removed in 2.0. Use \Twig\TwigFunction instead.', E_USER_DEPRECATED); /** * Represents a function template function. * - * Use Twig_SimpleFunction instead. + * Use \Twig\TwigFunction instead. * * @author Arnaud Le Blanc <arnaud.lb@gmail.com> * @@ -25,7 +25,7 @@ class Twig_Function_Function extends Twig_Function { protected $function; - public function __construct($function, array $options = array()) + public function __construct($function, array $options = []) { $options['callable'] = $function; diff --git a/vendor/twig/twig/lib/Twig/Function/Method.php b/vendor/twig/twig/lib/Twig/Function/Method.php index 4299e11815e28b2060ad3feae9ea953049a3920f..9e472c5d1058f811bc9eac75cf992f0a5fd3bfd0 100644 --- a/vendor/twig/twig/lib/Twig/Function/Method.php +++ b/vendor/twig/twig/lib/Twig/Function/Method.php @@ -10,12 +10,14 @@ * file that was distributed with this source code. */ -@trigger_error('The Twig_Function_Method class is deprecated since version 1.12 and will be removed in 2.0. Use Twig_SimpleFunction instead.', E_USER_DEPRECATED); +use Twig\Extension\ExtensionInterface; + +@trigger_error('The Twig_Function_Method class is deprecated since version 1.12 and will be removed in 2.0. Use \Twig\TwigFunction instead.', E_USER_DEPRECATED); /** * Represents a method template function. * - * Use Twig_SimpleFunction instead. + * Use \Twig\TwigFunction instead. * * @author Arnaud Le Blanc <arnaud.lb@gmail.com> * @@ -26,9 +28,9 @@ class Twig_Function_Method extends Twig_Function protected $extension; protected $method; - public function __construct(Twig_ExtensionInterface $extension, $method, array $options = array()) + public function __construct(ExtensionInterface $extension, $method, array $options = []) { - $options['callable'] = array($extension, $method); + $options['callable'] = [$extension, $method]; parent::__construct($options); @@ -38,6 +40,6 @@ class Twig_Function_Method extends Twig_Function public function compile() { - return sprintf('$this->env->getExtension(\'%s\')->%s', get_class($this->extension), $this->method); + return sprintf('$this->env->getExtension(\'%s\')->%s', \get_class($this->extension), $this->method); } } diff --git a/vendor/twig/twig/lib/Twig/Function/Node.php b/vendor/twig/twig/lib/Twig/Function/Node.php index 0adc5d93755c8892a213b3b44cd45fd0db0e6391..8148ec32d7b571f052a0f3d1047bcf60981a31f8 100644 --- a/vendor/twig/twig/lib/Twig/Function/Node.php +++ b/vendor/twig/twig/lib/Twig/Function/Node.php @@ -9,12 +9,12 @@ * file that was distributed with this source code. */ -@trigger_error('The Twig_Function_Node class is deprecated since version 1.12 and will be removed in 2.0. Use Twig_SimpleFunction instead.', E_USER_DEPRECATED); +@trigger_error('The Twig_Function_Node class is deprecated since version 1.12 and will be removed in 2.0. Use \Twig\TwigFunction instead.', E_USER_DEPRECATED); /** * Represents a template function as a node. * - * Use Twig_SimpleFunction instead. + * Use \Twig\TwigFunction instead. * * @author Fabien Potencier <fabien@symfony.com> * @@ -24,7 +24,7 @@ class Twig_Function_Node extends Twig_Function { protected $class; - public function __construct($class, array $options = array()) + public function __construct($class, array $options = []) { parent::__construct($options); diff --git a/vendor/twig/twig/lib/Twig/FunctionCallableInterface.php b/vendor/twig/twig/lib/Twig/FunctionCallableInterface.php index d23d69173dab693e75c8a5941d909a056d34f172..abc83ea4ae9322a057f1275716de0a8534737fd7 100644 --- a/vendor/twig/twig/lib/Twig/FunctionCallableInterface.php +++ b/vendor/twig/twig/lib/Twig/FunctionCallableInterface.php @@ -12,7 +12,7 @@ /** * Represents a callable template function. * - * Use Twig_SimpleFunction instead. + * Use \Twig\TwigFunction instead. * * @author Fabien Potencier <fabien@symfony.com> * diff --git a/vendor/twig/twig/lib/Twig/FunctionInterface.php b/vendor/twig/twig/lib/Twig/FunctionInterface.php index 00d4f95c7ce1f53651e38baa3b334a77579ca275..915d6cc3a43d95c1498e34b1dbd3bb9e1a2d332b 100644 --- a/vendor/twig/twig/lib/Twig/FunctionInterface.php +++ b/vendor/twig/twig/lib/Twig/FunctionInterface.php @@ -10,10 +10,12 @@ * file that was distributed with this source code. */ +use Twig\Node\Node; + /** * Represents a template function. * - * Use Twig_SimpleFunction instead. + * Use \Twig\TwigFunction instead. * * @author Arnaud Le Blanc <arnaud.lb@gmail.com> * @@ -32,7 +34,7 @@ interface Twig_FunctionInterface public function needsContext(); - public function getSafe(Twig_Node $filterArgs); + public function getSafe(Node $filterArgs); public function setArguments($arguments); diff --git a/vendor/twig/twig/lib/Twig/Lexer.php b/vendor/twig/twig/lib/Twig/Lexer.php index 85390b28c75c0963c31528c8da269ef086b30927..00d74cc47aabcd9430d4fa423a4805dbc302b9fb 100644 --- a/vendor/twig/twig/lib/Twig/Lexer.php +++ b/vendor/twig/twig/lib/Twig/Lexer.php @@ -1,424 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * (c) Armin Ronacher - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +use Twig\Lexer; -/** - * Lexes a template string. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class Twig_Lexer implements Twig_LexerInterface -{ - protected $tokens; - protected $code; - protected $cursor; - protected $lineno; - protected $end; - protected $state; - protected $states; - protected $brackets; - protected $env; - // to be renamed to $name in 2.0 (where it is private) - protected $filename; - protected $options; - protected $regexes; - protected $position; - protected $positions; - protected $currentVarBlockLine; +class_exists('Twig\Lexer'); - private $source; - - const STATE_DATA = 0; - const STATE_BLOCK = 1; - const STATE_VAR = 2; - const STATE_STRING = 3; - const STATE_INTERPOLATION = 4; - - const REGEX_NAME = '/[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*/A'; - const REGEX_NUMBER = '/[0-9]+(?:\.[0-9]+)?/A'; - const REGEX_STRING = '/"([^#"\\\\]*(?:\\\\.[^#"\\\\]*)*)"|\'([^\'\\\\]*(?:\\\\.[^\'\\\\]*)*)\'/As'; - const REGEX_DQ_STRING_DELIM = '/"/A'; - const REGEX_DQ_STRING_PART = '/[^#"\\\\]*(?:(?:\\\\.|#(?!\{))[^#"\\\\]*)*/As'; - const PUNCTUATION = '()[]{}?:.,|'; - - public function __construct(Twig_Environment $env, array $options = array()) - { - $this->env = $env; - - $this->options = array_merge(array( - 'tag_comment' => array('{#', '#}'), - 'tag_block' => array('{%', '%}'), - 'tag_variable' => array('{{', '}}'), - 'whitespace_trim' => '-', - 'interpolation' => array('#{', '}'), - ), $options); - - $this->regexes = array( - 'lex_var' => '/\s*'.preg_quote($this->options['whitespace_trim'].$this->options['tag_variable'][1], '/').'\s*|\s*'.preg_quote($this->options['tag_variable'][1], '/').'/A', - 'lex_block' => '/\s*(?:'.preg_quote($this->options['whitespace_trim'].$this->options['tag_block'][1], '/').'\s*|\s*'.preg_quote($this->options['tag_block'][1], '/').')\n?/A', - 'lex_raw_data' => '/('.preg_quote($this->options['tag_block'][0].$this->options['whitespace_trim'], '/').'|'.preg_quote($this->options['tag_block'][0], '/').')\s*(?:end%s)\s*(?:'.preg_quote($this->options['whitespace_trim'].$this->options['tag_block'][1], '/').'\s*|\s*'.preg_quote($this->options['tag_block'][1], '/').')/s', - 'operator' => $this->getOperatorRegex(), - 'lex_comment' => '/(?:'.preg_quote($this->options['whitespace_trim'], '/').preg_quote($this->options['tag_comment'][1], '/').'\s*|'.preg_quote($this->options['tag_comment'][1], '/').')\n?/s', - 'lex_block_raw' => '/\s*(raw|verbatim)\s*(?:'.preg_quote($this->options['whitespace_trim'].$this->options['tag_block'][1], '/').'\s*|\s*'.preg_quote($this->options['tag_block'][1], '/').')/As', - 'lex_block_line' => '/\s*line\s+(\d+)\s*'.preg_quote($this->options['tag_block'][1], '/').'/As', - 'lex_tokens_start' => '/('.preg_quote($this->options['tag_variable'][0], '/').'|'.preg_quote($this->options['tag_block'][0], '/').'|'.preg_quote($this->options['tag_comment'][0], '/').')('.preg_quote($this->options['whitespace_trim'], '/').')?/s', - 'interpolation_start' => '/'.preg_quote($this->options['interpolation'][0], '/').'\s*/A', - 'interpolation_end' => '/\s*'.preg_quote($this->options['interpolation'][1], '/').'/A', - ); - } - - public function tokenize($code, $name = null) - { - if (!$code instanceof Twig_Source) { - @trigger_error(sprintf('Passing a string as the $code argument of %s() is deprecated since version 1.27 and will be removed in 2.0. Pass a Twig_Source instance instead.', __METHOD__), E_USER_DEPRECATED); - $this->source = new Twig_Source($code, $name); - } else { - $this->source = $code; - } - - if (((int) ini_get('mbstring.func_overload')) & 2) { - @trigger_error('Support for having "mbstring.func_overload" different from 0 is deprecated version 1.29 and will be removed in 2.0.', E_USER_DEPRECATED); - } - - if (function_exists('mb_internal_encoding') && ((int) ini_get('mbstring.func_overload')) & 2) { - $mbEncoding = mb_internal_encoding(); - mb_internal_encoding('ASCII'); - } else { - $mbEncoding = null; - } - - $this->code = str_replace(array("\r\n", "\r"), "\n", $this->source->getCode()); - $this->filename = $this->source->getName(); - $this->cursor = 0; - $this->lineno = 1; - $this->end = strlen($this->code); - $this->tokens = array(); - $this->state = self::STATE_DATA; - $this->states = array(); - $this->brackets = array(); - $this->position = -1; - - // find all token starts in one go - preg_match_all($this->regexes['lex_tokens_start'], $this->code, $matches, PREG_OFFSET_CAPTURE); - $this->positions = $matches; - - while ($this->cursor < $this->end) { - // dispatch to the lexing functions depending - // on the current state - switch ($this->state) { - case self::STATE_DATA: - $this->lexData(); - break; - - case self::STATE_BLOCK: - $this->lexBlock(); - break; - - case self::STATE_VAR: - $this->lexVar(); - break; - - case self::STATE_STRING: - $this->lexString(); - break; - - case self::STATE_INTERPOLATION: - $this->lexInterpolation(); - break; - } - } - - $this->pushToken(Twig_Token::EOF_TYPE); - - if (!empty($this->brackets)) { - list($expect, $lineno) = array_pop($this->brackets); - throw new Twig_Error_Syntax(sprintf('Unclosed "%s".', $expect), $lineno, $this->source); - } - - if ($mbEncoding) { - mb_internal_encoding($mbEncoding); - } - - return new Twig_TokenStream($this->tokens, $this->source); - } - - protected function lexData() - { - // if no matches are left we return the rest of the template as simple text token - if ($this->position == count($this->positions[0]) - 1) { - $this->pushToken(Twig_Token::TEXT_TYPE, substr($this->code, $this->cursor)); - $this->cursor = $this->end; - - return; - } - - // Find the first token after the current cursor - $position = $this->positions[0][++$this->position]; - while ($position[1] < $this->cursor) { - if ($this->position == count($this->positions[0]) - 1) { - return; - } - $position = $this->positions[0][++$this->position]; - } - - // push the template text first - $text = $textContent = substr($this->code, $this->cursor, $position[1] - $this->cursor); - if (isset($this->positions[2][$this->position][0])) { - $text = rtrim($text); - } - $this->pushToken(Twig_Token::TEXT_TYPE, $text); - $this->moveCursor($textContent.$position[0]); - - switch ($this->positions[1][$this->position][0]) { - case $this->options['tag_comment'][0]: - $this->lexComment(); - break; - - case $this->options['tag_block'][0]: - // raw data? - if (preg_match($this->regexes['lex_block_raw'], $this->code, $match, null, $this->cursor)) { - $this->moveCursor($match[0]); - $this->lexRawData($match[1]); - // {% line \d+ %} - } elseif (preg_match($this->regexes['lex_block_line'], $this->code, $match, null, $this->cursor)) { - $this->moveCursor($match[0]); - $this->lineno = (int) $match[1]; - } else { - $this->pushToken(Twig_Token::BLOCK_START_TYPE); - $this->pushState(self::STATE_BLOCK); - $this->currentVarBlockLine = $this->lineno; - } - break; - - case $this->options['tag_variable'][0]: - $this->pushToken(Twig_Token::VAR_START_TYPE); - $this->pushState(self::STATE_VAR); - $this->currentVarBlockLine = $this->lineno; - break; - } - } - - protected function lexBlock() - { - if (empty($this->brackets) && preg_match($this->regexes['lex_block'], $this->code, $match, null, $this->cursor)) { - $this->pushToken(Twig_Token::BLOCK_END_TYPE); - $this->moveCursor($match[0]); - $this->popState(); - } else { - $this->lexExpression(); - } - } - - protected function lexVar() - { - if (empty($this->brackets) && preg_match($this->regexes['lex_var'], $this->code, $match, null, $this->cursor)) { - $this->pushToken(Twig_Token::VAR_END_TYPE); - $this->moveCursor($match[0]); - $this->popState(); - } else { - $this->lexExpression(); - } - } - - protected function lexExpression() - { - // whitespace - if (preg_match('/\s+/A', $this->code, $match, null, $this->cursor)) { - $this->moveCursor($match[0]); - - if ($this->cursor >= $this->end) { - throw new Twig_Error_Syntax(sprintf('Unclosed "%s".', $this->state === self::STATE_BLOCK ? 'block' : 'variable'), $this->currentVarBlockLine, $this->source); - } - } - - // operators - if (preg_match($this->regexes['operator'], $this->code, $match, null, $this->cursor)) { - $this->pushToken(Twig_Token::OPERATOR_TYPE, preg_replace('/\s+/', ' ', $match[0])); - $this->moveCursor($match[0]); - } - // names - elseif (preg_match(self::REGEX_NAME, $this->code, $match, null, $this->cursor)) { - $this->pushToken(Twig_Token::NAME_TYPE, $match[0]); - $this->moveCursor($match[0]); - } - // numbers - elseif (preg_match(self::REGEX_NUMBER, $this->code, $match, null, $this->cursor)) { - $number = (float) $match[0]; // floats - if (ctype_digit($match[0]) && $number <= PHP_INT_MAX) { - $number = (int) $match[0]; // integers lower than the maximum - } - $this->pushToken(Twig_Token::NUMBER_TYPE, $number); - $this->moveCursor($match[0]); - } - // punctuation - elseif (false !== strpos(self::PUNCTUATION, $this->code[$this->cursor])) { - // opening bracket - if (false !== strpos('([{', $this->code[$this->cursor])) { - $this->brackets[] = array($this->code[$this->cursor], $this->lineno); - } - // closing bracket - elseif (false !== strpos(')]}', $this->code[$this->cursor])) { - if (empty($this->brackets)) { - throw new Twig_Error_Syntax(sprintf('Unexpected "%s".', $this->code[$this->cursor]), $this->lineno, $this->source); - } - - list($expect, $lineno) = array_pop($this->brackets); - if ($this->code[$this->cursor] != strtr($expect, '([{', ')]}')) { - throw new Twig_Error_Syntax(sprintf('Unclosed "%s".', $expect), $lineno, $this->source); - } - } - - $this->pushToken(Twig_Token::PUNCTUATION_TYPE, $this->code[$this->cursor]); - ++$this->cursor; - } - // strings - elseif (preg_match(self::REGEX_STRING, $this->code, $match, null, $this->cursor)) { - $this->pushToken(Twig_Token::STRING_TYPE, stripcslashes(substr($match[0], 1, -1))); - $this->moveCursor($match[0]); - } - // opening double quoted string - elseif (preg_match(self::REGEX_DQ_STRING_DELIM, $this->code, $match, null, $this->cursor)) { - $this->brackets[] = array('"', $this->lineno); - $this->pushState(self::STATE_STRING); - $this->moveCursor($match[0]); - } - // unlexable - else { - throw new Twig_Error_Syntax(sprintf('Unexpected character "%s".', $this->code[$this->cursor]), $this->lineno, $this->source); - } - } - - protected function lexRawData($tag) - { - if ('raw' === $tag) { - @trigger_error(sprintf('Twig Tag "raw" is deprecated since version 1.21. Use "verbatim" instead in %s at line %d.', $this->filename, $this->lineno), E_USER_DEPRECATED); - } - - if (!preg_match(str_replace('%s', $tag, $this->regexes['lex_raw_data']), $this->code, $match, PREG_OFFSET_CAPTURE, $this->cursor)) { - throw new Twig_Error_Syntax(sprintf('Unexpected end of file: Unclosed "%s" block.', $tag), $this->lineno, $this->source); - } - - $text = substr($this->code, $this->cursor, $match[0][1] - $this->cursor); - $this->moveCursor($text.$match[0][0]); - - if (false !== strpos($match[1][0], $this->options['whitespace_trim'])) { - $text = rtrim($text); - } - - $this->pushToken(Twig_Token::TEXT_TYPE, $text); - } - - protected function lexComment() - { - if (!preg_match($this->regexes['lex_comment'], $this->code, $match, PREG_OFFSET_CAPTURE, $this->cursor)) { - throw new Twig_Error_Syntax('Unclosed comment.', $this->lineno, $this->source); - } - - $this->moveCursor(substr($this->code, $this->cursor, $match[0][1] - $this->cursor).$match[0][0]); - } - - protected function lexString() - { - if (preg_match($this->regexes['interpolation_start'], $this->code, $match, null, $this->cursor)) { - $this->brackets[] = array($this->options['interpolation'][0], $this->lineno); - $this->pushToken(Twig_Token::INTERPOLATION_START_TYPE); - $this->moveCursor($match[0]); - $this->pushState(self::STATE_INTERPOLATION); - } elseif (preg_match(self::REGEX_DQ_STRING_PART, $this->code, $match, null, $this->cursor) && strlen($match[0]) > 0) { - $this->pushToken(Twig_Token::STRING_TYPE, stripcslashes($match[0])); - $this->moveCursor($match[0]); - } elseif (preg_match(self::REGEX_DQ_STRING_DELIM, $this->code, $match, null, $this->cursor)) { - list($expect, $lineno) = array_pop($this->brackets); - if ($this->code[$this->cursor] != '"') { - throw new Twig_Error_Syntax(sprintf('Unclosed "%s".', $expect), $lineno, $this->source); - } - - $this->popState(); - ++$this->cursor; - } - } - - protected function lexInterpolation() - { - $bracket = end($this->brackets); - if ($this->options['interpolation'][0] === $bracket[0] && preg_match($this->regexes['interpolation_end'], $this->code, $match, null, $this->cursor)) { - array_pop($this->brackets); - $this->pushToken(Twig_Token::INTERPOLATION_END_TYPE); - $this->moveCursor($match[0]); - $this->popState(); - } else { - $this->lexExpression(); - } - } - - protected function pushToken($type, $value = '') - { - // do not push empty text tokens - if (Twig_Token::TEXT_TYPE === $type && '' === $value) { - return; - } - - $this->tokens[] = new Twig_Token($type, $value, $this->lineno); - } - - protected function moveCursor($text) +if (\false) { + class Twig_Lexer extends Lexer { - $this->cursor += strlen($text); - $this->lineno += substr_count($text, "\n"); - } - - protected function getOperatorRegex() - { - $operators = array_merge( - array('='), - array_keys($this->env->getUnaryOperators()), - array_keys($this->env->getBinaryOperators()) - ); - - $operators = array_combine($operators, array_map('strlen', $operators)); - arsort($operators); - - $regex = array(); - foreach ($operators as $operator => $length) { - // an operator that ends with a character must be followed by - // a whitespace or a parenthesis - if (ctype_alpha($operator[$length - 1])) { - $r = preg_quote($operator, '/').'(?=[\s()])'; - } else { - $r = preg_quote($operator, '/'); - } - - // an operator with a space can be any amount of whitespaces - $r = preg_replace('/\s+/', '\s+', $r); - - $regex[] = $r; - } - - return '/'.implode('|', $regex).'/A'; - } - - protected function pushState($state) - { - $this->states[] = $this->state; - $this->state = $state; - } - - protected function popState() - { - if (0 === count($this->states)) { - throw new Exception('Cannot pop state without a previous state.'); - } - - $this->state = array_pop($this->states); } } - -class_alias('Twig_Lexer', 'Twig\Lexer', false); diff --git a/vendor/twig/twig/lib/Twig/LexerInterface.php b/vendor/twig/twig/lib/Twig/LexerInterface.php index c10bbfec4a02e0d70610fd51265938e020dddb30..cc04f68413e208d867ab3d64d1c5043e12d21260 100644 --- a/vendor/twig/twig/lib/Twig/LexerInterface.php +++ b/vendor/twig/twig/lib/Twig/LexerInterface.php @@ -9,6 +9,10 @@ * file that was distributed with this source code. */ +use Twig\Error\SyntaxError; +use Twig\Source; +use Twig\TokenStream; + /** * Interface implemented by lexer classes. * @@ -21,12 +25,12 @@ interface Twig_LexerInterface /** * Tokenizes a source code. * - * @param string|Twig_Source $code The source code - * @param string $name A unique identifier for the source code + * @param string|Source $code The source code + * @param string $name A unique identifier for the source code * - * @return Twig_TokenStream + * @return TokenStream * - * @throws Twig_Error_Syntax When the code is syntactically wrong + * @throws SyntaxError When the code is syntactically wrong */ public function tokenize($code, $name = null); } diff --git a/vendor/twig/twig/lib/Twig/Loader/Array.php b/vendor/twig/twig/lib/Twig/Loader/Array.php index 0aac76900fc5bcc40094dee6b1515d642637fafa..13f915c95f4f4ca733ef172a5cc16ba3d558a04e 100644 --- a/vendor/twig/twig/lib/Twig/Loader/Array.php +++ b/vendor/twig/twig/lib/Twig/Loader/Array.php @@ -1,97 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +use Twig\Loader\ArrayLoader; -/** - * Loads a template from an array. - * - * When using this loader with a cache mechanism, you should know that a new cache - * key is generated each time a template content "changes" (the cache key being the - * source code of the template). If you don't want to see your cache grows out of - * control, you need to take care of clearing the old cache file by yourself. - * - * This loader should only be used for unit testing. - * - * @final - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class Twig_Loader_Array implements Twig_LoaderInterface, Twig_ExistsLoaderInterface, Twig_SourceContextLoaderInterface -{ - protected $templates = array(); +class_exists('Twig\Loader\ArrayLoader'); - /** - * @param array $templates An array of templates (keys are the names, and values are the source code) - */ - public function __construct(array $templates = array()) +if (\false) { + class Twig_Loader_Array extends ArrayLoader { - $this->templates = $templates; - } - - /** - * Adds or overrides a template. - * - * @param string $name The template name - * @param string $template The template source - */ - public function setTemplate($name, $template) - { - $this->templates[(string) $name] = $template; - } - - public function getSource($name) - { - @trigger_error(sprintf('Calling "getSource" on "%s" is deprecated since 1.27. Use getSourceContext() instead.', get_class($this)), E_USER_DEPRECATED); - - $name = (string) $name; - if (!isset($this->templates[$name])) { - throw new Twig_Error_Loader(sprintf('Template "%s" is not defined.', $name)); - } - - return $this->templates[$name]; - } - - public function getSourceContext($name) - { - $name = (string) $name; - if (!isset($this->templates[$name])) { - throw new Twig_Error_Loader(sprintf('Template "%s" is not defined.', $name)); - } - - return new Twig_Source($this->templates[$name], $name); - } - - public function exists($name) - { - return isset($this->templates[(string) $name]); - } - - public function getCacheKey($name) - { - $name = (string) $name; - if (!isset($this->templates[$name])) { - throw new Twig_Error_Loader(sprintf('Template "%s" is not defined.', $name)); - } - - return $name.':'.$this->templates[$name]; - } - - public function isFresh($name, $time) - { - $name = (string) $name; - if (!isset($this->templates[$name])) { - throw new Twig_Error_Loader(sprintf('Template "%s" is not defined.', $name)); - } - - return true; } } - -class_alias('Twig_Loader_Array', 'Twig\Loader\ArrayLoader', false); diff --git a/vendor/twig/twig/lib/Twig/Loader/Chain.php b/vendor/twig/twig/lib/Twig/Loader/Chain.php index 59a337969e5995a2ac75e65b4f4d33722bc80e63..885b37a7fe82d5b9cc950593539b24f8eb670261 100644 --- a/vendor/twig/twig/lib/Twig/Loader/Chain.php +++ b/vendor/twig/twig/lib/Twig/Loader/Chain.php @@ -1,151 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +use Twig\Loader\ChainLoader; -/** - * Loads templates from other loaders. - * - * @final - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class Twig_Loader_Chain implements Twig_LoaderInterface, Twig_ExistsLoaderInterface, Twig_SourceContextLoaderInterface -{ - private $hasSourceCache = array(); - protected $loaders = array(); +class_exists('Twig\Loader\ChainLoader'); - /** - * @param Twig_LoaderInterface[] $loaders - */ - public function __construct(array $loaders = array()) +if (\false) { + class Twig_Loader_Chain extends ChainLoader { - foreach ($loaders as $loader) { - $this->addLoader($loader); - } - } - - public function addLoader(Twig_LoaderInterface $loader) - { - $this->loaders[] = $loader; - $this->hasSourceCache = array(); - } - - public function getSource($name) - { - @trigger_error(sprintf('Calling "getSource" on "%s" is deprecated since 1.27. Use getSourceContext() instead.', get_class($this)), E_USER_DEPRECATED); - - $exceptions = array(); - foreach ($this->loaders as $loader) { - if ($loader instanceof Twig_ExistsLoaderInterface && !$loader->exists($name)) { - continue; - } - - try { - return $loader->getSource($name); - } catch (Twig_Error_Loader $e) { - $exceptions[] = $e->getMessage(); - } - } - - throw new Twig_Error_Loader(sprintf('Template "%s" is not defined%s.', $name, $exceptions ? ' ('.implode(', ', $exceptions).')' : '')); - } - - public function getSourceContext($name) - { - $exceptions = array(); - foreach ($this->loaders as $loader) { - if ($loader instanceof Twig_ExistsLoaderInterface && !$loader->exists($name)) { - continue; - } - - try { - if ($loader instanceof Twig_SourceContextLoaderInterface) { - return $loader->getSourceContext($name); - } - - return new Twig_Source($loader->getSource($name), $name); - } catch (Twig_Error_Loader $e) { - $exceptions[] = $e->getMessage(); - } - } - - throw new Twig_Error_Loader(sprintf('Template "%s" is not defined%s.', $name, $exceptions ? ' ('.implode(', ', $exceptions).')' : '')); - } - - public function exists($name) - { - $name = (string) $name; - - if (isset($this->hasSourceCache[$name])) { - return $this->hasSourceCache[$name]; - } - - foreach ($this->loaders as $loader) { - if ($loader instanceof Twig_ExistsLoaderInterface) { - if ($loader->exists($name)) { - return $this->hasSourceCache[$name] = true; - } - - continue; - } - - try { - if ($loader instanceof Twig_SourceContextLoaderInterface) { - $loader->getSourceContext($name); - } else { - $loader->getSource($name); - } - - return $this->hasSourceCache[$name] = true; - } catch (Twig_Error_Loader $e) { - } - } - - return $this->hasSourceCache[$name] = false; - } - - public function getCacheKey($name) - { - $exceptions = array(); - foreach ($this->loaders as $loader) { - if ($loader instanceof Twig_ExistsLoaderInterface && !$loader->exists($name)) { - continue; - } - - try { - return $loader->getCacheKey($name); - } catch (Twig_Error_Loader $e) { - $exceptions[] = get_class($loader).': '.$e->getMessage(); - } - } - - throw new Twig_Error_Loader(sprintf('Template "%s" is not defined%s.', $name, $exceptions ? ' ('.implode(', ', $exceptions).')' : '')); - } - - public function isFresh($name, $time) - { - $exceptions = array(); - foreach ($this->loaders as $loader) { - if ($loader instanceof Twig_ExistsLoaderInterface && !$loader->exists($name)) { - continue; - } - - try { - return $loader->isFresh($name, $time); - } catch (Twig_Error_Loader $e) { - $exceptions[] = get_class($loader).': '.$e->getMessage(); - } - } - - throw new Twig_Error_Loader(sprintf('Template "%s" is not defined%s.', $name, $exceptions ? ' ('.implode(', ', $exceptions).')' : '')); } } - -class_alias('Twig_Loader_Chain', 'Twig\Loader\ChainLoader', false); diff --git a/vendor/twig/twig/lib/Twig/Loader/Filesystem.php b/vendor/twig/twig/lib/Twig/Loader/Filesystem.php index 1275044f8bc1d24c11094e752c165e778a76060d..c3eae7d840cbed5627d6e68bf238c1646d3a841b 100644 --- a/vendor/twig/twig/lib/Twig/Loader/Filesystem.php +++ b/vendor/twig/twig/lib/Twig/Loader/Filesystem.php @@ -1,290 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +use Twig\Loader\FilesystemLoader; -/** - * Loads template from the filesystem. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class Twig_Loader_Filesystem implements Twig_LoaderInterface, Twig_ExistsLoaderInterface, Twig_SourceContextLoaderInterface -{ - /** Identifier of the main namespace. */ - const MAIN_NAMESPACE = '__main__'; +class_exists('Twig\Loader\FilesystemLoader'); - protected $paths = array(); - protected $cache = array(); - protected $errorCache = array(); - - private $rootPath; - - /** - * @param string|array $paths A path or an array of paths where to look for templates - * @param string|null $rootPath The root path common to all relative paths (null for getcwd()) - */ - public function __construct($paths = array(), $rootPath = null) - { - $this->rootPath = (null === $rootPath ? getcwd() : $rootPath).DIRECTORY_SEPARATOR; - if (false !== $realPath = realpath($rootPath)) { - $this->rootPath = $realPath.DIRECTORY_SEPARATOR; - } - - if ($paths) { - $this->setPaths($paths); - } - } - - /** - * Returns the paths to the templates. - * - * @param string $namespace A path namespace - * - * @return array The array of paths where to look for templates - */ - public function getPaths($namespace = self::MAIN_NAMESPACE) - { - return isset($this->paths[$namespace]) ? $this->paths[$namespace] : array(); - } - - /** - * Returns the path namespaces. - * - * The main namespace is always defined. - * - * @return array The array of defined namespaces - */ - public function getNamespaces() - { - return array_keys($this->paths); - } - - /** - * Sets the paths where templates are stored. - * - * @param string|array $paths A path or an array of paths where to look for templates - * @param string $namespace A path namespace - */ - public function setPaths($paths, $namespace = self::MAIN_NAMESPACE) - { - if (!is_array($paths)) { - $paths = array($paths); - } - - $this->paths[$namespace] = array(); - foreach ($paths as $path) { - $this->addPath($path, $namespace); - } - } - - /** - * Adds a path where templates are stored. - * - * @param string $path A path where to look for templates - * @param string $namespace A path namespace - * - * @throws Twig_Error_Loader - */ - public function addPath($path, $namespace = self::MAIN_NAMESPACE) - { - // invalidate the cache - $this->cache = $this->errorCache = array(); - - $checkPath = $this->isAbsolutePath($path) ? $path : $this->rootPath.$path; - if (!is_dir($checkPath)) { - throw new Twig_Error_Loader(sprintf('The "%s" directory does not exist ("%s").', $path, $checkPath)); - } - - $this->paths[$namespace][] = rtrim($path, '/\\'); - } - - /** - * Prepends a path where templates are stored. - * - * @param string $path A path where to look for templates - * @param string $namespace A path namespace - * - * @throws Twig_Error_Loader - */ - public function prependPath($path, $namespace = self::MAIN_NAMESPACE) - { - // invalidate the cache - $this->cache = $this->errorCache = array(); - - $checkPath = $this->isAbsolutePath($path) ? $path : $this->rootPath.$path; - if (!is_dir($checkPath)) { - throw new Twig_Error_Loader(sprintf('The "%s" directory does not exist ("%s").', $path, $checkPath)); - } - - $path = rtrim($path, '/\\'); - - if (!isset($this->paths[$namespace])) { - $this->paths[$namespace][] = $path; - } else { - array_unshift($this->paths[$namespace], $path); - } - } - - public function getSource($name) - { - @trigger_error(sprintf('Calling "getSource" on "%s" is deprecated since 1.27. Use getSourceContext() instead.', get_class($this)), E_USER_DEPRECATED); - - return file_get_contents($this->findTemplate($name)); - } - - public function getSourceContext($name) - { - $path = $this->findTemplate($name); - - return new Twig_Source(file_get_contents($path), $name, $path); - } - - public function getCacheKey($name) - { - $path = $this->findTemplate($name); - $len = strlen($this->rootPath); - if (0 === strncmp($this->rootPath, $path, $len)) { - return substr($path, $len); - } - - return $path; - } - - public function exists($name) - { - $name = $this->normalizeName($name); - - if (isset($this->cache[$name])) { - return true; - } - - try { - return false !== $this->findTemplate($name, false); - } catch (Twig_Error_Loader $exception) { - @trigger_error(sprintf('In %s::findTemplate(), you must accept a second argument that when set to "false" returns "false" instead of throwing an exception. Not supporting this argument is deprecated since version 1.27.', get_class($this)), E_USER_DEPRECATED); - - return false; - } - } - - public function isFresh($name, $time) - { - return filemtime($this->findTemplate($name)) <= $time; - } - - protected function findTemplate($name) - { - $throw = func_num_args() > 1 ? func_get_arg(1) : true; - $name = $this->normalizeName($name); - - if (isset($this->cache[$name])) { - return $this->cache[$name]; - } - - if (isset($this->errorCache[$name])) { - if (!$throw) { - return false; - } - - throw new Twig_Error_Loader($this->errorCache[$name]); - } - - $this->validateName($name); - - list($namespace, $shortname) = $this->parseName($name); - - if (!isset($this->paths[$namespace])) { - $this->errorCache[$name] = sprintf('There are no registered paths for namespace "%s".', $namespace); - - if (!$throw) { - return false; - } - - throw new Twig_Error_Loader($this->errorCache[$name]); - } - - foreach ($this->paths[$namespace] as $path) { - if (!$this->isAbsolutePath($path)) { - $path = $this->rootPath.'/'.$path; - } - - if (is_file($path.'/'.$shortname)) { - if (false !== $realpath = realpath($path.'/'.$shortname)) { - return $this->cache[$name] = $realpath; - } - - return $this->cache[$name] = $path.'/'.$shortname; - } - } - - $this->errorCache[$name] = sprintf('Unable to find template "%s" (looked into: %s).', $name, implode(', ', $this->paths[$namespace])); - - if (!$throw) { - return false; - } - - throw new Twig_Error_Loader($this->errorCache[$name]); - } - - protected function parseName($name, $default = self::MAIN_NAMESPACE) - { - if (isset($name[0]) && '@' == $name[0]) { - if (false === $pos = strpos($name, '/')) { - throw new Twig_Error_Loader(sprintf('Malformed namespaced template name "%s" (expecting "@namespace/template_name").', $name)); - } - - $namespace = substr($name, 1, $pos - 1); - $shortname = substr($name, $pos + 1); - - return array($namespace, $shortname); - } - - return array($default, $name); - } - - protected function normalizeName($name) - { - return preg_replace('#/{2,}#', '/', str_replace('\\', '/', (string) $name)); - } - - protected function validateName($name) - { - if (false !== strpos($name, "\0")) { - throw new Twig_Error_Loader('A template name cannot contain NUL bytes.'); - } - - $name = ltrim($name, '/'); - $parts = explode('/', $name); - $level = 0; - foreach ($parts as $part) { - if ('..' === $part) { - --$level; - } elseif ('.' !== $part) { - ++$level; - } - - if ($level < 0) { - throw new Twig_Error_Loader(sprintf('Looks like you try to load a template outside configured directories (%s).', $name)); - } - } - } - - private function isAbsolutePath($file) +if (\false) { + class Twig_Loader_Filesystem extends FilesystemLoader { - return strspn($file, '/\\', 0, 1) - || (strlen($file) > 3 && ctype_alpha($file[0]) - && substr($file, 1, 1) === ':' - && strspn($file, '/\\', 2, 1) - ) - || null !== parse_url($file, PHP_URL_SCHEME) - ; } } - -class_alias('Twig_Loader_Filesystem', 'Twig\Loader\FilesystemLoader', false); diff --git a/vendor/twig/twig/lib/Twig/Loader/String.php b/vendor/twig/twig/lib/Twig/Loader/String.php index 950bd35b0f09b8f916d121cb508cce97c5b696bd..348af0c1d5766ffd9ad5ad3d021c2cd66002ddf6 100644 --- a/vendor/twig/twig/lib/Twig/Loader/String.php +++ b/vendor/twig/twig/lib/Twig/Loader/String.php @@ -9,7 +9,12 @@ * file that was distributed with this source code. */ -@trigger_error('The Twig_Loader_String class is deprecated since version 1.18.1 and will be removed in 2.0. Use Twig_Loader_Array instead or Twig_Environment::createTemplate().', E_USER_DEPRECATED); +use Twig\Loader\ExistsLoaderInterface; +use Twig\Loader\LoaderInterface; +use Twig\Loader\SourceContextLoaderInterface; +use Twig\Source; + +@trigger_error('The Twig_Loader_String class is deprecated since version 1.18.1 and will be removed in 2.0. Use "Twig\Loader\ArrayLoader" instead or "Twig\Environment::createTemplate()".', E_USER_DEPRECATED); /** * Loads a template from a string. @@ -27,18 +32,18 @@ * * @author Fabien Potencier <fabien@symfony.com> */ -class Twig_Loader_String implements Twig_LoaderInterface, Twig_ExistsLoaderInterface, Twig_SourceContextLoaderInterface +class Twig_Loader_String implements LoaderInterface, ExistsLoaderInterface, SourceContextLoaderInterface { public function getSource($name) { - @trigger_error(sprintf('Calling "getSource" on "%s" is deprecated since 1.27. Use getSourceContext() instead.', get_class($this)), E_USER_DEPRECATED); + @trigger_error(sprintf('Calling "getSource" on "%s" is deprecated since 1.27. Use getSourceContext() instead.', \get_class($this)), E_USER_DEPRECATED); return $name; } public function getSourceContext($name) { - return new Twig_Source($name, $name); + return new Source($name, $name); } public function exists($name) diff --git a/vendor/twig/twig/lib/Twig/LoaderInterface.php b/vendor/twig/twig/lib/Twig/LoaderInterface.php index 459a70abbf6a4cdfa46304b7862f98b5a2eb1554..db515bbdf4a2c2db2ea2c088d5dafe0a3fbdcc95 100644 --- a/vendor/twig/twig/lib/Twig/LoaderInterface.php +++ b/vendor/twig/twig/lib/Twig/LoaderInterface.php @@ -1,57 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +use Twig\Loader\LoaderInterface; -/** - * Interface all loaders must implement. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -interface Twig_LoaderInterface -{ - /** - * Gets the source code of a template, given its name. - * - * @param string $name The name of the template to load - * - * @return string The template source code - * - * @throws Twig_Error_Loader When $name is not found - * - * @deprecated since 1.27 (to be removed in 2.0), implement Twig_SourceContextLoaderInterface - */ - public function getSource($name); +class_exists('Twig\Loader\LoaderInterface'); - /** - * Gets the cache key to use for the cache for a given template name. - * - * @param string $name The name of the template to load - * - * @return string The cache key - * - * @throws Twig_Error_Loader When $name is not found - */ - public function getCacheKey($name); - - /** - * Returns true if the template is still fresh. - * - * @param string $name The template name - * @param int $time Timestamp of the last modification time of the - * cached template - * - * @return bool true if the template is fresh, false otherwise - * - * @throws Twig_Error_Loader When $name is not found - */ - public function isFresh($name, $time); +if (\false) { + class Twig_LoaderInterface extends LoaderInterface + { + } } - -class_alias('Twig_LoaderInterface', 'Twig\Loader\LoaderInterface', false); diff --git a/vendor/twig/twig/lib/Twig/Markup.php b/vendor/twig/twig/lib/Twig/Markup.php index 8591d1f9344f0dbabb61b2616dbb3fc8dc4527a5..9a3804665445768a43008620516d77de94a1af33 100644 --- a/vendor/twig/twig/lib/Twig/Markup.php +++ b/vendor/twig/twig/lib/Twig/Markup.php @@ -1,39 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +use Twig\Markup; -/** - * Marks a content as safe. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class Twig_Markup implements Countable -{ - protected $content; - protected $charset; +class_exists('Twig\Markup'); - public function __construct($content, $charset) +if (\false) { + class Twig_Markup extends Markup { - $this->content = (string) $content; - $this->charset = $charset; - } - - public function __toString() - { - return $this->content; - } - - public function count() - { - return function_exists('mb_get_info') ? mb_strlen($this->content, $this->charset) : strlen($this->content); } } - -class_alias('Twig_Markup', 'Twig\Markup', false); diff --git a/vendor/twig/twig/lib/Twig/Node.php b/vendor/twig/twig/lib/Twig/Node.php index 89ada14492d7d2a029926f49b2f3ee3ad7ef1c86..78cc271198440e026420b704a627549b38b323db 100644 --- a/vendor/twig/twig/lib/Twig/Node.php +++ b/vendor/twig/twig/lib/Twig/Node.php @@ -1,256 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * (c) Armin Ronacher - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +use Twig\Node\Node; -/** - * Represents a node in the AST. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class Twig_Node implements Twig_NodeInterface -{ - protected $nodes; - protected $attributes; - protected $lineno; - protected $tag; +class_exists('Twig\Node\Node'); - private $name; - - /** - * Constructor. - * - * The nodes are automatically made available as properties ($this->node). - * The attributes are automatically made available as array items ($this['name']). - * - * @param array $nodes An array of named nodes - * @param array $attributes An array of attributes (should not be nodes) - * @param int $lineno The line number - * @param string $tag The tag name associated with the Node - */ - public function __construct(array $nodes = array(), array $attributes = array(), $lineno = 0, $tag = null) - { - foreach ($nodes as $name => $node) { - if (!$node instanceof Twig_NodeInterface) { - @trigger_error(sprintf('Using "%s" for the value of node "%s" of "%s" is deprecated since version 1.25 and will be removed in 2.0.', is_object($node) ? get_class($node) : null === $node ? 'null' : gettype($node), $name, get_class($this)), E_USER_DEPRECATED); - } - } - $this->nodes = $nodes; - $this->attributes = $attributes; - $this->lineno = $lineno; - $this->tag = $tag; - } - - public function __toString() - { - $attributes = array(); - foreach ($this->attributes as $name => $value) { - $attributes[] = sprintf('%s: %s', $name, str_replace("\n", '', var_export($value, true))); - } - - $repr = array(get_class($this).'('.implode(', ', $attributes)); - - if (count($this->nodes)) { - foreach ($this->nodes as $name => $node) { - $len = strlen($name) + 4; - $noderepr = array(); - foreach (explode("\n", (string) $node) as $line) { - $noderepr[] = str_repeat(' ', $len).$line; - } - - $repr[] = sprintf(' %s: %s', $name, ltrim(implode("\n", $noderepr))); - } - - $repr[] = ')'; - } else { - $repr[0] .= ')'; - } - - return implode("\n", $repr); - } - - /** - * @deprecated since 1.16.1 (to be removed in 2.0) - */ - public function toXml($asDom = false) - { - @trigger_error(sprintf('%s is deprecated since version 1.16.1 and will be removed in 2.0.', __METHOD__), E_USER_DEPRECATED); - - $dom = new DOMDocument('1.0', 'UTF-8'); - $dom->formatOutput = true; - $dom->appendChild($xml = $dom->createElement('twig')); - - $xml->appendChild($node = $dom->createElement('node')); - $node->setAttribute('class', get_class($this)); - - foreach ($this->attributes as $name => $value) { - $node->appendChild($attribute = $dom->createElement('attribute')); - $attribute->setAttribute('name', $name); - $attribute->appendChild($dom->createTextNode($value)); - } - - foreach ($this->nodes as $name => $n) { - if (null === $n) { - continue; - } - - $child = $n->toXml(true)->getElementsByTagName('node')->item(0); - $child = $dom->importNode($child, true); - $child->setAttribute('name', $name); - - $node->appendChild($child); - } - - return $asDom ? $dom : $dom->saveXML(); - } - - public function compile(Twig_Compiler $compiler) - { - foreach ($this->nodes as $node) { - $node->compile($compiler); - } - } - - public function getTemplateLine() - { - return $this->lineno; - } - - /** - * @deprecated since 1.27 (to be removed in 2.0) - */ - public function getLine() - { - @trigger_error('The '.__METHOD__.' method is deprecated since version 1.27 and will be removed in 2.0. Use getTemplateLine() instead.', E_USER_DEPRECATED); - - return $this->lineno; - } - - public function getNodeTag() - { - return $this->tag; - } - - /** - * @return bool - */ - public function hasAttribute($name) - { - return array_key_exists($name, $this->attributes); - } - - /** - * @return mixed - */ - public function getAttribute($name) - { - if (!array_key_exists($name, $this->attributes)) { - throw new LogicException(sprintf('Attribute "%s" does not exist for Node "%s".', $name, get_class($this))); - } - - return $this->attributes[$name]; - } - - /** - * @param string $name - * @param mixed $value - */ - public function setAttribute($name, $value) - { - $this->attributes[$name] = $value; - } - - public function removeAttribute($name) - { - unset($this->attributes[$name]); - } - - /** - * @return bool - */ - public function hasNode($name) - { - return array_key_exists($name, $this->nodes); - } - - /** - * @return Twig_Node - */ - public function getNode($name) - { - if (!array_key_exists($name, $this->nodes)) { - throw new LogicException(sprintf('Node "%s" does not exist for Node "%s".', $name, get_class($this))); - } - - return $this->nodes[$name]; - } - - public function setNode($name, $node = null) - { - if (!$node instanceof Twig_NodeInterface) { - @trigger_error(sprintf('Using "%s" for the value of node "%s" of "%s" is deprecated since version 1.25 and will be removed in 2.0.', is_object($node) ? get_class($node) : null === $node ? 'null' : gettype($node), $name, get_class($this)), E_USER_DEPRECATED); - } - - $this->nodes[$name] = $node; - } - - public function removeNode($name) - { - unset($this->nodes[$name]); - } - - public function count() - { - return count($this->nodes); - } - - public function getIterator() - { - return new ArrayIterator($this->nodes); - } - - public function setTemplateName($name) - { - $this->name = $name; - foreach ($this->nodes as $node) { - if (null !== $node) { - $node->setTemplateName($name); - } - } - } - - public function getTemplateName() - { - return $this->name; - } - - /** - * @deprecated since 1.27 (to be removed in 2.0) - */ - public function setFilename($name) - { - @trigger_error('The '.__METHOD__.' method is deprecated since version 1.27 and will be removed in 2.0. Use setTemplateName() instead.', E_USER_DEPRECATED); - - $this->setTemplateName($name); - } - - /** - * @deprecated since 1.27 (to be removed in 2.0) - */ - public function getFilename() +if (\false) { + class Twig_Node extends Node { - @trigger_error('The '.__METHOD__.' method is deprecated since version 1.27 and will be removed in 2.0. Use getTemplateName() instead.', E_USER_DEPRECATED); - - return $this->name; } } - -class_alias('Twig_Node', 'Twig\Node\Node', false); -class_exists('Twig_Compiler'); diff --git a/vendor/twig/twig/lib/Twig/Node/AutoEscape.php b/vendor/twig/twig/lib/Twig/Node/AutoEscape.php index 17e4e3813f08c2b4dda5ab7b0ca2f89cfb7b1a5d..7d308fff5ce5799ec896e8be56f83f027a6ef445 100644 --- a/vendor/twig/twig/lib/Twig/Node/AutoEscape.php +++ b/vendor/twig/twig/lib/Twig/Node/AutoEscape.php @@ -1,36 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +use Twig\Node\AutoEscapeNode; -/** - * Represents an autoescape node. - * - * The value is the escaping strategy (can be html, js, ...) - * - * The true value is equivalent to html. - * - * If autoescaping is disabled, then the value is false. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class Twig_Node_AutoEscape extends Twig_Node -{ - public function __construct($value, Twig_NodeInterface $body, $lineno, $tag = 'autoescape') - { - parent::__construct(array('body' => $body), array('value' => $value), $lineno, $tag); - } +class_exists('Twig\Node\AutoEscapeNode'); - public function compile(Twig_Compiler $compiler) +if (\false) { + class Twig_Node_AutoEscape extends AutoEscapeNode { - $compiler->subcompile($this->getNode('body')); } } - -class_alias('Twig_Node_AutoEscape', 'Twig\Node\AutoEscapeNode', false); diff --git a/vendor/twig/twig/lib/Twig/Node/Block.php b/vendor/twig/twig/lib/Twig/Node/Block.php index 91752ad2773f5ee1fdf56914181e372ef9e04b7b..33cd088f3bd2e17269fcc298cb7083a4b79ff1c9 100644 --- a/vendor/twig/twig/lib/Twig/Node/Block.php +++ b/vendor/twig/twig/lib/Twig/Node/Block.php @@ -1,41 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * (c) Armin Ronacher - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +use Twig\Node\BlockNode; -/** - * Represents a block node. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class Twig_Node_Block extends Twig_Node -{ - public function __construct($name, Twig_NodeInterface $body, $lineno, $tag = null) - { - parent::__construct(array('body' => $body), array('name' => $name), $lineno, $tag); - } +class_exists('Twig\Node\BlockNode'); - public function compile(Twig_Compiler $compiler) +if (\false) { + class Twig_Node_Block extends BlockNode { - $compiler - ->addDebugInfo($this) - ->write(sprintf("public function block_%s(\$context, array \$blocks = array())\n", $this->getAttribute('name')), "{\n") - ->indent() - ; - - $compiler - ->subcompile($this->getNode('body')) - ->outdent() - ->write("}\n\n") - ; } } - -class_alias('Twig_Node_Block', 'Twig\Node\BlockNode', false); diff --git a/vendor/twig/twig/lib/Twig/Node/BlockReference.php b/vendor/twig/twig/lib/Twig/Node/BlockReference.php index 92a9f398a47b817dd720e3efdf43de953f994ad6..55d2d00b2b7087cb60daf32d8f17960d8bbae914 100644 --- a/vendor/twig/twig/lib/Twig/Node/BlockReference.php +++ b/vendor/twig/twig/lib/Twig/Node/BlockReference.php @@ -1,34 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * (c) Armin Ronacher - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +use Twig\Node\BlockReferenceNode; -/** - * Represents a block call node. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class Twig_Node_BlockReference extends Twig_Node implements Twig_NodeOutputInterface -{ - public function __construct($name, $lineno, $tag = null) - { - parent::__construct(array(), array('name' => $name), $lineno, $tag); - } +class_exists('Twig\Node\BlockReferenceNode'); - public function compile(Twig_Compiler $compiler) +if (\false) { + class Twig_Node_BlockReference extends BlockReferenceNode { - $compiler - ->addDebugInfo($this) - ->write(sprintf("\$this->displayBlock('%s', \$context, \$blocks);\n", $this->getAttribute('name'))) - ; } } - -class_alias('Twig_Node_BlockReference', 'Twig\Node\BlockReferenceNode', false); diff --git a/vendor/twig/twig/lib/Twig/Node/Body.php b/vendor/twig/twig/lib/Twig/Node/Body.php index 07dfef8b5e74fd17bbbcf1bee428964ef3c35042..0874364d19eaaf5d69d5c9f8f360b7515170de71 100644 --- a/vendor/twig/twig/lib/Twig/Node/Body.php +++ b/vendor/twig/twig/lib/Twig/Node/Body.php @@ -1,21 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +use Twig\Node\BodyNode; -/** - * Represents a body node. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class Twig_Node_Body extends Twig_Node -{ -} +class_exists('Twig\Node\BodyNode'); -class_alias('Twig_Node_Body', 'Twig\Node\BodyNode', false); +if (\false) { + class Twig_Node_Body extends BodyNode + { + } +} diff --git a/vendor/twig/twig/lib/Twig/Node/CheckSecurity.php b/vendor/twig/twig/lib/Twig/Node/CheckSecurity.php index 7258acb6a2f75fd2e76346019da4256f7afa47a9..e42ce689a807d0854b10aacf746f38bc98b357aa 100644 --- a/vendor/twig/twig/lib/Twig/Node/CheckSecurity.php +++ b/vendor/twig/twig/lib/Twig/Node/CheckSecurity.php @@ -1,80 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +use Twig\Node\CheckSecurityNode; -/** - * @author Fabien Potencier <fabien@symfony.com> - */ -class Twig_Node_CheckSecurity extends Twig_Node -{ - protected $usedFilters; - protected $usedTags; - protected $usedFunctions; +class_exists('Twig\Node\CheckSecurityNode'); - public function __construct(array $usedFilters, array $usedTags, array $usedFunctions) +if (\false) { + class Twig_Node_CheckSecurity extends CheckSecurityNode { - $this->usedFilters = $usedFilters; - $this->usedTags = $usedTags; - $this->usedFunctions = $usedFunctions; - - parent::__construct(); - } - - public function compile(Twig_Compiler $compiler) - { - $tags = $filters = $functions = array(); - foreach (array('tags', 'filters', 'functions') as $type) { - foreach ($this->{'used'.ucfirst($type)} as $name => $node) { - if ($node instanceof Twig_Node) { - ${$type}[$name] = $node->getTemplateLine(); - } else { - ${$type}[$node] = null; - } - } - } - - $compiler - ->write('$tags = ')->repr(array_filter($tags))->raw(";\n") - ->write('$filters = ')->repr(array_filter($filters))->raw(";\n") - ->write('$functions = ')->repr(array_filter($functions))->raw(";\n\n") - ->write("try {\n") - ->indent() - ->write("\$this->env->getExtension('Twig_Extension_Sandbox')->checkSecurity(\n") - ->indent() - ->write(!$tags ? "array(),\n" : "array('".implode("', '", array_keys($tags))."'),\n") - ->write(!$filters ? "array(),\n" : "array('".implode("', '", array_keys($filters))."'),\n") - ->write(!$functions ? "array()\n" : "array('".implode("', '", array_keys($functions))."')\n") - ->outdent() - ->write(");\n") - ->outdent() - ->write("} catch (Twig_Sandbox_SecurityError \$e) {\n") - ->indent() - ->write("\$e->setSourceContext(\$this->getSourceContext());\n\n") - ->write("if (\$e instanceof Twig_Sandbox_SecurityNotAllowedTagError && isset(\$tags[\$e->getTagName()])) {\n") - ->indent() - ->write("\$e->setTemplateLine(\$tags[\$e->getTagName()]);\n") - ->outdent() - ->write("} elseif (\$e instanceof Twig_Sandbox_SecurityNotAllowedFilterError && isset(\$filters[\$e->getFilterName()])) {\n") - ->indent() - ->write("\$e->setTemplateLine(\$filters[\$e->getFilterName()]);\n") - ->outdent() - ->write("} elseif (\$e instanceof Twig_Sandbox_SecurityNotAllowedFunctionError && isset(\$functions[\$e->getFunctionName()])) {\n") - ->indent() - ->write("\$e->setTemplateLine(\$functions[\$e->getFunctionName()]);\n") - ->outdent() - ->write("}\n\n") - ->write("throw \$e;\n") - ->outdent() - ->write("}\n\n") - ; } } - -class_alias('Twig_Node_CheckSecurity', 'Twig\Node\CheckSecurityNode', false); diff --git a/vendor/twig/twig/lib/Twig/Node/Deprecated.php b/vendor/twig/twig/lib/Twig/Node/Deprecated.php new file mode 100644 index 0000000000000000000000000000000000000000..19b7f8b4aa9e1341b3130f153175307bb36c44d8 --- /dev/null +++ b/vendor/twig/twig/lib/Twig/Node/Deprecated.php @@ -0,0 +1,11 @@ +<?php + +use Twig\Node\DeprecatedNode; + +class_exists('Twig\Node\DeprecatedNode'); + +if (\false) { + class Twig_Node_Deprecated extends DeprecatedNode + { + } +} diff --git a/vendor/twig/twig/lib/Twig/Node/Do.php b/vendor/twig/twig/lib/Twig/Node/Do.php index cdd7e77a407d8910973841fabf57aa5a30cca30d..f538be2f0504e53e39da40b947ca2842021fb64a 100644 --- a/vendor/twig/twig/lib/Twig/Node/Do.php +++ b/vendor/twig/twig/lib/Twig/Node/Do.php @@ -1,35 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +use Twig\Node\DoNode; -/** - * Represents a do node. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class Twig_Node_Do extends Twig_Node -{ - public function __construct(Twig_Node_Expression $expr, $lineno, $tag = null) - { - parent::__construct(array('expr' => $expr), array(), $lineno, $tag); - } +class_exists('Twig\Node\DoNode'); - public function compile(Twig_Compiler $compiler) +if (\false) { + class Twig_Node_Do extends DoNode { - $compiler - ->addDebugInfo($this) - ->write('') - ->subcompile($this->getNode('expr')) - ->raw(";\n") - ; } } - -class_alias('Twig_Node_Do', 'Twig\Node\DoNode', false); diff --git a/vendor/twig/twig/lib/Twig/Node/Embed.php b/vendor/twig/twig/lib/Twig/Node/Embed.php index 3785d3a9fec456c09c8515e0fc08efd46ec69703..2dfe266a313f58c47c6301b611545e120acdf1ba 100644 --- a/vendor/twig/twig/lib/Twig/Node/Embed.php +++ b/vendor/twig/twig/lib/Twig/Node/Embed.php @@ -1,46 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +use Twig\Node\EmbedNode; -/** - * Represents an embed node. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class Twig_Node_Embed extends Twig_Node_Include -{ - // we don't inject the module to avoid node visitors to traverse it twice (as it will be already visited in the main module) - public function __construct($name, $index, Twig_Node_Expression $variables = null, $only = false, $ignoreMissing = false, $lineno, $tag = null) - { - parent::__construct(new Twig_Node_Expression_Constant('not_used', $lineno), $variables, $only, $ignoreMissing, $lineno, $tag); - - $this->setAttribute('name', $name); - // to be removed in 2.0, used name instead - $this->setAttribute('filename', $name); - $this->setAttribute('index', $index); - } +class_exists('Twig\Node\EmbedNode'); - protected function addGetTemplate(Twig_Compiler $compiler) +if (\false) { + class Twig_Node_Embed extends EmbedNode { - $compiler - ->write('$this->loadTemplate(') - ->string($this->getAttribute('name')) - ->raw(', ') - ->repr($this->getTemplateName()) - ->raw(', ') - ->repr($this->getTemplateLine()) - ->raw(', ') - ->string($this->getAttribute('index')) - ->raw(')') - ; } } - -class_alias('Twig_Node_Embed', 'Twig\Node\EmbedNode', false); diff --git a/vendor/twig/twig/lib/Twig/Node/Expression.php b/vendor/twig/twig/lib/Twig/Node/Expression.php index a99c4e63add2dd4b07664fe91a1c971dc6401400..9775df02f830a4840431872751f3e855b404f03f 100644 --- a/vendor/twig/twig/lib/Twig/Node/Expression.php +++ b/vendor/twig/twig/lib/Twig/Node/Expression.php @@ -1,22 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * (c) Armin Ronacher - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +use Twig\Node\Expression\AbstractExpression; -/** - * Abstract class for all nodes that represents an expression. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -abstract class Twig_Node_Expression extends Twig_Node -{ -} +class_exists('Twig\Node\Expression\AbstractExpression'); -class_alias('Twig_Node_Expression', 'Twig\Node\Expression\AbstractExpression', false); +if (\false) { + class Twig_Node_Expression extends AbstractExpression + { + } +} diff --git a/vendor/twig/twig/lib/Twig/Node/Expression/Array.php b/vendor/twig/twig/lib/Twig/Node/Expression/Array.php index 0e77bb08bca88c1199a38b4707962528989b1d35..dec28df7bfe25a3a455d76d3c0f5a3ba155e4c36 100644 --- a/vendor/twig/twig/lib/Twig/Node/Expression/Array.php +++ b/vendor/twig/twig/lib/Twig/Node/Expression/Array.php @@ -1,83 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ -class Twig_Node_Expression_Array extends Twig_Node_Expression -{ - protected $index; +use Twig\Node\Expression\ArrayExpression; - public function __construct(array $elements, $lineno) - { - parent::__construct($elements, array(), $lineno); - - $this->index = -1; - foreach ($this->getKeyValuePairs() as $pair) { - if ($pair['key'] instanceof Twig_Node_Expression_Constant && ctype_digit((string) $pair['key']->getAttribute('value')) && $pair['key']->getAttribute('value') > $this->index) { - $this->index = $pair['key']->getAttribute('value'); - } - } - } - - public function getKeyValuePairs() - { - $pairs = array(); - - foreach (array_chunk($this->nodes, 2) as $pair) { - $pairs[] = array( - 'key' => $pair[0], - 'value' => $pair[1], - ); - } - - return $pairs; - } - - public function hasElement(Twig_Node_Expression $key) - { - foreach ($this->getKeyValuePairs() as $pair) { - // we compare the string representation of the keys - // to avoid comparing the line numbers which are not relevant here. - if ((string) $key === (string) $pair['key']) { - return true; - } - } - - return false; - } +class_exists('Twig\Node\Expression\ArrayExpression'); - public function addElement(Twig_Node_Expression $value, Twig_Node_Expression $key = null) +if (\false) { + class Twig_Node_Expression_Array extends ArrayExpression { - if (null === $key) { - $key = new Twig_Node_Expression_Constant(++$this->index, $value->getTemplateLine()); - } - - array_push($this->nodes, $key, $value); - } - - public function compile(Twig_Compiler $compiler) - { - $compiler->raw('array('); - $first = true; - foreach ($this->getKeyValuePairs() as $pair) { - if (!$first) { - $compiler->raw(', '); - } - $first = false; - - $compiler - ->subcompile($pair['key']) - ->raw(' => ') - ->subcompile($pair['value']) - ; - } - $compiler->raw(')'); } } - -class_alias('Twig_Node_Expression_Array', 'Twig\Node\Expression\ArrayExpression', false); diff --git a/vendor/twig/twig/lib/Twig/Node/Expression/AssignName.php b/vendor/twig/twig/lib/Twig/Node/Expression/AssignName.php index 2e6b4c7ca3260cd4110f03b2b731d625beaa43c1..cf2e91cf0f20b3122a6377508ae4e2e3ddcfee47 100644 --- a/vendor/twig/twig/lib/Twig/Node/Expression/AssignName.php +++ b/vendor/twig/twig/lib/Twig/Node/Expression/AssignName.php @@ -1,25 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * (c) Armin Ronacher - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +use Twig\Node\Expression\AssignNameExpression; -class Twig_Node_Expression_AssignName extends Twig_Node_Expression_Name -{ - public function compile(Twig_Compiler $compiler) +class_exists('Twig\Node\Expression\AssignNameExpression'); + +if (\false) { + class Twig_Node_Expression_AssignName extends AssignNameExpression { - $compiler - ->raw('$context[') - ->string($this->getAttribute('name')) - ->raw(']') - ; } } - -class_alias('Twig_Node_Expression_AssignName', 'Twig\Node\Expression\AssignNameExpression', false); diff --git a/vendor/twig/twig/lib/Twig/Node/Expression/Binary.php b/vendor/twig/twig/lib/Twig/Node/Expression/Binary.php index 2b545d98482ddb4f18403ae038213596a05a568e..6591c4223f734461e6cb69edec12edcb224735f7 100644 --- a/vendor/twig/twig/lib/Twig/Node/Expression/Binary.php +++ b/vendor/twig/twig/lib/Twig/Node/Expression/Binary.php @@ -1,37 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * (c) Armin Ronacher - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ -abstract class Twig_Node_Expression_Binary extends Twig_Node_Expression -{ - public function __construct(Twig_NodeInterface $left, Twig_NodeInterface $right, $lineno) - { - parent::__construct(array('left' => $left, 'right' => $right), array(), $lineno); - } +use Twig\Node\Expression\Binary\AbstractBinary; + +class_exists('Twig\Node\Expression\Binary\AbstractBinary'); - public function compile(Twig_Compiler $compiler) +if (\false) { + class Twig_Node_Expression_Binary extends AbstractBinary { - $compiler - ->raw('(') - ->subcompile($this->getNode('left')) - ->raw(' ') - ; - $this->operator($compiler); - $compiler - ->raw(' ') - ->subcompile($this->getNode('right')) - ->raw(')') - ; } - - abstract public function operator(Twig_Compiler $compiler); } - -class_alias('Twig_Node_Expression_Binary', 'Twig\Node\Expression\Binary\AbstractBinary', false); diff --git a/vendor/twig/twig/lib/Twig/Node/Expression/Binary/Add.php b/vendor/twig/twig/lib/Twig/Node/Expression/Binary/Add.php index 5a09d8367fa1d8bfcd7f6a464d478c0e151dd3d2..895a2fce3bbcb772a3657180a5202b322995ce77 100644 --- a/vendor/twig/twig/lib/Twig/Node/Expression/Binary/Add.php +++ b/vendor/twig/twig/lib/Twig/Node/Expression/Binary/Add.php @@ -1,20 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * (c) Armin Ronacher - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ -class Twig_Node_Expression_Binary_Add extends Twig_Node_Expression_Binary -{ - public function operator(Twig_Compiler $compiler) +use Twig\Node\Expression\Binary\AddBinary; + +class_exists('Twig\Node\Expression\Binary\AddBinary'); + +if (\false) { + class Twig_Node_Expression_Binary_Add extends AddBinary { - return $compiler->raw('+'); } } - -class_alias('Twig_Node_Expression_Binary_Add', 'Twig\Node\Expression\Binary\AddBinary', false); diff --git a/vendor/twig/twig/lib/Twig/Node/Expression/Binary/And.php b/vendor/twig/twig/lib/Twig/Node/Expression/Binary/And.php index 9ffddce6b1d36bdf34b78501b18e9521956c94b3..738c6aa1789b70a9e35519c343df131f1bcf8f3b 100644 --- a/vendor/twig/twig/lib/Twig/Node/Expression/Binary/And.php +++ b/vendor/twig/twig/lib/Twig/Node/Expression/Binary/And.php @@ -1,20 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * (c) Armin Ronacher - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ -class Twig_Node_Expression_Binary_And extends Twig_Node_Expression_Binary -{ - public function operator(Twig_Compiler $compiler) +use Twig\Node\Expression\Binary\AndBinary; + +class_exists('Twig\Node\Expression\Binary\AndBinary'); + +if (\false) { + class Twig_Node_Expression_Binary_And extends AndBinary { - return $compiler->raw('&&'); } } - -class_alias('Twig_Node_Expression_Binary_And', 'Twig\Node\Expression\Binary\AndBinary', false); diff --git a/vendor/twig/twig/lib/Twig/Node/Expression/Binary/BitwiseAnd.php b/vendor/twig/twig/lib/Twig/Node/Expression/Binary/BitwiseAnd.php index e46e9ebfa40f1fc06b5b6606d1a039f34ba83fd4..8649e899b2bea85cb7906dc9e1cce3ca1b747d76 100644 --- a/vendor/twig/twig/lib/Twig/Node/Expression/Binary/BitwiseAnd.php +++ b/vendor/twig/twig/lib/Twig/Node/Expression/Binary/BitwiseAnd.php @@ -1,20 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * (c) Armin Ronacher - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ -class Twig_Node_Expression_Binary_BitwiseAnd extends Twig_Node_Expression_Binary -{ - public function operator(Twig_Compiler $compiler) +use Twig\Node\Expression\Binary\BitwiseAndBinary; + +class_exists('Twig\Node\Expression\Binary\BitwiseAndBinary'); + +if (\false) { + class Twig_Node_Expression_Binary_BitwiseAnd extends BitwiseAndBinary { - return $compiler->raw('&'); } } - -class_alias('Twig_Node_Expression_Binary_BitwiseAnd', 'Twig\Node\Expression\Binary\BitwiseAndBinary', false); diff --git a/vendor/twig/twig/lib/Twig/Node/Expression/Binary/BitwiseOr.php b/vendor/twig/twig/lib/Twig/Node/Expression/Binary/BitwiseOr.php index 5d7f1b7c04b86e7d441398cf06bf7774c1b7d39c..473fba270ac3503d192da59cd7743b552b2588be 100644 --- a/vendor/twig/twig/lib/Twig/Node/Expression/Binary/BitwiseOr.php +++ b/vendor/twig/twig/lib/Twig/Node/Expression/Binary/BitwiseOr.php @@ -1,20 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * (c) Armin Ronacher - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ -class Twig_Node_Expression_Binary_BitwiseOr extends Twig_Node_Expression_Binary -{ - public function operator(Twig_Compiler $compiler) +use Twig\Node\Expression\Binary\BitwiseOrBinary; + +class_exists('Twig\Node\Expression\Binary\BitwiseOrBinary'); + +if (\false) { + class Twig_Node_Expression_Binary_BitwiseOr extends BitwiseOrBinary { - return $compiler->raw('|'); } } - -class_alias('Twig_Node_Expression_Binary_BitwiseOr', 'Twig\Node\Expression\Binary\BitwiseOrBinary', false); diff --git a/vendor/twig/twig/lib/Twig/Node/Expression/Binary/BitwiseXor.php b/vendor/twig/twig/lib/Twig/Node/Expression/Binary/BitwiseXor.php index 82edf516cec4771aabb5d5c44769986277cdd183..3fedc369ec586dbf2ba6d2c944243c03bea66c82 100644 --- a/vendor/twig/twig/lib/Twig/Node/Expression/Binary/BitwiseXor.php +++ b/vendor/twig/twig/lib/Twig/Node/Expression/Binary/BitwiseXor.php @@ -1,20 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * (c) Armin Ronacher - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ -class Twig_Node_Expression_Binary_BitwiseXor extends Twig_Node_Expression_Binary -{ - public function operator(Twig_Compiler $compiler) +use Twig\Node\Expression\Binary\BitwiseXorBinary; + +class_exists('Twig\Node\Expression\Binary\BitwiseXorBinary'); + +if (\false) { + class Twig_Node_Expression_Binary_BitwiseXor extends BitwiseXorBinary { - return $compiler->raw('^'); } } - -class_alias('Twig_Node_Expression_Binary_BitwiseXor', 'Twig\Node\Expression\Binary\BitwiseXorBinary', false); diff --git a/vendor/twig/twig/lib/Twig/Node/Expression/Binary/Concat.php b/vendor/twig/twig/lib/Twig/Node/Expression/Binary/Concat.php index 91abca6023bda9e27164b7c4d2ee039ef96c525b..8d7b723c1f82abc6a33cb674d2f8dd1af0a68772 100644 --- a/vendor/twig/twig/lib/Twig/Node/Expression/Binary/Concat.php +++ b/vendor/twig/twig/lib/Twig/Node/Expression/Binary/Concat.php @@ -1,20 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * (c) Armin Ronacher - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ -class Twig_Node_Expression_Binary_Concat extends Twig_Node_Expression_Binary -{ - public function operator(Twig_Compiler $compiler) +use Twig\Node\Expression\Binary\ConcatBinary; + +class_exists('Twig\Node\Expression\Binary\ConcatBinary'); + +if (\false) { + class Twig_Node_Expression_Binary_Concat extends ConcatBinary { - return $compiler->raw('.'); } } - -class_alias('Twig_Node_Expression_Binary_Concat', 'Twig\Node\Expression\Binary\ConcatBinary', false); diff --git a/vendor/twig/twig/lib/Twig/Node/Expression/Binary/Div.php b/vendor/twig/twig/lib/Twig/Node/Expression/Binary/Div.php index 38ffa30c32390759d0ad4a17c78fa64bd1050592..ce19322f02a353f584a1b2576d58c19e00a41f49 100644 --- a/vendor/twig/twig/lib/Twig/Node/Expression/Binary/Div.php +++ b/vendor/twig/twig/lib/Twig/Node/Expression/Binary/Div.php @@ -1,20 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * (c) Armin Ronacher - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ -class Twig_Node_Expression_Binary_Div extends Twig_Node_Expression_Binary -{ - public function operator(Twig_Compiler $compiler) +use Twig\Node\Expression\Binary\DivBinary; + +class_exists('Twig\Node\Expression\Binary\DivBinary'); + +if (\false) { + class Twig_Node_Expression_Binary_Div extends DivBinary { - return $compiler->raw('/'); } } - -class_alias('Twig_Node_Expression_Binary_Div', 'Twig\Node\Expression\Binary\DivBinary', false); diff --git a/vendor/twig/twig/lib/Twig/Node/Expression/Binary/EndsWith.php b/vendor/twig/twig/lib/Twig/Node/Expression/Binary/EndsWith.php index 85c52937665ed5707f5b19de4c46dbb1f78c8258..b6d3e3c430c96910ec4a3aa9f7be4414672ed2f5 100644 --- a/vendor/twig/twig/lib/Twig/Node/Expression/Binary/EndsWith.php +++ b/vendor/twig/twig/lib/Twig/Node/Expression/Binary/EndsWith.php @@ -1,32 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ -class Twig_Node_Expression_Binary_EndsWith extends Twig_Node_Expression_Binary -{ - public function compile(Twig_Compiler $compiler) - { - $left = $compiler->getVarName(); - $right = $compiler->getVarName(); - $compiler - ->raw(sprintf('(is_string($%s = ', $left)) - ->subcompile($this->getNode('left')) - ->raw(sprintf(') && is_string($%s = ', $right)) - ->subcompile($this->getNode('right')) - ->raw(sprintf(') && (\'\' === $%2$s || $%2$s === substr($%1$s, -strlen($%2$s))))', $left, $right)) - ; - } +use Twig\Node\Expression\Binary\EndsWithBinary; - public function operator(Twig_Compiler $compiler) +class_exists('Twig\Node\Expression\Binary\EndsWithBinary'); + +if (\false) { + class Twig_Node_Expression_Binary_EndsWith extends EndsWithBinary { - return $compiler->raw(''); } } - -class_alias('Twig_Node_Expression_Binary_EndsWith', 'Twig\Node\Expression\Binary\EndsWithBinary', false); diff --git a/vendor/twig/twig/lib/Twig/Node/Expression/Binary/Equal.php b/vendor/twig/twig/lib/Twig/Node/Expression/Binary/Equal.php index a6a6946b6d4cddb3f2edc2b8fc2a0017138e0625..e737b61e8a374b666d224ca974af6294c1b9402e 100644 --- a/vendor/twig/twig/lib/Twig/Node/Expression/Binary/Equal.php +++ b/vendor/twig/twig/lib/Twig/Node/Expression/Binary/Equal.php @@ -1,19 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ -class Twig_Node_Expression_Binary_Equal extends Twig_Node_Expression_Binary -{ - public function operator(Twig_Compiler $compiler) +use Twig\Node\Expression\Binary\EqualBinary; + +class_exists('Twig\Node\Expression\Binary\EqualBinary'); + +if (\false) { + class Twig_Node_Expression_Binary_Equal extends EqualBinary { - return $compiler->raw('=='); } } - -class_alias('Twig_Node_Expression_Binary_Equal', 'Twig\Node\Expression\Binary\EqualBinary', false); diff --git a/vendor/twig/twig/lib/Twig/Node/Expression/Binary/FloorDiv.php b/vendor/twig/twig/lib/Twig/Node/Expression/Binary/FloorDiv.php index 7393bcb89756f1ae52cf7139b47b1a490a8a1564..7119351fcf6da56a0210825e9b5b9763fde1f80f 100644 --- a/vendor/twig/twig/lib/Twig/Node/Expression/Binary/FloorDiv.php +++ b/vendor/twig/twig/lib/Twig/Node/Expression/Binary/FloorDiv.php @@ -1,26 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ -class Twig_Node_Expression_Binary_FloorDiv extends Twig_Node_Expression_Binary -{ - public function compile(Twig_Compiler $compiler) - { - $compiler->raw('(int) floor('); - parent::compile($compiler); - $compiler->raw(')'); - } +use Twig\Node\Expression\Binary\FloorDivBinary; - public function operator(Twig_Compiler $compiler) +class_exists('Twig\Node\Expression\Binary\FloorDivBinary'); + +if (\false) { + class Twig_Node_Expression_Binary_FloorDiv extends FloorDivBinary { - return $compiler->raw('/'); } } - -class_alias('Twig_Node_Expression_Binary_FloorDiv', 'Twig\Node\Expression\Binary\FloorDivBinary', false); diff --git a/vendor/twig/twig/lib/Twig/Node/Expression/Binary/Greater.php b/vendor/twig/twig/lib/Twig/Node/Expression/Binary/Greater.php index 832f97977c65234dc92344e98c7c4e10da4a9d78..183301d7e0084c18430c9c4552340417ac817be2 100644 --- a/vendor/twig/twig/lib/Twig/Node/Expression/Binary/Greater.php +++ b/vendor/twig/twig/lib/Twig/Node/Expression/Binary/Greater.php @@ -1,19 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ -class Twig_Node_Expression_Binary_Greater extends Twig_Node_Expression_Binary -{ - public function operator(Twig_Compiler $compiler) +use Twig\Node\Expression\Binary\GreaterBinary; + +class_exists('Twig\Node\Expression\Binary\GreaterBinary'); + +if (\false) { + class Twig_Node_Expression_Binary_Greater extends GreaterBinary { - return $compiler->raw('>'); } } - -class_alias('Twig_Node_Expression_Binary_Greater', 'Twig\Node\Expression\Binary\GreaterBinary', false); diff --git a/vendor/twig/twig/lib/Twig/Node/Expression/Binary/GreaterEqual.php b/vendor/twig/twig/lib/Twig/Node/Expression/Binary/GreaterEqual.php index c5f762457282daacb7e29c195499c423a72da8ae..f47999bd84cb8fc582bf9444acbabafae8920fcf 100644 --- a/vendor/twig/twig/lib/Twig/Node/Expression/Binary/GreaterEqual.php +++ b/vendor/twig/twig/lib/Twig/Node/Expression/Binary/GreaterEqual.php @@ -1,19 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ -class Twig_Node_Expression_Binary_GreaterEqual extends Twig_Node_Expression_Binary -{ - public function operator(Twig_Compiler $compiler) +use Twig\Node\Expression\Binary\GreaterEqualBinary; + +class_exists('Twig\Node\Expression\Binary\GreaterEqualBinary'); + +if (\false) { + class Twig_Node_Expression_Binary_GreaterEqual extends GreaterEqualBinary { - return $compiler->raw('>='); } } - -class_alias('Twig_Node_Expression_Binary_GreaterEqual', 'Twig\Node\Expression\Binary\GreaterEqualBinary', false); diff --git a/vendor/twig/twig/lib/Twig/Node/Expression/Binary/In.php b/vendor/twig/twig/lib/Twig/Node/Expression/Binary/In.php index af112448f46715259ab3723e1fb735bc67c64ed4..7a13d9544b1adda47165258e33dc9b4619ad5e3a 100644 --- a/vendor/twig/twig/lib/Twig/Node/Expression/Binary/In.php +++ b/vendor/twig/twig/lib/Twig/Node/Expression/Binary/In.php @@ -1,30 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ -class Twig_Node_Expression_Binary_In extends Twig_Node_Expression_Binary -{ - public function compile(Twig_Compiler $compiler) - { - $compiler - ->raw('twig_in_filter(') - ->subcompile($this->getNode('left')) - ->raw(', ') - ->subcompile($this->getNode('right')) - ->raw(')') - ; - } +use Twig\Node\Expression\Binary\InBinary; - public function operator(Twig_Compiler $compiler) +class_exists('Twig\Node\Expression\Binary\InBinary'); + +if (\false) { + class Twig_Node_Expression_Binary_In extends InBinary { - return $compiler->raw('in'); } } - -class_alias('Twig_Node_Expression_Binary_In', 'Twig\Node\Expression\Binary\InBinary', false); diff --git a/vendor/twig/twig/lib/Twig/Node/Expression/Binary/Less.php b/vendor/twig/twig/lib/Twig/Node/Expression/Binary/Less.php index ab8fc1f9a81e13b19b19e5e7f063cb96ff6dd3d6..7295179a4ce5066b50707b17214f241e35a543e1 100644 --- a/vendor/twig/twig/lib/Twig/Node/Expression/Binary/Less.php +++ b/vendor/twig/twig/lib/Twig/Node/Expression/Binary/Less.php @@ -1,19 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ -class Twig_Node_Expression_Binary_Less extends Twig_Node_Expression_Binary -{ - public function operator(Twig_Compiler $compiler) +use Twig\Node\Expression\Binary\LessBinary; + +class_exists('Twig\Node\Expression\Binary\LessBinary'); + +if (\false) { + class Twig_Node_Expression_Binary_Less extends LessBinary { - return $compiler->raw('<'); } } - -class_alias('Twig_Node_Expression_Binary_Less', 'Twig\Node\Expression\Binary\LessBinary', false); diff --git a/vendor/twig/twig/lib/Twig/Node/Expression/Binary/LessEqual.php b/vendor/twig/twig/lib/Twig/Node/Expression/Binary/LessEqual.php index 71a279e9ceba31b48e4c9c19dc5bc7892396e7e2..cbfbc8c7ad0376ebc066aad869201a951bc9b4b9 100644 --- a/vendor/twig/twig/lib/Twig/Node/Expression/Binary/LessEqual.php +++ b/vendor/twig/twig/lib/Twig/Node/Expression/Binary/LessEqual.php @@ -1,19 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ -class Twig_Node_Expression_Binary_LessEqual extends Twig_Node_Expression_Binary -{ - public function operator(Twig_Compiler $compiler) +use Twig\Node\Expression\Binary\LessEqualBinary; + +class_exists('Twig\Node\Expression\Binary\LessEqualBinary'); + +if (\false) { + class Twig_Node_Expression_Binary_LessEqual extends LessEqualBinary { - return $compiler->raw('<='); } } - -class_alias('Twig_Node_Expression_Binary_LessEqual', 'Twig\Node\Expression\Binary\LessEqualBinary', false); diff --git a/vendor/twig/twig/lib/Twig/Node/Expression/Binary/Matches.php b/vendor/twig/twig/lib/Twig/Node/Expression/Binary/Matches.php index 5cb855842887357d4a064342ba4cb7960797b8e1..5209083ebdd429ddaa8374abc37a9ff49a73ff00 100644 --- a/vendor/twig/twig/lib/Twig/Node/Expression/Binary/Matches.php +++ b/vendor/twig/twig/lib/Twig/Node/Expression/Binary/Matches.php @@ -1,30 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ -class Twig_Node_Expression_Binary_Matches extends Twig_Node_Expression_Binary -{ - public function compile(Twig_Compiler $compiler) - { - $compiler - ->raw('preg_match(') - ->subcompile($this->getNode('right')) - ->raw(', ') - ->subcompile($this->getNode('left')) - ->raw(')') - ; - } +use Twig\Node\Expression\Binary\MatchesBinary; - public function operator(Twig_Compiler $compiler) +class_exists('Twig\Node\Expression\Binary\MatchesBinary'); + +if (\false) { + class Twig_Node_Expression_Binary_Matches extends MatchesBinary { - return $compiler->raw(''); } } - -class_alias('Twig_Node_Expression_Binary_Matches', 'Twig\Node\Expression\Binary\MatchesBinary', false); diff --git a/vendor/twig/twig/lib/Twig/Node/Expression/Binary/Mod.php b/vendor/twig/twig/lib/Twig/Node/Expression/Binary/Mod.php index 28109633dad025e6e631d3c31e28d6b7bf0f6358..aec59e3bae66755e09f7311aee6a541037882fa8 100644 --- a/vendor/twig/twig/lib/Twig/Node/Expression/Binary/Mod.php +++ b/vendor/twig/twig/lib/Twig/Node/Expression/Binary/Mod.php @@ -1,20 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * (c) Armin Ronacher - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ -class Twig_Node_Expression_Binary_Mod extends Twig_Node_Expression_Binary -{ - public function operator(Twig_Compiler $compiler) +use Twig\Node\Expression\Binary\ModBinary; + +class_exists('Twig\Node\Expression\Binary\ModBinary'); + +if (\false) { + class Twig_Node_Expression_Binary_Mod extends ModBinary { - return $compiler->raw('%'); } } - -class_alias('Twig_Node_Expression_Binary_Mod', 'Twig\Node\Expression\Binary\ModBinary', false); diff --git a/vendor/twig/twig/lib/Twig/Node/Expression/Binary/Mul.php b/vendor/twig/twig/lib/Twig/Node/Expression/Binary/Mul.php index 790c6a22d8813e857e0dc0f7dd84dca6105161c4..850934a1008d777635a8a7758a3a44e6fd55cdbc 100644 --- a/vendor/twig/twig/lib/Twig/Node/Expression/Binary/Mul.php +++ b/vendor/twig/twig/lib/Twig/Node/Expression/Binary/Mul.php @@ -1,20 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * (c) Armin Ronacher - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ -class Twig_Node_Expression_Binary_Mul extends Twig_Node_Expression_Binary -{ - public function operator(Twig_Compiler $compiler) +use Twig\Node\Expression\Binary\MulBinary; + +class_exists('Twig\Node\Expression\Binary\MulBinary'); + +if (\false) { + class Twig_Node_Expression_Binary_Mul extends MulBinary { - return $compiler->raw('*'); } } - -class_alias('Twig_Node_Expression_Binary_Mul', 'Twig\Node\Expression\Binary\MulBinary', false); diff --git a/vendor/twig/twig/lib/Twig/Node/Expression/Binary/NotEqual.php b/vendor/twig/twig/lib/Twig/Node/Expression/Binary/NotEqual.php index bb45c9ed552549aadf0377322dc7abf545f79c6e..842c8bc8b8bf0cf62734cff43c6952bb145117b4 100644 --- a/vendor/twig/twig/lib/Twig/Node/Expression/Binary/NotEqual.php +++ b/vendor/twig/twig/lib/Twig/Node/Expression/Binary/NotEqual.php @@ -1,19 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ -class Twig_Node_Expression_Binary_NotEqual extends Twig_Node_Expression_Binary -{ - public function operator(Twig_Compiler $compiler) +use Twig\Node\Expression\Binary\NotEqualBinary; + +class_exists('Twig\Node\Expression\Binary\NotEqualBinary'); + +if (\false) { + class Twig_Node_Expression_Binary_NotEqual extends NotEqualBinary { - return $compiler->raw('!='); } } - -class_alias('Twig_Node_Expression_Binary_NotEqual', 'Twig\Node\Expression\Binary\NotEqualBinary', false); diff --git a/vendor/twig/twig/lib/Twig/Node/Expression/Binary/NotIn.php b/vendor/twig/twig/lib/Twig/Node/Expression/Binary/NotIn.php index 9dedf92f920a398a26895b2576109181e3ac6bbb..7d3c1288f38d6f9b86cda7b868461ef49d380e1d 100644 --- a/vendor/twig/twig/lib/Twig/Node/Expression/Binary/NotIn.php +++ b/vendor/twig/twig/lib/Twig/Node/Expression/Binary/NotIn.php @@ -1,30 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ -class Twig_Node_Expression_Binary_NotIn extends Twig_Node_Expression_Binary -{ - public function compile(Twig_Compiler $compiler) - { - $compiler - ->raw('!twig_in_filter(') - ->subcompile($this->getNode('left')) - ->raw(', ') - ->subcompile($this->getNode('right')) - ->raw(')') - ; - } +use Twig\Node\Expression\Binary\NotInBinary; - public function operator(Twig_Compiler $compiler) +class_exists('Twig\Node\Expression\Binary\NotInBinary'); + +if (\false) { + class Twig_Node_Expression_Binary_NotIn extends NotInBinary { - return $compiler->raw('not in'); } } - -class_alias('Twig_Node_Expression_Binary_NotIn', 'Twig\Node\Expression\Binary\NotInBinary', false); diff --git a/vendor/twig/twig/lib/Twig/Node/Expression/Binary/Or.php b/vendor/twig/twig/lib/Twig/Node/Expression/Binary/Or.php index dc9eece14cad4e4c5ca9ac4d76c1349357cb88e6..3a38faed6bbf2f56bf2aa58868315657b14c8fa5 100644 --- a/vendor/twig/twig/lib/Twig/Node/Expression/Binary/Or.php +++ b/vendor/twig/twig/lib/Twig/Node/Expression/Binary/Or.php @@ -1,20 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * (c) Armin Ronacher - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ -class Twig_Node_Expression_Binary_Or extends Twig_Node_Expression_Binary -{ - public function operator(Twig_Compiler $compiler) +use Twig\Node\Expression\Binary\OrBinary; + +class_exists('Twig\Node\Expression\Binary\OrBinary'); + +if (\false) { + class Twig_Node_Expression_Binary_Or extends OrBinary { - return $compiler->raw('||'); } } - -class_alias('Twig_Node_Expression_Binary_Or', 'Twig\Node\Expression\Binary\OrBinary', false); diff --git a/vendor/twig/twig/lib/Twig/Node/Expression/Binary/Power.php b/vendor/twig/twig/lib/Twig/Node/Expression/Binary/Power.php index d24777bd5525f29d4182d13c777b22ad2f97bbd3..7eafca80f28b9ccbeead737a7fd44e4a0c9a507a 100644 --- a/vendor/twig/twig/lib/Twig/Node/Expression/Binary/Power.php +++ b/vendor/twig/twig/lib/Twig/Node/Expression/Binary/Power.php @@ -1,34 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ -class Twig_Node_Expression_Binary_Power extends Twig_Node_Expression_Binary -{ - public function compile(Twig_Compiler $compiler) - { - if (PHP_VERSION_ID >= 50600) { - return parent::compile($compiler); - } +use Twig\Node\Expression\Binary\PowerBinary; - $compiler - ->raw('pow(') - ->subcompile($this->getNode('left')) - ->raw(', ') - ->subcompile($this->getNode('right')) - ->raw(')') - ; - } +class_exists('Twig\Node\Expression\Binary\PowerBinary'); - public function operator(Twig_Compiler $compiler) +if (\false) { + class Twig_Node_Expression_Binary_Power extends PowerBinary { - return $compiler->raw('**'); } } - -class_alias('Twig_Node_Expression_Binary_Power', 'Twig\Node\Expression\Binary\PowerBinary', false); diff --git a/vendor/twig/twig/lib/Twig/Node/Expression/Binary/Range.php b/vendor/twig/twig/lib/Twig/Node/Expression/Binary/Range.php index 187f67653b0510e9733fadbbaab1d71d95dcc39c..01564142afe3348f91ca49c72730e46758483d97 100644 --- a/vendor/twig/twig/lib/Twig/Node/Expression/Binary/Range.php +++ b/vendor/twig/twig/lib/Twig/Node/Expression/Binary/Range.php @@ -1,30 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ -class Twig_Node_Expression_Binary_Range extends Twig_Node_Expression_Binary -{ - public function compile(Twig_Compiler $compiler) - { - $compiler - ->raw('range(') - ->subcompile($this->getNode('left')) - ->raw(', ') - ->subcompile($this->getNode('right')) - ->raw(')') - ; - } +use Twig\Node\Expression\Binary\RangeBinary; - public function operator(Twig_Compiler $compiler) +class_exists('Twig\Node\Expression\Binary\RangeBinary'); + +if (\false) { + class Twig_Node_Expression_Binary_Range extends RangeBinary { - return $compiler->raw('..'); } } - -class_alias('Twig_Node_Expression_Binary_Range', 'Twig\Node\Expression\Binary\RangeBinary', false); diff --git a/vendor/twig/twig/lib/Twig/Node/Expression/Binary/StartsWith.php b/vendor/twig/twig/lib/Twig/Node/Expression/Binary/StartsWith.php index 7e43b8de09d3f7e30ac5d86774daa8e44d5c1d31..f72ea49ca990c7fa6ff60d5eeeb047b3988f40ba 100644 --- a/vendor/twig/twig/lib/Twig/Node/Expression/Binary/StartsWith.php +++ b/vendor/twig/twig/lib/Twig/Node/Expression/Binary/StartsWith.php @@ -1,32 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ -class Twig_Node_Expression_Binary_StartsWith extends Twig_Node_Expression_Binary -{ - public function compile(Twig_Compiler $compiler) - { - $left = $compiler->getVarName(); - $right = $compiler->getVarName(); - $compiler - ->raw(sprintf('(is_string($%s = ', $left)) - ->subcompile($this->getNode('left')) - ->raw(sprintf(') && is_string($%s = ', $right)) - ->subcompile($this->getNode('right')) - ->raw(sprintf(') && (\'\' === $%2$s || 0 === strpos($%1$s, $%2$s)))', $left, $right)) - ; - } +use Twig\Node\Expression\Binary\StartsWithBinary; - public function operator(Twig_Compiler $compiler) +class_exists('Twig\Node\Expression\Binary\StartsWithBinary'); + +if (\false) { + class Twig_Node_Expression_Binary_StartsWith extends StartsWithBinary { - return $compiler->raw(''); } } - -class_alias('Twig_Node_Expression_Binary_StartsWith', 'Twig\Node\Expression\Binary\StartsWithBinary', false); diff --git a/vendor/twig/twig/lib/Twig/Node/Expression/Binary/Sub.php b/vendor/twig/twig/lib/Twig/Node/Expression/Binary/Sub.php index cff8ed075bae306301e3e0e25b1b76ab2ea49d12..f596da703c07eb9977d7e7bb09e5bfb55616d10f 100644 --- a/vendor/twig/twig/lib/Twig/Node/Expression/Binary/Sub.php +++ b/vendor/twig/twig/lib/Twig/Node/Expression/Binary/Sub.php @@ -1,20 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * (c) Armin Ronacher - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ -class Twig_Node_Expression_Binary_Sub extends Twig_Node_Expression_Binary -{ - public function operator(Twig_Compiler $compiler) +use Twig\Node\Expression\Binary\SubBinary; + +class_exists('Twig\Node\Expression\Binary\SubBinary'); + +if (\false) { + class Twig_Node_Expression_Binary_Sub extends SubBinary { - return $compiler->raw('-'); } } - -class_alias('Twig_Node_Expression_Binary_Sub', 'Twig\Node\Expression\Binary\SubBinary', false); diff --git a/vendor/twig/twig/lib/Twig/Node/Expression/BlockReference.php b/vendor/twig/twig/lib/Twig/Node/Expression/BlockReference.php index 37a3983d68713fdeb6e6af26a4bc1a0edda343ed..8ea2350a394da1498e118733a8112aab3b0de0a6 100644 --- a/vendor/twig/twig/lib/Twig/Node/Expression/BlockReference.php +++ b/vendor/twig/twig/lib/Twig/Node/Expression/BlockReference.php @@ -1,93 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * (c) Armin Ronacher - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +use Twig\Node\Expression\BlockReferenceExpression; -/** - * Represents a block call node. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class Twig_Node_Expression_BlockReference extends Twig_Node_Expression -{ - /** - * @param Twig_Node|null $template - */ - public function __construct(Twig_NodeInterface $name, $template = null, $lineno, $tag = null) - { - if (is_bool($template)) { - @trigger_error(sprintf('The %s method "$asString" argument is deprecated since version 1.28 and will be removed in 2.0.', __METHOD__), E_USER_DEPRECATED); - - $template = null; - } - - $nodes = array('name' => $name); - if (null !== $template) { - $nodes['template'] = $template; - } - - parent::__construct($nodes, array('is_defined_test' => false, 'output' => false), $lineno, $tag); - } +class_exists('Twig\Node\Expression\BlockReferenceExpression'); - public function compile(Twig_Compiler $compiler) +if (\false) { + class Twig_Node_Expression_BlockReference extends BlockReferenceExpression { - if ($this->getAttribute('is_defined_test')) { - $this->compileTemplateCall($compiler, 'hasBlock'); - } else { - if ($this->getAttribute('output')) { - $compiler->addDebugInfo($this); - - $this - ->compileTemplateCall($compiler, 'displayBlock') - ->raw(";\n"); - } else { - $this->compileTemplateCall($compiler, 'renderBlock'); - } - } - } - - private function compileTemplateCall(Twig_Compiler $compiler, $method) - { - if (!$this->hasNode('template')) { - $compiler->write('$this'); - } else { - $compiler - ->write('$this->loadTemplate(') - ->subcompile($this->getNode('template')) - ->raw(', ') - ->repr($this->getTemplateName()) - ->raw(', ') - ->repr($this->getTemplateLine()) - ->raw(')') - ; - } - - $compiler->raw(sprintf('->%s', $method)); - $this->compileBlockArguments($compiler); - - return $compiler; - } - - private function compileBlockArguments(Twig_Compiler $compiler) - { - $compiler - ->raw('(') - ->subcompile($this->getNode('name')) - ->raw(', $context'); - - if (!$this->hasNode('template')) { - $compiler->raw(', $blocks'); - } - - return $compiler->raw(')'); } } - -class_alias('Twig_Node_Expression_BlockReference', 'Twig\Node\Expression\BlockReferenceExpression', false); diff --git a/vendor/twig/twig/lib/Twig/Node/Expression/Call.php b/vendor/twig/twig/lib/Twig/Node/Expression/Call.php index d962b6a501d6ca4ed6c11d271d3befdb547618ca..019ddf7b85db59ea9e1bb76014578802b452af34 100644 --- a/vendor/twig/twig/lib/Twig/Node/Expression/Call.php +++ b/vendor/twig/twig/lib/Twig/Node/Expression/Call.php @@ -1,291 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ -abstract class Twig_Node_Expression_Call extends Twig_Node_Expression -{ - private $reflector; +use Twig\Node\Expression\CallExpression; - protected function compileCallable(Twig_Compiler $compiler) - { - $closingParenthesis = false; - if ($this->hasAttribute('callable') && $callable = $this->getAttribute('callable')) { - if (is_string($callable) && false === strpos($callable, '::')) { - $compiler->raw($callable); - } else { - list($r, $callable) = $this->reflectCallable($callable); - if ($r instanceof ReflectionMethod && is_string($callable[0])) { - if ($r->isStatic()) { - $compiler->raw(sprintf('%s::%s', $callable[0], $callable[1])); - } else { - $compiler->raw(sprintf('$this->env->getRuntime(\'%s\')->%s', $callable[0], $callable[1])); - } - } elseif ($r instanceof ReflectionMethod && $callable[0] instanceof Twig_ExtensionInterface) { - $compiler->raw(sprintf('$this->env->getExtension(\'%s\')->%s', get_class($callable[0]), $callable[1])); - } else { - $type = ucfirst($this->getAttribute('type')); - $compiler->raw(sprintf('call_user_func_array($this->env->get%s(\'%s\')->getCallable(), array', $type, $this->getAttribute('name'))); - $closingParenthesis = true; - } - } - } else { - $compiler->raw($this->getAttribute('thing')->compile()); - } - - $this->compileArguments($compiler); - - if ($closingParenthesis) { - $compiler->raw(')'); - } - } +class_exists('Twig\Node\Expression\CallExpression'); - protected function compileArguments(Twig_Compiler $compiler) +if (\false) { + class Twig_Node_Expression_Call extends CallExpression { - $compiler->raw('('); - - $first = true; - - if ($this->hasAttribute('needs_environment') && $this->getAttribute('needs_environment')) { - $compiler->raw('$this->env'); - $first = false; - } - - if ($this->hasAttribute('needs_context') && $this->getAttribute('needs_context')) { - if (!$first) { - $compiler->raw(', '); - } - $compiler->raw('$context'); - $first = false; - } - - if ($this->hasAttribute('arguments')) { - foreach ($this->getAttribute('arguments') as $argument) { - if (!$first) { - $compiler->raw(', '); - } - $compiler->string($argument); - $first = false; - } - } - - if ($this->hasNode('node')) { - if (!$first) { - $compiler->raw(', '); - } - $compiler->subcompile($this->getNode('node')); - $first = false; - } - - if ($this->hasNode('arguments')) { - $callable = $this->hasAttribute('callable') ? $this->getAttribute('callable') : null; - - $arguments = $this->getArguments($callable, $this->getNode('arguments')); - - foreach ($arguments as $node) { - if (!$first) { - $compiler->raw(', '); - } - $compiler->subcompile($node); - $first = false; - } - } - - $compiler->raw(')'); - } - - protected function getArguments($callable, $arguments) - { - $callType = $this->getAttribute('type'); - $callName = $this->getAttribute('name'); - - $parameters = array(); - $named = false; - foreach ($arguments as $name => $node) { - if (!is_int($name)) { - $named = true; - $name = $this->normalizeName($name); - } elseif ($named) { - throw new Twig_Error_Syntax(sprintf('Positional arguments cannot be used after named arguments for %s "%s".', $callType, $callName)); - } - - $parameters[$name] = $node; - } - - $isVariadic = $this->hasAttribute('is_variadic') && $this->getAttribute('is_variadic'); - if (!$named && !$isVariadic) { - return $parameters; - } - - if (!$callable) { - if ($named) { - $message = sprintf('Named arguments are not supported for %s "%s".', $callType, $callName); - } else { - $message = sprintf('Arbitrary positional arguments are not supported for %s "%s".', $callType, $callName); - } - - throw new LogicException($message); - } - - $callableParameters = $this->getCallableParameters($callable, $isVariadic); - $arguments = array(); - $names = array(); - $missingArguments = array(); - $optionalArguments = array(); - $pos = 0; - foreach ($callableParameters as $callableParameter) { - $names[] = $name = $this->normalizeName($callableParameter->name); - - if (array_key_exists($name, $parameters)) { - if (array_key_exists($pos, $parameters)) { - throw new Twig_Error_Syntax(sprintf('Argument "%s" is defined twice for %s "%s".', $name, $callType, $callName)); - } - - if (count($missingArguments)) { - throw new Twig_Error_Syntax(sprintf( - 'Argument "%s" could not be assigned for %s "%s(%s)" because it is mapped to an internal PHP function which cannot determine default value for optional argument%s "%s".', - $name, $callType, $callName, implode(', ', $names), count($missingArguments) > 1 ? 's' : '', implode('", "', $missingArguments)) - ); - } - - $arguments = array_merge($arguments, $optionalArguments); - $arguments[] = $parameters[$name]; - unset($parameters[$name]); - $optionalArguments = array(); - } elseif (array_key_exists($pos, $parameters)) { - $arguments = array_merge($arguments, $optionalArguments); - $arguments[] = $parameters[$pos]; - unset($parameters[$pos]); - $optionalArguments = array(); - ++$pos; - } elseif ($callableParameter->isDefaultValueAvailable()) { - $optionalArguments[] = new Twig_Node_Expression_Constant($callableParameter->getDefaultValue(), -1); - } elseif ($callableParameter->isOptional()) { - if (empty($parameters)) { - break; - } else { - $missingArguments[] = $name; - } - } else { - throw new Twig_Error_Syntax(sprintf('Value for argument "%s" is required for %s "%s".', $name, $callType, $callName)); - } - } - - if ($isVariadic) { - $arbitraryArguments = new Twig_Node_Expression_Array(array(), -1); - foreach ($parameters as $key => $value) { - if (is_int($key)) { - $arbitraryArguments->addElement($value); - } else { - $arbitraryArguments->addElement($value, new Twig_Node_Expression_Constant($key, -1)); - } - unset($parameters[$key]); - } - - if ($arbitraryArguments->count()) { - $arguments = array_merge($arguments, $optionalArguments); - $arguments[] = $arbitraryArguments; - } - } - - if (!empty($parameters)) { - $unknownParameter = null; - foreach ($parameters as $parameter) { - if ($parameter instanceof Twig_Node) { - $unknownParameter = $parameter; - break; - } - } - - throw new Twig_Error_Syntax(sprintf( - 'Unknown argument%s "%s" for %s "%s(%s)".', - count($parameters) > 1 ? 's' : '', implode('", "', array_keys($parameters)), $callType, $callName, implode(', ', $names) - ), $unknownParameter ? $unknownParameter->getTemplateLine() : -1); - } - - return $arguments; - } - - protected function normalizeName($name) - { - return strtolower(preg_replace(array('/([A-Z]+)([A-Z][a-z])/', '/([a-z\d])([A-Z])/'), array('\\1_\\2', '\\1_\\2'), $name)); - } - - private function getCallableParameters($callable, $isVariadic) - { - list($r) = $this->reflectCallable($callable); - if (null === $r) { - return array(); - } - - $parameters = $r->getParameters(); - if ($this->hasNode('node')) { - array_shift($parameters); - } - if ($this->hasAttribute('needs_environment') && $this->getAttribute('needs_environment')) { - array_shift($parameters); - } - if ($this->hasAttribute('needs_context') && $this->getAttribute('needs_context')) { - array_shift($parameters); - } - if ($this->hasAttribute('arguments') && null !== $this->getAttribute('arguments')) { - foreach ($this->getAttribute('arguments') as $argument) { - array_shift($parameters); - } - } - if ($isVariadic) { - $argument = end($parameters); - if ($argument && $argument->isArray() && $argument->isDefaultValueAvailable() && array() === $argument->getDefaultValue()) { - array_pop($parameters); - } else { - $callableName = $r->name; - if ($r instanceof ReflectionMethod) { - $callableName = $r->getDeclaringClass()->name.'::'.$callableName; - } - - throw new LogicException(sprintf('The last parameter of "%s" for %s "%s" must be an array with default value, eg. "array $arg = array()".', $callableName, $this->getAttribute('type'), $this->getAttribute('name'))); - } - } - - return $parameters; - } - - private function reflectCallable($callable) - { - if (null !== $this->reflector) { - return $this->reflector; - } - - if (is_array($callable)) { - if (!method_exists($callable[0], $callable[1])) { - // __call() - return array(null, array()); - } - $r = new ReflectionMethod($callable[0], $callable[1]); - } elseif (is_object($callable) && !$callable instanceof Closure) { - $r = new ReflectionObject($callable); - $r = $r->getMethod('__invoke'); - $callable = array($callable, '__invoke'); - } elseif (is_string($callable) && false !== $pos = strpos($callable, '::')) { - $class = substr($callable, 0, $pos); - $method = substr($callable, $pos + 2); - if (!method_exists($class, $method)) { - // __staticCall() - return array(null, array()); - } - $r = new ReflectionMethod($callable); - $callable = array($class, $method); - } else { - $r = new ReflectionFunction($callable); - } - - return $this->reflector = array($r, $callable); } } - -class_alias('Twig_Node_Expression_Call', 'Twig\Node\Expression\CallExpression', false); diff --git a/vendor/twig/twig/lib/Twig/Node/Expression/Conditional.php b/vendor/twig/twig/lib/Twig/Node/Expression/Conditional.php index c339d773c05b4ae8185c921f4240f262ed8d101d..308df26f0f8c826bbd798799f5bccf361db13bfb 100644 --- a/vendor/twig/twig/lib/Twig/Node/Expression/Conditional.php +++ b/vendor/twig/twig/lib/Twig/Node/Expression/Conditional.php @@ -1,33 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * (c) Armin Ronacher - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ -class Twig_Node_Expression_Conditional extends Twig_Node_Expression -{ - public function __construct(Twig_Node_Expression $expr1, Twig_Node_Expression $expr2, Twig_Node_Expression $expr3, $lineno) - { - parent::__construct(array('expr1' => $expr1, 'expr2' => $expr2, 'expr3' => $expr3), array(), $lineno); - } +use Twig\Node\Expression\ConditionalExpression; - public function compile(Twig_Compiler $compiler) +class_exists('Twig\Node\Expression\ConditionalExpression'); + +if (\false) { + class Twig_Node_Expression_Conditional extends ConditionalExpression { - $compiler - ->raw('((') - ->subcompile($this->getNode('expr1')) - ->raw(') ? (') - ->subcompile($this->getNode('expr2')) - ->raw(') : (') - ->subcompile($this->getNode('expr3')) - ->raw('))') - ; } } - -class_alias('Twig_Node_Expression_Conditional', 'Twig\Node\Expression\ConditionalExpression', false); diff --git a/vendor/twig/twig/lib/Twig/Node/Expression/Constant.php b/vendor/twig/twig/lib/Twig/Node/Expression/Constant.php index bf4d031cf92dce334d1b1b7f572ac18f0dff62c5..435ccdd79f7a546c3376feba21cb75b5a546d214 100644 --- a/vendor/twig/twig/lib/Twig/Node/Expression/Constant.php +++ b/vendor/twig/twig/lib/Twig/Node/Expression/Constant.php @@ -1,25 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * (c) Armin Ronacher - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ -class Twig_Node_Expression_Constant extends Twig_Node_Expression -{ - public function __construct($value, $lineno) - { - parent::__construct(array(), array('value' => $value), $lineno); - } +use Twig\Node\Expression\ConstantExpression; - public function compile(Twig_Compiler $compiler) +class_exists('Twig\Node\Expression\ConstantExpression'); + +if (\false) { + class Twig_Node_Expression_Constant extends ConstantExpression { - $compiler->repr($this->getAttribute('value')); } } - -class_alias('Twig_Node_Expression_Constant', 'Twig\Node\Expression\ConstantExpression', false); diff --git a/vendor/twig/twig/lib/Twig/Node/Expression/ExtensionReference.php b/vendor/twig/twig/lib/Twig/Node/Expression/ExtensionReference.php index 114b5cd975ff23f5f701e91be17052ed29700094..9b8927a317fa0a782c6d50180207ccbf6a3353a4 100644 --- a/vendor/twig/twig/lib/Twig/Node/Expression/ExtensionReference.php +++ b/vendor/twig/twig/lib/Twig/Node/Expression/ExtensionReference.php @@ -9,6 +9,9 @@ * file that was distributed with this source code. */ +use Twig\Compiler; +use Twig\Node\Expression\AbstractExpression; + @trigger_error('The Twig_Node_Expression_ExtensionReference class is deprecated since version 1.23 and will be removed in 2.0.', E_USER_DEPRECATED); /** @@ -18,14 +21,14 @@ * * @deprecated since 1.23 and will be removed in 2.0. */ -class Twig_Node_Expression_ExtensionReference extends Twig_Node_Expression +class Twig_Node_Expression_ExtensionReference extends AbstractExpression { public function __construct($name, $lineno, $tag = null) { - parent::__construct(array(), array('name' => $name), $lineno, $tag); + parent::__construct([], ['name' => $name], $lineno, $tag); } - public function compile(Twig_Compiler $compiler) + public function compile(Compiler $compiler) { $compiler->raw(sprintf("\$this->env->getExtension('%s')", $this->getAttribute('name'))); } diff --git a/vendor/twig/twig/lib/Twig/Node/Expression/Filter.php b/vendor/twig/twig/lib/Twig/Node/Expression/Filter.php index 12da1d676110bbfe6078745caf04aae212f9302f..85705715e9cc79a320821212739694b5e2390687 100644 --- a/vendor/twig/twig/lib/Twig/Node/Expression/Filter.php +++ b/vendor/twig/twig/lib/Twig/Node/Expression/Filter.php @@ -1,41 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * (c) Armin Ronacher - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ -class Twig_Node_Expression_Filter extends Twig_Node_Expression_Call -{ - public function __construct(Twig_NodeInterface $node, Twig_Node_Expression_Constant $filterName, Twig_NodeInterface $arguments, $lineno, $tag = null) - { - parent::__construct(array('node' => $node, 'filter' => $filterName, 'arguments' => $arguments), array(), $lineno, $tag); - } - - public function compile(Twig_Compiler $compiler) - { - $name = $this->getNode('filter')->getAttribute('value'); - $filter = $compiler->getEnvironment()->getFilter($name); +use Twig\Node\Expression\FilterExpression; - $this->setAttribute('name', $name); - $this->setAttribute('type', 'filter'); - $this->setAttribute('thing', $filter); - $this->setAttribute('needs_environment', $filter->needsEnvironment()); - $this->setAttribute('needs_context', $filter->needsContext()); - $this->setAttribute('arguments', $filter->getArguments()); - if ($filter instanceof Twig_FilterCallableInterface || $filter instanceof Twig_SimpleFilter) { - $this->setAttribute('callable', $filter->getCallable()); - } - if ($filter instanceof Twig_SimpleFilter) { - $this->setAttribute('is_variadic', $filter->isVariadic()); - } +class_exists('Twig\Node\Expression\FilterExpression'); - $this->compileCallable($compiler); +if (\false) { + class Twig_Node_Expression_Filter extends FilterExpression + { } } - -class_alias('Twig_Node_Expression_Filter', 'Twig\Node\Expression\FilterExpression', false); diff --git a/vendor/twig/twig/lib/Twig/Node/Expression/Filter/Default.php b/vendor/twig/twig/lib/Twig/Node/Expression/Filter/Default.php index d2e19d54ef9d19bb9d574e81f78713a3e3090cb3..9688743f28d0a7c98637de81ff1887e1c1f42859 100644 --- a/vendor/twig/twig/lib/Twig/Node/Expression/Filter/Default.php +++ b/vendor/twig/twig/lib/Twig/Node/Expression/Filter/Default.php @@ -1,45 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +use Twig\Node\Expression\Filter\DefaultFilter; -/** - * Returns the value or the default value when it is undefined or empty. - * - * <pre> - * {{ var.foo|default('foo item on var is not defined') }} - * </pre> - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class Twig_Node_Expression_Filter_Default extends Twig_Node_Expression_Filter -{ - public function __construct(Twig_NodeInterface $node, Twig_Node_Expression_Constant $filterName, Twig_NodeInterface $arguments, $lineno, $tag = null) - { - $default = new Twig_Node_Expression_Filter($node, new Twig_Node_Expression_Constant('default', $node->getTemplateLine()), $arguments, $node->getTemplateLine()); - - if ('default' === $filterName->getAttribute('value') && ($node instanceof Twig_Node_Expression_Name || $node instanceof Twig_Node_Expression_GetAttr)) { - $test = new Twig_Node_Expression_Test_Defined(clone $node, 'defined', new Twig_Node(), $node->getTemplateLine()); - $false = count($arguments) ? $arguments->getNode(0) : new Twig_Node_Expression_Constant('', $node->getTemplateLine()); - - $node = new Twig_Node_Expression_Conditional($test, $default, $false, $node->getTemplateLine()); - } else { - $node = $default; - } +class_exists('Twig\Node\Expression\Filter\DefaultFilter'); - parent::__construct($node, $filterName, $arguments, $lineno, $tag); - } - - public function compile(Twig_Compiler $compiler) +if (\false) { + class Twig_Node_Expression_Filter_Default extends DefaultFilter { - $compiler->subcompile($this->getNode('node')); } } - -class_alias('Twig_Node_Expression_Filter_Default', 'Twig\Node\Expression\Filter\DefaultFilter', false); diff --git a/vendor/twig/twig/lib/Twig/Node/Expression/Function.php b/vendor/twig/twig/lib/Twig/Node/Expression/Function.php index cdee7c97220868615e84c70a83073387a6c62211..5d408e46aef7094369fe4ce6befab9326efc9241 100644 --- a/vendor/twig/twig/lib/Twig/Node/Expression/Function.php +++ b/vendor/twig/twig/lib/Twig/Node/Expression/Function.php @@ -1,45 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ -class Twig_Node_Expression_Function extends Twig_Node_Expression_Call -{ - public function __construct($name, Twig_NodeInterface $arguments, $lineno) - { - parent::__construct(array('arguments' => $arguments), array('name' => $name, 'is_defined_test' => false), $lineno); - } - - public function compile(Twig_Compiler $compiler) - { - $name = $this->getAttribute('name'); - $function = $compiler->getEnvironment()->getFunction($name); +use Twig\Node\Expression\FunctionExpression; - $this->setAttribute('name', $name); - $this->setAttribute('type', 'function'); - $this->setAttribute('thing', $function); - $this->setAttribute('needs_environment', $function->needsEnvironment()); - $this->setAttribute('needs_context', $function->needsContext()); - $this->setAttribute('arguments', $function->getArguments()); - if ($function instanceof Twig_FunctionCallableInterface || $function instanceof Twig_SimpleFunction) { - $callable = $function->getCallable(); - if ('constant' === $name && $this->getAttribute('is_defined_test')) { - $callable = 'twig_constant_is_defined'; - } +class_exists('Twig\Node\Expression\FunctionExpression'); - $this->setAttribute('callable', $callable); - } - if ($function instanceof Twig_SimpleFunction) { - $this->setAttribute('is_variadic', $function->isVariadic()); - } - - $this->compileCallable($compiler); +if (\false) { + class Twig_Node_Expression_Function extends FunctionExpression + { } } - -class_alias('Twig_Node_Expression_Function', 'Twig\Node\Expression\FunctionExpression', false); diff --git a/vendor/twig/twig/lib/Twig/Node/Expression/GetAttr.php b/vendor/twig/twig/lib/Twig/Node/Expression/GetAttr.php index b7823accb935bddd7028aa01094c383acc231792..7b99eb376d71845fb51f235497006d5d509368e9 100644 --- a/vendor/twig/twig/lib/Twig/Node/Expression/GetAttr.php +++ b/vendor/twig/twig/lib/Twig/Node/Expression/GetAttr.php @@ -1,74 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * (c) Armin Ronacher - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ -class Twig_Node_Expression_GetAttr extends Twig_Node_Expression -{ - public function __construct(Twig_Node_Expression $node, Twig_Node_Expression $attribute, Twig_Node_Expression $arguments = null, $type, $lineno) - { - $nodes = array('node' => $node, 'attribute' => $attribute); - if (null !== $arguments) { - $nodes['arguments'] = $arguments; - } +use Twig\Node\Expression\GetAttrExpression; - parent::__construct($nodes, array('type' => $type, 'is_defined_test' => false, 'ignore_strict_check' => false, 'disable_c_ext' => false), $lineno); - } +class_exists('Twig\Node\Expression\GetAttrExpression'); - public function compile(Twig_Compiler $compiler) +if (\false) { + class Twig_Node_Expression_GetAttr extends GetAttrExpression { - if ($this->getAttribute('disable_c_ext')) { - @trigger_error(sprintf('Using the "disable_c_ext" attribute on %s is deprecated since version 1.30 and will be removed in 2.0.', __CLASS__), E_USER_DEPRECATED); - } - - if (function_exists('twig_template_get_attributes') && !$this->getAttribute('disable_c_ext')) { - $compiler->raw('twig_template_get_attributes($this, '); - } else { - $compiler->raw('$this->getAttribute('); - } - - if ($this->getAttribute('ignore_strict_check')) { - $this->getNode('node')->setAttribute('ignore_strict_check', true); - } - - $compiler->subcompile($this->getNode('node')); - - $compiler->raw(', ')->subcompile($this->getNode('attribute')); - - // only generate optional arguments when needed (to make generated code more readable) - $needFourth = $this->getAttribute('ignore_strict_check'); - $needThird = $needFourth || $this->getAttribute('is_defined_test'); - $needSecond = $needThird || Twig_Template::ANY_CALL !== $this->getAttribute('type'); - $needFirst = $needSecond || $this->hasNode('arguments'); - - if ($needFirst) { - if ($this->hasNode('arguments')) { - $compiler->raw(', ')->subcompile($this->getNode('arguments')); - } else { - $compiler->raw(', array()'); - } - } - - if ($needSecond) { - $compiler->raw(', ')->repr($this->getAttribute('type')); - } - - if ($needThird) { - $compiler->raw(', ')->repr($this->getAttribute('is_defined_test')); - } - - if ($needFourth) { - $compiler->raw(', ')->repr($this->getAttribute('ignore_strict_check')); - } - - $compiler->raw(')'); } } - -class_alias('Twig_Node_Expression_GetAttr', 'Twig\Node\Expression\GetAttrExpression', false); diff --git a/vendor/twig/twig/lib/Twig/Node/Expression/MethodCall.php b/vendor/twig/twig/lib/Twig/Node/Expression/MethodCall.php index 709016eb225b620ba4ac01dc2824ef20911db844..5b0cef8c4371f6748ff0c2458fb33cef2687c613 100644 --- a/vendor/twig/twig/lib/Twig/Node/Expression/MethodCall.php +++ b/vendor/twig/twig/lib/Twig/Node/Expression/MethodCall.php @@ -1,43 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ -class Twig_Node_Expression_MethodCall extends Twig_Node_Expression -{ - public function __construct(Twig_Node_Expression $node, $method, Twig_Node_Expression_Array $arguments, $lineno) - { - parent::__construct(array('node' => $node, 'arguments' => $arguments), array('method' => $method, 'safe' => false), $lineno); +use Twig\Node\Expression\MethodCallExpression; - if ($node instanceof Twig_Node_Expression_Name) { - $node->setAttribute('always_defined', true); - } - } +class_exists('Twig\Node\Expression\MethodCallExpression'); - public function compile(Twig_Compiler $compiler) +if (\false) { + class Twig_Node_Expression_MethodCall extends MethodCallExpression { - $compiler - ->subcompile($this->getNode('node')) - ->raw('->') - ->raw($this->getAttribute('method')) - ->raw('(') - ; - $first = true; - foreach ($this->getNode('arguments')->getKeyValuePairs() as $pair) { - if (!$first) { - $compiler->raw(', '); - } - $first = false; - - $compiler->subcompile($pair['value']); - } - $compiler->raw(')'); } } - -class_alias('Twig_Node_Expression_MethodCall', 'Twig\Node\Expression\MethodCallExpression', false); diff --git a/vendor/twig/twig/lib/Twig/Node/Expression/Name.php b/vendor/twig/twig/lib/Twig/Node/Expression/Name.php index 9d5a21f87d768bab9d151e85aadeb64bd30b222f..3b41ff9fc7c8dda0da670285b34bfba229f54f4f 100644 --- a/vendor/twig/twig/lib/Twig/Node/Expression/Name.php +++ b/vendor/twig/twig/lib/Twig/Node/Expression/Name.php @@ -1,102 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * (c) Armin Ronacher - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ -class Twig_Node_Expression_Name extends Twig_Node_Expression -{ - protected $specialVars = array( - '_self' => '$this', - '_context' => '$context', - '_charset' => '$this->env->getCharset()', - ); +use Twig\Node\Expression\NameExpression; - public function __construct($name, $lineno) - { - parent::__construct(array(), array('name' => $name, 'is_defined_test' => false, 'ignore_strict_check' => false, 'always_defined' => false), $lineno); - } +class_exists('Twig\Node\Expression\NameExpression'); - public function compile(Twig_Compiler $compiler) +if (\false) { + class Twig_Node_Expression_Name extends NameExpression { - $name = $this->getAttribute('name'); - - $compiler->addDebugInfo($this); - - if ($this->getAttribute('is_defined_test')) { - if ($this->isSpecial()) { - $compiler->repr(true); - } else { - $compiler->raw('array_key_exists(')->repr($name)->raw(', $context)'); - } - } elseif ($this->isSpecial()) { - $compiler->raw($this->specialVars[$name]); - } elseif ($this->getAttribute('always_defined')) { - $compiler - ->raw('$context[') - ->string($name) - ->raw(']') - ; - } else { - if (PHP_VERSION_ID >= 70000) { - // use PHP 7 null coalescing operator - $compiler - ->raw('($context[') - ->string($name) - ->raw('] ?? ') - ; - - if ($this->getAttribute('ignore_strict_check') || !$compiler->getEnvironment()->isStrictVariables()) { - $compiler->raw('null)'); - } else { - $compiler->raw('$this->getContext($context, ')->string($name)->raw('))'); - } - } elseif (PHP_VERSION_ID >= 50400) { - // PHP 5.4 ternary operator performance was optimized - $compiler - ->raw('(isset($context[') - ->string($name) - ->raw(']) ? $context[') - ->string($name) - ->raw('] : ') - ; - - if ($this->getAttribute('ignore_strict_check') || !$compiler->getEnvironment()->isStrictVariables()) { - $compiler->raw('null)'); - } else { - $compiler->raw('$this->getContext($context, ')->string($name)->raw('))'); - } - } else { - $compiler - ->raw('$this->getContext($context, ') - ->string($name) - ; - - if ($this->getAttribute('ignore_strict_check')) { - $compiler->raw(', true'); - } - - $compiler - ->raw(')') - ; - } - } - } - - public function isSpecial() - { - return isset($this->specialVars[$this->getAttribute('name')]); - } - - public function isSimple() - { - return !$this->isSpecial() && !$this->getAttribute('is_defined_test'); } } - -class_alias('Twig_Node_Expression_Name', 'Twig\Node\Expression\NameExpression', false); diff --git a/vendor/twig/twig/lib/Twig/Node/Expression/NullCoalesce.php b/vendor/twig/twig/lib/Twig/Node/Expression/NullCoalesce.php index eaafa4c91ead2eee83ce5c1c9595561b0d8ebd66..89d6bf6a5011b7f7cdd55c773595efcbf9639b83 100644 --- a/vendor/twig/twig/lib/Twig/Node/Expression/NullCoalesce.php +++ b/vendor/twig/twig/lib/Twig/Node/Expression/NullCoalesce.php @@ -1,48 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ -class Twig_Node_Expression_NullCoalesce extends Twig_Node_Expression_Conditional -{ - public function __construct(Twig_NodeInterface $left, Twig_NodeInterface $right, $lineno) - { - $test = new Twig_Node_Expression_Binary_And( - new Twig_Node_Expression_Test_Defined(clone $left, 'defined', new Twig_Node(), $left->getTemplateLine()), - new Twig_Node_Expression_Unary_Not(new Twig_Node_Expression_Test_Null($left, 'null', new Twig_Node(), $left->getTemplateLine()), $left->getTemplateLine()), - $left->getTemplateLine() - ); +use Twig\Node\Expression\NullCoalesceExpression; - parent::__construct($test, $left, $right, $lineno); - } +class_exists('Twig\Node\Expression\NullCoalesceExpression'); - public function compile(Twig_Compiler $compiler) +if (\false) { + class Twig_Node_Expression_NullCoalesce extends NullCoalesceExpression { - /* - * This optimizes only one case. PHP 7 also supports more complex expressions - * that can return null. So, for instance, if log is defined, log("foo") ?? "..." works, - * but log($a["foo"]) ?? "..." does not if $a["foo"] is not defined. More advanced - * cases might be implemented as an optimizer node visitor, but has not been done - * as benefits are probably not worth the added complexity. - */ - if (PHP_VERSION_ID >= 70000 && $this->getNode('expr2') instanceof Twig_Node_Expression_Name) { - $this->getNode('expr2')->setAttribute('always_defined', true); - $compiler - ->raw('((') - ->subcompile($this->getNode('expr2')) - ->raw(') ?? (') - ->subcompile($this->getNode('expr3')) - ->raw('))') - ; - } else { - parent::compile($compiler); - } } } - -class_alias('Twig_Node_Expression_NullCoalesce', 'Twig\Node\Expression\NullCoalesceExpression', false); diff --git a/vendor/twig/twig/lib/Twig/Node/Expression/Parent.php b/vendor/twig/twig/lib/Twig/Node/Expression/Parent.php index 78692db293d7b3ee3df900e2796f28148881928e..236c79fd4d40baa881e0d5d08379d7645c000f96 100644 --- a/vendor/twig/twig/lib/Twig/Node/Expression/Parent.php +++ b/vendor/twig/twig/lib/Twig/Node/Expression/Parent.php @@ -1,44 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * (c) Armin Ronacher - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +use Twig\Node\Expression\ParentExpression; -/** - * Represents a parent node. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class Twig_Node_Expression_Parent extends Twig_Node_Expression -{ - public function __construct($name, $lineno, $tag = null) - { - parent::__construct(array(), array('output' => false, 'name' => $name), $lineno, $tag); - } +class_exists('Twig\Node\Expression\ParentExpression'); - public function compile(Twig_Compiler $compiler) +if (\false) { + class Twig_Node_Expression_Parent extends ParentExpression { - if ($this->getAttribute('output')) { - $compiler - ->addDebugInfo($this) - ->write('$this->displayParentBlock(') - ->string($this->getAttribute('name')) - ->raw(", \$context, \$blocks);\n") - ; - } else { - $compiler - ->raw('$this->renderParentBlock(') - ->string($this->getAttribute('name')) - ->raw(', $context, $blocks)') - ; - } } } - -class_alias('Twig_Node_Expression_Parent', 'Twig\Node\Expression\ParentExpression', false); diff --git a/vendor/twig/twig/lib/Twig/Node/Expression/TempName.php b/vendor/twig/twig/lib/Twig/Node/Expression/TempName.php index 0a86e003dcdcd4433f1b6b0f4b5610f7587e45d7..e77ebe06bb8ab6e136de98be6e05695fcedd2f76 100644 --- a/vendor/twig/twig/lib/Twig/Node/Expression/TempName.php +++ b/vendor/twig/twig/lib/Twig/Node/Expression/TempName.php @@ -1,28 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ -class Twig_Node_Expression_TempName extends Twig_Node_Expression -{ - public function __construct($name, $lineno) - { - parent::__construct(array(), array('name' => $name), $lineno); - } +use Twig\Node\Expression\TempNameExpression; - public function compile(Twig_Compiler $compiler) +class_exists('Twig\Node\Expression\TempNameExpression'); + +if (\false) { + class Twig_Node_Expression_TempName extends TempNameExpression { - $compiler - ->raw('$_') - ->raw($this->getAttribute('name')) - ->raw('_') - ; } } - -class_alias('Twig_Node_Expression_TempName', 'Twig\Node\Expression\TempNameExpression', false); diff --git a/vendor/twig/twig/lib/Twig/Node/Expression/Test.php b/vendor/twig/twig/lib/Twig/Node/Expression/Test.php index ad102ba60df5ae7737fede9bd9a483396b1727d5..9c300ba3f5fc4098d8eed1023c961bb1816b4acf 100644 --- a/vendor/twig/twig/lib/Twig/Node/Expression/Test.php +++ b/vendor/twig/twig/lib/Twig/Node/Expression/Test.php @@ -1,42 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ -class Twig_Node_Expression_Test extends Twig_Node_Expression_Call -{ - public function __construct(Twig_NodeInterface $node, $name, Twig_NodeInterface $arguments = null, $lineno) - { - $nodes = array('node' => $node); - if (null !== $arguments) { - $nodes['arguments'] = $arguments; - } +use Twig\Node\Expression\TestExpression; - parent::__construct($nodes, array('name' => $name), $lineno); - } +class_exists('Twig\Node\Expression\TestExpression'); - public function compile(Twig_Compiler $compiler) +if (\false) { + class Twig_Node_Expression_Test extends TestExpression { - $name = $this->getAttribute('name'); - $test = $compiler->getEnvironment()->getTest($name); - - $this->setAttribute('name', $name); - $this->setAttribute('type', 'test'); - $this->setAttribute('thing', $test); - if ($test instanceof Twig_TestCallableInterface || $test instanceof Twig_SimpleTest) { - $this->setAttribute('callable', $test->getCallable()); - } - if ($test instanceof Twig_SimpleTest) { - $this->setAttribute('is_variadic', $test->isVariadic()); - } - - $this->compileCallable($compiler); } } - -class_alias('Twig_Node_Expression_Test', 'Twig\Node\Expression\TestExpression', false); diff --git a/vendor/twig/twig/lib/Twig/Node/Expression/Test/Constant.php b/vendor/twig/twig/lib/Twig/Node/Expression/Test/Constant.php index a51a4ba133b3fed3cf7e34a1b6894b3fed5a22d8..bc796ec356439753862395f94836c1d4ae9a0b6e 100644 --- a/vendor/twig/twig/lib/Twig/Node/Expression/Test/Constant.php +++ b/vendor/twig/twig/lib/Twig/Node/Expression/Test/Constant.php @@ -1,48 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +use Twig\Node\Expression\Test\ConstantTest; -/** - * Checks if a variable is the exact same value as a constant. - * - * <pre> - * {% if post.status is constant('Post::PUBLISHED') %} - * the status attribute is exactly the same as Post::PUBLISHED - * {% endif %} - * </pre> - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class Twig_Node_Expression_Test_Constant extends Twig_Node_Expression_Test -{ - public function compile(Twig_Compiler $compiler) - { - $compiler - ->raw('(') - ->subcompile($this->getNode('node')) - ->raw(' === constant(') - ; - - if ($this->getNode('arguments')->hasNode(1)) { - $compiler - ->raw('get_class(') - ->subcompile($this->getNode('arguments')->getNode(1)) - ->raw(')."::".') - ; - } +class_exists('Twig\Node\Expression\Test\ConstantTest'); - $compiler - ->subcompile($this->getNode('arguments')->getNode(0)) - ->raw('))') - ; +if (\false) { + class Twig_Node_Expression_Test_Constant extends ConstantTest + { } } - -class_alias('Twig_Node_Expression_Test_Constant', 'Twig\Node\Expression\Test\ConstantTest', false); diff --git a/vendor/twig/twig/lib/Twig/Node/Expression/Test/Defined.php b/vendor/twig/twig/lib/Twig/Node/Expression/Test/Defined.php index 2136c3907a5df66467cd2bee788d2cbcdb16b8c3..759cb491a351eff1222fe84696b8272ea64f70eb 100644 --- a/vendor/twig/twig/lib/Twig/Node/Expression/Test/Defined.php +++ b/vendor/twig/twig/lib/Twig/Node/Expression/Test/Defined.php @@ -1,61 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +use Twig\Node\Expression\Test\DefinedTest; -/** - * Checks if a variable is defined in the current context. - * - * <pre> - * {# defined works with variable names and variable attributes #} - * {% if foo is defined %} - * {# ... #} - * {% endif %} - * </pre> - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class Twig_Node_Expression_Test_Defined extends Twig_Node_Expression_Test -{ - public function __construct(Twig_NodeInterface $node, $name, Twig_NodeInterface $arguments = null, $lineno) - { - if ($node instanceof Twig_Node_Expression_Name) { - $node->setAttribute('is_defined_test', true); - } elseif ($node instanceof Twig_Node_Expression_GetAttr) { - $node->setAttribute('is_defined_test', true); - $this->changeIgnoreStrictCheck($node); - } elseif ($node instanceof Twig_Node_Expression_BlockReference) { - $node->setAttribute('is_defined_test', true); - } elseif ($node instanceof Twig_Node_Expression_Function && 'constant' === $node->getAttribute('name')) { - $node->setAttribute('is_defined_test', true); - } elseif ($node instanceof Twig_Node_Expression_Constant || $node instanceof Twig_Node_Expression_Array) { - $node = new Twig_Node_Expression_Constant(true, $node->getTemplateLine()); - } else { - throw new Twig_Error_Syntax('The "defined" test only works with simple variables.', $this->getTemplateLine()); - } - - parent::__construct($node, $name, $arguments, $lineno); - } - - protected function changeIgnoreStrictCheck(Twig_Node_Expression_GetAttr $node) - { - $node->setAttribute('ignore_strict_check', true); - - if ($node->getNode('node') instanceof Twig_Node_Expression_GetAttr) { - $this->changeIgnoreStrictCheck($node->getNode('node')); - } - } +class_exists('Twig\Node\Expression\Test\DefinedTest'); - public function compile(Twig_Compiler $compiler) +if (\false) { + class Twig_Node_Expression_Test_Defined extends DefinedTest { - $compiler->subcompile($this->getNode('node')); } } - -class_alias('Twig_Node_Expression_Test_Defined', 'Twig\Node\Expression\Test\DefinedTest', false); diff --git a/vendor/twig/twig/lib/Twig/Node/Expression/Test/Divisibleby.php b/vendor/twig/twig/lib/Twig/Node/Expression/Test/Divisibleby.php index a5d71961a8e3a8aacb2f8ca07ba3c939d10c9318..c999e9e174b88a57cd8c2ec077c30ea96e1d4f4a 100644 --- a/vendor/twig/twig/lib/Twig/Node/Expression/Test/Divisibleby.php +++ b/vendor/twig/twig/lib/Twig/Node/Expression/Test/Divisibleby.php @@ -1,35 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +use Twig\Node\Expression\Test\DivisiblebyTest; -/** - * Checks if a variable is divisible by a number. - * - * <pre> - * {% if loop.index is divisible by(3) %} - * </pre> - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class Twig_Node_Expression_Test_Divisibleby extends Twig_Node_Expression_Test -{ - public function compile(Twig_Compiler $compiler) +class_exists('Twig\Node\Expression\Test\DivisiblebyTest'); + +if (\false) { + class Twig_Node_Expression_Test_Divisibleby extends DivisiblebyTest { - $compiler - ->raw('(0 == ') - ->subcompile($this->getNode('node')) - ->raw(' % ') - ->subcompile($this->getNode('arguments')->getNode(0)) - ->raw(')') - ; } } - -class_alias('Twig_Node_Expression_Test_Divisibleby', 'Twig\Node\Expression\Test\DivisiblebyTest', false); diff --git a/vendor/twig/twig/lib/Twig/Node/Expression/Test/Even.php b/vendor/twig/twig/lib/Twig/Node/Expression/Test/Even.php index 7e198bea67480f153346b714d92431ad86d9d2c2..a751079dbaa43852df005c8e97fbdf15a07e2522 100644 --- a/vendor/twig/twig/lib/Twig/Node/Expression/Test/Even.php +++ b/vendor/twig/twig/lib/Twig/Node/Expression/Test/Even.php @@ -1,34 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +use Twig\Node\Expression\Test\EvenTest; -/** - * Checks if a number is even. - * - * <pre> - * {{ var is even }} - * </pre> - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class Twig_Node_Expression_Test_Even extends Twig_Node_Expression_Test -{ - public function compile(Twig_Compiler $compiler) +class_exists('Twig\Node\Expression\Test\EvenTest'); + +if (\false) { + class Twig_Node_Expression_Test_Even extends EvenTest { - $compiler - ->raw('(') - ->subcompile($this->getNode('node')) - ->raw(' % 2 == 0') - ->raw(')') - ; } } - -class_alias('Twig_Node_Expression_Test_Even', 'Twig\Node\Expression\Test\EvenTest', false); diff --git a/vendor/twig/twig/lib/Twig/Node/Expression/Test/Null.php b/vendor/twig/twig/lib/Twig/Node/Expression/Test/Null.php index 3746e4cbd30f7e0b1a81a073c9a60ea03357c65a..404360ee2e151d4e8ad20087758aaae03accf603 100644 --- a/vendor/twig/twig/lib/Twig/Node/Expression/Test/Null.php +++ b/vendor/twig/twig/lib/Twig/Node/Expression/Test/Null.php @@ -1,33 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +use Twig\Node\Expression\Test\NullTest; -/** - * Checks that a variable is null. - * - * <pre> - * {{ var is none }} - * </pre> - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class Twig_Node_Expression_Test_Null extends Twig_Node_Expression_Test -{ - public function compile(Twig_Compiler $compiler) +class_exists('Twig\Node\Expression\Test\NullTest'); + +if (\false) { + class Twig_Node_Expression_Test_Null extends NullTest { - $compiler - ->raw('(null === ') - ->subcompile($this->getNode('node')) - ->raw(')') - ; } } - -class_alias('Twig_Node_Expression_Test_Null', 'Twig\Node\Expression\Test\NullTest', false); diff --git a/vendor/twig/twig/lib/Twig/Node/Expression/Test/Odd.php b/vendor/twig/twig/lib/Twig/Node/Expression/Test/Odd.php index 0c6c099bbcad430a9b272e9bcc0f7c4d8323a7dd..7a06ac59a5b86ec4282bf94a310422c904f06d00 100644 --- a/vendor/twig/twig/lib/Twig/Node/Expression/Test/Odd.php +++ b/vendor/twig/twig/lib/Twig/Node/Expression/Test/Odd.php @@ -1,34 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +use Twig\Node\Expression\Test\OddTest; -/** - * Checks if a number is odd. - * - * <pre> - * {{ var is odd }} - * </pre> - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class Twig_Node_Expression_Test_Odd extends Twig_Node_Expression_Test -{ - public function compile(Twig_Compiler $compiler) +class_exists('Twig\Node\Expression\Test\OddTest'); + +if (\false) { + class Twig_Node_Expression_Test_Odd extends OddTest { - $compiler - ->raw('(') - ->subcompile($this->getNode('node')) - ->raw(' % 2 == 1') - ->raw(')') - ; } } - -class_alias('Twig_Node_Expression_Test_Odd', 'Twig\Node\Expression\Test\OddTest', false); diff --git a/vendor/twig/twig/lib/Twig/Node/Expression/Test/Sameas.php b/vendor/twig/twig/lib/Twig/Node/Expression/Test/Sameas.php index e95ff1f20c7f4e0a67e3feb0bf361c113ca0a2ff..c937d712158e4647fec274bb7efbd58ab11f1a4a 100644 --- a/vendor/twig/twig/lib/Twig/Node/Expression/Test/Sameas.php +++ b/vendor/twig/twig/lib/Twig/Node/Expression/Test/Sameas.php @@ -1,31 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +use Twig\Node\Expression\Test\SameasTest; -/** - * Checks if a variable is the same as another one (=== in PHP). - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class Twig_Node_Expression_Test_Sameas extends Twig_Node_Expression_Test -{ - public function compile(Twig_Compiler $compiler) +class_exists('Twig\Node\Expression\Test\SameasTest'); + +if (\false) { + class Twig_Node_Expression_Test_Sameas extends SameasTest { - $compiler - ->raw('(') - ->subcompile($this->getNode('node')) - ->raw(' === ') - ->subcompile($this->getNode('arguments')->getNode(0)) - ->raw(')') - ; } } - -class_alias('Twig_Node_Expression_Test_Sameas', 'Twig\Node\Expression\Test\SameasTest', false); diff --git a/vendor/twig/twig/lib/Twig/Node/Expression/Unary.php b/vendor/twig/twig/lib/Twig/Node/Expression/Unary.php index 5804485e3ecaf31f036516edf48b7fcb289a8c8d..1969d2c7663bdfb23a183a98f8b0bca5e04ba331 100644 --- a/vendor/twig/twig/lib/Twig/Node/Expression/Unary.php +++ b/vendor/twig/twig/lib/Twig/Node/Expression/Unary.php @@ -1,29 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * (c) Armin Ronacher - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ -abstract class Twig_Node_Expression_Unary extends Twig_Node_Expression -{ - public function __construct(Twig_NodeInterface $node, $lineno) - { - parent::__construct(array('node' => $node), array(), $lineno); - } +use Twig\Node\Expression\Unary\AbstractUnary; + +class_exists('Twig\Node\Expression\Unary\AbstractUnary'); - public function compile(Twig_Compiler $compiler) +if (\false) { + class Twig_Node_Expression_Unary extends AbstractUnary { - $compiler->raw(' '); - $this->operator($compiler); - $compiler->subcompile($this->getNode('node')); } - - abstract public function operator(Twig_Compiler $compiler); } - -class_alias('Twig_Node_Expression_Unary', 'Twig\Node\Expression\Unary\AbstractUnary', false); diff --git a/vendor/twig/twig/lib/Twig/Node/Expression/Unary/Neg.php b/vendor/twig/twig/lib/Twig/Node/Expression/Unary/Neg.php index 039d933d9314f024a533f6addd746dcdaeb9f8c0..e6c25a01c4d7670e92e30e395369f9e0458ade94 100644 --- a/vendor/twig/twig/lib/Twig/Node/Expression/Unary/Neg.php +++ b/vendor/twig/twig/lib/Twig/Node/Expression/Unary/Neg.php @@ -1,20 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * (c) Armin Ronacher - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ -class Twig_Node_Expression_Unary_Neg extends Twig_Node_Expression_Unary -{ - public function operator(Twig_Compiler $compiler) +use Twig\Node\Expression\Unary\NegUnary; + +class_exists('Twig\Node\Expression\Unary\NegUnary'); + +if (\false) { + class Twig_Node_Expression_Unary_Neg extends NegUnary { - $compiler->raw('-'); } } - -class_alias('Twig_Node_Expression_Unary_Neg', 'Twig\Node\Expression\Unary\NegUnary', false); diff --git a/vendor/twig/twig/lib/Twig/Node/Expression/Unary/Not.php b/vendor/twig/twig/lib/Twig/Node/Expression/Unary/Not.php index a0860b1838e53b815de268b9ba3116361e08cb2e..669105f36862eaca541e07f56a6fe89e3f161fa7 100644 --- a/vendor/twig/twig/lib/Twig/Node/Expression/Unary/Not.php +++ b/vendor/twig/twig/lib/Twig/Node/Expression/Unary/Not.php @@ -1,20 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * (c) Armin Ronacher - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ -class Twig_Node_Expression_Unary_Not extends Twig_Node_Expression_Unary -{ - public function operator(Twig_Compiler $compiler) +use Twig\Node\Expression\Unary\NotUnary; + +class_exists('Twig\Node\Expression\Unary\NotUnary'); + +if (\false) { + class Twig_Node_Expression_Unary_Not extends NotUnary { - $compiler->raw('!'); } } - -class_alias('Twig_Node_Expression_Unary_Not', 'Twig\Node\Expression\Unary\NotUnary', false); diff --git a/vendor/twig/twig/lib/Twig/Node/Expression/Unary/Pos.php b/vendor/twig/twig/lib/Twig/Node/Expression/Unary/Pos.php index eeff5452fff98ddbf4218f34ef68edb1f583d09c..4e2bb504df01d98d8f2185a28168b686e1322a29 100644 --- a/vendor/twig/twig/lib/Twig/Node/Expression/Unary/Pos.php +++ b/vendor/twig/twig/lib/Twig/Node/Expression/Unary/Pos.php @@ -1,20 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * (c) Armin Ronacher - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ -class Twig_Node_Expression_Unary_Pos extends Twig_Node_Expression_Unary -{ - public function operator(Twig_Compiler $compiler) +use Twig\Node\Expression\Unary\PosUnary; + +class_exists('Twig\Node\Expression\Unary\PosUnary'); + +if (\false) { + class Twig_Node_Expression_Unary_Pos extends PosUnary { - $compiler->raw('+'); } } - -class_alias('Twig_Node_Expression_Unary_Pos', 'Twig\Node\Expression\Unary\PosUnary', false); diff --git a/vendor/twig/twig/lib/Twig/Node/Flush.php b/vendor/twig/twig/lib/Twig/Node/Flush.php index fcc461ac000a293d9a55b80cedad0fc431b65a06..92af475b74db4b820eafe43fc50029328217231a 100644 --- a/vendor/twig/twig/lib/Twig/Node/Flush.php +++ b/vendor/twig/twig/lib/Twig/Node/Flush.php @@ -1,33 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +use Twig\Node\FlushNode; -/** - * Represents a flush node. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class Twig_Node_Flush extends Twig_Node -{ - public function __construct($lineno, $tag) - { - parent::__construct(array(), array(), $lineno, $tag); - } +class_exists('Twig\Node\FlushNode'); - public function compile(Twig_Compiler $compiler) +if (\false) { + class Twig_Node_Flush extends FlushNode { - $compiler - ->addDebugInfo($this) - ->write("flush();\n") - ; } } - -class_alias('Twig_Node_Flush', 'Twig\Node\FlushNode', false); diff --git a/vendor/twig/twig/lib/Twig/Node/For.php b/vendor/twig/twig/lib/Twig/Node/For.php index 914b70c984a31dbd1bf00a0598fe2577415d22f0..c72aa782b11b081ce072f74c9ba4b29dfa78ab1f 100644 --- a/vendor/twig/twig/lib/Twig/Node/For.php +++ b/vendor/twig/twig/lib/Twig/Node/For.php @@ -1,113 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * (c) Armin Ronacher - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +use Twig\Node\ForNode; -/** - * Represents a for node. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class Twig_Node_For extends Twig_Node -{ - protected $loop; +class_exists('Twig\Node\ForNode'); - public function __construct(Twig_Node_Expression_AssignName $keyTarget, Twig_Node_Expression_AssignName $valueTarget, Twig_Node_Expression $seq, Twig_Node_Expression $ifexpr = null, Twig_NodeInterface $body, Twig_NodeInterface $else = null, $lineno, $tag = null) +if (\false) { + class Twig_Node_For extends ForNode { - $body = new Twig_Node(array($body, $this->loop = new Twig_Node_ForLoop($lineno, $tag))); - - if (null !== $ifexpr) { - $body = new Twig_Node_If(new Twig_Node(array($ifexpr, $body)), null, $lineno, $tag); - } - - $nodes = array('key_target' => $keyTarget, 'value_target' => $valueTarget, 'seq' => $seq, 'body' => $body); - if (null !== $else) { - $nodes['else'] = $else; - } - - parent::__construct($nodes, array('with_loop' => true, 'ifexpr' => null !== $ifexpr), $lineno, $tag); - } - - public function compile(Twig_Compiler $compiler) - { - $compiler - ->addDebugInfo($this) - ->write("\$context['_parent'] = \$context;\n") - ->write("\$context['_seq'] = twig_ensure_traversable(") - ->subcompile($this->getNode('seq')) - ->raw(");\n") - ; - - if ($this->hasNode('else')) { - $compiler->write("\$context['_iterated'] = false;\n"); - } - - if ($this->getAttribute('with_loop')) { - $compiler - ->write("\$context['loop'] = array(\n") - ->write(" 'parent' => \$context['_parent'],\n") - ->write(" 'index0' => 0,\n") - ->write(" 'index' => 1,\n") - ->write(" 'first' => true,\n") - ->write(");\n") - ; - - if (!$this->getAttribute('ifexpr')) { - $compiler - ->write("if (is_array(\$context['_seq']) || (is_object(\$context['_seq']) && \$context['_seq'] instanceof Countable)) {\n") - ->indent() - ->write("\$length = count(\$context['_seq']);\n") - ->write("\$context['loop']['revindex0'] = \$length - 1;\n") - ->write("\$context['loop']['revindex'] = \$length;\n") - ->write("\$context['loop']['length'] = \$length;\n") - ->write("\$context['loop']['last'] = 1 === \$length;\n") - ->outdent() - ->write("}\n") - ; - } - } - - $this->loop->setAttribute('else', $this->hasNode('else')); - $this->loop->setAttribute('with_loop', $this->getAttribute('with_loop')); - $this->loop->setAttribute('ifexpr', $this->getAttribute('ifexpr')); - - $compiler - ->write("foreach (\$context['_seq'] as ") - ->subcompile($this->getNode('key_target')) - ->raw(' => ') - ->subcompile($this->getNode('value_target')) - ->raw(") {\n") - ->indent() - ->subcompile($this->getNode('body')) - ->outdent() - ->write("}\n") - ; - - if ($this->hasNode('else')) { - $compiler - ->write("if (!\$context['_iterated']) {\n") - ->indent() - ->subcompile($this->getNode('else')) - ->outdent() - ->write("}\n") - ; - } - - $compiler->write("\$_parent = \$context['_parent'];\n"); - - // remove some "private" loop variables (needed for nested loops) - $compiler->write('unset($context[\'_seq\'], $context[\'_iterated\'], $context[\''.$this->getNode('key_target')->getAttribute('name').'\'], $context[\''.$this->getNode('value_target')->getAttribute('name').'\'], $context[\'_parent\'], $context[\'loop\']);'."\n"); - - // keep the values set in the inner context for variables defined in the outer context - $compiler->write("\$context = array_intersect_key(\$context, \$_parent) + \$_parent;\n"); } } - -class_alias('Twig_Node_For', 'Twig\Node\ForNode', false); diff --git a/vendor/twig/twig/lib/Twig/Node/ForLoop.php b/vendor/twig/twig/lib/Twig/Node/ForLoop.php index 06477cf1fe155668772fcb4839ee6145a6d0032c..5b21005270b9387d1fc6c2524070ef19ca8e4ef1 100644 --- a/vendor/twig/twig/lib/Twig/Node/ForLoop.php +++ b/vendor/twig/twig/lib/Twig/Node/ForLoop.php @@ -1,52 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +use Twig\Node\ForLoopNode; -/** - * Internal node used by the for node. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class Twig_Node_ForLoop extends Twig_Node -{ - public function __construct($lineno, $tag = null) - { - parent::__construct(array(), array('with_loop' => false, 'ifexpr' => false, 'else' => false), $lineno, $tag); - } +class_exists('Twig\Node\ForLoopNode'); - public function compile(Twig_Compiler $compiler) +if (\false) { + class Twig_Node_ForLoop extends ForLoopNode { - if ($this->getAttribute('else')) { - $compiler->write("\$context['_iterated'] = true;\n"); - } - - if ($this->getAttribute('with_loop')) { - $compiler - ->write("++\$context['loop']['index0'];\n") - ->write("++\$context['loop']['index'];\n") - ->write("\$context['loop']['first'] = false;\n") - ; - - if (!$this->getAttribute('ifexpr')) { - $compiler - ->write("if (isset(\$context['loop']['length'])) {\n") - ->indent() - ->write("--\$context['loop']['revindex0'];\n") - ->write("--\$context['loop']['revindex'];\n") - ->write("\$context['loop']['last'] = 0 === \$context['loop']['revindex0'];\n") - ->outdent() - ->write("}\n") - ; - } - } } } - -class_alias('Twig_Node_ForLoop', 'Twig\Node\ForLoopNode', false); diff --git a/vendor/twig/twig/lib/Twig/Node/If.php b/vendor/twig/twig/lib/Twig/Node/If.php index d82edec770d0cd1dc2ef72cd8253909030be0f6c..de884b345d8e51c9bd9edfd051c1bffb92dc4120 100644 --- a/vendor/twig/twig/lib/Twig/Node/If.php +++ b/vendor/twig/twig/lib/Twig/Node/If.php @@ -1,68 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * (c) Armin Ronacher - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +use Twig\Node\IfNode; -/** - * Represents an if node. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class Twig_Node_If extends Twig_Node -{ - public function __construct(Twig_NodeInterface $tests, Twig_NodeInterface $else = null, $lineno, $tag = null) - { - $nodes = array('tests' => $tests); - if (null !== $else) { - $nodes['else'] = $else; - } - - parent::__construct($nodes, array(), $lineno, $tag); - } +class_exists('Twig\Node\IfNode'); - public function compile(Twig_Compiler $compiler) +if (\false) { + class Twig_Node_If extends IfNode { - $compiler->addDebugInfo($this); - for ($i = 0, $count = count($this->getNode('tests')); $i < $count; $i += 2) { - if ($i > 0) { - $compiler - ->outdent() - ->write('} elseif (') - ; - } else { - $compiler - ->write('if (') - ; - } - - $compiler - ->subcompile($this->getNode('tests')->getNode($i)) - ->raw(") {\n") - ->indent() - ->subcompile($this->getNode('tests')->getNode($i + 1)) - ; - } - - if ($this->hasNode('else')) { - $compiler - ->outdent() - ->write("} else {\n") - ->indent() - ->subcompile($this->getNode('else')) - ; - } - - $compiler - ->outdent() - ->write("}\n"); } } - -class_alias('Twig_Node_If', 'Twig\Node\IfNode', false); diff --git a/vendor/twig/twig/lib/Twig/Node/Import.php b/vendor/twig/twig/lib/Twig/Node/Import.php index c77e320b72d362f5e2c37e2271c9af1409bc542a..9d3892a68c76ce85b0b0d41e30d3c56be6cb9c87 100644 --- a/vendor/twig/twig/lib/Twig/Node/Import.php +++ b/vendor/twig/twig/lib/Twig/Node/Import.php @@ -1,51 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +use Twig\Node\ImportNode; -/** - * Represents an import node. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class Twig_Node_Import extends Twig_Node -{ - public function __construct(Twig_Node_Expression $expr, Twig_Node_Expression $var, $lineno, $tag = null) - { - parent::__construct(array('expr' => $expr, 'var' => $var), array(), $lineno, $tag); - } +class_exists('Twig\Node\ImportNode'); - public function compile(Twig_Compiler $compiler) +if (\false) { + class Twig_Node_Import extends ImportNode { - $compiler - ->addDebugInfo($this) - ->write('') - ->subcompile($this->getNode('var')) - ->raw(' = ') - ; - - if ($this->getNode('expr') instanceof Twig_Node_Expression_Name && '_self' === $this->getNode('expr')->getAttribute('name')) { - $compiler->raw('$this'); - } else { - $compiler - ->raw('$this->loadTemplate(') - ->subcompile($this->getNode('expr')) - ->raw(', ') - ->repr($this->getTemplateName()) - ->raw(', ') - ->repr($this->getTemplateLine()) - ->raw(')') - ; - } - - $compiler->raw(";\n"); } } - -class_alias('Twig_Node_Import', 'Twig\Node\ImportNode', false); diff --git a/vendor/twig/twig/lib/Twig/Node/Include.php b/vendor/twig/twig/lib/Twig/Node/Include.php index 2a5114cb87aa521d8013160cbe50c735f23cb7b2..f43d203bc17ee8bf91aa83d02c2d50a64a5489ba 100644 --- a/vendor/twig/twig/lib/Twig/Node/Include.php +++ b/vendor/twig/twig/lib/Twig/Node/Include.php @@ -1,90 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * (c) Armin Ronacher - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +use Twig\Node\IncludeNode; -/** - * Represents an include node. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class Twig_Node_Include extends Twig_Node implements Twig_NodeOutputInterface -{ - public function __construct(Twig_Node_Expression $expr, Twig_Node_Expression $variables = null, $only = false, $ignoreMissing = false, $lineno, $tag = null) - { - $nodes = array('expr' => $expr); - if (null !== $variables) { - $nodes['variables'] = $variables; - } - - parent::__construct($nodes, array('only' => (bool) $only, 'ignore_missing' => (bool) $ignoreMissing), $lineno, $tag); - } - - public function compile(Twig_Compiler $compiler) - { - $compiler->addDebugInfo($this); - - if ($this->getAttribute('ignore_missing')) { - $compiler - ->write("try {\n") - ->indent() - ; - } - - $this->addGetTemplate($compiler); - - $compiler->raw('->display('); +class_exists('Twig\Node\IncludeNode'); - $this->addTemplateArguments($compiler); - - $compiler->raw(");\n"); - - if ($this->getAttribute('ignore_missing')) { - $compiler - ->outdent() - ->write("} catch (Twig_Error_Loader \$e) {\n") - ->indent() - ->write("// ignore missing template\n") - ->outdent() - ->write("}\n\n") - ; - } - } - - protected function addGetTemplate(Twig_Compiler $compiler) +if (\false) { + class Twig_Node_Include extends IncludeNode { - $compiler - ->write('$this->loadTemplate(') - ->subcompile($this->getNode('expr')) - ->raw(', ') - ->repr($this->getTemplateName()) - ->raw(', ') - ->repr($this->getTemplateLine()) - ->raw(')') - ; - } - - protected function addTemplateArguments(Twig_Compiler $compiler) - { - if (!$this->hasNode('variables')) { - $compiler->raw(false === $this->getAttribute('only') ? '$context' : 'array()'); - } elseif (false === $this->getAttribute('only')) { - $compiler - ->raw('array_merge($context, ') - ->subcompile($this->getNode('variables')) - ->raw(')') - ; - } else { - $compiler->subcompile($this->getNode('variables')); - } } } - -class_alias('Twig_Node_Include', 'Twig\Node\IncludeNode', false); diff --git a/vendor/twig/twig/lib/Twig/Node/Macro.php b/vendor/twig/twig/lib/Twig/Node/Macro.php index 3cf5497704459b312e88ef2bfd29d2ed896579af..8d2389dfcfbc74ce9c31d32cdde347f7d2b7f679 100644 --- a/vendor/twig/twig/lib/Twig/Node/Macro.php +++ b/vendor/twig/twig/lib/Twig/Node/Macro.php @@ -1,125 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +use Twig\Node\MacroNode; -/** - * Represents a macro node. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class Twig_Node_Macro extends Twig_Node -{ - const VARARGS_NAME = 'varargs'; +class_exists('Twig\Node\MacroNode'); - public function __construct($name, Twig_NodeInterface $body, Twig_NodeInterface $arguments, $lineno, $tag = null) +if (\false) { + class Twig_Node_Macro extends MacroNode { - foreach ($arguments as $argumentName => $argument) { - if (self::VARARGS_NAME === $argumentName) { - throw new Twig_Error_Syntax(sprintf('The argument "%s" in macro "%s" cannot be defined because the variable "%s" is reserved for arbitrary arguments.', self::VARARGS_NAME, $name, self::VARARGS_NAME), $argument->getTemplateLine()); - } - } - - parent::__construct(array('body' => $body, 'arguments' => $arguments), array('name' => $name), $lineno, $tag); - } - - public function compile(Twig_Compiler $compiler) - { - $compiler - ->addDebugInfo($this) - ->write(sprintf('public function get%s(', $this->getAttribute('name'))) - ; - - $count = count($this->getNode('arguments')); - $pos = 0; - foreach ($this->getNode('arguments') as $name => $default) { - $compiler - ->raw('$__'.$name.'__ = ') - ->subcompile($default) - ; - - if (++$pos < $count) { - $compiler->raw(', '); - } - } - - if (PHP_VERSION_ID >= 50600) { - if ($count) { - $compiler->raw(', '); - } - - $compiler->raw('...$__varargs__'); - } - - $compiler - ->raw(")\n") - ->write("{\n") - ->indent() - ; - - $compiler - ->write("\$context = \$this->env->mergeGlobals(array(\n") - ->indent() - ; - - foreach ($this->getNode('arguments') as $name => $default) { - $compiler - ->write('') - ->string($name) - ->raw(' => $__'.$name.'__') - ->raw(",\n") - ; - } - - $compiler - ->write('') - ->string(self::VARARGS_NAME) - ->raw(' => ') - ; - - if (PHP_VERSION_ID >= 50600) { - $compiler->raw("\$__varargs__,\n"); - } else { - $compiler - ->raw('func_num_args() > ') - ->repr($count) - ->raw(' ? array_slice(func_get_args(), ') - ->repr($count) - ->raw(") : array(),\n") - ; - } - - $compiler - ->outdent() - ->write("));\n\n") - ->write("\$blocks = array();\n\n") - ->write("ob_start();\n") - ->write("try {\n") - ->indent() - ->subcompile($this->getNode('body')) - ->outdent() - ->write("} catch (Exception \$e) {\n") - ->indent() - ->write("ob_end_clean();\n\n") - ->write("throw \$e;\n") - ->outdent() - ->write("} catch (Throwable \$e) {\n") - ->indent() - ->write("ob_end_clean();\n\n") - ->write("throw \$e;\n") - ->outdent() - ->write("}\n\n") - ->write("return ('' === \$tmp = ob_get_clean()) ? '' : new Twig_Markup(\$tmp, \$this->env->getCharset());\n") - ->outdent() - ->write("}\n\n") - ; } } - -class_alias('Twig_Node_Macro', 'Twig\Node\MacroNode', false); diff --git a/vendor/twig/twig/lib/Twig/Node/Module.php b/vendor/twig/twig/lib/Twig/Node/Module.php index 5cd8d0502f60c9de753d9eb23532743edd6f5349..ca5276750f6e9e5a072f024df17ad1fdbfaa09ec 100644 --- a/vendor/twig/twig/lib/Twig/Node/Module.php +++ b/vendor/twig/twig/lib/Twig/Node/Module.php @@ -1,461 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * (c) Armin Ronacher - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +use Twig\Node\ModuleNode; -/** - * Represents a module node. - * - * Consider this class as being final. If you need to customize the behavior of - * the generated class, consider adding nodes to the following nodes: display_start, - * display_end, constructor_start, constructor_end, and class_end. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class Twig_Node_Module extends Twig_Node -{ - private $source; +class_exists('Twig\Node\ModuleNode'); - public function __construct(Twig_NodeInterface $body, Twig_Node_Expression $parent = null, Twig_NodeInterface $blocks, Twig_NodeInterface $macros, Twig_NodeInterface $traits, $embeddedTemplates, $name, $source = '') +if (\false) { + class Twig_Node_Module extends ModuleNode { - if (!$name instanceof Twig_Source) { - @trigger_error(sprintf('Passing a string as the $name argument of %s() is deprecated since version 1.27. Pass a Twig_Source instance instead.', __METHOD__), E_USER_DEPRECATED); - $this->source = new Twig_Source($source, $name); - } else { - $this->source = $name; - } - - $nodes = array( - 'body' => $body, - 'blocks' => $blocks, - 'macros' => $macros, - 'traits' => $traits, - 'display_start' => new Twig_Node(), - 'display_end' => new Twig_Node(), - 'constructor_start' => new Twig_Node(), - 'constructor_end' => new Twig_Node(), - 'class_end' => new Twig_Node(), - ); - if (null !== $parent) { - $nodes['parent'] = $parent; - } - - // embedded templates are set as attributes so that they are only visited once by the visitors - parent::__construct($nodes, array( - // source to be remove in 2.0 - 'source' => $this->source->getCode(), - // filename to be remove in 2.0 (use getTemplateName() instead) - 'filename' => $this->source->getName(), - 'index' => null, - 'embedded_templates' => $embeddedTemplates, - ), 1); - - // populate the template name of all node children - $this->setTemplateName($this->source->getName()); - } - - public function setIndex($index) - { - $this->setAttribute('index', $index); - } - - public function compile(Twig_Compiler $compiler) - { - $this->compileTemplate($compiler); - - foreach ($this->getAttribute('embedded_templates') as $template) { - $compiler->subcompile($template); - } - } - - protected function compileTemplate(Twig_Compiler $compiler) - { - if (!$this->getAttribute('index')) { - $compiler->write('<?php'); - } - - $this->compileClassHeader($compiler); - - if ( - count($this->getNode('blocks')) - || count($this->getNode('traits')) - || !$this->hasNode('parent') - || $this->getNode('parent') instanceof Twig_Node_Expression_Constant - || count($this->getNode('constructor_start')) - || count($this->getNode('constructor_end')) - ) { - $this->compileConstructor($compiler); - } - - $this->compileGetParent($compiler); - - $this->compileDisplay($compiler); - - $compiler->subcompile($this->getNode('blocks')); - - $this->compileMacros($compiler); - - $this->compileGetTemplateName($compiler); - - $this->compileIsTraitable($compiler); - - $this->compileDebugInfo($compiler); - - $this->compileGetSource($compiler); - - $this->compileGetSourceContext($compiler); - - $this->compileClassFooter($compiler); - } - - protected function compileGetParent(Twig_Compiler $compiler) - { - if (!$this->hasNode('parent')) { - return; - } - $parent = $this->getNode('parent'); - - $compiler - ->write("protected function doGetParent(array \$context)\n", "{\n") - ->indent() - ->addDebugInfo($parent) - ->write('return ') - ; - - if ($parent instanceof Twig_Node_Expression_Constant) { - $compiler->subcompile($parent); - } else { - $compiler - ->raw('$this->loadTemplate(') - ->subcompile($parent) - ->raw(', ') - ->repr($this->source->getName()) - ->raw(', ') - ->repr($parent->getTemplateLine()) - ->raw(')') - ; - } - - $compiler - ->raw(";\n") - ->outdent() - ->write("}\n\n") - ; - } - - protected function compileClassHeader(Twig_Compiler $compiler) - { - $compiler - ->write("\n\n") - // if the template name contains */, add a blank to avoid a PHP parse error - ->write('/* '.str_replace('*/', '* /', $this->source->getName())." */\n") - ->write('class '.$compiler->getEnvironment()->getTemplateClass($this->source->getName(), $this->getAttribute('index'))) - ->raw(sprintf(" extends %s\n", $compiler->getEnvironment()->getBaseTemplateClass())) - ->write("{\n") - ->indent() - ; - } - - protected function compileConstructor(Twig_Compiler $compiler) - { - $compiler - ->write("public function __construct(Twig_Environment \$env)\n", "{\n") - ->indent() - ->subcompile($this->getNode('constructor_start')) - ->write("parent::__construct(\$env);\n\n") - ; - - // parent - if (!$this->hasNode('parent')) { - $compiler->write("\$this->parent = false;\n\n"); - } elseif (($parent = $this->getNode('parent')) && $parent instanceof Twig_Node_Expression_Constant) { - $compiler - ->addDebugInfo($parent) - ->write('$this->parent = $this->loadTemplate(') - ->subcompile($parent) - ->raw(', ') - ->repr($this->source->getName()) - ->raw(', ') - ->repr($parent->getTemplateLine()) - ->raw(");\n") - ; - } - - $countTraits = count($this->getNode('traits')); - if ($countTraits) { - // traits - foreach ($this->getNode('traits') as $i => $trait) { - $this->compileLoadTemplate($compiler, $trait->getNode('template'), sprintf('$_trait_%s', $i)); - - $compiler - ->addDebugInfo($trait->getNode('template')) - ->write(sprintf("if (!\$_trait_%s->isTraitable()) {\n", $i)) - ->indent() - ->write("throw new Twig_Error_Runtime('Template \"'.") - ->subcompile($trait->getNode('template')) - ->raw(".'\" cannot be used as a trait.');\n") - ->outdent() - ->write("}\n") - ->write(sprintf("\$_trait_%s_blocks = \$_trait_%s->getBlocks();\n\n", $i, $i)) - ; - - foreach ($trait->getNode('targets') as $key => $value) { - $compiler - ->write(sprintf('if (!isset($_trait_%s_blocks[', $i)) - ->string($key) - ->raw("])) {\n") - ->indent() - ->write("throw new Twig_Error_Runtime(sprintf('Block ") - ->string($key) - ->raw(' is not defined in trait ') - ->subcompile($trait->getNode('template')) - ->raw(".'));\n") - ->outdent() - ->write("}\n\n") - - ->write(sprintf('$_trait_%s_blocks[', $i)) - ->subcompile($value) - ->raw(sprintf('] = $_trait_%s_blocks[', $i)) - ->string($key) - ->raw(sprintf(']; unset($_trait_%s_blocks[', $i)) - ->string($key) - ->raw("]);\n\n") - ; - } - } - - if ($countTraits > 1) { - $compiler - ->write("\$this->traits = array_merge(\n") - ->indent() - ; - - for ($i = 0; $i < $countTraits; ++$i) { - $compiler - ->write(sprintf('$_trait_%s_blocks'.($i == $countTraits - 1 ? '' : ',')."\n", $i)) - ; - } - - $compiler - ->outdent() - ->write(");\n\n") - ; - } else { - $compiler - ->write("\$this->traits = \$_trait_0_blocks;\n\n") - ; - } - - $compiler - ->write("\$this->blocks = array_merge(\n") - ->indent() - ->write("\$this->traits,\n") - ->write("array(\n") - ; - } else { - $compiler - ->write("\$this->blocks = array(\n") - ; - } - - // blocks - $compiler - ->indent() - ; - - foreach ($this->getNode('blocks') as $name => $node) { - $compiler - ->write(sprintf("'%s' => array(\$this, 'block_%s'),\n", $name, $name)) - ; - } - - if ($countTraits) { - $compiler - ->outdent() - ->write(")\n") - ; - } - - $compiler - ->outdent() - ->write(");\n") - ->outdent() - ->subcompile($this->getNode('constructor_end')) - ->write("}\n\n") - ; - } - - protected function compileDisplay(Twig_Compiler $compiler) - { - $compiler - ->write("protected function doDisplay(array \$context, array \$blocks = array())\n", "{\n") - ->indent() - ->subcompile($this->getNode('display_start')) - ->subcompile($this->getNode('body')) - ; - - if ($this->hasNode('parent')) { - $parent = $this->getNode('parent'); - $compiler->addDebugInfo($parent); - if ($parent instanceof Twig_Node_Expression_Constant) { - $compiler->write('$this->parent'); - } else { - $compiler->write('$this->getParent($context)'); - } - $compiler->raw("->display(\$context, array_merge(\$this->blocks, \$blocks));\n"); - } - - $compiler - ->subcompile($this->getNode('display_end')) - ->outdent() - ->write("}\n\n") - ; - } - - protected function compileClassFooter(Twig_Compiler $compiler) - { - $compiler - ->subcompile($this->getNode('class_end')) - ->outdent() - ->write("}\n") - ; - } - - protected function compileMacros(Twig_Compiler $compiler) - { - $compiler->subcompile($this->getNode('macros')); - } - - protected function compileGetTemplateName(Twig_Compiler $compiler) - { - $compiler - ->write("public function getTemplateName()\n", "{\n") - ->indent() - ->write('return ') - ->repr($this->source->getName()) - ->raw(";\n") - ->outdent() - ->write("}\n\n") - ; - } - - protected function compileIsTraitable(Twig_Compiler $compiler) - { - // A template can be used as a trait if: - // * it has no parent - // * it has no macros - // * it has no body - // - // Put another way, a template can be used as a trait if it - // only contains blocks and use statements. - $traitable = !$this->hasNode('parent') && 0 === count($this->getNode('macros')); - if ($traitable) { - if ($this->getNode('body') instanceof Twig_Node_Body) { - $nodes = $this->getNode('body')->getNode(0); - } else { - $nodes = $this->getNode('body'); - } - - if (!count($nodes)) { - $nodes = new Twig_Node(array($nodes)); - } - - foreach ($nodes as $node) { - if (!count($node)) { - continue; - } - - if ($node instanceof Twig_Node_Text && ctype_space($node->getAttribute('data'))) { - continue; - } - - if ($node instanceof Twig_Node_BlockReference) { - continue; - } - - $traitable = false; - break; - } - } - - if ($traitable) { - return; - } - - $compiler - ->write("public function isTraitable()\n", "{\n") - ->indent() - ->write(sprintf("return %s;\n", $traitable ? 'true' : 'false')) - ->outdent() - ->write("}\n\n") - ; - } - - protected function compileDebugInfo(Twig_Compiler $compiler) - { - $compiler - ->write("public function getDebugInfo()\n", "{\n") - ->indent() - ->write(sprintf("return %s;\n", str_replace("\n", '', var_export(array_reverse($compiler->getDebugInfo(), true), true)))) - ->outdent() - ->write("}\n\n") - ; - } - - protected function compileGetSource(Twig_Compiler $compiler) - { - $compiler - ->write("/** @deprecated since 1.27 (to be removed in 2.0). Use getSourceContext() instead */\n") - ->write("public function getSource()\n", "{\n") - ->indent() - ->write("@trigger_error('The '.__METHOD__.' method is deprecated since version 1.27 and will be removed in 2.0. Use getSourceContext() instead.', E_USER_DEPRECATED);\n\n") - ->write('return $this->getSourceContext()->getCode();') - ->raw("\n") - ->outdent() - ->write("}\n\n") - ; - } - - protected function compileGetSourceContext(Twig_Compiler $compiler) - { - $compiler - ->write("public function getSourceContext()\n", "{\n") - ->indent() - ->write('return new Twig_Source(') - ->string($compiler->getEnvironment()->isDebug() ? $this->source->getCode() : '') - ->raw(', ') - ->string($this->source->getName()) - ->raw(', ') - ->string($this->source->getPath()) - ->raw(");\n") - ->outdent() - ->write("}\n") - ; - } - - protected function compileLoadTemplate(Twig_Compiler $compiler, $node, $var) - { - if ($node instanceof Twig_Node_Expression_Constant) { - $compiler - ->write(sprintf('%s = $this->loadTemplate(', $var)) - ->subcompile($node) - ->raw(', ') - ->repr($node->getTemplateName()) - ->raw(', ') - ->repr($node->getTemplateLine()) - ->raw(");\n") - ; - } else { - throw new LogicException('Trait templates can only be constant nodes.'); - } } } - -class_alias('Twig_Node_Module', 'Twig\Node\ModuleNode', false); diff --git a/vendor/twig/twig/lib/Twig/Node/Print.php b/vendor/twig/twig/lib/Twig/Node/Print.php index 374db89b7cac9ac490b9ba1328480d718358bec2..65a605e7e7d32838c23b39e6fa0fdd70036f442c 100644 --- a/vendor/twig/twig/lib/Twig/Node/Print.php +++ b/vendor/twig/twig/lib/Twig/Node/Print.php @@ -1,36 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * (c) Armin Ronacher - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +use Twig\Node\PrintNode; -/** - * Represents a node that outputs an expression. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class Twig_Node_Print extends Twig_Node implements Twig_NodeOutputInterface -{ - public function __construct(Twig_Node_Expression $expr, $lineno, $tag = null) - { - parent::__construct(array('expr' => $expr), array(), $lineno, $tag); - } +class_exists('Twig\Node\PrintNode'); - public function compile(Twig_Compiler $compiler) +if (\false) { + class Twig_Node_Print extends PrintNode { - $compiler - ->addDebugInfo($this) - ->write('echo ') - ->subcompile($this->getNode('expr')) - ->raw(";\n") - ; } } - -class_alias('Twig_Node_Print', 'Twig\Node\PrintNode', false); diff --git a/vendor/twig/twig/lib/Twig/Node/Sandbox.php b/vendor/twig/twig/lib/Twig/Node/Sandbox.php index 44b30ab9c73073b9970d4a2f31d4b062e2c81fd3..3ff57ff7d9dd147b64ce3a8893ef827dd31cb026 100644 --- a/vendor/twig/twig/lib/Twig/Node/Sandbox.php +++ b/vendor/twig/twig/lib/Twig/Node/Sandbox.php @@ -1,44 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +use Twig\Node\SandboxNode; -/** - * Represents a sandbox node. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class Twig_Node_Sandbox extends Twig_Node -{ - public function __construct(Twig_NodeInterface $body, $lineno, $tag = null) - { - parent::__construct(array('body' => $body), array(), $lineno, $tag); - } +class_exists('Twig\Node\SandboxNode'); - public function compile(Twig_Compiler $compiler) +if (\false) { + class Twig_Node_Sandbox extends SandboxNode { - $compiler - ->addDebugInfo($this) - ->write("\$sandbox = \$this->env->getExtension('Twig_Extension_Sandbox');\n") - ->write("if (!\$alreadySandboxed = \$sandbox->isSandboxed()) {\n") - ->indent() - ->write("\$sandbox->enableSandbox();\n") - ->outdent() - ->write("}\n") - ->subcompile($this->getNode('body')) - ->write("if (!\$alreadySandboxed) {\n") - ->indent() - ->write("\$sandbox->disableSandbox();\n") - ->outdent() - ->write("}\n") - ; } } - -class_alias('Twig_Node_Sandbox', 'Twig\Node\SandboxNode', false); diff --git a/vendor/twig/twig/lib/Twig/Node/SandboxedPrint.php b/vendor/twig/twig/lib/Twig/Node/SandboxedPrint.php index a08f21f5676c21762398e4ea4496c004a47d34f3..a223eeb2cac6b08122767f857ef7c065d89e782b 100644 --- a/vendor/twig/twig/lib/Twig/Node/SandboxedPrint.php +++ b/vendor/twig/twig/lib/Twig/Node/SandboxedPrint.php @@ -1,51 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +use Twig\Node\SandboxedPrintNode; -/** - * Twig_Node_SandboxedPrint adds a check for the __toString() method - * when the variable is an object and the sandbox is activated. - * - * When there is a simple Print statement, like {{ article }}, - * and if the sandbox is enabled, we need to check that the __toString() - * method is allowed if 'article' is an object. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class Twig_Node_SandboxedPrint extends Twig_Node_Print -{ - public function compile(Twig_Compiler $compiler) - { - $compiler - ->addDebugInfo($this) - ->write('echo $this->env->getExtension(\'Twig_Extension_Sandbox\')->ensureToStringAllowed(') - ->subcompile($this->getNode('expr')) - ->raw(");\n") - ; - } +class_exists('Twig\Node\SandboxedPrintNode'); - /** - * Removes node filters. - * - * This is mostly needed when another visitor adds filters (like the escaper one). - * - * @return Twig_Node - */ - protected function removeNodeFilter(Twig_Node $node) +if (\false) { + class Twig_Node_SandboxedPrint extends SandboxedPrintNode { - if ($node instanceof Twig_Node_Expression_Filter) { - return $this->removeNodeFilter($node->getNode('node')); - } - - return $node; } } - -class_alias('Twig_Node_SandboxedPrint', 'Twig\Node\SandboxedPrintNode', false); diff --git a/vendor/twig/twig/lib/Twig/Node/Set.php b/vendor/twig/twig/lib/Twig/Node/Set.php index 6c6743eeb3f5c142518f47d3a88aaabbd412a74f..5b0a6d4f1cd6a391af00c180d906d1ac0382b233 100644 --- a/vendor/twig/twig/lib/Twig/Node/Set.php +++ b/vendor/twig/twig/lib/Twig/Node/Set.php @@ -1,98 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +use Twig\Node\SetNode; -/** - * Represents a set node. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class Twig_Node_Set extends Twig_Node implements Twig_NodeCaptureInterface -{ - public function __construct($capture, Twig_NodeInterface $names, Twig_NodeInterface $values, $lineno, $tag = null) - { - parent::__construct(array('names' => $names, 'values' => $values), array('capture' => $capture, 'safe' => false), $lineno, $tag); - - /* - * Optimizes the node when capture is used for a large block of text. - * - * {% set foo %}foo{% endset %} is compiled to $context['foo'] = new Twig_Markup("foo"); - */ - if ($this->getAttribute('capture')) { - $this->setAttribute('safe', true); - - $values = $this->getNode('values'); - if ($values instanceof Twig_Node_Text) { - $this->setNode('values', new Twig_Node_Expression_Constant($values->getAttribute('data'), $values->getTemplateLine())); - $this->setAttribute('capture', false); - } - } - } +class_exists('Twig\Node\SetNode'); - public function compile(Twig_Compiler $compiler) +if (\false) { + class Twig_Node_Set extends SetNode { - $compiler->addDebugInfo($this); - - if (count($this->getNode('names')) > 1) { - $compiler->write('list('); - foreach ($this->getNode('names') as $idx => $node) { - if ($idx) { - $compiler->raw(', '); - } - - $compiler->subcompile($node); - } - $compiler->raw(')'); - } else { - if ($this->getAttribute('capture')) { - $compiler - ->write("ob_start();\n") - ->subcompile($this->getNode('values')) - ; - } - - $compiler->subcompile($this->getNode('names'), false); - - if ($this->getAttribute('capture')) { - $compiler->raw(" = ('' === \$tmp = ob_get_clean()) ? '' : new Twig_Markup(\$tmp, \$this->env->getCharset())"); - } - } - - if (!$this->getAttribute('capture')) { - $compiler->raw(' = '); - - if (count($this->getNode('names')) > 1) { - $compiler->write('array('); - foreach ($this->getNode('values') as $idx => $value) { - if ($idx) { - $compiler->raw(', '); - } - - $compiler->subcompile($value); - } - $compiler->raw(')'); - } else { - if ($this->getAttribute('safe')) { - $compiler - ->raw("('' === \$tmp = ") - ->subcompile($this->getNode('values')) - ->raw(") ? '' : new Twig_Markup(\$tmp, \$this->env->getCharset())") - ; - } else { - $compiler->subcompile($this->getNode('values')); - } - } - } - - $compiler->raw(";\n"); } } - -class_alias('Twig_Node_Set', 'Twig\Node\SetNode', false); diff --git a/vendor/twig/twig/lib/Twig/Node/SetTemp.php b/vendor/twig/twig/lib/Twig/Node/SetTemp.php index 996fdcde75001244f3d29f9bf273ac2587517715..211ab4ec5e733e7f62b5dc8551f1a9e01c0aa472 100644 --- a/vendor/twig/twig/lib/Twig/Node/SetTemp.php +++ b/vendor/twig/twig/lib/Twig/Node/SetTemp.php @@ -1,40 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +use Twig\Node\SetTempNode; -/** - * @internal - */ -class Twig_Node_SetTemp extends Twig_Node -{ - public function __construct($name, $lineno) - { - parent::__construct(array(), array('name' => $name), $lineno); - } +class_exists('Twig\Node\SetTempNode'); - public function compile(Twig_Compiler $compiler) +if (\false) { + class Twig_Node_SetTemp extends SetTempNode { - $name = $this->getAttribute('name'); - $compiler - ->addDebugInfo($this) - ->write('if (isset($context[') - ->string($name) - ->raw('])) { $_') - ->raw($name) - ->raw('_ = $context[') - ->repr($name) - ->raw(']; } else { $_') - ->raw($name) - ->raw("_ = null; }\n") - ; } } - -class_alias('Twig_Node_SetTemp', 'Twig\Node\SetTempNode', false); diff --git a/vendor/twig/twig/lib/Twig/Node/Spaceless.php b/vendor/twig/twig/lib/Twig/Node/Spaceless.php index 76f90cde53ea210a2b70bbac399a2975981e95fc..0ae024c3f53a5b72a75349cc921b24f6ba4ea4dc 100644 --- a/vendor/twig/twig/lib/Twig/Node/Spaceless.php +++ b/vendor/twig/twig/lib/Twig/Node/Spaceless.php @@ -1,37 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +use Twig\Node\SpacelessNode; -/** - * Represents a spaceless node. - * - * It removes spaces between HTML tags. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class Twig_Node_Spaceless extends Twig_Node -{ - public function __construct(Twig_NodeInterface $body, $lineno, $tag = 'spaceless') - { - parent::__construct(array('body' => $body), array(), $lineno, $tag); - } +class_exists('Twig\Node\SpacelessNode'); - public function compile(Twig_Compiler $compiler) +if (\false) { + class Twig_Node_Spaceless extends SpacelessNode { - $compiler - ->addDebugInfo($this) - ->write("ob_start();\n") - ->subcompile($this->getNode('body')) - ->write("echo trim(preg_replace('/>\s+</', '><', ob_get_clean()));\n") - ; } } - -class_alias('Twig_Node_Spaceless', 'Twig\Node\SpacelessNode', false); diff --git a/vendor/twig/twig/lib/Twig/Node/Text.php b/vendor/twig/twig/lib/Twig/Node/Text.php index f4577fee2b8f3adbf9ab053bd86a44f486596f6d..1a3f956fff4535208c6e5ced442b1f9ec5e20cbf 100644 --- a/vendor/twig/twig/lib/Twig/Node/Text.php +++ b/vendor/twig/twig/lib/Twig/Node/Text.php @@ -1,36 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * (c) Armin Ronacher - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +use Twig\Node\TextNode; -/** - * Represents a text node. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class Twig_Node_Text extends Twig_Node implements Twig_NodeOutputInterface -{ - public function __construct($data, $lineno) - { - parent::__construct(array(), array('data' => $data), $lineno); - } +class_exists('Twig\Node\TextNode'); - public function compile(Twig_Compiler $compiler) +if (\false) { + class Twig_Node_Text extends TextNode { - $compiler - ->addDebugInfo($this) - ->write('echo ') - ->string($this->getAttribute('data')) - ->raw(";\n") - ; } } - -class_alias('Twig_Node_Text', 'Twig\Node\TextNode', false); diff --git a/vendor/twig/twig/lib/Twig/Node/With.php b/vendor/twig/twig/lib/Twig/Node/With.php index 2ab0ea5d7c80ac2e71904c3377e1b76edd1f07aa..266240d6acd301a3533b2c73a69ac5a78f378bda 100644 --- a/vendor/twig/twig/lib/Twig/Node/With.php +++ b/vendor/twig/twig/lib/Twig/Node/With.php @@ -1,64 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +use Twig\Node\WithNode; -/** - * Represents a nested "with" scope. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class Twig_Node_With extends Twig_Node -{ - public function __construct(Twig_Node $body, Twig_Node $variables = null, $only = false, $lineno, $tag = null) - { - $nodes = array('body' => $body); - if (null !== $variables) { - $nodes['variables'] = $variables; - } - - parent::__construct($nodes, array('only' => (bool) $only), $lineno, $tag); - } +class_exists('Twig\Node\WithNode'); - public function compile(Twig_Compiler $compiler) +if (\false) { + class Twig_Node_With extends WithNode { - $compiler->addDebugInfo($this); - - if ($this->hasNode('variables')) { - $varsName = $compiler->getVarName(); - $compiler - ->write(sprintf('$%s = ', $varsName)) - ->subcompile($this->getNode('variables')) - ->raw(";\n") - ->write(sprintf("if (!is_array(\$%s)) {\n", $varsName)) - ->indent() - ->write("throw new Twig_Error_Runtime('Variables passed to the \"with\" tag must be a hash.');\n") - ->outdent() - ->write("}\n") - ; - - if ($this->getAttribute('only')) { - $compiler->write("\$context = array('_parent' => \$context);\n"); - } else { - $compiler->write("\$context['_parent'] = \$context;\n"); - } - - $compiler->write(sprintf("\$context = array_merge(\$context, \$%s);\n", $varsName)); - } else { - $compiler->write("\$context['_parent'] = \$context;\n"); - } - - $compiler - ->subcompile($this->getNode('body')) - ->write("\$context = \$context['_parent'];\n") - ; } } - -class_alias('Twig_Node_With', 'Twig\Node\WithNode', false); diff --git a/vendor/twig/twig/lib/Twig/NodeCaptureInterface.php b/vendor/twig/twig/lib/Twig/NodeCaptureInterface.php index 6638834b12359f793cd64eaeb3489689db1db493..696f4a59f8ab90c484d53c74d536cf2f5acd809a 100644 --- a/vendor/twig/twig/lib/Twig/NodeCaptureInterface.php +++ b/vendor/twig/twig/lib/Twig/NodeCaptureInterface.php @@ -1,21 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +use Twig\Node\NodeCaptureInterface; -/** - * Represents a node that captures any nested displayable nodes. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -interface Twig_NodeCaptureInterface -{ -} +class_exists('Twig\Node\NodeCaptureInterface'); -class_alias('Twig_NodeCaptureInterface', 'Twig\Node\NodeCaptureInterface', false); +if (\false) { + class Twig_NodeCaptureInterface extends NodeCaptureInterface + { + } +} diff --git a/vendor/twig/twig/lib/Twig/NodeInterface.php b/vendor/twig/twig/lib/Twig/NodeInterface.php index 78e758bd4321d667648552995286201b0aed3647..b2b9d3295f9177bb8a2159951936358eace28d05 100644 --- a/vendor/twig/twig/lib/Twig/NodeInterface.php +++ b/vendor/twig/twig/lib/Twig/NodeInterface.php @@ -9,6 +9,8 @@ * file that was distributed with this source code. */ +use Twig\Compiler; + /** * Represents a node in the AST. * @@ -16,12 +18,12 @@ * * @deprecated since 1.12 (to be removed in 3.0) */ -interface Twig_NodeInterface extends Countable, IteratorAggregate +interface Twig_NodeInterface extends \Countable, \IteratorAggregate { /** * Compiles the node to PHP. */ - public function compile(Twig_Compiler $compiler); + public function compile(Compiler $compiler); /** * @deprecated since 1.27 (to be removed in 2.0) diff --git a/vendor/twig/twig/lib/Twig/NodeOutputInterface.php b/vendor/twig/twig/lib/Twig/NodeOutputInterface.php index 5a8eaa9c3d948146aad88ed72b554cd586ded4c9..54009c0a677926093e5359051c027fd094738da7 100644 --- a/vendor/twig/twig/lib/Twig/NodeOutputInterface.php +++ b/vendor/twig/twig/lib/Twig/NodeOutputInterface.php @@ -1,21 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +use Twig\Node\NodeOutputInterface; -/** - * Represents a displayable node in the AST. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -interface Twig_NodeOutputInterface -{ -} +class_exists('Twig\Node\NodeOutputInterface'); -class_alias('Twig_NodeOutputInterface', 'Twig\Node\NodeOutputInterface', false); +if (\false) { + class Twig_NodeOutputInterface extends NodeOutputInterface + { + } +} diff --git a/vendor/twig/twig/lib/Twig/NodeTraverser.php b/vendor/twig/twig/lib/Twig/NodeTraverser.php index 787629ce3449cc25d54ceaa33557ea56d12a8b0c..1e52a6a27189bd6ad13bb70af886496bc22474ed 100644 --- a/vendor/twig/twig/lib/Twig/NodeTraverser.php +++ b/vendor/twig/twig/lib/Twig/NodeTraverser.php @@ -1,84 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +use Twig\NodeTraverser; -/** - * Twig_NodeTraverser is a node traverser. - * - * It visits all nodes and their children and calls the given visitor for each. - * - * @final - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class Twig_NodeTraverser -{ - protected $env; - protected $visitors = array(); +class_exists('Twig\NodeTraverser'); - /** - * @param Twig_Environment $env - * @param Twig_NodeVisitorInterface[] $visitors - */ - public function __construct(Twig_Environment $env, array $visitors = array()) +if (\false) { + class Twig_NodeTraverser extends NodeTraverser { - $this->env = $env; - foreach ($visitors as $visitor) { - $this->addVisitor($visitor); - } - } - - public function addVisitor(Twig_NodeVisitorInterface $visitor) - { - if (!isset($this->visitors[$visitor->getPriority()])) { - $this->visitors[$visitor->getPriority()] = array(); - } - - $this->visitors[$visitor->getPriority()][] = $visitor; - } - - /** - * Traverses a node and calls the registered visitors. - * - * @return Twig_NodeInterface - */ - public function traverse(Twig_NodeInterface $node) - { - ksort($this->visitors); - foreach ($this->visitors as $visitors) { - foreach ($visitors as $visitor) { - $node = $this->traverseForVisitor($visitor, $node); - } - } - - return $node; - } - - protected function traverseForVisitor(Twig_NodeVisitorInterface $visitor, Twig_NodeInterface $node = null) - { - if (null === $node) { - return; - } - - $node = $visitor->enterNode($node, $this->env); - - foreach ($node as $k => $n) { - if (false !== $n = $this->traverseForVisitor($visitor, $n)) { - $node->setNode($k, $n); - } else { - $node->removeNode($k); - } - } - - return $visitor->leaveNode($node, $this->env); } } - -class_alias('Twig_NodeTraverser', 'Twig\NodeTraverser', false); diff --git a/vendor/twig/twig/lib/Twig/NodeVisitor/Escaper.php b/vendor/twig/twig/lib/Twig/NodeVisitor/Escaper.php index 1a1ae66f7584d6e916fe0d8d1fe247c9af68afd5..d8b877ed161ba2e9b2ff661297b3ce3e0fc455e9 100644 --- a/vendor/twig/twig/lib/Twig/NodeVisitor/Escaper.php +++ b/vendor/twig/twig/lib/Twig/NodeVisitor/Escaper.php @@ -1,154 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +use Twig\NodeVisitor\EscaperNodeVisitor; -/** - * Twig_NodeVisitor_Escaper implements output escaping. - * - * @final - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class Twig_NodeVisitor_Escaper extends Twig_BaseNodeVisitor -{ - protected $statusStack = array(); - protected $blocks = array(); - protected $safeAnalysis; - protected $traverser; - protected $defaultStrategy = false; - protected $safeVars = array(); +class_exists('Twig\NodeVisitor\EscaperNodeVisitor'); - public function __construct() +if (\false) { + class Twig_NodeVisitor_Escaper extends EscaperNodeVisitor { - $this->safeAnalysis = new Twig_NodeVisitor_SafeAnalysis(); - } - - protected function doEnterNode(Twig_Node $node, Twig_Environment $env) - { - if ($node instanceof Twig_Node_Module) { - if ($env->hasExtension('Twig_Extension_Escaper') && $defaultStrategy = $env->getExtension('Twig_Extension_Escaper')->getDefaultStrategy($node->getTemplateName())) { - $this->defaultStrategy = $defaultStrategy; - } - $this->safeVars = array(); - $this->blocks = array(); - } elseif ($node instanceof Twig_Node_AutoEscape) { - $this->statusStack[] = $node->getAttribute('value'); - } elseif ($node instanceof Twig_Node_Block) { - $this->statusStack[] = isset($this->blocks[$node->getAttribute('name')]) ? $this->blocks[$node->getAttribute('name')] : $this->needEscaping($env); - } elseif ($node instanceof Twig_Node_Import) { - $this->safeVars[] = $node->getNode('var')->getAttribute('name'); - } - - return $node; - } - - protected function doLeaveNode(Twig_Node $node, Twig_Environment $env) - { - if ($node instanceof Twig_Node_Module) { - $this->defaultStrategy = false; - $this->safeVars = array(); - $this->blocks = array(); - } elseif ($node instanceof Twig_Node_Expression_Filter) { - return $this->preEscapeFilterNode($node, $env); - } elseif ($node instanceof Twig_Node_Print) { - return $this->escapePrintNode($node, $env, $this->needEscaping($env)); - } - - if ($node instanceof Twig_Node_AutoEscape || $node instanceof Twig_Node_Block) { - array_pop($this->statusStack); - } elseif ($node instanceof Twig_Node_BlockReference) { - $this->blocks[$node->getAttribute('name')] = $this->needEscaping($env); - } - - return $node; - } - - protected function escapePrintNode(Twig_Node_Print $node, Twig_Environment $env, $type) - { - if (false === $type) { - return $node; - } - - $expression = $node->getNode('expr'); - - if ($this->isSafeFor($type, $expression, $env)) { - return $node; - } - - $class = get_class($node); - - return new $class( - $this->getEscaperFilter($type, $expression), - $node->getTemplateLine() - ); - } - - protected function preEscapeFilterNode(Twig_Node_Expression_Filter $filter, Twig_Environment $env) - { - $name = $filter->getNode('filter')->getAttribute('value'); - - $type = $env->getFilter($name)->getPreEscape(); - if (null === $type) { - return $filter; - } - - $node = $filter->getNode('node'); - if ($this->isSafeFor($type, $node, $env)) { - return $filter; - } - - $filter->setNode('node', $this->getEscaperFilter($type, $node)); - - return $filter; - } - - protected function isSafeFor($type, Twig_NodeInterface $expression, $env) - { - $safe = $this->safeAnalysis->getSafe($expression); - - if (null === $safe) { - if (null === $this->traverser) { - $this->traverser = new Twig_NodeTraverser($env, array($this->safeAnalysis)); - } - - $this->safeAnalysis->setSafeVars($this->safeVars); - - $this->traverser->traverse($expression); - $safe = $this->safeAnalysis->getSafe($expression); - } - - return in_array($type, $safe) || in_array('all', $safe); - } - - protected function needEscaping(Twig_Environment $env) - { - if (count($this->statusStack)) { - return $this->statusStack[count($this->statusStack) - 1]; - } - - return $this->defaultStrategy ? $this->defaultStrategy : false; - } - - protected function getEscaperFilter($type, Twig_NodeInterface $node) - { - $line = $node->getTemplateLine(); - $name = new Twig_Node_Expression_Constant('escape', $line); - $args = new Twig_Node(array(new Twig_Node_Expression_Constant((string) $type, $line), new Twig_Node_Expression_Constant(null, $line), new Twig_Node_Expression_Constant(true, $line))); - - return new Twig_Node_Expression_Filter($node, $name, $args, $line); - } - - public function getPriority() - { - return 0; } } - -class_alias('Twig_NodeVisitor_Escaper', 'Twig\NodeVisitor\EscaperNodeVisitor', false); diff --git a/vendor/twig/twig/lib/Twig/NodeVisitor/Optimizer.php b/vendor/twig/twig/lib/Twig/NodeVisitor/Optimizer.php index 2fa19f3d756271d0c45421dd0a86db979f67a46d..7e6a77ae4d001877bd91777dc18d183c25a8348a 100644 --- a/vendor/twig/twig/lib/Twig/NodeVisitor/Optimizer.php +++ b/vendor/twig/twig/lib/Twig/NodeVisitor/Optimizer.php @@ -1,253 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +use Twig\NodeVisitor\OptimizerNodeVisitor; -/** - * Twig_NodeVisitor_Optimizer tries to optimizes the AST. - * - * This visitor is always the last registered one. - * - * You can configure which optimizations you want to activate via the - * optimizer mode. - * - * @final - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class Twig_NodeVisitor_Optimizer extends Twig_BaseNodeVisitor -{ - const OPTIMIZE_ALL = -1; - const OPTIMIZE_NONE = 0; - const OPTIMIZE_FOR = 2; - const OPTIMIZE_RAW_FILTER = 4; - const OPTIMIZE_VAR_ACCESS = 8; +class_exists('Twig\NodeVisitor\OptimizerNodeVisitor'); - protected $loops = array(); - protected $loopsTargets = array(); - protected $optimizers; - protected $prependedNodes = array(); - protected $inABody = false; - - /** - * @param int $optimizers The optimizer mode - */ - public function __construct($optimizers = -1) - { - if (!is_int($optimizers) || $optimizers > (self::OPTIMIZE_FOR | self::OPTIMIZE_RAW_FILTER | self::OPTIMIZE_VAR_ACCESS)) { - throw new InvalidArgumentException(sprintf('Optimizer mode "%s" is not valid.', $optimizers)); - } - - $this->optimizers = $optimizers; - } - - protected function doEnterNode(Twig_Node $node, Twig_Environment $env) - { - if (self::OPTIMIZE_FOR === (self::OPTIMIZE_FOR & $this->optimizers)) { - $this->enterOptimizeFor($node, $env); - } - - if (PHP_VERSION_ID < 50400 && self::OPTIMIZE_VAR_ACCESS === (self::OPTIMIZE_VAR_ACCESS & $this->optimizers) && !$env->isStrictVariables() && !$env->hasExtension('Twig_Extension_Sandbox')) { - if ($this->inABody) { - if (!$node instanceof Twig_Node_Expression) { - if (get_class($node) !== 'Twig_Node') { - array_unshift($this->prependedNodes, array()); - } - } else { - $node = $this->optimizeVariables($node, $env); - } - } elseif ($node instanceof Twig_Node_Body) { - $this->inABody = true; - } - } - - return $node; - } - - protected function doLeaveNode(Twig_Node $node, Twig_Environment $env) - { - $expression = $node instanceof Twig_Node_Expression; - - if (self::OPTIMIZE_FOR === (self::OPTIMIZE_FOR & $this->optimizers)) { - $this->leaveOptimizeFor($node, $env); - } - - if (self::OPTIMIZE_RAW_FILTER === (self::OPTIMIZE_RAW_FILTER & $this->optimizers)) { - $node = $this->optimizeRawFilter($node, $env); - } - - $node = $this->optimizePrintNode($node, $env); - - if (self::OPTIMIZE_VAR_ACCESS === (self::OPTIMIZE_VAR_ACCESS & $this->optimizers) && !$env->isStrictVariables() && !$env->hasExtension('Twig_Extension_Sandbox')) { - if ($node instanceof Twig_Node_Body) { - $this->inABody = false; - } elseif ($this->inABody) { - if (!$expression && get_class($node) !== 'Twig_Node' && $prependedNodes = array_shift($this->prependedNodes)) { - $nodes = array(); - foreach (array_unique($prependedNodes) as $name) { - $nodes[] = new Twig_Node_SetTemp($name, $node->getTemplateLine()); - } - - $nodes[] = $node; - $node = new Twig_Node($nodes); - } - } - } - - return $node; - } - - protected function optimizeVariables(Twig_NodeInterface $node, Twig_Environment $env) - { - if ('Twig_Node_Expression_Name' === get_class($node) && $node->isSimple()) { - $this->prependedNodes[0][] = $node->getAttribute('name'); - - return new Twig_Node_Expression_TempName($node->getAttribute('name'), $node->getTemplateLine()); - } - - return $node; - } - - /** - * Optimizes print nodes. - * - * It replaces: - * - * * "echo $this->render(Parent)Block()" with "$this->display(Parent)Block()" - * - * @return Twig_NodeInterface - */ - protected function optimizePrintNode(Twig_NodeInterface $node, Twig_Environment $env) - { - if (!$node instanceof Twig_Node_Print) { - return $node; - } - - $exprNode = $node->getNode('expr'); - if ( - $exprNode instanceof Twig_Node_Expression_BlockReference || - $exprNode instanceof Twig_Node_Expression_Parent - ) { - $exprNode->setAttribute('output', true); - - return $exprNode; - } - - return $node; - } - - /** - * Removes "raw" filters. - * - * @return Twig_NodeInterface - */ - protected function optimizeRawFilter(Twig_NodeInterface $node, Twig_Environment $env) - { - if ($node instanceof Twig_Node_Expression_Filter && 'raw' == $node->getNode('filter')->getAttribute('value')) { - return $node->getNode('node'); - } - - return $node; - } - - /** - * Optimizes "for" tag by removing the "loop" variable creation whenever possible. - */ - protected function enterOptimizeFor(Twig_NodeInterface $node, Twig_Environment $env) +if (\false) { + class Twig_NodeVisitor_Optimizer extends OptimizerNodeVisitor { - if ($node instanceof Twig_Node_For) { - // disable the loop variable by default - $node->setAttribute('with_loop', false); - array_unshift($this->loops, $node); - array_unshift($this->loopsTargets, $node->getNode('value_target')->getAttribute('name')); - array_unshift($this->loopsTargets, $node->getNode('key_target')->getAttribute('name')); - } elseif (!$this->loops) { - // we are outside a loop - return; - } - - // when do we need to add the loop variable back? - - // the loop variable is referenced for the current loop - elseif ($node instanceof Twig_Node_Expression_Name && 'loop' === $node->getAttribute('name')) { - $node->setAttribute('always_defined', true); - $this->addLoopToCurrent(); - } - - // optimize access to loop targets - elseif ($node instanceof Twig_Node_Expression_Name && in_array($node->getAttribute('name'), $this->loopsTargets)) { - $node->setAttribute('always_defined', true); - } - - // block reference - elseif ($node instanceof Twig_Node_BlockReference || $node instanceof Twig_Node_Expression_BlockReference) { - $this->addLoopToCurrent(); - } - - // include without the only attribute - elseif ($node instanceof Twig_Node_Include && !$node->getAttribute('only')) { - $this->addLoopToAll(); - } - - // include function without the with_context=false parameter - elseif ($node instanceof Twig_Node_Expression_Function - && 'include' === $node->getAttribute('name') - && (!$node->getNode('arguments')->hasNode('with_context') - || false !== $node->getNode('arguments')->getNode('with_context')->getAttribute('value') - ) - ) { - $this->addLoopToAll(); - } - - // the loop variable is referenced via an attribute - elseif ($node instanceof Twig_Node_Expression_GetAttr - && (!$node->getNode('attribute') instanceof Twig_Node_Expression_Constant - || 'parent' === $node->getNode('attribute')->getAttribute('value') - ) - && (true === $this->loops[0]->getAttribute('with_loop') - || ($node->getNode('node') instanceof Twig_Node_Expression_Name - && 'loop' === $node->getNode('node')->getAttribute('name') - ) - ) - ) { - $this->addLoopToAll(); - } - } - - /** - * Optimizes "for" tag by removing the "loop" variable creation whenever possible. - */ - protected function leaveOptimizeFor(Twig_NodeInterface $node, Twig_Environment $env) - { - if ($node instanceof Twig_Node_For) { - array_shift($this->loops); - array_shift($this->loopsTargets); - array_shift($this->loopsTargets); - } - } - - protected function addLoopToCurrent() - { - $this->loops[0]->setAttribute('with_loop', true); - } - - protected function addLoopToAll() - { - foreach ($this->loops as $loop) { - $loop->setAttribute('with_loop', true); - } - } - - public function getPriority() - { - return 255; } } - -class_alias('Twig_NodeVisitor_Optimizer', 'Twig\NodeVisitor\OptimizerNodeVisitor', false); diff --git a/vendor/twig/twig/lib/Twig/NodeVisitor/SafeAnalysis.php b/vendor/twig/twig/lib/Twig/NodeVisitor/SafeAnalysis.php index ca31c8fc76b759a484cbc815a43a13be3e7db4e8..bee25230261ec9920b2e5001b250e0bbca448c9c 100644 --- a/vendor/twig/twig/lib/Twig/NodeVisitor/SafeAnalysis.php +++ b/vendor/twig/twig/lib/Twig/NodeVisitor/SafeAnalysis.php @@ -1,150 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +use Twig\NodeVisitor\SafeAnalysisNodeVisitor; -/** - * @final - */ -class Twig_NodeVisitor_SafeAnalysis extends Twig_BaseNodeVisitor -{ - protected $data = array(); - protected $safeVars = array(); +class_exists('Twig\NodeVisitor\SafeAnalysisNodeVisitor'); - public function setSafeVars($safeVars) +if (\false) { + class Twig_NodeVisitor_SafeAnalysis extends SafeAnalysisNodeVisitor { - $this->safeVars = $safeVars; - } - - public function getSafe(Twig_NodeInterface $node) - { - $hash = spl_object_hash($node); - if (!isset($this->data[$hash])) { - return; - } - - foreach ($this->data[$hash] as $bucket) { - if ($bucket['key'] !== $node) { - continue; - } - - if (in_array('html_attr', $bucket['value'])) { - $bucket['value'][] = 'html'; - } - - return $bucket['value']; - } - } - - protected function setSafe(Twig_NodeInterface $node, array $safe) - { - $hash = spl_object_hash($node); - if (isset($this->data[$hash])) { - foreach ($this->data[$hash] as &$bucket) { - if ($bucket['key'] === $node) { - $bucket['value'] = $safe; - - return; - } - } - } - $this->data[$hash][] = array( - 'key' => $node, - 'value' => $safe, - ); - } - - protected function doEnterNode(Twig_Node $node, Twig_Environment $env) - { - return $node; - } - - protected function doLeaveNode(Twig_Node $node, Twig_Environment $env) - { - if ($node instanceof Twig_Node_Expression_Constant) { - // constants are marked safe for all - $this->setSafe($node, array('all')); - } elseif ($node instanceof Twig_Node_Expression_BlockReference) { - // blocks are safe by definition - $this->setSafe($node, array('all')); - } elseif ($node instanceof Twig_Node_Expression_Parent) { - // parent block is safe by definition - $this->setSafe($node, array('all')); - } elseif ($node instanceof Twig_Node_Expression_Conditional) { - // intersect safeness of both operands - $safe = $this->intersectSafe($this->getSafe($node->getNode('expr2')), $this->getSafe($node->getNode('expr3'))); - $this->setSafe($node, $safe); - } elseif ($node instanceof Twig_Node_Expression_Filter) { - // filter expression is safe when the filter is safe - $name = $node->getNode('filter')->getAttribute('value'); - $args = $node->getNode('arguments'); - if (false !== $filter = $env->getFilter($name)) { - $safe = $filter->getSafe($args); - if (null === $safe) { - $safe = $this->intersectSafe($this->getSafe($node->getNode('node')), $filter->getPreservesSafety()); - } - $this->setSafe($node, $safe); - } else { - $this->setSafe($node, array()); - } - } elseif ($node instanceof Twig_Node_Expression_Function) { - // function expression is safe when the function is safe - $name = $node->getAttribute('name'); - $args = $node->getNode('arguments'); - $function = $env->getFunction($name); - if (false !== $function) { - $this->setSafe($node, $function->getSafe($args)); - } else { - $this->setSafe($node, array()); - } - } elseif ($node instanceof Twig_Node_Expression_MethodCall) { - if ($node->getAttribute('safe')) { - $this->setSafe($node, array('all')); - } else { - $this->setSafe($node, array()); - } - } elseif ($node instanceof Twig_Node_Expression_GetAttr && $node->getNode('node') instanceof Twig_Node_Expression_Name) { - $name = $node->getNode('node')->getAttribute('name'); - // attributes on template instances are safe - if ('_self' == $name || in_array($name, $this->safeVars)) { - $this->setSafe($node, array('all')); - } else { - $this->setSafe($node, array()); - } - } else { - $this->setSafe($node, array()); - } - - return $node; - } - - protected function intersectSafe(array $a = null, array $b = null) - { - if (null === $a || null === $b) { - return array(); - } - - if (in_array('all', $a)) { - return $b; - } - - if (in_array('all', $b)) { - return $a; - } - - return array_intersect($a, $b); - } - - public function getPriority() - { - return 0; } } - -class_alias('Twig_NodeVisitor_SafeAnalysis', 'Twig\NodeVisitor\SafeAnalysisNodeVisitor', false); diff --git a/vendor/twig/twig/lib/Twig/NodeVisitor/Sandbox.php b/vendor/twig/twig/lib/Twig/NodeVisitor/Sandbox.php index b631b29d4d15ec8efee53999acf14c7fd007d5c5..1f21c2d25870c5595db41beded8e36e8e4e90026 100644 --- a/vendor/twig/twig/lib/Twig/NodeVisitor/Sandbox.php +++ b/vendor/twig/twig/lib/Twig/NodeVisitor/Sandbox.php @@ -1,77 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +use Twig\NodeVisitor\SandboxNodeVisitor; -/** - * Twig_NodeVisitor_Sandbox implements sandboxing. - * - * @final - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class Twig_NodeVisitor_Sandbox extends Twig_BaseNodeVisitor -{ - protected $inAModule = false; - protected $tags; - protected $filters; - protected $functions; +class_exists('Twig\NodeVisitor\SandboxNodeVisitor'); - protected function doEnterNode(Twig_Node $node, Twig_Environment $env) +if (\false) { + class Twig_NodeVisitor_Sandbox extends SandboxNodeVisitor { - if ($node instanceof Twig_Node_Module) { - $this->inAModule = true; - $this->tags = array(); - $this->filters = array(); - $this->functions = array(); - - return $node; - } elseif ($this->inAModule) { - // look for tags - if ($node->getNodeTag() && !isset($this->tags[$node->getNodeTag()])) { - $this->tags[$node->getNodeTag()] = $node; - } - - // look for filters - if ($node instanceof Twig_Node_Expression_Filter && !isset($this->filters[$node->getNode('filter')->getAttribute('value')])) { - $this->filters[$node->getNode('filter')->getAttribute('value')] = $node; - } - - // look for functions - if ($node instanceof Twig_Node_Expression_Function && !isset($this->functions[$node->getAttribute('name')])) { - $this->functions[$node->getAttribute('name')] = $node; - } - - // wrap print to check __toString() calls - if ($node instanceof Twig_Node_Print) { - return new Twig_Node_SandboxedPrint($node->getNode('expr'), $node->getTemplateLine(), $node->getNodeTag()); - } - } - - return $node; - } - - protected function doLeaveNode(Twig_Node $node, Twig_Environment $env) - { - if ($node instanceof Twig_Node_Module) { - $this->inAModule = false; - - $node->setNode('display_start', new Twig_Node(array(new Twig_Node_CheckSecurity($this->filters, $this->tags, $this->functions), $node->getNode('display_start')))); - } - - return $node; - } - - public function getPriority() - { - return 0; } } - -class_alias('Twig_NodeVisitor_Sandbox', 'Twig\NodeVisitor\SandboxNodeVisitor', false); diff --git a/vendor/twig/twig/lib/Twig/NodeVisitorInterface.php b/vendor/twig/twig/lib/Twig/NodeVisitorInterface.php index 1270a3724302d87c7b6eb70b83ea690b4d40dc83..809b4176eb57adbda1f3de00f377c9418a253bdf 100644 --- a/vendor/twig/twig/lib/Twig/NodeVisitorInterface.php +++ b/vendor/twig/twig/lib/Twig/NodeVisitorInterface.php @@ -1,45 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +use Twig\NodeVisitor\NodeVisitorInterface; -/** - * Twig_NodeVisitorInterface is the interface the all node visitor classes must implement. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -interface Twig_NodeVisitorInterface -{ - /** - * Called before child nodes are visited. - * - * @return Twig_NodeInterface The modified node - */ - public function enterNode(Twig_NodeInterface $node, Twig_Environment $env); +class_exists('Twig\NodeVisitor\NodeVisitorInterface'); - /** - * Called after child nodes are visited. - * - * @return Twig_NodeInterface|false The modified node or false if the node must be removed - */ - public function leaveNode(Twig_NodeInterface $node, Twig_Environment $env); - - /** - * Returns the priority for this visitor. - * - * Priority should be between -10 and 10 (0 is the default). - * - * @return int The priority level - */ - public function getPriority(); +if (\false) { + class Twig_NodeVisitorInterface extends NodeVisitorInterface + { + } } - -class_alias('Twig_NodeVisitorInterface', 'Twig\NodeVisitor\NodeVisitorInterface', false); -class_exists('Twig_Environment'); -class_exists('Twig_Node'); diff --git a/vendor/twig/twig/lib/Twig/Parser.php b/vendor/twig/twig/lib/Twig/Parser.php index e796f197ac4d06c496918ed260e8262a0515f286..cf56f69688161d815c0ce941c3783012d68918d8 100644 --- a/vendor/twig/twig/lib/Twig/Parser.php +++ b/vendor/twig/twig/lib/Twig/Parser.php @@ -1,410 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * (c) Armin Ronacher - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +use Twig\Parser; -/** - * Default parser implementation. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class Twig_Parser implements Twig_ParserInterface -{ - protected $stack = array(); - protected $stream; - protected $parent; - protected $handlers; - protected $visitors; - protected $expressionParser; - protected $blocks; - protected $blockStack; - protected $macros; - protected $env; - protected $reservedMacroNames; - protected $importedSymbols; - protected $traits; - protected $embeddedTemplates = array(); +class_exists('Twig\Parser'); - public function __construct(Twig_Environment $env) +if (\false) { + class Twig_Parser extends Parser { - $this->env = $env; - } - - /** - * @deprecated since 1.27 (to be removed in 2.0) - */ - public function getEnvironment() - { - @trigger_error('The '.__METHOD__.' method is deprecated since version 1.27 and will be removed in 2.0.', E_USER_DEPRECATED); - - return $this->env; - } - - public function getVarName() - { - return sprintf('__internal_%s', hash('sha256', uniqid(mt_rand(), true), false)); - } - - /** - * @deprecated since 1.27 (to be removed in 2.0). Use $parser->getStream()->getSourceContext()->getPath() instead. - */ - public function getFilename() - { - @trigger_error(sprintf('The "%s" method is deprecated since version 1.27 and will be removed in 2.0. Use $parser->getStream()->getSourceContext()->getPath() instead.', __METHOD__), E_USER_DEPRECATED); - - return $this->stream->getSourceContext()->getName(); - } - - public function parse(Twig_TokenStream $stream, $test = null, $dropNeedle = false) - { - // push all variables into the stack to keep the current state of the parser - // using get_object_vars() instead of foreach would lead to https://bugs.php.net/71336 - // This hack can be removed when min version if PHP 7.0 - $vars = array(); - foreach ($this as $k => $v) { - $vars[$k] = $v; - } - - unset($vars['stack'], $vars['env'], $vars['handlers'], $vars['visitors'], $vars['expressionParser'], $vars['reservedMacroNames']); - $this->stack[] = $vars; - - // tag handlers - if (null === $this->handlers) { - $this->handlers = $this->env->getTokenParsers(); - $this->handlers->setParser($this); - } - - // node visitors - if (null === $this->visitors) { - $this->visitors = $this->env->getNodeVisitors(); - } - - if (null === $this->expressionParser) { - $this->expressionParser = new Twig_ExpressionParser($this, $this->env); - } - - $this->stream = $stream; - $this->parent = null; - $this->blocks = array(); - $this->macros = array(); - $this->traits = array(); - $this->blockStack = array(); - $this->importedSymbols = array(array()); - $this->embeddedTemplates = array(); - - try { - $body = $this->subparse($test, $dropNeedle); - - if (null !== $this->parent && null === $body = $this->filterBodyNodes($body)) { - $body = new Twig_Node(); - } - } catch (Twig_Error_Syntax $e) { - if (!$e->getSourceContext()) { - $e->setSourceContext($this->stream->getSourceContext()); - } - - if (!$e->getTemplateLine()) { - $e->setTemplateLine($this->stream->getCurrent()->getLine()); - } - - throw $e; - } - - $node = new Twig_Node_Module(new Twig_Node_Body(array($body)), $this->parent, new Twig_Node($this->blocks), new Twig_Node($this->macros), new Twig_Node($this->traits), $this->embeddedTemplates, $stream->getSourceContext()); - - $traverser = new Twig_NodeTraverser($this->env, $this->visitors); - - $node = $traverser->traverse($node); - - // restore previous stack so previous parse() call can resume working - foreach (array_pop($this->stack) as $key => $val) { - $this->$key = $val; - } - - return $node; - } - - public function subparse($test, $dropNeedle = false) - { - $lineno = $this->getCurrentToken()->getLine(); - $rv = array(); - while (!$this->stream->isEOF()) { - switch ($this->getCurrentToken()->getType()) { - case Twig_Token::TEXT_TYPE: - $token = $this->stream->next(); - $rv[] = new Twig_Node_Text($token->getValue(), $token->getLine()); - break; - - case Twig_Token::VAR_START_TYPE: - $token = $this->stream->next(); - $expr = $this->expressionParser->parseExpression(); - $this->stream->expect(Twig_Token::VAR_END_TYPE); - $rv[] = new Twig_Node_Print($expr, $token->getLine()); - break; - - case Twig_Token::BLOCK_START_TYPE: - $this->stream->next(); - $token = $this->getCurrentToken(); - - if ($token->getType() !== Twig_Token::NAME_TYPE) { - throw new Twig_Error_Syntax('A block must start with a tag name.', $token->getLine(), $this->stream->getSourceContext()); - } - - if (null !== $test && call_user_func($test, $token)) { - if ($dropNeedle) { - $this->stream->next(); - } - - if (1 === count($rv)) { - return $rv[0]; - } - - return new Twig_Node($rv, array(), $lineno); - } - - $subparser = $this->handlers->getTokenParser($token->getValue()); - if (null === $subparser) { - if (null !== $test) { - $e = new Twig_Error_Syntax(sprintf('Unexpected "%s" tag', $token->getValue()), $token->getLine(), $this->stream->getSourceContext()); - - if (is_array($test) && isset($test[0]) && $test[0] instanceof Twig_TokenParserInterface) { - $e->appendMessage(sprintf(' (expecting closing tag for the "%s" tag defined near line %s).', $test[0]->getTag(), $lineno)); - } - } else { - $e = new Twig_Error_Syntax(sprintf('Unknown "%s" tag.', $token->getValue()), $token->getLine(), $this->stream->getSourceContext()); - $e->addSuggestions($token->getValue(), array_keys($this->env->getTags())); - } - - throw $e; - } - - $this->stream->next(); - - $node = $subparser->parse($token); - if (null !== $node) { - $rv[] = $node; - } - break; - - default: - throw new Twig_Error_Syntax('Lexer or parser ended up in unsupported state.', $this->getCurrentToken()->getLine(), $this->stream->getSourceContext()); - } - } - - if (1 === count($rv)) { - return $rv[0]; - } - - return new Twig_Node($rv, array(), $lineno); - } - - /** - * @deprecated since 1.27 (to be removed in 2.0) - */ - public function addHandler($name, $class) - { - @trigger_error('The '.__METHOD__.' method is deprecated since version 1.27 and will be removed in 2.0.', E_USER_DEPRECATED); - - $this->handlers[$name] = $class; - } - - /** - * @deprecated since 1.27 (to be removed in 2.0) - */ - public function addNodeVisitor(Twig_NodeVisitorInterface $visitor) - { - @trigger_error('The '.__METHOD__.' method is deprecated since version 1.27 and will be removed in 2.0.', E_USER_DEPRECATED); - - $this->visitors[] = $visitor; - } - - public function getBlockStack() - { - return $this->blockStack; - } - - public function peekBlockStack() - { - return $this->blockStack[count($this->blockStack) - 1]; - } - - public function popBlockStack() - { - array_pop($this->blockStack); - } - - public function pushBlockStack($name) - { - $this->blockStack[] = $name; - } - - public function hasBlock($name) - { - return isset($this->blocks[$name]); - } - - public function getBlock($name) - { - return $this->blocks[$name]; - } - - public function setBlock($name, Twig_Node_Block $value) - { - $this->blocks[$name] = new Twig_Node_Body(array($value), array(), $value->getTemplateLine()); - } - - public function hasMacro($name) - { - return isset($this->macros[$name]); - } - - public function setMacro($name, Twig_Node_Macro $node) - { - if ($this->isReservedMacroName($name)) { - throw new Twig_Error_Syntax(sprintf('"%s" cannot be used as a macro name as it is a reserved keyword.', $name), $node->getTemplateLine(), $this->stream->getSourceContext()); - } - - $this->macros[$name] = $node; - } - - public function isReservedMacroName($name) - { - if (null === $this->reservedMacroNames) { - $this->reservedMacroNames = array(); - $r = new ReflectionClass($this->env->getBaseTemplateClass()); - foreach ($r->getMethods() as $method) { - $methodName = strtolower($method->getName()); - - if ('get' === substr($methodName, 0, 3) && isset($methodName[3])) { - $this->reservedMacroNames[] = substr($methodName, 3); - } - } - } - - return in_array(strtolower($name), $this->reservedMacroNames); - } - - public function addTrait($trait) - { - $this->traits[] = $trait; - } - - public function hasTraits() - { - return count($this->traits) > 0; - } - - public function embedTemplate(Twig_Node_Module $template) - { - $template->setIndex(mt_rand()); - - $this->embeddedTemplates[] = $template; - } - - public function addImportedSymbol($type, $alias, $name = null, Twig_Node_Expression $node = null) - { - $this->importedSymbols[0][$type][$alias] = array('name' => $name, 'node' => $node); - } - - public function getImportedSymbol($type, $alias) - { - foreach ($this->importedSymbols as $functions) { - if (isset($functions[$type][$alias])) { - return $functions[$type][$alias]; - } - } - } - - public function isMainScope() - { - return 1 === count($this->importedSymbols); - } - - public function pushLocalScope() - { - array_unshift($this->importedSymbols, array()); - } - - public function popLocalScope() - { - array_shift($this->importedSymbols); - } - - /** - * @return Twig_ExpressionParser - */ - public function getExpressionParser() - { - return $this->expressionParser; - } - - public function getParent() - { - return $this->parent; - } - - public function setParent($parent) - { - $this->parent = $parent; - } - - /** - * @return Twig_TokenStream - */ - public function getStream() - { - return $this->stream; - } - - /** - * @return Twig_Token - */ - public function getCurrentToken() - { - return $this->stream->getCurrent(); - } - - protected function filterBodyNodes(Twig_NodeInterface $node) - { - // check that the body does not contain non-empty output nodes - if ( - ($node instanceof Twig_Node_Text && !ctype_space($node->getAttribute('data'))) - || - (!$node instanceof Twig_Node_Text && !$node instanceof Twig_Node_BlockReference && $node instanceof Twig_NodeOutputInterface) - ) { - if (false !== strpos((string) $node, chr(0xEF).chr(0xBB).chr(0xBF))) { - throw new Twig_Error_Syntax('A template that extends another one cannot start with a byte order mark (BOM); it must be removed.', $node->getTemplateLine(), $this->stream->getSourceContext()); - } - - throw new Twig_Error_Syntax('A template that extends another one cannot include contents outside Twig blocks. Did you forget to put the contents inside a {% block %} tag?', $node->getTemplateLine(), $this->stream->getSourceContext()); - } - - // bypass nodes that will "capture" the output - if ($node instanceof Twig_NodeCaptureInterface) { - return $node; - } - - if ($node instanceof Twig_NodeOutputInterface) { - return; - } - - foreach ($node as $k => $n) { - if (null !== $n && null === $this->filterBodyNodes($n)) { - $node->removeNode($k); - } - } - - return $node; } } - -class_alias('Twig_Parser', 'Twig\Parser', false); -class_exists('Twig_Node'); -class_exists('Twig_TokenStream'); diff --git a/vendor/twig/twig/lib/Twig/ParserInterface.php b/vendor/twig/twig/lib/Twig/ParserInterface.php index 85c6e67b20ce3ca94d5f4a9f0af85c10698c65b3..96e9aaa946373be78c0dba58c638b451beae4d78 100644 --- a/vendor/twig/twig/lib/Twig/ParserInterface.php +++ b/vendor/twig/twig/lib/Twig/ParserInterface.php @@ -9,6 +9,10 @@ * file that was distributed with this source code. */ +use Twig\Error\SyntaxError; +use Twig\Node\ModuleNode; +use Twig\TokenStream; + /** * Interface implemented by parser classes. * @@ -21,9 +25,9 @@ interface Twig_ParserInterface /** * Converts a token stream to a node tree. * - * @return Twig_Node_Module + * @return ModuleNode * - * @throws Twig_Error_Syntax When the token stream is syntactically or semantically wrong + * @throws SyntaxError When the token stream is syntactically or semantically wrong */ - public function parse(Twig_TokenStream $stream); + public function parse(TokenStream $stream); } diff --git a/vendor/twig/twig/lib/Twig/Profiler/Dumper/Base.php b/vendor/twig/twig/lib/Twig/Profiler/Dumper/Base.php index 913afd4f0f9679a8fa18b8a147750832fe9b79be..5bcb1ba6335d5eea98c486f03bc5142e6675b0e7 100644 --- a/vendor/twig/twig/lib/Twig/Profiler/Dumper/Base.php +++ b/vendor/twig/twig/lib/Twig/Profiler/Dumper/Base.php @@ -1,62 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +use Twig\Profiler\Dumper\BaseDumper; -/** - * @author Fabien Potencier <fabien@symfony.com> - */ -abstract class Twig_Profiler_Dumper_Base -{ - private $root; +class_exists('Twig\Profiler\Dumper\BaseDumper'); - public function dump(Twig_Profiler_Profile $profile) +if (\false) { + class Twig_Profiler_Dumper_Base extends BaseDumper { - return $this->dumpProfile($profile); - } - - abstract protected function formatTemplate(Twig_Profiler_Profile $profile, $prefix); - - abstract protected function formatNonTemplate(Twig_Profiler_Profile $profile, $prefix); - - abstract protected function formatTime(Twig_Profiler_Profile $profile, $percent); - - private function dumpProfile(Twig_Profiler_Profile $profile, $prefix = '', $sibling = false) - { - if ($profile->isRoot()) { - $this->root = $profile->getDuration(); - $start = $profile->getName(); - } else { - if ($profile->isTemplate()) { - $start = $this->formatTemplate($profile, $prefix); - } else { - $start = $this->formatNonTemplate($profile, $prefix); - } - $prefix .= $sibling ? '│ ' : ' '; - } - - $percent = $this->root ? $profile->getDuration() / $this->root * 100 : 0; - - if ($profile->getDuration() * 1000 < 1) { - $str = $start."\n"; - } else { - $str = sprintf("%s %s\n", $start, $this->formatTime($profile, $percent)); - } - - $nCount = count($profile->getProfiles()); - foreach ($profile as $i => $p) { - $str .= $this->dumpProfile($p, $prefix, $i + 1 !== $nCount); - } - - return $str; } } - -class_alias('Twig_Profiler_Dumper_Base', 'Twig\Profiler\Dumper\BaseDumper', false); -class_exists('Twig_Profiler_Profile'); diff --git a/vendor/twig/twig/lib/Twig/Profiler/Dumper/Blackfire.php b/vendor/twig/twig/lib/Twig/Profiler/Dumper/Blackfire.php index 7a33baf2d670b3ba7367a3aa170e81a6a1ee71cc..cf09413fce3649637e5b6c15ec8431e2ed1964d9 100644 --- a/vendor/twig/twig/lib/Twig/Profiler/Dumper/Blackfire.php +++ b/vendor/twig/twig/lib/Twig/Profiler/Dumper/Blackfire.php @@ -1,72 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -/** - * @author Fabien Potencier <fabien@symfony.com> - * - * @final - */ -class Twig_Profiler_Dumper_Blackfire -{ - public function dump(Twig_Profiler_Profile $profile) - { - $data = array(); - $this->dumpProfile('main()', $profile, $data); - $this->dumpChildren('main()', $profile, $data); - - $start = sprintf('%f', microtime(true)); - $str = <<<EOF -file-format: BlackfireProbe -cost-dimensions: wt mu pmu -request-start: {$start} +use Twig\Profiler\Dumper\BlackfireDumper; +class_exists('Twig\Profiler\Dumper\BlackfireDumper'); -EOF; - - foreach ($data as $name => $values) { - $str .= "{$name}//{$values['ct']} {$values['wt']} {$values['mu']} {$values['pmu']}\n"; - } - - return $str; - } - - private function dumpChildren($parent, Twig_Profiler_Profile $profile, &$data) +if (\false) { + class Twig_Profiler_Dumper_Blackfire extends BlackfireDumper { - foreach ($profile as $p) { - if ($p->isTemplate()) { - $name = $p->getTemplate(); - } else { - $name = sprintf('%s::%s(%s)', $p->getTemplate(), $p->getType(), $p->getName()); - } - $this->dumpProfile(sprintf('%s==>%s', $parent, $name), $p, $data); - $this->dumpChildren($name, $p, $data); - } - } - - private function dumpProfile($edge, Twig_Profiler_Profile $profile, &$data) - { - if (isset($data[$edge])) { - $data[$edge]['ct'] += 1; - $data[$edge]['wt'] += floor($profile->getDuration() * 1000000); - $data[$edge]['mu'] += $profile->getMemoryUsage(); - $data[$edge]['pmu'] += $profile->getPeakMemoryUsage(); - } else { - $data[$edge] = array( - 'ct' => 1, - 'wt' => floor($profile->getDuration() * 1000000), - 'mu' => $profile->getMemoryUsage(), - 'pmu' => $profile->getPeakMemoryUsage(), - ); - } } } - -class_alias('Twig_Profiler_Dumper_Blackfire', 'Twig\Profiler\Dumper\BlackfireDumper', false); diff --git a/vendor/twig/twig/lib/Twig/Profiler/Dumper/Html.php b/vendor/twig/twig/lib/Twig/Profiler/Dumper/Html.php index b57a25517e45a088f855424f1ba275980ee16de9..36dc573a5b1dcd18003847c20fb95143efc43b5b 100644 --- a/vendor/twig/twig/lib/Twig/Profiler/Dumper/Html.php +++ b/vendor/twig/twig/lib/Twig/Profiler/Dumper/Html.php @@ -1,47 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +use Twig\Profiler\Dumper\HtmlDumper; -/** - * @author Fabien Potencier <fabien@symfony.com> - * - * @final - */ -class Twig_Profiler_Dumper_Html extends Twig_Profiler_Dumper_Base -{ - private static $colors = array( - 'block' => '#dfd', - 'macro' => '#ddf', - 'template' => '#ffd', - 'big' => '#d44', - ); +class_exists('Twig\Profiler\Dumper\HtmlDumper'); - public function dump(Twig_Profiler_Profile $profile) +if (\false) { + class Twig_Profiler_Dumper_Html extends HtmlDumper { - return '<pre>'.parent::dump($profile).'</pre>'; - } - - protected function formatTemplate(Twig_Profiler_Profile $profile, $prefix) - { - return sprintf('%s└ <span style="background-color: %s">%s</span>', $prefix, self::$colors['template'], $profile->getTemplate()); - } - - protected function formatNonTemplate(Twig_Profiler_Profile $profile, $prefix) - { - return sprintf('%s└ %s::%s(<span style="background-color: %s">%s</span>)', $prefix, $profile->getTemplate(), $profile->getType(), isset(self::$colors[$profile->getType()]) ? self::$colors[$profile->getType()] : 'auto', $profile->getName()); - } - - protected function formatTime(Twig_Profiler_Profile $profile, $percent) - { - return sprintf('<span style="color: %s">%.2fms/%.0f%%</span>', $percent > 20 ? self::$colors['big'] : 'auto', $profile->getDuration() * 1000, $percent); } } - -class_alias('Twig_Profiler_Dumper_Html', 'Twig\Profiler\Dumper\HtmlDumper', false); diff --git a/vendor/twig/twig/lib/Twig/Profiler/Dumper/Text.php b/vendor/twig/twig/lib/Twig/Profiler/Dumper/Text.php index 69d2c4bf34197f055d4944f04dbbc5e226504d02..3ff1395363f0b104a80cf5e846914c47420630a6 100644 --- a/vendor/twig/twig/lib/Twig/Profiler/Dumper/Text.php +++ b/vendor/twig/twig/lib/Twig/Profiler/Dumper/Text.php @@ -1,35 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +use Twig\Profiler\Dumper\TextDumper; -/** - * @author Fabien Potencier <fabien@symfony.com> - * - * @final - */ -class Twig_Profiler_Dumper_Text extends Twig_Profiler_Dumper_Base -{ - protected function formatTemplate(Twig_Profiler_Profile $profile, $prefix) - { - return sprintf('%s└ %s', $prefix, $profile->getTemplate()); - } - - protected function formatNonTemplate(Twig_Profiler_Profile $profile, $prefix) - { - return sprintf('%s└ %s::%s(%s)', $prefix, $profile->getTemplate(), $profile->getType(), $profile->getName()); - } +class_exists('Twig\Profiler\Dumper\TextDumper'); - protected function formatTime(Twig_Profiler_Profile $profile, $percent) +if (\false) { + class Twig_Profiler_Dumper_Text extends TextDumper { - return sprintf('%.2fms/%.0f%%', $profile->getDuration() * 1000, $percent); } } - -class_alias('Twig_Profiler_Dumper_Text', 'Twig\Profiler\Dumper\TextDumper', false); diff --git a/vendor/twig/twig/lib/Twig/Profiler/Node/EnterProfile.php b/vendor/twig/twig/lib/Twig/Profiler/Node/EnterProfile.php index 69c8f7970224578521e17515a57a917d315d5aed..ce25ec4b5d78a59fa4d6d1e8f430e7480761cb19 100644 --- a/vendor/twig/twig/lib/Twig/Profiler/Node/EnterProfile.php +++ b/vendor/twig/twig/lib/Twig/Profiler/Node/EnterProfile.php @@ -1,39 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +use Twig\Profiler\Node\EnterProfileNode; -/** - * Represents a profile enter node. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class Twig_Profiler_Node_EnterProfile extends Twig_Node -{ - public function __construct($extensionName, $type, $name, $varName) - { - parent::__construct(array(), array('extension_name' => $extensionName, 'name' => $name, 'type' => $type, 'var_name' => $varName)); - } +class_exists('Twig\Profiler\Node\EnterProfileNode'); - public function compile(Twig_Compiler $compiler) +if (\false) { + class Twig_Profiler_Node_EnterProfile extends EnterProfileNode { - $compiler - ->write(sprintf('$%s = $this->env->getExtension(', $this->getAttribute('var_name'))) - ->repr($this->getAttribute('extension_name')) - ->raw(");\n") - ->write(sprintf('$%s->enter($%s = new Twig_Profiler_Profile($this->getTemplateName(), ', $this->getAttribute('var_name'), $this->getAttribute('var_name').'_prof')) - ->repr($this->getAttribute('type')) - ->raw(', ') - ->repr($this->getAttribute('name')) - ->raw("));\n\n") - ; } } - -class_alias('Twig_Profiler_Node_EnterProfile', 'Twig\Profiler\Node\EnterProfileNode', false); diff --git a/vendor/twig/twig/lib/Twig/Profiler/Node/LeaveProfile.php b/vendor/twig/twig/lib/Twig/Profiler/Node/LeaveProfile.php index d1d6a7cc114d9aa9e75b3864018c02891c362f55..31cc7231c8ed8cbefee1fca4fcbf136aa930e4a6 100644 --- a/vendor/twig/twig/lib/Twig/Profiler/Node/LeaveProfile.php +++ b/vendor/twig/twig/lib/Twig/Profiler/Node/LeaveProfile.php @@ -1,33 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +use Twig\Profiler\Node\LeaveProfileNode; -/** - * Represents a profile leave node. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class Twig_Profiler_Node_LeaveProfile extends Twig_Node -{ - public function __construct($varName) - { - parent::__construct(array(), array('var_name' => $varName)); - } +class_exists('Twig\Profiler\Node\LeaveProfileNode'); - public function compile(Twig_Compiler $compiler) +if (\false) { + class Twig_Profiler_Node_LeaveProfile extends LeaveProfileNode { - $compiler - ->write("\n") - ->write(sprintf("\$%s->leave(\$%s);\n\n", $this->getAttribute('var_name'), $this->getAttribute('var_name').'_prof')) - ; } } - -class_alias('Twig_Profiler_Node_LeaveProfile', 'Twig\Profiler\Node\LeaveProfileNode', false); diff --git a/vendor/twig/twig/lib/Twig/Profiler/NodeVisitor/Profiler.php b/vendor/twig/twig/lib/Twig/Profiler/NodeVisitor/Profiler.php index a395ae7fda19ae02d7ee575d677fe32e2d266d9a..463a96bd3acf91672c6dbb928600c23cf1aef497 100644 --- a/vendor/twig/twig/lib/Twig/Profiler/NodeVisitor/Profiler.php +++ b/vendor/twig/twig/lib/Twig/Profiler/NodeVisitor/Profiler.php @@ -1,67 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +use Twig\Profiler\NodeVisitor\ProfilerNodeVisitor; -/** - * @author Fabien Potencier <fabien@symfony.com> - * - * @final - */ -class Twig_Profiler_NodeVisitor_Profiler extends Twig_BaseNodeVisitor -{ - private $extensionName; +class_exists('Twig\Profiler\NodeVisitor\ProfilerNodeVisitor'); - public function __construct($extensionName) +if (\false) { + class Twig_Profiler_NodeVisitor_Profiler extends ProfilerNodeVisitor { - $this->extensionName = $extensionName; - } - - protected function doEnterNode(Twig_Node $node, Twig_Environment $env) - { - return $node; - } - - protected function doLeaveNode(Twig_Node $node, Twig_Environment $env) - { - if ($node instanceof Twig_Node_Module) { - $varName = $this->getVarName(); - $node->setNode('display_start', new Twig_Node(array(new Twig_Profiler_Node_EnterProfile($this->extensionName, Twig_Profiler_Profile::TEMPLATE, $node->getTemplateName(), $varName), $node->getNode('display_start')))); - $node->setNode('display_end', new Twig_Node(array(new Twig_Profiler_Node_LeaveProfile($varName), $node->getNode('display_end')))); - } elseif ($node instanceof Twig_Node_Block) { - $varName = $this->getVarName(); - $node->setNode('body', new Twig_Node_Body(array( - new Twig_Profiler_Node_EnterProfile($this->extensionName, Twig_Profiler_Profile::BLOCK, $node->getAttribute('name'), $varName), - $node->getNode('body'), - new Twig_Profiler_Node_LeaveProfile($varName), - ))); - } elseif ($node instanceof Twig_Node_Macro) { - $varName = $this->getVarName(); - $node->setNode('body', new Twig_Node_Body(array( - new Twig_Profiler_Node_EnterProfile($this->extensionName, Twig_Profiler_Profile::MACRO, $node->getAttribute('name'), $varName), - $node->getNode('body'), - new Twig_Profiler_Node_LeaveProfile($varName), - ))); - } - - return $node; - } - - private function getVarName() - { - return sprintf('__internal_%s', hash('sha256', uniqid(mt_rand(), true), false)); - } - - public function getPriority() - { - return 0; } } - -class_alias('Twig_Profiler_NodeVisitor_Profiler', 'Twig\Profiler\NodeVisitor\ProfilerNodeVisitor', false); diff --git a/vendor/twig/twig/lib/Twig/Profiler/Profile.php b/vendor/twig/twig/lib/Twig/Profiler/Profile.php index 3fdc1a8ae2dbeff29142264e187dae0646ceed41..bb13c7a11d3d13249ac3e9def984ffd6d81f132e 100644 --- a/vendor/twig/twig/lib/Twig/Profiler/Profile.php +++ b/vendor/twig/twig/lib/Twig/Profiler/Profile.php @@ -1,170 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +use Twig\Profiler\Profile; -/** - * @author Fabien Potencier <fabien@symfony.com> - * - * @final - */ -class Twig_Profiler_Profile implements IteratorAggregate, Serializable -{ - const ROOT = 'ROOT'; - const BLOCK = 'block'; - const TEMPLATE = 'template'; - const MACRO = 'macro'; +class_exists('Twig\Profiler\Profile'); - private $template; - private $name; - private $type; - private $starts = array(); - private $ends = array(); - private $profiles = array(); - - public function __construct($template = 'main', $type = self::ROOT, $name = 'main') - { - $this->template = $template; - $this->type = $type; - $this->name = 0 === strpos($name, '__internal_') ? 'INTERNAL' : $name; - $this->enter(); - } - - public function getTemplate() - { - return $this->template; - } - - public function getType() - { - return $this->type; - } - - public function getName() - { - return $this->name; - } - - public function isRoot() - { - return self::ROOT === $this->type; - } - - public function isTemplate() - { - return self::TEMPLATE === $this->type; - } - - public function isBlock() - { - return self::BLOCK === $this->type; - } - - public function isMacro() - { - return self::MACRO === $this->type; - } - - public function getProfiles() - { - return $this->profiles; - } - - public function addProfile(Twig_Profiler_Profile $profile) - { - $this->profiles[] = $profile; - } - - /** - * Returns the duration in microseconds. - * - * @return int - */ - public function getDuration() - { - if ($this->isRoot() && $this->profiles) { - // for the root node with children, duration is the sum of all child durations - $duration = 0; - foreach ($this->profiles as $profile) { - $duration += $profile->getDuration(); - } - - return $duration; - } - - return isset($this->ends['wt']) && isset($this->starts['wt']) ? $this->ends['wt'] - $this->starts['wt'] : 0; - } - - /** - * Returns the memory usage in bytes. - * - * @return int - */ - public function getMemoryUsage() +if (\false) { + class Twig_Profiler_Profile extends Profile { - return isset($this->ends['mu']) && isset($this->starts['mu']) ? $this->ends['mu'] - $this->starts['mu'] : 0; - } - - /** - * Returns the peak memory usage in bytes. - * - * @return int - */ - public function getPeakMemoryUsage() - { - return isset($this->ends['pmu']) && isset($this->starts['pmu']) ? $this->ends['pmu'] - $this->starts['pmu'] : 0; - } - - /** - * Starts the profiling. - */ - public function enter() - { - $this->starts = array( - 'wt' => microtime(true), - 'mu' => memory_get_usage(), - 'pmu' => memory_get_peak_usage(), - ); - } - - /** - * Stops the profiling. - */ - public function leave() - { - $this->ends = array( - 'wt' => microtime(true), - 'mu' => memory_get_usage(), - 'pmu' => memory_get_peak_usage(), - ); - } - - public function reset() - { - $this->starts = $this->ends = $this->profiles = array(); - $this->enter(); - } - - public function getIterator() - { - return new ArrayIterator($this->profiles); - } - - public function serialize() - { - return serialize(array($this->template, $this->name, $this->type, $this->starts, $this->ends, $this->profiles)); - } - - public function unserialize($data) - { - list($this->template, $this->name, $this->type, $this->starts, $this->ends, $this->profiles) = unserialize($data); } } - -class_alias('Twig_Profiler_Profile', 'Twig\Profiler\Profile', false); diff --git a/vendor/twig/twig/lib/Twig/RuntimeLoaderInterface.php b/vendor/twig/twig/lib/Twig/RuntimeLoaderInterface.php index f5eb14e0d90fbe8a4a9407030549e2006a1b07ea..f21cde5a90bba6c9fed06901f5129d6c74cb8abd 100644 --- a/vendor/twig/twig/lib/Twig/RuntimeLoaderInterface.php +++ b/vendor/twig/twig/lib/Twig/RuntimeLoaderInterface.php @@ -1,29 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +use Twig\RuntimeLoader\RuntimeLoaderInterface; -/** - * Creates runtime implementations for Twig elements (filters/functions/tests). - * - * @author Fabien Potencier <fabien@symfony.com> - */ -interface Twig_RuntimeLoaderInterface -{ - /** - * Creates the runtime implementation of a Twig element (filter/function/test). - * - * @param string $class A runtime class - * - * @return object|null The runtime instance or null if the loader does not know how to create the runtime for this class - */ - public function load($class); -} +class_exists('Twig\RuntimeLoader\RuntimeLoaderInterface'); -class_alias('Twig_RuntimeLoaderInterface', 'Twig\RuntimeLoader\RuntimeLoaderInterface', false); +if (\false) { + class Twig_RuntimeLoaderInterface extends RuntimeLoaderInterface + { + } +} diff --git a/vendor/twig/twig/lib/Twig/Sandbox/SecurityError.php b/vendor/twig/twig/lib/Twig/Sandbox/SecurityError.php index b6707e3861ed73e401866b5f899b97d849890d91..d018ece1cb8c7f45ca693ada36c02bddac8aec56 100644 --- a/vendor/twig/twig/lib/Twig/Sandbox/SecurityError.php +++ b/vendor/twig/twig/lib/Twig/Sandbox/SecurityError.php @@ -1,21 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +use Twig\Sandbox\SecurityError; -/** - * Exception thrown when a security error occurs at runtime. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class Twig_Sandbox_SecurityError extends Twig_Error -{ -} +class_exists('Twig\Sandbox\SecurityError'); -class_alias('Twig_Sandbox_SecurityError', 'Twig\Sandbox\SecurityError', false); +if (\false) { + class Twig_Sandbox_SecurityError extends SecurityError + { + } +} diff --git a/vendor/twig/twig/lib/Twig/Sandbox/SecurityNotAllowedFilterError.php b/vendor/twig/twig/lib/Twig/Sandbox/SecurityNotAllowedFilterError.php index 0ba332762d4a88b497bf025c3f044a2eef1feb9c..1a5f9eb2a57a63eccb1868648ca3e49b4288907b 100644 --- a/vendor/twig/twig/lib/Twig/Sandbox/SecurityNotAllowedFilterError.php +++ b/vendor/twig/twig/lib/Twig/Sandbox/SecurityNotAllowedFilterError.php @@ -1,33 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +use Twig\Sandbox\SecurityNotAllowedFilterError; -/** - * Exception thrown when a not allowed filter is used in a template. - * - * @author Martin Hasoň <martin.hason@gmail.com> - */ -class Twig_Sandbox_SecurityNotAllowedFilterError extends Twig_Sandbox_SecurityError -{ - private $filterName; +class_exists('Twig\Sandbox\SecurityNotAllowedFilterError'); - public function __construct($message, $functionName, $lineno = -1, $filename = null, Exception $previous = null) +if (\false) { + class Twig_Sandbox_SecurityNotAllowedFilterError extends SecurityNotAllowedFilterError { - parent::__construct($message, $lineno, $filename, $previous); - $this->filterName = $functionName; - } - - public function getFilterName() - { - return $this->filterName; } } - -class_alias('Twig_Sandbox_SecurityNotAllowedFilterError', 'Twig\Sandbox\SecurityNotAllowedFilterError', false); diff --git a/vendor/twig/twig/lib/Twig/Sandbox/SecurityNotAllowedFunctionError.php b/vendor/twig/twig/lib/Twig/Sandbox/SecurityNotAllowedFunctionError.php index aa39142932a29b2fe84bc4114021bb83a6ba176f..34e2b2b9a3fed318cbd60be3b52cb65662eec213 100644 --- a/vendor/twig/twig/lib/Twig/Sandbox/SecurityNotAllowedFunctionError.php +++ b/vendor/twig/twig/lib/Twig/Sandbox/SecurityNotAllowedFunctionError.php @@ -1,33 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +use Twig\Sandbox\SecurityNotAllowedFunctionError; -/** - * Exception thrown when a not allowed function is used in a template. - * - * @author Martin Hasoň <martin.hason@gmail.com> - */ -class Twig_Sandbox_SecurityNotAllowedFunctionError extends Twig_Sandbox_SecurityError -{ - private $functionName; +class_exists('Twig\Sandbox\SecurityNotAllowedFunctionError'); - public function __construct($message, $functionName, $lineno = -1, $filename = null, Exception $previous = null) +if (\false) { + class Twig_Sandbox_SecurityNotAllowedFunctionError extends SecurityNotAllowedFunctionError { - parent::__construct($message, $lineno, $filename, $previous); - $this->functionName = $functionName; - } - - public function getFunctionName() - { - return $this->functionName; } } - -class_alias('Twig_Sandbox_SecurityNotAllowedFunctionError', 'Twig\Sandbox\SecurityNotAllowedFunctionError', false); diff --git a/vendor/twig/twig/lib/Twig/Sandbox/SecurityNotAllowedMethodError.php b/vendor/twig/twig/lib/Twig/Sandbox/SecurityNotAllowedMethodError.php index 93012fe9909c4fe443bbb55c6a60608ade74abb7..c776b1011c28350e0250cedbd0c4f93b5ddaf34a 100644 --- a/vendor/twig/twig/lib/Twig/Sandbox/SecurityNotAllowedMethodError.php +++ b/vendor/twig/twig/lib/Twig/Sandbox/SecurityNotAllowedMethodError.php @@ -1,40 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +use Twig\Sandbox\SecurityNotAllowedMethodError; -/** - * Exception thrown when a not allowed class method is used in a template. - * - * @author Kit Burton-Senior <mail@kitbs.com> - */ -class Twig_Sandbox_SecurityNotAllowedMethodError extends Twig_Sandbox_SecurityError -{ - private $className; - private $methodName; +class_exists('Twig\Sandbox\SecurityNotAllowedMethodError'); - public function __construct($message, $className, $methodName, $lineno = -1, $filename = null, Exception $previous = null) +if (\false) { + class Twig_Sandbox_SecurityNotAllowedMethodError extends SecurityNotAllowedMethodError { - parent::__construct($message, $lineno, $filename, $previous); - $this->className = $className; - $this->methodName = $methodName; - } - - public function getClassName() - { - return $this->className; - } - - public function getMethodName() - { - return $this->methodName; } } - -class_alias('Twig_Sandbox_SecurityNotAllowedMethodError', 'Twig\Sandbox\SecurityNotAllowedMethodError', false); diff --git a/vendor/twig/twig/lib/Twig/Sandbox/SecurityNotAllowedPropertyError.php b/vendor/twig/twig/lib/Twig/Sandbox/SecurityNotAllowedPropertyError.php index f27969c155bf939f5dd97a7f321aeea1fffbf714..a99efeb24e4ea4b8dc0b5f3d5ebc6f4d89a29b2f 100644 --- a/vendor/twig/twig/lib/Twig/Sandbox/SecurityNotAllowedPropertyError.php +++ b/vendor/twig/twig/lib/Twig/Sandbox/SecurityNotAllowedPropertyError.php @@ -1,40 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +use Twig\Sandbox\SecurityNotAllowedPropertyError; -/** - * Exception thrown when a not allowed class property is used in a template. - * - * @author Kit Burton-Senior <mail@kitbs.com> - */ -class Twig_Sandbox_SecurityNotAllowedPropertyError extends Twig_Sandbox_SecurityError -{ - private $className; - private $propertyName; +class_exists('Twig\Sandbox\SecurityNotAllowedPropertyError'); - public function __construct($message, $className, $propertyName, $lineno = -1, $filename = null, Exception $previous = null) +if (\false) { + class Twig_Sandbox_SecurityNotAllowedPropertyError extends SecurityNotAllowedPropertyError { - parent::__construct($message, $lineno, $filename, $previous); - $this->className = $className; - $this->propertyName = $propertyName; - } - - public function getClassName() - { - return $this->className; - } - - public function getPropertyName() - { - return $this->propertyName; } } - -class_alias('Twig_Sandbox_SecurityNotAllowedPropertyError', 'Twig\Sandbox\SecurityNotAllowedPropertyError', false); diff --git a/vendor/twig/twig/lib/Twig/Sandbox/SecurityNotAllowedTagError.php b/vendor/twig/twig/lib/Twig/Sandbox/SecurityNotAllowedTagError.php index 4bbd22387397968ed29a4b36df761284a03a15e1..0ffd0f849a28ae09f01af2346dd2b5120962a0ea 100644 --- a/vendor/twig/twig/lib/Twig/Sandbox/SecurityNotAllowedTagError.php +++ b/vendor/twig/twig/lib/Twig/Sandbox/SecurityNotAllowedTagError.php @@ -1,33 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +use Twig\Sandbox\SecurityNotAllowedTagError; -/** - * Exception thrown when a not allowed tag is used in a template. - * - * @author Martin Hasoň <martin.hason@gmail.com> - */ -class Twig_Sandbox_SecurityNotAllowedTagError extends Twig_Sandbox_SecurityError -{ - private $tagName; +class_exists('Twig\Sandbox\SecurityNotAllowedTagError'); - public function __construct($message, $tagName, $lineno = -1, $filename = null, Exception $previous = null) +if (\false) { + class Twig_Sandbox_SecurityNotAllowedTagError extends SecurityNotAllowedTagError { - parent::__construct($message, $lineno, $filename, $previous); - $this->tagName = $tagName; - } - - public function getTagName() - { - return $this->tagName; } } - -class_alias('Twig_Sandbox_SecurityNotAllowedTagError', 'Twig\Sandbox\SecurityNotAllowedTagError', false); diff --git a/vendor/twig/twig/lib/Twig/Sandbox/SecurityPolicy.php b/vendor/twig/twig/lib/Twig/Sandbox/SecurityPolicy.php index dca0b82b5f25897b0db605237e58392ad3bb0242..41038c430f47d2e41d98b11796626e1626ffda0b 100644 --- a/vendor/twig/twig/lib/Twig/Sandbox/SecurityPolicy.php +++ b/vendor/twig/twig/lib/Twig/Sandbox/SecurityPolicy.php @@ -1,125 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +use Twig\Sandbox\SecurityPolicy; -/** - * Represents a security policy which need to be enforced when sandbox mode is enabled. - * - * @final - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class Twig_Sandbox_SecurityPolicy implements Twig_Sandbox_SecurityPolicyInterface -{ - protected $allowedTags; - protected $allowedFilters; - protected $allowedMethods; - protected $allowedProperties; - protected $allowedFunctions; +class_exists('Twig\Sandbox\SecurityPolicy'); - public function __construct(array $allowedTags = array(), array $allowedFilters = array(), array $allowedMethods = array(), array $allowedProperties = array(), array $allowedFunctions = array()) +if (\false) { + class Twig_Sandbox_SecurityPolicy extends SecurityPolicy { - $this->allowedTags = $allowedTags; - $this->allowedFilters = $allowedFilters; - $this->setAllowedMethods($allowedMethods); - $this->allowedProperties = $allowedProperties; - $this->allowedFunctions = $allowedFunctions; - } - - public function setAllowedTags(array $tags) - { - $this->allowedTags = $tags; - } - - public function setAllowedFilters(array $filters) - { - $this->allowedFilters = $filters; - } - - public function setAllowedMethods(array $methods) - { - $this->allowedMethods = array(); - foreach ($methods as $class => $m) { - $this->allowedMethods[$class] = array_map('strtolower', is_array($m) ? $m : array($m)); - } - } - - public function setAllowedProperties(array $properties) - { - $this->allowedProperties = $properties; - } - - public function setAllowedFunctions(array $functions) - { - $this->allowedFunctions = $functions; - } - - public function checkSecurity($tags, $filters, $functions) - { - foreach ($tags as $tag) { - if (!in_array($tag, $this->allowedTags)) { - throw new Twig_Sandbox_SecurityNotAllowedTagError(sprintf('Tag "%s" is not allowed.', $tag), $tag); - } - } - - foreach ($filters as $filter) { - if (!in_array($filter, $this->allowedFilters)) { - throw new Twig_Sandbox_SecurityNotAllowedFilterError(sprintf('Filter "%s" is not allowed.', $filter), $filter); - } - } - - foreach ($functions as $function) { - if (!in_array($function, $this->allowedFunctions)) { - throw new Twig_Sandbox_SecurityNotAllowedFunctionError(sprintf('Function "%s" is not allowed.', $function), $function); - } - } - } - - public function checkMethodAllowed($obj, $method) - { - if ($obj instanceof Twig_TemplateInterface || $obj instanceof Twig_Markup) { - return true; - } - - $allowed = false; - $method = strtolower($method); - foreach ($this->allowedMethods as $class => $methods) { - if ($obj instanceof $class) { - $allowed = in_array($method, $methods); - - break; - } - } - - if (!$allowed) { - $class = get_class($obj); - throw new Twig_Sandbox_SecurityNotAllowedMethodError(sprintf('Calling "%s" method on a "%s" object is not allowed.', $method, $class), $class, $method); - } - } - - public function checkPropertyAllowed($obj, $property) - { - $allowed = false; - foreach ($this->allowedProperties as $class => $properties) { - if ($obj instanceof $class) { - $allowed = in_array($property, is_array($properties) ? $properties : array($properties)); - - break; - } - } - - if (!$allowed) { - $class = get_class($obj); - throw new Twig_Sandbox_SecurityNotAllowedPropertyError(sprintf('Calling "%s" property on a "%s" object is not allowed.', $property, $class), $class, $property); - } } } - -class_alias('Twig_Sandbox_SecurityPolicy', 'Twig\Sandbox\SecurityPolicy', false); diff --git a/vendor/twig/twig/lib/Twig/Sandbox/SecurityPolicyInterface.php b/vendor/twig/twig/lib/Twig/Sandbox/SecurityPolicyInterface.php index 88f64447aadee5cf58c74b9ea3c5ebcdf55a9ad1..f17e6a5e991215738fd156eb9532219ab094da80 100644 --- a/vendor/twig/twig/lib/Twig/Sandbox/SecurityPolicyInterface.php +++ b/vendor/twig/twig/lib/Twig/Sandbox/SecurityPolicyInterface.php @@ -1,26 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +use Twig\Sandbox\SecurityPolicyInterface; -/** - * Interfaces that all security policy classes must implements. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -interface Twig_Sandbox_SecurityPolicyInterface -{ - public function checkSecurity($tags, $filters, $functions); +class_exists('Twig\Sandbox\SecurityPolicyInterface'); - public function checkMethodAllowed($obj, $method); - - public function checkPropertyAllowed($obj, $method); +if (\false) { + class Twig_Sandbox_SecurityPolicyInterface extends SecurityPolicyInterface + { + } } - -class_alias('Twig_Sandbox_SecurityPolicyInterface', 'Twig\Sandbox\SecurityPolicyInterface', false); diff --git a/vendor/twig/twig/lib/Twig/SimpleFilter.php b/vendor/twig/twig/lib/Twig/SimpleFilter.php index ee4c0aebf081f9b7433a3fa773268b9c7f9539ca..bb830e0f03b682ef7e2c245463b7c0f5243adc37 100644 --- a/vendor/twig/twig/lib/Twig/SimpleFilter.php +++ b/vendor/twig/twig/lib/Twig/SimpleFilter.php @@ -1,121 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +use Twig\TwigFilter; -/** - * Represents a template filter. - * - * @final - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class Twig_SimpleFilter -{ - protected $name; - protected $callable; - protected $options; - protected $arguments = array(); +class_exists('Twig\TwigFilter'); - public function __construct($name, $callable, array $options = array()) +if (\false) { + class Twig_SimpleFilter extends TwigFilter { - $this->name = $name; - $this->callable = $callable; - $this->options = array_merge(array( - 'needs_environment' => false, - 'needs_context' => false, - 'is_variadic' => false, - 'is_safe' => null, - 'is_safe_callback' => null, - 'pre_escape' => null, - 'preserves_safety' => null, - 'node_class' => 'Twig_Node_Expression_Filter', - 'deprecated' => false, - 'alternative' => null, - ), $options); - } - - public function getName() - { - return $this->name; - } - - public function getCallable() - { - return $this->callable; - } - - public function getNodeClass() - { - return $this->options['node_class']; - } - - public function setArguments($arguments) - { - $this->arguments = $arguments; - } - - public function getArguments() - { - return $this->arguments; - } - - public function needsEnvironment() - { - return $this->options['needs_environment']; - } - - public function needsContext() - { - return $this->options['needs_context']; - } - - public function getSafe(Twig_Node $filterArgs) - { - if (null !== $this->options['is_safe']) { - return $this->options['is_safe']; - } - - if (null !== $this->options['is_safe_callback']) { - return call_user_func($this->options['is_safe_callback'], $filterArgs); - } - } - - public function getPreservesSafety() - { - return $this->options['preserves_safety']; - } - - public function getPreEscape() - { - return $this->options['pre_escape']; - } - - public function isVariadic() - { - return $this->options['is_variadic']; - } - - public function isDeprecated() - { - return (bool) $this->options['deprecated']; - } - - public function getDeprecatedVersion() - { - return $this->options['deprecated']; - } - - public function getAlternative() - { - return $this->options['alternative']; } } - -class_alias('Twig_SimpleFilter', 'Twig\TwigFilter', false); diff --git a/vendor/twig/twig/lib/Twig/SimpleFunction.php b/vendor/twig/twig/lib/Twig/SimpleFunction.php index a6aa7ca744b84c8ae8bf0ff2ad2319440319456b..6ec2abce155b94c8ba29db42dc86eddbb944b024 100644 --- a/vendor/twig/twig/lib/Twig/SimpleFunction.php +++ b/vendor/twig/twig/lib/Twig/SimpleFunction.php @@ -1,111 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +use Twig\TwigFunction; -/** - * Represents a template function. - * - * @final - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class Twig_SimpleFunction -{ - protected $name; - protected $callable; - protected $options; - protected $arguments = array(); +class_exists('Twig\TwigFunction'); - public function __construct($name, $callable, array $options = array()) +if (\false) { + class Twig_SimpleFunction extends TwigFunction { - $this->name = $name; - $this->callable = $callable; - $this->options = array_merge(array( - 'needs_environment' => false, - 'needs_context' => false, - 'is_variadic' => false, - 'is_safe' => null, - 'is_safe_callback' => null, - 'node_class' => 'Twig_Node_Expression_Function', - 'deprecated' => false, - 'alternative' => null, - ), $options); - } - - public function getName() - { - return $this->name; - } - - public function getCallable() - { - return $this->callable; - } - - public function getNodeClass() - { - return $this->options['node_class']; - } - - public function setArguments($arguments) - { - $this->arguments = $arguments; - } - - public function getArguments() - { - return $this->arguments; - } - - public function needsEnvironment() - { - return $this->options['needs_environment']; - } - - public function needsContext() - { - return $this->options['needs_context']; - } - - public function getSafe(Twig_Node $functionArgs) - { - if (null !== $this->options['is_safe']) { - return $this->options['is_safe']; - } - - if (null !== $this->options['is_safe_callback']) { - return call_user_func($this->options['is_safe_callback'], $functionArgs); - } - - return array(); - } - - public function isVariadic() - { - return $this->options['is_variadic']; - } - - public function isDeprecated() - { - return (bool) $this->options['deprecated']; - } - - public function getDeprecatedVersion() - { - return $this->options['deprecated']; - } - - public function getAlternative() - { - return $this->options['alternative']; } } - -class_alias('Twig_SimpleFunction', 'Twig\TwigFunction', false); diff --git a/vendor/twig/twig/lib/Twig/SimpleTest.php b/vendor/twig/twig/lib/Twig/SimpleTest.php index fee5778b3e008c3b168a7193b6ceacca85d20556..e1d20294711121b705f02c07793fccb7c9f58fa3 100644 --- a/vendor/twig/twig/lib/Twig/SimpleTest.php +++ b/vendor/twig/twig/lib/Twig/SimpleTest.php @@ -1,73 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +use Twig\TwigTest; -/** - * Represents a template test. - * - * @final - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class Twig_SimpleTest -{ - protected $name; - protected $callable; - protected $options; +class_exists('Twig\TwigTest'); - public function __construct($name, $callable, array $options = array()) +if (\false) { + class Twig_SimpleTest extends TwigTest { - $this->name = $name; - $this->callable = $callable; - $this->options = array_merge(array( - 'is_variadic' => false, - 'node_class' => 'Twig_Node_Expression_Test', - 'deprecated' => false, - 'alternative' => null, - ), $options); - } - - public function getName() - { - return $this->name; - } - - public function getCallable() - { - return $this->callable; - } - - public function getNodeClass() - { - return $this->options['node_class']; - } - - public function isVariadic() - { - return $this->options['is_variadic']; - } - - public function isDeprecated() - { - return (bool) $this->options['deprecated']; - } - - public function getDeprecatedVersion() - { - return $this->options['deprecated']; - } - - public function getAlternative() - { - return $this->options['alternative']; } } - -class_alias('Twig_SimpleTest', 'Twig\TwigTest', false); diff --git a/vendor/twig/twig/lib/Twig/Source.php b/vendor/twig/twig/lib/Twig/Source.php index bd8d869f3316cc8f3ddcd098be1c96be204a3b2f..6d3c1b97761dcc02494f44850d0c159b0caf3111 100644 --- a/vendor/twig/twig/lib/Twig/Source.php +++ b/vendor/twig/twig/lib/Twig/Source.php @@ -1,53 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +use Twig\Source; -/** - * Holds information about a non-compiled Twig template. - * - * @final - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class Twig_Source -{ - private $code; - private $name; - private $path; +class_exists('Twig\Source'); - /** - * @param string $code The template source code - * @param string $name The template logical name - * @param string $path The filesystem path of the template if any - */ - public function __construct($code, $name, $path = '') +if (\false) { + class Twig_Source extends Source { - $this->code = $code; - $this->name = $name; - $this->path = $path; - } - - public function getCode() - { - return $this->code; - } - - public function getName() - { - return $this->name; - } - - public function getPath() - { - return $this->path; } } - -class_alias('Twig_Source', 'Twig\Source', false); diff --git a/vendor/twig/twig/lib/Twig/SourceContextLoaderInterface.php b/vendor/twig/twig/lib/Twig/SourceContextLoaderInterface.php index a6e8c42550a18d06ecafc3c0570d86ff2a4110f8..3289ac1d2b6c78a07dae53af5a021441465df945 100644 --- a/vendor/twig/twig/lib/Twig/SourceContextLoaderInterface.php +++ b/vendor/twig/twig/lib/Twig/SourceContextLoaderInterface.php @@ -1,33 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +use Twig\Loader\SourceContextLoaderInterface; -/** - * Adds a getSourceContext() method for loaders. - * - * @author Fabien Potencier <fabien@symfony.com> - * - * @deprecated since 1.27 (to be removed in 3.0) - */ -interface Twig_SourceContextLoaderInterface -{ - /** - * Returns the source context for a given template logical name. - * - * @param string $name The template logical name - * - * @return Twig_Source - * - * @throws Twig_Error_Loader When $name is not found - */ - public function getSourceContext($name); -} +class_exists('Twig\Loader\SourceContextLoaderInterface'); -class_alias('Twig_SourceContextLoaderInterface', 'Twig\Loader\SourceContextLoaderInterface', false); +if (\false) { + class Twig_SourceContextLoaderInterface extends SourceContextLoaderInterface + { + } +} diff --git a/vendor/twig/twig/lib/Twig/Template.php b/vendor/twig/twig/lib/Twig/Template.php index 64563419ec0c17b9c2694ac05aba12c3a8b6bf9c..ef5988c91f290fad21726bdf3936a66e709c29cf 100644 --- a/vendor/twig/twig/lib/Twig/Template.php +++ b/vendor/twig/twig/lib/Twig/Template.php @@ -1,706 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * (c) Armin Ronacher - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +use Twig\Template; -/** - * Default base class for compiled templates. - * - * This class is an implementation detail of how template compilation currently - * works, which might change. It should never be used directly. Use $twig->load() - * instead, which returns an instance of Twig_TemplateWrapper. - * - * @author Fabien Potencier <fabien@symfony.com> - * - * @internal - */ -abstract class Twig_Template implements Twig_TemplateInterface -{ - /** - * @internal - */ - protected static $cache = array(); +class_exists('Twig\Template'); - protected $parent; - protected $parents = array(); - protected $env; - protected $blocks = array(); - protected $traits = array(); - - public function __construct(Twig_Environment $env) - { - $this->env = $env; - } - - /** - * @internal this method will be removed in 2.0 and is only used internally to provide an upgrade path from 1.x to 2.0 - */ - public function __toString() - { - return $this->getTemplateName(); - } - - /** - * Returns the template name. - * - * @return string The template name - */ - abstract public function getTemplateName(); - - /** - * Returns debug information about the template. - * - * @return array Debug information - * - * @internal - */ - public function getDebugInfo() - { - return array(); - } - - /** - * Returns the template source code. - * - * @return string The template source code - * - * @deprecated since 1.27 (to be removed in 2.0). Use getSourceContext() instead - */ - public function getSource() - { - @trigger_error('The '.__METHOD__.' method is deprecated since version 1.27 and will be removed in 2.0. Use getSourceContext() instead.', E_USER_DEPRECATED); - - return ''; - } - - /** - * Returns information about the original template source code. - * - * @return Twig_Source - */ - public function getSourceContext() - { - return new Twig_Source('', $this->getTemplateName()); - } - - /** - * @deprecated since 1.20 (to be removed in 2.0) - */ - public function getEnvironment() - { - @trigger_error('The '.__METHOD__.' method is deprecated since version 1.20 and will be removed in 2.0.', E_USER_DEPRECATED); - - return $this->env; - } - - /** - * Returns the parent template. - * - * This method is for internal use only and should never be called - * directly. - * - * @param array $context - * - * @return Twig_TemplateInterface|false The parent template or false if there is no parent - * - * @internal - */ - public function getParent(array $context) - { - if (null !== $this->parent) { - return $this->parent; - } - - try { - $parent = $this->doGetParent($context); - - if (false === $parent) { - return false; - } - - if ($parent instanceof self) { - return $this->parents[$parent->getTemplateName()] = $parent; - } - - if (!isset($this->parents[$parent])) { - $this->parents[$parent] = $this->loadTemplate($parent); - } - } catch (Twig_Error_Loader $e) { - $e->setSourceContext(null); - $e->guess(); - - throw $e; - } - - return $this->parents[$parent]; - } - - protected function doGetParent(array $context) - { - return false; - } - - public function isTraitable() - { - return true; - } - - /** - * Displays a parent block. - * - * This method is for internal use only and should never be called - * directly. - * - * @param string $name The block name to display from the parent - * @param array $context The context - * @param array $blocks The current set of blocks - * - * @internal - */ - public function displayParentBlock($name, array $context, array $blocks = array()) - { - $name = (string) $name; - - if (isset($this->traits[$name])) { - $this->traits[$name][0]->displayBlock($name, $context, $blocks, false); - } elseif (false !== $parent = $this->getParent($context)) { - $parent->displayBlock($name, $context, $blocks, false); - } else { - throw new Twig_Error_Runtime(sprintf('The template has no parent and no traits defining the "%s" block.', $name), -1, $this->getSourceContext()); - } - } - - /** - * Displays a block. - * - * This method is for internal use only and should never be called - * directly. - * - * @param string $name The block name to display - * @param array $context The context - * @param array $blocks The current set of blocks - * @param bool $useBlocks Whether to use the current set of blocks - * - * @internal - */ - public function displayBlock($name, array $context, array $blocks = array(), $useBlocks = true) - { - $name = (string) $name; - - if ($useBlocks && isset($blocks[$name])) { - $template = $blocks[$name][0]; - $block = $blocks[$name][1]; - } elseif (isset($this->blocks[$name])) { - $template = $this->blocks[$name][0]; - $block = $this->blocks[$name][1]; - } else { - $template = null; - $block = null; - } - - // avoid RCEs when sandbox is enabled - if (null !== $template && !$template instanceof self) { - throw new LogicException('A block must be a method on a Twig_Template instance.'); - } - - if (null !== $template) { - try { - $template->$block($context, $blocks); - } catch (Twig_Error $e) { - if (!$e->getSourceContext()) { - $e->setSourceContext($template->getSourceContext()); - } - - // this is mostly useful for Twig_Error_Loader exceptions - // see Twig_Error_Loader - if (false === $e->getTemplateLine()) { - $e->setTemplateLine(-1); - $e->guess(); - } - - throw $e; - } catch (Exception $e) { - throw new Twig_Error_Runtime(sprintf('An exception has been thrown during the rendering of a template ("%s").', $e->getMessage()), -1, $template->getSourceContext(), $e); - } - } elseif (false !== $parent = $this->getParent($context)) { - $parent->displayBlock($name, $context, array_merge($this->blocks, $blocks), false); - } else { - @trigger_error(sprintf('Silent display of undefined block "%s" in template "%s" is deprecated since version 1.29 and will throw an exception in 2.0. Use the "block(\'%s\') is defined" expression to test for block existence.', $name, $this->getTemplateName(), $name), E_USER_DEPRECATED); - } - } - - /** - * Renders a parent block. - * - * This method is for internal use only and should never be called - * directly. - * - * @param string $name The block name to render from the parent - * @param array $context The context - * @param array $blocks The current set of blocks - * - * @return string The rendered block - * - * @internal - */ - public function renderParentBlock($name, array $context, array $blocks = array()) - { - ob_start(); - $this->displayParentBlock($name, $context, $blocks); - - return ob_get_clean(); - } - - /** - * Renders a block. - * - * This method is for internal use only and should never be called - * directly. - * - * @param string $name The block name to render - * @param array $context The context - * @param array $blocks The current set of blocks - * @param bool $useBlocks Whether to use the current set of blocks - * - * @return string The rendered block - * - * @internal - */ - public function renderBlock($name, array $context, array $blocks = array(), $useBlocks = true) - { - ob_start(); - $this->displayBlock($name, $context, $blocks, $useBlocks); - - return ob_get_clean(); - } - - /** - * Returns whether a block exists or not in the current context of the template. - * - * This method checks blocks defined in the current template - * or defined in "used" traits or defined in parent templates. - * - * @param string $name The block name - * @param array $context The context - * @param array $blocks The current set of blocks - * - * @return bool true if the block exists, false otherwise - * - * @internal - */ - public function hasBlock($name, array $context = null, array $blocks = array()) - { - if (null === $context) { - @trigger_error('The '.__METHOD__.' method is internal and should never be called; calling it directly is deprecated since version 1.28 and won\'t be possible anymore in 2.0.', E_USER_DEPRECATED); - - return isset($this->blocks[(string) $name]); - } - - if (isset($blocks[$name])) { - return $blocks[$name][0] instanceof self; - } - - if (isset($this->blocks[$name])) { - return true; - } - - if (false !== $parent = $this->getParent($context)) { - return $parent->hasBlock($name, $context); - } - - return false; - } - - /** - * Returns all block names in the current context of the template. - * - * This method checks blocks defined in the current template - * or defined in "used" traits or defined in parent templates. - * - * @param array $context The context - * @param array $blocks The current set of blocks - * - * @return array An array of block names - * - * @internal - */ - public function getBlockNames(array $context = null, array $blocks = array()) - { - if (null === $context) { - @trigger_error('The '.__METHOD__.' method is internal and should never be called; calling it directly is deprecated since version 1.28 and won\'t be possible anymore in 2.0.', E_USER_DEPRECATED); - - return array_keys($this->blocks); - } - - $names = array_merge(array_keys($blocks), array_keys($this->blocks)); - - if (false !== $parent = $this->getParent($context)) { - $names = array_merge($names, $parent->getBlockNames($context)); - } - - return array_unique($names); - } - - protected function loadTemplate($template, $templateName = null, $line = null, $index = null) - { - try { - if (is_array($template)) { - return $this->env->resolveTemplate($template); - } - - if ($template instanceof self) { - return $template; - } - - if ($template instanceof Twig_TemplateWrapper) { - return $template; - } - - return $this->env->loadTemplate($template, $index); - } catch (Twig_Error $e) { - if (!$e->getSourceContext()) { - $e->setSourceContext($templateName ? new Twig_Source('', $templateName) : $this->getSourceContext()); - } - - if ($e->getTemplateLine()) { - throw $e; - } - - if (!$line) { - $e->guess(); - } else { - $e->setTemplateLine($line); - } - - throw $e; - } - } - - /** - * Returns all blocks. - * - * This method is for internal use only and should never be called - * directly. - * - * @return array An array of blocks - * - * @internal - */ - public function getBlocks() - { - return $this->blocks; - } - - public function display(array $context, array $blocks = array()) +if (\false) { + class Twig_Template extends Template { - $this->displayWithErrorHandling($this->env->mergeGlobals($context), array_merge($this->blocks, $blocks)); - } - - public function render(array $context) - { - $level = ob_get_level(); - ob_start(); - try { - $this->display($context); - } catch (Exception $e) { - while (ob_get_level() > $level) { - ob_end_clean(); - } - - throw $e; - } catch (Throwable $e) { - while (ob_get_level() > $level) { - ob_end_clean(); - } - - throw $e; - } - - return ob_get_clean(); - } - - protected function displayWithErrorHandling(array $context, array $blocks = array()) - { - try { - $this->doDisplay($context, $blocks); - } catch (Twig_Error $e) { - if (!$e->getSourceContext()) { - $e->setSourceContext($this->getSourceContext()); - } - - // this is mostly useful for Twig_Error_Loader exceptions - // see Twig_Error_Loader - if (false === $e->getTemplateLine()) { - $e->setTemplateLine(-1); - $e->guess(); - } - - throw $e; - } catch (Exception $e) { - throw new Twig_Error_Runtime(sprintf('An exception has been thrown during the rendering of a template ("%s").', $e->getMessage()), -1, $this->getSourceContext(), $e); - } - } - - /** - * Auto-generated method to display the template with the given context. - * - * @param array $context An array of parameters to pass to the template - * @param array $blocks An array of blocks to pass to the template - */ - abstract protected function doDisplay(array $context, array $blocks = array()); - - /** - * Returns a variable from the context. - * - * This method is for internal use only and should never be called - * directly. - * - * This method should not be overridden in a sub-class as this is an - * implementation detail that has been introduced to optimize variable - * access for versions of PHP before 5.4. This is not a way to override - * the way to get a variable value. - * - * @param array $context The context - * @param string $item The variable to return from the context - * @param bool $ignoreStrictCheck Whether to ignore the strict variable check or not - * - * @return mixed The content of the context variable - * - * @throws Twig_Error_Runtime if the variable does not exist and Twig is running in strict mode - * - * @internal - */ - final protected function getContext($context, $item, $ignoreStrictCheck = false) - { - if (!array_key_exists($item, $context)) { - if ($ignoreStrictCheck || !$this->env->isStrictVariables()) { - return; - } - - throw new Twig_Error_Runtime(sprintf('Variable "%s" does not exist.', $item), -1, $this->getSourceContext()); - } - - return $context[$item]; - } - - /** - * Returns the attribute value for a given array/object. - * - * @param mixed $object The object or array from where to get the item - * @param mixed $item The item to get from the array or object - * @param array $arguments An array of arguments to pass if the item is an object method - * @param string $type The type of attribute (@see Twig_Template constants) - * @param bool $isDefinedTest Whether this is only a defined check - * @param bool $ignoreStrictCheck Whether to ignore the strict attribute check or not - * - * @return mixed The attribute value, or a Boolean when $isDefinedTest is true, or null when the attribute is not set and $ignoreStrictCheck is true - * - * @throws Twig_Error_Runtime if the attribute does not exist and Twig is running in strict mode and $isDefinedTest is false - * - * @internal - */ - protected function getAttribute($object, $item, array $arguments = array(), $type = self::ANY_CALL, $isDefinedTest = false, $ignoreStrictCheck = false) - { - // array - if (self::METHOD_CALL !== $type) { - $arrayItem = is_bool($item) || is_float($item) ? (int) $item : $item; - - if ((is_array($object) && (isset($object[$arrayItem]) || array_key_exists($arrayItem, $object))) - || ($object instanceof ArrayAccess && isset($object[$arrayItem])) - ) { - if ($isDefinedTest) { - return true; - } - - return $object[$arrayItem]; - } - - if (self::ARRAY_CALL === $type || !is_object($object)) { - if ($isDefinedTest) { - return false; - } - - if ($ignoreStrictCheck || !$this->env->isStrictVariables()) { - return; - } - - if ($object instanceof ArrayAccess) { - $message = sprintf('Key "%s" in object with ArrayAccess of class "%s" does not exist.', $arrayItem, get_class($object)); - } elseif (is_object($object)) { - $message = sprintf('Impossible to access a key "%s" on an object of class "%s" that does not implement ArrayAccess interface.', $item, get_class($object)); - } elseif (is_array($object)) { - if (empty($object)) { - $message = sprintf('Key "%s" does not exist as the array is empty.', $arrayItem); - } else { - $message = sprintf('Key "%s" for array with keys "%s" does not exist.', $arrayItem, implode(', ', array_keys($object))); - } - } elseif (self::ARRAY_CALL === $type) { - if (null === $object) { - $message = sprintf('Impossible to access a key ("%s") on a null variable.', $item); - } else { - $message = sprintf('Impossible to access a key ("%s") on a %s variable ("%s").', $item, gettype($object), $object); - } - } elseif (null === $object) { - $message = sprintf('Impossible to access an attribute ("%s") on a null variable.', $item); - } else { - $message = sprintf('Impossible to access an attribute ("%s") on a %s variable ("%s").', $item, gettype($object), $object); - } - - throw new Twig_Error_Runtime($message, -1, $this->getSourceContext()); - } - } - - if (!is_object($object)) { - if ($isDefinedTest) { - return false; - } - - if ($ignoreStrictCheck || !$this->env->isStrictVariables()) { - return; - } - - if (null === $object) { - $message = sprintf('Impossible to invoke a method ("%s") on a null variable.', $item); - } else { - $message = sprintf('Impossible to invoke a method ("%s") on a %s variable ("%s").', $item, gettype($object), $object); - } - - throw new Twig_Error_Runtime($message, -1, $this->getSourceContext()); - } - - // object property - if (self::METHOD_CALL !== $type && !$object instanceof self) { // Twig_Template does not have public properties, and we don't want to allow access to internal ones - if (isset($object->$item) || array_key_exists((string) $item, $object)) { - if ($isDefinedTest) { - return true; - } - - if ($this->env->hasExtension('Twig_Extension_Sandbox')) { - $this->env->getExtension('Twig_Extension_Sandbox')->checkPropertyAllowed($object, $item); - } - - return $object->$item; - } - } - - $class = get_class($object); - - // object method - if (!isset(self::$cache[$class])) { - // get_class_methods returns all methods accessible in the scope, but we only want public ones to be accessible in templates - if ($object instanceof self) { - $ref = new ReflectionClass($class); - $methods = array(); - - foreach ($ref->getMethods(ReflectionMethod::IS_PUBLIC) as $refMethod) { - // Accessing the environment from templates is forbidden to prevent untrusted changes to the environment - if ('getenvironment' !== strtolower($refMethod->name)) { - $methods[] = $refMethod->name; - } - } - } else { - $methods = get_class_methods($object); - } - // sort values to have consistent behavior, so that "get" methods win precedence over "is" methods - sort($methods); - - $cache = array(); - - foreach ($methods as $method) { - $cache[$method] = $method; - $cache[$lcName = strtolower($method)] = $method; - - if ('g' === $lcName[0] && 0 === strpos($lcName, 'get')) { - $name = substr($method, 3); - $lcName = substr($lcName, 3); - } elseif ('i' === $lcName[0] && 0 === strpos($lcName, 'is')) { - $name = substr($method, 2); - $lcName = substr($lcName, 2); - } else { - continue; - } - - // skip get() and is() methods (in which case, $name is empty) - if ($name) { - if (!isset($cache[$name])) { - $cache[$name] = $method; - } - if (!isset($cache[$lcName])) { - $cache[$lcName] = $method; - } - } - } - self::$cache[$class] = $cache; - } - - $call = false; - if (isset(self::$cache[$class][$item])) { - $method = self::$cache[$class][$item]; - } elseif (isset(self::$cache[$class][$lcItem = strtolower($item)])) { - $method = self::$cache[$class][$lcItem]; - } elseif (isset(self::$cache[$class]['__call'])) { - $method = $item; - $call = true; - } else { - if ($isDefinedTest) { - return false; - } - - if ($ignoreStrictCheck || !$this->env->isStrictVariables()) { - return; - } - - throw new Twig_Error_Runtime(sprintf('Neither the property "%1$s" nor one of the methods "%1$s()", "get%1$s()"/"is%1$s()" or "__call()" exist and have public access in class "%2$s".', $item, $class), -1, $this->getSourceContext()); - } - - if ($isDefinedTest) { - return true; - } - - if ($this->env->hasExtension('Twig_Extension_Sandbox')) { - $this->env->getExtension('Twig_Extension_Sandbox')->checkMethodAllowed($object, $method); - } - - // Some objects throw exceptions when they have __call, and the method we try - // to call is not supported. If ignoreStrictCheck is true, we should return null. - try { - if (!$arguments) { - $ret = $object->$method(); - } else { - $ret = call_user_func_array(array($object, $method), $arguments); - } - } catch (BadMethodCallException $e) { - if ($call && ($ignoreStrictCheck || !$this->env->isStrictVariables())) { - return; - } - throw $e; - } - - // @deprecated in 1.28 - if ($object instanceof Twig_TemplateInterface) { - $self = $object->getTemplateName() === $this->getTemplateName(); - $message = sprintf('Calling "%s" on template "%s" from template "%s" is deprecated since version 1.28 and won\'t be supported anymore in 2.0.', $item, $object->getTemplateName(), $this->getTemplateName()); - if ('renderBlock' === $method || 'displayBlock' === $method) { - $message .= sprintf(' Use block("%s"%s) instead).', $arguments[0], $self ? '' : ', template'); - } elseif ('hasBlock' === $method) { - $message .= sprintf(' Use "block("%s"%s) is defined" instead).', $arguments[0], $self ? '' : ', template'); - } elseif ('render' === $method || 'display' === $method) { - $message .= sprintf(' Use include("%s") instead).', $object->getTemplateName()); - } - @trigger_error($message, E_USER_DEPRECATED); - - return $ret === '' ? '' : new Twig_Markup($ret, $this->env->getCharset()); - } - - return $ret; } } - -class_alias('Twig_Template', 'Twig\Template', false); diff --git a/vendor/twig/twig/lib/Twig/TemplateInterface.php b/vendor/twig/twig/lib/Twig/TemplateInterface.php index 457ef7d7bb330d829adf9a907ceb44e4b1645bf6..0f767b8fc8d5a9b1fd316c524d47a29e35a5bda6 100644 --- a/vendor/twig/twig/lib/Twig/TemplateInterface.php +++ b/vendor/twig/twig/lib/Twig/TemplateInterface.php @@ -9,6 +9,8 @@ * file that was distributed with this source code. */ +use Twig\Environment; + /** * Interface implemented by all compiled templates. * @@ -37,12 +39,12 @@ interface Twig_TemplateInterface * @param array $context An array of parameters to pass to the template * @param array $blocks An array of blocks to pass to the template */ - public function display(array $context, array $blocks = array()); + public function display(array $context, array $blocks = []); /** * Returns the bound environment for this template. * - * @return Twig_Environment + * @return Environment */ public function getEnvironment(); } diff --git a/vendor/twig/twig/lib/Twig/TemplateWrapper.php b/vendor/twig/twig/lib/Twig/TemplateWrapper.php index 497f6e9803f2103f02673ed05c9319263a43cd08..6cb4ce4f7ea2f1b2d006ccfff68584c1f6c436e0 100644 --- a/vendor/twig/twig/lib/Twig/TemplateWrapper.php +++ b/vendor/twig/twig/lib/Twig/TemplateWrapper.php @@ -1,133 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +use Twig\TemplateWrapper; -/** - * Exposes a template to userland. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -final class Twig_TemplateWrapper -{ - private $env; - private $template; +class_exists('Twig\TemplateWrapper'); - /** - * This method is for internal use only and should never be called - * directly (use Twig_Environment::load() instead). - * - * @internal - */ - public function __construct(Twig_Environment $env, Twig_Template $template) +if (\false) { + class Twig_TemplateWrapper extends TemplateWrapper { - $this->env = $env; - $this->template = $template; - } - - /** - * Renders the template. - * - * @param array $context An array of parameters to pass to the template - * - * @return string The rendered template - */ - public function render($context = array()) - { - return $this->template->render($context); - } - - /** - * Displays the template. - * - * @param array $context An array of parameters to pass to the template - */ - public function display($context = array()) - { - $this->template->display($context); - } - - /** - * Checks if a block is defined. - * - * @param string $name The block name - * @param array $context An array of parameters to pass to the template - * - * @return bool - */ - public function hasBlock($name, $context = array()) - { - return $this->template->hasBlock($name, $context); - } - - /** - * Returns defined block names in the template. - * - * @param array $context An array of parameters to pass to the template - * - * @return string[] An array of defined template block names - */ - public function getBlockNames($context = array()) - { - return $this->template->getBlockNames($context); - } - - /** - * Renders a template block. - * - * @param string $name The block name to render - * @param array $context An array of parameters to pass to the template - * - * @return string The rendered block - */ - public function renderBlock($name, $context = array()) - { - $context = $this->env->mergeGlobals($context); - $level = ob_get_level(); - ob_start(); - try { - $this->template->displayBlock($name, $context); - } catch (Exception $e) { - while (ob_get_level() > $level) { - ob_end_clean(); - } - - throw $e; - } catch (Throwable $e) { - while (ob_get_level() > $level) { - ob_end_clean(); - } - - throw $e; - } - - return ob_get_clean(); - } - - /** - * Displays a template block. - * - * @param string $name The block name to render - * @param array $context An array of parameters to pass to the template - */ - public function displayBlock($name, $context = array()) - { - $this->template->displayBlock($name, $this->env->mergeGlobals($context)); - } - - /** - * @return Twig_Source - */ - public function getSourceContext() - { - return $this->template->getSourceContext(); } } - -class_alias('Twig_TemplateWrapper', 'Twig\TemplateWrapper', false); diff --git a/vendor/twig/twig/lib/Twig/Test.php b/vendor/twig/twig/lib/Twig/Test.php index b450ec625fe51115aa18cde152cb76a2d0ab0fcf..d032284eac67cf1879f6c1a8f9526b15161f2edb 100644 --- a/vendor/twig/twig/lib/Twig/Test.php +++ b/vendor/twig/twig/lib/Twig/Test.php @@ -9,7 +9,7 @@ * file that was distributed with this source code. */ -@trigger_error('The Twig_Test class is deprecated since version 1.12 and will be removed in 2.0. Use Twig_SimpleTest instead.', E_USER_DEPRECATED); +@trigger_error('The Twig_Test class is deprecated since version 1.12 and will be removed in 2.0. Use \Twig\TwigTest instead.', E_USER_DEPRECATED); /** * Represents a template test. @@ -21,13 +21,13 @@ abstract class Twig_Test implements Twig_TestInterface, Twig_TestCallableInterface { protected $options; - protected $arguments = array(); + protected $arguments = []; - public function __construct(array $options = array()) + public function __construct(array $options = []) { - $this->options = array_merge(array( + $this->options = array_merge([ 'callable' => null, - ), $options); + ], $options); } public function getCallable() diff --git a/vendor/twig/twig/lib/Twig/Test/Function.php b/vendor/twig/twig/lib/Twig/Test/Function.php index 9e83c3f844cdae49ec62cfa3c7e498e931c19b10..a789c4025937dea1f53d8136742a1b1c63b49c1f 100644 --- a/vendor/twig/twig/lib/Twig/Test/Function.php +++ b/vendor/twig/twig/lib/Twig/Test/Function.php @@ -9,7 +9,7 @@ * file that was distributed with this source code. */ -@trigger_error('The Twig_Test_Function class is deprecated since version 1.12 and will be removed in 2.0. Use Twig_SimpleTest instead.', E_USER_DEPRECATED); +@trigger_error('The Twig_Test_Function class is deprecated since version 1.12 and will be removed in 2.0. Use \Twig\TwigTest instead.', E_USER_DEPRECATED); /** * Represents a function template test. @@ -22,7 +22,7 @@ class Twig_Test_Function extends Twig_Test { protected $function; - public function __construct($function, array $options = array()) + public function __construct($function, array $options = []) { $options['callable'] = $function; diff --git a/vendor/twig/twig/lib/Twig/Test/IntegrationTestCase.php b/vendor/twig/twig/lib/Twig/Test/IntegrationTestCase.php index 016951aa61147c741742e35b6c7c1582e9f78192..e302bdbaf8aa910e7579df7a48508d84a80cc22c 100644 --- a/vendor/twig/twig/lib/Twig/Test/IntegrationTestCase.php +++ b/vendor/twig/twig/lib/Twig/Test/IntegrationTestCase.php @@ -1,249 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +use Twig\Test\IntegrationTestCase; -use PHPUnit\Framework\TestCase; +class_exists('Twig\Test\IntegrationTestCase'); -/** - * Integration test helper. - * - * @author Fabien Potencier <fabien@symfony.com> - * @author Karma Dordrak <drak@zikula.org> - */ -abstract class Twig_Test_IntegrationTestCase extends TestCase -{ - /** - * @return string - */ - abstract protected function getFixturesDir(); - - /** - * @return Twig_RuntimeLoaderInterface[] - */ - protected function getRuntimeLoaders() - { - return array(); - } - - /** - * @return Twig_ExtensionInterface[] - */ - protected function getExtensions() - { - return array(); - } - - /** - * @return Twig_SimpleFilter[] - */ - protected function getTwigFilters() - { - return array(); - } - - /** - * @return Twig_SimpleFunction[] - */ - protected function getTwigFunctions() - { - return array(); - } - - /** - * @return Twig_SimpleTest[] - */ - protected function getTwigTests() - { - return array(); - } - - /** - * @dataProvider getTests - */ - public function testIntegration($file, $message, $condition, $templates, $exception, $outputs) - { - $this->doIntegrationTest($file, $message, $condition, $templates, $exception, $outputs); - } - - /** - * @dataProvider getLegacyTests - * @group legacy - */ - public function testLegacyIntegration($file, $message, $condition, $templates, $exception, $outputs) +if (\false) { + class Twig_Test_IntegrationTestCase extends IntegrationTestCase { - $this->doIntegrationTest($file, $message, $condition, $templates, $exception, $outputs); - } - - public function getTests($name, $legacyTests = false) - { - $fixturesDir = realpath($this->getFixturesDir()); - $tests = array(); - - foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator($fixturesDir), RecursiveIteratorIterator::LEAVES_ONLY) as $file) { - if (!preg_match('/\.test$/', $file)) { - continue; - } - - if ($legacyTests xor false !== strpos($file->getRealpath(), '.legacy.test')) { - continue; - } - - $test = file_get_contents($file->getRealpath()); - - if (preg_match('/--TEST--\s*(.*?)\s*(?:--CONDITION--\s*(.*))?\s*((?:--TEMPLATE(?:\(.*?\))?--(?:.*?))+)\s*(?:--DATA--\s*(.*))?\s*--EXCEPTION--\s*(.*)/sx', $test, $match)) { - $message = $match[1]; - $condition = $match[2]; - $templates = self::parseTemplates($match[3]); - $exception = $match[5]; - $outputs = array(array(null, $match[4], null, '')); - } elseif (preg_match('/--TEST--\s*(.*?)\s*(?:--CONDITION--\s*(.*))?\s*((?:--TEMPLATE(?:\(.*?\))?--(?:.*?))+)--DATA--.*?--EXPECT--.*/s', $test, $match)) { - $message = $match[1]; - $condition = $match[2]; - $templates = self::parseTemplates($match[3]); - $exception = false; - preg_match_all('/--DATA--(.*?)(?:--CONFIG--(.*?))?--EXPECT--(.*?)(?=\-\-DATA\-\-|$)/s', $test, $outputs, PREG_SET_ORDER); - } else { - throw new InvalidArgumentException(sprintf('Test "%s" is not valid.', str_replace($fixturesDir.'/', '', $file))); - } - - $tests[] = array(str_replace($fixturesDir.'/', '', $file), $message, $condition, $templates, $exception, $outputs); - } - - if ($legacyTests && empty($tests)) { - // add a dummy test to avoid a PHPUnit message - return array(array('not', '-', '', array(), '', array())); - } - - return $tests; - } - - public function getLegacyTests() - { - return $this->getTests('testLegacyIntegration', true); - } - - protected function doIntegrationTest($file, $message, $condition, $templates, $exception, $outputs) - { - if (!$outputs) { - $this->markTestSkipped('no legacy tests to run'); - } - - if ($condition) { - eval('$ret = '.$condition.';'); - if (!$ret) { - $this->markTestSkipped($condition); - } - } - - $loader = new Twig_Loader_Array($templates); - - foreach ($outputs as $i => $match) { - $config = array_merge(array( - 'cache' => false, - 'strict_variables' => true, - ), $match[2] ? eval($match[2].';') : array()); - $twig = new Twig_Environment($loader, $config); - $twig->addGlobal('global', 'global'); - foreach ($this->getRuntimeLoaders() as $runtimeLoader) { - $twig->addRuntimeLoader($runtimeLoader); - } - - foreach ($this->getExtensions() as $extension) { - $twig->addExtension($extension); - } - - foreach ($this->getTwigFilters() as $filter) { - $twig->addFilter($filter); - } - - foreach ($this->getTwigTests() as $test) { - $twig->addTest($test); - } - - foreach ($this->getTwigFunctions() as $function) { - $twig->addFunction($function); - } - - // avoid using the same PHP class name for different cases - // only for PHP 5.2+ - if (PHP_VERSION_ID >= 50300) { - $p = new ReflectionProperty($twig, 'templateClassPrefix'); - $p->setAccessible(true); - $p->setValue($twig, '__TwigTemplate_'.hash('sha256', uniqid(mt_rand(), true), false).'_'); - } - - try { - $template = $twig->loadTemplate('index.twig'); - } catch (Exception $e) { - if (false !== $exception) { - $message = $e->getMessage(); - $this->assertSame(trim($exception), trim(sprintf('%s: %s', get_class($e), $message))); - $last = substr($message, strlen($message) - 1); - $this->assertTrue('.' === $last || '?' === $last, $message, 'Exception message must end with a dot or a question mark.'); - - return; - } - - throw new Twig_Error(sprintf('%s: %s', get_class($e), $e->getMessage()), -1, $file, $e); - } - - try { - $output = trim($template->render(eval($match[1].';')), "\n "); - } catch (Exception $e) { - if (false !== $exception) { - $this->assertSame(trim($exception), trim(sprintf('%s: %s', get_class($e), $e->getMessage()))); - - return; - } - - $e = new Twig_Error(sprintf('%s: %s', get_class($e), $e->getMessage()), -1, $file, $e); - - $output = trim(sprintf('%s: %s', get_class($e), $e->getMessage())); - } - - if (false !== $exception) { - list($class) = explode(':', $exception); - $constraintClass = class_exists('PHPUnit\Framework\Constraint\Exception') ? 'PHPUnit\Framework\Constraint\Exception' : 'PHPUnit_Framework_Constraint_Exception'; - $this->assertThat(null, new $constraintClass($class)); - } - - $expected = trim($match[3], "\n "); - - if ($expected !== $output) { - printf("Compiled templates that failed on case %d:\n", $i + 1); - - foreach (array_keys($templates) as $name) { - echo "Template: $name\n"; - $loader = $twig->getLoader(); - if (!$loader instanceof Twig_SourceContextLoaderInterface) { - $source = new Twig_Source($loader->getSource($name), $name); - } else { - $source = $loader->getSourceContext($name); - } - echo $twig->compile($twig->parse($twig->tokenize($source))); - } - } - $this->assertEquals($expected, $output, $message.' (in '.$file.')'); - } - } - - protected static function parseTemplates($test) - { - $templates = array(); - preg_match_all('/--TEMPLATE(?:\((.*?)\))?--(.*?)(?=\-\-TEMPLATE|$)/s', $test, $matches, PREG_SET_ORDER); - foreach ($matches as $match) { - $templates[($match[1] ? $match[1] : 'index.twig')] = $match[2]; - } - - return $templates; } } - -class_alias('Twig_Test_IntegrationTestCase', 'Twig\Test\IntegrationTestCase', false); diff --git a/vendor/twig/twig/lib/Twig/Test/Method.php b/vendor/twig/twig/lib/Twig/Test/Method.php index feccd5db345f0a1e6455c558f702b996f944c962..3559f34dc8cedd337a0b4167d3abfce8c35ffe69 100644 --- a/vendor/twig/twig/lib/Twig/Test/Method.php +++ b/vendor/twig/twig/lib/Twig/Test/Method.php @@ -9,7 +9,9 @@ * file that was distributed with this source code. */ -@trigger_error('The Twig_Test_Method class is deprecated since version 1.12 and will be removed in 2.0. Use Twig_SimpleTest instead.', E_USER_DEPRECATED); +use Twig\Extension\ExtensionInterface; + +@trigger_error('The Twig_Test_Method class is deprecated since version 1.12 and will be removed in 2.0. Use \Twig\TwigTest instead.', E_USER_DEPRECATED); /** * Represents a method template test. @@ -23,9 +25,9 @@ class Twig_Test_Method extends Twig_Test protected $extension; protected $method; - public function __construct(Twig_ExtensionInterface $extension, $method, array $options = array()) + public function __construct(ExtensionInterface $extension, $method, array $options = []) { - $options['callable'] = array($extension, $method); + $options['callable'] = [$extension, $method]; parent::__construct($options); @@ -35,6 +37,6 @@ class Twig_Test_Method extends Twig_Test public function compile() { - return sprintf('$this->env->getExtension(\'%s\')->%s', get_class($this->extension), $this->method); + return sprintf('$this->env->getExtension(\'%s\')->%s', \get_class($this->extension), $this->method); } } diff --git a/vendor/twig/twig/lib/Twig/Test/Node.php b/vendor/twig/twig/lib/Twig/Test/Node.php index 6098a5275f2058563673bed1a467fcc1a14a9bd6..6b5de1597b6cdf2e458eade80d8118b3f187c8f7 100644 --- a/vendor/twig/twig/lib/Twig/Test/Node.php +++ b/vendor/twig/twig/lib/Twig/Test/Node.php @@ -22,7 +22,7 @@ class Twig_Test_Node extends Twig_Test { protected $class; - public function __construct($class, array $options = array()) + public function __construct($class, array $options = []) { parent::__construct($options); diff --git a/vendor/twig/twig/lib/Twig/Test/NodeTestCase.php b/vendor/twig/twig/lib/Twig/Test/NodeTestCase.php index 47942675703a4799ae11480b311b355e371de7f1..62aaaaff7d797226f7817728b1bcf35b8e965f10 100644 --- a/vendor/twig/twig/lib/Twig/Test/NodeTestCase.php +++ b/vendor/twig/twig/lib/Twig/Test/NodeTestCase.php @@ -1,75 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +use Twig\Test\NodeTestCase; -use PHPUnit\Framework\TestCase; +class_exists('Twig\Test\NodeTestCase'); -abstract class Twig_Test_NodeTestCase extends TestCase -{ - abstract public function getTests(); - - /** - * @dataProvider getTests - */ - public function testCompile($node, $source, $environment = null, $isPattern = false) - { - $this->assertNodeCompilation($source, $node, $environment, $isPattern); - } - - public function assertNodeCompilation($source, Twig_Node $node, Twig_Environment $environment = null, $isPattern = false) - { - $compiler = $this->getCompiler($environment); - $compiler->compile($node); - - if ($isPattern) { - $this->assertStringMatchesFormat($source, trim($compiler->getSource())); - } else { - $this->assertEquals($source, trim($compiler->getSource())); - } - } - - protected function getCompiler(Twig_Environment $environment = null) - { - return new Twig_Compiler(null === $environment ? $this->getEnvironment() : $environment); - } - - protected function getEnvironment() +if (\false) { + class Twig_Test_NodeTestCase extends NodeTestCase { - return new Twig_Environment(new Twig_Loader_Array(array())); - } - - protected function getVariableGetter($name, $line = false) - { - $line = $line > 0 ? "// line {$line}\n" : ''; - - if (PHP_VERSION_ID >= 70000) { - return sprintf('%s($context["%s"] ?? null)', $line, $name, $name); - } - - if (PHP_VERSION_ID >= 50400) { - return sprintf('%s(isset($context["%s"]) ? $context["%s"] : null)', $line, $name, $name); - } - - return sprintf('%s$this->getContext($context, "%s")', $line, $name); - } - - protected function getAttributeGetter() - { - if (function_exists('twig_template_get_attributes')) { - return 'twig_template_get_attributes($this, '; - } - - return '$this->getAttribute('; } } - -class_alias('Twig_Test_NodeTestCase', 'Twig\Test\NodeTestCase', false); -class_exists('Twig_Environment'); -class_exists('Twig_Node'); diff --git a/vendor/twig/twig/lib/Twig/Token.php b/vendor/twig/twig/lib/Twig/Token.php index c7850eccc3d8a3f84105d4ce7d7dd69b9f326b0e..e4d18069eb64d876f9b0f82bfd58a1701c48e90b 100644 --- a/vendor/twig/twig/lib/Twig/Token.php +++ b/vendor/twig/twig/lib/Twig/Token.php @@ -1,207 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * (c) Armin Ronacher - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +use Twig\Token; -/** - * Represents a Token. - * - * @author Fabien Potencier <fabien@symfony.com> - * - * @final - */ -class Twig_Token -{ - protected $value; - protected $type; - protected $lineno; +class_exists('Twig\Token'); - const EOF_TYPE = -1; - const TEXT_TYPE = 0; - const BLOCK_START_TYPE = 1; - const VAR_START_TYPE = 2; - const BLOCK_END_TYPE = 3; - const VAR_END_TYPE = 4; - const NAME_TYPE = 5; - const NUMBER_TYPE = 6; - const STRING_TYPE = 7; - const OPERATOR_TYPE = 8; - const PUNCTUATION_TYPE = 9; - const INTERPOLATION_START_TYPE = 10; - const INTERPOLATION_END_TYPE = 11; - - /** - * @param int $type The type of the token - * @param string $value The token value - * @param int $lineno The line position in the source - */ - public function __construct($type, $value, $lineno) - { - $this->type = $type; - $this->value = $value; - $this->lineno = $lineno; - } - - public function __toString() +if (\false) { + class Twig_Token extends Token { - return sprintf('%s(%s)', self::typeToString($this->type, true), $this->value); - } - - /** - * Tests the current token for a type and/or a value. - * - * Parameters may be: - * * just type - * * type and value (or array of possible values) - * * just value (or array of possible values) (NAME_TYPE is used as type) - * - * @param array|int $type The type to test - * @param array|string|null $values The token value - * - * @return bool - */ - public function test($type, $values = null) - { - if (null === $values && !is_int($type)) { - $values = $type; - $type = self::NAME_TYPE; - } - - return ($this->type === $type) && ( - null === $values || - (is_array($values) && in_array($this->value, $values)) || - $this->value == $values - ); - } - - /** - * @return int - */ - public function getLine() - { - return $this->lineno; - } - - /** - * @return int - */ - public function getType() - { - return $this->type; - } - - /** - * @return string - */ - public function getValue() - { - return $this->value; - } - - /** - * Returns the constant representation (internal) of a given type. - * - * @param int $type The type as an integer - * @param bool $short Whether to return a short representation or not - * - * @return string The string representation - */ - public static function typeToString($type, $short = false) - { - switch ($type) { - case self::EOF_TYPE: - $name = 'EOF_TYPE'; - break; - case self::TEXT_TYPE: - $name = 'TEXT_TYPE'; - break; - case self::BLOCK_START_TYPE: - $name = 'BLOCK_START_TYPE'; - break; - case self::VAR_START_TYPE: - $name = 'VAR_START_TYPE'; - break; - case self::BLOCK_END_TYPE: - $name = 'BLOCK_END_TYPE'; - break; - case self::VAR_END_TYPE: - $name = 'VAR_END_TYPE'; - break; - case self::NAME_TYPE: - $name = 'NAME_TYPE'; - break; - case self::NUMBER_TYPE: - $name = 'NUMBER_TYPE'; - break; - case self::STRING_TYPE: - $name = 'STRING_TYPE'; - break; - case self::OPERATOR_TYPE: - $name = 'OPERATOR_TYPE'; - break; - case self::PUNCTUATION_TYPE: - $name = 'PUNCTUATION_TYPE'; - break; - case self::INTERPOLATION_START_TYPE: - $name = 'INTERPOLATION_START_TYPE'; - break; - case self::INTERPOLATION_END_TYPE: - $name = 'INTERPOLATION_END_TYPE'; - break; - default: - throw new LogicException(sprintf('Token of type "%s" does not exist.', $type)); - } - - return $short ? $name : 'Twig_Token::'.$name; - } - - /** - * Returns the English representation of a given type. - * - * @param int $type The type as an integer - * - * @return string The string representation - */ - public static function typeToEnglish($type) - { - switch ($type) { - case self::EOF_TYPE: - return 'end of template'; - case self::TEXT_TYPE: - return 'text'; - case self::BLOCK_START_TYPE: - return 'begin of statement block'; - case self::VAR_START_TYPE: - return 'begin of print statement'; - case self::BLOCK_END_TYPE: - return 'end of statement block'; - case self::VAR_END_TYPE: - return 'end of print statement'; - case self::NAME_TYPE: - return 'name'; - case self::NUMBER_TYPE: - return 'number'; - case self::STRING_TYPE: - return 'string'; - case self::OPERATOR_TYPE: - return 'operator'; - case self::PUNCTUATION_TYPE: - return 'punctuation'; - case self::INTERPOLATION_START_TYPE: - return 'begin of string interpolation'; - case self::INTERPOLATION_END_TYPE: - return 'end of string interpolation'; - default: - throw new LogicException(sprintf('Token of type "%s" does not exist.', $type)); - } } } - -class_alias('Twig_Token', 'Twig\Token', false); diff --git a/vendor/twig/twig/lib/Twig/TokenParser.php b/vendor/twig/twig/lib/Twig/TokenParser.php index 1b4de14da53cdb60f46dac3032616147df2849a8..c0595438ab0d51fd92a81cc6c2d7d93b3514c225 100644 --- a/vendor/twig/twig/lib/Twig/TokenParser.php +++ b/vendor/twig/twig/lib/Twig/TokenParser.php @@ -1,33 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +use Twig\TokenParser\AbstractTokenParser; -/** - * Base class for all token parsers. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -abstract class Twig_TokenParser implements Twig_TokenParserInterface -{ - /** - * @var Twig_Parser - */ - protected $parser; +class_exists('Twig\TokenParser\AbstractTokenParser'); - /** - * Sets the parser associated with this token parser. - */ - public function setParser(Twig_Parser $parser) +if (\false) { + class Twig_TokenParser extends AbstractTokenParser { - $this->parser = $parser; } } - -class_alias('Twig_TokenParser', 'Twig\TokenParser\AbstractTokenParser', false); diff --git a/vendor/twig/twig/lib/Twig/TokenParser/AutoEscape.php b/vendor/twig/twig/lib/Twig/TokenParser/AutoEscape.php index a20dedd18e6048ea7428655979365da5713305a8..3f9e528d2e88ac1cb9da581b1e41c31e235805c9 100644 --- a/vendor/twig/twig/lib/Twig/TokenParser/AutoEscape.php +++ b/vendor/twig/twig/lib/Twig/TokenParser/AutoEscape.php @@ -1,83 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +use Twig\TokenParser\AutoEscapeTokenParser; -/** - * Marks a section of a template to be escaped or not. - * - * <pre> - * {% autoescape true %} - * Everything will be automatically escaped in this block - * {% endautoescape %} - * - * {% autoescape false %} - * Everything will be outputed as is in this block - * {% endautoescape %} - * - * {% autoescape true js %} - * Everything will be automatically escaped in this block - * using the js escaping strategy - * {% endautoescape %} - * </pre> - * - * @final - */ -class Twig_TokenParser_AutoEscape extends Twig_TokenParser -{ - public function parse(Twig_Token $token) - { - $lineno = $token->getLine(); - $stream = $this->parser->getStream(); - - if ($stream->test(Twig_Token::BLOCK_END_TYPE)) { - $value = 'html'; - } else { - $expr = $this->parser->getExpressionParser()->parseExpression(); - if (!$expr instanceof Twig_Node_Expression_Constant) { - throw new Twig_Error_Syntax('An escaping strategy must be a string or a bool.', $stream->getCurrent()->getLine(), $stream->getSourceContext()); - } - $value = $expr->getAttribute('value'); - - $compat = true === $value || false === $value; - - if (true === $value) { - $value = 'html'; - } - - if ($compat && $stream->test(Twig_Token::NAME_TYPE)) { - @trigger_error('Using the autoescape tag with "true" or "false" before the strategy name is deprecated since version 1.21.', E_USER_DEPRECATED); - - if (false === $value) { - throw new Twig_Error_Syntax('Unexpected escaping strategy as you set autoescaping to false.', $stream->getCurrent()->getLine(), $stream->getSourceContext()); - } - - $value = $stream->next()->getValue(); - } - } +class_exists('Twig\TokenParser\AutoEscapeTokenParser'); - $stream->expect(Twig_Token::BLOCK_END_TYPE); - $body = $this->parser->subparse(array($this, 'decideBlockEnd'), true); - $stream->expect(Twig_Token::BLOCK_END_TYPE); - - return new Twig_Node_AutoEscape($value, $body, $lineno, $this->getTag()); - } - - public function decideBlockEnd(Twig_Token $token) +if (\false) { + class Twig_TokenParser_AutoEscape extends AutoEscapeTokenParser { - return $token->test('endautoescape'); - } - - public function getTag() - { - return 'autoescape'; } } - -class_alias('Twig_TokenParser_AutoEscape', 'Twig\TokenParser\AutoEscapeTokenParser', false); diff --git a/vendor/twig/twig/lib/Twig/TokenParser/Block.php b/vendor/twig/twig/lib/Twig/TokenParser/Block.php index f30f86b5812491120e792aa77b1d56bc835efe94..d2f687702353a831874cab9d86ac231c0aa8fe98 100644 --- a/vendor/twig/twig/lib/Twig/TokenParser/Block.php +++ b/vendor/twig/twig/lib/Twig/TokenParser/Block.php @@ -1,73 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * (c) Armin Ronacher - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +use Twig\TokenParser\BlockTokenParser; -/** - * Marks a section of a template as being reusable. - * - * <pre> - * {% block head %} - * <link rel="stylesheet" href="style.css" /> - * <title>{% block title %}{% endblock %} - My Webpage</title> - * {% endblock %} - * </pre> - * - * @final - */ -class Twig_TokenParser_Block extends Twig_TokenParser -{ - public function parse(Twig_Token $token) - { - $lineno = $token->getLine(); - $stream = $this->parser->getStream(); - $name = $stream->expect(Twig_Token::NAME_TYPE)->getValue(); - if ($this->parser->hasBlock($name)) { - throw new Twig_Error_Syntax(sprintf("The block '%s' has already been defined line %d.", $name, $this->parser->getBlock($name)->getTemplateLine()), $stream->getCurrent()->getLine(), $stream->getSourceContext()); - } - $this->parser->setBlock($name, $block = new Twig_Node_Block($name, new Twig_Node(array()), $lineno)); - $this->parser->pushLocalScope(); - $this->parser->pushBlockStack($name); - - if ($stream->nextIf(Twig_Token::BLOCK_END_TYPE)) { - $body = $this->parser->subparse(array($this, 'decideBlockEnd'), true); - if ($token = $stream->nextIf(Twig_Token::NAME_TYPE)) { - $value = $token->getValue(); - - if ($value != $name) { - throw new Twig_Error_Syntax(sprintf('Expected endblock for block "%s" (but "%s" given).', $name, $value), $stream->getCurrent()->getLine(), $stream->getSourceContext()); - } - } - } else { - $body = new Twig_Node(array( - new Twig_Node_Print($this->parser->getExpressionParser()->parseExpression(), $lineno), - )); - } - $stream->expect(Twig_Token::BLOCK_END_TYPE); - - $block->setNode('body', $body); - $this->parser->popBlockStack(); - $this->parser->popLocalScope(); - - return new Twig_Node_BlockReference($name, $lineno, $this->getTag()); - } +class_exists('Twig\TokenParser\BlockTokenParser'); - public function decideBlockEnd(Twig_Token $token) +if (\false) { + class Twig_TokenParser_Block extends BlockTokenParser { - return $token->test('endblock'); - } - - public function getTag() - { - return 'block'; } } - -class_alias('Twig_TokenParser_Block', 'Twig\TokenParser\BlockTokenParser', false); diff --git a/vendor/twig/twig/lib/Twig/TokenParser/Deprecated.php b/vendor/twig/twig/lib/Twig/TokenParser/Deprecated.php new file mode 100644 index 0000000000000000000000000000000000000000..9a74fe43e13a91ab6c6e2dbe688726ff20202b13 --- /dev/null +++ b/vendor/twig/twig/lib/Twig/TokenParser/Deprecated.php @@ -0,0 +1,11 @@ +<?php + +use Twig\TokenParser\DeprecatedTokenParser; + +class_exists('Twig\TokenParser\DeprecatedTokenParser'); + +if (\false) { + class Twig_TokenParser_Deprecated extends DeprecatedTokenParser + { + } +} diff --git a/vendor/twig/twig/lib/Twig/TokenParser/Do.php b/vendor/twig/twig/lib/Twig/TokenParser/Do.php index 8ce088089e0c6440efc67e15abb19483a2551e2a..0750e471ecced9f7b21eb5279531430494d4ea22 100644 --- a/vendor/twig/twig/lib/Twig/TokenParser/Do.php +++ b/vendor/twig/twig/lib/Twig/TokenParser/Do.php @@ -1,34 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +use Twig\TokenParser\DoTokenParser; -/** - * Evaluates an expression, discarding the returned value. - * - * @final - */ -class Twig_TokenParser_Do extends Twig_TokenParser -{ - public function parse(Twig_Token $token) - { - $expr = $this->parser->getExpressionParser()->parseExpression(); - - $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE); +class_exists('Twig\TokenParser\DoTokenParser'); - return new Twig_Node_Do($expr, $token->getLine(), $this->getTag()); - } - - public function getTag() +if (\false) { + class Twig_TokenParser_Do extends DoTokenParser { - return 'do'; } } - -class_alias('Twig_TokenParser_Do', 'Twig\TokenParser\DoTokenParser', false); diff --git a/vendor/twig/twig/lib/Twig/TokenParser/Embed.php b/vendor/twig/twig/lib/Twig/TokenParser/Embed.php index 44644cc6bbdf335a4182d44208ec2859dd8ee181..a60c26734f0a64c0e5c41da60317944218b91a29 100644 --- a/vendor/twig/twig/lib/Twig/TokenParser/Embed.php +++ b/vendor/twig/twig/lib/Twig/TokenParser/Embed.php @@ -1,67 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +use Twig\TokenParser\EmbedTokenParser; -/** - * Embeds a template. - * - * @final - */ -class Twig_TokenParser_Embed extends Twig_TokenParser_Include -{ - public function parse(Twig_Token $token) - { - $stream = $this->parser->getStream(); - - $parent = $this->parser->getExpressionParser()->parseExpression(); - - list($variables, $only, $ignoreMissing) = $this->parseArguments(); - - $parentToken = $fakeParentToken = new Twig_Token(Twig_Token::STRING_TYPE, '__parent__', $token->getLine()); - if ($parent instanceof Twig_Node_Expression_Constant) { - $parentToken = new Twig_Token(Twig_Token::STRING_TYPE, $parent->getAttribute('value'), $token->getLine()); - } elseif ($parent instanceof Twig_Node_Expression_Name) { - $parentToken = new Twig_Token(Twig_Token::NAME_TYPE, $parent->getAttribute('name'), $token->getLine()); - } - - // inject a fake parent to make the parent() function work - $stream->injectTokens(array( - new Twig_Token(Twig_Token::BLOCK_START_TYPE, '', $token->getLine()), - new Twig_Token(Twig_Token::NAME_TYPE, 'extends', $token->getLine()), - $parentToken, - new Twig_Token(Twig_Token::BLOCK_END_TYPE, '', $token->getLine()), - )); - - $module = $this->parser->parse($stream, array($this, 'decideBlockEnd'), true); - - // override the parent with the correct one - if ($fakeParentToken === $parentToken) { - $module->setNode('parent', $parent); - } - - $this->parser->embedTemplate($module); +class_exists('Twig\TokenParser\EmbedTokenParser'); - $stream->expect(Twig_Token::BLOCK_END_TYPE); - - return new Twig_Node_Embed($module->getTemplateName(), $module->getAttribute('index'), $variables, $only, $ignoreMissing, $token->getLine(), $this->getTag()); - } - - public function decideBlockEnd(Twig_Token $token) +if (\false) { + class Twig_TokenParser_Embed extends EmbedTokenParser { - return $token->test('endembed'); - } - - public function getTag() - { - return 'embed'; } } - -class_alias('Twig_TokenParser_Embed', 'Twig\TokenParser\EmbedTokenParser', false); diff --git a/vendor/twig/twig/lib/Twig/TokenParser/Extends.php b/vendor/twig/twig/lib/Twig/TokenParser/Extends.php index 31168ccec36d7943306f89eba92fe15e6bbccc99..79cc2d3a3dad2b8ebce539040301483c4ecc391d 100644 --- a/vendor/twig/twig/lib/Twig/TokenParser/Extends.php +++ b/vendor/twig/twig/lib/Twig/TokenParser/Extends.php @@ -1,46 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * (c) Armin Ronacher - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +use Twig\TokenParser\ExtendsTokenParser; -/** - * Extends a template by another one. - * - * <pre> - * {% extends "base.html" %} - * </pre> - * - * @final - */ -class Twig_TokenParser_Extends extends Twig_TokenParser -{ - public function parse(Twig_Token $token) - { - $stream = $this->parser->getStream(); - - if (!$this->parser->isMainScope()) { - throw new Twig_Error_Syntax('Cannot extend from a block.', $token->getLine(), $stream->getSourceContext()); - } - - if (null !== $this->parser->getParent()) { - throw new Twig_Error_Syntax('Multiple extends tags are forbidden.', $token->getLine(), $stream->getSourceContext()); - } - $this->parser->setParent($this->parser->getExpressionParser()->parseExpression()); +class_exists('Twig\TokenParser\ExtendsTokenParser'); - $stream->expect(Twig_Token::BLOCK_END_TYPE); - } - - public function getTag() +if (\false) { + class Twig_TokenParser_Extends extends ExtendsTokenParser { - return 'extends'; } } - -class_alias('Twig_TokenParser_Extends', 'Twig\TokenParser\ExtendsTokenParser', false); diff --git a/vendor/twig/twig/lib/Twig/TokenParser/Filter.php b/vendor/twig/twig/lib/Twig/TokenParser/Filter.php index 760178293e752a0f8ed0fc796783bb3d67de54bd..5110c2344f0db4c30e88cbb31339e66ab0592832 100644 --- a/vendor/twig/twig/lib/Twig/TokenParser/Filter.php +++ b/vendor/twig/twig/lib/Twig/TokenParser/Filter.php @@ -1,53 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +use Twig\TokenParser\FilterTokenParser; -/** - * Filters a section of a template by applying filters. - * - * <pre> - * {% filter upper %} - * This text becomes uppercase - * {% endfilter %} - * </pre> - * - * @final - */ -class Twig_TokenParser_Filter extends Twig_TokenParser -{ - public function parse(Twig_Token $token) - { - $name = $this->parser->getVarName(); - $ref = new Twig_Node_Expression_BlockReference(new Twig_Node_Expression_Constant($name, $token->getLine()), null, $token->getLine(), $this->getTag()); - - $filter = $this->parser->getExpressionParser()->parseFilterExpressionRaw($ref, $this->getTag()); - $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE); - - $body = $this->parser->subparse(array($this, 'decideBlockEnd'), true); - $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE); - - $block = new Twig_Node_Block($name, $body, $token->getLine()); - $this->parser->setBlock($name, $block); - - return new Twig_Node_Print($filter, $token->getLine(), $this->getTag()); - } +class_exists('Twig\TokenParser\FilterTokenParser'); - public function decideBlockEnd(Twig_Token $token) +if (\false) { + class Twig_TokenParser_Filter extends FilterTokenParser { - return $token->test('endfilter'); - } - - public function getTag() - { - return 'filter'; } } - -class_alias('Twig_TokenParser_Filter', 'Twig\TokenParser\FilterTokenParser', false); diff --git a/vendor/twig/twig/lib/Twig/TokenParser/Flush.php b/vendor/twig/twig/lib/Twig/TokenParser/Flush.php index 51832c77e11689cae4efa08410e00921804b6ceb..df8be30ddf9e6ddadb15b002c23140181a446abf 100644 --- a/vendor/twig/twig/lib/Twig/TokenParser/Flush.php +++ b/vendor/twig/twig/lib/Twig/TokenParser/Flush.php @@ -1,34 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +use Twig\TokenParser\FlushTokenParser; -/** - * Flushes the output to the client. - * - * @see flush() - * - * @final - */ -class Twig_TokenParser_Flush extends Twig_TokenParser -{ - public function parse(Twig_Token $token) - { - $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE); - - return new Twig_Node_Flush($token->getLine(), $this->getTag()); - } +class_exists('Twig\TokenParser\FlushTokenParser'); - public function getTag() +if (\false) { + class Twig_TokenParser_Flush extends FlushTokenParser { - return 'flush'; } } - -class_alias('Twig_TokenParser_Flush', 'Twig\TokenParser\FlushTokenParser', false); diff --git a/vendor/twig/twig/lib/Twig/TokenParser/For.php b/vendor/twig/twig/lib/Twig/TokenParser/For.php index 63bf41d665425e1f61b8671018d00b988b8cd086..596dad785b7f70fd612f284d63d6fc267c52383d 100644 --- a/vendor/twig/twig/lib/Twig/TokenParser/For.php +++ b/vendor/twig/twig/lib/Twig/TokenParser/For.php @@ -1,127 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * (c) Armin Ronacher - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +use Twig\TokenParser\ForTokenParser; -/** - * Loops over each item of a sequence. - * - * <pre> - * <ul> - * {% for user in users %} - * <li>{{ user.username|e }}</li> - * {% endfor %} - * </ul> - * </pre> - * - * @final - */ -class Twig_TokenParser_For extends Twig_TokenParser -{ - public function parse(Twig_Token $token) - { - $lineno = $token->getLine(); - $stream = $this->parser->getStream(); - $targets = $this->parser->getExpressionParser()->parseAssignmentExpression(); - $stream->expect(Twig_Token::OPERATOR_TYPE, 'in'); - $seq = $this->parser->getExpressionParser()->parseExpression(); - - $ifexpr = null; - if ($stream->nextIf(Twig_Token::NAME_TYPE, 'if')) { - $ifexpr = $this->parser->getExpressionParser()->parseExpression(); - } - - $stream->expect(Twig_Token::BLOCK_END_TYPE); - $body = $this->parser->subparse(array($this, 'decideForFork')); - if ($stream->next()->getValue() == 'else') { - $stream->expect(Twig_Token::BLOCK_END_TYPE); - $else = $this->parser->subparse(array($this, 'decideForEnd'), true); - } else { - $else = null; - } - $stream->expect(Twig_Token::BLOCK_END_TYPE); - - if (count($targets) > 1) { - $keyTarget = $targets->getNode(0); - $keyTarget = new Twig_Node_Expression_AssignName($keyTarget->getAttribute('name'), $keyTarget->getTemplateLine()); - $valueTarget = $targets->getNode(1); - $valueTarget = new Twig_Node_Expression_AssignName($valueTarget->getAttribute('name'), $valueTarget->getTemplateLine()); - } else { - $keyTarget = new Twig_Node_Expression_AssignName('_key', $lineno); - $valueTarget = $targets->getNode(0); - $valueTarget = new Twig_Node_Expression_AssignName($valueTarget->getAttribute('name'), $valueTarget->getTemplateLine()); - } - - if ($ifexpr) { - $this->checkLoopUsageCondition($stream, $ifexpr); - $this->checkLoopUsageBody($stream, $body); - } - - return new Twig_Node_For($keyTarget, $valueTarget, $seq, $ifexpr, $body, $else, $lineno, $this->getTag()); - } +class_exists('Twig\TokenParser\ForTokenParser'); - public function decideForFork(Twig_Token $token) +if (\false) { + class Twig_TokenParser_For extends ForTokenParser { - return $token->test(array('else', 'endfor')); - } - - public function decideForEnd(Twig_Token $token) - { - return $token->test('endfor'); - } - - // the loop variable cannot be used in the condition - protected function checkLoopUsageCondition(Twig_TokenStream $stream, Twig_NodeInterface $node) - { - if ($node instanceof Twig_Node_Expression_GetAttr && $node->getNode('node') instanceof Twig_Node_Expression_Name && 'loop' == $node->getNode('node')->getAttribute('name')) { - throw new Twig_Error_Syntax('The "loop" variable cannot be used in a looping condition.', $node->getTemplateLine(), $stream->getSourceContext()); - } - - foreach ($node as $n) { - if (!$n) { - continue; - } - - $this->checkLoopUsageCondition($stream, $n); - } - } - - // check usage of non-defined loop-items - // it does not catch all problems (for instance when a for is included into another or when the variable is used in an include) - protected function checkLoopUsageBody(Twig_TokenStream $stream, Twig_NodeInterface $node) - { - if ($node instanceof Twig_Node_Expression_GetAttr && $node->getNode('node') instanceof Twig_Node_Expression_Name && 'loop' == $node->getNode('node')->getAttribute('name')) { - $attribute = $node->getNode('attribute'); - if ($attribute instanceof Twig_Node_Expression_Constant && in_array($attribute->getAttribute('value'), array('length', 'revindex0', 'revindex', 'last'))) { - throw new Twig_Error_Syntax(sprintf('The "loop.%s" variable is not defined when looping with a condition.', $attribute->getAttribute('value')), $node->getTemplateLine(), $stream->getSourceContext()); - } - } - - // should check for parent.loop.XXX usage - if ($node instanceof Twig_Node_For) { - return; - } - - foreach ($node as $n) { - if (!$n) { - continue; - } - - $this->checkLoopUsageBody($stream, $n); - } - } - - public function getTag() - { - return 'for'; } } - -class_alias('Twig_TokenParser_For', 'Twig\TokenParser\ForTokenParser', false); diff --git a/vendor/twig/twig/lib/Twig/TokenParser/From.php b/vendor/twig/twig/lib/Twig/TokenParser/From.php index f3053da4b9fdfd1e05f5632ad118832122a8d33a..af794be8898f0f9ea98ea301a98e24044797310e 100644 --- a/vendor/twig/twig/lib/Twig/TokenParser/From.php +++ b/vendor/twig/twig/lib/Twig/TokenParser/From.php @@ -1,66 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +use Twig\TokenParser\FromTokenParser; -/** - * Imports macros. - * - * <pre> - * {% from 'forms.html' import forms %} - * </pre> - * - * @final - */ -class Twig_TokenParser_From extends Twig_TokenParser -{ - public function parse(Twig_Token $token) - { - $macro = $this->parser->getExpressionParser()->parseExpression(); - $stream = $this->parser->getStream(); - $stream->expect('import'); - - $targets = array(); - do { - $name = $stream->expect(Twig_Token::NAME_TYPE)->getValue(); - - $alias = $name; - if ($stream->nextIf('as')) { - $alias = $stream->expect(Twig_Token::NAME_TYPE)->getValue(); - } - - $targets[$name] = $alias; - - if (!$stream->nextIf(Twig_Token::PUNCTUATION_TYPE, ',')) { - break; - } - } while (true); - - $stream->expect(Twig_Token::BLOCK_END_TYPE); +class_exists('Twig\TokenParser\FromTokenParser'); - $node = new Twig_Node_Import($macro, new Twig_Node_Expression_AssignName($this->parser->getVarName(), $token->getLine()), $token->getLine(), $this->getTag()); - - foreach ($targets as $name => $alias) { - if ($this->parser->isReservedMacroName($name)) { - throw new Twig_Error_Syntax(sprintf('"%s" cannot be an imported macro as it is a reserved keyword.', $name), $token->getLine(), $stream->getSourceContext()); - } - - $this->parser->addImportedSymbol('function', $alias, 'get'.$name, $node->getNode('var')); - } - - return $node; - } - - public function getTag() +if (\false) { + class Twig_TokenParser_From extends FromTokenParser { - return 'from'; } } - -class_alias('Twig_TokenParser_From', 'Twig\TokenParser\FromTokenParser', false); diff --git a/vendor/twig/twig/lib/Twig/TokenParser/If.php b/vendor/twig/twig/lib/Twig/TokenParser/If.php index f081df3abd2aa77f944a38a810283dbc7e7cba0d..e035c5ed5f91d15ed03eb0c7d9898e81ab39cbb3 100644 --- a/vendor/twig/twig/lib/Twig/TokenParser/If.php +++ b/vendor/twig/twig/lib/Twig/TokenParser/If.php @@ -1,86 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * (c) Armin Ronacher - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +use Twig\TokenParser\IfTokenParser; -/** - * Tests a condition. - * - * <pre> - * {% if users %} - * <ul> - * {% for user in users %} - * <li>{{ user.username|e }}</li> - * {% endfor %} - * </ul> - * {% endif %} - * </pre> - * - * @final - */ -class Twig_TokenParser_If extends Twig_TokenParser -{ - public function parse(Twig_Token $token) - { - $lineno = $token->getLine(); - $expr = $this->parser->getExpressionParser()->parseExpression(); - $stream = $this->parser->getStream(); - $stream->expect(Twig_Token::BLOCK_END_TYPE); - $body = $this->parser->subparse(array($this, 'decideIfFork')); - $tests = array($expr, $body); - $else = null; - - $end = false; - while (!$end) { - switch ($stream->next()->getValue()) { - case 'else': - $stream->expect(Twig_Token::BLOCK_END_TYPE); - $else = $this->parser->subparse(array($this, 'decideIfEnd')); - break; - - case 'elseif': - $expr = $this->parser->getExpressionParser()->parseExpression(); - $stream->expect(Twig_Token::BLOCK_END_TYPE); - $body = $this->parser->subparse(array($this, 'decideIfFork')); - $tests[] = $expr; - $tests[] = $body; - break; - - case 'endif': - $end = true; - break; - - default: - throw new Twig_Error_Syntax(sprintf('Unexpected end of template. Twig was looking for the following tags "else", "elseif", or "endif" to close the "if" block started at line %d).', $lineno), $stream->getCurrent()->getLine(), $stream->getSourceContext()); - } - } - - $stream->expect(Twig_Token::BLOCK_END_TYPE); - - return new Twig_Node_If(new Twig_Node($tests), $else, $lineno, $this->getTag()); - } +class_exists('Twig\TokenParser\IfTokenParser'); - public function decideIfFork(Twig_Token $token) +if (\false) { + class Twig_TokenParser_If extends IfTokenParser { - return $token->test(array('elseif', 'else', 'endif')); - } - - public function decideIfEnd(Twig_Token $token) - { - return $token->test(array('endif')); - } - - public function getTag() - { - return 'if'; } } - -class_alias('Twig_TokenParser_If', 'Twig\TokenParser\IfTokenParser', false); diff --git a/vendor/twig/twig/lib/Twig/TokenParser/Import.php b/vendor/twig/twig/lib/Twig/TokenParser/Import.php index 47802f502aa63981429ab3560b124dbcc537db1d..2ee0165368ad6522ae364bcf8c53dd40496abc02 100644 --- a/vendor/twig/twig/lib/Twig/TokenParser/Import.php +++ b/vendor/twig/twig/lib/Twig/TokenParser/Import.php @@ -1,41 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +use Twig\TokenParser\ImportTokenParser; -/** - * Imports macros. - * - * <pre> - * {% import 'forms.html' as forms %} - * </pre> - * - * @final - */ -class Twig_TokenParser_Import extends Twig_TokenParser -{ - public function parse(Twig_Token $token) - { - $macro = $this->parser->getExpressionParser()->parseExpression(); - $this->parser->getStream()->expect('as'); - $var = new Twig_Node_Expression_AssignName($this->parser->getStream()->expect(Twig_Token::NAME_TYPE)->getValue(), $token->getLine()); - $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE); - - $this->parser->addImportedSymbol('template', $var->getAttribute('name')); +class_exists('Twig\TokenParser\ImportTokenParser'); - return new Twig_Node_Import($macro, $var, $token->getLine(), $this->getTag()); - } - - public function getTag() +if (\false) { + class Twig_TokenParser_Import extends ImportTokenParser { - return 'import'; } } - -class_alias('Twig_TokenParser_Import', 'Twig\TokenParser\ImportTokenParser', false); diff --git a/vendor/twig/twig/lib/Twig/TokenParser/Include.php b/vendor/twig/twig/lib/Twig/TokenParser/Include.php index 309f11db4738358106e594bd2866f8e61254d97f..6047c615dda206d4fb94a8a93bd3a064d63a4c0a 100644 --- a/vendor/twig/twig/lib/Twig/TokenParser/Include.php +++ b/vendor/twig/twig/lib/Twig/TokenParser/Include.php @@ -1,65 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * (c) Armin Ronacher - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +use Twig\TokenParser\IncludeTokenParser; -/** - * Includes a template. - * - * <pre> - * {% include 'header.html' %} - * Body - * {% include 'footer.html' %} - * </pre> - */ -class Twig_TokenParser_Include extends Twig_TokenParser -{ - public function parse(Twig_Token $token) - { - $expr = $this->parser->getExpressionParser()->parseExpression(); - - list($variables, $only, $ignoreMissing) = $this->parseArguments(); - - return new Twig_Node_Include($expr, $variables, $only, $ignoreMissing, $token->getLine(), $this->getTag()); - } - - protected function parseArguments() - { - $stream = $this->parser->getStream(); - - $ignoreMissing = false; - if ($stream->nextIf(Twig_Token::NAME_TYPE, 'ignore')) { - $stream->expect(Twig_Token::NAME_TYPE, 'missing'); +class_exists('Twig\TokenParser\IncludeTokenParser'); - $ignoreMissing = true; - } - - $variables = null; - if ($stream->nextIf(Twig_Token::NAME_TYPE, 'with')) { - $variables = $this->parser->getExpressionParser()->parseExpression(); - } - - $only = false; - if ($stream->nextIf(Twig_Token::NAME_TYPE, 'only')) { - $only = true; - } - - $stream->expect(Twig_Token::BLOCK_END_TYPE); - - return array($variables, $only, $ignoreMissing); - } - - public function getTag() +if (\false) { + class Twig_TokenParser_Include extends IncludeTokenParser { - return 'include'; } } - -class_alias('Twig_TokenParser_Include', 'Twig\TokenParser\IncludeTokenParser', false); diff --git a/vendor/twig/twig/lib/Twig/TokenParser/Macro.php b/vendor/twig/twig/lib/Twig/TokenParser/Macro.php index 4287934bad52f3149862e9fe5c8d9dd99a23fdc6..523de8c1c75c329f14ad5f72fceac2e26befb4fd 100644 --- a/vendor/twig/twig/lib/Twig/TokenParser/Macro.php +++ b/vendor/twig/twig/lib/Twig/TokenParser/Macro.php @@ -1,60 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +use Twig\TokenParser\MacroTokenParser; -/** - * Defines a macro. - * - * <pre> - * {% macro input(name, value, type, size) %} - * <input type="{{ type|default('text') }}" name="{{ name }}" value="{{ value|e }}" size="{{ size|default(20) }}" /> - * {% endmacro %} - * </pre> - * - * @final - */ -class Twig_TokenParser_Macro extends Twig_TokenParser -{ - public function parse(Twig_Token $token) - { - $lineno = $token->getLine(); - $stream = $this->parser->getStream(); - $name = $stream->expect(Twig_Token::NAME_TYPE)->getValue(); - - $arguments = $this->parser->getExpressionParser()->parseArguments(true, true); - - $stream->expect(Twig_Token::BLOCK_END_TYPE); - $this->parser->pushLocalScope(); - $body = $this->parser->subparse(array($this, 'decideBlockEnd'), true); - if ($token = $stream->nextIf(Twig_Token::NAME_TYPE)) { - $value = $token->getValue(); - - if ($value != $name) { - throw new Twig_Error_Syntax(sprintf('Expected endmacro for macro "%s" (but "%s" given).', $name, $value), $stream->getCurrent()->getLine(), $stream->getSourceContext()); - } - } - $this->parser->popLocalScope(); - $stream->expect(Twig_Token::BLOCK_END_TYPE); - - $this->parser->setMacro($name, new Twig_Node_Macro($name, new Twig_Node_Body(array($body)), $arguments, $lineno, $this->getTag())); - } +class_exists('Twig\TokenParser\MacroTokenParser'); - public function decideBlockEnd(Twig_Token $token) +if (\false) { + class Twig_TokenParser_Macro extends MacroTokenParser { - return $token->test('endmacro'); - } - - public function getTag() - { - return 'macro'; } } - -class_alias('Twig_TokenParser_Macro', 'Twig\TokenParser\MacroTokenParser', false); diff --git a/vendor/twig/twig/lib/Twig/TokenParser/Sandbox.php b/vendor/twig/twig/lib/Twig/TokenParser/Sandbox.php index b8f581cbc3abd7ee18ef8f01c462c628b6157808..25684343a179b0d2a473897e88bb57b7997706c3 100644 --- a/vendor/twig/twig/lib/Twig/TokenParser/Sandbox.php +++ b/vendor/twig/twig/lib/Twig/TokenParser/Sandbox.php @@ -1,61 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +use Twig\TokenParser\SandboxTokenParser; -/** - * Marks a section of a template as untrusted code that must be evaluated in the sandbox mode. - * - * <pre> - * {% sandbox %} - * {% include 'user.html' %} - * {% endsandbox %} - * </pre> - * - * @see http://www.twig-project.org/doc/api.html#sandbox-extension for details - * - * @final - */ -class Twig_TokenParser_Sandbox extends Twig_TokenParser -{ - public function parse(Twig_Token $token) - { - $stream = $this->parser->getStream(); - $stream->expect(Twig_Token::BLOCK_END_TYPE); - $body = $this->parser->subparse(array($this, 'decideBlockEnd'), true); - $stream->expect(Twig_Token::BLOCK_END_TYPE); - - // in a sandbox tag, only include tags are allowed - if (!$body instanceof Twig_Node_Include) { - foreach ($body as $node) { - if ($node instanceof Twig_Node_Text && ctype_space($node->getAttribute('data'))) { - continue; - } - - if (!$node instanceof Twig_Node_Include) { - throw new Twig_Error_Syntax('Only "include" tags are allowed within a "sandbox" section.', $node->getTemplateLine(), $stream->getSourceContext()); - } - } - } - - return new Twig_Node_Sandbox($body, $token->getLine(), $this->getTag()); - } +class_exists('Twig\TokenParser\SandboxTokenParser'); - public function decideBlockEnd(Twig_Token $token) +if (\false) { + class Twig_TokenParser_Sandbox extends SandboxTokenParser { - return $token->test('endsandbox'); - } - - public function getTag() - { - return 'sandbox'; } } - -class_alias('Twig_TokenParser_Sandbox', 'Twig\TokenParser\SandboxTokenParser', false); diff --git a/vendor/twig/twig/lib/Twig/TokenParser/Set.php b/vendor/twig/twig/lib/Twig/TokenParser/Set.php index 48c6b3aeb0b918514090b8fcd13f38ba11a9bbb5..03139f61abdc278de9e34c97f261fe983125fd1a 100644 --- a/vendor/twig/twig/lib/Twig/TokenParser/Set.php +++ b/vendor/twig/twig/lib/Twig/TokenParser/Set.php @@ -1,75 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +use Twig\TokenParser\SetTokenParser; -/** - * Defines a variable. - * - * <pre> - * {% set foo = 'foo' %} - * - * {% set foo = [1, 2] %} - * - * {% set foo = {'foo': 'bar'} %} - * - * {% set foo = 'foo' ~ 'bar' %} - * - * {% set foo, bar = 'foo', 'bar' %} - * - * {% set foo %}Some content{% endset %} - * </pre> - * - * @final - */ -class Twig_TokenParser_Set extends Twig_TokenParser -{ - public function parse(Twig_Token $token) - { - $lineno = $token->getLine(); - $stream = $this->parser->getStream(); - $names = $this->parser->getExpressionParser()->parseAssignmentExpression(); - - $capture = false; - if ($stream->nextIf(Twig_Token::OPERATOR_TYPE, '=')) { - $values = $this->parser->getExpressionParser()->parseMultitargetExpression(); - - $stream->expect(Twig_Token::BLOCK_END_TYPE); - - if (count($names) !== count($values)) { - throw new Twig_Error_Syntax('When using set, you must have the same number of variables and assignments.', $stream->getCurrent()->getLine(), $stream->getSourceContext()); - } - } else { - $capture = true; - - if (count($names) > 1) { - throw new Twig_Error_Syntax('When using set with a block, you cannot have a multi-target.', $stream->getCurrent()->getLine(), $stream->getSourceContext()); - } - - $stream->expect(Twig_Token::BLOCK_END_TYPE); - - $values = $this->parser->subparse(array($this, 'decideBlockEnd'), true); - $stream->expect(Twig_Token::BLOCK_END_TYPE); - } +class_exists('Twig\TokenParser\SetTokenParser'); - return new Twig_Node_Set($capture, $names, $values, $lineno, $this->getTag()); - } - - public function decideBlockEnd(Twig_Token $token) - { - return $token->test('endset'); - } - - public function getTag() +if (\false) { + class Twig_TokenParser_Set extends SetTokenParser { - return 'set'; } } - -class_alias('Twig_TokenParser_Set', 'Twig\TokenParser\SetTokenParser', false); diff --git a/vendor/twig/twig/lib/Twig/TokenParser/Spaceless.php b/vendor/twig/twig/lib/Twig/TokenParser/Spaceless.php index cecf27c67c2e629978ee6a4758b5a72d0bbd28c7..92444a0d8e9f6ba68efe82736967cf011e4af928 100644 --- a/vendor/twig/twig/lib/Twig/TokenParser/Spaceless.php +++ b/vendor/twig/twig/lib/Twig/TokenParser/Spaceless.php @@ -1,51 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +use Twig\TokenParser\SpacelessTokenParser; -/** - * Remove whitespaces between HTML tags. - * - * <pre> - * {% spaceless %} - * <div> - * <strong>foo</strong> - * </div> - * {% endspaceless %} - * - * {# output will be <div><strong>foo</strong></div> #} - * </pre> - * - * @final - */ -class Twig_TokenParser_Spaceless extends Twig_TokenParser -{ - public function parse(Twig_Token $token) - { - $lineno = $token->getLine(); - - $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE); - $body = $this->parser->subparse(array($this, 'decideSpacelessEnd'), true); - $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE); - - return new Twig_Node_Spaceless($body, $lineno, $this->getTag()); - } +class_exists('Twig\TokenParser\SpacelessTokenParser'); - public function decideSpacelessEnd(Twig_Token $token) +if (\false) { + class Twig_TokenParser_Spaceless extends SpacelessTokenParser { - return $token->test('endspaceless'); - } - - public function getTag() - { - return 'spaceless'; } } - -class_alias('Twig_TokenParser_Spaceless', 'Twig\TokenParser\SpacelessTokenParser', false); diff --git a/vendor/twig/twig/lib/Twig/TokenParser/Use.php b/vendor/twig/twig/lib/Twig/TokenParser/Use.php index f15a91ea0dfaa61f983da8a90a0d8881a3fa2eef..c588211eea0ff64136933359a0969afd0bf84001 100644 --- a/vendor/twig/twig/lib/Twig/TokenParser/Use.php +++ b/vendor/twig/twig/lib/Twig/TokenParser/Use.php @@ -1,70 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +use Twig\TokenParser\UseTokenParser; -/** - * Imports blocks defined in another template into the current template. - * - * <pre> - * {% extends "base.html" %} - * - * {% use "blocks.html" %} - * - * {% block title %}{% endblock %} - * {% block content %}{% endblock %} - * </pre> - * - * @see http://www.twig-project.org/doc/templates.html#horizontal-reuse for details. - * - * @final - */ -class Twig_TokenParser_Use extends Twig_TokenParser -{ - public function parse(Twig_Token $token) - { - $template = $this->parser->getExpressionParser()->parseExpression(); - $stream = $this->parser->getStream(); - - if (!$template instanceof Twig_Node_Expression_Constant) { - throw new Twig_Error_Syntax('The template references in a "use" statement must be a string.', $stream->getCurrent()->getLine(), $stream->getSourceContext()); - } - - $targets = array(); - if ($stream->nextIf('with')) { - do { - $name = $stream->expect(Twig_Token::NAME_TYPE)->getValue(); - - $alias = $name; - if ($stream->nextIf('as')) { - $alias = $stream->expect(Twig_Token::NAME_TYPE)->getValue(); - } - - $targets[$name] = new Twig_Node_Expression_Constant($alias, -1); - - if (!$stream->nextIf(Twig_Token::PUNCTUATION_TYPE, ',')) { - break; - } - } while (true); - } +class_exists('Twig\TokenParser\UseTokenParser'); - $stream->expect(Twig_Token::BLOCK_END_TYPE); - - $this->parser->addTrait(new Twig_Node(array('template' => $template, 'targets' => new Twig_Node($targets)))); - - return new Twig_Node(); - } - - public function getTag() +if (\false) { + class Twig_TokenParser_Use extends UseTokenParser { - return 'use'; } } - -class_alias('Twig_TokenParser_Use', 'Twig\TokenParser\UseTokenParser', false); diff --git a/vendor/twig/twig/lib/Twig/TokenParser/With.php b/vendor/twig/twig/lib/Twig/TokenParser/With.php index 7a692597c697acab35a10b00adda096c5b278c88..8067cbe6cc9cb2541809282b9dd9a0e7a100084c 100644 --- a/vendor/twig/twig/lib/Twig/TokenParser/With.php +++ b/vendor/twig/twig/lib/Twig/TokenParser/With.php @@ -1,52 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +use Twig\TokenParser\WithTokenParser; -/** - * Creates a nested scope. - * - * @author Fabien Potencier <fabien@symfony.com> - * - * @final - */ -class Twig_TokenParser_With extends Twig_TokenParser -{ - public function parse(Twig_Token $token) - { - $stream = $this->parser->getStream(); - - $variables = null; - $only = false; - if (!$stream->test(Twig_Token::BLOCK_END_TYPE)) { - $variables = $this->parser->getExpressionParser()->parseExpression(); - $only = $stream->nextIf(Twig_Token::NAME_TYPE, 'only'); - } - - $stream->expect(Twig_Token::BLOCK_END_TYPE); +class_exists('Twig\TokenParser\WithTokenParser'); - $body = $this->parser->subparse(array($this, 'decideWithEnd'), true); - - $stream->expect(Twig_Token::BLOCK_END_TYPE); - - return new Twig_Node_With($body, $variables, $only, $token->getLine(), $this->getTag()); - } - - public function decideWithEnd(Twig_Token $token) +if (\false) { + class Twig_TokenParser_With extends WithTokenParser { - return $token->test('endwith'); - } - - public function getTag() - { - return 'with'; } } - -class_alias('Twig_TokenParser_With', 'Twig\TokenParser\WithTokenParser', false); diff --git a/vendor/twig/twig/lib/Twig/TokenParserBroker.php b/vendor/twig/twig/lib/Twig/TokenParserBroker.php index a64013508ecf7d801ec479629c9d5d203b766b8b..8cca809b83ea861de39efc7627c873ca8cd03f2c 100644 --- a/vendor/twig/twig/lib/Twig/TokenParserBroker.php +++ b/vendor/twig/twig/lib/Twig/TokenParserBroker.php @@ -10,6 +10,8 @@ * file that was distributed with this source code. */ +use Twig\TokenParser\TokenParserInterface; + /** * Default implementation of a token parser broker. * @@ -20,40 +22,40 @@ class Twig_TokenParserBroker implements Twig_TokenParserBrokerInterface { protected $parser; - protected $parsers = array(); - protected $brokers = array(); + protected $parsers = []; + protected $brokers = []; /** - * @param array|Traversable $parsers A Traversable of Twig_TokenParserInterface instances - * @param array|Traversable $brokers A Traversable of Twig_TokenParserBrokerInterface instances - * @param bool $triggerDeprecationError + * @param array|\Traversable $parsers A \Traversable of Twig_TokenParserInterface instances + * @param array|\Traversable $brokers A \Traversable of Twig_TokenParserBrokerInterface instances + * @param bool $triggerDeprecationError */ - public function __construct($parsers = array(), $brokers = array(), $triggerDeprecationError = true) + public function __construct($parsers = [], $brokers = [], $triggerDeprecationError = true) { if ($triggerDeprecationError) { @trigger_error('The '.__CLASS__.' class is deprecated since version 1.12 and will be removed in 2.0.', E_USER_DEPRECATED); } foreach ($parsers as $parser) { - if (!$parser instanceof Twig_TokenParserInterface) { - throw new LogicException('$parsers must a an array of Twig_TokenParserInterface.'); + if (!$parser instanceof TokenParserInterface) { + throw new \LogicException('$parsers must a an array of Twig_TokenParserInterface.'); } $this->parsers[$parser->getTag()] = $parser; } foreach ($brokers as $broker) { if (!$broker instanceof Twig_TokenParserBrokerInterface) { - throw new LogicException('$brokers must a an array of Twig_TokenParserBrokerInterface.'); + throw new \LogicException('$brokers must a an array of Twig_TokenParserBrokerInterface.'); } $this->brokers[] = $broker; } } - public function addTokenParser(Twig_TokenParserInterface $parser) + public function addTokenParser(TokenParserInterface $parser) { $this->parsers[$parser->getTag()] = $parser; } - public function removeTokenParser(Twig_TokenParserInterface $parser) + public function removeTokenParser(TokenParserInterface $parser) { $name = $parser->getTag(); if (isset($this->parsers[$name]) && $parser === $this->parsers[$name]) { @@ -61,12 +63,12 @@ class Twig_TokenParserBroker implements Twig_TokenParserBrokerInterface } } - public function addTokenParserBroker(Twig_TokenParserBroker $broker) + public function addTokenParserBroker(self $broker) { $this->brokers[] = $broker; } - public function removeTokenParserBroker(Twig_TokenParserBroker $broker) + public function removeTokenParserBroker(self $broker) { if (false !== $pos = array_search($broker, $this->brokers)) { unset($this->brokers[$pos]); @@ -80,7 +82,7 @@ class Twig_TokenParserBroker implements Twig_TokenParserBrokerInterface * * @param string $tag A tag name * - * @return null|Twig_TokenParserInterface A Twig_TokenParserInterface or null if no suitable TokenParser was found + * @return TokenParserInterface|null A Twig_TokenParserInterface or null if no suitable TokenParser was found */ public function getTokenParser($tag) { diff --git a/vendor/twig/twig/lib/Twig/TokenParserBrokerInterface.php b/vendor/twig/twig/lib/Twig/TokenParserBrokerInterface.php index 6c93f5ea19afc157bd6a24cfe2abff3962ca1495..f369264d9e6606a65d721222466b6d6dbc19fa7e 100644 --- a/vendor/twig/twig/lib/Twig/TokenParserBrokerInterface.php +++ b/vendor/twig/twig/lib/Twig/TokenParserBrokerInterface.php @@ -10,6 +10,8 @@ * file that was distributed with this source code. */ +use Twig\TokenParser\TokenParserInterface; + /** * Interface implemented by token parser brokers. * @@ -26,19 +28,19 @@ interface Twig_TokenParserBrokerInterface * * @param string $tag A tag name * - * @return Twig_TokenParserInterface|null A Twig_TokenParserInterface or null if no suitable TokenParser was found + * @return TokenParserInterface|null A Twig_TokenParserInterface or null if no suitable TokenParser was found */ public function getTokenParser($tag); /** - * Calls Twig_TokenParserInterface::setParser on all parsers the implementation knows of. + * Calls Twig\TokenParser\TokenParserInterface::setParser on all parsers the implementation knows of. */ public function setParser(Twig_ParserInterface $parser); /** * Gets the Twig_ParserInterface. * - * @return null|Twig_ParserInterface A Twig_ParserInterface instance or null + * @return Twig_ParserInterface|null A Twig_ParserInterface instance or null */ public function getParser(); } diff --git a/vendor/twig/twig/lib/Twig/TokenParserInterface.php b/vendor/twig/twig/lib/Twig/TokenParserInterface.php index 14acc8084b56450f99304afa97b34b480a5f1cde..800c971943b2e7dad13d30ca2b5552340735c764 100644 --- a/vendor/twig/twig/lib/Twig/TokenParserInterface.php +++ b/vendor/twig/twig/lib/Twig/TokenParserInterface.php @@ -1,43 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +use Twig\TokenParser\TokenParserInterface; -/** - * Interface implemented by token parsers. - * - * @author Fabien Potencier <fabien@symfony.com> - */ -interface Twig_TokenParserInterface -{ - /** - * Sets the parser associated with this token parser. - */ - public function setParser(Twig_Parser $parser); +class_exists('Twig\TokenParser\TokenParserInterface'); - /** - * Parses a token and returns a node. - * - * @return Twig_NodeInterface - * - * @throws Twig_Error_Syntax - */ - public function parse(Twig_Token $token); - - /** - * Gets the tag name associated with this token parser. - * - * @return string The tag name - */ - public function getTag(); +if (\false) { + class Twig_TokenParserInterface extends TokenParserInterface + { + } } - -class_alias('Twig_TokenParserInterface', 'Twig\TokenParser\TokenParserInterface', false); -class_exists('Twig_Parser'); -class_exists('Twig_Token'); diff --git a/vendor/twig/twig/lib/Twig/TokenStream.php b/vendor/twig/twig/lib/Twig/TokenStream.php index e1bd7ca1e331ea387ab350dcfbc0b7e07e6af3fd..b1abb80720ea9ced4f8e085499fc58567f41f848 100644 --- a/vendor/twig/twig/lib/Twig/TokenStream.php +++ b/vendor/twig/twig/lib/Twig/TokenStream.php @@ -1,196 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * (c) Armin Ronacher - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +use Twig\TokenStream; -/** - * Represents a token stream. - * - * @final - * - * @author Fabien Potencier <fabien@symfony.com> - */ -class Twig_TokenStream -{ - protected $tokens; - protected $current = 0; - protected $filename; +class_exists('Twig\TokenStream'); - private $source; - - /** - * @param array $tokens An array of tokens - * @param string|null $name The name of the template which tokens are associated with - * @param string|null $source The source code associated with the tokens - */ - public function __construct(array $tokens, $name = null, $source = null) - { - if (!$name instanceof Twig_Source) { - if (null !== $name || null !== $source) { - @trigger_error(sprintf('Passing a string as the $name argument of %s() is deprecated since version 1.27. Pass a Twig_Source instance instead.', __METHOD__), E_USER_DEPRECATED); - } - $this->source = new Twig_Source($source, $name); - } else { - $this->source = $name; - } - - $this->tokens = $tokens; - - // deprecated, not used anymore, to be removed in 2.0 - $this->filename = $this->source->getName(); - } - - public function __toString() +if (\false) { + class Twig_TokenStream extends TokenStream { - return implode("\n", $this->tokens); - } - - public function injectTokens(array $tokens) - { - $this->tokens = array_merge(array_slice($this->tokens, 0, $this->current), $tokens, array_slice($this->tokens, $this->current)); - } - - /** - * Sets the pointer to the next token and returns the old one. - * - * @return Twig_Token - */ - public function next() - { - if (!isset($this->tokens[++$this->current])) { - throw new Twig_Error_Syntax('Unexpected end of template.', $this->tokens[$this->current - 1]->getLine(), $this->source); - } - - return $this->tokens[$this->current - 1]; - } - - /** - * Tests a token, sets the pointer to the next one and returns it or throws a syntax error. - * - * @return Twig_Token|null The next token if the condition is true, null otherwise - */ - public function nextIf($primary, $secondary = null) - { - if ($this->tokens[$this->current]->test($primary, $secondary)) { - return $this->next(); - } - } - - /** - * Tests a token and returns it or throws a syntax error. - * - * @return Twig_Token - */ - public function expect($type, $value = null, $message = null) - { - $token = $this->tokens[$this->current]; - if (!$token->test($type, $value)) { - $line = $token->getLine(); - throw new Twig_Error_Syntax(sprintf('%sUnexpected token "%s" of value "%s" ("%s" expected%s).', - $message ? $message.'. ' : '', - Twig_Token::typeToEnglish($token->getType()), $token->getValue(), - Twig_Token::typeToEnglish($type), $value ? sprintf(' with value "%s"', $value) : ''), - $line, - $this->source - ); - } - $this->next(); - - return $token; - } - - /** - * Looks at the next token. - * - * @param int $number - * - * @return Twig_Token - */ - public function look($number = 1) - { - if (!isset($this->tokens[$this->current + $number])) { - throw new Twig_Error_Syntax('Unexpected end of template.', $this->tokens[$this->current + $number - 1]->getLine(), $this->source); - } - - return $this->tokens[$this->current + $number]; - } - - /** - * Tests the current token. - * - * @return bool - */ - public function test($primary, $secondary = null) - { - return $this->tokens[$this->current]->test($primary, $secondary); - } - - /** - * Checks if end of stream was reached. - * - * @return bool - */ - public function isEOF() - { - return $this->tokens[$this->current]->getType() === Twig_Token::EOF_TYPE; - } - - /** - * @return Twig_Token - */ - public function getCurrent() - { - return $this->tokens[$this->current]; - } - - /** - * Gets the name associated with this stream (null if not defined). - * - * @return string|null - * - * @deprecated since 1.27 (to be removed in 2.0) - */ - public function getFilename() - { - @trigger_error(sprintf('The %s() method is deprecated since version 1.27 and will be removed in 2.0. Use getSourceContext() instead.', __METHOD__), E_USER_DEPRECATED); - - return $this->source->getName(); - } - - /** - * Gets the source code associated with this stream. - * - * @return string - * - * @internal Don't use this as it might be empty depending on the environment configuration - * - * @deprecated since 1.27 (to be removed in 2.0) - */ - public function getSource() - { - @trigger_error(sprintf('The %s() method is deprecated since version 1.27 and will be removed in 2.0. Use getSourceContext() instead.', __METHOD__), E_USER_DEPRECATED); - - return $this->source->getCode(); - } - - /** - * Gets the source associated with this stream. - * - * @return Twig_Source - * - * @internal - */ - public function getSourceContext() - { - return $this->source; } } - -class_alias('Twig_TokenStream', 'Twig\TokenStream', false); diff --git a/vendor/twig/twig/lib/Twig/Util/DeprecationCollector.php b/vendor/twig/twig/lib/Twig/Util/DeprecationCollector.php index c7bf53be2e705c83f0af71803ff9dde0c4716e0c..46fd4ef6bbcaa5c51685dfc730539ad567d61255 100644 --- a/vendor/twig/twig/lib/Twig/Util/DeprecationCollector.php +++ b/vendor/twig/twig/lib/Twig/Util/DeprecationCollector.php @@ -1,86 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +use Twig\Util\DeprecationCollector; -/** - * @author Fabien Potencier <fabien@symfony.com> - * - * @final - */ -class Twig_Util_DeprecationCollector -{ - private $twig; - private $deprecations; +class_exists('Twig\Util\DeprecationCollector'); - public function __construct(Twig_Environment $twig) +if (\false) { + class Twig_Util_DeprecationCollector extends DeprecationCollector { - $this->twig = $twig; - } - - /** - * Returns deprecations for templates contained in a directory. - * - * @param string $dir A directory where templates are stored - * @param string $ext Limit the loaded templates by extension - * - * @return array An array of deprecations - */ - public function collectDir($dir, $ext = '.twig') - { - $iterator = new RegexIterator( - new RecursiveIteratorIterator( - new RecursiveDirectoryIterator($dir), RecursiveIteratorIterator::LEAVES_ONLY - ), '{'.preg_quote($ext).'$}' - ); - - return $this->collect(new Twig_Util_TemplateDirIterator($iterator)); - } - - /** - * Returns deprecations for passed templates. - * - * @param Traversable $iterator An iterator of templates (where keys are template names and values the contents of the template) - * - * @return array An array of deprecations - */ - public function collect(Traversable $iterator) - { - $this->deprecations = array(); - - set_error_handler(array($this, 'errorHandler')); - - foreach ($iterator as $name => $contents) { - try { - $this->twig->parse($this->twig->tokenize(new Twig_Source($contents, $name))); - } catch (Twig_Error_Syntax $e) { - // ignore templates containing syntax errors - } - } - - restore_error_handler(); - - $deprecations = $this->deprecations; - $this->deprecations = array(); - - return $deprecations; - } - - /** - * @internal - */ - public function errorHandler($type, $msg) - { - if (E_USER_DEPRECATED === $type) { - $this->deprecations[] = $msg; - } } } - -class_alias('Twig_Util_DeprecationCollector', 'Twig\Util\DeprecationCollector', false); diff --git a/vendor/twig/twig/lib/Twig/Util/TemplateDirIterator.php b/vendor/twig/twig/lib/Twig/Util/TemplateDirIterator.php index c8682335dee1e0cf9fcc72a656adc4f2f26ee2b3..f9a1e0be398ae9d723d40efbf0931347dfe3d9f4 100644 --- a/vendor/twig/twig/lib/Twig/Util/TemplateDirIterator.php +++ b/vendor/twig/twig/lib/Twig/Util/TemplateDirIterator.php @@ -1,28 +1,11 @@ <?php -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ +use Twig\Util\TemplateDirIterator; -/** - * @author Fabien Potencier <fabien@symfony.com> - */ -class Twig_Util_TemplateDirIterator extends IteratorIterator -{ - public function current() - { - return file_get_contents(parent::current()); - } +class_exists('Twig\Util\TemplateDirIterator'); - public function key() +if (\false) { + class Twig_Util_TemplateDirIterator extends TemplateDirIterator { - return (string) parent::key(); } } - -class_alias('Twig_Util_TemplateDirIterator', 'Twig\Util\TemplateDirIterator', false); diff --git a/vendor/twig/twig/phpunit.xml.dist b/vendor/twig/twig/phpunit.xml.dist index ce773278553adac1f7f150e41cd9531d62f3b10d..391f244a7f48ad377cd4ef9048eb85b94f878750 100644 --- a/vendor/twig/twig/phpunit.xml.dist +++ b/vendor/twig/twig/phpunit.xml.dist @@ -8,17 +8,17 @@ convertWarningsToExceptions="true" processIsolation="false" stopOnFailure="false" - syntaxCheck="false" bootstrap="vendor/autoload.php" > <testsuites> <testsuite name="Twig Test Suite"> - <directory>./test/Twig/</directory> + <directory>./tests/</directory> </testsuite> </testsuites> <php> <ini name="error_reporting" value="-1" /> + <ini name="xdebug.overload_var_dump" value="0" /> </php> <listeners> @@ -27,7 +27,7 @@ <filter> <whitelist> - <directory suffix=".php">./lib/Twig/</directory> + <directory suffix=".php">./src/</directory> </whitelist> </filter> </phpunit> diff --git a/vendor/twig/twig/src/Cache/CacheInterface.php b/vendor/twig/twig/src/Cache/CacheInterface.php index 2e35e3ba03ff9fea6d2ef373a42f84bca6627b50..1c8bb1ec9a93c26ddbc65cecd17e0a7cc27b1821 100644 --- a/vendor/twig/twig/src/Cache/CacheInterface.php +++ b/vendor/twig/twig/src/Cache/CacheInterface.php @@ -1,11 +1,60 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\Cache; -class_exists('Twig_CacheInterface'); +/** + * Interface implemented by cache classes. + * + * It is highly recommended to always store templates on the filesystem to + * benefit from the PHP opcode cache. This interface is mostly useful if you + * need to implement a custom strategy for storing templates on the filesystem. + * + * @author Andrew Tch <andrew@noop.lv> + */ +interface CacheInterface +{ + /** + * Generates a cache key for the given template class name. + * + * @param string $name The template name + * @param string $className The template class name + * + * @return string + */ + public function generateKey($name, $className); + + /** + * Writes the compiled template to cache. + * + * @param string $key The cache key + * @param string $content The template representation as a PHP class + */ + public function write($key, $content); -if (\false) { - interface CacheInterface extends \Twig_CacheInterface - { - } + /** + * Loads a template from the cache. + * + * @param string $key The cache key + */ + public function load($key); + + /** + * Returns the modification timestamp of a key. + * + * @param string $key The cache key + * + * @return int + */ + public function getTimestamp($key); } + +class_alias('Twig\Cache\CacheInterface', 'Twig_CacheInterface'); diff --git a/vendor/twig/twig/src/Cache/FilesystemCache.php b/vendor/twig/twig/src/Cache/FilesystemCache.php index 9882c988677043ac966d32b67675e7abc496145b..b7c1e438e790ab8fc7d981e3d693a1b40f05ab6f 100644 --- a/vendor/twig/twig/src/Cache/FilesystemCache.php +++ b/vendor/twig/twig/src/Cache/FilesystemCache.php @@ -1,11 +1,93 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\Cache; -class_exists('Twig_Cache_Filesystem'); +/** + * Implements a cache on the filesystem. + * + * @author Andrew Tch <andrew@noop.lv> + */ +class FilesystemCache implements CacheInterface +{ + const FORCE_BYTECODE_INVALIDATION = 1; + + private $directory; + private $options; + + /** + * @param string $directory The root cache directory + * @param int $options A set of options + */ + public function __construct($directory, $options = 0) + { + $this->directory = rtrim($directory, '\/').'/'; + $this->options = $options; + } -if (\false) { - class FilesystemCache extends \Twig_Cache_Filesystem + public function generateKey($name, $className) { + $hash = hash('sha256', $className); + + return $this->directory.$hash[0].$hash[1].'/'.$hash.'.php'; + } + + public function load($key) + { + if (file_exists($key)) { + @include_once $key; + } + } + + public function write($key, $content) + { + $dir = \dirname($key); + if (!is_dir($dir)) { + if (false === @mkdir($dir, 0777, true)) { + clearstatcache(true, $dir); + if (!is_dir($dir)) { + throw new \RuntimeException(sprintf('Unable to create the cache directory (%s).', $dir)); + } + } + } elseif (!is_writable($dir)) { + throw new \RuntimeException(sprintf('Unable to write in the cache directory (%s).', $dir)); + } + + $tmpFile = tempnam($dir, basename($key)); + if (false !== @file_put_contents($tmpFile, $content) && @rename($tmpFile, $key)) { + @chmod($key, 0666 & ~umask()); + + if (self::FORCE_BYTECODE_INVALIDATION == ($this->options & self::FORCE_BYTECODE_INVALIDATION)) { + // Compile cached file into bytecode cache + if (\function_exists('opcache_invalidate') && filter_var(ini_get('opcache.enable'), FILTER_VALIDATE_BOOLEAN)) { + @opcache_invalidate($key, true); + } elseif (\function_exists('apc_compile_file')) { + apc_compile_file($key); + } + } + + return; + } + + throw new \RuntimeException(sprintf('Failed to write cache file "%s".', $key)); + } + + public function getTimestamp($key) + { + if (!file_exists($key)) { + return 0; + } + + return (int) @filemtime($key); } } + +class_alias('Twig\Cache\FilesystemCache', 'Twig_Cache_Filesystem'); diff --git a/vendor/twig/twig/src/Cache/NullCache.php b/vendor/twig/twig/src/Cache/NullCache.php index c3d4055514cfc1783d4fbaa423d9ae95ed5c05c8..c1b37c1243e2f3502ae4cf93435a64fa234190b1 100644 --- a/vendor/twig/twig/src/Cache/NullCache.php +++ b/vendor/twig/twig/src/Cache/NullCache.php @@ -1,11 +1,42 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\Cache; -class_exists('Twig_Cache_Null'); +/** + * Implements a no-cache strategy. + * + * @final + * + * @author Fabien Potencier <fabien@symfony.com> + */ +class NullCache implements CacheInterface +{ + public function generateKey($name, $className) + { + return ''; + } + + public function write($key, $content) + { + } + + public function load($key) + { + } -if (\false) { - class NullCache extends \Twig_Cache_Null + public function getTimestamp($key) { + return 0; } } + +class_alias('Twig\Cache\NullCache', 'Twig_Cache_Null'); diff --git a/vendor/twig/twig/src/Compiler.php b/vendor/twig/twig/src/Compiler.php index 6025c4dfc4bf24eef4fd0eeb60bd11b8ed52d01f..e47003ae19ee3f6b9a3524cd114e3eaf9394ca45 100644 --- a/vendor/twig/twig/src/Compiler.php +++ b/vendor/twig/twig/src/Compiler.php @@ -1,11 +1,288 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * (c) Armin Ronacher + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig; -class_exists('Twig_Compiler'); +use Twig\Node\ModuleNode; + +/** + * Compiles a node to PHP code. + * + * @author Fabien Potencier <fabien@symfony.com> + */ +class Compiler implements \Twig_CompilerInterface +{ + protected $lastLine; + protected $source; + protected $indentation; + protected $env; + protected $debugInfo = []; + protected $sourceOffset; + protected $sourceLine; + protected $filename; + private $varNameSalt = 0; + + public function __construct(Environment $env) + { + $this->env = $env; + } + + /** + * @deprecated since 1.25 (to be removed in 2.0) + */ + public function getFilename() + { + @trigger_error(sprintf('The %s() method is deprecated since version 1.25 and will be removed in 2.0.', __FUNCTION__), E_USER_DEPRECATED); + + return $this->filename; + } + + /** + * Returns the environment instance related to this compiler. + * + * @return Environment + */ + public function getEnvironment() + { + return $this->env; + } + + /** + * Gets the current PHP code after compilation. + * + * @return string The PHP code + */ + public function getSource() + { + return $this->source; + } + + /** + * Compiles a node. + * + * @param int $indentation The current indentation + * + * @return $this + */ + public function compile(\Twig_NodeInterface $node, $indentation = 0) + { + $this->lastLine = null; + $this->source = ''; + $this->debugInfo = []; + $this->sourceOffset = 0; + // source code starts at 1 (as we then increment it when we encounter new lines) + $this->sourceLine = 1; + $this->indentation = $indentation; + $this->varNameSalt = 0; + + if ($node instanceof ModuleNode) { + // to be removed in 2.0 + $this->filename = $node->getTemplateName(); + } + + $node->compile($this); + + return $this; + } + + public function subcompile(\Twig_NodeInterface $node, $raw = true) + { + if (false === $raw) { + $this->source .= str_repeat(' ', $this->indentation * 4); + } + + $node->compile($this); + + return $this; + } + + /** + * Adds a raw string to the compiled code. + * + * @param string $string The string + * + * @return $this + */ + public function raw($string) + { + $this->source .= $string; + + return $this; + } + + /** + * Writes a string to the compiled code by adding indentation. + * + * @return $this + */ + public function write() + { + $strings = \func_get_args(); + foreach ($strings as $string) { + $this->source .= str_repeat(' ', $this->indentation * 4).$string; + } + + return $this; + } + + /** + * Appends an indentation to the current PHP code after compilation. + * + * @return $this + * + * @deprecated since 1.27 (to be removed in 2.0). + */ + public function addIndentation() + { + @trigger_error('The '.__METHOD__.' method is deprecated since version 1.27 and will be removed in 2.0. Use write(\'\') instead.', E_USER_DEPRECATED); + + $this->source .= str_repeat(' ', $this->indentation * 4); + + return $this; + } + + /** + * Adds a quoted string to the compiled code. + * + * @param string $value The string + * + * @return $this + */ + public function string($value) + { + $this->source .= sprintf('"%s"', addcslashes($value, "\0\t\"\$\\")); + + return $this; + } + + /** + * Returns a PHP representation of a given value. + * + * @param mixed $value The value to convert + * + * @return $this + */ + public function repr($value) + { + if (\is_int($value) || \is_float($value)) { + if (false !== $locale = setlocale(LC_NUMERIC, '0')) { + setlocale(LC_NUMERIC, 'C'); + } + + $this->raw(var_export($value, true)); + + if (false !== $locale) { + setlocale(LC_NUMERIC, $locale); + } + } elseif (null === $value) { + $this->raw('null'); + } elseif (\is_bool($value)) { + $this->raw($value ? 'true' : 'false'); + } elseif (\is_array($value)) { + $this->raw('['); + $first = true; + foreach ($value as $key => $v) { + if (!$first) { + $this->raw(', '); + } + $first = false; + $this->repr($key); + $this->raw(' => '); + $this->repr($v); + } + $this->raw(']'); + } else { + $this->string($value); + } + + return $this; + } -if (\false) { - class Compiler extends \Twig_Compiler + /** + * Adds debugging information. + * + * @return $this + */ + public function addDebugInfo(\Twig_NodeInterface $node) { + if ($node->getTemplateLine() != $this->lastLine) { + $this->write(sprintf("// line %d\n", $node->getTemplateLine())); + + // when mbstring.func_overload is set to 2 + // mb_substr_count() replaces substr_count() + // but they have different signatures! + if (((int) ini_get('mbstring.func_overload')) & 2) { + @trigger_error('Support for having "mbstring.func_overload" different from 0 is deprecated version 1.29 and will be removed in 2.0.', E_USER_DEPRECATED); + + // this is much slower than the "right" version + $this->sourceLine += mb_substr_count(mb_substr($this->source, $this->sourceOffset), "\n"); + } else { + $this->sourceLine += substr_count($this->source, "\n", $this->sourceOffset); + } + $this->sourceOffset = \strlen($this->source); + $this->debugInfo[$this->sourceLine] = $node->getTemplateLine(); + + $this->lastLine = $node->getTemplateLine(); + } + + return $this; + } + + public function getDebugInfo() + { + ksort($this->debugInfo); + + return $this->debugInfo; + } + + /** + * Indents the generated code. + * + * @param int $step The number of indentation to add + * + * @return $this + */ + public function indent($step = 1) + { + $this->indentation += $step; + + return $this; + } + + /** + * Outdents the generated code. + * + * @param int $step The number of indentation to remove + * + * @return $this + * + * @throws \LogicException When trying to outdent too much so the indentation would become negative + */ + public function outdent($step = 1) + { + // can't outdent by more steps than the current indentation level + if ($this->indentation < $step) { + throw new \LogicException('Unable to call outdent() as the indentation would become negative.'); + } + + $this->indentation -= $step; + + return $this; + } + + public function getVarName() + { + return sprintf('__internal_%s', hash('sha256', __METHOD__.$this->varNameSalt++)); } } + +class_alias('Twig\Compiler', 'Twig_Compiler'); diff --git a/vendor/twig/twig/src/Environment.php b/vendor/twig/twig/src/Environment.php index e0f9edcdcbf955920a307890ee907eeebb840b52..acd8233a7f9de1121dafdf9c396592b37f90e44f 100644 --- a/vendor/twig/twig/src/Environment.php +++ b/vendor/twig/twig/src/Environment.php @@ -1,11 +1,1638 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig; -class_exists('Twig_Environment'); +use Twig\Cache\CacheInterface; +use Twig\Cache\FilesystemCache; +use Twig\Cache\NullCache; +use Twig\Error\Error; +use Twig\Error\LoaderError; +use Twig\Error\RuntimeError; +use Twig\Error\SyntaxError; +use Twig\Extension\CoreExtension; +use Twig\Extension\EscaperExtension; +use Twig\Extension\ExtensionInterface; +use Twig\Extension\GlobalsInterface; +use Twig\Extension\InitRuntimeInterface; +use Twig\Extension\OptimizerExtension; +use Twig\Extension\StagingExtension; +use Twig\Loader\ArrayLoader; +use Twig\Loader\ChainLoader; +use Twig\Loader\LoaderInterface; +use Twig\Loader\SourceContextLoaderInterface; +use Twig\Node\ModuleNode; +use Twig\NodeVisitor\NodeVisitorInterface; +use Twig\RuntimeLoader\RuntimeLoaderInterface; +use Twig\TokenParser\TokenParserInterface; + +/** + * Stores the Twig configuration. + * + * @author Fabien Potencier <fabien@symfony.com> + */ +class Environment +{ + const VERSION = '1.42.3'; + const VERSION_ID = 14203; + const MAJOR_VERSION = 1; + const MINOR_VERSION = 42; + const RELEASE_VERSION = 3; + const EXTRA_VERSION = ''; + + protected $charset; + protected $loader; + protected $debug; + protected $autoReload; + protected $cache; + protected $lexer; + protected $parser; + protected $compiler; + protected $baseTemplateClass; + protected $extensions; + protected $parsers; + protected $visitors; + protected $filters; + protected $tests; + protected $functions; + protected $globals; + protected $runtimeInitialized = false; + protected $extensionInitialized = false; + protected $loadedTemplates; + protected $strictVariables; + protected $unaryOperators; + protected $binaryOperators; + protected $templateClassPrefix = '__TwigTemplate_'; + protected $functionCallbacks = []; + protected $filterCallbacks = []; + protected $staging; + + private $originalCache; + private $bcWriteCacheFile = false; + private $bcGetCacheFilename = false; + private $lastModifiedExtension = 0; + private $extensionsByClass = []; + private $runtimeLoaders = []; + private $runtimes = []; + private $optionsHash; + + /** + * Constructor. + * + * Available options: + * + * * debug: When set to true, it automatically set "auto_reload" to true as + * well (default to false). + * + * * charset: The charset used by the templates (default to UTF-8). + * + * * base_template_class: The base template class to use for generated + * templates (default to \Twig\Template). + * + * * cache: An absolute path where to store the compiled templates, + * a \Twig\Cache\CacheInterface implementation, + * or false to disable compilation cache (default). + * + * * auto_reload: Whether to reload the template if the original source changed. + * If you don't provide the auto_reload option, it will be + * determined automatically based on the debug value. + * + * * strict_variables: Whether to ignore invalid variables in templates + * (default to false). + * + * * autoescape: Whether to enable auto-escaping (default to html): + * * false: disable auto-escaping + * * true: equivalent to html + * * html, js: set the autoescaping to one of the supported strategies + * * name: set the autoescaping strategy based on the template name extension + * * PHP callback: a PHP callback that returns an escaping strategy based on the template "name" + * + * * optimizations: A flag that indicates which optimizations to apply + * (default to -1 which means that all optimizations are enabled; + * set it to 0 to disable). + */ + public function __construct(LoaderInterface $loader = null, $options = []) + { + if (null !== $loader) { + $this->setLoader($loader); + } else { + @trigger_error('Not passing a "Twig\Lodaer\LoaderInterface" as the first constructor argument of "Twig\Environment" is deprecated since version 1.21.', E_USER_DEPRECATED); + } + + $options = array_merge([ + 'debug' => false, + 'charset' => 'UTF-8', + 'base_template_class' => '\Twig\Template', + 'strict_variables' => false, + 'autoescape' => 'html', + 'cache' => false, + 'auto_reload' => null, + 'optimizations' => -1, + ], $options); + + $this->debug = (bool) $options['debug']; + $this->charset = strtoupper($options['charset']); + $this->baseTemplateClass = $options['base_template_class']; + $this->autoReload = null === $options['auto_reload'] ? $this->debug : (bool) $options['auto_reload']; + $this->strictVariables = (bool) $options['strict_variables']; + $this->setCache($options['cache']); + + $this->addExtension(new CoreExtension()); + $this->addExtension(new EscaperExtension($options['autoescape'])); + $this->addExtension(new OptimizerExtension($options['optimizations'])); + $this->staging = new StagingExtension(); + + // For BC + if (\is_string($this->originalCache)) { + $r = new \ReflectionMethod($this, 'writeCacheFile'); + if (__CLASS__ !== $r->getDeclaringClass()->getName()) { + @trigger_error('The Twig\Environment::writeCacheFile method is deprecated since version 1.22 and will be removed in Twig 2.0.', E_USER_DEPRECATED); + + $this->bcWriteCacheFile = true; + } + + $r = new \ReflectionMethod($this, 'getCacheFilename'); + if (__CLASS__ !== $r->getDeclaringClass()->getName()) { + @trigger_error('The Twig\Environment::getCacheFilename method is deprecated since version 1.22 and will be removed in Twig 2.0.', E_USER_DEPRECATED); + + $this->bcGetCacheFilename = true; + } + } + } + + /** + * Gets the base template class for compiled templates. + * + * @return string The base template class name + */ + public function getBaseTemplateClass() + { + return $this->baseTemplateClass; + } + + /** + * Sets the base template class for compiled templates. + * + * @param string $class The base template class name + */ + public function setBaseTemplateClass($class) + { + $this->baseTemplateClass = $class; + $this->updateOptionsHash(); + } + + /** + * Enables debugging mode. + */ + public function enableDebug() + { + $this->debug = true; + $this->updateOptionsHash(); + } + + /** + * Disables debugging mode. + */ + public function disableDebug() + { + $this->debug = false; + $this->updateOptionsHash(); + } + + /** + * Checks if debug mode is enabled. + * + * @return bool true if debug mode is enabled, false otherwise + */ + public function isDebug() + { + return $this->debug; + } + + /** + * Enables the auto_reload option. + */ + public function enableAutoReload() + { + $this->autoReload = true; + } + + /** + * Disables the auto_reload option. + */ + public function disableAutoReload() + { + $this->autoReload = false; + } + + /** + * Checks if the auto_reload option is enabled. + * + * @return bool true if auto_reload is enabled, false otherwise + */ + public function isAutoReload() + { + return $this->autoReload; + } + + /** + * Enables the strict_variables option. + */ + public function enableStrictVariables() + { + $this->strictVariables = true; + $this->updateOptionsHash(); + } + + /** + * Disables the strict_variables option. + */ + public function disableStrictVariables() + { + $this->strictVariables = false; + $this->updateOptionsHash(); + } + + /** + * Checks if the strict_variables option is enabled. + * + * @return bool true if strict_variables is enabled, false otherwise + */ + public function isStrictVariables() + { + return $this->strictVariables; + } + + /** + * Gets the current cache implementation. + * + * @param bool $original Whether to return the original cache option or the real cache instance + * + * @return CacheInterface|string|false A Twig\Cache\CacheInterface implementation, + * an absolute path to the compiled templates, + * or false to disable cache + */ + public function getCache($original = true) + { + return $original ? $this->originalCache : $this->cache; + } + + /** + * Sets the current cache implementation. + * + * @param CacheInterface|string|false $cache A Twig\Cache\CacheInterface implementation, + * an absolute path to the compiled templates, + * or false to disable cache + */ + public function setCache($cache) + { + if (\is_string($cache)) { + $this->originalCache = $cache; + $this->cache = new FilesystemCache($cache); + } elseif (false === $cache) { + $this->originalCache = $cache; + $this->cache = new NullCache(); + } elseif (null === $cache) { + @trigger_error('Using "null" as the cache strategy is deprecated since version 1.23 and will be removed in Twig 2.0.', E_USER_DEPRECATED); + $this->originalCache = false; + $this->cache = new NullCache(); + } elseif ($cache instanceof CacheInterface) { + $this->originalCache = $this->cache = $cache; + } else { + throw new \LogicException(sprintf('Cache can only be a string, false, or a \Twig\Cache\CacheInterface implementation.')); + } + } + + /** + * Gets the cache filename for a given template. + * + * @param string $name The template name + * + * @return string|false The cache file name or false when caching is disabled + * + * @deprecated since 1.22 (to be removed in 2.0) + */ + public function getCacheFilename($name) + { + @trigger_error(sprintf('The %s method is deprecated since version 1.22 and will be removed in Twig 2.0.', __METHOD__), E_USER_DEPRECATED); + + $key = $this->cache->generateKey($name, $this->getTemplateClass($name)); + + return !$key ? false : $key; + } + + /** + * Gets the template class associated with the given string. + * + * The generated template class is based on the following parameters: + * + * * The cache key for the given template; + * * The currently enabled extensions; + * * Whether the Twig C extension is available or not; + * * PHP version; + * * Twig version; + * * Options with what environment was created. + * + * @param string $name The name for which to calculate the template class name + * @param int|null $index The index if it is an embedded template + * + * @return string The template class name + */ + public function getTemplateClass($name, $index = null) + { + $key = $this->getLoader()->getCacheKey($name).$this->optionsHash; + + return $this->templateClassPrefix.hash('sha256', $key).(null === $index ? '' : '___'.$index); + } + + /** + * Gets the template class prefix. + * + * @return string The template class prefix + * + * @deprecated since 1.22 (to be removed in 2.0) + */ + public function getTemplateClassPrefix() + { + @trigger_error(sprintf('The %s method is deprecated since version 1.22 and will be removed in Twig 2.0.', __METHOD__), E_USER_DEPRECATED); + + return $this->templateClassPrefix; + } + + /** + * Renders a template. + * + * @param string|TemplateWrapper $name The template name + * @param array $context An array of parameters to pass to the template + * + * @return string The rendered template + * + * @throws LoaderError When the template cannot be found + * @throws SyntaxError When an error occurred during compilation + * @throws RuntimeError When an error occurred during rendering + */ + public function render($name, array $context = []) + { + return $this->load($name)->render($context); + } + + /** + * Displays a template. + * + * @param string|TemplateWrapper $name The template name + * @param array $context An array of parameters to pass to the template + * + * @throws LoaderError When the template cannot be found + * @throws SyntaxError When an error occurred during compilation + * @throws RuntimeError When an error occurred during rendering + */ + public function display($name, array $context = []) + { + $this->load($name)->display($context); + } + + /** + * Loads a template. + * + * @param string|TemplateWrapper|\Twig\Template $name The template name + * + * @throws LoaderError When the template cannot be found + * @throws RuntimeError When a previously generated cache is corrupted + * @throws SyntaxError When an error occurred during compilation + * + * @return TemplateWrapper + */ + public function load($name) + { + if ($name instanceof TemplateWrapper) { + return $name; + } + + if ($name instanceof Template) { + return new TemplateWrapper($this, $name); + } + + return new TemplateWrapper($this, $this->loadTemplate($name)); + } + + /** + * Loads a template internal representation. + * + * This method is for internal use only and should never be called + * directly. + * + * @param string $name The template name + * @param int $index The index if it is an embedded template + * + * @return \Twig_TemplateInterface A template instance representing the given template name + * + * @throws LoaderError When the template cannot be found + * @throws RuntimeError When a previously generated cache is corrupted + * @throws SyntaxError When an error occurred during compilation + * + * @internal + */ + public function loadTemplate($name, $index = null) + { + return $this->loadClass($this->getTemplateClass($name), $name, $index); + } + + /** + * @internal + */ + public function loadClass($cls, $name, $index = null) + { + $mainCls = $cls; + if (null !== $index) { + $cls .= '___'.$index; + } + + if (isset($this->loadedTemplates[$cls])) { + return $this->loadedTemplates[$cls]; + } + + if (!class_exists($cls, false)) { + if ($this->bcGetCacheFilename) { + $key = $this->getCacheFilename($name); + } else { + $key = $this->cache->generateKey($name, $mainCls); + } + + if (!$this->isAutoReload() || $this->isTemplateFresh($name, $this->cache->getTimestamp($key))) { + $this->cache->load($key); + } + + $source = null; + if (!class_exists($cls, false)) { + $loader = $this->getLoader(); + if (!$loader instanceof SourceContextLoaderInterface) { + $source = new Source($loader->getSource($name), $name); + } else { + $source = $loader->getSourceContext($name); + } + + $content = $this->compileSource($source); + + if ($this->bcWriteCacheFile) { + $this->writeCacheFile($key, $content); + } else { + $this->cache->write($key, $content); + $this->cache->load($key); + } + + if (!class_exists($mainCls, false)) { + /* Last line of defense if either $this->bcWriteCacheFile was used, + * $this->cache is implemented as a no-op or we have a race condition + * where the cache was cleared between the above calls to write to and load from + * the cache. + */ + eval('?>'.$content); + } + } + + if (!class_exists($cls, false)) { + throw new RuntimeError(sprintf('Failed to load Twig template "%s", index "%s": cache might be corrupted.', $name, $index), -1, $source); + } + } -if (\false) { - class Environment extends \Twig_Environment + if (!$this->runtimeInitialized) { + $this->initRuntime(); + } + + return $this->loadedTemplates[$cls] = new $cls($this); + } + + /** + * Creates a template from source. + * + * This method should not be used as a generic way to load templates. + * + * @param string $template The template name + * @param string $name An optional name of the template to be used in error messages + * + * @return TemplateWrapper A template instance representing the given template name + * + * @throws LoaderError When the template cannot be found + * @throws SyntaxError When an error occurred during compilation + */ + public function createTemplate($template, $name = null) + { + $hash = hash('sha256', $template, false); + if (null !== $name) { + $name = sprintf('%s (string template %s)', $name, $hash); + } else { + $name = sprintf('__string_template__%s', $hash); + } + + $loader = new ChainLoader([ + new ArrayLoader([$name => $template]), + $current = $this->getLoader(), + ]); + + $this->setLoader($loader); + try { + $template = new TemplateWrapper($this, $this->loadTemplate($name)); + } catch (\Exception $e) { + $this->setLoader($current); + + throw $e; + } catch (\Throwable $e) { + $this->setLoader($current); + + throw $e; + } + $this->setLoader($current); + + return $template; + } + + /** + * Returns true if the template is still fresh. + * + * Besides checking the loader for freshness information, + * this method also checks if the enabled extensions have + * not changed. + * + * @param string $name The template name + * @param int $time The last modification time of the cached template + * + * @return bool true if the template is fresh, false otherwise + */ + public function isTemplateFresh($name, $time) + { + if (0 === $this->lastModifiedExtension) { + foreach ($this->extensions as $extension) { + $r = new \ReflectionObject($extension); + if (file_exists($r->getFileName()) && ($extensionTime = filemtime($r->getFileName())) > $this->lastModifiedExtension) { + $this->lastModifiedExtension = $extensionTime; + } + } + } + + return $this->lastModifiedExtension <= $time && $this->getLoader()->isFresh($name, $time); + } + + /** + * Tries to load a template consecutively from an array. + * + * Similar to load() but it also accepts instances of \Twig\Template and + * \Twig\TemplateWrapper, and an array of templates where each is tried to be loaded. + * + * @param string|Template|\Twig\TemplateWrapper|array $names A template or an array of templates to try consecutively + * + * @return TemplateWrapper|Template + * + * @throws LoaderError When none of the templates can be found + * @throws SyntaxError When an error occurred during compilation + */ + public function resolveTemplate($names) + { + if (!\is_array($names)) { + $names = [$names]; + } + + foreach ($names as $name) { + if ($name instanceof Template) { + return $name; + } + if ($name instanceof TemplateWrapper) { + return $name; + } + + try { + return $this->loadTemplate($name); + } catch (LoaderError $e) { + if (1 === \count($names)) { + throw $e; + } + } + } + + throw new LoaderError(sprintf('Unable to find one of the following templates: "%s".', implode('", "', $names))); + } + + /** + * Clears the internal template cache. + * + * @deprecated since 1.18.3 (to be removed in 2.0) + */ + public function clearTemplateCache() + { + @trigger_error(sprintf('The %s method is deprecated since version 1.18.3 and will be removed in Twig 2.0.', __METHOD__), E_USER_DEPRECATED); + + $this->loadedTemplates = []; + } + + /** + * Clears the template cache files on the filesystem. + * + * @deprecated since 1.22 (to be removed in 2.0) + */ + public function clearCacheFiles() + { + @trigger_error(sprintf('The %s method is deprecated since version 1.22 and will be removed in Twig 2.0.', __METHOD__), E_USER_DEPRECATED); + + if (\is_string($this->originalCache)) { + foreach (new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($this->originalCache), \RecursiveIteratorIterator::LEAVES_ONLY) as $file) { + if ($file->isFile()) { + @unlink($file->getPathname()); + } + } + } + } + + /** + * Gets the Lexer instance. + * + * @return \Twig_LexerInterface + * + * @deprecated since 1.25 (to be removed in 2.0) + */ + public function getLexer() + { + @trigger_error(sprintf('The %s() method is deprecated since version 1.25 and will be removed in 2.0.', __FUNCTION__), E_USER_DEPRECATED); + + if (null === $this->lexer) { + $this->lexer = new Lexer($this); + } + + return $this->lexer; + } + + public function setLexer(\Twig_LexerInterface $lexer) + { + $this->lexer = $lexer; + } + + /** + * Tokenizes a source code. + * + * @param string|Source $source The template source code + * @param string $name The template name (deprecated) + * + * @return TokenStream + * + * @throws SyntaxError When the code is syntactically wrong + */ + public function tokenize($source, $name = null) + { + if (!$source instanceof Source) { + @trigger_error(sprintf('Passing a string as the $source argument of %s() is deprecated since version 1.27. Pass a Twig\Source instance instead.', __METHOD__), E_USER_DEPRECATED); + $source = new Source($source, $name); + } + + if (null === $this->lexer) { + $this->lexer = new Lexer($this); + } + + return $this->lexer->tokenize($source); + } + + /** + * Gets the Parser instance. + * + * @return \Twig_ParserInterface + * + * @deprecated since 1.25 (to be removed in 2.0) + */ + public function getParser() + { + @trigger_error(sprintf('The %s() method is deprecated since version 1.25 and will be removed in 2.0.', __FUNCTION__), E_USER_DEPRECATED); + + if (null === $this->parser) { + $this->parser = new Parser($this); + } + + return $this->parser; + } + + public function setParser(\Twig_ParserInterface $parser) + { + $this->parser = $parser; + } + + /** + * Converts a token stream to a node tree. + * + * @return ModuleNode + * + * @throws SyntaxError When the token stream is syntactically or semantically wrong + */ + public function parse(TokenStream $stream) + { + if (null === $this->parser) { + $this->parser = new Parser($this); + } + + return $this->parser->parse($stream); + } + + /** + * Gets the Compiler instance. + * + * @return \Twig_CompilerInterface + * + * @deprecated since 1.25 (to be removed in 2.0) + */ + public function getCompiler() { + @trigger_error(sprintf('The %s() method is deprecated since version 1.25 and will be removed in 2.0.', __FUNCTION__), E_USER_DEPRECATED); + + if (null === $this->compiler) { + $this->compiler = new Compiler($this); + } + + return $this->compiler; + } + + public function setCompiler(\Twig_CompilerInterface $compiler) + { + $this->compiler = $compiler; + } + + /** + * Compiles a node and returns the PHP code. + * + * @return string The compiled PHP source code + */ + public function compile(\Twig_NodeInterface $node) + { + if (null === $this->compiler) { + $this->compiler = new Compiler($this); + } + + return $this->compiler->compile($node)->getSource(); + } + + /** + * Compiles a template source code. + * + * @param string|Source $source The template source code + * @param string $name The template name (deprecated) + * + * @return string The compiled PHP source code + * + * @throws SyntaxError When there was an error during tokenizing, parsing or compiling + */ + public function compileSource($source, $name = null) + { + if (!$source instanceof Source) { + @trigger_error(sprintf('Passing a string as the $source argument of %s() is deprecated since version 1.27. Pass a Twig\Source instance instead.', __METHOD__), E_USER_DEPRECATED); + $source = new Source($source, $name); + } + + try { + return $this->compile($this->parse($this->tokenize($source))); + } catch (Error $e) { + $e->setSourceContext($source); + throw $e; + } catch (\Exception $e) { + throw new SyntaxError(sprintf('An exception has been thrown during the compilation of a template ("%s").', $e->getMessage()), -1, $source, $e); + } + } + + public function setLoader(LoaderInterface $loader) + { + if (!$loader instanceof SourceContextLoaderInterface && 0 !== strpos(\get_class($loader), 'Mock_')) { + @trigger_error(sprintf('Twig loader "%s" should implement Twig\Loader\SourceContextLoaderInterface since version 1.27.', \get_class($loader)), E_USER_DEPRECATED); + } + + $this->loader = $loader; + } + + /** + * Gets the Loader instance. + * + * @return LoaderInterface + */ + public function getLoader() + { + if (null === $this->loader) { + throw new \LogicException('You must set a loader first.'); + } + + return $this->loader; + } + + /** + * Sets the default template charset. + * + * @param string $charset The default charset + */ + public function setCharset($charset) + { + $this->charset = strtoupper($charset); + } + + /** + * Gets the default template charset. + * + * @return string The default charset + */ + public function getCharset() + { + return $this->charset; + } + + /** + * Initializes the runtime environment. + * + * @deprecated since 1.23 (to be removed in 2.0) + */ + public function initRuntime() + { + $this->runtimeInitialized = true; + + foreach ($this->getExtensions() as $name => $extension) { + if (!$extension instanceof InitRuntimeInterface) { + $m = new \ReflectionMethod($extension, 'initRuntime'); + + $parentClass = $m->getDeclaringClass()->getName(); + if ('Twig_Extension' !== $parentClass && 'Twig\Extension\AbstractExtension' !== $parentClass) { + @trigger_error(sprintf('Defining the initRuntime() method in the "%s" extension is deprecated since version 1.23. Use the `needs_environment` option to get the \Twig_Environment instance in filters, functions, or tests; or explicitly implement Twig\Extension\InitRuntimeInterface if needed (not recommended).', $name), E_USER_DEPRECATED); + } + } + + $extension->initRuntime($this); + } + } + + /** + * Returns true if the given extension is registered. + * + * @param string $class The extension class name + * + * @return bool Whether the extension is registered or not + */ + public function hasExtension($class) + { + $class = ltrim($class, '\\'); + if (!isset($this->extensionsByClass[$class]) && class_exists($class, false)) { + // For BC/FC with namespaced aliases + $class = new \ReflectionClass($class); + $class = $class->name; + } + + if (isset($this->extensions[$class])) { + if ($class !== \get_class($this->extensions[$class])) { + @trigger_error(sprintf('Referencing the "%s" extension by its name (defined by getName()) is deprecated since 1.26 and will be removed in Twig 2.0. Use the Fully Qualified Extension Class Name instead.', $class), E_USER_DEPRECATED); + } + + return true; + } + + return isset($this->extensionsByClass[$class]); + } + + /** + * Adds a runtime loader. + */ + public function addRuntimeLoader(RuntimeLoaderInterface $loader) + { + $this->runtimeLoaders[] = $loader; + } + + /** + * Gets an extension by class name. + * + * @param string $class The extension class name + * + * @return ExtensionInterface + */ + public function getExtension($class) + { + $class = ltrim($class, '\\'); + if (!isset($this->extensionsByClass[$class]) && class_exists($class, false)) { + // For BC/FC with namespaced aliases + $class = new \ReflectionClass($class); + $class = $class->name; + } + + if (isset($this->extensions[$class])) { + if ($class !== \get_class($this->extensions[$class])) { + @trigger_error(sprintf('Referencing the "%s" extension by its name (defined by getName()) is deprecated since 1.26 and will be removed in Twig 2.0. Use the Fully Qualified Extension Class Name instead.', $class), E_USER_DEPRECATED); + } + + return $this->extensions[$class]; + } + + if (!isset($this->extensionsByClass[$class])) { + throw new RuntimeError(sprintf('The "%s" extension is not enabled.', $class)); + } + + return $this->extensionsByClass[$class]; + } + + /** + * Returns the runtime implementation of a Twig element (filter/function/test). + * + * @param string $class A runtime class name + * + * @return object The runtime implementation + * + * @throws RuntimeError When the template cannot be found + */ + public function getRuntime($class) + { + if (isset($this->runtimes[$class])) { + return $this->runtimes[$class]; + } + + foreach ($this->runtimeLoaders as $loader) { + if (null !== $runtime = $loader->load($class)) { + return $this->runtimes[$class] = $runtime; + } + } + + throw new RuntimeError(sprintf('Unable to load the "%s" runtime.', $class)); + } + + public function addExtension(ExtensionInterface $extension) + { + if ($this->extensionInitialized) { + throw new \LogicException(sprintf('Unable to register extension "%s" as extensions have already been initialized.', $extension->getName())); + } + + $class = \get_class($extension); + if ($class !== $extension->getName()) { + if (isset($this->extensions[$extension->getName()])) { + unset($this->extensions[$extension->getName()], $this->extensionsByClass[$class]); + @trigger_error(sprintf('The possibility to register the same extension twice ("%s") is deprecated since version 1.23 and will be removed in Twig 2.0. Use proper PHP inheritance instead.', $extension->getName()), E_USER_DEPRECATED); + } + } + + $this->lastModifiedExtension = 0; + $this->extensionsByClass[$class] = $extension; + $this->extensions[$extension->getName()] = $extension; + $this->updateOptionsHash(); + } + + /** + * Removes an extension by name. + * + * This method is deprecated and you should not use it. + * + * @param string $name The extension name + * + * @deprecated since 1.12 (to be removed in 2.0) + */ + public function removeExtension($name) + { + @trigger_error(sprintf('The %s method is deprecated since version 1.12 and will be removed in Twig 2.0.', __METHOD__), E_USER_DEPRECATED); + + if ($this->extensionInitialized) { + throw new \LogicException(sprintf('Unable to remove extension "%s" as extensions have already been initialized.', $name)); + } + + $class = ltrim($name, '\\'); + if (!isset($this->extensionsByClass[$class]) && class_exists($class, false)) { + // For BC/FC with namespaced aliases + $class = new \ReflectionClass($class); + $class = $class->name; + } + + if (isset($this->extensions[$class])) { + if ($class !== \get_class($this->extensions[$class])) { + @trigger_error(sprintf('Referencing the "%s" extension by its name (defined by getName()) is deprecated since 1.26 and will be removed in Twig 2.0. Use the Fully Qualified Extension Class Name instead.', $class), E_USER_DEPRECATED); + } + + unset($this->extensions[$class]); + } + + unset($this->extensions[$class]); + $this->updateOptionsHash(); + } + + /** + * Registers an array of extensions. + * + * @param array $extensions An array of extensions + */ + public function setExtensions(array $extensions) + { + foreach ($extensions as $extension) { + $this->addExtension($extension); + } + } + + /** + * Returns all registered extensions. + * + * @return ExtensionInterface[] An array of extensions (keys are for internal usage only and should not be relied on) + */ + public function getExtensions() + { + return $this->extensions; + } + + public function addTokenParser(TokenParserInterface $parser) + { + if ($this->extensionInitialized) { + throw new \LogicException('Unable to add a token parser as extensions have already been initialized.'); + } + + $this->staging->addTokenParser($parser); + } + + /** + * Gets the registered Token Parsers. + * + * @return \Twig_TokenParserBrokerInterface + * + * @internal + */ + public function getTokenParsers() + { + if (!$this->extensionInitialized) { + $this->initExtensions(); + } + + return $this->parsers; + } + + /** + * Gets registered tags. + * + * Be warned that this method cannot return tags defined by \Twig_TokenParserBrokerInterface classes. + * + * @return TokenParserInterface[] + * + * @internal + */ + public function getTags() + { + $tags = []; + foreach ($this->getTokenParsers()->getParsers() as $parser) { + if ($parser instanceof TokenParserInterface) { + $tags[$parser->getTag()] = $parser; + } + } + + return $tags; + } + + public function addNodeVisitor(NodeVisitorInterface $visitor) + { + if ($this->extensionInitialized) { + throw new \LogicException('Unable to add a node visitor as extensions have already been initialized.'); + } + + $this->staging->addNodeVisitor($visitor); + } + + /** + * Gets the registered Node Visitors. + * + * @return NodeVisitorInterface[] + * + * @internal + */ + public function getNodeVisitors() + { + if (!$this->extensionInitialized) { + $this->initExtensions(); + } + + return $this->visitors; + } + + /** + * Registers a Filter. + * + * @param string|TwigFilter $name The filter name or a \Twig_SimpleFilter instance + * @param \Twig_FilterInterface|TwigFilter $filter + */ + public function addFilter($name, $filter = null) + { + if (!$name instanceof TwigFilter && !($filter instanceof TwigFilter || $filter instanceof \Twig_FilterInterface)) { + throw new \LogicException('A filter must be an instance of \Twig_FilterInterface or \Twig_SimpleFilter.'); + } + + if ($name instanceof TwigFilter) { + $filter = $name; + $name = $filter->getName(); + } else { + @trigger_error(sprintf('Passing a name as a first argument to the %s method is deprecated since version 1.21. Pass an instance of "Twig_SimpleFilter" instead when defining filter "%s".', __METHOD__, $name), E_USER_DEPRECATED); + } + + if ($this->extensionInitialized) { + throw new \LogicException(sprintf('Unable to add filter "%s" as extensions have already been initialized.', $name)); + } + + $this->staging->addFilter($name, $filter); + } + + /** + * Get a filter by name. + * + * Subclasses may override this method and load filters differently; + * so no list of filters is available. + * + * @param string $name The filter name + * + * @return \Twig_Filter|false + * + * @internal + */ + public function getFilter($name) + { + if (!$this->extensionInitialized) { + $this->initExtensions(); + } + + if (isset($this->filters[$name])) { + return $this->filters[$name]; + } + + foreach ($this->filters as $pattern => $filter) { + $pattern = str_replace('\\*', '(.*?)', preg_quote($pattern, '#'), $count); + + if ($count) { + if (preg_match('#^'.$pattern.'$#', $name, $matches)) { + array_shift($matches); + $filter->setArguments($matches); + + return $filter; + } + } + } + + foreach ($this->filterCallbacks as $callback) { + if (false !== $filter = \call_user_func($callback, $name)) { + return $filter; + } + } + + return false; + } + + public function registerUndefinedFilterCallback($callable) + { + $this->filterCallbacks[] = $callable; + } + + /** + * Gets the registered Filters. + * + * Be warned that this method cannot return filters defined with registerUndefinedFilterCallback. + * + * @return \Twig_FilterInterface[] + * + * @see registerUndefinedFilterCallback + * + * @internal + */ + public function getFilters() + { + if (!$this->extensionInitialized) { + $this->initExtensions(); + } + + return $this->filters; + } + + /** + * Registers a Test. + * + * @param string|TwigTest $name The test name or a \Twig_SimpleTest instance + * @param \Twig_TestInterface|TwigTest $test A \Twig_TestInterface instance or a \Twig_SimpleTest instance + */ + public function addTest($name, $test = null) + { + if (!$name instanceof TwigTest && !($test instanceof TwigTest || $test instanceof \Twig_TestInterface)) { + throw new \LogicException('A test must be an instance of \Twig_TestInterface or \Twig_SimpleTest.'); + } + + if ($name instanceof TwigTest) { + $test = $name; + $name = $test->getName(); + } else { + @trigger_error(sprintf('Passing a name as a first argument to the %s method is deprecated since version 1.21. Pass an instance of "Twig_SimpleTest" instead when defining test "%s".', __METHOD__, $name), E_USER_DEPRECATED); + } + + if ($this->extensionInitialized) { + throw new \LogicException(sprintf('Unable to add test "%s" as extensions have already been initialized.', $name)); + } + + $this->staging->addTest($name, $test); + } + + /** + * Gets the registered Tests. + * + * @return \Twig_TestInterface[] + * + * @internal + */ + public function getTests() + { + if (!$this->extensionInitialized) { + $this->initExtensions(); + } + + return $this->tests; + } + + /** + * Gets a test by name. + * + * @param string $name The test name + * + * @return \Twig_Test|false + * + * @internal + */ + public function getTest($name) + { + if (!$this->extensionInitialized) { + $this->initExtensions(); + } + + if (isset($this->tests[$name])) { + return $this->tests[$name]; + } + + foreach ($this->tests as $pattern => $test) { + $pattern = str_replace('\\*', '(.*?)', preg_quote($pattern, '#'), $count); + + if ($count) { + if (preg_match('#^'.$pattern.'$#', $name, $matches)) { + array_shift($matches); + $test->setArguments($matches); + + return $test; + } + } + } + + return false; + } + + /** + * Registers a Function. + * + * @param string|TwigFunction $name The function name or a \Twig_SimpleFunction instance + * @param \Twig_FunctionInterface|TwigFunction $function + */ + public function addFunction($name, $function = null) + { + if (!$name instanceof TwigFunction && !($function instanceof TwigFunction || $function instanceof \Twig_FunctionInterface)) { + throw new \LogicException('A function must be an instance of \Twig_FunctionInterface or \Twig_SimpleFunction.'); + } + + if ($name instanceof TwigFunction) { + $function = $name; + $name = $function->getName(); + } else { + @trigger_error(sprintf('Passing a name as a first argument to the %s method is deprecated since version 1.21. Pass an instance of "Twig_SimpleFunction" instead when defining function "%s".', __METHOD__, $name), E_USER_DEPRECATED); + } + + if ($this->extensionInitialized) { + throw new \LogicException(sprintf('Unable to add function "%s" as extensions have already been initialized.', $name)); + } + + $this->staging->addFunction($name, $function); + } + + /** + * Get a function by name. + * + * Subclasses may override this method and load functions differently; + * so no list of functions is available. + * + * @param string $name function name + * + * @return \Twig_Function|false + * + * @internal + */ + public function getFunction($name) + { + if (!$this->extensionInitialized) { + $this->initExtensions(); + } + + if (isset($this->functions[$name])) { + return $this->functions[$name]; + } + + foreach ($this->functions as $pattern => $function) { + $pattern = str_replace('\\*', '(.*?)', preg_quote($pattern, '#'), $count); + + if ($count) { + if (preg_match('#^'.$pattern.'$#', $name, $matches)) { + array_shift($matches); + $function->setArguments($matches); + + return $function; + } + } + } + + foreach ($this->functionCallbacks as $callback) { + if (false !== $function = \call_user_func($callback, $name)) { + return $function; + } + } + + return false; + } + + public function registerUndefinedFunctionCallback($callable) + { + $this->functionCallbacks[] = $callable; + } + + /** + * Gets registered functions. + * + * Be warned that this method cannot return functions defined with registerUndefinedFunctionCallback. + * + * @return \Twig_FunctionInterface[] + * + * @see registerUndefinedFunctionCallback + * + * @internal + */ + public function getFunctions() + { + if (!$this->extensionInitialized) { + $this->initExtensions(); + } + + return $this->functions; + } + + /** + * Registers a Global. + * + * New globals can be added before compiling or rendering a template; + * but after, you can only update existing globals. + * + * @param string $name The global name + * @param mixed $value The global value + */ + public function addGlobal($name, $value) + { + if ($this->extensionInitialized || $this->runtimeInitialized) { + if (null === $this->globals) { + $this->globals = $this->initGlobals(); + } + + if (!\array_key_exists($name, $this->globals)) { + // The deprecation notice must be turned into the following exception in Twig 2.0 + @trigger_error(sprintf('Registering global variable "%s" at runtime or when the extensions have already been initialized is deprecated since version 1.21.', $name), E_USER_DEPRECATED); + //throw new \LogicException(sprintf('Unable to add global "%s" as the runtime or the extensions have already been initialized.', $name)); + } + } + + if ($this->extensionInitialized || $this->runtimeInitialized) { + // update the value + $this->globals[$name] = $value; + } else { + $this->staging->addGlobal($name, $value); + } + } + + /** + * Gets the registered Globals. + * + * @return array An array of globals + * + * @internal + */ + public function getGlobals() + { + if (!$this->runtimeInitialized && !$this->extensionInitialized) { + return $this->initGlobals(); + } + + if (null === $this->globals) { + $this->globals = $this->initGlobals(); + } + + return $this->globals; + } + + /** + * Merges a context with the defined globals. + * + * @param array $context An array representing the context + * + * @return array The context merged with the globals + */ + public function mergeGlobals(array $context) + { + // we don't use array_merge as the context being generally + // bigger than globals, this code is faster. + foreach ($this->getGlobals() as $key => $value) { + if (!\array_key_exists($key, $context)) { + $context[$key] = $value; + } + } + + return $context; + } + + /** + * Gets the registered unary Operators. + * + * @return array An array of unary operators + * + * @internal + */ + public function getUnaryOperators() + { + if (!$this->extensionInitialized) { + $this->initExtensions(); + } + + return $this->unaryOperators; + } + + /** + * Gets the registered binary Operators. + * + * @return array An array of binary operators + * + * @internal + */ + public function getBinaryOperators() + { + if (!$this->extensionInitialized) { + $this->initExtensions(); + } + + return $this->binaryOperators; + } + + /** + * @deprecated since 1.23 (to be removed in 2.0) + */ + public function computeAlternatives($name, $items) + { + @trigger_error(sprintf('The %s method is deprecated since version 1.23 and will be removed in Twig 2.0.', __METHOD__), E_USER_DEPRECATED); + + return SyntaxError::computeAlternatives($name, $items); + } + + /** + * @internal + */ + protected function initGlobals() + { + $globals = []; + foreach ($this->extensions as $name => $extension) { + if (!$extension instanceof GlobalsInterface) { + $m = new \ReflectionMethod($extension, 'getGlobals'); + + $parentClass = $m->getDeclaringClass()->getName(); + if ('Twig_Extension' !== $parentClass && 'Twig\Extension\AbstractExtension' !== $parentClass) { + @trigger_error(sprintf('Defining the getGlobals() method in the "%s" extension without explicitly implementing Twig\Extension\GlobalsInterface is deprecated since version 1.23.', $name), E_USER_DEPRECATED); + } + } + + $extGlob = $extension->getGlobals(); + if (!\is_array($extGlob)) { + throw new \UnexpectedValueException(sprintf('"%s::getGlobals()" must return an array of globals.', \get_class($extension))); + } + + $globals[] = $extGlob; + } + + $globals[] = $this->staging->getGlobals(); + + return \call_user_func_array('array_merge', $globals); + } + + /** + * @internal + */ + protected function initExtensions() + { + if ($this->extensionInitialized) { + return; + } + + $this->parsers = new \Twig_TokenParserBroker([], [], false); + $this->filters = []; + $this->functions = []; + $this->tests = []; + $this->visitors = []; + $this->unaryOperators = []; + $this->binaryOperators = []; + + foreach ($this->extensions as $extension) { + $this->initExtension($extension); + } + $this->initExtension($this->staging); + // Done at the end only, so that an exception during initialization does not mark the environment as initialized when catching the exception + $this->extensionInitialized = true; + } + + /** + * @internal + */ + protected function initExtension(ExtensionInterface $extension) + { + // filters + foreach ($extension->getFilters() as $name => $filter) { + if ($filter instanceof TwigFilter) { + $name = $filter->getName(); + } else { + @trigger_error(sprintf('Using an instance of "%s" for filter "%s" is deprecated since version 1.21. Use \Twig_SimpleFilter instead.', \get_class($filter), $name), E_USER_DEPRECATED); + } + + $this->filters[$name] = $filter; + } + + // functions + foreach ($extension->getFunctions() as $name => $function) { + if ($function instanceof TwigFunction) { + $name = $function->getName(); + } else { + @trigger_error(sprintf('Using an instance of "%s" for function "%s" is deprecated since version 1.21. Use \Twig_SimpleFunction instead.', \get_class($function), $name), E_USER_DEPRECATED); + } + + $this->functions[$name] = $function; + } + + // tests + foreach ($extension->getTests() as $name => $test) { + if ($test instanceof TwigTest) { + $name = $test->getName(); + } else { + @trigger_error(sprintf('Using an instance of "%s" for test "%s" is deprecated since version 1.21. Use \Twig_SimpleTest instead.', \get_class($test), $name), E_USER_DEPRECATED); + } + + $this->tests[$name] = $test; + } + + // token parsers + foreach ($extension->getTokenParsers() as $parser) { + if ($parser instanceof TokenParserInterface) { + $this->parsers->addTokenParser($parser); + } elseif ($parser instanceof \Twig_TokenParserBrokerInterface) { + @trigger_error('Registering a \Twig_TokenParserBrokerInterface instance is deprecated since version 1.21.', E_USER_DEPRECATED); + + $this->parsers->addTokenParserBroker($parser); + } else { + throw new \LogicException('getTokenParsers() must return an array of \Twig_TokenParserInterface or \Twig_TokenParserBrokerInterface instances.'); + } + } + + // node visitors + foreach ($extension->getNodeVisitors() as $visitor) { + $this->visitors[] = $visitor; + } + + // operators + if ($operators = $extension->getOperators()) { + if (!\is_array($operators)) { + throw new \InvalidArgumentException(sprintf('"%s::getOperators()" must return an array with operators, got "%s".', \get_class($extension), \is_object($operators) ? \get_class($operators) : \gettype($operators).(\is_resource($operators) ? '' : '#'.$operators))); + } + + if (2 !== \count($operators)) { + throw new \InvalidArgumentException(sprintf('"%s::getOperators()" must return an array of 2 elements, got %d.', \get_class($extension), \count($operators))); + } + + $this->unaryOperators = array_merge($this->unaryOperators, $operators[0]); + $this->binaryOperators = array_merge($this->binaryOperators, $operators[1]); + } + } + + /** + * @deprecated since 1.22 (to be removed in 2.0) + */ + protected function writeCacheFile($file, $content) + { + $this->cache->write($file, $content); + } + + private function updateOptionsHash() + { + $hashParts = array_merge( + array_keys($this->extensions), + [ + (int) \function_exists('twig_template_get_attributes'), + PHP_MAJOR_VERSION, + PHP_MINOR_VERSION, + self::VERSION, + (int) $this->debug, + $this->baseTemplateClass, + (int) $this->strictVariables, + ] + ); + $this->optionsHash = implode(':', $hashParts); } } + +class_alias('Twig\Environment', 'Twig_Environment'); diff --git a/vendor/twig/twig/src/Error/Error.php b/vendor/twig/twig/src/Error/Error.php index 52224d8afb785395b6e53a40160345e07326686f..2aa70f1538ab4ed1dd78900a162d7e3558a4ca64 100644 --- a/vendor/twig/twig/src/Error/Error.php +++ b/vendor/twig/twig/src/Error/Error.php @@ -1,11 +1,325 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\Error; -class_exists('Twig_Error'); +use Twig\Source; +use Twig\Template; + +/** + * Twig base exception. + * + * This exception class and its children must only be used when + * an error occurs during the loading of a template, when a syntax error + * is detected in a template, or when rendering a template. Other + * errors must use regular PHP exception classes (like when the template + * cache directory is not writable for instance). + * + * To help debugging template issues, this class tracks the original template + * name and line where the error occurred. + * + * Whenever possible, you must set these information (original template name + * and line number) yourself by passing them to the constructor. If some or all + * these information are not available from where you throw the exception, then + * this class will guess them automatically (when the line number is set to -1 + * and/or the name is set to null). As this is a costly operation, this + * can be disabled by passing false for both the name and the line number + * when creating a new instance of this class. + * + * @author Fabien Potencier <fabien@symfony.com> + */ +class Error extends \Exception +{ + protected $lineno; + // to be renamed to name in 2.0 + protected $filename; + protected $rawMessage; + + private $sourcePath; + private $sourceCode; + + /** + * Constructor. + * + * Set the line number to -1 to enable its automatic guessing. + * Set the name to null to enable its automatic guessing. + * + * @param string $message The error message + * @param int $lineno The template line where the error occurred + * @param Source|string|null $source The source context where the error occurred + * @param \Exception $previous The previous exception + */ + public function __construct($message, $lineno = -1, $source = null, \Exception $previous = null) + { + if (null === $source) { + $name = null; + } elseif (!$source instanceof Source) { + // for compat with the Twig C ext., passing the template name as string is accepted + $name = $source; + } else { + $name = $source->getName(); + $this->sourceCode = $source->getCode(); + $this->sourcePath = $source->getPath(); + } + parent::__construct('', 0, $previous); + + $this->lineno = $lineno; + $this->filename = $name; + $this->rawMessage = $message; + $this->updateRepr(); + } + + /** + * Gets the raw message. + * + * @return string The raw message + */ + public function getRawMessage() + { + return $this->rawMessage; + } + + /** + * Gets the logical name where the error occurred. + * + * @return string The name + * + * @deprecated since 1.27 (to be removed in 2.0). Use getSourceContext() instead. + */ + public function getTemplateFile() + { + @trigger_error(sprintf('The "%s" method is deprecated since version 1.27 and will be removed in 2.0. Use getSourceContext() instead.', __METHOD__), E_USER_DEPRECATED); + + return $this->filename; + } + + /** + * Sets the logical name where the error occurred. + * + * @param string $name The name + * + * @deprecated since 1.27 (to be removed in 2.0). Use setSourceContext() instead. + */ + public function setTemplateFile($name) + { + @trigger_error(sprintf('The "%s" method is deprecated since version 1.27 and will be removed in 2.0. Use setSourceContext() instead.', __METHOD__), E_USER_DEPRECATED); + + $this->filename = $name; + + $this->updateRepr(); + } + + /** + * Gets the logical name where the error occurred. + * + * @return string The name + * + * @deprecated since 1.29 (to be removed in 2.0). Use getSourceContext() instead. + */ + public function getTemplateName() + { + @trigger_error(sprintf('The "%s" method is deprecated since version 1.29 and will be removed in 2.0. Use getSourceContext() instead.', __METHOD__), E_USER_DEPRECATED); + + return $this->filename; + } + + /** + * Sets the logical name where the error occurred. + * + * @param string $name The name + * + * @deprecated since 1.29 (to be removed in 2.0). Use setSourceContext() instead. + */ + public function setTemplateName($name) + { + @trigger_error(sprintf('The "%s" method is deprecated since version 1.29 and will be removed in 2.0. Use setSourceContext() instead.', __METHOD__), E_USER_DEPRECATED); + + $this->filename = $name; + $this->sourceCode = $this->sourcePath = null; + + $this->updateRepr(); + } + + /** + * Gets the template line where the error occurred. + * + * @return int The template line + */ + public function getTemplateLine() + { + return $this->lineno; + } + + /** + * Sets the template line where the error occurred. + * + * @param int $lineno The template line + */ + public function setTemplateLine($lineno) + { + $this->lineno = $lineno; + + $this->updateRepr(); + } + + /** + * Gets the source context of the Twig template where the error occurred. + * + * @return Source|null + */ + public function getSourceContext() + { + return $this->filename ? new Source($this->sourceCode, $this->filename, $this->sourcePath) : null; + } + + /** + * Sets the source context of the Twig template where the error occurred. + */ + public function setSourceContext(Source $source = null) + { + if (null === $source) { + $this->sourceCode = $this->filename = $this->sourcePath = null; + } else { + $this->sourceCode = $source->getCode(); + $this->filename = $source->getName(); + $this->sourcePath = $source->getPath(); + } + + $this->updateRepr(); + } + + public function guess() + { + $this->guessTemplateInfo(); + $this->updateRepr(); + } -if (\false) { - class Error extends \Twig_Error + public function appendMessage($rawMessage) { + $this->rawMessage .= $rawMessage; + $this->updateRepr(); + } + + /** + * @internal + */ + protected function updateRepr() + { + $this->message = $this->rawMessage; + + if ($this->sourcePath && $this->lineno > 0) { + $this->file = $this->sourcePath; + $this->line = $this->lineno; + + return; + } + + $dot = false; + if ('.' === substr($this->message, -1)) { + $this->message = substr($this->message, 0, -1); + $dot = true; + } + + $questionMark = false; + if ('?' === substr($this->message, -1)) { + $this->message = substr($this->message, 0, -1); + $questionMark = true; + } + + if ($this->filename) { + if (\is_string($this->filename) || (\is_object($this->filename) && method_exists($this->filename, '__toString'))) { + $name = sprintf('"%s"', $this->filename); + } else { + $name = json_encode($this->filename); + } + $this->message .= sprintf(' in %s', $name); + } + + if ($this->lineno && $this->lineno >= 0) { + $this->message .= sprintf(' at line %d', $this->lineno); + } + + if ($dot) { + $this->message .= '.'; + } + + if ($questionMark) { + $this->message .= '?'; + } + } + + /** + * @internal + */ + protected function guessTemplateInfo() + { + $template = null; + $templateClass = null; + + $backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS | DEBUG_BACKTRACE_PROVIDE_OBJECT); + foreach ($backtrace as $trace) { + if (isset($trace['object']) && $trace['object'] instanceof Template && 'Twig_Template' !== \get_class($trace['object'])) { + $currentClass = \get_class($trace['object']); + $isEmbedContainer = 0 === strpos($templateClass, $currentClass); + if (null === $this->filename || ($this->filename == $trace['object']->getTemplateName() && !$isEmbedContainer)) { + $template = $trace['object']; + $templateClass = \get_class($trace['object']); + } + } + } + + // update template name + if (null !== $template && null === $this->filename) { + $this->filename = $template->getTemplateName(); + } + + // update template path if any + if (null !== $template && null === $this->sourcePath) { + $src = $template->getSourceContext(); + $this->sourceCode = $src->getCode(); + $this->sourcePath = $src->getPath(); + } + + if (null === $template || $this->lineno > -1) { + return; + } + + $r = new \ReflectionObject($template); + $file = $r->getFileName(); + + $exceptions = [$e = $this]; + while ($e instanceof self && $e = $e->getPrevious()) { + $exceptions[] = $e; + } + + while ($e = array_pop($exceptions)) { + $traces = $e->getTrace(); + array_unshift($traces, ['file' => $e->getFile(), 'line' => $e->getLine()]); + + while ($trace = array_shift($traces)) { + if (!isset($trace['file']) || !isset($trace['line']) || $file != $trace['file']) { + continue; + } + + foreach ($template->getDebugInfo() as $codeLine => $templateLine) { + if ($codeLine <= $trace['line']) { + // update template line + $this->lineno = $templateLine; + + return; + } + } + } + } } } + +class_alias('Twig\Error\Error', 'Twig_Error'); diff --git a/vendor/twig/twig/src/Error/LoaderError.php b/vendor/twig/twig/src/Error/LoaderError.php index df731b15b30bac1db493ae7682b8477bbe4252df..dc5a9f1af735b6ad54f499a29bd81c1d0cde49d8 100644 --- a/vendor/twig/twig/src/Error/LoaderError.php +++ b/vendor/twig/twig/src/Error/LoaderError.php @@ -1,11 +1,23 @@ <?php -namespace Twig\Error; +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ -class_exists('Twig_Error_Loader'); +namespace Twig\Error; -if (\false) { - class LoaderError extends \Twig_Error_Loader - { - } +/** + * Exception thrown when an error occurs during template loading. + * + * @author Fabien Potencier <fabien@symfony.com> + */ +class LoaderError extends Error +{ } + +class_alias('Twig\Error\LoaderError', 'Twig_Error_Loader'); diff --git a/vendor/twig/twig/src/Error/RuntimeError.php b/vendor/twig/twig/src/Error/RuntimeError.php index b29ec536c2a7da3c34dd7ea1d33aaf3122b099fe..9b3f36e050e7bdf45a0b2af28d71ba06fb8a1bba 100644 --- a/vendor/twig/twig/src/Error/RuntimeError.php +++ b/vendor/twig/twig/src/Error/RuntimeError.php @@ -1,11 +1,24 @@ <?php -namespace Twig\Error; +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * (c) Armin Ronacher + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ -class_exists('Twig_Error_Runtime'); +namespace Twig\Error; -if (\false) { - class RuntimeError extends \Twig_Error_Runtime - { - } +/** + * Exception thrown when an error occurs at runtime. + * + * @author Fabien Potencier <fabien@symfony.com> + */ +class RuntimeError extends Error +{ } + +class_alias('Twig\Error\RuntimeError', 'Twig_Error_Runtime'); diff --git a/vendor/twig/twig/src/Error/SyntaxError.php b/vendor/twig/twig/src/Error/SyntaxError.php index 1b31520e5307da97eba8a0955bfadd9e1c0ff9e7..480e6606210c80c9b4dc371c4b6d4d1186bc3805 100644 --- a/vendor/twig/twig/src/Error/SyntaxError.php +++ b/vendor/twig/twig/src/Error/SyntaxError.php @@ -1,11 +1,57 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * (c) Armin Ronacher + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\Error; -class_exists('Twig_Error_Syntax'); +/** + * \Exception thrown when a syntax error occurs during lexing or parsing of a template. + * + * @author Fabien Potencier <fabien@symfony.com> + */ +class SyntaxError extends Error +{ + /** + * Tweaks the error message to include suggestions. + * + * @param string $name The original name of the item that does not exist + * @param array $items An array of possible items + */ + public function addSuggestions($name, array $items) + { + if (!$alternatives = self::computeAlternatives($name, $items)) { + return; + } + + $this->appendMessage(sprintf(' Did you mean "%s"?', implode('", "', $alternatives))); + } -if (\false) { - class SyntaxError extends \Twig_Error_Syntax + /** + * @internal + * + * To be merged with the addSuggestions() method in 2.0. + */ + public static function computeAlternatives($name, $items) { + $alternatives = []; + foreach ($items as $item) { + $lev = levenshtein($name, $item); + if ($lev <= \strlen($name) / 3 || false !== strpos($item, $name)) { + $alternatives[$item] = $lev; + } + } + asort($alternatives); + + return array_keys($alternatives); } } + +class_alias('Twig\Error\SyntaxError', 'Twig_Error_Syntax'); diff --git a/vendor/twig/twig/src/ExpressionParser.php b/vendor/twig/twig/src/ExpressionParser.php index 0cbbdbc246541efa6e8a8f5813cf6fd3658ed15b..9066ade169587d4f787676b3c5a7c21db916461d 100644 --- a/vendor/twig/twig/src/ExpressionParser.php +++ b/vendor/twig/twig/src/ExpressionParser.php @@ -1,11 +1,834 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * (c) Armin Ronacher + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig; -class_exists('Twig_ExpressionParser'); +use Twig\Error\SyntaxError; +use Twig\Node\Expression\ArrayExpression; +use Twig\Node\Expression\ArrowFunctionExpression; +use Twig\Node\Expression\AssignNameExpression; +use Twig\Node\Expression\Binary\ConcatBinary; +use Twig\Node\Expression\BlockReferenceExpression; +use Twig\Node\Expression\ConditionalExpression; +use Twig\Node\Expression\ConstantExpression; +use Twig\Node\Expression\GetAttrExpression; +use Twig\Node\Expression\MethodCallExpression; +use Twig\Node\Expression\NameExpression; +use Twig\Node\Expression\ParentExpression; +use Twig\Node\Expression\Unary\NegUnary; +use Twig\Node\Expression\Unary\NotUnary; +use Twig\Node\Expression\Unary\PosUnary; +use Twig\Node\Node; + +/** + * Parses expressions. + * + * This parser implements a "Precedence climbing" algorithm. + * + * @see https://www.engr.mun.ca/~theo/Misc/exp_parsing.htm + * @see https://en.wikipedia.org/wiki/Operator-precedence_parser + * + * @author Fabien Potencier <fabien@symfony.com> + * + * @internal + */ +class ExpressionParser +{ + const OPERATOR_LEFT = 1; + const OPERATOR_RIGHT = 2; + + protected $parser; + protected $unaryOperators; + protected $binaryOperators; + + private $env; + + public function __construct(Parser $parser, $env = null) + { + $this->parser = $parser; + + if ($env instanceof Environment) { + $this->env = $env; + $this->unaryOperators = $env->getUnaryOperators(); + $this->binaryOperators = $env->getBinaryOperators(); + } else { + @trigger_error('Passing the operators as constructor arguments to '.__METHOD__.' is deprecated since version 1.27. Pass the environment instead.', E_USER_DEPRECATED); + + $this->env = $parser->getEnvironment(); + $this->unaryOperators = func_get_arg(1); + $this->binaryOperators = func_get_arg(2); + } + } + + public function parseExpression($precedence = 0, $allowArrow = false) + { + if ($allowArrow && $arrow = $this->parseArrow()) { + return $arrow; + } + + $expr = $this->getPrimary(); + $token = $this->parser->getCurrentToken(); + while ($this->isBinary($token) && $this->binaryOperators[$token->getValue()]['precedence'] >= $precedence) { + $op = $this->binaryOperators[$token->getValue()]; + $this->parser->getStream()->next(); + + if ('is not' === $token->getValue()) { + $expr = $this->parseNotTestExpression($expr); + } elseif ('is' === $token->getValue()) { + $expr = $this->parseTestExpression($expr); + } elseif (isset($op['callable'])) { + $expr = \call_user_func($op['callable'], $this->parser, $expr); + } else { + $expr1 = $this->parseExpression(self::OPERATOR_LEFT === $op['associativity'] ? $op['precedence'] + 1 : $op['precedence']); + $class = $op['class']; + $expr = new $class($expr, $expr1, $token->getLine()); + } + + $token = $this->parser->getCurrentToken(); + } + + if (0 === $precedence) { + return $this->parseConditionalExpression($expr); + } + + return $expr; + } + + /** + * @return ArrowFunctionExpression|null + */ + private function parseArrow() + { + $stream = $this->parser->getStream(); + + // short array syntax (one argument, no parentheses)? + if ($stream->look(1)->test(Token::ARROW_TYPE)) { + $line = $stream->getCurrent()->getLine(); + $token = $stream->expect(Token::NAME_TYPE); + $names = [new AssignNameExpression($token->getValue(), $token->getLine())]; + $stream->expect(Token::ARROW_TYPE); + + return new ArrowFunctionExpression($this->parseExpression(0), new Node($names), $line); + } + + // first, determine if we are parsing an arrow function by finding => (long form) + $i = 0; + if (!$stream->look($i)->test(Token::PUNCTUATION_TYPE, '(')) { + return null; + } + ++$i; + while (true) { + // variable name + ++$i; + if (!$stream->look($i)->test(Token::PUNCTUATION_TYPE, ',')) { + break; + } + ++$i; + } + if (!$stream->look($i)->test(Token::PUNCTUATION_TYPE, ')')) { + return null; + } + ++$i; + if (!$stream->look($i)->test(Token::ARROW_TYPE)) { + return null; + } + + // yes, let's parse it properly + $token = $stream->expect(Token::PUNCTUATION_TYPE, '('); + $line = $token->getLine(); + + $names = []; + while (true) { + $token = $stream->expect(Token::NAME_TYPE); + $names[] = new AssignNameExpression($token->getValue(), $token->getLine()); + + if (!$stream->nextIf(Token::PUNCTUATION_TYPE, ',')) { + break; + } + } + $stream->expect(Token::PUNCTUATION_TYPE, ')'); + $stream->expect(Token::ARROW_TYPE); + + return new ArrowFunctionExpression($this->parseExpression(0), new Node($names), $line); + } + + protected function getPrimary() + { + $token = $this->parser->getCurrentToken(); + + if ($this->isUnary($token)) { + $operator = $this->unaryOperators[$token->getValue()]; + $this->parser->getStream()->next(); + $expr = $this->parseExpression($operator['precedence']); + $class = $operator['class']; + + return $this->parsePostfixExpression(new $class($expr, $token->getLine())); + } elseif ($token->test(Token::PUNCTUATION_TYPE, '(')) { + $this->parser->getStream()->next(); + $expr = $this->parseExpression(); + $this->parser->getStream()->expect(Token::PUNCTUATION_TYPE, ')', 'An opened parenthesis is not properly closed'); + + return $this->parsePostfixExpression($expr); + } + + return $this->parsePrimaryExpression(); + } + + protected function parseConditionalExpression($expr) + { + while ($this->parser->getStream()->nextIf(Token::PUNCTUATION_TYPE, '?')) { + if (!$this->parser->getStream()->nextIf(Token::PUNCTUATION_TYPE, ':')) { + $expr2 = $this->parseExpression(); + if ($this->parser->getStream()->nextIf(Token::PUNCTUATION_TYPE, ':')) { + $expr3 = $this->parseExpression(); + } else { + $expr3 = new ConstantExpression('', $this->parser->getCurrentToken()->getLine()); + } + } else { + $expr2 = $expr; + $expr3 = $this->parseExpression(); + } + + $expr = new ConditionalExpression($expr, $expr2, $expr3, $this->parser->getCurrentToken()->getLine()); + } + + return $expr; + } + + protected function isUnary(Token $token) + { + return $token->test(Token::OPERATOR_TYPE) && isset($this->unaryOperators[$token->getValue()]); + } + + protected function isBinary(Token $token) + { + return $token->test(Token::OPERATOR_TYPE) && isset($this->binaryOperators[$token->getValue()]); + } + + public function parsePrimaryExpression() + { + $token = $this->parser->getCurrentToken(); + switch ($token->getType()) { + case Token::NAME_TYPE: + $this->parser->getStream()->next(); + switch ($token->getValue()) { + case 'true': + case 'TRUE': + $node = new ConstantExpression(true, $token->getLine()); + break; + + case 'false': + case 'FALSE': + $node = new ConstantExpression(false, $token->getLine()); + break; + + case 'none': + case 'NONE': + case 'null': + case 'NULL': + $node = new ConstantExpression(null, $token->getLine()); + break; + + default: + if ('(' === $this->parser->getCurrentToken()->getValue()) { + $node = $this->getFunctionNode($token->getValue(), $token->getLine()); + } else { + $node = new NameExpression($token->getValue(), $token->getLine()); + } + } + break; + + case Token::NUMBER_TYPE: + $this->parser->getStream()->next(); + $node = new ConstantExpression($token->getValue(), $token->getLine()); + break; + + case Token::STRING_TYPE: + case Token::INTERPOLATION_START_TYPE: + $node = $this->parseStringExpression(); + break; + + case Token::OPERATOR_TYPE: + if (preg_match(Lexer::REGEX_NAME, $token->getValue(), $matches) && $matches[0] == $token->getValue()) { + // in this context, string operators are variable names + $this->parser->getStream()->next(); + $node = new NameExpression($token->getValue(), $token->getLine()); + break; + } elseif (isset($this->unaryOperators[$token->getValue()])) { + $class = $this->unaryOperators[$token->getValue()]['class']; + + $ref = new \ReflectionClass($class); + $negClass = 'Twig\Node\Expression\Unary\NegUnary'; + $posClass = 'Twig\Node\Expression\Unary\PosUnary'; + if (!(\in_array($ref->getName(), [$negClass, $posClass, 'Twig_Node_Expression_Unary_Neg', 'Twig_Node_Expression_Unary_Pos']) + || $ref->isSubclassOf($negClass) || $ref->isSubclassOf($posClass) + || $ref->isSubclassOf('Twig_Node_Expression_Unary_Neg') || $ref->isSubclassOf('Twig_Node_Expression_Unary_Pos')) + ) { + throw new SyntaxError(sprintf('Unexpected unary operator "%s".', $token->getValue()), $token->getLine(), $this->parser->getStream()->getSourceContext()); + } + + $this->parser->getStream()->next(); + $expr = $this->parsePrimaryExpression(); + + $node = new $class($expr, $token->getLine()); + break; + } + + // no break + default: + if ($token->test(Token::PUNCTUATION_TYPE, '[')) { + $node = $this->parseArrayExpression(); + } elseif ($token->test(Token::PUNCTUATION_TYPE, '{')) { + $node = $this->parseHashExpression(); + } elseif ($token->test(Token::OPERATOR_TYPE, '=') && ('==' === $this->parser->getStream()->look(-1)->getValue() || '!=' === $this->parser->getStream()->look(-1)->getValue())) { + throw new SyntaxError(sprintf('Unexpected operator of value "%s". Did you try to use "===" or "!==" for strict comparison? Use "is same as(value)" instead.', $token->getValue()), $token->getLine(), $this->parser->getStream()->getSourceContext()); + } else { + throw new SyntaxError(sprintf('Unexpected token "%s" of value "%s".', Token::typeToEnglish($token->getType()), $token->getValue()), $token->getLine(), $this->parser->getStream()->getSourceContext()); + } + } + + return $this->parsePostfixExpression($node); + } + + public function parseStringExpression() + { + $stream = $this->parser->getStream(); + + $nodes = []; + // a string cannot be followed by another string in a single expression + $nextCanBeString = true; + while (true) { + if ($nextCanBeString && $token = $stream->nextIf(Token::STRING_TYPE)) { + $nodes[] = new ConstantExpression($token->getValue(), $token->getLine()); + $nextCanBeString = false; + } elseif ($stream->nextIf(Token::INTERPOLATION_START_TYPE)) { + $nodes[] = $this->parseExpression(); + $stream->expect(Token::INTERPOLATION_END_TYPE); + $nextCanBeString = true; + } else { + break; + } + } + + $expr = array_shift($nodes); + foreach ($nodes as $node) { + $expr = new ConcatBinary($expr, $node, $node->getTemplateLine()); + } + + return $expr; + } + + public function parseArrayExpression() + { + $stream = $this->parser->getStream(); + $stream->expect(Token::PUNCTUATION_TYPE, '[', 'An array element was expected'); + + $node = new ArrayExpression([], $stream->getCurrent()->getLine()); + $first = true; + while (!$stream->test(Token::PUNCTUATION_TYPE, ']')) { + if (!$first) { + $stream->expect(Token::PUNCTUATION_TYPE, ',', 'An array element must be followed by a comma'); + + // trailing ,? + if ($stream->test(Token::PUNCTUATION_TYPE, ']')) { + break; + } + } + $first = false; + + $node->addElement($this->parseExpression()); + } + $stream->expect(Token::PUNCTUATION_TYPE, ']', 'An opened array is not properly closed'); + + return $node; + } + + public function parseHashExpression() + { + $stream = $this->parser->getStream(); + $stream->expect(Token::PUNCTUATION_TYPE, '{', 'A hash element was expected'); + + $node = new ArrayExpression([], $stream->getCurrent()->getLine()); + $first = true; + while (!$stream->test(Token::PUNCTUATION_TYPE, '}')) { + if (!$first) { + $stream->expect(Token::PUNCTUATION_TYPE, ',', 'A hash value must be followed by a comma'); + + // trailing ,? + if ($stream->test(Token::PUNCTUATION_TYPE, '}')) { + break; + } + } + $first = false; + + // a hash key can be: + // + // * a number -- 12 + // * a string -- 'a' + // * a name, which is equivalent to a string -- a + // * an expression, which must be enclosed in parentheses -- (1 + 2) + if (($token = $stream->nextIf(Token::STRING_TYPE)) || ($token = $stream->nextIf(Token::NAME_TYPE)) || $token = $stream->nextIf(Token::NUMBER_TYPE)) { + $key = new ConstantExpression($token->getValue(), $token->getLine()); + } elseif ($stream->test(Token::PUNCTUATION_TYPE, '(')) { + $key = $this->parseExpression(); + } else { + $current = $stream->getCurrent(); + + throw new SyntaxError(sprintf('A hash key must be a quoted string, a number, a name, or an expression enclosed in parentheses (unexpected token "%s" of value "%s".', Token::typeToEnglish($current->getType()), $current->getValue()), $current->getLine(), $stream->getSourceContext()); + } + + $stream->expect(Token::PUNCTUATION_TYPE, ':', 'A hash key must be followed by a colon (:)'); + $value = $this->parseExpression(); + + $node->addElement($value, $key); + } + $stream->expect(Token::PUNCTUATION_TYPE, '}', 'An opened hash is not properly closed'); + + return $node; + } + + public function parsePostfixExpression($node) + { + while (true) { + $token = $this->parser->getCurrentToken(); + if (Token::PUNCTUATION_TYPE == $token->getType()) { + if ('.' == $token->getValue() || '[' == $token->getValue()) { + $node = $this->parseSubscriptExpression($node); + } elseif ('|' == $token->getValue()) { + $node = $this->parseFilterExpression($node); + } else { + break; + } + } else { + break; + } + } + + return $node; + } + + public function getFunctionNode($name, $line) + { + switch ($name) { + case 'parent': + $this->parseArguments(); + if (!\count($this->parser->getBlockStack())) { + throw new SyntaxError('Calling "parent" outside a block is forbidden.', $line, $this->parser->getStream()->getSourceContext()); + } + + if (!$this->parser->getParent() && !$this->parser->hasTraits()) { + throw new SyntaxError('Calling "parent" on a template that does not extend nor "use" another template is forbidden.', $line, $this->parser->getStream()->getSourceContext()); + } + + return new ParentExpression($this->parser->peekBlockStack(), $line); + case 'block': + $args = $this->parseArguments(); + if (\count($args) < 1) { + throw new SyntaxError('The "block" function takes one argument (the block name).', $line, $this->parser->getStream()->getSourceContext()); + } + + return new BlockReferenceExpression($args->getNode(0), \count($args) > 1 ? $args->getNode(1) : null, $line); + case 'attribute': + $args = $this->parseArguments(); + if (\count($args) < 2) { + throw new SyntaxError('The "attribute" function takes at least two arguments (the variable and the attributes).', $line, $this->parser->getStream()->getSourceContext()); + } + + return new GetAttrExpression($args->getNode(0), $args->getNode(1), \count($args) > 2 ? $args->getNode(2) : null, Template::ANY_CALL, $line); + default: + if (null !== $alias = $this->parser->getImportedSymbol('function', $name)) { + $arguments = new ArrayExpression([], $line); + foreach ($this->parseArguments() as $n) { + $arguments->addElement($n); + } + + $node = new MethodCallExpression($alias['node'], $alias['name'], $arguments, $line); + $node->setAttribute('safe', true); + + return $node; + } -if (\false) { - class ExpressionParser extends \Twig_ExpressionParser + $args = $this->parseArguments(true); + $class = $this->getFunctionNodeClass($name, $line); + + return new $class($name, $args, $line); + } + } + + public function parseSubscriptExpression($node) + { + $stream = $this->parser->getStream(); + $token = $stream->next(); + $lineno = $token->getLine(); + $arguments = new ArrayExpression([], $lineno); + $type = Template::ANY_CALL; + if ('.' == $token->getValue()) { + $token = $stream->next(); + if ( + Token::NAME_TYPE == $token->getType() + || + Token::NUMBER_TYPE == $token->getType() + || + (Token::OPERATOR_TYPE == $token->getType() && preg_match(Lexer::REGEX_NAME, $token->getValue())) + ) { + $arg = new ConstantExpression($token->getValue(), $lineno); + + if ($stream->test(Token::PUNCTUATION_TYPE, '(')) { + $type = Template::METHOD_CALL; + foreach ($this->parseArguments() as $n) { + $arguments->addElement($n); + } + } + } else { + throw new SyntaxError('Expected name or number.', $lineno, $stream->getSourceContext()); + } + + if ($node instanceof NameExpression && null !== $this->parser->getImportedSymbol('template', $node->getAttribute('name'))) { + if (!$arg instanceof ConstantExpression) { + throw new SyntaxError(sprintf('Dynamic macro names are not supported (called on "%s").', $node->getAttribute('name')), $token->getLine(), $stream->getSourceContext()); + } + + $name = $arg->getAttribute('value'); + + if ($this->parser->isReservedMacroName($name)) { + throw new SyntaxError(sprintf('"%s" cannot be called as macro as it is a reserved keyword.', $name), $token->getLine(), $stream->getSourceContext()); + } + + $node = new MethodCallExpression($node, 'get'.$name, $arguments, $lineno); + $node->setAttribute('safe', true); + + return $node; + } + } else { + $type = Template::ARRAY_CALL; + + // slice? + $slice = false; + if ($stream->test(Token::PUNCTUATION_TYPE, ':')) { + $slice = true; + $arg = new ConstantExpression(0, $token->getLine()); + } else { + $arg = $this->parseExpression(); + } + + if ($stream->nextIf(Token::PUNCTUATION_TYPE, ':')) { + $slice = true; + } + + if ($slice) { + if ($stream->test(Token::PUNCTUATION_TYPE, ']')) { + $length = new ConstantExpression(null, $token->getLine()); + } else { + $length = $this->parseExpression(); + } + + $class = $this->getFilterNodeClass('slice', $token->getLine()); + $arguments = new Node([$arg, $length]); + $filter = new $class($node, new ConstantExpression('slice', $token->getLine()), $arguments, $token->getLine()); + + $stream->expect(Token::PUNCTUATION_TYPE, ']'); + + return $filter; + } + + $stream->expect(Token::PUNCTUATION_TYPE, ']'); + } + + return new GetAttrExpression($node, $arg, $arguments, $type, $lineno); + } + + public function parseFilterExpression($node) + { + $this->parser->getStream()->next(); + + return $this->parseFilterExpressionRaw($node); + } + + public function parseFilterExpressionRaw($node, $tag = null) + { + while (true) { + $token = $this->parser->getStream()->expect(Token::NAME_TYPE); + + $name = new ConstantExpression($token->getValue(), $token->getLine()); + if (!$this->parser->getStream()->test(Token::PUNCTUATION_TYPE, '(')) { + $arguments = new Node(); + } else { + $arguments = $this->parseArguments(true, false, true); + } + + $class = $this->getFilterNodeClass($name->getAttribute('value'), $token->getLine()); + + $node = new $class($node, $name, $arguments, $token->getLine(), $tag); + + if (!$this->parser->getStream()->test(Token::PUNCTUATION_TYPE, '|')) { + break; + } + + $this->parser->getStream()->next(); + } + + return $node; + } + + /** + * Parses arguments. + * + * @param bool $namedArguments Whether to allow named arguments or not + * @param bool $definition Whether we are parsing arguments for a function definition + * + * @return Node + * + * @throws SyntaxError + */ + public function parseArguments($namedArguments = false, $definition = false, $allowArrow = false) + { + $args = []; + $stream = $this->parser->getStream(); + + $stream->expect(Token::PUNCTUATION_TYPE, '(', 'A list of arguments must begin with an opening parenthesis'); + while (!$stream->test(Token::PUNCTUATION_TYPE, ')')) { + if (!empty($args)) { + $stream->expect(Token::PUNCTUATION_TYPE, ',', 'Arguments must be separated by a comma'); + } + + if ($definition) { + $token = $stream->expect(Token::NAME_TYPE, null, 'An argument must be a name'); + $value = new NameExpression($token->getValue(), $this->parser->getCurrentToken()->getLine()); + } else { + $value = $this->parseExpression(0, $allowArrow); + } + + $name = null; + if ($namedArguments && $token = $stream->nextIf(Token::OPERATOR_TYPE, '=')) { + if (!$value instanceof NameExpression) { + throw new SyntaxError(sprintf('A parameter name must be a string, "%s" given.', \get_class($value)), $token->getLine(), $stream->getSourceContext()); + } + $name = $value->getAttribute('name'); + + if ($definition) { + $value = $this->parsePrimaryExpression(); + + if (!$this->checkConstantExpression($value)) { + throw new SyntaxError(sprintf('A default value for an argument must be a constant (a boolean, a string, a number, or an array).'), $token->getLine(), $stream->getSourceContext()); + } + } else { + $value = $this->parseExpression(0, $allowArrow); + } + } + + if ($definition) { + if (null === $name) { + $name = $value->getAttribute('name'); + $value = new ConstantExpression(null, $this->parser->getCurrentToken()->getLine()); + } + $args[$name] = $value; + } else { + if (null === $name) { + $args[] = $value; + } else { + $args[$name] = $value; + } + } + } + $stream->expect(Token::PUNCTUATION_TYPE, ')', 'A list of arguments must be closed by a parenthesis'); + + return new Node($args); + } + + public function parseAssignmentExpression() + { + $stream = $this->parser->getStream(); + $targets = []; + while (true) { + $token = $this->parser->getCurrentToken(); + if ($stream->test(Token::OPERATOR_TYPE) && preg_match(Lexer::REGEX_NAME, $token->getValue())) { + // in this context, string operators are variable names + $this->parser->getStream()->next(); + } else { + $stream->expect(Token::NAME_TYPE, null, 'Only variables can be assigned to'); + } + $value = $token->getValue(); + if (\in_array(strtolower($value), ['true', 'false', 'none', 'null'])) { + throw new SyntaxError(sprintf('You cannot assign a value to "%s".', $value), $token->getLine(), $stream->getSourceContext()); + } + $targets[] = new AssignNameExpression($value, $token->getLine()); + + if (!$stream->nextIf(Token::PUNCTUATION_TYPE, ',')) { + break; + } + } + + return new Node($targets); + } + + public function parseMultitargetExpression() + { + $targets = []; + while (true) { + $targets[] = $this->parseExpression(); + if (!$this->parser->getStream()->nextIf(Token::PUNCTUATION_TYPE, ',')) { + break; + } + } + + return new Node($targets); + } + + private function parseNotTestExpression(\Twig_NodeInterface $node) + { + return new NotUnary($this->parseTestExpression($node), $this->parser->getCurrentToken()->getLine()); + } + + private function parseTestExpression(\Twig_NodeInterface $node) + { + $stream = $this->parser->getStream(); + list($name, $test) = $this->getTest($node->getTemplateLine()); + + $class = $this->getTestNodeClass($test); + $arguments = null; + if ($stream->test(Token::PUNCTUATION_TYPE, '(')) { + $arguments = $this->parseArguments(true); + } + + return new $class($node, $name, $arguments, $this->parser->getCurrentToken()->getLine()); + } + + private function getTest($line) { + $stream = $this->parser->getStream(); + $name = $stream->expect(Token::NAME_TYPE)->getValue(); + + if ($test = $this->env->getTest($name)) { + return [$name, $test]; + } + + if ($stream->test(Token::NAME_TYPE)) { + // try 2-words tests + $name = $name.' '.$this->parser->getCurrentToken()->getValue(); + + if ($test = $this->env->getTest($name)) { + $stream->next(); + + return [$name, $test]; + } + } + + $e = new SyntaxError(sprintf('Unknown "%s" test.', $name), $line, $stream->getSourceContext()); + $e->addSuggestions($name, array_keys($this->env->getTests())); + + throw $e; + } + + private function getTestNodeClass($test) + { + if ($test instanceof TwigTest && $test->isDeprecated()) { + $stream = $this->parser->getStream(); + $message = sprintf('Twig Test "%s" is deprecated', $test->getName()); + if (!\is_bool($test->getDeprecatedVersion())) { + $message .= sprintf(' since version %s', $test->getDeprecatedVersion()); + } + if ($test->getAlternative()) { + $message .= sprintf('. Use "%s" instead', $test->getAlternative()); + } + $src = $stream->getSourceContext(); + $message .= sprintf(' in %s at line %d.', $src->getPath() ? $src->getPath() : $src->getName(), $stream->getCurrent()->getLine()); + + @trigger_error($message, E_USER_DEPRECATED); + } + + if ($test instanceof TwigTest) { + return $test->getNodeClass(); + } + + return $test instanceof \Twig_Test_Node ? $test->getClass() : 'Twig\Node\Expression\TestExpression'; + } + + protected function getFunctionNodeClass($name, $line) + { + if (false === $function = $this->env->getFunction($name)) { + $e = new SyntaxError(sprintf('Unknown "%s" function.', $name), $line, $this->parser->getStream()->getSourceContext()); + $e->addSuggestions($name, array_keys($this->env->getFunctions())); + + throw $e; + } + + if ($function instanceof TwigFunction && $function->isDeprecated()) { + $message = sprintf('Twig Function "%s" is deprecated', $function->getName()); + if (!\is_bool($function->getDeprecatedVersion())) { + $message .= sprintf(' since version %s', $function->getDeprecatedVersion()); + } + if ($function->getAlternative()) { + $message .= sprintf('. Use "%s" instead', $function->getAlternative()); + } + $src = $this->parser->getStream()->getSourceContext(); + $message .= sprintf(' in %s at line %d.', $src->getPath() ? $src->getPath() : $src->getName(), $line); + + @trigger_error($message, E_USER_DEPRECATED); + } + + if ($function instanceof TwigFunction) { + return $function->getNodeClass(); + } + + return $function instanceof \Twig_Function_Node ? $function->getClass() : 'Twig\Node\Expression\FunctionExpression'; + } + + protected function getFilterNodeClass($name, $line) + { + if (false === $filter = $this->env->getFilter($name)) { + $e = new SyntaxError(sprintf('Unknown "%s" filter.', $name), $line, $this->parser->getStream()->getSourceContext()); + $e->addSuggestions($name, array_keys($this->env->getFilters())); + + throw $e; + } + + if ($filter instanceof TwigFilter && $filter->isDeprecated()) { + $message = sprintf('Twig Filter "%s" is deprecated', $filter->getName()); + if (!\is_bool($filter->getDeprecatedVersion())) { + $message .= sprintf(' since version %s', $filter->getDeprecatedVersion()); + } + if ($filter->getAlternative()) { + $message .= sprintf('. Use "%s" instead', $filter->getAlternative()); + } + $src = $this->parser->getStream()->getSourceContext(); + $message .= sprintf(' in %s at line %d.', $src->getPath() ? $src->getPath() : $src->getName(), $line); + + @trigger_error($message, E_USER_DEPRECATED); + } + + if ($filter instanceof TwigFilter) { + return $filter->getNodeClass(); + } + + return $filter instanceof \Twig_Filter_Node ? $filter->getClass() : 'Twig\Node\Expression\FilterExpression'; + } + + // checks that the node only contains "constant" elements + protected function checkConstantExpression(\Twig_NodeInterface $node) + { + if (!($node instanceof ConstantExpression || $node instanceof ArrayExpression + || $node instanceof NegUnary || $node instanceof PosUnary + )) { + return false; + } + + foreach ($node as $n) { + if (!$this->checkConstantExpression($n)) { + return false; + } + } + + return true; } } + +class_alias('Twig\ExpressionParser', 'Twig_ExpressionParser'); diff --git a/vendor/twig/twig/src/Extension/AbstractExtension.php b/vendor/twig/twig/src/Extension/AbstractExtension.php index 8fc965c463a5dd54c1170ae76100193c458b80f1..fa3245b2984c4d6411bbd5e393801795fcee7a8a 100644 --- a/vendor/twig/twig/src/Extension/AbstractExtension.php +++ b/vendor/twig/twig/src/Extension/AbstractExtension.php @@ -1,11 +1,72 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\Extension; -class_exists('Twig_Extension'); +use Twig\Environment; + +abstract class AbstractExtension implements ExtensionInterface +{ + /** + * @deprecated since 1.23 (to be removed in 2.0), implement \Twig_Extension_InitRuntimeInterface instead + */ + public function initRuntime(Environment $environment) + { + } + + public function getTokenParsers() + { + return []; + } + + public function getNodeVisitors() + { + return []; + } + + public function getFilters() + { + return []; + } + + public function getTests() + { + return []; + } -if (\false) { - class AbstractExtension extends \Twig_Extension + public function getFunctions() { + return []; + } + + public function getOperators() + { + return []; + } + + /** + * @deprecated since 1.23 (to be removed in 2.0), implement \Twig_Extension_GlobalsInterface instead + */ + public function getGlobals() + { + return []; + } + + /** + * @deprecated since 1.26 (to be removed in 2.0), not used anymore internally + */ + public function getName() + { + return \get_class($this); } } + +class_alias('Twig\Extension\AbstractExtension', 'Twig_Extension'); diff --git a/vendor/twig/twig/src/Extension/CoreExtension.php b/vendor/twig/twig/src/Extension/CoreExtension.php index 6f66a44dd44e7971f35dfb6bae4161eae7f94fd9..5f3cc24a1954b15bfeec95f8b585117a2ff39cc2 100644 --- a/vendor/twig/twig/src/Extension/CoreExtension.php +++ b/vendor/twig/twig/src/Extension/CoreExtension.php @@ -1,11 +1,1728 @@ <?php -namespace Twig\Extension; +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ -class_exists('Twig_Extension_Core'); +namespace Twig\Extension { +use Twig\ExpressionParser; +use Twig\TokenParser\ApplyTokenParser; +use Twig\TokenParser\BlockTokenParser; +use Twig\TokenParser\DeprecatedTokenParser; +use Twig\TokenParser\DoTokenParser; +use Twig\TokenParser\EmbedTokenParser; +use Twig\TokenParser\ExtendsTokenParser; +use Twig\TokenParser\FilterTokenParser; +use Twig\TokenParser\FlushTokenParser; +use Twig\TokenParser\ForTokenParser; +use Twig\TokenParser\FromTokenParser; +use Twig\TokenParser\IfTokenParser; +use Twig\TokenParser\ImportTokenParser; +use Twig\TokenParser\IncludeTokenParser; +use Twig\TokenParser\MacroTokenParser; +use Twig\TokenParser\SetTokenParser; +use Twig\TokenParser\SpacelessTokenParser; +use Twig\TokenParser\UseTokenParser; +use Twig\TokenParser\WithTokenParser; +use Twig\TwigFilter; +use Twig\TwigFunction; +use Twig\TwigTest; -if (\false) { - class CoreExtension extends \Twig_Extension_Core +/** + * @final + */ +class CoreExtension extends AbstractExtension +{ + protected $dateFormats = ['F j, Y H:i', '%d days']; + protected $numberFormat = [0, '.', ',']; + protected $timezone = null; + protected $escapers = []; + + /** + * Defines a new escaper to be used via the escape filter. + * + * @param string $strategy The strategy name that should be used as a strategy in the escape call + * @param callable $callable A valid PHP callable + */ + public function setEscaper($strategy, $callable) + { + $this->escapers[$strategy] = $callable; + } + + /** + * Gets all defined escapers. + * + * @return array An array of escapers + */ + public function getEscapers() + { + return $this->escapers; + } + + /** + * Sets the default format to be used by the date filter. + * + * @param string $format The default date format string + * @param string $dateIntervalFormat The default date interval format string + */ + public function setDateFormat($format = null, $dateIntervalFormat = null) + { + if (null !== $format) { + $this->dateFormats[0] = $format; + } + + if (null !== $dateIntervalFormat) { + $this->dateFormats[1] = $dateIntervalFormat; + } + } + + /** + * Gets the default format to be used by the date filter. + * + * @return array The default date format string and the default date interval format string + */ + public function getDateFormat() + { + return $this->dateFormats; + } + + /** + * Sets the default timezone to be used by the date filter. + * + * @param \DateTimeZone|string $timezone The default timezone string or a \DateTimeZone object + */ + public function setTimezone($timezone) + { + $this->timezone = $timezone instanceof \DateTimeZone ? $timezone : new \DateTimeZone($timezone); + } + + /** + * Gets the default timezone to be used by the date filter. + * + * @return \DateTimeZone The default timezone currently in use + */ + public function getTimezone() + { + if (null === $this->timezone) { + $this->timezone = new \DateTimeZone(date_default_timezone_get()); + } + + return $this->timezone; + } + + /** + * Sets the default format to be used by the number_format filter. + * + * @param int $decimal the number of decimal places to use + * @param string $decimalPoint the character(s) to use for the decimal point + * @param string $thousandSep the character(s) to use for the thousands separator + */ + public function setNumberFormat($decimal, $decimalPoint, $thousandSep) + { + $this->numberFormat = [$decimal, $decimalPoint, $thousandSep]; + } + + /** + * Get the default format used by the number_format filter. + * + * @return array The arguments for number_format() + */ + public function getNumberFormat() + { + return $this->numberFormat; + } + + public function getTokenParsers() + { + return [ + new ApplyTokenParser(), + new ForTokenParser(), + new IfTokenParser(), + new ExtendsTokenParser(), + new IncludeTokenParser(), + new BlockTokenParser(), + new UseTokenParser(), + new FilterTokenParser(), + new MacroTokenParser(), + new ImportTokenParser(), + new FromTokenParser(), + new SetTokenParser(), + new SpacelessTokenParser(), + new FlushTokenParser(), + new DoTokenParser(), + new EmbedTokenParser(), + new WithTokenParser(), + new DeprecatedTokenParser(), + ]; + } + + public function getFilters() + { + $filters = [ + // formatting filters + new TwigFilter('date', 'twig_date_format_filter', ['needs_environment' => true]), + new TwigFilter('date_modify', 'twig_date_modify_filter', ['needs_environment' => true]), + new TwigFilter('format', 'sprintf'), + new TwigFilter('replace', 'twig_replace_filter'), + new TwigFilter('number_format', 'twig_number_format_filter', ['needs_environment' => true]), + new TwigFilter('abs', 'abs'), + new TwigFilter('round', 'twig_round'), + + // encoding + new TwigFilter('url_encode', 'twig_urlencode_filter'), + new TwigFilter('json_encode', 'twig_jsonencode_filter'), + new TwigFilter('convert_encoding', 'twig_convert_encoding'), + + // string filters + new TwigFilter('title', 'twig_title_string_filter', ['needs_environment' => true]), + new TwigFilter('capitalize', 'twig_capitalize_string_filter', ['needs_environment' => true]), + new TwigFilter('upper', 'strtoupper'), + new TwigFilter('lower', 'strtolower'), + new TwigFilter('striptags', 'strip_tags'), + new TwigFilter('trim', 'twig_trim_filter'), + new TwigFilter('nl2br', 'nl2br', ['pre_escape' => 'html', 'is_safe' => ['html']]), + new TwigFilter('spaceless', 'twig_spaceless', ['is_safe' => ['html']]), + + // array helpers + new TwigFilter('join', 'twig_join_filter'), + new TwigFilter('split', 'twig_split_filter', ['needs_environment' => true]), + new TwigFilter('sort', 'twig_sort_filter'), + new TwigFilter('merge', 'twig_array_merge'), + new TwigFilter('batch', 'twig_array_batch'), + new TwigFilter('filter', 'twig_array_filter'), + new TwigFilter('map', 'twig_array_map'), + new TwigFilter('reduce', 'twig_array_reduce'), + + // string/array filters + new TwigFilter('reverse', 'twig_reverse_filter', ['needs_environment' => true]), + new TwigFilter('length', 'twig_length_filter', ['needs_environment' => true]), + new TwigFilter('slice', 'twig_slice', ['needs_environment' => true]), + new TwigFilter('first', 'twig_first', ['needs_environment' => true]), + new TwigFilter('last', 'twig_last', ['needs_environment' => true]), + + // iteration and runtime + new TwigFilter('default', '_twig_default_filter', ['node_class' => '\Twig\Node\Expression\Filter\DefaultFilter']), + new TwigFilter('keys', 'twig_get_array_keys_filter'), + + // escaping + new TwigFilter('escape', 'twig_escape_filter', ['needs_environment' => true, 'is_safe_callback' => 'twig_escape_filter_is_safe']), + new TwigFilter('e', 'twig_escape_filter', ['needs_environment' => true, 'is_safe_callback' => 'twig_escape_filter_is_safe']), + ]; + + if (\function_exists('mb_get_info')) { + $filters[] = new TwigFilter('upper', 'twig_upper_filter', ['needs_environment' => true]); + $filters[] = new TwigFilter('lower', 'twig_lower_filter', ['needs_environment' => true]); + } + + return $filters; + } + + public function getFunctions() { + return [ + new TwigFunction('max', 'max'), + new TwigFunction('min', 'min'), + new TwigFunction('range', 'range'), + new TwigFunction('constant', 'twig_constant'), + new TwigFunction('cycle', 'twig_cycle'), + new TwigFunction('random', 'twig_random', ['needs_environment' => true]), + new TwigFunction('date', 'twig_date_converter', ['needs_environment' => true]), + new TwigFunction('include', 'twig_include', ['needs_environment' => true, 'needs_context' => true, 'is_safe' => ['all']]), + new TwigFunction('source', 'twig_source', ['needs_environment' => true, 'is_safe' => ['all']]), + ]; + } + + public function getTests() + { + return [ + new TwigTest('even', null, ['node_class' => '\Twig\Node\Expression\Test\EvenTest']), + new TwigTest('odd', null, ['node_class' => '\Twig\Node\Expression\Test\OddTest']), + new TwigTest('defined', null, ['node_class' => '\Twig\Node\Expression\Test\DefinedTest']), + new TwigTest('sameas', null, ['node_class' => '\Twig\Node\Expression\Test\SameasTest', 'deprecated' => '1.21', 'alternative' => 'same as']), + new TwigTest('same as', null, ['node_class' => '\Twig\Node\Expression\Test\SameasTest']), + new TwigTest('none', null, ['node_class' => '\Twig\Node\Expression\Test\NullTest']), + new TwigTest('null', null, ['node_class' => '\Twig\Node\Expression\Test\NullTest']), + new TwigTest('divisibleby', null, ['node_class' => '\Twig\Node\Expression\Test\DivisiblebyTest', 'deprecated' => '1.21', 'alternative' => 'divisible by']), + new TwigTest('divisible by', null, ['node_class' => '\Twig\Node\Expression\Test\DivisiblebyTest']), + new TwigTest('constant', null, ['node_class' => '\Twig\Node\Expression\Test\ConstantTest']), + new TwigTest('empty', 'twig_test_empty'), + new TwigTest('iterable', 'twig_test_iterable'), + ]; + } + + public function getOperators() + { + return [ + [ + 'not' => ['precedence' => 50, 'class' => '\Twig\Node\Expression\Unary\NotUnary'], + '-' => ['precedence' => 500, 'class' => '\Twig\Node\Expression\Unary\NegUnary'], + '+' => ['precedence' => 500, 'class' => '\Twig\Node\Expression\Unary\PosUnary'], + ], + [ + 'or' => ['precedence' => 10, 'class' => '\Twig\Node\Expression\Binary\OrBinary', 'associativity' => ExpressionParser::OPERATOR_LEFT], + 'and' => ['precedence' => 15, 'class' => '\Twig\Node\Expression\Binary\AndBinary', 'associativity' => ExpressionParser::OPERATOR_LEFT], + 'b-or' => ['precedence' => 16, 'class' => '\Twig\Node\Expression\Binary\BitwiseOrBinary', 'associativity' => ExpressionParser::OPERATOR_LEFT], + 'b-xor' => ['precedence' => 17, 'class' => '\Twig\Node\Expression\Binary\BitwiseXorBinary', 'associativity' => ExpressionParser::OPERATOR_LEFT], + 'b-and' => ['precedence' => 18, 'class' => '\Twig\Node\Expression\Binary\BitwiseAndBinary', 'associativity' => ExpressionParser::OPERATOR_LEFT], + '==' => ['precedence' => 20, 'class' => '\Twig\Node\Expression\Binary\EqualBinary', 'associativity' => ExpressionParser::OPERATOR_LEFT], + '!=' => ['precedence' => 20, 'class' => '\Twig\Node\Expression\Binary\NotEqualBinary', 'associativity' => ExpressionParser::OPERATOR_LEFT], + '<' => ['precedence' => 20, 'class' => '\Twig\Node\Expression\Binary\LessBinary', 'associativity' => ExpressionParser::OPERATOR_LEFT], + '>' => ['precedence' => 20, 'class' => '\Twig\Node\Expression\Binary\GreaterBinary', 'associativity' => ExpressionParser::OPERATOR_LEFT], + '>=' => ['precedence' => 20, 'class' => '\Twig\Node\Expression\Binary\GreaterEqualBinary', 'associativity' => ExpressionParser::OPERATOR_LEFT], + '<=' => ['precedence' => 20, 'class' => '\Twig\Node\Expression\Binary\LessEqualBinary', 'associativity' => ExpressionParser::OPERATOR_LEFT], + 'not in' => ['precedence' => 20, 'class' => '\Twig\Node\Expression\Binary\NotInBinary', 'associativity' => ExpressionParser::OPERATOR_LEFT], + 'in' => ['precedence' => 20, 'class' => '\Twig\Node\Expression\Binary\InBinary', 'associativity' => ExpressionParser::OPERATOR_LEFT], + 'matches' => ['precedence' => 20, 'class' => '\Twig\Node\Expression\Binary\MatchesBinary', 'associativity' => ExpressionParser::OPERATOR_LEFT], + 'starts with' => ['precedence' => 20, 'class' => '\Twig\Node\Expression\Binary\StartsWithBinary', 'associativity' => ExpressionParser::OPERATOR_LEFT], + 'ends with' => ['precedence' => 20, 'class' => '\Twig\Node\Expression\Binary\EndsWithBinary', 'associativity' => ExpressionParser::OPERATOR_LEFT], + '..' => ['precedence' => 25, 'class' => '\Twig\Node\Expression\Binary\RangeBinary', 'associativity' => ExpressionParser::OPERATOR_LEFT], + '+' => ['precedence' => 30, 'class' => '\Twig\Node\Expression\Binary\AddBinary', 'associativity' => ExpressionParser::OPERATOR_LEFT], + '-' => ['precedence' => 30, 'class' => '\Twig\Node\Expression\Binary\SubBinary', 'associativity' => ExpressionParser::OPERATOR_LEFT], + '~' => ['precedence' => 40, 'class' => '\Twig\Node\Expression\Binary\ConcatBinary', 'associativity' => ExpressionParser::OPERATOR_LEFT], + '*' => ['precedence' => 60, 'class' => '\Twig\Node\Expression\Binary\MulBinary', 'associativity' => ExpressionParser::OPERATOR_LEFT], + '/' => ['precedence' => 60, 'class' => '\Twig\Node\Expression\Binary\DivBinary', 'associativity' => ExpressionParser::OPERATOR_LEFT], + '//' => ['precedence' => 60, 'class' => '\Twig\Node\Expression\Binary\FloorDivBinary', 'associativity' => ExpressionParser::OPERATOR_LEFT], + '%' => ['precedence' => 60, 'class' => '\Twig\Node\Expression\Binary\ModBinary', 'associativity' => ExpressionParser::OPERATOR_LEFT], + 'is' => ['precedence' => 100, 'associativity' => ExpressionParser::OPERATOR_LEFT], + 'is not' => ['precedence' => 100, 'associativity' => ExpressionParser::OPERATOR_LEFT], + '**' => ['precedence' => 200, 'class' => '\Twig\Node\Expression\Binary\PowerBinary', 'associativity' => ExpressionParser::OPERATOR_RIGHT], + '??' => ['precedence' => 300, 'class' => '\Twig\Node\Expression\NullCoalesceExpression', 'associativity' => ExpressionParser::OPERATOR_RIGHT], + ], + ]; + } + + public function getName() + { + return 'core'; + } +} + +class_alias('Twig\Extension\CoreExtension', 'Twig_Extension_Core'); +} + +namespace { +use Twig\Environment; +use Twig\Error\LoaderError; +use Twig\Error\RuntimeError; +use Twig\Loader\SourceContextLoaderInterface; +use Twig\Markup; +use Twig\Node\Expression\ConstantExpression; +use Twig\Node\Node; + +/** + * Cycles over a value. + * + * @param \ArrayAccess|array $values + * @param int $position The cycle position + * + * @return string The next value in the cycle + */ +function twig_cycle($values, $position) +{ + if (!\is_array($values) && !$values instanceof \ArrayAccess) { + return $values; + } + + return $values[$position % \count($values)]; +} + +/** + * Returns a random value depending on the supplied parameter type: + * - a random item from a \Traversable or array + * - a random character from a string + * - a random integer between 0 and the integer parameter. + * + * @param \Traversable|array|int|float|string $values The values to pick a random item from + * @param int|null $max Maximum value used when $values is an int + * + * @throws RuntimeError when $values is an empty array (does not apply to an empty string which is returned as is) + * + * @return mixed A random value from the given sequence + */ +function twig_random(Environment $env, $values = null, $max = null) +{ + if (null === $values) { + return null === $max ? mt_rand() : mt_rand(0, $max); + } + + if (\is_int($values) || \is_float($values)) { + if (null === $max) { + if ($values < 0) { + $max = 0; + $min = $values; + } else { + $max = $values; + $min = 0; + } + } else { + $min = $values; + $max = $max; + } + + return mt_rand($min, $max); + } + + if (\is_string($values)) { + if ('' === $values) { + return ''; + } + if (null !== $charset = $env->getCharset()) { + if ('UTF-8' !== $charset) { + $values = twig_convert_encoding($values, 'UTF-8', $charset); + } + + // unicode version of str_split() + // split at all positions, but not after the start and not before the end + $values = preg_split('/(?<!^)(?!$)/u', $values); + + if ('UTF-8' !== $charset) { + foreach ($values as $i => $value) { + $values[$i] = twig_convert_encoding($value, $charset, 'UTF-8'); + } + } + } else { + return $values[mt_rand(0, \strlen($values) - 1)]; + } + } + + if (!twig_test_iterable($values)) { + return $values; + } + + $values = twig_to_array($values); + + if (0 === \count($values)) { + throw new RuntimeError('The random function cannot pick from an empty array.'); + } + + return $values[array_rand($values, 1)]; +} + +/** + * Converts a date to the given format. + * + * {{ post.published_at|date("m/d/Y") }} + * + * @param \DateTime|\DateTimeInterface|\DateInterval|string $date A date + * @param string|null $format The target format, null to use the default + * @param \DateTimeZone|string|false|null $timezone The target timezone, null to use the default, false to leave unchanged + * + * @return string The formatted date + */ +function twig_date_format_filter(Environment $env, $date, $format = null, $timezone = null) +{ + if (null === $format) { + $formats = $env->getExtension('\Twig\Extension\CoreExtension')->getDateFormat(); + $format = $date instanceof \DateInterval ? $formats[1] : $formats[0]; + } + + if ($date instanceof \DateInterval) { + return $date->format($format); + } + + return twig_date_converter($env, $date, $timezone)->format($format); +} + +/** + * Returns a new date object modified. + * + * {{ post.published_at|date_modify("-1day")|date("m/d/Y") }} + * + * @param \DateTime|string $date A date + * @param string $modifier A modifier string + * + * @return \DateTime + */ +function twig_date_modify_filter(Environment $env, $date, $modifier) +{ + $date = twig_date_converter($env, $date, false); + $resultDate = $date->modify($modifier); + + // This is a hack to ensure PHP 5.2 support and support for \DateTimeImmutable + // \DateTime::modify does not return the modified \DateTime object < 5.3.0 + // and \DateTimeImmutable does not modify $date. + return null === $resultDate ? $date : $resultDate; +} + +/** + * Converts an input to a \DateTime instance. + * + * {% if date(user.created_at) < date('+2days') %} + * {# do something #} + * {% endif %} + * + * @param \DateTime|\DateTimeInterface|string|null $date A date + * @param \DateTimeZone|string|false|null $timezone The target timezone, null to use the default, false to leave unchanged + * + * @return \DateTime + */ +function twig_date_converter(Environment $env, $date = null, $timezone = null) +{ + // determine the timezone + if (false !== $timezone) { + if (null === $timezone) { + $timezone = $env->getExtension('\Twig\Extension\CoreExtension')->getTimezone(); + } elseif (!$timezone instanceof \DateTimeZone) { + $timezone = new \DateTimeZone($timezone); + } + } + + // immutable dates + if ($date instanceof \DateTimeImmutable) { + return false !== $timezone ? $date->setTimezone($timezone) : $date; + } + + if ($date instanceof \DateTime || $date instanceof \DateTimeInterface) { + $date = clone $date; + if (false !== $timezone) { + $date->setTimezone($timezone); + } + + return $date; + } + + if (null === $date || 'now' === $date) { + return new \DateTime($date, false !== $timezone ? $timezone : $env->getExtension('\Twig\Extension\CoreExtension')->getTimezone()); + } + + $asString = (string) $date; + if (ctype_digit($asString) || (!empty($asString) && '-' === $asString[0] && ctype_digit(substr($asString, 1)))) { + $date = new \DateTime('@'.$date); + } else { + $date = new \DateTime($date, $env->getExtension('\Twig\Extension\CoreExtension')->getTimezone()); + } + + if (false !== $timezone) { + $date->setTimezone($timezone); + } + + return $date; +} + +/** + * Replaces strings within a string. + * + * @param string $str String to replace in + * @param array|\Traversable $from Replace values + * @param string|null $to Replace to, deprecated (@see https://secure.php.net/manual/en/function.strtr.php) + * + * @return string + */ +function twig_replace_filter($str, $from, $to = null) +{ + if (\is_string($from) && \is_string($to)) { + @trigger_error('Using "replace" with character by character replacement is deprecated since version 1.22 and will be removed in Twig 2.0', E_USER_DEPRECATED); + + return strtr($str, $from, $to); + } + + if (!twig_test_iterable($from)) { + throw new RuntimeError(sprintf('The "replace" filter expects an array or "Traversable" as replace values, got "%s".', \is_object($from) ? \get_class($from) : \gettype($from))); + } + + return strtr($str, twig_to_array($from)); +} + +/** + * Rounds a number. + * + * @param int|float $value The value to round + * @param int|float $precision The rounding precision + * @param string $method The method to use for rounding + * + * @return int|float The rounded number + */ +function twig_round($value, $precision = 0, $method = 'common') +{ + if ('common' == $method) { + return round($value, $precision); + } + + if ('ceil' != $method && 'floor' != $method) { + throw new RuntimeError('The round filter only supports the "common", "ceil", and "floor" methods.'); + } + + return $method($value * pow(10, $precision)) / pow(10, $precision); +} + +/** + * Number format filter. + * + * All of the formatting options can be left null, in that case the defaults will + * be used. Supplying any of the parameters will override the defaults set in the + * environment object. + * + * @param mixed $number A float/int/string of the number to format + * @param int $decimal the number of decimal points to display + * @param string $decimalPoint the character(s) to use for the decimal point + * @param string $thousandSep the character(s) to use for the thousands separator + * + * @return string The formatted number + */ +function twig_number_format_filter(Environment $env, $number, $decimal = null, $decimalPoint = null, $thousandSep = null) +{ + $defaults = $env->getExtension('\Twig\Extension\CoreExtension')->getNumberFormat(); + if (null === $decimal) { + $decimal = $defaults[0]; + } + + if (null === $decimalPoint) { + $decimalPoint = $defaults[1]; + } + + if (null === $thousandSep) { + $thousandSep = $defaults[2]; + } + + return number_format((float) $number, $decimal, $decimalPoint, $thousandSep); +} + +/** + * URL encodes (RFC 3986) a string as a path segment or an array as a query string. + * + * @param string|array $url A URL or an array of query parameters + * + * @return string The URL encoded value + */ +function twig_urlencode_filter($url) +{ + if (\is_array($url)) { + if (\defined('PHP_QUERY_RFC3986')) { + return http_build_query($url, '', '&', PHP_QUERY_RFC3986); + } + + return http_build_query($url, '', '&'); + } + + return rawurlencode($url); +} + +/** + * JSON encodes a variable. + * + * @param mixed $value the value to encode + * @param int $options Bitmask consisting of JSON_HEX_QUOT, JSON_HEX_TAG, JSON_HEX_AMP, JSON_HEX_APOS, JSON_NUMERIC_CHECK, JSON_PRETTY_PRINT, JSON_UNESCAPED_SLASHES, JSON_FORCE_OBJECT + * + * @return mixed The JSON encoded value + */ +function twig_jsonencode_filter($value, $options = 0) +{ + if ($value instanceof Markup) { + $value = (string) $value; + } elseif (\is_array($value)) { + array_walk_recursive($value, '_twig_markup2string'); + } + + return json_encode($value, $options); +} + +function _twig_markup2string(&$value) +{ + if ($value instanceof Markup) { + $value = (string) $value; + } +} + +/** + * Merges an array with another one. + * + * {% set items = { 'apple': 'fruit', 'orange': 'fruit' } %} + * + * {% set items = items|merge({ 'peugeot': 'car' }) %} + * + * {# items now contains { 'apple': 'fruit', 'orange': 'fruit', 'peugeot': 'car' } #} + * + * @param array|\Traversable $arr1 An array + * @param array|\Traversable $arr2 An array + * + * @return array The merged array + */ +function twig_array_merge($arr1, $arr2) +{ + if (!twig_test_iterable($arr1)) { + throw new RuntimeError(sprintf('The merge filter only works with arrays or "Traversable", got "%s" as first argument.', \gettype($arr1))); + } + + if (!twig_test_iterable($arr2)) { + throw new RuntimeError(sprintf('The merge filter only works with arrays or "Traversable", got "%s" as second argument.', \gettype($arr2))); + } + + return array_merge(twig_to_array($arr1), twig_to_array($arr2)); +} + +/** + * Slices a variable. + * + * @param mixed $item A variable + * @param int $start Start of the slice + * @param int $length Size of the slice + * @param bool $preserveKeys Whether to preserve key or not (when the input is an array) + * + * @return mixed The sliced variable + */ +function twig_slice(Environment $env, $item, $start, $length = null, $preserveKeys = false) +{ + if ($item instanceof \Traversable) { + while ($item instanceof \IteratorAggregate) { + $item = $item->getIterator(); + } + + if ($start >= 0 && $length >= 0 && $item instanceof \Iterator) { + try { + return iterator_to_array(new \LimitIterator($item, $start, null === $length ? -1 : $length), $preserveKeys); + } catch (\OutOfBoundsException $e) { + return []; + } + } + + $item = iterator_to_array($item, $preserveKeys); + } + + if (\is_array($item)) { + return \array_slice($item, $start, $length, $preserveKeys); + } + + $item = (string) $item; + + if (\function_exists('mb_get_info') && null !== $charset = $env->getCharset()) { + return (string) mb_substr($item, $start, null === $length ? mb_strlen($item, $charset) - $start : $length, $charset); + } + + return (string) (null === $length ? substr($item, $start) : substr($item, $start, $length)); +} + +/** + * Returns the first element of the item. + * + * @param mixed $item A variable + * + * @return mixed The first element of the item + */ +function twig_first(Environment $env, $item) +{ + $elements = twig_slice($env, $item, 0, 1, false); + + return \is_string($elements) ? $elements : current($elements); +} + +/** + * Returns the last element of the item. + * + * @param mixed $item A variable + * + * @return mixed The last element of the item + */ +function twig_last(Environment $env, $item) +{ + $elements = twig_slice($env, $item, -1, 1, false); + + return \is_string($elements) ? $elements : current($elements); +} + +/** + * Joins the values to a string. + * + * The separators between elements are empty strings per default, you can define them with the optional parameters. + * + * {{ [1, 2, 3]|join(', ', ' and ') }} + * {# returns 1, 2 and 3 #} + * + * {{ [1, 2, 3]|join('|') }} + * {# returns 1|2|3 #} + * + * {{ [1, 2, 3]|join }} + * {# returns 123 #} + * + * @param array $value An array + * @param string $glue The separator + * @param string|null $and The separator for the last pair + * + * @return string The concatenated string + */ +function twig_join_filter($value, $glue = '', $and = null) +{ + if (!twig_test_iterable($value)) { + $value = (array) $value; + } + + $value = twig_to_array($value, false); + + if (0 === \count($value)) { + return ''; + } + + if (null === $and || $and === $glue) { + return implode($glue, $value); + } + + if (1 === \count($value)) { + return $value[0]; + } + + return implode($glue, \array_slice($value, 0, -1)).$and.$value[\count($value) - 1]; +} + +/** + * Splits the string into an array. + * + * {{ "one,two,three"|split(',') }} + * {# returns [one, two, three] #} + * + * {{ "one,two,three,four,five"|split(',', 3) }} + * {# returns [one, two, "three,four,five"] #} + * + * {{ "123"|split('') }} + * {# returns [1, 2, 3] #} + * + * {{ "aabbcc"|split('', 2) }} + * {# returns [aa, bb, cc] #} + * + * @param string $value A string + * @param string $delimiter The delimiter + * @param int $limit The limit + * + * @return array The split string as an array + */ +function twig_split_filter(Environment $env, $value, $delimiter, $limit = null) +{ + if (\strlen($delimiter) > 0) { + return null === $limit ? explode($delimiter, $value) : explode($delimiter, $value, $limit); + } + + if (!\function_exists('mb_get_info') || null === $charset = $env->getCharset()) { + return str_split($value, null === $limit ? 1 : $limit); + } + + if ($limit <= 1) { + return preg_split('/(?<!^)(?!$)/u', $value); + } + + $length = mb_strlen($value, $charset); + if ($length < $limit) { + return [$value]; + } + + $r = []; + for ($i = 0; $i < $length; $i += $limit) { + $r[] = mb_substr($value, $i, $limit, $charset); + } + + return $r; +} + +// The '_default' filter is used internally to avoid using the ternary operator +// which costs a lot for big contexts (before PHP 5.4). So, on average, +// a function call is cheaper. +/** + * @internal + */ +function _twig_default_filter($value, $default = '') +{ + if (twig_test_empty($value)) { + return $default; + } + + return $value; +} + +/** + * Returns the keys for the given array. + * + * It is useful when you want to iterate over the keys of an array: + * + * {% for key in array|keys %} + * {# ... #} + * {% endfor %} + * + * @param array $array An array + * + * @return array The keys + */ +function twig_get_array_keys_filter($array) +{ + if ($array instanceof \Traversable) { + while ($array instanceof \IteratorAggregate) { + $array = $array->getIterator(); + } + + if ($array instanceof \Iterator) { + $keys = []; + $array->rewind(); + while ($array->valid()) { + $keys[] = $array->key(); + $array->next(); + } + + return $keys; + } + + $keys = []; + foreach ($array as $key => $item) { + $keys[] = $key; + } + + return $keys; + } + + if (!\is_array($array)) { + return []; + } + + return array_keys($array); +} + +/** + * Reverses a variable. + * + * @param array|\Traversable|string $item An array, a \Traversable instance, or a string + * @param bool $preserveKeys Whether to preserve key or not + * + * @return mixed The reversed input + */ +function twig_reverse_filter(Environment $env, $item, $preserveKeys = false) +{ + if ($item instanceof \Traversable) { + return array_reverse(iterator_to_array($item), $preserveKeys); + } + + if (\is_array($item)) { + return array_reverse($item, $preserveKeys); + } + + if (null !== $charset = $env->getCharset()) { + $string = (string) $item; + + if ('UTF-8' !== $charset) { + $item = twig_convert_encoding($string, 'UTF-8', $charset); + } + + preg_match_all('/./us', $item, $matches); + + $string = implode('', array_reverse($matches[0])); + + if ('UTF-8' !== $charset) { + $string = twig_convert_encoding($string, $charset, 'UTF-8'); + } + + return $string; + } + + return strrev((string) $item); +} + +/** + * Sorts an array. + * + * @param array|\Traversable $array + * + * @return array + */ +function twig_sort_filter($array) +{ + if ($array instanceof \Traversable) { + $array = iterator_to_array($array); + } elseif (!\is_array($array)) { + throw new RuntimeError(sprintf('The sort filter only works with arrays or "Traversable", got "%s".', \gettype($array))); } + + asort($array); + + return $array; +} + +/** + * @internal + */ +function twig_in_filter($value, $compare) +{ + if ($value instanceof Markup) { + $value = (string) $value; + } + if ($compare instanceof Markup) { + $compare = (string) $compare; + } + + if (\is_array($compare)) { + return \in_array($value, $compare, \is_object($value) || \is_resource($value)); + } elseif (\is_string($compare) && (\is_string($value) || \is_int($value) || \is_float($value))) { + return '' === $value || false !== strpos($compare, (string) $value); + } elseif ($compare instanceof \Traversable) { + if (\is_object($value) || \is_resource($value)) { + foreach ($compare as $item) { + if ($item === $value) { + return true; + } + } + } else { + foreach ($compare as $item) { + if ($item == $value) { + return true; + } + } + } + + return false; + } + + return false; +} + +/** + * Returns a trimmed string. + * + * @return string + * + * @throws RuntimeError When an invalid trimming side is used (not a string or not 'left', 'right', or 'both') + */ +function twig_trim_filter($string, $characterMask = null, $side = 'both') +{ + if (null === $characterMask) { + $characterMask = " \t\n\r\0\x0B"; + } + + switch ($side) { + case 'both': + return trim($string, $characterMask); + case 'left': + return ltrim($string, $characterMask); + case 'right': + return rtrim($string, $characterMask); + default: + throw new RuntimeError('Trimming side must be "left", "right" or "both".'); + } +} + +/** + * Removes whitespaces between HTML tags. + * + * @return string + */ +function twig_spaceless($content) +{ + return trim(preg_replace('/>\s+</', '><', $content)); +} + +/** + * Escapes a string. + * + * @param mixed $string The value to be escaped + * @param string $strategy The escaping strategy + * @param string $charset The charset + * @param bool $autoescape Whether the function is called by the auto-escaping feature (true) or by the developer (false) + * + * @return string + */ +function twig_escape_filter(Environment $env, $string, $strategy = 'html', $charset = null, $autoescape = false) +{ + if ($autoescape && $string instanceof Markup) { + return $string; + } + + if (!\is_string($string)) { + if (\is_object($string) && method_exists($string, '__toString')) { + $string = (string) $string; + } elseif (\in_array($strategy, ['html', 'js', 'css', 'html_attr', 'url'])) { + return $string; + } + } + + if ('' === $string) { + return ''; + } + + if (null === $charset) { + $charset = $env->getCharset(); + } + + switch ($strategy) { + case 'html': + // see https://secure.php.net/htmlspecialchars + + // Using a static variable to avoid initializing the array + // each time the function is called. Moving the declaration on the + // top of the function slow downs other escaping strategies. + static $htmlspecialcharsCharsets = [ + 'ISO-8859-1' => true, 'ISO8859-1' => true, + 'ISO-8859-15' => true, 'ISO8859-15' => true, + 'utf-8' => true, 'UTF-8' => true, + 'CP866' => true, 'IBM866' => true, '866' => true, + 'CP1251' => true, 'WINDOWS-1251' => true, 'WIN-1251' => true, + '1251' => true, + 'CP1252' => true, 'WINDOWS-1252' => true, '1252' => true, + 'KOI8-R' => true, 'KOI8-RU' => true, 'KOI8R' => true, + 'BIG5' => true, '950' => true, + 'GB2312' => true, '936' => true, + 'BIG5-HKSCS' => true, + 'SHIFT_JIS' => true, 'SJIS' => true, '932' => true, + 'EUC-JP' => true, 'EUCJP' => true, + 'ISO8859-5' => true, 'ISO-8859-5' => true, 'MACROMAN' => true, + ]; + + if (isset($htmlspecialcharsCharsets[$charset])) { + return htmlspecialchars($string, ENT_QUOTES | ENT_SUBSTITUTE, $charset); + } + + if (isset($htmlspecialcharsCharsets[strtoupper($charset)])) { + // cache the lowercase variant for future iterations + $htmlspecialcharsCharsets[$charset] = true; + + return htmlspecialchars($string, ENT_QUOTES | ENT_SUBSTITUTE, $charset); + } + + $string = twig_convert_encoding($string, 'UTF-8', $charset); + $string = htmlspecialchars($string, ENT_QUOTES | ENT_SUBSTITUTE, 'UTF-8'); + + return twig_convert_encoding($string, $charset, 'UTF-8'); + + case 'js': + // escape all non-alphanumeric characters + // into their \x or \uHHHH representations + if ('UTF-8' !== $charset) { + $string = twig_convert_encoding($string, 'UTF-8', $charset); + } + + if (!preg_match('//u', $string)) { + throw new RuntimeError('The string to escape is not a valid UTF-8 string.'); + } + + $string = preg_replace_callback('#[^a-zA-Z0-9,\._]#Su', '_twig_escape_js_callback', $string); + + if ('UTF-8' !== $charset) { + $string = twig_convert_encoding($string, $charset, 'UTF-8'); + } + + return $string; + + case 'css': + if ('UTF-8' !== $charset) { + $string = twig_convert_encoding($string, 'UTF-8', $charset); + } + + if (!preg_match('//u', $string)) { + throw new RuntimeError('The string to escape is not a valid UTF-8 string.'); + } + + $string = preg_replace_callback('#[^a-zA-Z0-9]#Su', '_twig_escape_css_callback', $string); + + if ('UTF-8' !== $charset) { + $string = twig_convert_encoding($string, $charset, 'UTF-8'); + } + + return $string; + + case 'html_attr': + if ('UTF-8' !== $charset) { + $string = twig_convert_encoding($string, 'UTF-8', $charset); + } + + if (!preg_match('//u', $string)) { + throw new RuntimeError('The string to escape is not a valid UTF-8 string.'); + } + + $string = preg_replace_callback('#[^a-zA-Z0-9,\.\-_]#Su', '_twig_escape_html_attr_callback', $string); + + if ('UTF-8' !== $charset) { + $string = twig_convert_encoding($string, $charset, 'UTF-8'); + } + + return $string; + + case 'url': + return rawurlencode($string); + + default: + static $escapers; + + if (null === $escapers) { + $escapers = $env->getExtension('\Twig\Extension\CoreExtension')->getEscapers(); + } + + if (isset($escapers[$strategy])) { + return \call_user_func($escapers[$strategy], $env, $string, $charset); + } + + $validStrategies = implode(', ', array_merge(['html', 'js', 'url', 'css', 'html_attr'], array_keys($escapers))); + + throw new RuntimeError(sprintf('Invalid escaping strategy "%s" (valid ones: %s).', $strategy, $validStrategies)); + } +} + +/** + * @internal + */ +function twig_escape_filter_is_safe(Node $filterArgs) +{ + foreach ($filterArgs as $arg) { + if ($arg instanceof ConstantExpression) { + return [$arg->getAttribute('value')]; + } + + return []; + } + + return ['html']; +} + +if (\function_exists('mb_convert_encoding')) { + function twig_convert_encoding($string, $to, $from) + { + return mb_convert_encoding($string, $to, $from); + } +} elseif (\function_exists('iconv')) { + function twig_convert_encoding($string, $to, $from) + { + return iconv($from, $to, $string); + } +} else { + function twig_convert_encoding($string, $to, $from) + { + throw new RuntimeError('No suitable convert encoding function (use UTF-8 as your encoding or install the iconv or mbstring extension).'); + } +} + +if (\function_exists('mb_ord')) { + function twig_ord($string) + { + return mb_ord($string, 'UTF-8'); + } +} else { + function twig_ord($string) + { + $code = ($string = unpack('C*', substr($string, 0, 4))) ? $string[1] : 0; + if (0xF0 <= $code) { + return (($code - 0xF0) << 18) + (($string[2] - 0x80) << 12) + (($string[3] - 0x80) << 6) + $string[4] - 0x80; + } + if (0xE0 <= $code) { + return (($code - 0xE0) << 12) + (($string[2] - 0x80) << 6) + $string[3] - 0x80; + } + if (0xC0 <= $code) { + return (($code - 0xC0) << 6) + $string[2] - 0x80; + } + + return $code; + } +} + +function _twig_escape_js_callback($matches) +{ + $char = $matches[0]; + + /* + * A few characters have short escape sequences in JSON and JavaScript. + * Escape sequences supported only by JavaScript, not JSON, are ommitted. + * \" is also supported but omitted, because the resulting string is not HTML safe. + */ + static $shortMap = [ + '\\' => '\\\\', + '/' => '\\/', + "\x08" => '\b', + "\x0C" => '\f', + "\x0A" => '\n', + "\x0D" => '\r', + "\x09" => '\t', + ]; + + if (isset($shortMap[$char])) { + return $shortMap[$char]; + } + + // \uHHHH + $char = twig_convert_encoding($char, 'UTF-16BE', 'UTF-8'); + $char = strtoupper(bin2hex($char)); + + if (4 >= \strlen($char)) { + return sprintf('\u%04s', $char); + } + + return sprintf('\u%04s\u%04s', substr($char, 0, -4), substr($char, -4)); +} + +function _twig_escape_css_callback($matches) +{ + $char = $matches[0]; + + return sprintf('\\%X ', 1 === \strlen($char) ? \ord($char) : twig_ord($char)); +} + +/** + * This function is adapted from code coming from Zend Framework. + * + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (https://www.zend.com) + * @license https://framework.zend.com/license/new-bsd New BSD License + */ +function _twig_escape_html_attr_callback($matches) +{ + $chr = $matches[0]; + $ord = \ord($chr); + + /* + * The following replaces characters undefined in HTML with the + * hex entity for the Unicode replacement character. + */ + if (($ord <= 0x1f && "\t" != $chr && "\n" != $chr && "\r" != $chr) || ($ord >= 0x7f && $ord <= 0x9f)) { + return '�'; + } + + /* + * Check if the current character to escape has a name entity we should + * replace it with while grabbing the hex value of the character. + */ + if (1 == \strlen($chr)) { + /* + * While HTML supports far more named entities, the lowest common denominator + * has become HTML5's XML Serialisation which is restricted to the those named + * entities that XML supports. Using HTML entities would result in this error: + * XML Parsing Error: undefined entity + */ + static $entityMap = [ + 34 => '"', /* quotation mark */ + 38 => '&', /* ampersand */ + 60 => '<', /* less-than sign */ + 62 => '>', /* greater-than sign */ + ]; + + if (isset($entityMap[$ord])) { + return $entityMap[$ord]; + } + + return sprintf('&#x%02X;', $ord); + } + + /* + * Per OWASP recommendations, we'll use hex entities for any other + * characters where a named entity does not exist. + */ + return sprintf('&#x%04X;', twig_ord($chr)); +} + +// add multibyte extensions if possible +if (\function_exists('mb_get_info')) { + /** + * Returns the length of a variable. + * + * @param mixed $thing A variable + * + * @return int The length of the value + */ + function twig_length_filter(Environment $env, $thing) + { + if (null === $thing) { + return 0; + } + + if (is_scalar($thing)) { + return mb_strlen($thing, $env->getCharset()); + } + + if ($thing instanceof \Countable || \is_array($thing) || $thing instanceof \SimpleXMLElement) { + return \count($thing); + } + + if ($thing instanceof \Traversable) { + return iterator_count($thing); + } + + if (\is_object($thing) && method_exists($thing, '__toString')) { + return mb_strlen((string) $thing, $env->getCharset()); + } + + return 1; + } + + /** + * Converts a string to uppercase. + * + * @param string $string A string + * + * @return string The uppercased string + */ + function twig_upper_filter(Environment $env, $string) + { + if (null !== $charset = $env->getCharset()) { + return mb_strtoupper($string, $charset); + } + + return strtoupper($string); + } + + /** + * Converts a string to lowercase. + * + * @param string $string A string + * + * @return string The lowercased string + */ + function twig_lower_filter(Environment $env, $string) + { + if (null !== $charset = $env->getCharset()) { + return mb_strtolower($string, $charset); + } + + return strtolower($string); + } + + /** + * Returns a titlecased string. + * + * @param string $string A string + * + * @return string The titlecased string + */ + function twig_title_string_filter(Environment $env, $string) + { + if (null !== $charset = $env->getCharset()) { + return mb_convert_case($string, MB_CASE_TITLE, $charset); + } + + return ucwords(strtolower($string)); + } + + /** + * Returns a capitalized string. + * + * @param string $string A string + * + * @return string The capitalized string + */ + function twig_capitalize_string_filter(Environment $env, $string) + { + if (null !== $charset = $env->getCharset()) { + return mb_strtoupper(mb_substr($string, 0, 1, $charset), $charset).mb_strtolower(mb_substr($string, 1, mb_strlen($string, $charset), $charset), $charset); + } + + return ucfirst(strtolower($string)); + } +} +// and byte fallback +else { + /** + * Returns the length of a variable. + * + * @param mixed $thing A variable + * + * @return int The length of the value + */ + function twig_length_filter(Environment $env, $thing) + { + if (null === $thing) { + return 0; + } + + if (is_scalar($thing)) { + return \strlen($thing); + } + + if ($thing instanceof \SimpleXMLElement) { + return \count($thing); + } + + if (\is_object($thing) && method_exists($thing, '__toString') && !$thing instanceof \Countable) { + return \strlen((string) $thing); + } + + if ($thing instanceof \Countable || \is_array($thing)) { + return \count($thing); + } + + if ($thing instanceof \IteratorAggregate) { + return iterator_count($thing); + } + + return 1; + } + + /** + * Returns a titlecased string. + * + * @param string $string A string + * + * @return string The titlecased string + */ + function twig_title_string_filter(Environment $env, $string) + { + return ucwords(strtolower($string)); + } + + /** + * Returns a capitalized string. + * + * @param string $string A string + * + * @return string The capitalized string + */ + function twig_capitalize_string_filter(Environment $env, $string) + { + return ucfirst(strtolower($string)); + } +} + +/** + * @internal + */ +function twig_ensure_traversable($seq) +{ + if ($seq instanceof \Traversable || \is_array($seq)) { + return $seq; + } + + return []; +} + +/** + * @internal + */ +function twig_to_array($seq, $preserveKeys = true) +{ + if ($seq instanceof \Traversable) { + return iterator_to_array($seq, $preserveKeys); + } + + if (!\is_array($seq)) { + return $seq; + } + + return $preserveKeys ? $seq : array_values($seq); +} + +/** + * Checks if a variable is empty. + * + * {# evaluates to true if the foo variable is null, false, or the empty string #} + * {% if foo is empty %} + * {# ... #} + * {% endif %} + * + * @param mixed $value A variable + * + * @return bool true if the value is empty, false otherwise + */ +function twig_test_empty($value) +{ + if ($value instanceof \Countable) { + return 0 == \count($value); + } + + if ($value instanceof \Traversable) { + return !iterator_count($value); + } + + if (\is_object($value) && method_exists($value, '__toString')) { + return '' === (string) $value; + } + + return '' === $value || false === $value || null === $value || [] === $value; +} + +/** + * Checks if a variable is traversable. + * + * {# evaluates to true if the foo variable is an array or a traversable object #} + * {% if foo is iterable %} + * {# ... #} + * {% endif %} + * + * @param mixed $value A variable + * + * @return bool true if the value is traversable + */ +function twig_test_iterable($value) +{ + return $value instanceof \Traversable || \is_array($value); +} + +/** + * Renders a template. + * + * @param array $context + * @param string|array $template The template to render or an array of templates to try consecutively + * @param array $variables The variables to pass to the template + * @param bool $withContext + * @param bool $ignoreMissing Whether to ignore missing templates or not + * @param bool $sandboxed Whether to sandbox the template or not + * + * @return string The rendered template + */ +function twig_include(Environment $env, $context, $template, $variables = [], $withContext = true, $ignoreMissing = false, $sandboxed = false) +{ + $alreadySandboxed = false; + $sandbox = null; + if ($withContext) { + $variables = array_merge($context, $variables); + } + + if ($isSandboxed = $sandboxed && $env->hasExtension('\Twig\Extension\SandboxExtension')) { + $sandbox = $env->getExtension('\Twig\Extension\SandboxExtension'); + if (!$alreadySandboxed = $sandbox->isSandboxed()) { + $sandbox->enableSandbox(); + } + } + + $loaded = null; + try { + $loaded = $env->resolveTemplate($template); + } catch (LoaderError $e) { + if (!$ignoreMissing) { + if ($isSandboxed && !$alreadySandboxed) { + $sandbox->disableSandbox(); + } + + throw $e; + } + } catch (\Throwable $e) { + if ($isSandboxed && !$alreadySandboxed) { + $sandbox->disableSandbox(); + } + + throw $e; + } catch (\Exception $e) { + if ($isSandboxed && !$alreadySandboxed) { + $sandbox->disableSandbox(); + } + + throw $e; + } + + try { + $ret = $loaded ? $loaded->render($variables) : ''; + } catch (\Exception $e) { + if ($isSandboxed && !$alreadySandboxed) { + $sandbox->disableSandbox(); + } + + throw $e; + } + + if ($isSandboxed && !$alreadySandboxed) { + $sandbox->disableSandbox(); + } + + return $ret; +} + +/** + * Returns a template content without rendering it. + * + * @param string $name The template name + * @param bool $ignoreMissing Whether to ignore missing templates or not + * + * @return string The template source + */ +function twig_source(Environment $env, $name, $ignoreMissing = false) +{ + $loader = $env->getLoader(); + try { + if (!$loader instanceof SourceContextLoaderInterface) { + return $loader->getSource($name); + } else { + return $loader->getSourceContext($name)->getCode(); + } + } catch (LoaderError $e) { + if (!$ignoreMissing) { + throw $e; + } + } +} + +/** + * Provides the ability to get constants from instances as well as class/global constants. + * + * @param string $constant The name of the constant + * @param object|null $object The object to get the constant from + * + * @return string + */ +function twig_constant($constant, $object = null) +{ + if (null !== $object) { + $constant = \get_class($object).'::'.$constant; + } + + return \constant($constant); +} + +/** + * Checks if a constant exists. + * + * @param string $constant The name of the constant + * @param object|null $object The object to get the constant from + * + * @return bool + */ +function twig_constant_is_defined($constant, $object = null) +{ + if (null !== $object) { + $constant = \get_class($object).'::'.$constant; + } + + return \defined($constant); +} + +/** + * Batches item. + * + * @param array $items An array of items + * @param int $size The size of the batch + * @param mixed $fill A value used to fill missing items + * + * @return array + */ +function twig_array_batch($items, $size, $fill = null, $preserveKeys = true) +{ + if (!twig_test_iterable($items)) { + throw new RuntimeError(sprintf('The "batch" filter expects an array or "Traversable", got "%s".', \is_object($items) ? \get_class($items) : \gettype($items))); + } + + $size = ceil($size); + + $result = array_chunk(twig_to_array($items, $preserveKeys), $size, $preserveKeys); + + if (null !== $fill && $result) { + $last = \count($result) - 1; + if ($fillCount = $size - \count($result[$last])) { + for ($i = 0; $i < $fillCount; ++$i) { + $result[$last][] = $fill; + } + } + } + + return $result; +} + +function twig_array_filter($array, $arrow) +{ + if (\is_array($array)) { + if (\PHP_VERSION_ID >= 50600) { + return array_filter($array, $arrow, \ARRAY_FILTER_USE_BOTH); + } + + return array_filter($array, $arrow); + } + + // the IteratorIterator wrapping is needed as some internal PHP classes are \Traversable but do not implement \Iterator + return new \CallbackFilterIterator(new \IteratorIterator($array), $arrow); +} + +function twig_array_map($array, $arrow) +{ + $r = []; + foreach ($array as $k => $v) { + $r[$k] = $arrow($v, $k); + } + + return $r; +} + +function twig_array_reduce($array, $arrow, $initial = null) +{ + if (!\is_array($array)) { + $array = iterator_to_array($array); + } + + return array_reduce($array, $arrow, $initial); +} } diff --git a/vendor/twig/twig/src/Extension/DebugExtension.php b/vendor/twig/twig/src/Extension/DebugExtension.php index d196850c2ff680e131a65ea8a4086417f0eb658a..09b0223e2f7e99be79f561356b91321493918f83 100644 --- a/vendor/twig/twig/src/Extension/DebugExtension.php +++ b/vendor/twig/twig/src/Extension/DebugExtension.php @@ -1,11 +1,76 @@ <?php -namespace Twig\Extension; +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ -class_exists('Twig_Extension_Debug'); +namespace Twig\Extension { +use Twig\TwigFunction; -if (\false) { - class DebugExtension extends \Twig_Extension_Debug +/** + * @final + */ +class DebugExtension extends AbstractExtension +{ + public function getFunctions() { + // dump is safe if var_dump is overridden by xdebug + $isDumpOutputHtmlSafe = \extension_loaded('xdebug') + // false means that it was not set (and the default is on) or it explicitly enabled + && (false === ini_get('xdebug.overload_var_dump') || ini_get('xdebug.overload_var_dump')) + // false means that it was not set (and the default is on) or it explicitly enabled + // xdebug.overload_var_dump produces HTML only when html_errors is also enabled + && (false === ini_get('html_errors') || ini_get('html_errors')) + || 'cli' === \PHP_SAPI + ; + + return [ + new TwigFunction('dump', 'twig_var_dump', ['is_safe' => $isDumpOutputHtmlSafe ? ['html'] : [], 'needs_context' => true, 'needs_environment' => true, 'is_variadic' => true]), + ]; + } + + public function getName() + { + return 'debug'; + } +} + +class_alias('Twig\Extension\DebugExtension', 'Twig_Extension_Debug'); +} + +namespace { +use Twig\Environment; +use Twig\Template; +use Twig\TemplateWrapper; + +function twig_var_dump(Environment $env, $context, array $vars = []) +{ + if (!$env->isDebug()) { + return; + } + + ob_start(); + + if (!$vars) { + $vars = []; + foreach ($context as $key => $value) { + if (!$value instanceof Template && !$value instanceof TemplateWrapper) { + $vars[$key] = $value; + } + } + + var_dump($vars); + } else { + foreach ($vars as $var) { + var_dump($var); + } } + + return ob_get_clean(); +} } diff --git a/vendor/twig/twig/src/Extension/EscaperExtension.php b/vendor/twig/twig/src/Extension/EscaperExtension.php index c6d60b5e52d69e14b4dfe5551c1946608f21f739..fc7f6dfeeadee5a7e350acf1be5037239b727ea9 100644 --- a/vendor/twig/twig/src/Extension/EscaperExtension.php +++ b/vendor/twig/twig/src/Extension/EscaperExtension.php @@ -1,11 +1,120 @@ <?php -namespace Twig\Extension; +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ -class_exists('Twig_Extension_Escaper'); +namespace Twig\Extension { +use Twig\NodeVisitor\EscaperNodeVisitor; +use Twig\TokenParser\AutoEscapeTokenParser; +use Twig\TwigFilter; -if (\false) { - class EscaperExtension extends \Twig_Extension_Escaper +/** + * @final + */ +class EscaperExtension extends AbstractExtension +{ + protected $defaultStrategy; + + /** + * @param string|false|callable $defaultStrategy An escaping strategy + * + * @see setDefaultStrategy() + */ + public function __construct($defaultStrategy = 'html') + { + $this->setDefaultStrategy($defaultStrategy); + } + + public function getTokenParsers() + { + return [new AutoEscapeTokenParser()]; + } + + public function getNodeVisitors() + { + return [new EscaperNodeVisitor()]; + } + + public function getFilters() + { + return [ + new TwigFilter('raw', 'twig_raw_filter', ['is_safe' => ['all']]), + ]; + } + + /** + * Sets the default strategy to use when not defined by the user. + * + * The strategy can be a valid PHP callback that takes the template + * name as an argument and returns the strategy to use. + * + * @param string|false|callable $defaultStrategy An escaping strategy + */ + public function setDefaultStrategy($defaultStrategy) + { + // for BC + if (true === $defaultStrategy) { + @trigger_error('Using "true" as the default strategy is deprecated since version 1.21. Use "html" instead.', E_USER_DEPRECATED); + + $defaultStrategy = 'html'; + } + + if ('filename' === $defaultStrategy) { + @trigger_error('Using "filename" as the default strategy is deprecated since version 1.27. Use "name" instead.', E_USER_DEPRECATED); + + $defaultStrategy = 'name'; + } + + if ('name' === $defaultStrategy) { + $defaultStrategy = ['\Twig\FileExtensionEscapingStrategy', 'guess']; + } + + $this->defaultStrategy = $defaultStrategy; + } + + /** + * Gets the default strategy to use when not defined by the user. + * + * @param string $name The template name + * + * @return string|false The default strategy to use for the template + */ + public function getDefaultStrategy($name) { + // disable string callables to avoid calling a function named html or js, + // or any other upcoming escaping strategy + if (!\is_string($this->defaultStrategy) && false !== $this->defaultStrategy) { + return \call_user_func($this->defaultStrategy, $name); + } + + return $this->defaultStrategy; } + + public function getName() + { + return 'escaper'; + } +} + +class_alias('Twig\Extension\EscaperExtension', 'Twig_Extension_Escaper'); +} + +namespace { +/** + * Marks a variable as being safe. + * + * @param string $string A PHP variable + * + * @return string + */ +function twig_raw_filter($string) +{ + return $string; +} } diff --git a/vendor/twig/twig/src/Extension/ExtensionInterface.php b/vendor/twig/twig/src/Extension/ExtensionInterface.php index 0a1d502e47ce6ea97f89c9a6bb8f87931c42f25c..72b31e9d1af9da107e299810dbb6a95229abc209 100644 --- a/vendor/twig/twig/src/Extension/ExtensionInterface.php +++ b/vendor/twig/twig/src/Extension/ExtensionInterface.php @@ -1,11 +1,101 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\Extension; -class_exists('Twig_ExtensionInterface'); +use Twig\Environment; +use Twig\NodeVisitor\NodeVisitorInterface; +use Twig\TokenParser\TokenParserInterface; +use Twig\TwigFilter; +use Twig\TwigFunction; +use Twig\TwigTest; + +/** + * Interface implemented by extension classes. + * + * @author Fabien Potencier <fabien@symfony.com> + */ +interface ExtensionInterface +{ + /** + * Initializes the runtime environment. + * + * This is where you can load some file that contains filter functions for instance. + * + * @deprecated since 1.23 (to be removed in 2.0), implement \Twig_Extension_InitRuntimeInterface instead + */ + public function initRuntime(Environment $environment); + + /** + * Returns the token parser instances to add to the existing list. + * + * @return TokenParserInterface[] + */ + public function getTokenParsers(); + + /** + * Returns the node visitor instances to add to the existing list. + * + * @return NodeVisitorInterface[] + */ + public function getNodeVisitors(); + + /** + * Returns a list of filters to add to the existing list. + * + * @return TwigFilter[] + */ + public function getFilters(); + + /** + * Returns a list of tests to add to the existing list. + * + * @return TwigTest[] + */ + public function getTests(); -if (\false) { - interface ExtensionInterface extends \Twig_ExtensionInterface - { - } + /** + * Returns a list of functions to add to the existing list. + * + * @return TwigFunction[] + */ + public function getFunctions(); + + /** + * Returns a list of operators to add to the existing list. + * + * @return array<array> First array of unary operators, second array of binary operators + */ + public function getOperators(); + + /** + * Returns a list of global variables to add to the existing list. + * + * @return array An array of global variables + * + * @deprecated since 1.23 (to be removed in 2.0), implement \Twig_Extension_GlobalsInterface instead + */ + public function getGlobals(); + + /** + * Returns the name of the extension. + * + * @return string The extension name + * + * @deprecated since 1.26 (to be removed in 2.0), not used anymore internally + */ + public function getName(); } + +class_alias('Twig\Extension\ExtensionInterface', 'Twig_ExtensionInterface'); + +// Ensure that the aliased name is loaded to keep BC for classes implementing the typehint with the old aliased name. +class_exists('Twig\Environment'); diff --git a/vendor/twig/twig/src/Extension/GlobalsInterface.php b/vendor/twig/twig/src/Extension/GlobalsInterface.php index 024f314d9a02d1444367e9cf58e1e7318ac82ed6..1f54e257245b1e07055e6f1fb77dd163079d87e5 100644 --- a/vendor/twig/twig/src/Extension/GlobalsInterface.php +++ b/vendor/twig/twig/src/Extension/GlobalsInterface.php @@ -1,11 +1,26 @@ <?php -namespace Twig\Extension; +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ -class_exists('Twig_Extension_GlobalsInterface'); +namespace Twig\Extension; -if (\false) { - interface GlobalsInterface extends \Twig_Extension_ExtensionInterface - { - } +/** + * Enables usage of the deprecated Twig\Extension\AbstractExtension::getGlobals() method. + * + * Explicitly implement this interface if you really need to implement the + * deprecated getGlobals() method in your extensions. + * + * @author Fabien Potencier <fabien@symfony.com> + */ +interface GlobalsInterface +{ } + +class_alias('Twig\Extension\GlobalsInterface', 'Twig_Extension_GlobalsInterface'); diff --git a/vendor/twig/twig/src/Extension/InitRuntimeInterface.php b/vendor/twig/twig/src/Extension/InitRuntimeInterface.php index b7a2e30086e5d04a7f617cf5f90ef8a9d802c0f4..f71d9cb51dce81ec98fb3e3861b86c817a096847 100644 --- a/vendor/twig/twig/src/Extension/InitRuntimeInterface.php +++ b/vendor/twig/twig/src/Extension/InitRuntimeInterface.php @@ -1,11 +1,26 @@ <?php -namespace Twig\Extension; +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ -class_exists('Twig_Extension_InitRuntimeInterface'); +namespace Twig\Extension; -if (\false) { - interface InitRuntimeInterface extends \Twig_Extension_InitRuntimeInterface - { - } +/** + * Enables usage of the deprecated Twig\Extension\AbstractExtension::initRuntime() method. + * + * Explicitly implement this interface if you really need to implement the + * deprecated initRuntime() method in your extensions. + * + * @author Fabien Potencier <fabien@symfony.com> + */ +interface InitRuntimeInterface +{ } + +class_alias('Twig\Extension\InitRuntimeInterface', 'Twig_Extension_InitRuntimeInterface'); diff --git a/vendor/twig/twig/src/Extension/OptimizerExtension.php b/vendor/twig/twig/src/Extension/OptimizerExtension.php index 5aa6ea3449af697d329aef7bd1def2e0a33d76a8..3e137409e27ada9541d16810b8f8f803341462ed 100644 --- a/vendor/twig/twig/src/Extension/OptimizerExtension.php +++ b/vendor/twig/twig/src/Extension/OptimizerExtension.php @@ -1,11 +1,39 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\Extension; -class_exists('Twig_Extension_Optimizer'); +use Twig\NodeVisitor\OptimizerNodeVisitor; + +/** + * @final + */ +class OptimizerExtension extends AbstractExtension +{ + protected $optimizers; + + public function __construct($optimizers = -1) + { + $this->optimizers = $optimizers; + } -if (\false) { - class OptimizerExtension extends \Twig_Extension_Optimizer + public function getNodeVisitors() { + return [new OptimizerNodeVisitor($this->optimizers)]; + } + + public function getName() + { + return 'optimizer'; } } + +class_alias('Twig\Extension\OptimizerExtension', 'Twig_Extension_Optimizer'); diff --git a/vendor/twig/twig/src/Extension/ProfilerExtension.php b/vendor/twig/twig/src/Extension/ProfilerExtension.php index 58fb5bc8b219e638d47efe2e9f08ee7d4fa20276..7b21b9fa55580c8df4019bfac0255fee9e463ebe 100644 --- a/vendor/twig/twig/src/Extension/ProfilerExtension.php +++ b/vendor/twig/twig/src/Extension/ProfilerExtension.php @@ -1,11 +1,53 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\Extension; -class_exists('Twig_Extension_Profiler'); +use Twig\Profiler\NodeVisitor\ProfilerNodeVisitor; +use Twig\Profiler\Profile; + +class ProfilerExtension extends AbstractExtension +{ + private $actives = []; + + public function __construct(Profile $profile) + { + $this->actives[] = $profile; + } + + public function enter(Profile $profile) + { + $this->actives[0]->addProfile($profile); + array_unshift($this->actives, $profile); + } + + public function leave(Profile $profile) + { + $profile->leave(); + array_shift($this->actives); + + if (1 === \count($this->actives)) { + $this->actives[0]->leave(); + } + } + + public function getNodeVisitors() + { + return [new ProfilerNodeVisitor(\get_class($this))]; + } -if (\false) { - class ProfilerExtension extends \Twig_Extension_Profiler + public function getName() { + return 'profiler'; } } + +class_alias('Twig\Extension\ProfilerExtension', 'Twig_Extension_Profiler'); diff --git a/vendor/twig/twig/src/Extension/SandboxExtension.php b/vendor/twig/twig/src/Extension/SandboxExtension.php index 0c244ffc660d8acdd8d6f77cf0e1dde11dfab815..818c8c94c816aefcd0c55fcfc512272b111c420c 100644 --- a/vendor/twig/twig/src/Extension/SandboxExtension.php +++ b/vendor/twig/twig/src/Extension/SandboxExtension.php @@ -1,11 +1,109 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\Extension; -class_exists('Twig_Extension_Sandbox'); +use Twig\NodeVisitor\SandboxNodeVisitor; +use Twig\Sandbox\SecurityPolicyInterface; +use Twig\TokenParser\SandboxTokenParser; + +/** + * @final + */ +class SandboxExtension extends AbstractExtension +{ + protected $sandboxedGlobally; + protected $sandboxed; + protected $policy; + + public function __construct(SecurityPolicyInterface $policy, $sandboxed = false) + { + $this->policy = $policy; + $this->sandboxedGlobally = $sandboxed; + } + + public function getTokenParsers() + { + return [new SandboxTokenParser()]; + } + + public function getNodeVisitors() + { + return [new SandboxNodeVisitor()]; + } + + public function enableSandbox() + { + $this->sandboxed = true; + } + + public function disableSandbox() + { + $this->sandboxed = false; + } -if (\false) { - class SandboxExtension extends \Twig_Extension_Sandbox + public function isSandboxed() { + return $this->sandboxedGlobally || $this->sandboxed; + } + + public function isSandboxedGlobally() + { + return $this->sandboxedGlobally; + } + + public function setSecurityPolicy(SecurityPolicyInterface $policy) + { + $this->policy = $policy; + } + + public function getSecurityPolicy() + { + return $this->policy; + } + + public function checkSecurity($tags, $filters, $functions) + { + if ($this->isSandboxed()) { + $this->policy->checkSecurity($tags, $filters, $functions); + } + } + + public function checkMethodAllowed($obj, $method) + { + if ($this->isSandboxed()) { + $this->policy->checkMethodAllowed($obj, $method); + } + } + + public function checkPropertyAllowed($obj, $method) + { + if ($this->isSandboxed()) { + $this->policy->checkPropertyAllowed($obj, $method); + } + } + + public function ensureToStringAllowed($obj) + { + if ($this->isSandboxed() && \is_object($obj) && method_exists($obj, '__toString')) { + $this->policy->checkMethodAllowed($obj, '__toString'); + } + + return $obj; + } + + public function getName() + { + return 'sandbox'; } } + +class_alias('Twig\Extension\SandboxExtension', 'Twig_Extension_Sandbox'); diff --git a/vendor/twig/twig/src/Extension/StagingExtension.php b/vendor/twig/twig/src/Extension/StagingExtension.php index 62016faefedfad14ee70e9e0ce21f836cedaa880..049c5c79775c4d7f1a3b07f3c191978147859cec 100644 --- a/vendor/twig/twig/src/Extension/StagingExtension.php +++ b/vendor/twig/twig/src/Extension/StagingExtension.php @@ -1,11 +1,117 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\Extension; -class_exists('Twig_Extension_Staging'); +use Twig\NodeVisitor\NodeVisitorInterface; +use Twig\TokenParser\TokenParserInterface; + +/** + * Internal class. + * + * This class is used by \Twig\Environment as a staging area and must not be used directly. + * + * @author Fabien Potencier <fabien@symfony.com> + * + * @internal + */ +class StagingExtension extends AbstractExtension +{ + protected $functions = []; + protected $filters = []; + protected $visitors = []; + protected $tokenParsers = []; + protected $globals = []; + protected $tests = []; + + public function addFunction($name, $function) + { + if (isset($this->functions[$name])) { + @trigger_error(sprintf('Overriding function "%s" that is already registered is deprecated since version 1.30 and won\'t be possible anymore in 2.0.', $name), E_USER_DEPRECATED); + } + + $this->functions[$name] = $function; + } + + public function getFunctions() + { + return $this->functions; + } + + public function addFilter($name, $filter) + { + if (isset($this->filters[$name])) { + @trigger_error(sprintf('Overriding filter "%s" that is already registered is deprecated since version 1.30 and won\'t be possible anymore in 2.0.', $name), E_USER_DEPRECATED); + } + + $this->filters[$name] = $filter; + } + + public function getFilters() + { + return $this->filters; + } -if (\false) { - class StagingExtension extends \Twig_Extension_Staging + public function addNodeVisitor(NodeVisitorInterface $visitor) { + $this->visitors[] = $visitor; + } + + public function getNodeVisitors() + { + return $this->visitors; + } + + public function addTokenParser(TokenParserInterface $parser) + { + if (isset($this->tokenParsers[$parser->getTag()])) { + @trigger_error(sprintf('Overriding tag "%s" that is already registered is deprecated since version 1.30 and won\'t be possible anymore in 2.0.', $parser->getTag()), E_USER_DEPRECATED); + } + + $this->tokenParsers[$parser->getTag()] = $parser; + } + + public function getTokenParsers() + { + return $this->tokenParsers; + } + + public function addGlobal($name, $value) + { + $this->globals[$name] = $value; + } + + public function getGlobals() + { + return $this->globals; + } + + public function addTest($name, $test) + { + if (isset($this->tests[$name])) { + @trigger_error(sprintf('Overriding test "%s" that is already registered is deprecated since version 1.30 and won\'t be possible anymore in 2.0.', $name), E_USER_DEPRECATED); + } + + $this->tests[$name] = $test; + } + + public function getTests() + { + return $this->tests; + } + + public function getName() + { + return 'staging'; } } + +class_alias('Twig\Extension\StagingExtension', 'Twig_Extension_Staging'); diff --git a/vendor/twig/twig/src/Extension/StringLoaderExtension.php b/vendor/twig/twig/src/Extension/StringLoaderExtension.php index 0474432d79167bbdc814ae70d931b5ce12ef1a8d..93ac834ac24359365798a69dacc43fd11786f7b7 100644 --- a/vendor/twig/twig/src/Extension/StringLoaderExtension.php +++ b/vendor/twig/twig/src/Extension/StringLoaderExtension.php @@ -1,11 +1,54 @@ <?php -namespace Twig\Extension; +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ -class_exists('Twig_Extension_StringLoader'); +namespace Twig\Extension { +use Twig\TwigFunction; -if (\false) { - class StringLoaderExtension extends \Twig_Extension_StringLoader +/** + * @final + */ +class StringLoaderExtension extends AbstractExtension +{ + public function getFunctions() { + return [ + new TwigFunction('template_from_string', 'twig_template_from_string', ['needs_environment' => true]), + ]; } + + public function getName() + { + return 'string_loader'; + } +} + +class_alias('Twig\Extension\StringLoaderExtension', 'Twig_Extension_StringLoader'); +} + +namespace { +use Twig\Environment; +use Twig\TemplateWrapper; + +/** + * Loads a template from a string. + * + * {{ include(template_from_string("Hello {{ name }}")) }} + * + * @param string $template A template as a string or object implementing __toString() + * @param string $name An optional name of the template to be used in error messages + * + * @return TemplateWrapper + */ +function twig_template_from_string(Environment $env, $template, $name = null) +{ + return $env->createTemplate((string) $template, $name); +} } diff --git a/vendor/twig/twig/src/FileExtensionEscapingStrategy.php b/vendor/twig/twig/src/FileExtensionEscapingStrategy.php index 189f8132d915856c3191e427667c9017bbe9958b..bc95f33435c8dea866c87b47c5cd428b0b559d89 100644 --- a/vendor/twig/twig/src/FileExtensionEscapingStrategy.php +++ b/vendor/twig/twig/src/FileExtensionEscapingStrategy.php @@ -1,11 +1,62 @@ <?php -namespace Twig; +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ -class_exists('Twig_FileExtensionEscapingStrategy'); +namespace Twig; -if (\false) { - class FileExtensionEscapingStrategy extends \Twig_FileExtensionEscapingStrategy +/** + * Default autoescaping strategy based on file names. + * + * This strategy sets the HTML as the default autoescaping strategy, + * but changes it based on the template name. + * + * Note that there is no runtime performance impact as the + * default autoescaping strategy is set at compilation time. + * + * @author Fabien Potencier <fabien@symfony.com> + */ +class FileExtensionEscapingStrategy +{ + /** + * Guesses the best autoescaping strategy based on the file name. + * + * @param string $name The template name + * + * @return string|false The escaping strategy name to use or false to disable + */ + public static function guess($name) { + if (\in_array(substr($name, -1), ['/', '\\'])) { + return 'html'; // return html for directories + } + + if ('.twig' === substr($name, -5)) { + $name = substr($name, 0, -5); + } + + $extension = pathinfo($name, PATHINFO_EXTENSION); + + switch ($extension) { + case 'js': + return 'js'; + + case 'css': + return 'css'; + + case 'txt': + return false; + + default: + return 'html'; + } } } + +class_alias('Twig\FileExtensionEscapingStrategy', 'Twig_FileExtensionEscapingStrategy'); diff --git a/vendor/twig/twig/src/Lexer.php b/vendor/twig/twig/src/Lexer.php index f141afe6f7ca338cab8712b38400d2ab175c9ae4..8cae3597f12494f85cb71daba00a3f36d50dae42 100644 --- a/vendor/twig/twig/src/Lexer.php +++ b/vendor/twig/twig/src/Lexer.php @@ -1,11 +1,534 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * (c) Armin Ronacher + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig; -class_exists('Twig_Lexer'); +use Twig\Error\SyntaxError; + +/** + * Lexes a template string. + * + * @author Fabien Potencier <fabien@symfony.com> + */ +class Lexer implements \Twig_LexerInterface +{ + protected $tokens; + protected $code; + protected $cursor; + protected $lineno; + protected $end; + protected $state; + protected $states; + protected $brackets; + protected $env; + // to be renamed to $name in 2.0 (where it is private) + protected $filename; + protected $options; + protected $regexes; + protected $position; + protected $positions; + protected $currentVarBlockLine; + + private $source; + + const STATE_DATA = 0; + const STATE_BLOCK = 1; + const STATE_VAR = 2; + const STATE_STRING = 3; + const STATE_INTERPOLATION = 4; + + const REGEX_NAME = '/[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*/A'; + const REGEX_NUMBER = '/[0-9]+(?:\.[0-9]+)?/A'; + const REGEX_STRING = '/"([^#"\\\\]*(?:\\\\.[^#"\\\\]*)*)"|\'([^\'\\\\]*(?:\\\\.[^\'\\\\]*)*)\'/As'; + const REGEX_DQ_STRING_DELIM = '/"/A'; + const REGEX_DQ_STRING_PART = '/[^#"\\\\]*(?:(?:\\\\.|#(?!\{))[^#"\\\\]*)*/As'; + const PUNCTUATION = '()[]{}?:.,|'; + + public function __construct(Environment $env, array $options = []) + { + $this->env = $env; + + $this->options = array_merge([ + 'tag_comment' => ['{#', '#}'], + 'tag_block' => ['{%', '%}'], + 'tag_variable' => ['{{', '}}'], + 'whitespace_trim' => '-', + 'whitespace_line_trim' => '~', + 'whitespace_line_chars' => ' \t\0\x0B', + 'interpolation' => ['#{', '}'], + ], $options); + + // when PHP 7.3 is the min version, we will be able to remove the '#' part in preg_quote as it's part of the default + $this->regexes = [ + // }} + 'lex_var' => '{ + \s* + (?:'. + preg_quote($this->options['whitespace_trim'].$this->options['tag_variable'][1], '#').'\s*'. // -}}\s* + '|'. + preg_quote($this->options['whitespace_line_trim'].$this->options['tag_variable'][1], '#').'['.$this->options['whitespace_line_chars'].']*'. // ~}}[ \t\0\x0B]* + '|'. + preg_quote($this->options['tag_variable'][1], '#'). // }} + ') + }Ax', + + // %} + 'lex_block' => '{ + \s* + (?:'. + preg_quote($this->options['whitespace_trim'].$this->options['tag_block'][1], '#').'\s*\n?'. // -%}\s*\n? + '|'. + preg_quote($this->options['whitespace_line_trim'].$this->options['tag_block'][1], '#').'['.$this->options['whitespace_line_chars'].']*'. // ~%}[ \t\0\x0B]* + '|'. + preg_quote($this->options['tag_block'][1], '#').'\n?'. // %}\n? + ') + }Ax', + + // {% endverbatim %} + 'lex_raw_data' => '{'. + preg_quote($this->options['tag_block'][0], '#'). // {% + '('. + $this->options['whitespace_trim']. // - + '|'. + $this->options['whitespace_line_trim']. // ~ + ')?\s*'. + '(?:end%s)'. // endraw or endverbatim + '\s*'. + '(?:'. + preg_quote($this->options['whitespace_trim'].$this->options['tag_block'][1], '#').'\s*'. // -%} + '|'. + preg_quote($this->options['whitespace_line_trim'].$this->options['tag_block'][1], '#').'['.$this->options['whitespace_line_chars'].']*'. // ~%}[ \t\0\x0B]* + '|'. + preg_quote($this->options['tag_block'][1], '#'). // %} + ') + }sx', + + 'operator' => $this->getOperatorRegex(), + + // #} + 'lex_comment' => '{ + (?:'. + preg_quote($this->options['whitespace_trim']).preg_quote($this->options['tag_comment'][1], '#').'\s*\n?'. // -#}\s*\n? + '|'. + preg_quote($this->options['whitespace_line_trim'].$this->options['tag_comment'][1], '#').'['.$this->options['whitespace_line_chars'].']*'. // ~#}[ \t\0\x0B]* + '|'. + preg_quote($this->options['tag_comment'][1], '#').'\n?'. // #}\n? + ') + }sx', + + // verbatim %} + 'lex_block_raw' => '{ + \s* + (raw|verbatim) + \s* + (?:'. + preg_quote($this->options['whitespace_trim'].$this->options['tag_block'][1], '#').'\s*'. // -%}\s* + '|'. + preg_quote($this->options['whitespace_line_trim'].$this->options['tag_block'][1], '#').'['.$this->options['whitespace_line_chars'].']*'. // ~%}[ \t\0\x0B]* + '|'. + preg_quote($this->options['tag_block'][1], '#'). // %} + ') + }Asx', + + 'lex_block_line' => '{\s*line\s+(\d+)\s*'.preg_quote($this->options['tag_block'][1], '#').'}As', + + // {{ or {% or {# + 'lex_tokens_start' => '{ + ('. + preg_quote($this->options['tag_variable'][0], '#'). // {{ + '|'. + preg_quote($this->options['tag_block'][0], '#'). // {% + '|'. + preg_quote($this->options['tag_comment'][0], '#'). // {# + ')('. + preg_quote($this->options['whitespace_trim'], '#'). // - + '|'. + preg_quote($this->options['whitespace_line_trim'], '#'). // ~ + ')? + }sx', + 'interpolation_start' => '{'.preg_quote($this->options['interpolation'][0], '#').'\s*}A', + 'interpolation_end' => '{\s*'.preg_quote($this->options['interpolation'][1], '#').'}A', + ]; + } + + public function tokenize($code, $name = null) + { + if (!$code instanceof Source) { + @trigger_error(sprintf('Passing a string as the $code argument of %s() is deprecated since version 1.27 and will be removed in 2.0. Pass a \Twig\Source instance instead.', __METHOD__), E_USER_DEPRECATED); + $this->source = new Source($code, $name); + } else { + $this->source = $code; + } + + if (((int) ini_get('mbstring.func_overload')) & 2) { + @trigger_error('Support for having "mbstring.func_overload" different from 0 is deprecated version 1.29 and will be removed in 2.0.', E_USER_DEPRECATED); + } + + if (\function_exists('mb_internal_encoding') && ((int) ini_get('mbstring.func_overload')) & 2) { + $mbEncoding = mb_internal_encoding(); + mb_internal_encoding('ASCII'); + } else { + $mbEncoding = null; + } + + $this->code = str_replace(["\r\n", "\r"], "\n", $this->source->getCode()); + $this->filename = $this->source->getName(); + $this->cursor = 0; + $this->lineno = 1; + $this->end = \strlen($this->code); + $this->tokens = []; + $this->state = self::STATE_DATA; + $this->states = []; + $this->brackets = []; + $this->position = -1; + + // find all token starts in one go + preg_match_all($this->regexes['lex_tokens_start'], $this->code, $matches, PREG_OFFSET_CAPTURE); + $this->positions = $matches; + + while ($this->cursor < $this->end) { + // dispatch to the lexing functions depending + // on the current state + switch ($this->state) { + case self::STATE_DATA: + $this->lexData(); + break; + + case self::STATE_BLOCK: + $this->lexBlock(); + break; + + case self::STATE_VAR: + $this->lexVar(); + break; + + case self::STATE_STRING: + $this->lexString(); + break; + + case self::STATE_INTERPOLATION: + $this->lexInterpolation(); + break; + } + } + + $this->pushToken(Token::EOF_TYPE); + + if (!empty($this->brackets)) { + list($expect, $lineno) = array_pop($this->brackets); + throw new SyntaxError(sprintf('Unclosed "%s".', $expect), $lineno, $this->source); + } + + if ($mbEncoding) { + mb_internal_encoding($mbEncoding); + } + + return new TokenStream($this->tokens, $this->source); + } + + protected function lexData() + { + // if no matches are left we return the rest of the template as simple text token + if ($this->position == \count($this->positions[0]) - 1) { + $this->pushToken(Token::TEXT_TYPE, substr($this->code, $this->cursor)); + $this->cursor = $this->end; + + return; + } + + // Find the first token after the current cursor + $position = $this->positions[0][++$this->position]; + while ($position[1] < $this->cursor) { + if ($this->position == \count($this->positions[0]) - 1) { + return; + } + $position = $this->positions[0][++$this->position]; + } + + // push the template text first + $text = $textContent = substr($this->code, $this->cursor, $position[1] - $this->cursor); + + // trim? + if (isset($this->positions[2][$this->position][0])) { + if ($this->options['whitespace_trim'] === $this->positions[2][$this->position][0]) { + // whitespace_trim detected ({%-, {{- or {#-) + $text = rtrim($text); + } elseif ($this->options['whitespace_line_trim'] === $this->positions[2][$this->position][0]) { + // whitespace_line_trim detected ({%~, {{~ or {#~) + // don't trim \r and \n + $text = rtrim($text, " \t\0\x0B"); + } + } + $this->pushToken(Token::TEXT_TYPE, $text); + $this->moveCursor($textContent.$position[0]); + + switch ($this->positions[1][$this->position][0]) { + case $this->options['tag_comment'][0]: + $this->lexComment(); + break; + + case $this->options['tag_block'][0]: + // raw data? + if (preg_match($this->regexes['lex_block_raw'], $this->code, $match, 0, $this->cursor)) { + $this->moveCursor($match[0]); + $this->lexRawData($match[1]); + // {% line \d+ %} + } elseif (preg_match($this->regexes['lex_block_line'], $this->code, $match, 0, $this->cursor)) { + $this->moveCursor($match[0]); + $this->lineno = (int) $match[1]; + } else { + $this->pushToken(Token::BLOCK_START_TYPE); + $this->pushState(self::STATE_BLOCK); + $this->currentVarBlockLine = $this->lineno; + } + break; + + case $this->options['tag_variable'][0]: + $this->pushToken(Token::VAR_START_TYPE); + $this->pushState(self::STATE_VAR); + $this->currentVarBlockLine = $this->lineno; + break; + } + } + + protected function lexBlock() + { + if (empty($this->brackets) && preg_match($this->regexes['lex_block'], $this->code, $match, 0, $this->cursor)) { + $this->pushToken(Token::BLOCK_END_TYPE); + $this->moveCursor($match[0]); + $this->popState(); + } else { + $this->lexExpression(); + } + } + + protected function lexVar() + { + if (empty($this->brackets) && preg_match($this->regexes['lex_var'], $this->code, $match, 0, $this->cursor)) { + $this->pushToken(Token::VAR_END_TYPE); + $this->moveCursor($match[0]); + $this->popState(); + } else { + $this->lexExpression(); + } + } + + protected function lexExpression() + { + // whitespace + if (preg_match('/\s+/A', $this->code, $match, 0, $this->cursor)) { + $this->moveCursor($match[0]); + + if ($this->cursor >= $this->end) { + throw new SyntaxError(sprintf('Unclosed "%s".', self::STATE_BLOCK === $this->state ? 'block' : 'variable'), $this->currentVarBlockLine, $this->source); + } + } + + // arrow function + if ('=' === $this->code[$this->cursor] && '>' === $this->code[$this->cursor + 1]) { + $this->pushToken(Token::ARROW_TYPE, '=>'); + $this->moveCursor('=>'); + } + // operators + elseif (preg_match($this->regexes['operator'], $this->code, $match, 0, $this->cursor)) { + $this->pushToken(Token::OPERATOR_TYPE, preg_replace('/\s+/', ' ', $match[0])); + $this->moveCursor($match[0]); + } + // names + elseif (preg_match(self::REGEX_NAME, $this->code, $match, 0, $this->cursor)) { + $this->pushToken(Token::NAME_TYPE, $match[0]); + $this->moveCursor($match[0]); + } + // numbers + elseif (preg_match(self::REGEX_NUMBER, $this->code, $match, 0, $this->cursor)) { + $number = (float) $match[0]; // floats + if (ctype_digit($match[0]) && $number <= PHP_INT_MAX) { + $number = (int) $match[0]; // integers lower than the maximum + } + $this->pushToken(Token::NUMBER_TYPE, $number); + $this->moveCursor($match[0]); + } + // punctuation + elseif (false !== strpos(self::PUNCTUATION, $this->code[$this->cursor])) { + // opening bracket + if (false !== strpos('([{', $this->code[$this->cursor])) { + $this->brackets[] = [$this->code[$this->cursor], $this->lineno]; + } + // closing bracket + elseif (false !== strpos(')]}', $this->code[$this->cursor])) { + if (empty($this->brackets)) { + throw new SyntaxError(sprintf('Unexpected "%s".', $this->code[$this->cursor]), $this->lineno, $this->source); + } + + list($expect, $lineno) = array_pop($this->brackets); + if ($this->code[$this->cursor] != strtr($expect, '([{', ')]}')) { + throw new SyntaxError(sprintf('Unclosed "%s".', $expect), $lineno, $this->source); + } + } + + $this->pushToken(Token::PUNCTUATION_TYPE, $this->code[$this->cursor]); + ++$this->cursor; + } + // strings + elseif (preg_match(self::REGEX_STRING, $this->code, $match, 0, $this->cursor)) { + $this->pushToken(Token::STRING_TYPE, stripcslashes(substr($match[0], 1, -1))); + $this->moveCursor($match[0]); + } + // opening double quoted string + elseif (preg_match(self::REGEX_DQ_STRING_DELIM, $this->code, $match, 0, $this->cursor)) { + $this->brackets[] = ['"', $this->lineno]; + $this->pushState(self::STATE_STRING); + $this->moveCursor($match[0]); + } + // unlexable + else { + throw new SyntaxError(sprintf('Unexpected character "%s".', $this->code[$this->cursor]), $this->lineno, $this->source); + } + } + + protected function lexRawData($tag) + { + if ('raw' === $tag) { + @trigger_error(sprintf('Twig Tag "raw" is deprecated since version 1.21. Use "verbatim" instead in %s at line %d.', $this->filename, $this->lineno), E_USER_DEPRECATED); + } + + if (!preg_match(str_replace('%s', $tag, $this->regexes['lex_raw_data']), $this->code, $match, PREG_OFFSET_CAPTURE, $this->cursor)) { + throw new SyntaxError(sprintf('Unexpected end of file: Unclosed "%s" block.', $tag), $this->lineno, $this->source); + } + + $text = substr($this->code, $this->cursor, $match[0][1] - $this->cursor); + $this->moveCursor($text.$match[0][0]); + + // trim? + if (isset($match[1][0])) { + if ($this->options['whitespace_trim'] === $match[1][0]) { + // whitespace_trim detected ({%-, {{- or {#-) + $text = rtrim($text); + } else { + // whitespace_line_trim detected ({%~, {{~ or {#~) + // don't trim \r and \n + $text = rtrim($text, " \t\0\x0B"); + } + } + + $this->pushToken(Token::TEXT_TYPE, $text); + } + + protected function lexComment() + { + if (!preg_match($this->regexes['lex_comment'], $this->code, $match, PREG_OFFSET_CAPTURE, $this->cursor)) { + throw new SyntaxError('Unclosed comment.', $this->lineno, $this->source); + } + + $this->moveCursor(substr($this->code, $this->cursor, $match[0][1] - $this->cursor).$match[0][0]); + } + + protected function lexString() + { + if (preg_match($this->regexes['interpolation_start'], $this->code, $match, 0, $this->cursor)) { + $this->brackets[] = [$this->options['interpolation'][0], $this->lineno]; + $this->pushToken(Token::INTERPOLATION_START_TYPE); + $this->moveCursor($match[0]); + $this->pushState(self::STATE_INTERPOLATION); + } elseif (preg_match(self::REGEX_DQ_STRING_PART, $this->code, $match, 0, $this->cursor) && \strlen($match[0]) > 0) { + $this->pushToken(Token::STRING_TYPE, stripcslashes($match[0])); + $this->moveCursor($match[0]); + } elseif (preg_match(self::REGEX_DQ_STRING_DELIM, $this->code, $match, 0, $this->cursor)) { + list($expect, $lineno) = array_pop($this->brackets); + if ('"' != $this->code[$this->cursor]) { + throw new SyntaxError(sprintf('Unclosed "%s".', $expect), $lineno, $this->source); + } + + $this->popState(); + ++$this->cursor; + } else { + // unlexable + throw new SyntaxError(sprintf('Unexpected character "%s".', $this->code[$this->cursor]), $this->lineno, $this->source); + } + } -if (\false) { - class Lexer extends \Twig_Lexer + protected function lexInterpolation() { + $bracket = end($this->brackets); + if ($this->options['interpolation'][0] === $bracket[0] && preg_match($this->regexes['interpolation_end'], $this->code, $match, 0, $this->cursor)) { + array_pop($this->brackets); + $this->pushToken(Token::INTERPOLATION_END_TYPE); + $this->moveCursor($match[0]); + $this->popState(); + } else { + $this->lexExpression(); + } + } + + protected function pushToken($type, $value = '') + { + // do not push empty text tokens + if (Token::TEXT_TYPE === $type && '' === $value) { + return; + } + + $this->tokens[] = new Token($type, $value, $this->lineno); + } + + protected function moveCursor($text) + { + $this->cursor += \strlen($text); + $this->lineno += substr_count($text, "\n"); + } + + protected function getOperatorRegex() + { + $operators = array_merge( + ['='], + array_keys($this->env->getUnaryOperators()), + array_keys($this->env->getBinaryOperators()) + ); + + $operators = array_combine($operators, array_map('strlen', $operators)); + arsort($operators); + + $regex = []; + foreach ($operators as $operator => $length) { + // an operator that ends with a character must be followed by + // a whitespace or a parenthesis + if (ctype_alpha($operator[$length - 1])) { + $r = preg_quote($operator, '/').'(?=[\s()])'; + } else { + $r = preg_quote($operator, '/'); + } + + // an operator with a space can be any amount of whitespaces + $r = preg_replace('/\s+/', '\s+', $r); + + $regex[] = $r; + } + + return '/'.implode('|', $regex).'/A'; + } + + protected function pushState($state) + { + $this->states[] = $this->state; + $this->state = $state; + } + + protected function popState() + { + if (0 === \count($this->states)) { + throw new \LogicException('Cannot pop state without a previous state.'); + } + + $this->state = array_pop($this->states); } } + +class_alias('Twig\Lexer', 'Twig_Lexer'); diff --git a/vendor/twig/twig/src/Loader/ArrayLoader.php b/vendor/twig/twig/src/Loader/ArrayLoader.php index 9f5de3c7ed27f9e34eae20bb5dac1d3cf17d2611..6bc430f50e4b64cba6b5f3dc7413ab09bedda0a2 100644 --- a/vendor/twig/twig/src/Loader/ArrayLoader.php +++ b/vendor/twig/twig/src/Loader/ArrayLoader.php @@ -1,11 +1,102 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\Loader; -class_exists('Twig_Loader_Array'); +use Twig\Error\LoaderError; +use Twig\Source; + +/** + * Loads a template from an array. + * + * When using this loader with a cache mechanism, you should know that a new cache + * key is generated each time a template content "changes" (the cache key being the + * source code of the template). If you don't want to see your cache grows out of + * control, you need to take care of clearing the old cache file by yourself. + * + * This loader should only be used for unit testing. + * + * @final + * + * @author Fabien Potencier <fabien@symfony.com> + */ +class ArrayLoader implements LoaderInterface, ExistsLoaderInterface, SourceContextLoaderInterface +{ + protected $templates = []; + + /** + * @param array $templates An array of templates (keys are the names, and values are the source code) + */ + public function __construct(array $templates = []) + { + $this->templates = $templates; + } + + /** + * Adds or overrides a template. + * + * @param string $name The template name + * @param string $template The template source + */ + public function setTemplate($name, $template) + { + $this->templates[(string) $name] = $template; + } + + public function getSource($name) + { + @trigger_error(sprintf('Calling "getSource" on "%s" is deprecated since 1.27. Use getSourceContext() instead.', \get_class($this)), E_USER_DEPRECATED); + + $name = (string) $name; + if (!isset($this->templates[$name])) { + throw new LoaderError(sprintf('Template "%s" is not defined.', $name)); + } + + return $this->templates[$name]; + } + + public function getSourceContext($name) + { + $name = (string) $name; + if (!isset($this->templates[$name])) { + throw new LoaderError(sprintf('Template "%s" is not defined.', $name)); + } + + return new Source($this->templates[$name], $name); + } -if (\false) { - class ArrayLoader extends \Twig_Loader_Array + public function exists($name) { + return isset($this->templates[(string) $name]); + } + + public function getCacheKey($name) + { + $name = (string) $name; + if (!isset($this->templates[$name])) { + throw new LoaderError(sprintf('Template "%s" is not defined.', $name)); + } + + return $name.':'.$this->templates[$name]; + } + + public function isFresh($name, $time) + { + $name = (string) $name; + if (!isset($this->templates[$name])) { + throw new LoaderError(sprintf('Template "%s" is not defined.', $name)); + } + + return true; } } + +class_alias('Twig\Loader\ArrayLoader', 'Twig_Loader_Array'); diff --git a/vendor/twig/twig/src/Loader/ChainLoader.php b/vendor/twig/twig/src/Loader/ChainLoader.php index 396eca525fc0b58294612675ec5b2f93dbd00a2e..25ac55a335b82e7455e3417475914e8e89a97d3f 100644 --- a/vendor/twig/twig/src/Loader/ChainLoader.php +++ b/vendor/twig/twig/src/Loader/ChainLoader.php @@ -1,11 +1,164 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\Loader; -class_exists('Twig_Loader_Chain'); +use Twig\Error\LoaderError; +use Twig\Source; + +/** + * Loads templates from other loaders. + * + * @final + * + * @author Fabien Potencier <fabien@symfony.com> + */ +class ChainLoader implements LoaderInterface, ExistsLoaderInterface, SourceContextLoaderInterface +{ + private $hasSourceCache = []; + protected $loaders = []; + + /** + * @param LoaderInterface[] $loaders + */ + public function __construct(array $loaders = []) + { + foreach ($loaders as $loader) { + $this->addLoader($loader); + } + } + + public function addLoader(LoaderInterface $loader) + { + $this->loaders[] = $loader; + $this->hasSourceCache = []; + } + + /** + * @return LoaderInterface[] + */ + public function getLoaders() + { + return $this->loaders; + } + + public function getSource($name) + { + @trigger_error(sprintf('Calling "getSource" on "%s" is deprecated since 1.27. Use getSourceContext() instead.', \get_class($this)), E_USER_DEPRECATED); + + $exceptions = []; + foreach ($this->loaders as $loader) { + if ($loader instanceof ExistsLoaderInterface && !$loader->exists($name)) { + continue; + } + + try { + return $loader->getSource($name); + } catch (LoaderError $e) { + $exceptions[] = $e->getMessage(); + } + } + + throw new LoaderError(sprintf('Template "%s" is not defined%s.', $name, $exceptions ? ' ('.implode(', ', $exceptions).')' : '')); + } + + public function getSourceContext($name) + { + $exceptions = []; + foreach ($this->loaders as $loader) { + if ($loader instanceof ExistsLoaderInterface && !$loader->exists($name)) { + continue; + } + + try { + if ($loader instanceof SourceContextLoaderInterface) { + return $loader->getSourceContext($name); + } -if (\false) { - class ChainLoader extends \Twig_Loader_Chain + return new Source($loader->getSource($name), $name); + } catch (LoaderError $e) { + $exceptions[] = $e->getMessage(); + } + } + + throw new LoaderError(sprintf('Template "%s" is not defined%s.', $name, $exceptions ? ' ('.implode(', ', $exceptions).')' : '')); + } + + public function exists($name) + { + $name = (string) $name; + + if (isset($this->hasSourceCache[$name])) { + return $this->hasSourceCache[$name]; + } + + foreach ($this->loaders as $loader) { + if ($loader instanceof ExistsLoaderInterface) { + if ($loader->exists($name)) { + return $this->hasSourceCache[$name] = true; + } + + continue; + } + + try { + if ($loader instanceof SourceContextLoaderInterface) { + $loader->getSourceContext($name); + } else { + $loader->getSource($name); + } + + return $this->hasSourceCache[$name] = true; + } catch (LoaderError $e) { + } + } + + return $this->hasSourceCache[$name] = false; + } + + public function getCacheKey($name) + { + $exceptions = []; + foreach ($this->loaders as $loader) { + if ($loader instanceof ExistsLoaderInterface && !$loader->exists($name)) { + continue; + } + + try { + return $loader->getCacheKey($name); + } catch (LoaderError $e) { + $exceptions[] = \get_class($loader).': '.$e->getMessage(); + } + } + + throw new LoaderError(sprintf('Template "%s" is not defined%s.', $name, $exceptions ? ' ('.implode(', ', $exceptions).')' : '')); + } + + public function isFresh($name, $time) { + $exceptions = []; + foreach ($this->loaders as $loader) { + if ($loader instanceof ExistsLoaderInterface && !$loader->exists($name)) { + continue; + } + + try { + return $loader->isFresh($name, $time); + } catch (LoaderError $e) { + $exceptions[] = \get_class($loader).': '.$e->getMessage(); + } + } + + throw new LoaderError(sprintf('Template "%s" is not defined%s.', $name, $exceptions ? ' ('.implode(', ', $exceptions).')' : '')); } } + +class_alias('Twig\Loader\ChainLoader', 'Twig_Loader_Chain'); diff --git a/vendor/twig/twig/src/Loader/ExistsLoaderInterface.php b/vendor/twig/twig/src/Loader/ExistsLoaderInterface.php index e533d4b24195e0d2a0b892917b48e1fa5b31051d..940d87618c6c45a863a267653bdd4c254f9c0372 100644 --- a/vendor/twig/twig/src/Loader/ExistsLoaderInterface.php +++ b/vendor/twig/twig/src/Loader/ExistsLoaderInterface.php @@ -1,11 +1,33 @@ <?php -namespace Twig\Loader; +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ -class_exists('Twig_ExistsLoaderInterface'); +namespace Twig\Loader; -if (\false) { - interface ExistsLoaderInterface extends \Twig_ExistsLoaderInterface - { - } +/** + * Adds an exists() method for loaders. + * + * @author Florin Patan <florinpatan@gmail.com> + * + * @deprecated since 1.12 (to be removed in 3.0) + */ +interface ExistsLoaderInterface +{ + /** + * Check if we have the source code of a template, given its name. + * + * @param string $name The name of the template to check if we can load + * + * @return bool If the template source code is handled by this loader or not + */ + public function exists($name); } + +class_alias('Twig\Loader\ExistsLoaderInterface', 'Twig_ExistsLoaderInterface'); diff --git a/vendor/twig/twig/src/Loader/FilesystemLoader.php b/vendor/twig/twig/src/Loader/FilesystemLoader.php index 83e8833f7d08775d790c22d44b45c13bbcc69002..19b43a2954955c391edc691af1dd503f83ab9612 100644 --- a/vendor/twig/twig/src/Loader/FilesystemLoader.php +++ b/vendor/twig/twig/src/Loader/FilesystemLoader.php @@ -1,11 +1,323 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\Loader; -class_exists('Twig_Loader_Filesystem'); +use Twig\Error\LoaderError; +use Twig\Source; + +/** + * Loads template from the filesystem. + * + * @author Fabien Potencier <fabien@symfony.com> + */ +class FilesystemLoader implements LoaderInterface, ExistsLoaderInterface, SourceContextLoaderInterface +{ + /** Identifier of the main namespace. */ + const MAIN_NAMESPACE = '__main__'; + + protected $paths = []; + protected $cache = []; + protected $errorCache = []; + + private $rootPath; + + /** + * @param string|array $paths A path or an array of paths where to look for templates + * @param string|null $rootPath The root path common to all relative paths (null for getcwd()) + */ + public function __construct($paths = [], $rootPath = null) + { + $this->rootPath = (null === $rootPath ? getcwd() : $rootPath).\DIRECTORY_SEPARATOR; + if (false !== $realPath = realpath($rootPath)) { + $this->rootPath = $realPath.\DIRECTORY_SEPARATOR; + } + + if ($paths) { + $this->setPaths($paths); + } + } + + /** + * Returns the paths to the templates. + * + * @param string $namespace A path namespace + * + * @return array The array of paths where to look for templates + */ + public function getPaths($namespace = self::MAIN_NAMESPACE) + { + return isset($this->paths[$namespace]) ? $this->paths[$namespace] : []; + } + + /** + * Returns the path namespaces. + * + * The main namespace is always defined. + * + * @return array The array of defined namespaces + */ + public function getNamespaces() + { + return array_keys($this->paths); + } -if (\false) { - class FilesystemLoader extends \Twig_Loader_Filesystem + /** + * Sets the paths where templates are stored. + * + * @param string|array $paths A path or an array of paths where to look for templates + * @param string $namespace A path namespace + */ + public function setPaths($paths, $namespace = self::MAIN_NAMESPACE) { + if (!\is_array($paths)) { + $paths = [$paths]; + } + + $this->paths[$namespace] = []; + foreach ($paths as $path) { + $this->addPath($path, $namespace); + } + } + + /** + * Adds a path where templates are stored. + * + * @param string $path A path where to look for templates + * @param string $namespace A path namespace + * + * @throws LoaderError + */ + public function addPath($path, $namespace = self::MAIN_NAMESPACE) + { + // invalidate the cache + $this->cache = $this->errorCache = []; + + $checkPath = $this->isAbsolutePath($path) ? $path : $this->rootPath.$path; + if (!is_dir($checkPath)) { + throw new LoaderError(sprintf('The "%s" directory does not exist ("%s").', $path, $checkPath)); + } + + $this->paths[$namespace][] = rtrim($path, '/\\'); + } + + /** + * Prepends a path where templates are stored. + * + * @param string $path A path where to look for templates + * @param string $namespace A path namespace + * + * @throws LoaderError + */ + public function prependPath($path, $namespace = self::MAIN_NAMESPACE) + { + // invalidate the cache + $this->cache = $this->errorCache = []; + + $checkPath = $this->isAbsolutePath($path) ? $path : $this->rootPath.$path; + if (!is_dir($checkPath)) { + throw new LoaderError(sprintf('The "%s" directory does not exist ("%s").', $path, $checkPath)); + } + + $path = rtrim($path, '/\\'); + + if (!isset($this->paths[$namespace])) { + $this->paths[$namespace][] = $path; + } else { + array_unshift($this->paths[$namespace], $path); + } + } + + public function getSource($name) + { + @trigger_error(sprintf('Calling "getSource" on "%s" is deprecated since 1.27. Use getSourceContext() instead.', \get_class($this)), E_USER_DEPRECATED); + + if (null === ($path = $this->findTemplate($name)) || false === $path) { + return ''; + } + + return file_get_contents($path); + } + + public function getSourceContext($name) + { + if (null === ($path = $this->findTemplate($name)) || false === $path) { + return new Source('', $name, ''); + } + + return new Source(file_get_contents($path), $name, $path); + } + + public function getCacheKey($name) + { + if (null === ($path = $this->findTemplate($name)) || false === $path) { + return ''; + } + $len = \strlen($this->rootPath); + if (0 === strncmp($this->rootPath, $path, $len)) { + return substr($path, $len); + } + + return $path; + } + + public function exists($name) + { + $name = $this->normalizeName($name); + + if (isset($this->cache[$name])) { + return true; + } + + try { + return null !== ($path = $this->findTemplate($name, false)) && false !== $path; + } catch (LoaderError $e) { + @trigger_error(sprintf('In %s::findTemplate(), you must accept a second argument that when set to "false" returns "false" instead of throwing an exception. Not supporting this argument is deprecated since version 1.27.', \get_class($this)), E_USER_DEPRECATED); + + return false; + } + } + + public function isFresh($name, $time) + { + // false support to be removed in 3.0 + if (null === ($path = $this->findTemplate($name)) || false === $path) { + return false; + } + + return filemtime($path) < $time; + } + + /** + * Checks if the template can be found. + * + * @param string $name The template name + * + * @return string|false|null The template name or false/null + */ + protected function findTemplate($name) + { + $throw = \func_num_args() > 1 ? func_get_arg(1) : true; + $name = $this->normalizeName($name); + + if (isset($this->cache[$name])) { + return $this->cache[$name]; + } + + if (isset($this->errorCache[$name])) { + if (!$throw) { + return false; + } + + throw new LoaderError($this->errorCache[$name]); + } + + try { + $this->validateName($name); + + list($namespace, $shortname) = $this->parseName($name); + } catch (LoaderError $e) { + if (!$throw) { + return false; + } + + throw $e; + } + + if (!isset($this->paths[$namespace])) { + $this->errorCache[$name] = sprintf('There are no registered paths for namespace "%s".', $namespace); + + if (!$throw) { + return false; + } + + throw new LoaderError($this->errorCache[$name]); + } + + foreach ($this->paths[$namespace] as $path) { + if (!$this->isAbsolutePath($path)) { + $path = $this->rootPath.$path; + } + + if (is_file($path.'/'.$shortname)) { + if (false !== $realpath = realpath($path.'/'.$shortname)) { + return $this->cache[$name] = $realpath; + } + + return $this->cache[$name] = $path.'/'.$shortname; + } + } + + $this->errorCache[$name] = sprintf('Unable to find template "%s" (looked into: %s).', $name, implode(', ', $this->paths[$namespace])); + + if (!$throw) { + return false; + } + + throw new LoaderError($this->errorCache[$name]); + } + + protected function parseName($name, $default = self::MAIN_NAMESPACE) + { + if (isset($name[0]) && '@' == $name[0]) { + if (false === $pos = strpos($name, '/')) { + throw new LoaderError(sprintf('Malformed namespaced template name "%s" (expecting "@namespace/template_name").', $name)); + } + + $namespace = substr($name, 1, $pos - 1); + $shortname = substr($name, $pos + 1); + + return [$namespace, $shortname]; + } + + return [$default, $name]; + } + + protected function normalizeName($name) + { + return preg_replace('#/{2,}#', '/', str_replace('\\', '/', (string) $name)); + } + + protected function validateName($name) + { + if (false !== strpos($name, "\0")) { + throw new LoaderError('A template name cannot contain NUL bytes.'); + } + + $name = ltrim($name, '/'); + $parts = explode('/', $name); + $level = 0; + foreach ($parts as $part) { + if ('..' === $part) { + --$level; + } elseif ('.' !== $part) { + ++$level; + } + + if ($level < 0) { + throw new LoaderError(sprintf('Looks like you try to load a template outside configured directories (%s).', $name)); + } + } + } + + private function isAbsolutePath($file) + { + return strspn($file, '/\\', 0, 1) + || (\strlen($file) > 3 && ctype_alpha($file[0]) + && ':' === substr($file, 1, 1) + && strspn($file, '/\\', 2, 1) + ) + || null !== parse_url($file, PHP_URL_SCHEME) + ; } } + +class_alias('Twig\Loader\FilesystemLoader', 'Twig_Loader_Filesystem'); diff --git a/vendor/twig/twig/src/Loader/LoaderInterface.php b/vendor/twig/twig/src/Loader/LoaderInterface.php index 67c331e6c6e331e57aa236f8253d60702fcab049..15be7a88cd00b075bcbb44d1233d69df98be2609 100644 --- a/vendor/twig/twig/src/Loader/LoaderInterface.php +++ b/vendor/twig/twig/src/Loader/LoaderInterface.php @@ -1,11 +1,61 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\Loader; -class_exists('Twig_LoaderInterface'); +use Twig\Error\LoaderError; + +/** + * Interface all loaders must implement. + * + * @author Fabien Potencier <fabien@symfony.com> + */ +interface LoaderInterface +{ + /** + * Gets the source code of a template, given its name. + * + * @param string $name The name of the template to load + * + * @return string The template source code + * + * @throws LoaderError When $name is not found + * + * @deprecated since 1.27 (to be removed in 2.0), implement Twig\Loader\SourceContextLoaderInterface + */ + public function getSource($name); -if (\false) { - interface LoaderInterface extends \Twig_LoaderInterface - { - } + /** + * Gets the cache key to use for the cache for a given template name. + * + * @param string $name The name of the template to load + * + * @return string The cache key + * + * @throws LoaderError When $name is not found + */ + public function getCacheKey($name); + + /** + * Returns true if the template is still fresh. + * + * @param string $name The template name + * @param int $time Timestamp of the last modification time of the + * cached template + * + * @return bool true if the template is fresh, false otherwise + * + * @throws LoaderError When $name is not found + */ + public function isFresh($name, $time); } + +class_alias('Twig\Loader\LoaderInterface', 'Twig_LoaderInterface'); diff --git a/vendor/twig/twig/src/Loader/SourceContextLoaderInterface.php b/vendor/twig/twig/src/Loader/SourceContextLoaderInterface.php index 4444f8082a49e8fa727586cbf51e149e50313a4a..78b1fcd40e480c0bb9861bf770bf123d8fdc5866 100644 --- a/vendor/twig/twig/src/Loader/SourceContextLoaderInterface.php +++ b/vendor/twig/twig/src/Loader/SourceContextLoaderInterface.php @@ -1,11 +1,38 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\Loader; -class_exists('Twig_SourceContextLoaderInterface'); +use Twig\Error\LoaderError; +use Twig\Source; -if (\false) { - interface SourceContextLoaderInterface extends \Twig_SourceContextLoaderInterface - { - } +/** + * Adds a getSourceContext() method for loaders. + * + * @author Fabien Potencier <fabien@symfony.com> + * + * @deprecated since 1.27 (to be removed in 3.0) + */ +interface SourceContextLoaderInterface +{ + /** + * Returns the source context for a given template logical name. + * + * @param string $name The template logical name + * + * @return Source + * + * @throws LoaderError When $name is not found + */ + public function getSourceContext($name); } + +class_alias('Twig\Loader\SourceContextLoaderInterface', 'Twig_SourceContextLoaderInterface'); diff --git a/vendor/twig/twig/src/Markup.php b/vendor/twig/twig/src/Markup.php index 8dad08221a5fd04c75ccd473883d4564ed6b3ecb..107941cdf71425e14a4473bcb5896f43d4ad0b05 100644 --- a/vendor/twig/twig/src/Markup.php +++ b/vendor/twig/twig/src/Markup.php @@ -1,11 +1,41 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig; -class_exists('Twig_Markup'); +/** + * Marks a content as safe. + * + * @author Fabien Potencier <fabien@symfony.com> + */ +class Markup implements \Countable +{ + protected $content; + protected $charset; + + public function __construct($content, $charset) + { + $this->content = (string) $content; + $this->charset = $charset; + } + + public function __toString() + { + return $this->content; + } -if (\false) { - class Markup extends \Twig_Markup + public function count() { + return \function_exists('mb_get_info') ? mb_strlen($this->content, $this->charset) : \strlen($this->content); } } + +class_alias('Twig\Markup', 'Twig_Markup'); diff --git a/vendor/twig/twig/src/Node/AutoEscapeNode.php b/vendor/twig/twig/src/Node/AutoEscapeNode.php index 9edb8e3da17c3b78c5e37db0f879615ed8d0fe1f..a9403066aea798e776b059abacd0755104f9d870 100644 --- a/vendor/twig/twig/src/Node/AutoEscapeNode.php +++ b/vendor/twig/twig/src/Node/AutoEscapeNode.php @@ -1,11 +1,40 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\Node; -class_exists('Twig_Node_AutoEscape'); +use Twig\Compiler; -if (\false) { - class AutoEscapeNode extends \Twig_Node_AutoEscape +/** + * Represents an autoescape node. + * + * The value is the escaping strategy (can be html, js, ...) + * + * The true value is equivalent to html. + * + * If autoescaping is disabled, then the value is false. + * + * @author Fabien Potencier <fabien@symfony.com> + */ +class AutoEscapeNode extends Node +{ + public function __construct($value, \Twig_NodeInterface $body, $lineno, $tag = 'autoescape') { + parent::__construct(['body' => $body], ['value' => $value], $lineno, $tag); + } + + public function compile(Compiler $compiler) + { + $compiler->subcompile($this->getNode('body')); } } + +class_alias('Twig\Node\AutoEscapeNode', 'Twig_Node_AutoEscape'); diff --git a/vendor/twig/twig/src/Node/BlockNode.php b/vendor/twig/twig/src/Node/BlockNode.php index 27e30f98357ad944262252a30365c4e97ba3df3f..1ffc8ca78a60c73ac562a07ec63fdb489d5a757e 100644 --- a/vendor/twig/twig/src/Node/BlockNode.php +++ b/vendor/twig/twig/src/Node/BlockNode.php @@ -1,11 +1,45 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * (c) Armin Ronacher + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\Node; -class_exists('Twig_Node_Block'); +use Twig\Compiler; + +/** + * Represents a block node. + * + * @author Fabien Potencier <fabien@symfony.com> + */ +class BlockNode extends Node +{ + public function __construct($name, \Twig_NodeInterface $body, $lineno, $tag = null) + { + parent::__construct(['body' => $body], ['name' => $name], $lineno, $tag); + } -if (\false) { - class BlockNode extends \Twig_Node_Block + public function compile(Compiler $compiler) { + $compiler + ->addDebugInfo($this) + ->write(sprintf("public function block_%s(\$context, array \$blocks = [])\n", $this->getAttribute('name')), "{\n") + ->indent() + ; + + $compiler + ->subcompile($this->getNode('body')) + ->outdent() + ->write("}\n\n") + ; } } + +class_alias('Twig\Node\BlockNode', 'Twig_Node_Block'); diff --git a/vendor/twig/twig/src/Node/BlockReferenceNode.php b/vendor/twig/twig/src/Node/BlockReferenceNode.php index 87bdd1f93de2527b2b83832d79ee49a93ac1751e..de069093f6611daabfc4e162405c2f6d31a64d31 100644 --- a/vendor/twig/twig/src/Node/BlockReferenceNode.php +++ b/vendor/twig/twig/src/Node/BlockReferenceNode.php @@ -1,11 +1,38 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * (c) Armin Ronacher + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\Node; -class_exists('Twig_Node_BlockReference'); +use Twig\Compiler; -if (\false) { - class BlockReferenceNode extends \Twig_Node_BlockReference +/** + * Represents a block call node. + * + * @author Fabien Potencier <fabien@symfony.com> + */ +class BlockReferenceNode extends Node implements NodeOutputInterface +{ + public function __construct($name, $lineno, $tag = null) { + parent::__construct([], ['name' => $name], $lineno, $tag); + } + + public function compile(Compiler $compiler) + { + $compiler + ->addDebugInfo($this) + ->write(sprintf("\$this->displayBlock('%s', \$context, \$blocks);\n", $this->getAttribute('name'))) + ; } } + +class_alias('Twig\Node\BlockReferenceNode', 'Twig_Node_BlockReference'); diff --git a/vendor/twig/twig/src/Node/BodyNode.php b/vendor/twig/twig/src/Node/BodyNode.php index 013bda3b506079dfe5dbfcd939433fa3c714c457..5290be56db6739abb0bd41032300c18f4d4cfa58 100644 --- a/vendor/twig/twig/src/Node/BodyNode.php +++ b/vendor/twig/twig/src/Node/BodyNode.php @@ -1,11 +1,23 @@ <?php -namespace Twig\Node; +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ -class_exists('Twig_Node_Body'); +namespace Twig\Node; -if (\false) { - class BodyNode extends \Twig_Node_Body - { - } +/** + * Represents a body node. + * + * @author Fabien Potencier <fabien@symfony.com> + */ +class BodyNode extends Node +{ } + +class_alias('Twig\Node\BodyNode', 'Twig_Node_Body'); diff --git a/vendor/twig/twig/src/Node/CheckSecurityNode.php b/vendor/twig/twig/src/Node/CheckSecurityNode.php index 6510086baf8c3e7b7d5cc92aa0a9fedd37b56904..cf0a7a13d8acd376a04111386241551e3b30c252 100644 --- a/vendor/twig/twig/src/Node/CheckSecurityNode.php +++ b/vendor/twig/twig/src/Node/CheckSecurityNode.php @@ -1,11 +1,85 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\Node; -class_exists('Twig_Node_CheckSecurity'); +use Twig\Compiler; + +/** + * @author Fabien Potencier <fabien@symfony.com> + */ +class CheckSecurityNode extends Node +{ + protected $usedFilters; + protected $usedTags; + protected $usedFunctions; + + public function __construct(array $usedFilters, array $usedTags, array $usedFunctions) + { + $this->usedFilters = $usedFilters; + $this->usedTags = $usedTags; + $this->usedFunctions = $usedFunctions; + + parent::__construct(); + } -if (\false) { - class CheckSecurityNode extends \Twig_Node_CheckSecurity + public function compile(Compiler $compiler) { + $tags = $filters = $functions = []; + foreach (['tags', 'filters', 'functions'] as $type) { + foreach ($this->{'used'.ucfirst($type)} as $name => $node) { + if ($node instanceof Node) { + ${$type}[$name] = $node->getTemplateLine(); + } else { + ${$type}[$node] = null; + } + } + } + + $compiler + ->write("\$this->sandbox = \$this->env->getExtension('\Twig\Extension\SandboxExtension');\n") + ->write('$tags = ')->repr(array_filter($tags))->raw(";\n") + ->write('$filters = ')->repr(array_filter($filters))->raw(";\n") + ->write('$functions = ')->repr(array_filter($functions))->raw(";\n\n") + ->write("try {\n") + ->indent() + ->write("\$this->sandbox->checkSecurity(\n") + ->indent() + ->write(!$tags ? "[],\n" : "['".implode("', '", array_keys($tags))."'],\n") + ->write(!$filters ? "[],\n" : "['".implode("', '", array_keys($filters))."'],\n") + ->write(!$functions ? "[]\n" : "['".implode("', '", array_keys($functions))."']\n") + ->outdent() + ->write(");\n") + ->outdent() + ->write("} catch (SecurityError \$e) {\n") + ->indent() + ->write("\$e->setSourceContext(\$this->getSourceContext());\n\n") + ->write("if (\$e instanceof SecurityNotAllowedTagError && isset(\$tags[\$e->getTagName()])) {\n") + ->indent() + ->write("\$e->setTemplateLine(\$tags[\$e->getTagName()]);\n") + ->outdent() + ->write("} elseif (\$e instanceof SecurityNotAllowedFilterError && isset(\$filters[\$e->getFilterName()])) {\n") + ->indent() + ->write("\$e->setTemplateLine(\$filters[\$e->getFilterName()]);\n") + ->outdent() + ->write("} elseif (\$e instanceof SecurityNotAllowedFunctionError && isset(\$functions[\$e->getFunctionName()])) {\n") + ->indent() + ->write("\$e->setTemplateLine(\$functions[\$e->getFunctionName()]);\n") + ->outdent() + ->write("}\n\n") + ->write("throw \$e;\n") + ->outdent() + ->write("}\n\n") + ; } } + +class_alias('Twig\Node\CheckSecurityNode', 'Twig_Node_CheckSecurity'); diff --git a/vendor/twig/twig/src/Node/CheckToStringNode.php b/vendor/twig/twig/src/Node/CheckToStringNode.php new file mode 100644 index 0000000000000000000000000000000000000000..5d67467916eef2a34f76180701505f2b6e17a4b9 --- /dev/null +++ b/vendor/twig/twig/src/Node/CheckToStringNode.php @@ -0,0 +1,42 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Twig\Node; + +use Twig\Compiler; +use Twig\Node\Expression\AbstractExpression; + +/** + * Checks if casting an expression to __toString() is allowed by the sandbox. + * + * For instance, when there is a simple Print statement, like {{ article }}, + * and if the sandbox is enabled, we need to check that the __toString() + * method is allowed if 'article' is an object. The same goes for {{ article|upper }} + * or {{ random(article) }} + * + * @author Fabien Potencier <fabien@symfony.com> + */ +class CheckToStringNode extends AbstractExpression +{ + public function __construct(AbstractExpression $expr) + { + parent::__construct(['expr' => $expr], [], $expr->getTemplateLine(), $expr->getNodeTag()); + } + + public function compile(Compiler $compiler) + { + $compiler + ->raw('$this->sandbox->ensureToStringAllowed(') + ->subcompile($this->getNode('expr')) + ->raw(')') + ; + } +} diff --git a/vendor/twig/twig/src/Node/DeprecatedNode.php b/vendor/twig/twig/src/Node/DeprecatedNode.php new file mode 100644 index 0000000000000000000000000000000000000000..62c0dd4ba51ab61cea0295a4c46e65806c687901 --- /dev/null +++ b/vendor/twig/twig/src/Node/DeprecatedNode.php @@ -0,0 +1,55 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Twig\Node; + +use Twig\Compiler; +use Twig\Node\Expression\AbstractExpression; +use Twig\Node\Expression\ConstantExpression; + +/** + * Represents a deprecated node. + * + * @author Yonel Ceruto <yonelceruto@gmail.com> + */ +class DeprecatedNode extends Node +{ + public function __construct(AbstractExpression $expr, $lineno, $tag = null) + { + parent::__construct(['expr' => $expr], [], $lineno, $tag); + } + + public function compile(Compiler $compiler) + { + $compiler->addDebugInfo($this); + + $expr = $this->getNode('expr'); + + if ($expr instanceof ConstantExpression) { + $compiler->write('@trigger_error(') + ->subcompile($expr); + } else { + $varName = $compiler->getVarName(); + $compiler->write(sprintf('$%s = ', $varName)) + ->subcompile($expr) + ->raw(";\n") + ->write(sprintf('@trigger_error($%s', $varName)); + } + + $compiler + ->raw('.') + ->string(sprintf(' ("%s" at line %d).', $this->getTemplateName(), $this->getTemplateLine())) + ->raw(", E_USER_DEPRECATED);\n") + ; + } +} + +class_alias('Twig\Node\DeprecatedNode', 'Twig_Node_Deprecated'); diff --git a/vendor/twig/twig/src/Node/DoNode.php b/vendor/twig/twig/src/Node/DoNode.php index 1a972ff35557aa4c1ede6ed4d149657a130d21c6..80c4cea79ec3b914d3297595011012cc98f4f9a8 100644 --- a/vendor/twig/twig/src/Node/DoNode.php +++ b/vendor/twig/twig/src/Node/DoNode.php @@ -1,11 +1,40 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\Node; -class_exists('Twig_Node_Do'); +use Twig\Compiler; +use Twig\Node\Expression\AbstractExpression; -if (\false) { - class DoNode extends \Twig_Node_Do +/** + * Represents a do node. + * + * @author Fabien Potencier <fabien@symfony.com> + */ +class DoNode extends Node +{ + public function __construct(AbstractExpression $expr, $lineno, $tag = null) { + parent::__construct(['expr' => $expr], [], $lineno, $tag); + } + + public function compile(Compiler $compiler) + { + $compiler + ->addDebugInfo($this) + ->write('') + ->subcompile($this->getNode('expr')) + ->raw(";\n") + ; } } + +class_alias('Twig\Node\DoNode', 'Twig_Node_Do'); diff --git a/vendor/twig/twig/src/Node/EmbedNode.php b/vendor/twig/twig/src/Node/EmbedNode.php index 960942393e10bf9ff46c39cdb26bba8b2dea3090..05051ecec8a92d854ea52175fce55967fe928100 100644 --- a/vendor/twig/twig/src/Node/EmbedNode.php +++ b/vendor/twig/twig/src/Node/EmbedNode.php @@ -1,11 +1,52 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\Node; -class_exists('Twig_Node_Embed'); +use Twig\Compiler; +use Twig\Node\Expression\AbstractExpression; +use Twig\Node\Expression\ConstantExpression; + +/** + * Represents an embed node. + * + * @author Fabien Potencier <fabien@symfony.com> + */ +class EmbedNode extends IncludeNode +{ + // we don't inject the module to avoid node visitors to traverse it twice (as it will be already visited in the main module) + public function __construct($name, $index, AbstractExpression $variables = null, $only = false, $ignoreMissing = false, $lineno, $tag = null) + { + parent::__construct(new ConstantExpression('not_used', $lineno), $variables, $only, $ignoreMissing, $lineno, $tag); + + $this->setAttribute('name', $name); + // to be removed in 2.0, used name instead + $this->setAttribute('filename', $name); + $this->setAttribute('index', $index); + } -if (\false) { - class EmbedNode extends \Twig_Node_Embed + protected function addGetTemplate(Compiler $compiler) { + $compiler + ->write('$this->loadTemplate(') + ->string($this->getAttribute('name')) + ->raw(', ') + ->repr($this->getTemplateName()) + ->raw(', ') + ->repr($this->getTemplateLine()) + ->raw(', ') + ->string($this->getAttribute('index')) + ->raw(')') + ; } } + +class_alias('Twig\Node\EmbedNode', 'Twig_Node_Embed'); diff --git a/vendor/twig/twig/src/Node/Expression/AbstractExpression.php b/vendor/twig/twig/src/Node/Expression/AbstractExpression.php index 1fdbea85e799c761198d98322721cfa5626ec49e..a3528924ca044c8f00f15279221570a3d20dfd62 100644 --- a/vendor/twig/twig/src/Node/Expression/AbstractExpression.php +++ b/vendor/twig/twig/src/Node/Expression/AbstractExpression.php @@ -1,11 +1,26 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * (c) Armin Ronacher + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\Node\Expression; -class_exists('Twig_Node_Expression'); +use Twig\Node\Node; -if (\false) { - class AbstractExpression extends \Twig_Node_Expression - { - } +/** + * Abstract class for all nodes that represents an expression. + * + * @author Fabien Potencier <fabien@symfony.com> + */ +abstract class AbstractExpression extends Node +{ } + +class_alias('Twig\Node\Expression\AbstractExpression', 'Twig_Node_Expression'); diff --git a/vendor/twig/twig/src/Node/Expression/ArrayExpression.php b/vendor/twig/twig/src/Node/Expression/ArrayExpression.php index c408657965db08811d085a073171242b24c3b030..cd63f934e4febdcb75680fe551af61927e5453e1 100644 --- a/vendor/twig/twig/src/Node/Expression/ArrayExpression.php +++ b/vendor/twig/twig/src/Node/Expression/ArrayExpression.php @@ -1,11 +1,88 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\Node\Expression; -class_exists('Twig_Node_Expression_Array'); +use Twig\Compiler; + +class ArrayExpression extends AbstractExpression +{ + protected $index; -if (\false) { - class ArrayExpression extends \Twig_Node_Expression_Array + public function __construct(array $elements, $lineno) { + parent::__construct($elements, [], $lineno); + + $this->index = -1; + foreach ($this->getKeyValuePairs() as $pair) { + if ($pair['key'] instanceof ConstantExpression && ctype_digit((string) $pair['key']->getAttribute('value')) && $pair['key']->getAttribute('value') > $this->index) { + $this->index = $pair['key']->getAttribute('value'); + } + } + } + + public function getKeyValuePairs() + { + $pairs = []; + + foreach (array_chunk($this->nodes, 2) as $pair) { + $pairs[] = [ + 'key' => $pair[0], + 'value' => $pair[1], + ]; + } + + return $pairs; + } + + public function hasElement(AbstractExpression $key) + { + foreach ($this->getKeyValuePairs() as $pair) { + // we compare the string representation of the keys + // to avoid comparing the line numbers which are not relevant here. + if ((string) $key === (string) $pair['key']) { + return true; + } + } + + return false; + } + + public function addElement(AbstractExpression $value, AbstractExpression $key = null) + { + if (null === $key) { + $key = new ConstantExpression(++$this->index, $value->getTemplateLine()); + } + + array_push($this->nodes, $key, $value); + } + + public function compile(Compiler $compiler) + { + $compiler->raw('['); + $first = true; + foreach ($this->getKeyValuePairs() as $pair) { + if (!$first) { + $compiler->raw(', '); + } + $first = false; + + $compiler + ->subcompile($pair['key']) + ->raw(' => ') + ->subcompile($pair['value']) + ; + } + $compiler->raw(']'); } } + +class_alias('Twig\Node\Expression\ArrayExpression', 'Twig_Node_Expression_Array'); diff --git a/vendor/twig/twig/src/Node/Expression/ArrowFunctionExpression.php b/vendor/twig/twig/src/Node/Expression/ArrowFunctionExpression.php new file mode 100644 index 0000000000000000000000000000000000000000..36b77da86f58d913b727de91feebc991f9c2d7ac --- /dev/null +++ b/vendor/twig/twig/src/Node/Expression/ArrowFunctionExpression.php @@ -0,0 +1,64 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Twig\Node\Expression; + +use Twig\Compiler; +use Twig\Node\Node; + +/** + * Represents an arrow function. + * + * @author Fabien Potencier <fabien@symfony.com> + */ +class ArrowFunctionExpression extends AbstractExpression +{ + public function __construct(AbstractExpression $expr, Node $names, $lineno, $tag = null) + { + parent::__construct(['expr' => $expr, 'names' => $names], [], $lineno, $tag); + } + + public function compile(Compiler $compiler) + { + $compiler + ->addDebugInfo($this) + ->raw('function (') + ; + foreach ($this->getNode('names') as $i => $name) { + if ($i) { + $compiler->raw(', '); + } + + $compiler + ->raw('$__') + ->raw($name->getAttribute('name')) + ->raw('__') + ; + } + $compiler + ->raw(') use ($context) { ') + ; + foreach ($this->getNode('names') as $name) { + $compiler + ->raw('$context["') + ->raw($name->getAttribute('name')) + ->raw('"] = $__') + ->raw($name->getAttribute('name')) + ->raw('__; ') + ; + } + $compiler + ->raw('return ') + ->subcompile($this->getNode('expr')) + ->raw('; }') + ; + } +} diff --git a/vendor/twig/twig/src/Node/Expression/AssignNameExpression.php b/vendor/twig/twig/src/Node/Expression/AssignNameExpression.php index f1cd3a1a8446b627fd3b812498dcadc818fdcffb..62c4ac0b48fbeb696df55a12a8b6c90581b57315 100644 --- a/vendor/twig/twig/src/Node/Expression/AssignNameExpression.php +++ b/vendor/twig/twig/src/Node/Expression/AssignNameExpression.php @@ -1,11 +1,29 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * (c) Armin Ronacher + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\Node\Expression; -class_exists('Twig_Node_Expression_AssignName'); +use Twig\Compiler; -if (\false) { - class AssignNameExpression extends \Twig_Node_Expression_AssignName +class AssignNameExpression extends NameExpression +{ + public function compile(Compiler $compiler) { + $compiler + ->raw('$context[') + ->string($this->getAttribute('name')) + ->raw(']') + ; } } + +class_alias('Twig\Node\Expression\AssignNameExpression', 'Twig_Node_Expression_AssignName'); diff --git a/vendor/twig/twig/src/Node/Expression/Binary/AbstractBinary.php b/vendor/twig/twig/src/Node/Expression/Binary/AbstractBinary.php index 7462a8cf61053aee81d9ca289fa57d7c76da290f..0600aeedbb704438246d1b5ae04eb3ff62443de9 100644 --- a/vendor/twig/twig/src/Node/Expression/Binary/AbstractBinary.php +++ b/vendor/twig/twig/src/Node/Expression/Binary/AbstractBinary.php @@ -1,11 +1,43 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * (c) Armin Ronacher + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\Node\Expression\Binary; -class_exists('Twig_Node_Expression_Binary'); +use Twig\Compiler; +use Twig\Node\Expression\AbstractExpression; + +abstract class AbstractBinary extends AbstractExpression +{ + public function __construct(\Twig_NodeInterface $left, \Twig_NodeInterface $right, $lineno) + { + parent::__construct(['left' => $left, 'right' => $right], [], $lineno); + } -if (\false) { - class AbstractBinary extends \Twig_Node_Expression_Binary + public function compile(Compiler $compiler) { + $compiler + ->raw('(') + ->subcompile($this->getNode('left')) + ->raw(' ') + ; + $this->operator($compiler); + $compiler + ->raw(' ') + ->subcompile($this->getNode('right')) + ->raw(')') + ; } + + abstract public function operator(Compiler $compiler); } + +class_alias('Twig\Node\Expression\Binary\AbstractBinary', 'Twig_Node_Expression_Binary'); diff --git a/vendor/twig/twig/src/Node/Expression/Binary/AddBinary.php b/vendor/twig/twig/src/Node/Expression/Binary/AddBinary.php index 9bb84168b11b05cb9fec346e0cec9af40d91eafb..f7719a19ea2af51160ebaba612c7833887cfc797 100644 --- a/vendor/twig/twig/src/Node/Expression/Binary/AddBinary.php +++ b/vendor/twig/twig/src/Node/Expression/Binary/AddBinary.php @@ -1,11 +1,25 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * (c) Armin Ronacher + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\Node\Expression\Binary; -class_exists('Twig_Node_Expression_Binary_Add'); +use Twig\Compiler; -if (\false) { - class AddBinary extends \Twig_Node_Expression_Binary_Add +class AddBinary extends AbstractBinary +{ + public function operator(Compiler $compiler) { + return $compiler->raw('+'); } } + +class_alias('Twig\Node\Expression\Binary\AddBinary', 'Twig_Node_Expression_Binary_Add'); diff --git a/vendor/twig/twig/src/Node/Expression/Binary/AndBinary.php b/vendor/twig/twig/src/Node/Expression/Binary/AndBinary.php index 06034a60bac5aa1ca7196fc42fa79fc40a2b7c8a..484597da77d2407143b06bebe47e169f24641961 100644 --- a/vendor/twig/twig/src/Node/Expression/Binary/AndBinary.php +++ b/vendor/twig/twig/src/Node/Expression/Binary/AndBinary.php @@ -1,11 +1,25 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * (c) Armin Ronacher + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\Node\Expression\Binary; -class_exists('Twig_Node_Expression_Binary_And'); +use Twig\Compiler; -if (\false) { - class AndBinary extends \Twig_Node_Expression_Binary_And +class AndBinary extends AbstractBinary +{ + public function operator(Compiler $compiler) { + return $compiler->raw('&&'); } } + +class_alias('Twig\Node\Expression\Binary\AndBinary', 'Twig_Node_Expression_Binary_And'); diff --git a/vendor/twig/twig/src/Node/Expression/Binary/BitwiseAndBinary.php b/vendor/twig/twig/src/Node/Expression/Binary/BitwiseAndBinary.php index da98ce061deec48cdc2bd071d2293700fbadf367..cf286912b28bbfdf3b9772fb1e300f17d5c56794 100644 --- a/vendor/twig/twig/src/Node/Expression/Binary/BitwiseAndBinary.php +++ b/vendor/twig/twig/src/Node/Expression/Binary/BitwiseAndBinary.php @@ -1,11 +1,25 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * (c) Armin Ronacher + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\Node\Expression\Binary; -class_exists('Twig_Node_Expression_Binary_BitwiseAnd'); +use Twig\Compiler; -if (\false) { - class BitwiseAndBinary extends \Twig_Node_Expression_Binary_BitwiseAnd +class BitwiseAndBinary extends AbstractBinary +{ + public function operator(Compiler $compiler) { + return $compiler->raw('&'); } } + +class_alias('Twig\Node\Expression\Binary\BitwiseAndBinary', 'Twig_Node_Expression_Binary_BitwiseAnd'); diff --git a/vendor/twig/twig/src/Node/Expression/Binary/BitwiseOrBinary.php b/vendor/twig/twig/src/Node/Expression/Binary/BitwiseOrBinary.php index 16b434c4d33b938fdbb74369ce2a1a513abf881d..7d5d260079999987afc2d2ae1517875c0f3636b2 100644 --- a/vendor/twig/twig/src/Node/Expression/Binary/BitwiseOrBinary.php +++ b/vendor/twig/twig/src/Node/Expression/Binary/BitwiseOrBinary.php @@ -1,11 +1,25 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * (c) Armin Ronacher + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\Node\Expression\Binary; -class_exists('Twig_Node_Expression_Binary_BitwiseOr'); +use Twig\Compiler; -if (\false) { - class BitwiseOrBinary extends \Twig_Node_Expression_Binary_BitwiseOr +class BitwiseOrBinary extends AbstractBinary +{ + public function operator(Compiler $compiler) { + return $compiler->raw('|'); } } + +class_alias('Twig\Node\Expression\Binary\BitwiseOrBinary', 'Twig_Node_Expression_Binary_BitwiseOr'); diff --git a/vendor/twig/twig/src/Node/Expression/Binary/BitwiseXorBinary.php b/vendor/twig/twig/src/Node/Expression/Binary/BitwiseXorBinary.php index ee6a6880a89abd0e66a149f213c4fcec4f37ffb8..729198719528b97b0ab508318cd7fe2647b1eb66 100644 --- a/vendor/twig/twig/src/Node/Expression/Binary/BitwiseXorBinary.php +++ b/vendor/twig/twig/src/Node/Expression/Binary/BitwiseXorBinary.php @@ -1,11 +1,25 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * (c) Armin Ronacher + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\Node\Expression\Binary; -class_exists('Twig_Node_Expression_Binary_BitwiseXor'); +use Twig\Compiler; -if (\false) { - class BitwiseXorBinary extends \Twig_Node_Expression_Binary_BitwiseXor +class BitwiseXorBinary extends AbstractBinary +{ + public function operator(Compiler $compiler) { + return $compiler->raw('^'); } } + +class_alias('Twig\Node\Expression\Binary\BitwiseXorBinary', 'Twig_Node_Expression_Binary_BitwiseXor'); diff --git a/vendor/twig/twig/src/Node/Expression/Binary/ConcatBinary.php b/vendor/twig/twig/src/Node/Expression/Binary/ConcatBinary.php index 29dfda34082e3298dc14e80983e2494df4236ff6..f6e5938fdd1d9be7ec0fa32327901b72f9c14be3 100644 --- a/vendor/twig/twig/src/Node/Expression/Binary/ConcatBinary.php +++ b/vendor/twig/twig/src/Node/Expression/Binary/ConcatBinary.php @@ -1,11 +1,25 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * (c) Armin Ronacher + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\Node\Expression\Binary; -class_exists('Twig_Node_Expression_Binary_Concat'); +use Twig\Compiler; -if (\false) { - class ConcatBinary extends \Twig_Node_Expression_Binary_Concat +class ConcatBinary extends AbstractBinary +{ + public function operator(Compiler $compiler) { + return $compiler->raw('.'); } } + +class_alias('Twig\Node\Expression\Binary\ConcatBinary', 'Twig_Node_Expression_Binary_Concat'); diff --git a/vendor/twig/twig/src/Node/Expression/Binary/DivBinary.php b/vendor/twig/twig/src/Node/Expression/Binary/DivBinary.php index 7326bde69f7628479bd71c520b7bd98ea5de804b..ebfcc758b6576c6334448561d35bf44ec72a487d 100644 --- a/vendor/twig/twig/src/Node/Expression/Binary/DivBinary.php +++ b/vendor/twig/twig/src/Node/Expression/Binary/DivBinary.php @@ -1,11 +1,25 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * (c) Armin Ronacher + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\Node\Expression\Binary; -class_exists('Twig_Node_Expression_Binary_Div'); +use Twig\Compiler; -if (\false) { - class DivBinary extends \Twig_Node_Expression_Binary_Div +class DivBinary extends AbstractBinary +{ + public function operator(Compiler $compiler) { + return $compiler->raw('/'); } } + +class_alias('Twig\Node\Expression\Binary\DivBinary', 'Twig_Node_Expression_Binary_Div'); diff --git a/vendor/twig/twig/src/Node/Expression/Binary/EndsWithBinary.php b/vendor/twig/twig/src/Node/Expression/Binary/EndsWithBinary.php index 9845ad163b8f8937b37b1cdabfe2d51d5d2c69e2..41a0065bbc69b83b66c1b1cce3d4e03a8ccc4c20 100644 --- a/vendor/twig/twig/src/Node/Expression/Binary/EndsWithBinary.php +++ b/vendor/twig/twig/src/Node/Expression/Binary/EndsWithBinary.php @@ -1,11 +1,37 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\Node\Expression\Binary; -class_exists('Twig_Node_Expression_Binary_EndsWith'); +use Twig\Compiler; -if (\false) { - class EndsWithBinary extends \Twig_Node_Expression_Binary_EndsWith +class EndsWithBinary extends AbstractBinary +{ + public function compile(Compiler $compiler) { + $left = $compiler->getVarName(); + $right = $compiler->getVarName(); + $compiler + ->raw(sprintf('(is_string($%s = ', $left)) + ->subcompile($this->getNode('left')) + ->raw(sprintf(') && is_string($%s = ', $right)) + ->subcompile($this->getNode('right')) + ->raw(sprintf(') && (\'\' === $%2$s || $%2$s === substr($%1$s, -strlen($%2$s))))', $left, $right)) + ; + } + + public function operator(Compiler $compiler) + { + return $compiler->raw(''); } } + +class_alias('Twig\Node\Expression\Binary\EndsWithBinary', 'Twig_Node_Expression_Binary_EndsWith'); diff --git a/vendor/twig/twig/src/Node/Expression/Binary/EqualBinary.php b/vendor/twig/twig/src/Node/Expression/Binary/EqualBinary.php index 97e4889a7524127fb8ade6719ed54771b2c8f6a8..84904c364ae3000323d8b793da0d58cb36ea807a 100644 --- a/vendor/twig/twig/src/Node/Expression/Binary/EqualBinary.php +++ b/vendor/twig/twig/src/Node/Expression/Binary/EqualBinary.php @@ -1,11 +1,24 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\Node\Expression\Binary; -class_exists('Twig_Node_Expression_Binary_Equal'); +use Twig\Compiler; -if (\false) { - class EqualBinary extends \Twig_Node_Expression_Binary_Equal +class EqualBinary extends AbstractBinary +{ + public function operator(Compiler $compiler) { + return $compiler->raw('=='); } } + +class_alias('Twig\Node\Expression\Binary\EqualBinary', 'Twig_Node_Expression_Binary_Equal'); diff --git a/vendor/twig/twig/src/Node/Expression/Binary/FloorDivBinary.php b/vendor/twig/twig/src/Node/Expression/Binary/FloorDivBinary.php index 9e8676f49afc2ea574b16ce0f6713e66baeabe0e..4dd5e3d32b749cb805e9285fc9d43b692ce2efde 100644 --- a/vendor/twig/twig/src/Node/Expression/Binary/FloorDivBinary.php +++ b/vendor/twig/twig/src/Node/Expression/Binary/FloorDivBinary.php @@ -1,11 +1,31 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\Node\Expression\Binary; -class_exists('Twig_Node_Expression_Binary_FloorDiv'); +use Twig\Compiler; -if (\false) { - class FloorDivBinary extends \Twig_Node_Expression_Binary_FloorDiv +class FloorDivBinary extends AbstractBinary +{ + public function compile(Compiler $compiler) { + $compiler->raw('(int) floor('); + parent::compile($compiler); + $compiler->raw(')'); + } + + public function operator(Compiler $compiler) + { + return $compiler->raw('/'); } } + +class_alias('Twig\Node\Expression\Binary\FloorDivBinary', 'Twig_Node_Expression_Binary_FloorDiv'); diff --git a/vendor/twig/twig/src/Node/Expression/Binary/GreaterBinary.php b/vendor/twig/twig/src/Node/Expression/Binary/GreaterBinary.php index 8dde9d2a97675c800e7e76029f8fb53a230575b3..be73001e5b9ad45d4701cff4448bb705adf97f43 100644 --- a/vendor/twig/twig/src/Node/Expression/Binary/GreaterBinary.php +++ b/vendor/twig/twig/src/Node/Expression/Binary/GreaterBinary.php @@ -1,11 +1,24 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\Node\Expression\Binary; -class_exists('Twig_Node_Expression_Binary_Greater'); +use Twig\Compiler; -if (\false) { - class GreaterBinary extends \Twig_Node_Expression_Binary_Greater +class GreaterBinary extends AbstractBinary +{ + public function operator(Compiler $compiler) { + return $compiler->raw('>'); } } + +class_alias('Twig\Node\Expression\Binary\GreaterBinary', 'Twig_Node_Expression_Binary_Greater'); diff --git a/vendor/twig/twig/src/Node/Expression/Binary/GreaterEqualBinary.php b/vendor/twig/twig/src/Node/Expression/Binary/GreaterEqualBinary.php index 455f6d840efd031b79e8cf070774e13f02cd7666..5c2ae72ee23f669ffa487c3790bade772f398122 100644 --- a/vendor/twig/twig/src/Node/Expression/Binary/GreaterEqualBinary.php +++ b/vendor/twig/twig/src/Node/Expression/Binary/GreaterEqualBinary.php @@ -1,11 +1,24 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\Node\Expression\Binary; -class_exists('Twig_Node_Expression_Binary_GreaterEqual'); +use Twig\Compiler; -if (\false) { - class GreaterEqualBinary extends \Twig_Node_Expression_Binary_GreaterEqual +class GreaterEqualBinary extends AbstractBinary +{ + public function operator(Compiler $compiler) { + return $compiler->raw('>='); } } + +class_alias('Twig\Node\Expression\Binary\GreaterEqualBinary', 'Twig_Node_Expression_Binary_GreaterEqual'); diff --git a/vendor/twig/twig/src/Node/Expression/Binary/InBinary.php b/vendor/twig/twig/src/Node/Expression/Binary/InBinary.php index 3e3cf2fe3eb476169bd4b5f56c464bd2c249804a..f00b23060f8e76cabfe709e5412ac246d6db277f 100644 --- a/vendor/twig/twig/src/Node/Expression/Binary/InBinary.php +++ b/vendor/twig/twig/src/Node/Expression/Binary/InBinary.php @@ -1,11 +1,35 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\Node\Expression\Binary; -class_exists('Twig_Node_Expression_Binary_In'); +use Twig\Compiler; -if (\false) { - class InBinary extends \Twig_Node_Expression_Binary_In +class InBinary extends AbstractBinary +{ + public function compile(Compiler $compiler) { + $compiler + ->raw('twig_in_filter(') + ->subcompile($this->getNode('left')) + ->raw(', ') + ->subcompile($this->getNode('right')) + ->raw(')') + ; + } + + public function operator(Compiler $compiler) + { + return $compiler->raw('in'); } } + +class_alias('Twig\Node\Expression\Binary\InBinary', 'Twig_Node_Expression_Binary_In'); diff --git a/vendor/twig/twig/src/Node/Expression/Binary/LessBinary.php b/vendor/twig/twig/src/Node/Expression/Binary/LessBinary.php index 84bcfe6b3bba3f0a09b5e4b9c745c303aea4d3e2..2b202daa72873ebaf400349d9b152f8cbda0a6f4 100644 --- a/vendor/twig/twig/src/Node/Expression/Binary/LessBinary.php +++ b/vendor/twig/twig/src/Node/Expression/Binary/LessBinary.php @@ -1,11 +1,24 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\Node\Expression\Binary; -class_exists('Twig_Node_Expression_Binary_Less'); +use Twig\Compiler; -if (\false) { - class LessBinary extends \Twig_Node_Expression_Binary_Less +class LessBinary extends AbstractBinary +{ + public function operator(Compiler $compiler) { + return $compiler->raw('<'); } } + +class_alias('Twig\Node\Expression\Binary\LessBinary', 'Twig_Node_Expression_Binary_Less'); diff --git a/vendor/twig/twig/src/Node/Expression/Binary/LessEqualBinary.php b/vendor/twig/twig/src/Node/Expression/Binary/LessEqualBinary.php index 0f3018a4c3c263223f8359680b2b973e843836c1..4fffafea6dccce1320e06cb418968e67d860cd5f 100644 --- a/vendor/twig/twig/src/Node/Expression/Binary/LessEqualBinary.php +++ b/vendor/twig/twig/src/Node/Expression/Binary/LessEqualBinary.php @@ -1,11 +1,24 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\Node\Expression\Binary; -class_exists('Twig_Node_Expression_Binary_LessEqual'); +use Twig\Compiler; -if (\false) { - class LessEqualBinary extends \Twig_Node_Expression_Binary_LessEqual +class LessEqualBinary extends AbstractBinary +{ + public function operator(Compiler $compiler) { + return $compiler->raw('<='); } } + +class_alias('Twig\Node\Expression\Binary\LessEqualBinary', 'Twig_Node_Expression_Binary_LessEqual'); diff --git a/vendor/twig/twig/src/Node/Expression/Binary/MatchesBinary.php b/vendor/twig/twig/src/Node/Expression/Binary/MatchesBinary.php index d8b039a7792aaadfe2d562e2ef90e1216e80edf0..ae810b2664a859b851c3ee941b530b5e378ad855 100644 --- a/vendor/twig/twig/src/Node/Expression/Binary/MatchesBinary.php +++ b/vendor/twig/twig/src/Node/Expression/Binary/MatchesBinary.php @@ -1,11 +1,35 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\Node\Expression\Binary; -class_exists('Twig_Node_Expression_Binary_Matches'); +use Twig\Compiler; -if (\false) { - class MatchesBinary extends \Twig_Node_Expression_Binary_Matches +class MatchesBinary extends AbstractBinary +{ + public function compile(Compiler $compiler) { + $compiler + ->raw('preg_match(') + ->subcompile($this->getNode('right')) + ->raw(', ') + ->subcompile($this->getNode('left')) + ->raw(')') + ; + } + + public function operator(Compiler $compiler) + { + return $compiler->raw(''); } } + +class_alias('Twig\Node\Expression\Binary\MatchesBinary', 'Twig_Node_Expression_Binary_Matches'); diff --git a/vendor/twig/twig/src/Node/Expression/Binary/ModBinary.php b/vendor/twig/twig/src/Node/Expression/Binary/ModBinary.php index d39d5a4674e0303446b2f03622f43626355ac004..e6a2b360346a89f0d0752c0d364a6289f31e0932 100644 --- a/vendor/twig/twig/src/Node/Expression/Binary/ModBinary.php +++ b/vendor/twig/twig/src/Node/Expression/Binary/ModBinary.php @@ -1,11 +1,25 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * (c) Armin Ronacher + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\Node\Expression\Binary; -class_exists('Twig_Node_Expression_Binary_Mod'); +use Twig\Compiler; -if (\false) { - class ModBinary extends \Twig_Node_Expression_Binary_Mod +class ModBinary extends AbstractBinary +{ + public function operator(Compiler $compiler) { + return $compiler->raw('%'); } } + +class_alias('Twig\Node\Expression\Binary\ModBinary', 'Twig_Node_Expression_Binary_Mod'); diff --git a/vendor/twig/twig/src/Node/Expression/Binary/MulBinary.php b/vendor/twig/twig/src/Node/Expression/Binary/MulBinary.php index 46d6d3f61fdd94c2a72bad56e62800104e843bb4..cd65f5dff2d01c78e0b2dc868c28f7501c7c4656 100644 --- a/vendor/twig/twig/src/Node/Expression/Binary/MulBinary.php +++ b/vendor/twig/twig/src/Node/Expression/Binary/MulBinary.php @@ -1,11 +1,25 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * (c) Armin Ronacher + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\Node\Expression\Binary; -class_exists('Twig_Node_Expression_Binary_Mul'); +use Twig\Compiler; -if (\false) { - class MulBinary extends \Twig_Node_Expression_Binary_Mul +class MulBinary extends AbstractBinary +{ + public function operator(Compiler $compiler) { + return $compiler->raw('*'); } } + +class_alias('Twig\Node\Expression\Binary\MulBinary', 'Twig_Node_Expression_Binary_Mul'); diff --git a/vendor/twig/twig/src/Node/Expression/Binary/NotEqualBinary.php b/vendor/twig/twig/src/Node/Expression/Binary/NotEqualBinary.php index 09a546fd9afbec8a74ba565dd57cde0c6b615b08..df5c6a23884d7ed740a287cd9bae52eb6b67e727 100644 --- a/vendor/twig/twig/src/Node/Expression/Binary/NotEqualBinary.php +++ b/vendor/twig/twig/src/Node/Expression/Binary/NotEqualBinary.php @@ -1,11 +1,24 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\Node\Expression\Binary; -class_exists('Twig_Node_Expression_Binary_NotEqual'); +use Twig\Compiler; -if (\false) { - class NotEqualBinary extends \Twig_Node_Expression_Binary_NotEqual +class NotEqualBinary extends AbstractBinary +{ + public function operator(Compiler $compiler) { + return $compiler->raw('!='); } } + +class_alias('Twig\Node\Expression\Binary\NotEqualBinary', 'Twig_Node_Expression_Binary_NotEqual'); diff --git a/vendor/twig/twig/src/Node/Expression/Binary/NotInBinary.php b/vendor/twig/twig/src/Node/Expression/Binary/NotInBinary.php index 3ef89954ced8e770f5275a48ca68a6bf486f2f00..ed2034e35ad3d36a777589173d4c35d3157f87f9 100644 --- a/vendor/twig/twig/src/Node/Expression/Binary/NotInBinary.php +++ b/vendor/twig/twig/src/Node/Expression/Binary/NotInBinary.php @@ -1,11 +1,35 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\Node\Expression\Binary; -class_exists('Twig_Node_Expression_Binary_NotIn'); +use Twig\Compiler; -if (\false) { - class NotInBinary extends \Twig_Node_Expression_Binary_NotIn +class NotInBinary extends AbstractBinary +{ + public function compile(Compiler $compiler) { + $compiler + ->raw('!twig_in_filter(') + ->subcompile($this->getNode('left')) + ->raw(', ') + ->subcompile($this->getNode('right')) + ->raw(')') + ; + } + + public function operator(Compiler $compiler) + { + return $compiler->raw('not in'); } } + +class_alias('Twig\Node\Expression\Binary\NotInBinary', 'Twig_Node_Expression_Binary_NotIn'); diff --git a/vendor/twig/twig/src/Node/Expression/Binary/OrBinary.php b/vendor/twig/twig/src/Node/Expression/Binary/OrBinary.php index f0311fd26f1ca8de13ad2844105b2caf43d94768..8f9da43105c32adb60b6cf4e7e9781197c5ffb6f 100644 --- a/vendor/twig/twig/src/Node/Expression/Binary/OrBinary.php +++ b/vendor/twig/twig/src/Node/Expression/Binary/OrBinary.php @@ -1,11 +1,25 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * (c) Armin Ronacher + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\Node\Expression\Binary; -class_exists('Twig_Node_Expression_Binary_Or'); +use Twig\Compiler; -if (\false) { - class OrBinary extends \Twig_Node_Expression_Binary_Or +class OrBinary extends AbstractBinary +{ + public function operator(Compiler $compiler) { + return $compiler->raw('||'); } } + +class_alias('Twig\Node\Expression\Binary\OrBinary', 'Twig_Node_Expression_Binary_Or'); diff --git a/vendor/twig/twig/src/Node/Expression/Binary/PowerBinary.php b/vendor/twig/twig/src/Node/Expression/Binary/PowerBinary.php index f4033cb12eed42d350034db4ec4086670b3c1cac..10a8d94cfe879a864750ead07431f494d8f94fa5 100644 --- a/vendor/twig/twig/src/Node/Expression/Binary/PowerBinary.php +++ b/vendor/twig/twig/src/Node/Expression/Binary/PowerBinary.php @@ -1,11 +1,39 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\Node\Expression\Binary; -class_exists('Twig_Node_Expression_Binary_Power'); +use Twig\Compiler; + +class PowerBinary extends AbstractBinary +{ + public function compile(Compiler $compiler) + { + if (\PHP_VERSION_ID >= 50600) { + return parent::compile($compiler); + } + + $compiler + ->raw('pow(') + ->subcompile($this->getNode('left')) + ->raw(', ') + ->subcompile($this->getNode('right')) + ->raw(')') + ; + } -if (\false) { - class PowerBinary extends \Twig_Node_Expression_Binary_Power + public function operator(Compiler $compiler) { + return $compiler->raw('**'); } } + +class_alias('Twig\Node\Expression\Binary\PowerBinary', 'Twig_Node_Expression_Binary_Power'); diff --git a/vendor/twig/twig/src/Node/Expression/Binary/RangeBinary.php b/vendor/twig/twig/src/Node/Expression/Binary/RangeBinary.php index 7ffe00a05ee273461ee24ffbe347541f5a06f2f5..e9c0cdf5e4131a57e32cf46460045c1f892e39be 100644 --- a/vendor/twig/twig/src/Node/Expression/Binary/RangeBinary.php +++ b/vendor/twig/twig/src/Node/Expression/Binary/RangeBinary.php @@ -1,11 +1,35 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\Node\Expression\Binary; -class_exists('Twig_Node_Expression_Binary_Range'); +use Twig\Compiler; -if (\false) { - class RangeBinary extends \Twig_Node_Expression_Binary_Range +class RangeBinary extends AbstractBinary +{ + public function compile(Compiler $compiler) { + $compiler + ->raw('range(') + ->subcompile($this->getNode('left')) + ->raw(', ') + ->subcompile($this->getNode('right')) + ->raw(')') + ; + } + + public function operator(Compiler $compiler) + { + return $compiler->raw('..'); } } + +class_alias('Twig\Node\Expression\Binary\RangeBinary', 'Twig_Node_Expression_Binary_Range'); diff --git a/vendor/twig/twig/src/Node/Expression/Binary/StartsWithBinary.php b/vendor/twig/twig/src/Node/Expression/Binary/StartsWithBinary.php index 3548ce47d4f5eb4f9f20da1055d2159886c2e2bb..1fe59fb417385fd257731c520e58f61679c7e37d 100644 --- a/vendor/twig/twig/src/Node/Expression/Binary/StartsWithBinary.php +++ b/vendor/twig/twig/src/Node/Expression/Binary/StartsWithBinary.php @@ -1,11 +1,37 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\Node\Expression\Binary; -class_exists('Twig_Node_Expression_Binary_StartsWith'); +use Twig\Compiler; -if (\false) { - class StartsWithBinary extends \Twig_Node_Expression_Binary_StartsWith +class StartsWithBinary extends AbstractBinary +{ + public function compile(Compiler $compiler) { + $left = $compiler->getVarName(); + $right = $compiler->getVarName(); + $compiler + ->raw(sprintf('(is_string($%s = ', $left)) + ->subcompile($this->getNode('left')) + ->raw(sprintf(') && is_string($%s = ', $right)) + ->subcompile($this->getNode('right')) + ->raw(sprintf(') && (\'\' === $%2$s || 0 === strpos($%1$s, $%2$s)))', $left, $right)) + ; + } + + public function operator(Compiler $compiler) + { + return $compiler->raw(''); } } + +class_alias('Twig\Node\Expression\Binary\StartsWithBinary', 'Twig_Node_Expression_Binary_StartsWith'); diff --git a/vendor/twig/twig/src/Node/Expression/Binary/SubBinary.php b/vendor/twig/twig/src/Node/Expression/Binary/SubBinary.php index 1bd35cc3f2db7740fa3928007d4fa7554d6f93f5..25469750aa0ca580446ec92b1127984314b6da24 100644 --- a/vendor/twig/twig/src/Node/Expression/Binary/SubBinary.php +++ b/vendor/twig/twig/src/Node/Expression/Binary/SubBinary.php @@ -1,11 +1,25 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * (c) Armin Ronacher + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\Node\Expression\Binary; -class_exists('Twig_Node_Expression_Binary_Sub'); +use Twig\Compiler; -if (\false) { - class SubBinary extends \Twig_Node_Expression_Binary_Sub +class SubBinary extends AbstractBinary +{ + public function operator(Compiler $compiler) { + return $compiler->raw('-'); } } + +class_alias('Twig\Node\Expression\Binary\SubBinary', 'Twig_Node_Expression_Binary_Sub'); diff --git a/vendor/twig/twig/src/Node/Expression/BlockReferenceExpression.php b/vendor/twig/twig/src/Node/Expression/BlockReferenceExpression.php index 4d4439e35fb2a5f605de678de81da653201de90a..0a56849c7aade3b92390524bf64dbc5c420845c2 100644 --- a/vendor/twig/twig/src/Node/Expression/BlockReferenceExpression.php +++ b/vendor/twig/twig/src/Node/Expression/BlockReferenceExpression.php @@ -1,11 +1,98 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * (c) Armin Ronacher + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\Node\Expression; -class_exists('Twig_Node_Expression_BlockReference'); +use Twig\Compiler; +use Twig\Node\Node; + +/** + * Represents a block call node. + * + * @author Fabien Potencier <fabien@symfony.com> + */ +class BlockReferenceExpression extends AbstractExpression +{ + /** + * @param Node|null $template + */ + public function __construct(\Twig_NodeInterface $name, $template = null, $lineno, $tag = null) + { + if (\is_bool($template)) { + @trigger_error(sprintf('The %s method "$asString" argument is deprecated since version 1.28 and will be removed in 2.0.', __METHOD__), E_USER_DEPRECATED); + + $template = null; + } + + $nodes = ['name' => $name]; + if (null !== $template) { + $nodes['template'] = $template; + } -if (\false) { - class BlockReferenceExpression extends \Twig_Node_Expression_BlockReference + parent::__construct($nodes, ['is_defined_test' => false, 'output' => false], $lineno, $tag); + } + + public function compile(Compiler $compiler) { + if ($this->getAttribute('is_defined_test')) { + $this->compileTemplateCall($compiler, 'hasBlock'); + } else { + if ($this->getAttribute('output')) { + $compiler->addDebugInfo($this); + + $this + ->compileTemplateCall($compiler, 'displayBlock') + ->raw(";\n"); + } else { + $this->compileTemplateCall($compiler, 'renderBlock'); + } + } + } + + private function compileTemplateCall(Compiler $compiler, $method) + { + if (!$this->hasNode('template')) { + $compiler->write('$this'); + } else { + $compiler + ->write('$this->loadTemplate(') + ->subcompile($this->getNode('template')) + ->raw(', ') + ->repr($this->getTemplateName()) + ->raw(', ') + ->repr($this->getTemplateLine()) + ->raw(')') + ; + } + + $compiler->raw(sprintf('->%s', $method)); + $this->compileBlockArguments($compiler); + + return $compiler; + } + + private function compileBlockArguments(Compiler $compiler) + { + $compiler + ->raw('(') + ->subcompile($this->getNode('name')) + ->raw(', $context'); + + if (!$this->hasNode('template')) { + $compiler->raw(', $blocks'); + } + + return $compiler->raw(')'); } } + +class_alias('Twig\Node\Expression\BlockReferenceExpression', 'Twig_Node_Expression_BlockReference'); diff --git a/vendor/twig/twig/src/Node/Expression/CallExpression.php b/vendor/twig/twig/src/Node/Expression/CallExpression.php index f9af30b2933fd8d67a71558a06ee38501190687d..d202a739532c40ca88726c298a4b5f104e9f29d5 100644 --- a/vendor/twig/twig/src/Node/Expression/CallExpression.php +++ b/vendor/twig/twig/src/Node/Expression/CallExpression.php @@ -1,11 +1,305 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\Node\Expression; -class_exists('Twig_Node_Expression_Call'); +use Twig\Compiler; +use Twig\Error\SyntaxError; +use Twig\Extension\ExtensionInterface; +use Twig\Node\Node; + +abstract class CallExpression extends AbstractExpression +{ + private $reflector; + + protected function compileCallable(Compiler $compiler) + { + $closingParenthesis = false; + $isArray = false; + if ($this->hasAttribute('callable') && $callable = $this->getAttribute('callable')) { + if (\is_string($callable) && false === strpos($callable, '::')) { + $compiler->raw($callable); + } else { + list($r, $callable) = $this->reflectCallable($callable); + if ($r instanceof \ReflectionMethod && \is_string($callable[0])) { + if ($r->isStatic()) { + $compiler->raw(sprintf('%s::%s', $callable[0], $callable[1])); + } else { + $compiler->raw(sprintf('$this->env->getRuntime(\'%s\')->%s', $callable[0], $callable[1])); + } + } elseif ($r instanceof \ReflectionMethod && $callable[0] instanceof ExtensionInterface) { + $compiler->raw(sprintf('$this->env->getExtension(\'%s\')->%s', \get_class($callable[0]), $callable[1])); + } else { + $type = ucfirst($this->getAttribute('type')); + $compiler->raw(sprintf('call_user_func_array($this->env->get%s(\'%s\')->getCallable(), ', $type, $this->getAttribute('name'))); + $closingParenthesis = true; + $isArray = true; + } + } + } else { + $compiler->raw($this->getAttribute('thing')->compile()); + } + + $this->compileArguments($compiler, $isArray); + + if ($closingParenthesis) { + $compiler->raw(')'); + } + } + + protected function compileArguments(Compiler $compiler, $isArray = false) + { + $compiler->raw($isArray ? '[' : '('); + + $first = true; + + if ($this->hasAttribute('needs_environment') && $this->getAttribute('needs_environment')) { + $compiler->raw('$this->env'); + $first = false; + } + + if ($this->hasAttribute('needs_context') && $this->getAttribute('needs_context')) { + if (!$first) { + $compiler->raw(', '); + } + $compiler->raw('$context'); + $first = false; + } + + if ($this->hasAttribute('arguments')) { + foreach ($this->getAttribute('arguments') as $argument) { + if (!$first) { + $compiler->raw(', '); + } + $compiler->string($argument); + $first = false; + } + } + + if ($this->hasNode('node')) { + if (!$first) { + $compiler->raw(', '); + } + $compiler->subcompile($this->getNode('node')); + $first = false; + } + + if ($this->hasNode('arguments')) { + $callable = $this->hasAttribute('callable') ? $this->getAttribute('callable') : null; + + $arguments = $this->getArguments($callable, $this->getNode('arguments')); + + foreach ($arguments as $node) { + if (!$first) { + $compiler->raw(', '); + } + $compiler->subcompile($node); + $first = false; + } + } + + $compiler->raw($isArray ? ']' : ')'); + } + + protected function getArguments($callable, $arguments) + { + $callType = $this->getAttribute('type'); + $callName = $this->getAttribute('name'); + + $parameters = []; + $named = false; + foreach ($arguments as $name => $node) { + if (!\is_int($name)) { + $named = true; + $name = $this->normalizeName($name); + } elseif ($named) { + throw new SyntaxError(sprintf('Positional arguments cannot be used after named arguments for %s "%s".', $callType, $callName), $this->getTemplateLine(), $this->getSourceContext()); + } + + $parameters[$name] = $node; + } + + $isVariadic = $this->hasAttribute('is_variadic') && $this->getAttribute('is_variadic'); + if (!$named && !$isVariadic) { + return $parameters; + } -if (\false) { - class CallExpression extends \Twig_Node_Expression_Call + if (!$callable) { + if ($named) { + $message = sprintf('Named arguments are not supported for %s "%s".', $callType, $callName); + } else { + $message = sprintf('Arbitrary positional arguments are not supported for %s "%s".', $callType, $callName); + } + + throw new \LogicException($message); + } + + $callableParameters = $this->getCallableParameters($callable, $isVariadic); + $arguments = []; + $names = []; + $missingArguments = []; + $optionalArguments = []; + $pos = 0; + foreach ($callableParameters as $callableParameter) { + $names[] = $name = $this->normalizeName($callableParameter->name); + + if (\array_key_exists($name, $parameters)) { + if (\array_key_exists($pos, $parameters)) { + throw new SyntaxError(sprintf('Argument "%s" is defined twice for %s "%s".', $name, $callType, $callName), $this->getTemplateLine(), $this->getSourceContext()); + } + + if (\count($missingArguments)) { + throw new SyntaxError(sprintf( + 'Argument "%s" could not be assigned for %s "%s(%s)" because it is mapped to an internal PHP function which cannot determine default value for optional argument%s "%s".', + $name, $callType, $callName, implode(', ', $names), \count($missingArguments) > 1 ? 's' : '', implode('", "', $missingArguments) + ), $this->getTemplateLine(), $this->getSourceContext()); + } + + $arguments = array_merge($arguments, $optionalArguments); + $arguments[] = $parameters[$name]; + unset($parameters[$name]); + $optionalArguments = []; + } elseif (\array_key_exists($pos, $parameters)) { + $arguments = array_merge($arguments, $optionalArguments); + $arguments[] = $parameters[$pos]; + unset($parameters[$pos]); + $optionalArguments = []; + ++$pos; + } elseif ($callableParameter->isDefaultValueAvailable()) { + $optionalArguments[] = new ConstantExpression($callableParameter->getDefaultValue(), -1); + } elseif ($callableParameter->isOptional()) { + if (empty($parameters)) { + break; + } else { + $missingArguments[] = $name; + } + } else { + throw new SyntaxError(sprintf('Value for argument "%s" is required for %s "%s".', $name, $callType, $callName), $this->getTemplateLine(), $this->getSourceContext()); + } + } + + if ($isVariadic) { + $arbitraryArguments = new ArrayExpression([], -1); + foreach ($parameters as $key => $value) { + if (\is_int($key)) { + $arbitraryArguments->addElement($value); + } else { + $arbitraryArguments->addElement($value, new ConstantExpression($key, -1)); + } + unset($parameters[$key]); + } + + if ($arbitraryArguments->count()) { + $arguments = array_merge($arguments, $optionalArguments); + $arguments[] = $arbitraryArguments; + } + } + + if (!empty($parameters)) { + $unknownParameter = null; + foreach ($parameters as $parameter) { + if ($parameter instanceof Node) { + $unknownParameter = $parameter; + break; + } + } + + throw new SyntaxError( + sprintf( + 'Unknown argument%s "%s" for %s "%s(%s)".', + \count($parameters) > 1 ? 's' : '', implode('", "', array_keys($parameters)), $callType, $callName, implode(', ', $names) + ), + $unknownParameter ? $unknownParameter->getTemplateLine() : $this->getTemplateLine(), + $unknownParameter ? $unknownParameter->getSourceContext() : $this->getSourceContext() + ); + } + + return $arguments; + } + + protected function normalizeName($name) { + return strtolower(preg_replace(['/([A-Z]+)([A-Z][a-z])/', '/([a-z\d])([A-Z])/'], ['\\1_\\2', '\\1_\\2'], $name)); + } + + private function getCallableParameters($callable, $isVariadic) + { + list($r) = $this->reflectCallable($callable); + if (null === $r) { + return []; + } + + $parameters = $r->getParameters(); + if ($this->hasNode('node')) { + array_shift($parameters); + } + if ($this->hasAttribute('needs_environment') && $this->getAttribute('needs_environment')) { + array_shift($parameters); + } + if ($this->hasAttribute('needs_context') && $this->getAttribute('needs_context')) { + array_shift($parameters); + } + if ($this->hasAttribute('arguments') && null !== $this->getAttribute('arguments')) { + foreach ($this->getAttribute('arguments') as $argument) { + array_shift($parameters); + } + } + if ($isVariadic) { + $argument = end($parameters); + if ($argument && $argument->isArray() && $argument->isDefaultValueAvailable() && [] === $argument->getDefaultValue()) { + array_pop($parameters); + } else { + $callableName = $r->name; + if ($r instanceof \ReflectionMethod) { + $callableName = $r->getDeclaringClass()->name.'::'.$callableName; + } + + throw new \LogicException(sprintf('The last parameter of "%s" for %s "%s" must be an array with default value, eg. "array $arg = []".', $callableName, $this->getAttribute('type'), $this->getAttribute('name'))); + } + } + + return $parameters; + } + + private function reflectCallable($callable) + { + if (null !== $this->reflector) { + return $this->reflector; + } + + if (\is_array($callable)) { + if (!method_exists($callable[0], $callable[1])) { + // __call() + return [null, []]; + } + $r = new \ReflectionMethod($callable[0], $callable[1]); + } elseif (\is_object($callable) && !$callable instanceof \Closure) { + $r = new \ReflectionObject($callable); + $r = $r->getMethod('__invoke'); + $callable = [$callable, '__invoke']; + } elseif (\is_string($callable) && false !== $pos = strpos($callable, '::')) { + $class = substr($callable, 0, $pos); + $method = substr($callable, $pos + 2); + if (!method_exists($class, $method)) { + // __staticCall() + return [null, []]; + } + $r = new \ReflectionMethod($callable); + $callable = [$class, $method]; + } else { + $r = new \ReflectionFunction($callable); + } + + return $this->reflector = [$r, $callable]; } } + +class_alias('Twig\Node\Expression\CallExpression', 'Twig_Node_Expression_Call'); diff --git a/vendor/twig/twig/src/Node/Expression/ConditionalExpression.php b/vendor/twig/twig/src/Node/Expression/ConditionalExpression.php index 507d085e020913a3d81374cf794f46acdc8f3f7f..b611218d31b862180a15be20d147ed591364efef 100644 --- a/vendor/twig/twig/src/Node/Expression/ConditionalExpression.php +++ b/vendor/twig/twig/src/Node/Expression/ConditionalExpression.php @@ -1,11 +1,38 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * (c) Armin Ronacher + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\Node\Expression; -class_exists('Twig_Node_Expression_Conditional'); +use Twig\Compiler; -if (\false) { - class ConditionalExpression extends \Twig_Node_Expression_Conditional +class ConditionalExpression extends AbstractExpression +{ + public function __construct(AbstractExpression $expr1, AbstractExpression $expr2, AbstractExpression $expr3, $lineno) { + parent::__construct(['expr1' => $expr1, 'expr2' => $expr2, 'expr3' => $expr3], [], $lineno); + } + + public function compile(Compiler $compiler) + { + $compiler + ->raw('((') + ->subcompile($this->getNode('expr1')) + ->raw(') ? (') + ->subcompile($this->getNode('expr2')) + ->raw(') : (') + ->subcompile($this->getNode('expr3')) + ->raw('))') + ; } } + +class_alias('Twig\Node\Expression\ConditionalExpression', 'Twig_Node_Expression_Conditional'); diff --git a/vendor/twig/twig/src/Node/Expression/ConstantExpression.php b/vendor/twig/twig/src/Node/Expression/ConstantExpression.php index ef197ba02d2645181026db8e5654ee96868950f6..fd58264dca1bcc84a71f5f4902e0356dabc007a8 100644 --- a/vendor/twig/twig/src/Node/Expression/ConstantExpression.php +++ b/vendor/twig/twig/src/Node/Expression/ConstantExpression.php @@ -1,11 +1,30 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * (c) Armin Ronacher + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\Node\Expression; -class_exists('Twig_Node_Expression_Constant'); +use Twig\Compiler; -if (\false) { - class ConstantExpression extends \Twig_Node_Expression_Constant +class ConstantExpression extends AbstractExpression +{ + public function __construct($value, $lineno) { + parent::__construct([], ['value' => $value], $lineno); + } + + public function compile(Compiler $compiler) + { + $compiler->repr($this->getAttribute('value')); } } + +class_alias('Twig\Node\Expression\ConstantExpression', 'Twig_Node_Expression_Constant'); diff --git a/vendor/twig/twig/src/Node/Expression/Filter/DefaultFilter.php b/vendor/twig/twig/src/Node/Expression/Filter/DefaultFilter.php index 2eb573c2f0084c94d0a306733a0ff88afed529a8..7c5e2d20aa46ddcfc4c393a88d0edd51eea29a7e 100644 --- a/vendor/twig/twig/src/Node/Expression/Filter/DefaultFilter.php +++ b/vendor/twig/twig/src/Node/Expression/Filter/DefaultFilter.php @@ -1,11 +1,54 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\Node\Expression\Filter; -class_exists('Twig_Node_Expression_Filter_Default'); +use Twig\Compiler; +use Twig\Node\Expression\ConditionalExpression; +use Twig\Node\Expression\ConstantExpression; +use Twig\Node\Expression\FilterExpression; +use Twig\Node\Expression\GetAttrExpression; +use Twig\Node\Expression\NameExpression; +use Twig\Node\Expression\Test\DefinedTest; +use Twig\Node\Node; + +/** + * Returns the value or the default value when it is undefined or empty. + * + * {{ var.foo|default('foo item on var is not defined') }} + * + * @author Fabien Potencier <fabien@symfony.com> + */ +class DefaultFilter extends FilterExpression +{ + public function __construct(\Twig_NodeInterface $node, ConstantExpression $filterName, \Twig_NodeInterface $arguments, $lineno, $tag = null) + { + $default = new FilterExpression($node, new ConstantExpression('default', $node->getTemplateLine()), $arguments, $node->getTemplateLine()); + + if ('default' === $filterName->getAttribute('value') && ($node instanceof NameExpression || $node instanceof GetAttrExpression)) { + $test = new DefinedTest(clone $node, 'defined', new Node(), $node->getTemplateLine()); + $false = \count($arguments) ? $arguments->getNode(0) : new ConstantExpression('', $node->getTemplateLine()); -if (\false) { - class DefaultFilter extends \Twig_Node_Expression_Filter_Default + $node = new ConditionalExpression($test, $default, $false, $node->getTemplateLine()); + } else { + $node = $default; + } + + parent::__construct($node, $filterName, $arguments, $lineno, $tag); + } + + public function compile(Compiler $compiler) { + $compiler->subcompile($this->getNode('node')); } } + +class_alias('Twig\Node\Expression\Filter\DefaultFilter', 'Twig_Node_Expression_Filter_Default'); diff --git a/vendor/twig/twig/src/Node/Expression/FilterExpression.php b/vendor/twig/twig/src/Node/Expression/FilterExpression.php index 47b3b41efbd56871116a231251819ca2c7c482fa..6131c2fd4033683076cd17d22072c945f375b503 100644 --- a/vendor/twig/twig/src/Node/Expression/FilterExpression.php +++ b/vendor/twig/twig/src/Node/Expression/FilterExpression.php @@ -1,11 +1,47 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * (c) Armin Ronacher + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\Node\Expression; -class_exists('Twig_Node_Expression_Filter'); +use Twig\Compiler; +use Twig\TwigFilter; -if (\false) { - class FilterExpression extends \Twig_Node_Expression_Filter +class FilterExpression extends CallExpression +{ + public function __construct(\Twig_NodeInterface $node, ConstantExpression $filterName, \Twig_NodeInterface $arguments, $lineno, $tag = null) { + parent::__construct(['node' => $node, 'filter' => $filterName, 'arguments' => $arguments], [], $lineno, $tag); + } + + public function compile(Compiler $compiler) + { + $name = $this->getNode('filter')->getAttribute('value'); + $filter = $compiler->getEnvironment()->getFilter($name); + + $this->setAttribute('name', $name); + $this->setAttribute('type', 'filter'); + $this->setAttribute('thing', $filter); + $this->setAttribute('needs_environment', $filter->needsEnvironment()); + $this->setAttribute('needs_context', $filter->needsContext()); + $this->setAttribute('arguments', $filter->getArguments()); + if ($filter instanceof \Twig_FilterCallableInterface || $filter instanceof TwigFilter) { + $this->setAttribute('callable', $filter->getCallable()); + } + if ($filter instanceof TwigFilter) { + $this->setAttribute('is_variadic', $filter->isVariadic()); + } + + $this->compileCallable($compiler); } } + +class_alias('Twig\Node\Expression\FilterExpression', 'Twig_Node_Expression_Filter'); diff --git a/vendor/twig/twig/src/Node/Expression/FunctionExpression.php b/vendor/twig/twig/src/Node/Expression/FunctionExpression.php index 9ab002fbfb0ddc9ad31204f82a389f7ddb675119..cf2c72b635f78ee09b0f0564ada6029d85667a1b 100644 --- a/vendor/twig/twig/src/Node/Expression/FunctionExpression.php +++ b/vendor/twig/twig/src/Node/Expression/FunctionExpression.php @@ -1,11 +1,51 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\Node\Expression; -class_exists('Twig_Node_Expression_Function'); +use Twig\Compiler; +use Twig\TwigFunction; + +class FunctionExpression extends CallExpression +{ + public function __construct($name, \Twig_NodeInterface $arguments, $lineno) + { + parent::__construct(['arguments' => $arguments], ['name' => $name, 'is_defined_test' => false], $lineno); + } -if (\false) { - class FunctionExpression extends \Twig_Node_Expression_Function + public function compile(Compiler $compiler) { + $name = $this->getAttribute('name'); + $function = $compiler->getEnvironment()->getFunction($name); + + $this->setAttribute('name', $name); + $this->setAttribute('type', 'function'); + $this->setAttribute('thing', $function); + $this->setAttribute('needs_environment', $function->needsEnvironment()); + $this->setAttribute('needs_context', $function->needsContext()); + $this->setAttribute('arguments', $function->getArguments()); + if ($function instanceof \Twig_FunctionCallableInterface || $function instanceof TwigFunction) { + $callable = $function->getCallable(); + if ('constant' === $name && $this->getAttribute('is_defined_test')) { + $callable = 'twig_constant_is_defined'; + } + + $this->setAttribute('callable', $callable); + } + if ($function instanceof TwigFunction) { + $this->setAttribute('is_variadic', $function->isVariadic()); + } + + $this->compileCallable($compiler); } } + +class_alias('Twig\Node\Expression\FunctionExpression', 'Twig_Node_Expression_Function'); diff --git a/vendor/twig/twig/src/Node/Expression/GetAttrExpression.php b/vendor/twig/twig/src/Node/Expression/GetAttrExpression.php index 6e810c7fe75f5ce59bbf572c8f543a975b7e4af9..b790bf7af7a840641dab6bbc9a9bcebefe65870d 100644 --- a/vendor/twig/twig/src/Node/Expression/GetAttrExpression.php +++ b/vendor/twig/twig/src/Node/Expression/GetAttrExpression.php @@ -1,11 +1,80 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * (c) Armin Ronacher + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\Node\Expression; -class_exists('Twig_Node_Expression_GetAttr'); +use Twig\Compiler; +use Twig\Template; + +class GetAttrExpression extends AbstractExpression +{ + public function __construct(AbstractExpression $node, AbstractExpression $attribute, AbstractExpression $arguments = null, $type, $lineno) + { + $nodes = ['node' => $node, 'attribute' => $attribute]; + if (null !== $arguments) { + $nodes['arguments'] = $arguments; + } + + parent::__construct($nodes, ['type' => $type, 'is_defined_test' => false, 'ignore_strict_check' => false, 'disable_c_ext' => false], $lineno); + } -if (\false) { - class GetAttrExpression extends \Twig_Node_Expression_GetAttr + public function compile(Compiler $compiler) { + if ($this->getAttribute('disable_c_ext')) { + @trigger_error(sprintf('Using the "disable_c_ext" attribute on %s is deprecated since version 1.30 and will be removed in 2.0.', __CLASS__), E_USER_DEPRECATED); + } + + if (\function_exists('twig_template_get_attributes') && !$this->getAttribute('disable_c_ext')) { + $compiler->raw('twig_template_get_attributes($this, '); + } else { + $compiler->raw('$this->getAttribute('); + } + + if ($this->getAttribute('ignore_strict_check')) { + $this->getNode('node')->setAttribute('ignore_strict_check', true); + } + + $compiler->subcompile($this->getNode('node')); + + $compiler->raw(', ')->subcompile($this->getNode('attribute')); + + // only generate optional arguments when needed (to make generated code more readable) + $needFourth = $this->getAttribute('ignore_strict_check'); + $needThird = $needFourth || $this->getAttribute('is_defined_test'); + $needSecond = $needThird || Template::ANY_CALL !== $this->getAttribute('type'); + $needFirst = $needSecond || $this->hasNode('arguments'); + + if ($needFirst) { + if ($this->hasNode('arguments')) { + $compiler->raw(', ')->subcompile($this->getNode('arguments')); + } else { + $compiler->raw(', []'); + } + } + + if ($needSecond) { + $compiler->raw(', ')->repr($this->getAttribute('type')); + } + + if ($needThird) { + $compiler->raw(', ')->repr($this->getAttribute('is_defined_test')); + } + + if ($needFourth) { + $compiler->raw(', ')->repr($this->getAttribute('ignore_strict_check')); + } + + $compiler->raw(')'); } } + +class_alias('Twig\Node\Expression\GetAttrExpression', 'Twig_Node_Expression_GetAttr'); diff --git a/vendor/twig/twig/src/Node/Expression/InlinePrint.php b/vendor/twig/twig/src/Node/Expression/InlinePrint.php new file mode 100644 index 0000000000000000000000000000000000000000..469e73675a43f02bb4d988d4bea44eb880caf23e --- /dev/null +++ b/vendor/twig/twig/src/Node/Expression/InlinePrint.php @@ -0,0 +1,35 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Twig\Node\Expression; + +use Twig\Compiler; +use Twig\Node\Node; + +/** + * @internal + */ +final class InlinePrint extends AbstractExpression +{ + public function __construct(Node $node, $lineno) + { + parent::__construct(['node' => $node], [], $lineno); + } + + public function compile(Compiler $compiler) + { + $compiler + ->raw('print (') + ->subcompile($this->getNode('node')) + ->raw(')') + ; + } +} diff --git a/vendor/twig/twig/src/Node/Expression/MethodCallExpression.php b/vendor/twig/twig/src/Node/Expression/MethodCallExpression.php index e751c31b83a5fe8293abc31bf5de817c316ee533..f6311249dee691091421498d3003b86de837086a 100644 --- a/vendor/twig/twig/src/Node/Expression/MethodCallExpression.php +++ b/vendor/twig/twig/src/Node/Expression/MethodCallExpression.php @@ -1,11 +1,48 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\Node\Expression; -class_exists('Twig_Node_Expression_MethodCall'); +use Twig\Compiler; -if (\false) { - class MethodCallExpression extends \Twig_Node_Expression_MethodCall +class MethodCallExpression extends AbstractExpression +{ + public function __construct(AbstractExpression $node, $method, ArrayExpression $arguments, $lineno) { + parent::__construct(['node' => $node, 'arguments' => $arguments], ['method' => $method, 'safe' => false], $lineno); + + if ($node instanceof NameExpression) { + $node->setAttribute('always_defined', true); + } + } + + public function compile(Compiler $compiler) + { + $compiler + ->subcompile($this->getNode('node')) + ->raw('->') + ->raw($this->getAttribute('method')) + ->raw('(') + ; + $first = true; + foreach ($this->getNode('arguments')->getKeyValuePairs() as $pair) { + if (!$first) { + $compiler->raw(', '); + } + $first = false; + + $compiler->subcompile($pair['value']); + } + $compiler->raw(')'); } } + +class_alias('Twig\Node\Expression\MethodCallExpression', 'Twig_Node_Expression_MethodCall'); diff --git a/vendor/twig/twig/src/Node/Expression/NameExpression.php b/vendor/twig/twig/src/Node/Expression/NameExpression.php index c32981afd6e72ecb74c52084e91517b936e3161e..d3f7d107fb00eef7c13657e5877ea354a5f8ac62 100644 --- a/vendor/twig/twig/src/Node/Expression/NameExpression.php +++ b/vendor/twig/twig/src/Node/Expression/NameExpression.php @@ -1,11 +1,119 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * (c) Armin Ronacher + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\Node\Expression; -class_exists('Twig_Node_Expression_Name'); +use Twig\Compiler; + +class NameExpression extends AbstractExpression +{ + protected $specialVars = [ + '_self' => '$this', + '_context' => '$context', + '_charset' => '$this->env->getCharset()', + ]; + + public function __construct($name, $lineno) + { + parent::__construct([], ['name' => $name, 'is_defined_test' => false, 'ignore_strict_check' => false, 'always_defined' => false], $lineno); + } + + public function compile(Compiler $compiler) + { + $name = $this->getAttribute('name'); + + $compiler->addDebugInfo($this); + + if ($this->getAttribute('is_defined_test')) { + if ($this->isSpecial()) { + $compiler->repr(true); + } elseif (\PHP_VERSION_ID >= 700400) { + $compiler + ->raw('array_key_exists(') + ->string($name) + ->raw(', $context)') + ; + } else { + $compiler + ->raw('(isset($context[') + ->string($name) + ->raw(']) || array_key_exists(') + ->string($name) + ->raw(', $context))') + ; + } + } elseif ($this->isSpecial()) { + $compiler->raw($this->specialVars[$name]); + } elseif ($this->getAttribute('always_defined')) { + $compiler + ->raw('$context[') + ->string($name) + ->raw(']') + ; + } else { + if (\PHP_VERSION_ID >= 70000) { + // use PHP 7 null coalescing operator + $compiler + ->raw('($context[') + ->string($name) + ->raw('] ?? ') + ; -if (\false) { - class NameExpression extends \Twig_Node_Expression_Name + if ($this->getAttribute('ignore_strict_check') || !$compiler->getEnvironment()->isStrictVariables()) { + $compiler->raw('null)'); + } else { + $compiler->raw('$this->getContext($context, ')->string($name)->raw('))'); + } + } elseif (\PHP_VERSION_ID >= 50400) { + // PHP 5.4 ternary operator performance was optimized + $compiler + ->raw('(isset($context[') + ->string($name) + ->raw(']) ? $context[') + ->string($name) + ->raw('] : ') + ; + + if ($this->getAttribute('ignore_strict_check') || !$compiler->getEnvironment()->isStrictVariables()) { + $compiler->raw('null)'); + } else { + $compiler->raw('$this->getContext($context, ')->string($name)->raw('))'); + } + } else { + $compiler + ->raw('$this->getContext($context, ') + ->string($name) + ; + + if ($this->getAttribute('ignore_strict_check')) { + $compiler->raw(', true'); + } + + $compiler + ->raw(')') + ; + } + } + } + + public function isSpecial() { + return isset($this->specialVars[$this->getAttribute('name')]); + } + + public function isSimple() + { + return !$this->isSpecial() && !$this->getAttribute('is_defined_test'); } } + +class_alias('Twig\Node\Expression\NameExpression', 'Twig_Node_Expression_Name'); diff --git a/vendor/twig/twig/src/Node/Expression/NullCoalesceExpression.php b/vendor/twig/twig/src/Node/Expression/NullCoalesceExpression.php index a1d3590a1c2604620390fdeaa3eeaf697e0b18dd..49326d467dbefe9f40fcbb44396a11965f2fc3dc 100644 --- a/vendor/twig/twig/src/Node/Expression/NullCoalesceExpression.php +++ b/vendor/twig/twig/src/Node/Expression/NullCoalesceExpression.php @@ -1,11 +1,58 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\Node\Expression; -class_exists('Twig_Node_Expression_NullCoalesce'); +use Twig\Compiler; +use Twig\Node\Expression\Binary\AndBinary; +use Twig\Node\Expression\Test\DefinedTest; +use Twig\Node\Expression\Test\NullTest; +use Twig\Node\Expression\Unary\NotUnary; +use Twig\Node\Node; + +class NullCoalesceExpression extends ConditionalExpression +{ + public function __construct(\Twig_NodeInterface $left, \Twig_NodeInterface $right, $lineno) + { + $test = new AndBinary( + new DefinedTest(clone $left, 'defined', new Node(), $left->getTemplateLine()), + new NotUnary(new NullTest($left, 'null', new Node(), $left->getTemplateLine()), $left->getTemplateLine()), + $left->getTemplateLine() + ); + + parent::__construct($test, $left, $right, $lineno); + } -if (\false) { - class NullCoalesceExpression extends \Twig_Node_Expression_NullCoalesce + public function compile(Compiler $compiler) { + /* + * This optimizes only one case. PHP 7 also supports more complex expressions + * that can return null. So, for instance, if log is defined, log("foo") ?? "..." works, + * but log($a["foo"]) ?? "..." does not if $a["foo"] is not defined. More advanced + * cases might be implemented as an optimizer node visitor, but has not been done + * as benefits are probably not worth the added complexity. + */ + if (\PHP_VERSION_ID >= 70000 && $this->getNode('expr2') instanceof NameExpression) { + $this->getNode('expr2')->setAttribute('always_defined', true); + $compiler + ->raw('((') + ->subcompile($this->getNode('expr2')) + ->raw(') ?? (') + ->subcompile($this->getNode('expr3')) + ->raw('))') + ; + } else { + parent::compile($compiler); + } } } + +class_alias('Twig\Node\Expression\NullCoalesceExpression', 'Twig_Node_Expression_NullCoalesce'); diff --git a/vendor/twig/twig/src/Node/Expression/ParentExpression.php b/vendor/twig/twig/src/Node/Expression/ParentExpression.php index 70b0e360ce31d1a08e011b8c2e8e8736c2b8d826..12472830362a1705e698e28e41ec6addefc69940 100644 --- a/vendor/twig/twig/src/Node/Expression/ParentExpression.php +++ b/vendor/twig/twig/src/Node/Expression/ParentExpression.php @@ -1,11 +1,48 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * (c) Armin Ronacher + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\Node\Expression; -class_exists('Twig_Node_Expression_Parent'); +use Twig\Compiler; -if (\false) { - class ParentExpression extends \Twig_Node_Expression_Parent +/** + * Represents a parent node. + * + * @author Fabien Potencier <fabien@symfony.com> + */ +class ParentExpression extends AbstractExpression +{ + public function __construct($name, $lineno, $tag = null) { + parent::__construct([], ['output' => false, 'name' => $name], $lineno, $tag); + } + + public function compile(Compiler $compiler) + { + if ($this->getAttribute('output')) { + $compiler + ->addDebugInfo($this) + ->write('$this->displayParentBlock(') + ->string($this->getAttribute('name')) + ->raw(", \$context, \$blocks);\n") + ; + } else { + $compiler + ->raw('$this->renderParentBlock(') + ->string($this->getAttribute('name')) + ->raw(', $context, $blocks)') + ; + } } } + +class_alias('Twig\Node\Expression\ParentExpression', 'Twig_Node_Expression_Parent'); diff --git a/vendor/twig/twig/src/Node/Expression/TempNameExpression.php b/vendor/twig/twig/src/Node/Expression/TempNameExpression.php index 178b6dec25423ace74a91f15ffd09a8cc4d1fd06..ce0a158981eda749aaa44519e5a57969ef5a48ac 100644 --- a/vendor/twig/twig/src/Node/Expression/TempNameExpression.php +++ b/vendor/twig/twig/src/Node/Expression/TempNameExpression.php @@ -1,11 +1,33 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\Node\Expression; -class_exists('Twig_Node_Expression_TempName'); +use Twig\Compiler; -if (\false) { - class TempNameExpression extends \Twig_Node_Expression_TempName +class TempNameExpression extends AbstractExpression +{ + public function __construct($name, $lineno) { + parent::__construct([], ['name' => $name], $lineno); + } + + public function compile(Compiler $compiler) + { + $compiler + ->raw('$_') + ->raw($this->getAttribute('name')) + ->raw('_') + ; } } + +class_alias('Twig\Node\Expression\TempNameExpression', 'Twig_Node_Expression_TempName'); diff --git a/vendor/twig/twig/src/Node/Expression/Test/ConstantTest.php b/vendor/twig/twig/src/Node/Expression/Test/ConstantTest.php index b54b2801ecf92c0a5a07f37151629b412414a6a0..78353a8b256aa79d3cbf8ff92d07285491876ade 100644 --- a/vendor/twig/twig/src/Node/Expression/Test/ConstantTest.php +++ b/vendor/twig/twig/src/Node/Expression/Test/ConstantTest.php @@ -1,11 +1,51 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\Node\Expression\Test; -class_exists('Twig_Node_Expression_Test_Constant'); +use Twig\Compiler; +use Twig\Node\Expression\TestExpression; -if (\false) { - class ConstantTest extends \Twig_Node_Expression_Test_Constant +/** + * Checks if a variable is the exact same value as a constant. + * + * {% if post.status is constant('Post::PUBLISHED') %} + * the status attribute is exactly the same as Post::PUBLISHED + * {% endif %} + * + * @author Fabien Potencier <fabien@symfony.com> + */ +class ConstantTest extends TestExpression +{ + public function compile(Compiler $compiler) { + $compiler + ->raw('(') + ->subcompile($this->getNode('node')) + ->raw(' === constant(') + ; + + if ($this->getNode('arguments')->hasNode(1)) { + $compiler + ->raw('get_class(') + ->subcompile($this->getNode('arguments')->getNode(1)) + ->raw(')."::".') + ; + } + + $compiler + ->subcompile($this->getNode('arguments')->getNode(0)) + ->raw('))') + ; } } + +class_alias('Twig\Node\Expression\Test\ConstantTest', 'Twig_Node_Expression_Test_Constant'); diff --git a/vendor/twig/twig/src/Node/Expression/Test/DefinedTest.php b/vendor/twig/twig/src/Node/Expression/Test/DefinedTest.php index 69c36a0bb61780019bfc682c8bbc75f408f610d3..2222e11cfda784e15532246ee5e82056ee87b1aa 100644 --- a/vendor/twig/twig/src/Node/Expression/Test/DefinedTest.php +++ b/vendor/twig/twig/src/Node/Expression/Test/DefinedTest.php @@ -1,11 +1,71 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\Node\Expression\Test; -class_exists('Twig_Node_Expression_Test_Defined'); +use Twig\Compiler; +use Twig\Error\SyntaxError; +use Twig\Node\Expression\ArrayExpression; +use Twig\Node\Expression\BlockReferenceExpression; +use Twig\Node\Expression\ConstantExpression; +use Twig\Node\Expression\FunctionExpression; +use Twig\Node\Expression\GetAttrExpression; +use Twig\Node\Expression\NameExpression; +use Twig\Node\Expression\TestExpression; + +/** + * Checks if a variable is defined in the current context. + * + * {# defined works with variable names and variable attributes #} + * {% if foo is defined %} + * {# ... #} + * {% endif %} + * + * @author Fabien Potencier <fabien@symfony.com> + */ +class DefinedTest extends TestExpression +{ + public function __construct(\Twig_NodeInterface $node, $name, \Twig_NodeInterface $arguments = null, $lineno) + { + if ($node instanceof NameExpression) { + $node->setAttribute('is_defined_test', true); + } elseif ($node instanceof GetAttrExpression) { + $node->setAttribute('is_defined_test', true); + $this->changeIgnoreStrictCheck($node); + } elseif ($node instanceof BlockReferenceExpression) { + $node->setAttribute('is_defined_test', true); + } elseif ($node instanceof FunctionExpression && 'constant' === $node->getAttribute('name')) { + $node->setAttribute('is_defined_test', true); + } elseif ($node instanceof ConstantExpression || $node instanceof ArrayExpression) { + $node = new ConstantExpression(true, $node->getTemplateLine()); + } else { + throw new SyntaxError('The "defined" test only works with simple variables.', $lineno); + } + + parent::__construct($node, $name, $arguments, $lineno); + } + + protected function changeIgnoreStrictCheck(GetAttrExpression $node) + { + $node->setAttribute('ignore_strict_check', true); -if (\false) { - class DefinedTest extends \Twig_Node_Expression_Test_Defined + if ($node->getNode('node') instanceof GetAttrExpression) { + $this->changeIgnoreStrictCheck($node->getNode('node')); + } + } + + public function compile(Compiler $compiler) { + $compiler->subcompile($this->getNode('node')); } } + +class_alias('Twig\Node\Expression\Test\DefinedTest', 'Twig_Node_Expression_Test_Defined'); diff --git a/vendor/twig/twig/src/Node/Expression/Test/DivisiblebyTest.php b/vendor/twig/twig/src/Node/Expression/Test/DivisiblebyTest.php index e9d9100480a1ec0919a8fa6b801e6b5235162aa3..05c8ad8f7c39f9743ab78db3c2c52933b46bae8c 100644 --- a/vendor/twig/twig/src/Node/Expression/Test/DivisiblebyTest.php +++ b/vendor/twig/twig/src/Node/Expression/Test/DivisiblebyTest.php @@ -1,11 +1,38 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\Node\Expression\Test; -class_exists('Twig_Node_Expression_Test_Divisibleby'); +use Twig\Compiler; +use Twig\Node\Expression\TestExpression; -if (\false) { - class DivisiblebyTest extends \Twig_Node_Expression_Test_Divisibleby +/** + * Checks if a variable is divisible by a number. + * + * {% if loop.index is divisible by(3) %} + * + * @author Fabien Potencier <fabien@symfony.com> + */ +class DivisiblebyTest extends TestExpression +{ + public function compile(Compiler $compiler) { + $compiler + ->raw('(0 == ') + ->subcompile($this->getNode('node')) + ->raw(' % ') + ->subcompile($this->getNode('arguments')->getNode(0)) + ->raw(')') + ; } } + +class_alias('Twig\Node\Expression\Test\DivisiblebyTest', 'Twig_Node_Expression_Test_Divisibleby'); diff --git a/vendor/twig/twig/src/Node/Expression/Test/EvenTest.php b/vendor/twig/twig/src/Node/Expression/Test/EvenTest.php index feb3a89c08a166dbfb2a59a7bf6ae4fd8d3ad3c4..3b955d26a2fceb9c5ebf135914084f6fb7b3172c 100644 --- a/vendor/twig/twig/src/Node/Expression/Test/EvenTest.php +++ b/vendor/twig/twig/src/Node/Expression/Test/EvenTest.php @@ -1,11 +1,37 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\Node\Expression\Test; -class_exists('Twig_Node_Expression_Test_Even'); +use Twig\Compiler; +use Twig\Node\Expression\TestExpression; -if (\false) { - class EvenTest extends \Twig_Node_Expression_Test_Even +/** + * Checks if a number is even. + * + * {{ var is even }} + * + * @author Fabien Potencier <fabien@symfony.com> + */ +class EvenTest extends TestExpression +{ + public function compile(Compiler $compiler) { + $compiler + ->raw('(') + ->subcompile($this->getNode('node')) + ->raw(' % 2 == 0') + ->raw(')') + ; } } + +class_alias('Twig\Node\Expression\Test\EvenTest', 'Twig_Node_Expression_Test_Even'); diff --git a/vendor/twig/twig/src/Node/Expression/Test/NullTest.php b/vendor/twig/twig/src/Node/Expression/Test/NullTest.php index 2263b1b2ba012015f10b9504d03ea29eb48a5347..24d399781ecd98c930dc0ab107e42955267d268f 100644 --- a/vendor/twig/twig/src/Node/Expression/Test/NullTest.php +++ b/vendor/twig/twig/src/Node/Expression/Test/NullTest.php @@ -1,11 +1,36 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\Node\Expression\Test; -class_exists('Twig_Node_Expression_Test_Null'); +use Twig\Compiler; +use Twig\Node\Expression\TestExpression; -if (\false) { - class NullTest extends \Twig_Node_Expression_Test_Null +/** + * Checks that a variable is null. + * + * {{ var is none }} + * + * @author Fabien Potencier <fabien@symfony.com> + */ +class NullTest extends TestExpression +{ + public function compile(Compiler $compiler) { + $compiler + ->raw('(null === ') + ->subcompile($this->getNode('node')) + ->raw(')') + ; } } + +class_alias('Twig\Node\Expression\Test\NullTest', 'Twig_Node_Expression_Test_Null'); diff --git a/vendor/twig/twig/src/Node/Expression/Test/OddTest.php b/vendor/twig/twig/src/Node/Expression/Test/OddTest.php index 86ddb22450146258de73c028363fe6b6400a99df..2dc693a9ae6f613b1517e8f410330a014ceaaef1 100644 --- a/vendor/twig/twig/src/Node/Expression/Test/OddTest.php +++ b/vendor/twig/twig/src/Node/Expression/Test/OddTest.php @@ -1,11 +1,37 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\Node\Expression\Test; -class_exists('Twig_Node_Expression_Test_Odd'); +use Twig\Compiler; +use Twig\Node\Expression\TestExpression; -if (\false) { - class OddTest extends \Twig_Node_Expression_Test_Odd +/** + * Checks if a number is odd. + * + * {{ var is odd }} + * + * @author Fabien Potencier <fabien@symfony.com> + */ +class OddTest extends TestExpression +{ + public function compile(Compiler $compiler) { + $compiler + ->raw('(') + ->subcompile($this->getNode('node')) + ->raw(' % 2 == 1') + ->raw(')') + ; } } + +class_alias('Twig\Node\Expression\Test\OddTest', 'Twig_Node_Expression_Test_Odd'); diff --git a/vendor/twig/twig/src/Node/Expression/Test/SameasTest.php b/vendor/twig/twig/src/Node/Expression/Test/SameasTest.php index 26a8f0ea5cffee0e112fc7b14bb01f03733e5bcc..75f2b82a5bbf8cbea257fc724450a2cc1b3c7044 100644 --- a/vendor/twig/twig/src/Node/Expression/Test/SameasTest.php +++ b/vendor/twig/twig/src/Node/Expression/Test/SameasTest.php @@ -1,11 +1,36 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\Node\Expression\Test; -class_exists('Twig_Node_Expression_Test_Sameas'); +use Twig\Compiler; +use Twig\Node\Expression\TestExpression; -if (\false) { - class SameasTest extends \Twig_Node_Expression_Test_Sameas +/** + * Checks if a variable is the same as another one (=== in PHP). + * + * @author Fabien Potencier <fabien@symfony.com> + */ +class SameasTest extends TestExpression +{ + public function compile(Compiler $compiler) { + $compiler + ->raw('(') + ->subcompile($this->getNode('node')) + ->raw(' === ') + ->subcompile($this->getNode('arguments')->getNode(0)) + ->raw(')') + ; } } + +class_alias('Twig\Node\Expression\Test\SameasTest', 'Twig_Node_Expression_Test_Sameas'); diff --git a/vendor/twig/twig/src/Node/Expression/TestExpression.php b/vendor/twig/twig/src/Node/Expression/TestExpression.php index f3d4f903ffe57b3b9464ad37a08bf2ff5eda3a27..8fc31d3aadc028969f7b4bddf6d92f0ebebfda65 100644 --- a/vendor/twig/twig/src/Node/Expression/TestExpression.php +++ b/vendor/twig/twig/src/Node/Expression/TestExpression.php @@ -1,11 +1,51 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\Node\Expression; -class_exists('Twig_Node_Expression_Test'); +use Twig\Compiler; +use Twig\TwigTest; + +class TestExpression extends CallExpression +{ + public function __construct(\Twig_NodeInterface $node, $name, \Twig_NodeInterface $arguments = null, $lineno) + { + $nodes = ['node' => $node]; + if (null !== $arguments) { + $nodes['arguments'] = $arguments; + } + + parent::__construct($nodes, ['name' => $name], $lineno); + } -if (\false) { - class TestExpression extends \Twig_Node_Expression_Test + public function compile(Compiler $compiler) { + $name = $this->getAttribute('name'); + $test = $compiler->getEnvironment()->getTest($name); + + $this->setAttribute('name', $name); + $this->setAttribute('type', 'test'); + $this->setAttribute('thing', $test); + if ($test instanceof TwigTest) { + $this->setAttribute('arguments', $test->getArguments()); + } + if ($test instanceof \Twig_TestCallableInterface || $test instanceof TwigTest) { + $this->setAttribute('callable', $test->getCallable()); + } + if ($test instanceof TwigTest) { + $this->setAttribute('is_variadic', $test->isVariadic()); + } + + $this->compileCallable($compiler); } } + +class_alias('Twig\Node\Expression\TestExpression', 'Twig_Node_Expression_Test'); diff --git a/vendor/twig/twig/src/Node/Expression/Unary/AbstractUnary.php b/vendor/twig/twig/src/Node/Expression/Unary/AbstractUnary.php index 7d998559a78aa241f9d56c00be8ef66dfd892ed9..415c3d407e9e4aad02122698c464801370f9319e 100644 --- a/vendor/twig/twig/src/Node/Expression/Unary/AbstractUnary.php +++ b/vendor/twig/twig/src/Node/Expression/Unary/AbstractUnary.php @@ -1,11 +1,35 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * (c) Armin Ronacher + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\Node\Expression\Unary; -class_exists('Twig_Node_Expression_Unary'); +use Twig\Compiler; +use Twig\Node\Expression\AbstractExpression; + +abstract class AbstractUnary extends AbstractExpression +{ + public function __construct(\Twig_NodeInterface $node, $lineno) + { + parent::__construct(['node' => $node], [], $lineno); + } -if (\false) { - class AbstractUnary extends \Twig_Node_Expression_Unary + public function compile(Compiler $compiler) { + $compiler->raw(' '); + $this->operator($compiler); + $compiler->subcompile($this->getNode('node')); } + + abstract public function operator(Compiler $compiler); } + +class_alias('Twig\Node\Expression\Unary\AbstractUnary', 'Twig_Node_Expression_Unary'); diff --git a/vendor/twig/twig/src/Node/Expression/Unary/NegUnary.php b/vendor/twig/twig/src/Node/Expression/Unary/NegUnary.php index 344b1216cf5fbd00ffc96bfaf606fc31eb7bda31..dfb6f542954a0de504d9c5c62d0fcb5319301456 100644 --- a/vendor/twig/twig/src/Node/Expression/Unary/NegUnary.php +++ b/vendor/twig/twig/src/Node/Expression/Unary/NegUnary.php @@ -1,11 +1,25 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * (c) Armin Ronacher + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\Node\Expression\Unary; -class_exists('Twig_Node_Expression_Unary_Neg'); +use Twig\Compiler; -if (\false) { - class NegUnary extends \Twig_Node_Expression_Unary_Neg +class NegUnary extends AbstractUnary +{ + public function operator(Compiler $compiler) { + $compiler->raw('-'); } } + +class_alias('Twig\Node\Expression\Unary\NegUnary', 'Twig_Node_Expression_Unary_Neg'); diff --git a/vendor/twig/twig/src/Node/Expression/Unary/NotUnary.php b/vendor/twig/twig/src/Node/Expression/Unary/NotUnary.php index 79c246286a92c8f01629201e42379c9b6316c3be..7bdde96fffc7c84f255258cbae8bb7e23332b752 100644 --- a/vendor/twig/twig/src/Node/Expression/Unary/NotUnary.php +++ b/vendor/twig/twig/src/Node/Expression/Unary/NotUnary.php @@ -1,11 +1,25 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * (c) Armin Ronacher + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\Node\Expression\Unary; -class_exists('Twig_Node_Expression_Unary_Not'); +use Twig\Compiler; -if (\false) { - class NotUnary extends \Twig_Node_Expression_Unary_Not +class NotUnary extends AbstractUnary +{ + public function operator(Compiler $compiler) { + $compiler->raw('!'); } } + +class_alias('Twig\Node\Expression\Unary\NotUnary', 'Twig_Node_Expression_Unary_Not'); diff --git a/vendor/twig/twig/src/Node/Expression/Unary/PosUnary.php b/vendor/twig/twig/src/Node/Expression/Unary/PosUnary.php index 24d88ccbe2d32a91c85dc9edaad58d6d68aa1f70..52d5d0c89a774a5368eaacdb7342dcbc7c4976f5 100644 --- a/vendor/twig/twig/src/Node/Expression/Unary/PosUnary.php +++ b/vendor/twig/twig/src/Node/Expression/Unary/PosUnary.php @@ -1,11 +1,25 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * (c) Armin Ronacher + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\Node\Expression\Unary; -class_exists('Twig_Node_Expression_Unary_Pos'); +use Twig\Compiler; -if (\false) { - class PosUnary extends \Twig_Node_Expression_Unary_Pos +class PosUnary extends AbstractUnary +{ + public function operator(Compiler $compiler) { + $compiler->raw('+'); } } + +class_alias('Twig\Node\Expression\Unary\PosUnary', 'Twig_Node_Expression_Unary_Pos'); diff --git a/vendor/twig/twig/src/Node/FlushNode.php b/vendor/twig/twig/src/Node/FlushNode.php index c06306e1fca3b36c95dc97d298064a3d6faa0822..6cbc489a62de1222171b5924bfec3bd022cb9c75 100644 --- a/vendor/twig/twig/src/Node/FlushNode.php +++ b/vendor/twig/twig/src/Node/FlushNode.php @@ -1,11 +1,37 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\Node; -class_exists('Twig_Node_Flush'); +use Twig\Compiler; -if (\false) { - class FlushNode extends \Twig_Node_Flush +/** + * Represents a flush node. + * + * @author Fabien Potencier <fabien@symfony.com> + */ +class FlushNode extends Node +{ + public function __construct($lineno, $tag) { + parent::__construct([], [], $lineno, $tag); + } + + public function compile(Compiler $compiler) + { + $compiler + ->addDebugInfo($this) + ->write("flush();\n") + ; } } + +class_alias('Twig\Node\FlushNode', 'Twig_Node_Flush'); diff --git a/vendor/twig/twig/src/Node/ForLoopNode.php b/vendor/twig/twig/src/Node/ForLoopNode.php index e8e3936c8726f93e58ce41b1b17d46c2af21483e..3902093556b93693981d8c3ed5fa111706e32be1 100644 --- a/vendor/twig/twig/src/Node/ForLoopNode.php +++ b/vendor/twig/twig/src/Node/ForLoopNode.php @@ -1,11 +1,56 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\Node; -class_exists('Twig_Node_ForLoop'); +use Twig\Compiler; -if (\false) { - class ForLoopNode extends \Twig_Node_ForLoop +/** + * Internal node used by the for node. + * + * @author Fabien Potencier <fabien@symfony.com> + */ +class ForLoopNode extends Node +{ + public function __construct($lineno, $tag = null) { + parent::__construct([], ['with_loop' => false, 'ifexpr' => false, 'else' => false], $lineno, $tag); + } + + public function compile(Compiler $compiler) + { + if ($this->getAttribute('else')) { + $compiler->write("\$context['_iterated'] = true;\n"); + } + + if ($this->getAttribute('with_loop')) { + $compiler + ->write("++\$context['loop']['index0'];\n") + ->write("++\$context['loop']['index'];\n") + ->write("\$context['loop']['first'] = false;\n") + ; + + if (!$this->getAttribute('ifexpr')) { + $compiler + ->write("if (isset(\$context['loop']['length'])) {\n") + ->indent() + ->write("--\$context['loop']['revindex0'];\n") + ->write("--\$context['loop']['revindex'];\n") + ->write("\$context['loop']['last'] = 0 === \$context['loop']['revindex0'];\n") + ->outdent() + ->write("}\n") + ; + } + } } } + +class_alias('Twig\Node\ForLoopNode', 'Twig_Node_ForLoop'); diff --git a/vendor/twig/twig/src/Node/ForNode.php b/vendor/twig/twig/src/Node/ForNode.php index 86521f4ee2cb2ecaeaa8965af3652a5f39a2cf57..49409a39b18eedfc743bfbbcc028aa2b6f260a46 100644 --- a/vendor/twig/twig/src/Node/ForNode.php +++ b/vendor/twig/twig/src/Node/ForNode.php @@ -1,11 +1,119 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * (c) Armin Ronacher + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\Node; -class_exists('Twig_Node_For'); +use Twig\Compiler; +use Twig\Node\Expression\AbstractExpression; +use Twig\Node\Expression\AssignNameExpression; + +/** + * Represents a for node. + * + * @author Fabien Potencier <fabien@symfony.com> + */ +class ForNode extends Node +{ + protected $loop; -if (\false) { - class ForNode extends \Twig_Node_For + public function __construct(AssignNameExpression $keyTarget, AssignNameExpression $valueTarget, AbstractExpression $seq, AbstractExpression $ifexpr = null, \Twig_NodeInterface $body, \Twig_NodeInterface $else = null, $lineno, $tag = null) { + $body = new Node([$body, $this->loop = new ForLoopNode($lineno, $tag)]); + + if (null !== $ifexpr) { + $body = new IfNode(new Node([$ifexpr, $body]), null, $lineno, $tag); + } + + $nodes = ['key_target' => $keyTarget, 'value_target' => $valueTarget, 'seq' => $seq, 'body' => $body]; + if (null !== $else) { + $nodes['else'] = $else; + } + + parent::__construct($nodes, ['with_loop' => true, 'ifexpr' => null !== $ifexpr], $lineno, $tag); + } + + public function compile(Compiler $compiler) + { + $compiler + ->addDebugInfo($this) + ->write("\$context['_parent'] = \$context;\n") + ->write("\$context['_seq'] = twig_ensure_traversable(") + ->subcompile($this->getNode('seq')) + ->raw(");\n") + ; + + if ($this->hasNode('else')) { + $compiler->write("\$context['_iterated'] = false;\n"); + } + + if ($this->getAttribute('with_loop')) { + $compiler + ->write("\$context['loop'] = [\n") + ->write(" 'parent' => \$context['_parent'],\n") + ->write(" 'index0' => 0,\n") + ->write(" 'index' => 1,\n") + ->write(" 'first' => true,\n") + ->write("];\n") + ; + + if (!$this->getAttribute('ifexpr')) { + $compiler + ->write("if (is_array(\$context['_seq']) || (is_object(\$context['_seq']) && \$context['_seq'] instanceof \Countable)) {\n") + ->indent() + ->write("\$length = count(\$context['_seq']);\n") + ->write("\$context['loop']['revindex0'] = \$length - 1;\n") + ->write("\$context['loop']['revindex'] = \$length;\n") + ->write("\$context['loop']['length'] = \$length;\n") + ->write("\$context['loop']['last'] = 1 === \$length;\n") + ->outdent() + ->write("}\n") + ; + } + } + + $this->loop->setAttribute('else', $this->hasNode('else')); + $this->loop->setAttribute('with_loop', $this->getAttribute('with_loop')); + $this->loop->setAttribute('ifexpr', $this->getAttribute('ifexpr')); + + $compiler + ->write("foreach (\$context['_seq'] as ") + ->subcompile($this->getNode('key_target')) + ->raw(' => ') + ->subcompile($this->getNode('value_target')) + ->raw(") {\n") + ->indent() + ->subcompile($this->getNode('body')) + ->outdent() + ->write("}\n") + ; + + if ($this->hasNode('else')) { + $compiler + ->write("if (!\$context['_iterated']) {\n") + ->indent() + ->subcompile($this->getNode('else')) + ->outdent() + ->write("}\n") + ; + } + + $compiler->write("\$_parent = \$context['_parent'];\n"); + + // remove some "private" loop variables (needed for nested loops) + $compiler->write('unset($context[\'_seq\'], $context[\'_iterated\'], $context[\''.$this->getNode('key_target')->getAttribute('name').'\'], $context[\''.$this->getNode('value_target')->getAttribute('name').'\'], $context[\'_parent\'], $context[\'loop\']);'."\n"); + + // keep the values set in the inner context for variables defined in the outer context + $compiler->write("\$context = array_intersect_key(\$context, \$_parent) + \$_parent;\n"); } } + +class_alias('Twig\Node\ForNode', 'Twig_Node_For'); diff --git a/vendor/twig/twig/src/Node/IfNode.php b/vendor/twig/twig/src/Node/IfNode.php index 2710ead0d352f69f07fb5513b4d334af944ce965..4836d91f088f311086519720f7c7e1ffd0041346 100644 --- a/vendor/twig/twig/src/Node/IfNode.php +++ b/vendor/twig/twig/src/Node/IfNode.php @@ -1,11 +1,72 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * (c) Armin Ronacher + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\Node; -class_exists('Twig_Node_If'); +use Twig\Compiler; -if (\false) { - class IfNode extends \Twig_Node_If +/** + * Represents an if node. + * + * @author Fabien Potencier <fabien@symfony.com> + */ +class IfNode extends Node +{ + public function __construct(\Twig_NodeInterface $tests, \Twig_NodeInterface $else = null, $lineno, $tag = null) { + $nodes = ['tests' => $tests]; + if (null !== $else) { + $nodes['else'] = $else; + } + + parent::__construct($nodes, [], $lineno, $tag); + } + + public function compile(Compiler $compiler) + { + $compiler->addDebugInfo($this); + for ($i = 0, $count = \count($this->getNode('tests')); $i < $count; $i += 2) { + if ($i > 0) { + $compiler + ->outdent() + ->write('} elseif (') + ; + } else { + $compiler + ->write('if (') + ; + } + + $compiler + ->subcompile($this->getNode('tests')->getNode($i)) + ->raw(") {\n") + ->indent() + ->subcompile($this->getNode('tests')->getNode($i + 1)) + ; + } + + if ($this->hasNode('else')) { + $compiler + ->outdent() + ->write("} else {\n") + ->indent() + ->subcompile($this->getNode('else')) + ; + } + + $compiler + ->outdent() + ->write("}\n"); } } + +class_alias('Twig\Node\IfNode', 'Twig_Node_If'); diff --git a/vendor/twig/twig/src/Node/ImportNode.php b/vendor/twig/twig/src/Node/ImportNode.php index 0bc23f339231169c16a2efc9c3d2ae34860b1817..236db8900ea29162be0c16daaaced5c15b55b6c0 100644 --- a/vendor/twig/twig/src/Node/ImportNode.php +++ b/vendor/twig/twig/src/Node/ImportNode.php @@ -1,11 +1,57 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\Node; -class_exists('Twig_Node_Import'); +use Twig\Compiler; +use Twig\Node\Expression\AbstractExpression; +use Twig\Node\Expression\NameExpression; -if (\false) { - class ImportNode extends \Twig_Node_Import +/** + * Represents an import node. + * + * @author Fabien Potencier <fabien@symfony.com> + */ +class ImportNode extends Node +{ + public function __construct(AbstractExpression $expr, AbstractExpression $var, $lineno, $tag = null) { + parent::__construct(['expr' => $expr, 'var' => $var], [], $lineno, $tag); + } + + public function compile(Compiler $compiler) + { + $compiler + ->addDebugInfo($this) + ->write('') + ->subcompile($this->getNode('var')) + ->raw(' = ') + ; + + if ($this->getNode('expr') instanceof NameExpression && '_self' === $this->getNode('expr')->getAttribute('name')) { + $compiler->raw('$this'); + } else { + $compiler + ->raw('$this->loadTemplate(') + ->subcompile($this->getNode('expr')) + ->raw(', ') + ->repr($this->getTemplateName()) + ->raw(', ') + ->repr($this->getTemplateLine()) + ->raw(')->unwrap()') + ; + } + + $compiler->raw(";\n"); } } + +class_alias('Twig\Node\ImportNode', 'Twig_Node_Import'); diff --git a/vendor/twig/twig/src/Node/IncludeNode.php b/vendor/twig/twig/src/Node/IncludeNode.php index d557efee2bb597e10b1399a9b3c03da8db365d2c..544db81eaf39c8ff9b470fa6ca5cd577afbac9d0 100644 --- a/vendor/twig/twig/src/Node/IncludeNode.php +++ b/vendor/twig/twig/src/Node/IncludeNode.php @@ -1,11 +1,108 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * (c) Armin Ronacher + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\Node; -class_exists('Twig_Node_Include'); +use Twig\Compiler; +use Twig\Node\Expression\AbstractExpression; + +/** + * Represents an include node. + * + * @author Fabien Potencier <fabien@symfony.com> + */ +class IncludeNode extends Node implements NodeOutputInterface +{ + public function __construct(AbstractExpression $expr, AbstractExpression $variables = null, $only = false, $ignoreMissing = false, $lineno, $tag = null) + { + $nodes = ['expr' => $expr]; + if (null !== $variables) { + $nodes['variables'] = $variables; + } + + parent::__construct($nodes, ['only' => (bool) $only, 'ignore_missing' => (bool) $ignoreMissing], $lineno, $tag); + } + + public function compile(Compiler $compiler) + { + $compiler->addDebugInfo($this); + + if ($this->getAttribute('ignore_missing')) { + $template = $compiler->getVarName(); -if (\false) { - class IncludeNode extends \Twig_Node_Include + $compiler + ->write(sprintf("$%s = null;\n", $template)) + ->write("try {\n") + ->indent() + ->write(sprintf('$%s = ', $template)) + ; + + $this->addGetTemplate($compiler); + + $compiler + ->raw(";\n") + ->outdent() + ->write("} catch (LoaderError \$e) {\n") + ->indent() + ->write("// ignore missing template\n") + ->outdent() + ->write("}\n") + ->write(sprintf("if ($%s) {\n", $template)) + ->indent() + ->write(sprintf('$%s->display(', $template)) + ; + $this->addTemplateArguments($compiler); + $compiler + ->raw(");\n") + ->outdent() + ->write("}\n") + ; + } else { + $this->addGetTemplate($compiler); + $compiler->raw('->display('); + $this->addTemplateArguments($compiler); + $compiler->raw(");\n"); + } + } + + protected function addGetTemplate(Compiler $compiler) { + $compiler + ->write('$this->loadTemplate(') + ->subcompile($this->getNode('expr')) + ->raw(', ') + ->repr($this->getTemplateName()) + ->raw(', ') + ->repr($this->getTemplateLine()) + ->raw(')') + ; + } + + protected function addTemplateArguments(Compiler $compiler) + { + if (!$this->hasNode('variables')) { + $compiler->raw(false === $this->getAttribute('only') ? '$context' : '[]'); + } elseif (false === $this->getAttribute('only')) { + $compiler + ->raw('twig_array_merge($context, ') + ->subcompile($this->getNode('variables')) + ->raw(')') + ; + } else { + $compiler->raw('twig_to_array('); + $compiler->subcompile($this->getNode('variables')); + $compiler->raw(')'); + } } } + +class_alias('Twig\Node\IncludeNode', 'Twig_Node_Include'); diff --git a/vendor/twig/twig/src/Node/MacroNode.php b/vendor/twig/twig/src/Node/MacroNode.php index 5752c6c8be69fdbe492b24444b9508dbcf9fdfd5..6eb67955f4b36ffd830c81745eaaa58199d1af4b 100644 --- a/vendor/twig/twig/src/Node/MacroNode.php +++ b/vendor/twig/twig/src/Node/MacroNode.php @@ -1,11 +1,136 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\Node; -class_exists('Twig_Node_Macro'); +use Twig\Compiler; +use Twig\Error\SyntaxError; + +/** + * Represents a macro node. + * + * @author Fabien Potencier <fabien@symfony.com> + */ +class MacroNode extends Node +{ + const VARARGS_NAME = 'varargs'; -if (\false) { - class MacroNode extends \Twig_Node_Macro + public function __construct($name, \Twig_NodeInterface $body, \Twig_NodeInterface $arguments, $lineno, $tag = null) { + foreach ($arguments as $argumentName => $argument) { + if (self::VARARGS_NAME === $argumentName) { + throw new SyntaxError(sprintf('The argument "%s" in macro "%s" cannot be defined because the variable "%s" is reserved for arbitrary arguments.', self::VARARGS_NAME, $name, self::VARARGS_NAME), $argument->getTemplateLine(), $argument->getSourceContext()); + } + } + + parent::__construct(['body' => $body, 'arguments' => $arguments], ['name' => $name], $lineno, $tag); + } + + public function compile(Compiler $compiler) + { + $compiler + ->addDebugInfo($this) + ->write(sprintf('public function get%s(', $this->getAttribute('name'))) + ; + + $count = \count($this->getNode('arguments')); + $pos = 0; + foreach ($this->getNode('arguments') as $name => $default) { + $compiler + ->raw('$__'.$name.'__ = ') + ->subcompile($default) + ; + + if (++$pos < $count) { + $compiler->raw(', '); + } + } + + if (\PHP_VERSION_ID >= 50600) { + if ($count) { + $compiler->raw(', '); + } + + $compiler->raw('...$__varargs__'); + } + + $compiler + ->raw(")\n") + ->write("{\n") + ->indent() + ; + + $compiler + ->write("\$context = \$this->env->mergeGlobals([\n") + ->indent() + ; + + foreach ($this->getNode('arguments') as $name => $default) { + $compiler + ->write('') + ->string($name) + ->raw(' => $__'.$name.'__') + ->raw(",\n") + ; + } + + $compiler + ->write('') + ->string(self::VARARGS_NAME) + ->raw(' => ') + ; + + if (\PHP_VERSION_ID >= 50600) { + $compiler->raw("\$__varargs__,\n"); + } else { + $compiler + ->raw('func_num_args() > ') + ->repr($count) + ->raw(' ? array_slice(func_get_args(), ') + ->repr($count) + ->raw(") : [],\n") + ; + } + + $compiler + ->outdent() + ->write("]);\n\n") + ->write("\$blocks = [];\n\n") + ; + if ($compiler->getEnvironment()->isDebug()) { + $compiler->write("ob_start();\n"); + } else { + $compiler->write("ob_start(function () { return ''; });\n"); + } + $compiler + ->write("try {\n") + ->indent() + ->subcompile($this->getNode('body')) + ->outdent() + ->write("} catch (\Exception \$e) {\n") + ->indent() + ->write("ob_end_clean();\n\n") + ->write("throw \$e;\n") + ->outdent() + ->write("} catch (\Throwable \$e) {\n") + ->indent() + ->write("ob_end_clean();\n\n") + ->write("throw \$e;\n") + ->outdent() + ->write("}\n\n") + ->write("return ('' === \$tmp = ob_get_clean()) ? '' : new Markup(\$tmp, \$this->env->getCharset());\n") + ->outdent() + ->write("}\n\n") + ; } } + +class_alias('Twig\Node\MacroNode', 'Twig_Node_Macro'); diff --git a/vendor/twig/twig/src/Node/ModuleNode.php b/vendor/twig/twig/src/Node/ModuleNode.php index d39c6ff0f6a63b4a5c6d42e59e8f1f7c79ab114a..aab2aa33f2d166ddb1c155af578c599977baac8a 100644 --- a/vendor/twig/twig/src/Node/ModuleNode.php +++ b/vendor/twig/twig/src/Node/ModuleNode.php @@ -1,11 +1,492 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * (c) Armin Ronacher + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\Node; -class_exists('Twig_Node_Module'); +use Twig\Compiler; +use Twig\Node\Expression\AbstractExpression; +use Twig\Node\Expression\ConstantExpression; +use Twig\Source; + +/** + * Represents a module node. + * + * Consider this class as being final. If you need to customize the behavior of + * the generated class, consider adding nodes to the following nodes: display_start, + * display_end, constructor_start, constructor_end, and class_end. + * + * @author Fabien Potencier <fabien@symfony.com> + */ +class ModuleNode extends Node +{ + public function __construct(\Twig_NodeInterface $body, AbstractExpression $parent = null, \Twig_NodeInterface $blocks, \Twig_NodeInterface $macros, \Twig_NodeInterface $traits, $embeddedTemplates, $name, $source = '') + { + if (!$name instanceof Source) { + @trigger_error(sprintf('Passing a string as the $name argument of %s() is deprecated since version 1.27. Pass a \Twig\Source instance instead.', __METHOD__), E_USER_DEPRECATED); + $source = new Source($source, $name); + } else { + $source = $name; + } + + $nodes = [ + 'body' => $body, + 'blocks' => $blocks, + 'macros' => $macros, + 'traits' => $traits, + 'display_start' => new Node(), + 'display_end' => new Node(), + 'constructor_start' => new Node(), + 'constructor_end' => new Node(), + 'class_end' => new Node(), + ]; + if (null !== $parent) { + $nodes['parent'] = $parent; + } + + // embedded templates are set as attributes so that they are only visited once by the visitors + parent::__construct($nodes, [ + // source to be remove in 2.0 + 'source' => $source->getCode(), + // filename to be remove in 2.0 (use getTemplateName() instead) + 'filename' => $source->getName(), + 'index' => null, + 'embedded_templates' => $embeddedTemplates, + ], 1); + + // populate the template name of all node children + $this->setTemplateName($source->getName()); + $this->setSourceContext($source); + } + + public function setIndex($index) + { + $this->setAttribute('index', $index); + } -if (\false) { - class ModuleNode extends \Twig_Node_Module + public function compile(Compiler $compiler) { + $this->compileTemplate($compiler); + + foreach ($this->getAttribute('embedded_templates') as $template) { + $compiler->subcompile($template); + } + } + + protected function compileTemplate(Compiler $compiler) + { + if (!$this->getAttribute('index')) { + $compiler->write('<?php'); + } + + $this->compileClassHeader($compiler); + + if ( + \count($this->getNode('blocks')) + || \count($this->getNode('traits')) + || !$this->hasNode('parent') + || $this->getNode('parent') instanceof ConstantExpression + || \count($this->getNode('constructor_start')) + || \count($this->getNode('constructor_end')) + ) { + $this->compileConstructor($compiler); + } + + $this->compileGetParent($compiler); + + $this->compileDisplay($compiler); + + $compiler->subcompile($this->getNode('blocks')); + + $this->compileMacros($compiler); + + $this->compileGetTemplateName($compiler); + + $this->compileIsTraitable($compiler); + + $this->compileDebugInfo($compiler); + + $this->compileGetSource($compiler); + + $this->compileGetSourceContext($compiler); + + $this->compileClassFooter($compiler); + } + + protected function compileGetParent(Compiler $compiler) + { + if (!$this->hasNode('parent')) { + return; + } + $parent = $this->getNode('parent'); + + $compiler + ->write("protected function doGetParent(array \$context)\n", "{\n") + ->indent() + ->addDebugInfo($parent) + ->write('return ') + ; + + if ($parent instanceof ConstantExpression) { + $compiler->subcompile($parent); + } else { + $compiler + ->raw('$this->loadTemplate(') + ->subcompile($parent) + ->raw(', ') + ->repr($this->getSourceContext()->getName()) + ->raw(', ') + ->repr($parent->getTemplateLine()) + ->raw(')') + ; + } + + $compiler + ->raw(";\n") + ->outdent() + ->write("}\n\n") + ; + } + + protected function compileClassHeader(Compiler $compiler) + { + $compiler + ->write("\n\n") + ; + if (!$this->getAttribute('index')) { + $compiler + ->write("use Twig\Environment;\n") + ->write("use Twig\Error\LoaderError;\n") + ->write("use Twig\Error\RuntimeError;\n") + ->write("use Twig\Markup;\n") + ->write("use Twig\Sandbox\SecurityError;\n") + ->write("use Twig\Sandbox\SecurityNotAllowedTagError;\n") + ->write("use Twig\Sandbox\SecurityNotAllowedFilterError;\n") + ->write("use Twig\Sandbox\SecurityNotAllowedFunctionError;\n") + ->write("use Twig\Source;\n") + ->write("use Twig\Template;\n\n") + ; + } + $compiler + // if the template name contains */, add a blank to avoid a PHP parse error + ->write('/* '.str_replace('*/', '* /', $this->getSourceContext()->getName())." */\n") + ->write('class '.$compiler->getEnvironment()->getTemplateClass($this->getSourceContext()->getName(), $this->getAttribute('index'))) + ->raw(sprintf(" extends %s\n", $compiler->getEnvironment()->getBaseTemplateClass())) + ->write("{\n") + ->indent() + ; + } + + protected function compileConstructor(Compiler $compiler) + { + $compiler + ->write("public function __construct(Environment \$env)\n", "{\n") + ->indent() + ->subcompile($this->getNode('constructor_start')) + ->write("parent::__construct(\$env);\n\n") + ; + + // parent + if (!$this->hasNode('parent')) { + $compiler->write("\$this->parent = false;\n\n"); + } + + $countTraits = \count($this->getNode('traits')); + if ($countTraits) { + // traits + foreach ($this->getNode('traits') as $i => $trait) { + $this->compileLoadTemplate($compiler, $trait->getNode('template'), sprintf('$_trait_%s', $i)); + + $node = $trait->getNode('template'); + $compiler + ->addDebugInfo($node) + ->write(sprintf("if (!\$_trait_%s->isTraitable()) {\n", $i)) + ->indent() + ->write("throw new RuntimeError('Template \"'.") + ->subcompile($trait->getNode('template')) + ->raw(".'\" cannot be used as a trait.', ") + ->repr($node->getTemplateLine()) + ->raw(", \$this->getSourceContext());\n") + ->outdent() + ->write("}\n") + ->write(sprintf("\$_trait_%s_blocks = \$_trait_%s->getBlocks();\n\n", $i, $i)) + ; + + foreach ($trait->getNode('targets') as $key => $value) { + $compiler + ->write(sprintf('if (!isset($_trait_%s_blocks[', $i)) + ->string($key) + ->raw("])) {\n") + ->indent() + ->write("throw new RuntimeError(sprintf('Block ") + ->string($key) + ->raw(' is not defined in trait ') + ->subcompile($trait->getNode('template')) + ->raw(".'), ") + ->repr($node->getTemplateLine()) + ->raw(", \$this->getSourceContext());\n") + ->outdent() + ->write("}\n\n") + + ->write(sprintf('$_trait_%s_blocks[', $i)) + ->subcompile($value) + ->raw(sprintf('] = $_trait_%s_blocks[', $i)) + ->string($key) + ->raw(sprintf(']; unset($_trait_%s_blocks[', $i)) + ->string($key) + ->raw("]);\n\n") + ; + } + } + + if ($countTraits > 1) { + $compiler + ->write("\$this->traits = array_merge(\n") + ->indent() + ; + + for ($i = 0; $i < $countTraits; ++$i) { + $compiler + ->write(sprintf('$_trait_%s_blocks'.($i == $countTraits - 1 ? '' : ',')."\n", $i)) + ; + } + + $compiler + ->outdent() + ->write(");\n\n") + ; + } else { + $compiler + ->write("\$this->traits = \$_trait_0_blocks;\n\n") + ; + } + + $compiler + ->write("\$this->blocks = array_merge(\n") + ->indent() + ->write("\$this->traits,\n") + ->write("[\n") + ; + } else { + $compiler + ->write("\$this->blocks = [\n") + ; + } + + // blocks + $compiler + ->indent() + ; + + foreach ($this->getNode('blocks') as $name => $node) { + $compiler + ->write(sprintf("'%s' => [\$this, 'block_%s'],\n", $name, $name)) + ; + } + + if ($countTraits) { + $compiler + ->outdent() + ->write("]\n") + ->outdent() + ->write(");\n") + ; + } else { + $compiler + ->outdent() + ->write("];\n") + ; + } + + $compiler + ->subcompile($this->getNode('constructor_end')) + ->outdent() + ->write("}\n\n") + ; + } + + protected function compileDisplay(Compiler $compiler) + { + $compiler + ->write("protected function doDisplay(array \$context, array \$blocks = [])\n", "{\n") + ->indent() + ->subcompile($this->getNode('display_start')) + ->subcompile($this->getNode('body')) + ; + + if ($this->hasNode('parent')) { + $parent = $this->getNode('parent'); + + $compiler->addDebugInfo($parent); + if ($parent instanceof ConstantExpression) { + $compiler + ->write('$this->parent = $this->loadTemplate(') + ->subcompile($parent) + ->raw(', ') + ->repr($this->getSourceContext()->getName()) + ->raw(', ') + ->repr($parent->getTemplateLine()) + ->raw(");\n") + ; + $compiler->write('$this->parent'); + } else { + $compiler->write('$this->getParent($context)'); + } + $compiler->raw("->display(\$context, array_merge(\$this->blocks, \$blocks));\n"); + } + + $compiler + ->subcompile($this->getNode('display_end')) + ->outdent() + ->write("}\n\n") + ; + } + + protected function compileClassFooter(Compiler $compiler) + { + $compiler + ->subcompile($this->getNode('class_end')) + ->outdent() + ->write("}\n") + ; + } + + protected function compileMacros(Compiler $compiler) + { + $compiler->subcompile($this->getNode('macros')); + } + + protected function compileGetTemplateName(Compiler $compiler) + { + $compiler + ->write("public function getTemplateName()\n", "{\n") + ->indent() + ->write('return ') + ->repr($this->getSourceContext()->getName()) + ->raw(";\n") + ->outdent() + ->write("}\n\n") + ; + } + + protected function compileIsTraitable(Compiler $compiler) + { + // A template can be used as a trait if: + // * it has no parent + // * it has no macros + // * it has no body + // + // Put another way, a template can be used as a trait if it + // only contains blocks and use statements. + $traitable = !$this->hasNode('parent') && 0 === \count($this->getNode('macros')); + if ($traitable) { + if ($this->getNode('body') instanceof BodyNode) { + $nodes = $this->getNode('body')->getNode(0); + } else { + $nodes = $this->getNode('body'); + } + + if (!\count($nodes)) { + $nodes = new Node([$nodes]); + } + + foreach ($nodes as $node) { + if (!\count($node)) { + continue; + } + + if ($node instanceof TextNode && ctype_space($node->getAttribute('data'))) { + continue; + } + + if ($node instanceof BlockReferenceNode) { + continue; + } + + $traitable = false; + break; + } + } + + if ($traitable) { + return; + } + + $compiler + ->write("public function isTraitable()\n", "{\n") + ->indent() + ->write(sprintf("return %s;\n", $traitable ? 'true' : 'false')) + ->outdent() + ->write("}\n\n") + ; + } + + protected function compileDebugInfo(Compiler $compiler) + { + $compiler + ->write("public function getDebugInfo()\n", "{\n") + ->indent() + ->write(sprintf("return %s;\n", str_replace("\n", '', var_export(array_reverse($compiler->getDebugInfo(), true), true)))) + ->outdent() + ->write("}\n\n") + ; + } + + protected function compileGetSource(Compiler $compiler) + { + $compiler + ->write("/** @deprecated since 1.27 (to be removed in 2.0). Use getSourceContext() instead */\n") + ->write("public function getSource()\n", "{\n") + ->indent() + ->write("@trigger_error('The '.__METHOD__.' method is deprecated since version 1.27 and will be removed in 2.0. Use getSourceContext() instead.', E_USER_DEPRECATED);\n\n") + ->write('return $this->getSourceContext()->getCode();') + ->raw("\n") + ->outdent() + ->write("}\n\n") + ; + } + + protected function compileGetSourceContext(Compiler $compiler) + { + $compiler + ->write("public function getSourceContext()\n", "{\n") + ->indent() + ->write('return new Source(') + ->string($compiler->getEnvironment()->isDebug() ? $this->getSourceContext()->getCode() : '') + ->raw(', ') + ->string($this->getSourceContext()->getName()) + ->raw(', ') + ->string($this->getSourceContext()->getPath()) + ->raw(");\n") + ->outdent() + ->write("}\n") + ; + } + + protected function compileLoadTemplate(Compiler $compiler, $node, $var) + { + if ($node instanceof ConstantExpression) { + $compiler + ->write(sprintf('%s = $this->loadTemplate(', $var)) + ->subcompile($node) + ->raw(', ') + ->repr($node->getTemplateName()) + ->raw(', ') + ->repr($node->getTemplateLine()) + ->raw(");\n") + ; + } else { + throw new \LogicException('Trait templates can only be constant nodes.'); + } } } + +class_alias('Twig\Node\ModuleNode', 'Twig_Node_Module'); diff --git a/vendor/twig/twig/src/Node/Node.php b/vendor/twig/twig/src/Node/Node.php index ca14a38cd3d470ef17b2fd7dce14bad3b2d848a8..c890feb72da3e01dee1f64d2bc2304c8dcbe138d 100644 --- a/vendor/twig/twig/src/Node/Node.php +++ b/vendor/twig/twig/src/Node/Node.php @@ -1,11 +1,274 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * (c) Armin Ronacher + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\Node; -class_exists('Twig_Node'); +use Twig\Compiler; +use Twig\Source; + +/** + * Represents a node in the AST. + * + * @author Fabien Potencier <fabien@symfony.com> + */ +class Node implements \Twig_NodeInterface +{ + protected $nodes; + protected $attributes; + protected $lineno; + protected $tag; + + private $name; + private $sourceContext; + + /** + * @param array $nodes An array of named nodes + * @param array $attributes An array of attributes (should not be nodes) + * @param int $lineno The line number + * @param string $tag The tag name associated with the Node + */ + public function __construct(array $nodes = [], array $attributes = [], $lineno = 0, $tag = null) + { + foreach ($nodes as $name => $node) { + if (!$node instanceof \Twig_NodeInterface) { + @trigger_error(sprintf('Using "%s" for the value of node "%s" of "%s" is deprecated since version 1.25 and will be removed in 2.0.', \is_object($node) ? \get_class($node) : (null === $node ? 'null' : \gettype($node)), $name, \get_class($this)), E_USER_DEPRECATED); + } + } + $this->nodes = $nodes; + $this->attributes = $attributes; + $this->lineno = $lineno; + $this->tag = $tag; + } -if (\false) { - class Node extends \Twig_Node + public function __toString() { + $attributes = []; + foreach ($this->attributes as $name => $value) { + $attributes[] = sprintf('%s: %s', $name, str_replace("\n", '', var_export($value, true))); + } + + $repr = [\get_class($this).'('.implode(', ', $attributes)]; + + if (\count($this->nodes)) { + foreach ($this->nodes as $name => $node) { + $len = \strlen($name) + 4; + $noderepr = []; + foreach (explode("\n", (string) $node) as $line) { + $noderepr[] = str_repeat(' ', $len).$line; + } + + $repr[] = sprintf(' %s: %s', $name, ltrim(implode("\n", $noderepr))); + } + + $repr[] = ')'; + } else { + $repr[0] .= ')'; + } + + return implode("\n", $repr); + } + + /** + * @deprecated since 1.16.1 (to be removed in 2.0) + */ + public function toXml($asDom = false) + { + @trigger_error(sprintf('%s is deprecated since version 1.16.1 and will be removed in 2.0.', __METHOD__), E_USER_DEPRECATED); + + $dom = new \DOMDocument('1.0', 'UTF-8'); + $dom->formatOutput = true; + $dom->appendChild($xml = $dom->createElement('twig')); + + $xml->appendChild($node = $dom->createElement('node')); + $node->setAttribute('class', \get_class($this)); + + foreach ($this->attributes as $name => $value) { + $node->appendChild($attribute = $dom->createElement('attribute')); + $attribute->setAttribute('name', $name); + $attribute->appendChild($dom->createTextNode($value)); + } + + foreach ($this->nodes as $name => $n) { + if (null === $n) { + continue; + } + + $child = $n->toXml(true)->getElementsByTagName('node')->item(0); + $child = $dom->importNode($child, true); + $child->setAttribute('name', $name); + + $node->appendChild($child); + } + + return $asDom ? $dom : $dom->saveXML(); + } + + public function compile(Compiler $compiler) + { + foreach ($this->nodes as $node) { + $node->compile($compiler); + } + } + + public function getTemplateLine() + { + return $this->lineno; + } + + /** + * @deprecated since 1.27 (to be removed in 2.0) + */ + public function getLine() + { + @trigger_error('The '.__METHOD__.' method is deprecated since version 1.27 and will be removed in 2.0. Use getTemplateLine() instead.', E_USER_DEPRECATED); + + return $this->lineno; + } + + public function getNodeTag() + { + return $this->tag; + } + + /** + * @return bool + */ + public function hasAttribute($name) + { + return \array_key_exists($name, $this->attributes); + } + + /** + * @return mixed + */ + public function getAttribute($name) + { + if (!\array_key_exists($name, $this->attributes)) { + throw new \LogicException(sprintf('Attribute "%s" does not exist for Node "%s".', $name, \get_class($this))); + } + + return $this->attributes[$name]; + } + + /** + * @param string $name + * @param mixed $value + */ + public function setAttribute($name, $value) + { + $this->attributes[$name] = $value; + } + + public function removeAttribute($name) + { + unset($this->attributes[$name]); + } + + /** + * @return bool + */ + public function hasNode($name) + { + return \array_key_exists($name, $this->nodes); + } + + /** + * @return Node + */ + public function getNode($name) + { + if (!\array_key_exists($name, $this->nodes)) { + throw new \LogicException(sprintf('Node "%s" does not exist for Node "%s".', $name, \get_class($this))); + } + + return $this->nodes[$name]; + } + + public function setNode($name, $node = null) + { + if (!$node instanceof \Twig_NodeInterface) { + @trigger_error(sprintf('Using "%s" for the value of node "%s" of "%s" is deprecated since version 1.25 and will be removed in 2.0.', \is_object($node) ? \get_class($node) : (null === $node ? 'null' : \gettype($node)), $name, \get_class($this)), E_USER_DEPRECATED); + } + + $this->nodes[$name] = $node; + } + + public function removeNode($name) + { + unset($this->nodes[$name]); + } + + public function count() + { + return \count($this->nodes); + } + + public function getIterator() + { + return new \ArrayIterator($this->nodes); + } + + public function setTemplateName($name) + { + $this->name = $name; + foreach ($this->nodes as $node) { + if (null !== $node) { + $node->setTemplateName($name); + } + } + } + + public function getTemplateName() + { + return $this->name; + } + + public function setSourceContext(Source $source) + { + $this->sourceContext = $source; + foreach ($this->nodes as $node) { + if ($node instanceof Node) { + $node->setSourceContext($source); + } + } + } + + public function getSourceContext() + { + return $this->sourceContext; + } + + /** + * @deprecated since 1.27 (to be removed in 2.0) + */ + public function setFilename($name) + { + @trigger_error('The '.__METHOD__.' method is deprecated since version 1.27 and will be removed in 2.0. Use setTemplateName() instead.', E_USER_DEPRECATED); + + $this->setTemplateName($name); + } + + /** + * @deprecated since 1.27 (to be removed in 2.0) + */ + public function getFilename() + { + @trigger_error('The '.__METHOD__.' method is deprecated since version 1.27 and will be removed in 2.0. Use getTemplateName() instead.', E_USER_DEPRECATED); + + return $this->name; } } + +class_alias('Twig\Node\Node', 'Twig_Node'); + +// Ensure that the aliased name is loaded to keep BC for classes implementing the typehint with the old aliased name. +class_exists('Twig\Compiler'); diff --git a/vendor/twig/twig/src/Node/NodeCaptureInterface.php b/vendor/twig/twig/src/Node/NodeCaptureInterface.php index 4ba4e21f7494cf3a0c0567a1f42ac0b06f9980c5..474003f34bda95d91d1c59a20d81f9c2fd490cbd 100644 --- a/vendor/twig/twig/src/Node/NodeCaptureInterface.php +++ b/vendor/twig/twig/src/Node/NodeCaptureInterface.php @@ -1,11 +1,23 @@ <?php -namespace Twig\Node; +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ -class_exists('Twig_NodeCaptureInterface'); +namespace Twig\Node; -if (\false) { - interface NodeCaptureInterface extends \Twig_NodeCaptureInterface - { - } +/** + * Represents a node that captures any nested displayable nodes. + * + * @author Fabien Potencier <fabien@symfony.com> + */ +interface NodeCaptureInterface +{ } + +class_alias('Twig\Node\NodeCaptureInterface', 'Twig_NodeCaptureInterface'); diff --git a/vendor/twig/twig/src/Node/NodeOutputInterface.php b/vendor/twig/twig/src/Node/NodeOutputInterface.php index 5602e7a1dd5cf8b1b25882804690c6fbca12ec6c..8b046ee766180c566a1555eeaa27adf1d33b43a9 100644 --- a/vendor/twig/twig/src/Node/NodeOutputInterface.php +++ b/vendor/twig/twig/src/Node/NodeOutputInterface.php @@ -1,11 +1,23 @@ <?php -namespace Twig\Node; +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ -class_exists('Twig_NodeOutputInterface'); +namespace Twig\Node; -if (\false) { - interface NodeOutputInterface extends \Twig_NodeOutputInterface - { - } +/** + * Represents a displayable node in the AST. + * + * @author Fabien Potencier <fabien@symfony.com> + */ +interface NodeOutputInterface +{ } + +class_alias('Twig\Node\NodeOutputInterface', 'Twig_NodeOutputInterface'); diff --git a/vendor/twig/twig/src/Node/PrintNode.php b/vendor/twig/twig/src/Node/PrintNode.php index 4ff2ed6124e23a509fefa485cd276043d22e61e8..27f1ca42272f2ca11d9291d3bf1100a8ceb119b4 100644 --- a/vendor/twig/twig/src/Node/PrintNode.php +++ b/vendor/twig/twig/src/Node/PrintNode.php @@ -1,11 +1,41 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * (c) Armin Ronacher + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\Node; -class_exists('Twig_Node_Print'); +use Twig\Compiler; +use Twig\Node\Expression\AbstractExpression; -if (\false) { - class PrintNode extends \Twig_Node_Print +/** + * Represents a node that outputs an expression. + * + * @author Fabien Potencier <fabien@symfony.com> + */ +class PrintNode extends Node implements NodeOutputInterface +{ + public function __construct(AbstractExpression $expr, $lineno, $tag = null) { + parent::__construct(['expr' => $expr], [], $lineno, $tag); + } + + public function compile(Compiler $compiler) + { + $compiler + ->addDebugInfo($this) + ->write('echo ') + ->subcompile($this->getNode('expr')) + ->raw(";\n") + ; } } + +class_alias('Twig\Node\PrintNode', 'Twig_Node_Print'); diff --git a/vendor/twig/twig/src/Node/SandboxNode.php b/vendor/twig/twig/src/Node/SandboxNode.php index a24219f1cec69d038e91cb8cd266b5eab5c8da80..2d644c3a137ba8ef47c6c918884e13648d95150f 100644 --- a/vendor/twig/twig/src/Node/SandboxNode.php +++ b/vendor/twig/twig/src/Node/SandboxNode.php @@ -1,11 +1,47 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\Node; -class_exists('Twig_Node_Sandbox'); +use Twig\Compiler; -if (\false) { - class SandboxNode extends \Twig_Node_Sandbox +/** + * Represents a sandbox node. + * + * @author Fabien Potencier <fabien@symfony.com> + */ +class SandboxNode extends Node +{ + public function __construct(\Twig_NodeInterface $body, $lineno, $tag = null) { + parent::__construct(['body' => $body], [], $lineno, $tag); + } + + public function compile(Compiler $compiler) + { + $compiler + ->addDebugInfo($this) + ->write("if (!\$alreadySandboxed = \$this->sandbox->isSandboxed()) {\n") + ->indent() + ->write("\$this->sandbox->enableSandbox();\n") + ->outdent() + ->write("}\n") + ->subcompile($this->getNode('body')) + ->write("if (!\$alreadySandboxed) {\n") + ->indent() + ->write("\$this->sandbox->disableSandbox();\n") + ->outdent() + ->write("}\n") + ; } } + +class_alias('Twig\Node\SandboxNode', 'Twig_Node_Sandbox'); diff --git a/vendor/twig/twig/src/Node/SandboxedPrintNode.php b/vendor/twig/twig/src/Node/SandboxedPrintNode.php index a9f42bd5122a4f0a4a9461ba3bfd09ad02310367..2359af911047977724cd29c8474d4e900e749ada 100644 --- a/vendor/twig/twig/src/Node/SandboxedPrintNode.php +++ b/vendor/twig/twig/src/Node/SandboxedPrintNode.php @@ -1,11 +1,69 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\Node; -class_exists('Twig_Node_SandboxedPrint'); +use Twig\Compiler; +use Twig\Node\Expression\ConstantExpression; +use Twig\Node\Expression\FilterExpression; + +/** + * Adds a check for the __toString() method when the variable is an object and the sandbox is activated. + * + * When there is a simple Print statement, like {{ article }}, + * and if the sandbox is enabled, we need to check that the __toString() + * method is allowed if 'article' is an object. + * + * Not used anymore, to be deprecated in 2.x and removed in 3.0 + * + * @author Fabien Potencier <fabien@symfony.com> + */ +class SandboxedPrintNode extends PrintNode +{ + public function compile(Compiler $compiler) + { + $compiler + ->addDebugInfo($this) + ->write('echo ') + ; + $expr = $this->getNode('expr'); + if ($expr instanceof ConstantExpression) { + $compiler + ->subcompile($expr) + ->raw(";\n") + ; + } else { + $compiler + ->write('$this->env->getExtension(\'\Twig\Extension\SandboxExtension\')->ensureToStringAllowed(') + ->subcompile($expr) + ->raw(");\n") + ; + } + } -if (\false) { - class SandboxedPrintNode extends \Twig_Node_SandboxedPrint + /** + * Removes node filters. + * + * This is mostly needed when another visitor adds filters (like the escaper one). + * + * @return Node + */ + protected function removeNodeFilter(Node $node) { + if ($node instanceof FilterExpression) { + return $this->removeNodeFilter($node->getNode('node')); + } + + return $node; } } + +class_alias('Twig\Node\SandboxedPrintNode', 'Twig_Node_SandboxedPrint'); diff --git a/vendor/twig/twig/src/Node/SetNode.php b/vendor/twig/twig/src/Node/SetNode.php index d45f133e1c2e8698ac0eac383726327d93ed04e8..656103b9fd20e6d6a278a8e5515ae3b40a477680 100644 --- a/vendor/twig/twig/src/Node/SetNode.php +++ b/vendor/twig/twig/src/Node/SetNode.php @@ -1,11 +1,107 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\Node; -class_exists('Twig_Node_Set'); +use Twig\Compiler; +use Twig\Node\Expression\ConstantExpression; -if (\false) { - class SetNode extends \Twig_Node_Set +/** + * Represents a set node. + * + * @author Fabien Potencier <fabien@symfony.com> + */ +class SetNode extends Node implements NodeCaptureInterface +{ + public function __construct($capture, \Twig_NodeInterface $names, \Twig_NodeInterface $values, $lineno, $tag = null) { + parent::__construct(['names' => $names, 'values' => $values], ['capture' => $capture, 'safe' => false], $lineno, $tag); + + /* + * Optimizes the node when capture is used for a large block of text. + * + * {% set foo %}foo{% endset %} is compiled to $context['foo'] = new Twig\Markup("foo"); + */ + if ($this->getAttribute('capture')) { + $this->setAttribute('safe', true); + + $values = $this->getNode('values'); + if ($values instanceof TextNode) { + $this->setNode('values', new ConstantExpression($values->getAttribute('data'), $values->getTemplateLine())); + $this->setAttribute('capture', false); + } + } + } + + public function compile(Compiler $compiler) + { + $compiler->addDebugInfo($this); + + if (\count($this->getNode('names')) > 1) { + $compiler->write('list('); + foreach ($this->getNode('names') as $idx => $node) { + if ($idx) { + $compiler->raw(', '); + } + + $compiler->subcompile($node); + } + $compiler->raw(')'); + } else { + if ($this->getAttribute('capture')) { + if ($compiler->getEnvironment()->isDebug()) { + $compiler->write("ob_start();\n"); + } else { + $compiler->write("ob_start(function () { return ''; });\n"); + } + $compiler + ->subcompile($this->getNode('values')) + ; + } + + $compiler->subcompile($this->getNode('names'), false); + + if ($this->getAttribute('capture')) { + $compiler->raw(" = ('' === \$tmp = ob_get_clean()) ? '' : new Markup(\$tmp, \$this->env->getCharset())"); + } + } + + if (!$this->getAttribute('capture')) { + $compiler->raw(' = '); + + if (\count($this->getNode('names')) > 1) { + $compiler->write('['); + foreach ($this->getNode('values') as $idx => $value) { + if ($idx) { + $compiler->raw(', '); + } + + $compiler->subcompile($value); + } + $compiler->raw(']'); + } else { + if ($this->getAttribute('safe')) { + $compiler + ->raw("('' === \$tmp = ") + ->subcompile($this->getNode('values')) + ->raw(") ? '' : new Markup(\$tmp, \$this->env->getCharset())") + ; + } else { + $compiler->subcompile($this->getNode('values')); + } + } + } + + $compiler->raw(";\n"); } } + +class_alias('Twig\Node\SetNode', 'Twig_Node_Set'); diff --git a/vendor/twig/twig/src/Node/SetTempNode.php b/vendor/twig/twig/src/Node/SetTempNode.php index 90915d2f563d3287cabb64bfa70915187c5b5914..918fb991de008d380e80c2558228b4d555697d8c 100644 --- a/vendor/twig/twig/src/Node/SetTempNode.php +++ b/vendor/twig/twig/src/Node/SetTempNode.php @@ -1,11 +1,44 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\Node; -class_exists('Twig_Node_SetTemp'); +use Twig\Compiler; -if (\false) { - class SetTempNode extends \Twig_Node_SetTemp +/** + * @internal + */ +class SetTempNode extends Node +{ + public function __construct($name, $lineno) { + parent::__construct([], ['name' => $name], $lineno); + } + + public function compile(Compiler $compiler) + { + $name = $this->getAttribute('name'); + $compiler + ->addDebugInfo($this) + ->write('if (isset($context[') + ->string($name) + ->raw('])) { $_') + ->raw($name) + ->raw('_ = $context[') + ->repr($name) + ->raw(']; } else { $_') + ->raw($name) + ->raw("_ = null; }\n") + ; } } + +class_alias('Twig\Node\SetTempNode', 'Twig_Node_SetTemp'); diff --git a/vendor/twig/twig/src/Node/SpacelessNode.php b/vendor/twig/twig/src/Node/SpacelessNode.php index 08cf9d082de007d164e3c41bf126d6ec36826b0d..c8d32daf6bda61edcdc7cc7c577a0c69b5ae09ae 100644 --- a/vendor/twig/twig/src/Node/SpacelessNode.php +++ b/vendor/twig/twig/src/Node/SpacelessNode.php @@ -1,11 +1,47 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\Node; -class_exists('Twig_Node_Spaceless'); +use Twig\Compiler; -if (\false) { - class SpacelessNode extends \Twig_Node_Spaceless +/** + * Represents a spaceless node. + * + * It removes spaces between HTML tags. + * + * @author Fabien Potencier <fabien@symfony.com> + */ +class SpacelessNode extends Node +{ + public function __construct(\Twig_NodeInterface $body, $lineno, $tag = 'spaceless') { + parent::__construct(['body' => $body], [], $lineno, $tag); + } + + public function compile(Compiler $compiler) + { + $compiler + ->addDebugInfo($this) + ; + if ($compiler->getEnvironment()->isDebug()) { + $compiler->write("ob_start();\n"); + } else { + $compiler->write("ob_start(function () { return ''; });\n"); + } + $compiler + ->subcompile($this->getNode('body')) + ->write("echo trim(preg_replace('/>\s+</', '><', ob_get_clean()));\n") + ; } } + +class_alias('Twig\Node\SpacelessNode', 'Twig_Node_Spaceless'); diff --git a/vendor/twig/twig/src/Node/TextNode.php b/vendor/twig/twig/src/Node/TextNode.php index daff76478dcd003de1ba15b727538fef3f3d1902..9ac435e904f3078e12bc0546114e27efad363fd2 100644 --- a/vendor/twig/twig/src/Node/TextNode.php +++ b/vendor/twig/twig/src/Node/TextNode.php @@ -1,11 +1,40 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * (c) Armin Ronacher + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\Node; -class_exists('Twig_Node_Text'); +use Twig\Compiler; -if (\false) { - class TextNode extends \Twig_Node_Text +/** + * Represents a text node. + * + * @author Fabien Potencier <fabien@symfony.com> + */ +class TextNode extends Node implements NodeOutputInterface +{ + public function __construct($data, $lineno) { + parent::__construct([], ['data' => $data], $lineno); + } + + public function compile(Compiler $compiler) + { + $compiler + ->addDebugInfo($this) + ->write('echo ') + ->string($this->getAttribute('data')) + ->raw(";\n") + ; } } + +class_alias('Twig\Node\TextNode', 'Twig_Node_Text'); diff --git a/vendor/twig/twig/src/Node/WithNode.php b/vendor/twig/twig/src/Node/WithNode.php index 072fa6d8869c3d465284a5e7da1af5167d995c02..f5ae9246ddc0a529440d0697a539c4d07d49f376 100644 --- a/vendor/twig/twig/src/Node/WithNode.php +++ b/vendor/twig/twig/src/Node/WithNode.php @@ -1,11 +1,72 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\Node; -class_exists('Twig_Node_With'); +use Twig\Compiler; + +/** + * Represents a nested "with" scope. + * + * @author Fabien Potencier <fabien@symfony.com> + */ +class WithNode extends Node +{ + public function __construct(Node $body, Node $variables = null, $only = false, $lineno, $tag = null) + { + $nodes = ['body' => $body]; + if (null !== $variables) { + $nodes['variables'] = $variables; + } + + parent::__construct($nodes, ['only' => (bool) $only], $lineno, $tag); + } -if (\false) { - class WithNode extends \Twig_Node_With + public function compile(Compiler $compiler) { + $compiler->addDebugInfo($this); + + if ($this->hasNode('variables')) { + $node = $this->getNode('variables'); + $varsName = $compiler->getVarName(); + $compiler + ->write(sprintf('$%s = ', $varsName)) + ->subcompile($node) + ->raw(";\n") + ->write(sprintf("if (!twig_test_iterable(\$%s)) {\n", $varsName)) + ->indent() + ->write("throw new RuntimeError('Variables passed to the \"with\" tag must be a hash.', ") + ->repr($node->getTemplateLine()) + ->raw(", \$this->getSourceContext());\n") + ->outdent() + ->write("}\n") + ->write(sprintf("\$%s = twig_to_array(\$%s);\n", $varsName, $varsName)) + ; + + if ($this->getAttribute('only')) { + $compiler->write("\$context = ['_parent' => \$context];\n"); + } else { + $compiler->write("\$context['_parent'] = \$context;\n"); + } + + $compiler->write(sprintf("\$context = \$this->env->mergeGlobals(array_merge(\$context, \$%s));\n", $varsName)); + } else { + $compiler->write("\$context['_parent'] = \$context;\n"); + } + + $compiler + ->subcompile($this->getNode('body')) + ->write("\$context = \$context['_parent'];\n") + ; } } + +class_alias('Twig\Node\WithNode', 'Twig_Node_With'); diff --git a/vendor/twig/twig/src/NodeTraverser.php b/vendor/twig/twig/src/NodeTraverser.php index 7fe843b7a9817c22841ac688dc27195aae3a825c..bd25d3cc7489d5a707472899d067e4ce1bdb7b14 100644 --- a/vendor/twig/twig/src/NodeTraverser.php +++ b/vendor/twig/twig/src/NodeTraverser.php @@ -1,11 +1,89 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig; -class_exists('Twig_NodeTraverser'); +use Twig\NodeVisitor\NodeVisitorInterface; + +/** + * A node traverser. + * + * It visits all nodes and their children and calls the given visitor for each. + * + * @final + * + * @author Fabien Potencier <fabien@symfony.com> + */ +class NodeTraverser +{ + protected $env; + protected $visitors = []; + + /** + * @param NodeVisitorInterface[] $visitors + */ + public function __construct(Environment $env, array $visitors = []) + { + $this->env = $env; + foreach ($visitors as $visitor) { + $this->addVisitor($visitor); + } + } -if (\false) { - class NodeTraverser extends \Twig_NodeTraverser + public function addVisitor(NodeVisitorInterface $visitor) { + $this->visitors[$visitor->getPriority()][] = $visitor; + } + + /** + * Traverses a node and calls the registered visitors. + * + * @return \Twig_NodeInterface + */ + public function traverse(\Twig_NodeInterface $node) + { + ksort($this->visitors); + foreach ($this->visitors as $visitors) { + foreach ($visitors as $visitor) { + $node = $this->traverseForVisitor($visitor, $node); + } + } + + return $node; + } + + protected function traverseForVisitor(NodeVisitorInterface $visitor, \Twig_NodeInterface $node = null) + { + if (null === $node) { + return; + } + + $node = $visitor->enterNode($node, $this->env); + + foreach ($node as $k => $n) { + if (null === $n) { + continue; + } + + if (false !== ($m = $this->traverseForVisitor($visitor, $n)) && null !== $m) { + if ($m !== $n) { + $node->setNode($k, $m); + } + } else { + $node->removeNode($k); + } + } + + return $visitor->leaveNode($node, $this->env); } } + +class_alias('Twig\NodeTraverser', 'Twig_NodeTraverser'); diff --git a/vendor/twig/twig/src/NodeVisitor/AbstractNodeVisitor.php b/vendor/twig/twig/src/NodeVisitor/AbstractNodeVisitor.php index 30e956fb54f83ad069c732d8370c8f427da162d2..b66c3c6f116a52947e52d312b2110b43947ce882 100644 --- a/vendor/twig/twig/src/NodeVisitor/AbstractNodeVisitor.php +++ b/vendor/twig/twig/src/NodeVisitor/AbstractNodeVisitor.php @@ -1,11 +1,59 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\NodeVisitor; -class_exists('Twig_BaseNodeVisitor'); +use Twig\Environment; +use Twig\Node\Node; -if (\false) { - class AbstractNodeVisitor extends \Twig_BaseNodeVisitor +/** + * Used to make node visitors compatible with Twig 1.x and 2.x. + * + * To be removed in Twig 3.1. + * + * @author Fabien Potencier <fabien@symfony.com> + */ +abstract class AbstractNodeVisitor implements NodeVisitorInterface +{ + final public function enterNode(\Twig_NodeInterface $node, Environment $env) { + if (!$node instanceof Node) { + throw new \LogicException(sprintf('%s only supports \Twig\Node\Node instances.', __CLASS__)); + } + + return $this->doEnterNode($node, $env); } + + final public function leaveNode(\Twig_NodeInterface $node, Environment $env) + { + if (!$node instanceof Node) { + throw new \LogicException(sprintf('%s only supports \Twig\Node\Node instances.', __CLASS__)); + } + + return $this->doLeaveNode($node, $env); + } + + /** + * Called before child nodes are visited. + * + * @return Node The modified node + */ + abstract protected function doEnterNode(Node $node, Environment $env); + + /** + * Called after child nodes are visited. + * + * @return Node|false|null The modified node or null if the node must be removed + */ + abstract protected function doLeaveNode(Node $node, Environment $env); } + +class_alias('Twig\NodeVisitor\AbstractNodeVisitor', 'Twig_BaseNodeVisitor'); diff --git a/vendor/twig/twig/src/NodeVisitor/EscaperNodeVisitor.php b/vendor/twig/twig/src/NodeVisitor/EscaperNodeVisitor.php index 68c28322e6207802dfe379fafadd154c57716b4e..f6e16fa7d77c5ef3777258f7daaf7f5d5371aed8 100644 --- a/vendor/twig/twig/src/NodeVisitor/EscaperNodeVisitor.php +++ b/vendor/twig/twig/src/NodeVisitor/EscaperNodeVisitor.php @@ -1,11 +1,209 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\NodeVisitor; -class_exists('Twig_NodeVisitor_Escaper'); +use Twig\Environment; +use Twig\Node\AutoEscapeNode; +use Twig\Node\BlockNode; +use Twig\Node\BlockReferenceNode; +use Twig\Node\DoNode; +use Twig\Node\Expression\ConditionalExpression; +use Twig\Node\Expression\ConstantExpression; +use Twig\Node\Expression\FilterExpression; +use Twig\Node\Expression\InlinePrint; +use Twig\Node\ImportNode; +use Twig\Node\ModuleNode; +use Twig\Node\Node; +use Twig\Node\PrintNode; +use Twig\NodeTraverser; + +/** + * @final + * + * @author Fabien Potencier <fabien@symfony.com> + */ +class EscaperNodeVisitor extends AbstractNodeVisitor +{ + protected $statusStack = []; + protected $blocks = []; + protected $safeAnalysis; + protected $traverser; + protected $defaultStrategy = false; + protected $safeVars = []; + + public function __construct() + { + $this->safeAnalysis = new SafeAnalysisNodeVisitor(); + } + + protected function doEnterNode(Node $node, Environment $env) + { + if ($node instanceof ModuleNode) { + if ($env->hasExtension('\Twig\Extension\EscaperExtension') && $defaultStrategy = $env->getExtension('\Twig\Extension\EscaperExtension')->getDefaultStrategy($node->getTemplateName())) { + $this->defaultStrategy = $defaultStrategy; + } + $this->safeVars = []; + $this->blocks = []; + } elseif ($node instanceof AutoEscapeNode) { + $this->statusStack[] = $node->getAttribute('value'); + } elseif ($node instanceof BlockNode) { + $this->statusStack[] = isset($this->blocks[$node->getAttribute('name')]) ? $this->blocks[$node->getAttribute('name')] : $this->needEscaping($env); + } elseif ($node instanceof ImportNode) { + $this->safeVars[] = $node->getNode('var')->getAttribute('name'); + } + + return $node; + } + + protected function doLeaveNode(Node $node, Environment $env) + { + if ($node instanceof ModuleNode) { + $this->defaultStrategy = false; + $this->safeVars = []; + $this->blocks = []; + } elseif ($node instanceof FilterExpression) { + return $this->preEscapeFilterNode($node, $env); + } elseif ($node instanceof PrintNode && false !== $type = $this->needEscaping($env)) { + $expression = $node->getNode('expr'); + if ($expression instanceof ConditionalExpression && $this->shouldUnwrapConditional($expression, $env, $type)) { + return new DoNode($this->unwrapConditional($expression, $env, $type), $expression->getTemplateLine()); + } + + return $this->escapePrintNode($node, $env, $type); + } + + if ($node instanceof AutoEscapeNode || $node instanceof BlockNode) { + array_pop($this->statusStack); + } elseif ($node instanceof BlockReferenceNode) { + $this->blocks[$node->getAttribute('name')] = $this->needEscaping($env); + } + + return $node; + } + + private function shouldUnwrapConditional(ConditionalExpression $expression, Environment $env, $type) + { + $expr2Safe = $this->isSafeFor($type, $expression->getNode('expr2'), $env); + $expr3Safe = $this->isSafeFor($type, $expression->getNode('expr3'), $env); + + return $expr2Safe !== $expr3Safe; + } + + private function unwrapConditional(ConditionalExpression $expression, Environment $env, $type) + { + // convert "echo a ? b : c" to "a ? echo b : echo c" recursively + $expr2 = $expression->getNode('expr2'); + if ($expr2 instanceof ConditionalExpression && $this->shouldUnwrapConditional($expr2, $env, $type)) { + $expr2 = $this->unwrapConditional($expr2, $env, $type); + } else { + $expr2 = $this->escapeInlinePrintNode(new InlinePrint($expr2, $expr2->getTemplateLine()), $env, $type); + } + $expr3 = $expression->getNode('expr3'); + if ($expr3 instanceof ConditionalExpression && $this->shouldUnwrapConditional($expr3, $env, $type)) { + $expr3 = $this->unwrapConditional($expr3, $env, $type); + } else { + $expr3 = $this->escapeInlinePrintNode(new InlinePrint($expr3, $expr3->getTemplateLine()), $env, $type); + } + + return new ConditionalExpression($expression->getNode('expr1'), $expr2, $expr3, $expression->getTemplateLine()); + } + + private function escapeInlinePrintNode(InlinePrint $node, Environment $env, $type) + { + $expression = $node->getNode('node'); + + if ($this->isSafeFor($type, $expression, $env)) { + return $node; + } + + return new InlinePrint($this->getEscaperFilter($type, $expression), $node->getTemplateLine()); + } + + protected function escapePrintNode(PrintNode $node, Environment $env, $type) + { + if (false === $type) { + return $node; + } + + $expression = $node->getNode('expr'); + + if ($this->isSafeFor($type, $expression, $env)) { + return $node; + } + + $class = \get_class($node); -if (\false) { - class EscaperNodeVisitor extends \Twig_NodeVisitor_Escaper + return new $class($this->getEscaperFilter($type, $expression), $node->getTemplateLine()); + } + + protected function preEscapeFilterNode(FilterExpression $filter, Environment $env) { + $name = $filter->getNode('filter')->getAttribute('value'); + + $type = $env->getFilter($name)->getPreEscape(); + if (null === $type) { + return $filter; + } + + $node = $filter->getNode('node'); + if ($this->isSafeFor($type, $node, $env)) { + return $filter; + } + + $filter->setNode('node', $this->getEscaperFilter($type, $node)); + + return $filter; + } + + protected function isSafeFor($type, \Twig_NodeInterface $expression, $env) + { + $safe = $this->safeAnalysis->getSafe($expression); + + if (null === $safe) { + if (null === $this->traverser) { + $this->traverser = new NodeTraverser($env, [$this->safeAnalysis]); + } + + $this->safeAnalysis->setSafeVars($this->safeVars); + + $this->traverser->traverse($expression); + $safe = $this->safeAnalysis->getSafe($expression); + } + + return \in_array($type, $safe) || \in_array('all', $safe); + } + + protected function needEscaping(Environment $env) + { + if (\count($this->statusStack)) { + return $this->statusStack[\count($this->statusStack) - 1]; + } + + return $this->defaultStrategy ? $this->defaultStrategy : false; + } + + protected function getEscaperFilter($type, \Twig_NodeInterface $node) + { + $line = $node->getTemplateLine(); + $name = new ConstantExpression('escape', $line); + $args = new Node([new ConstantExpression((string) $type, $line), new ConstantExpression(null, $line), new ConstantExpression(true, $line)]); + + return new FilterExpression($node, $name, $args, $line); + } + + public function getPriority() + { + return 0; } } + +class_alias('Twig\NodeVisitor\EscaperNodeVisitor', 'Twig_NodeVisitor_Escaper'); diff --git a/vendor/twig/twig/src/NodeVisitor/NodeVisitorInterface.php b/vendor/twig/twig/src/NodeVisitor/NodeVisitorInterface.php index f78f1d73dbcb79f0fa4530e1ac36ed676a0fe357..9b8730b48deb4148e4c604f52b0bb67ec7445f1d 100644 --- a/vendor/twig/twig/src/NodeVisitor/NodeVisitorInterface.php +++ b/vendor/twig/twig/src/NodeVisitor/NodeVisitorInterface.php @@ -1,11 +1,50 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\NodeVisitor; -class_exists('Twig_NodeVisitorInterface'); +use Twig\Environment; + +/** + * Interface for node visitor classes. + * + * @author Fabien Potencier <fabien@symfony.com> + */ +interface NodeVisitorInterface +{ + /** + * Called before child nodes are visited. + * + * @return \Twig_NodeInterface The modified node + */ + public function enterNode(\Twig_NodeInterface $node, Environment $env); + + /** + * Called after child nodes are visited. + * + * @return \Twig_NodeInterface|false|null The modified node or null if the node must be removed + */ + public function leaveNode(\Twig_NodeInterface $node, Environment $env); -if (\false) { - interface NodeVisitorInterface extends \Twig_NodeVisitorInterface - { - } + /** + * Returns the priority for this visitor. + * + * Priority should be between -10 and 10 (0 is the default). + * + * @return int The priority level + */ + public function getPriority(); } + +class_alias('Twig\NodeVisitor\NodeVisitorInterface', 'Twig_NodeVisitorInterface'); + +// Ensure that the aliased name is loaded to keep BC for classes implementing the typehint with the old aliased name. +class_exists('Twig\Environment'); diff --git a/vendor/twig/twig/src/NodeVisitor/OptimizerNodeVisitor.php b/vendor/twig/twig/src/NodeVisitor/OptimizerNodeVisitor.php index 9ed37a555fda11c86fa81be4cc39c701ca8e0a3e..e5ea9b7cc396fcd21dfa2845dcd4f93f97b6383d 100644 --- a/vendor/twig/twig/src/NodeVisitor/OptimizerNodeVisitor.php +++ b/vendor/twig/twig/src/NodeVisitor/OptimizerNodeVisitor.php @@ -1,11 +1,273 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\NodeVisitor; -class_exists('Twig_NodeVisitor_Optimizer'); +use Twig\Environment; +use Twig\Node\BlockReferenceNode; +use Twig\Node\BodyNode; +use Twig\Node\Expression\AbstractExpression; +use Twig\Node\Expression\BlockReferenceExpression; +use Twig\Node\Expression\ConstantExpression; +use Twig\Node\Expression\FilterExpression; +use Twig\Node\Expression\FunctionExpression; +use Twig\Node\Expression\GetAttrExpression; +use Twig\Node\Expression\NameExpression; +use Twig\Node\Expression\ParentExpression; +use Twig\Node\Expression\TempNameExpression; +use Twig\Node\ForNode; +use Twig\Node\IncludeNode; +use Twig\Node\Node; +use Twig\Node\PrintNode; +use Twig\Node\SetTempNode; + +/** + * Tries to optimize the AST. + * + * This visitor is always the last registered one. + * + * You can configure which optimizations you want to activate via the + * optimizer mode. + * + * @final + * + * @author Fabien Potencier <fabien@symfony.com> + */ +class OptimizerNodeVisitor extends AbstractNodeVisitor +{ + const OPTIMIZE_ALL = -1; + const OPTIMIZE_NONE = 0; + const OPTIMIZE_FOR = 2; + const OPTIMIZE_RAW_FILTER = 4; + const OPTIMIZE_VAR_ACCESS = 8; + + protected $loops = []; + protected $loopsTargets = []; + protected $optimizers; + protected $prependedNodes = []; + protected $inABody = false; + + /** + * @param int $optimizers The optimizer mode + */ + public function __construct($optimizers = -1) + { + if (!\is_int($optimizers) || $optimizers > (self::OPTIMIZE_FOR | self::OPTIMIZE_RAW_FILTER | self::OPTIMIZE_VAR_ACCESS)) { + throw new \InvalidArgumentException(sprintf('Optimizer mode "%s" is not valid.', $optimizers)); + } + + $this->optimizers = $optimizers; + } + + protected function doEnterNode(Node $node, Environment $env) + { + if (self::OPTIMIZE_FOR === (self::OPTIMIZE_FOR & $this->optimizers)) { + $this->enterOptimizeFor($node, $env); + } + + if (\PHP_VERSION_ID < 50400 && self::OPTIMIZE_VAR_ACCESS === (self::OPTIMIZE_VAR_ACCESS & $this->optimizers) && !$env->isStrictVariables() && !$env->hasExtension('\Twig\Extension\SandboxExtension')) { + if ($this->inABody) { + if (!$node instanceof AbstractExpression) { + if ('Twig_Node' !== \get_class($node)) { + array_unshift($this->prependedNodes, []); + } + } else { + $node = $this->optimizeVariables($node, $env); + } + } elseif ($node instanceof BodyNode) { + $this->inABody = true; + } + } + + return $node; + } + + protected function doLeaveNode(Node $node, Environment $env) + { + $expression = $node instanceof AbstractExpression; + + if (self::OPTIMIZE_FOR === (self::OPTIMIZE_FOR & $this->optimizers)) { + $this->leaveOptimizeFor($node, $env); + } + + if (self::OPTIMIZE_RAW_FILTER === (self::OPTIMIZE_RAW_FILTER & $this->optimizers)) { + $node = $this->optimizeRawFilter($node, $env); + } + + $node = $this->optimizePrintNode($node, $env); + + if (self::OPTIMIZE_VAR_ACCESS === (self::OPTIMIZE_VAR_ACCESS & $this->optimizers) && !$env->isStrictVariables() && !$env->hasExtension('\Twig\Extension\SandboxExtension')) { + if ($node instanceof BodyNode) { + $this->inABody = false; + } elseif ($this->inABody) { + if (!$expression && 'Twig_Node' !== \get_class($node) && $prependedNodes = array_shift($this->prependedNodes)) { + $nodes = []; + foreach (array_unique($prependedNodes) as $name) { + $nodes[] = new SetTempNode($name, $node->getTemplateLine()); + } + + $nodes[] = $node; + $node = new Node($nodes); + } + } + } + + return $node; + } + + protected function optimizeVariables(\Twig_NodeInterface $node, Environment $env) + { + if ('Twig_Node_Expression_Name' === \get_class($node) && $node->isSimple()) { + $this->prependedNodes[0][] = $node->getAttribute('name'); + + return new TempNameExpression($node->getAttribute('name'), $node->getTemplateLine()); + } + + return $node; + } + + /** + * Optimizes print nodes. + * + * It replaces: + * + * * "echo $this->render(Parent)Block()" with "$this->display(Parent)Block()" + * + * @return \Twig_NodeInterface + */ + protected function optimizePrintNode(\Twig_NodeInterface $node, Environment $env) + { + if (!$node instanceof PrintNode) { + return $node; + } + + $exprNode = $node->getNode('expr'); + if ( + $exprNode instanceof BlockReferenceExpression || + $exprNode instanceof ParentExpression + ) { + $exprNode->setAttribute('output', true); + + return $exprNode; + } + + return $node; + } + + /** + * Removes "raw" filters. + * + * @return \Twig_NodeInterface + */ + protected function optimizeRawFilter(\Twig_NodeInterface $node, Environment $env) + { + if ($node instanceof FilterExpression && 'raw' == $node->getNode('filter')->getAttribute('value')) { + return $node->getNode('node'); + } + + return $node; + } + + /** + * Optimizes "for" tag by removing the "loop" variable creation whenever possible. + */ + protected function enterOptimizeFor(\Twig_NodeInterface $node, Environment $env) + { + if ($node instanceof ForNode) { + // disable the loop variable by default + $node->setAttribute('with_loop', false); + array_unshift($this->loops, $node); + array_unshift($this->loopsTargets, $node->getNode('value_target')->getAttribute('name')); + array_unshift($this->loopsTargets, $node->getNode('key_target')->getAttribute('name')); + } elseif (!$this->loops) { + // we are outside a loop + return; + } + + // when do we need to add the loop variable back? + + // the loop variable is referenced for the current loop + elseif ($node instanceof NameExpression && 'loop' === $node->getAttribute('name')) { + $node->setAttribute('always_defined', true); + $this->addLoopToCurrent(); + } + + // optimize access to loop targets + elseif ($node instanceof NameExpression && \in_array($node->getAttribute('name'), $this->loopsTargets)) { + $node->setAttribute('always_defined', true); + } + + // block reference + elseif ($node instanceof BlockReferenceNode || $node instanceof BlockReferenceExpression) { + $this->addLoopToCurrent(); + } -if (\false) { - class OptimizerNodeVisitor extends \Twig_NodeVisitor_Optimizer + // include without the only attribute + elseif ($node instanceof IncludeNode && !$node->getAttribute('only')) { + $this->addLoopToAll(); + } + + // include function without the with_context=false parameter + elseif ($node instanceof FunctionExpression + && 'include' === $node->getAttribute('name') + && (!$node->getNode('arguments')->hasNode('with_context') + || false !== $node->getNode('arguments')->getNode('with_context')->getAttribute('value') + ) + ) { + $this->addLoopToAll(); + } + + // the loop variable is referenced via an attribute + elseif ($node instanceof GetAttrExpression + && (!$node->getNode('attribute') instanceof ConstantExpression + || 'parent' === $node->getNode('attribute')->getAttribute('value') + ) + && (true === $this->loops[0]->getAttribute('with_loop') + || ($node->getNode('node') instanceof NameExpression + && 'loop' === $node->getNode('node')->getAttribute('name') + ) + ) + ) { + $this->addLoopToAll(); + } + } + + /** + * Optimizes "for" tag by removing the "loop" variable creation whenever possible. + */ + protected function leaveOptimizeFor(\Twig_NodeInterface $node, Environment $env) + { + if ($node instanceof ForNode) { + array_shift($this->loops); + array_shift($this->loopsTargets); + array_shift($this->loopsTargets); + } + } + + protected function addLoopToCurrent() { + $this->loops[0]->setAttribute('with_loop', true); + } + + protected function addLoopToAll() + { + foreach ($this->loops as $loop) { + $loop->setAttribute('with_loop', true); + } + } + + public function getPriority() + { + return 255; } } + +class_alias('Twig\NodeVisitor\OptimizerNodeVisitor', 'Twig_NodeVisitor_Optimizer'); diff --git a/vendor/twig/twig/src/NodeVisitor/SafeAnalysisNodeVisitor.php b/vendor/twig/twig/src/NodeVisitor/SafeAnalysisNodeVisitor.php index 8906b37cc0cf4adab11225a2719916d146fbe222..97a7a3e6eebda081db690f26cfc00ecd2c712f02 100644 --- a/vendor/twig/twig/src/NodeVisitor/SafeAnalysisNodeVisitor.php +++ b/vendor/twig/twig/src/NodeVisitor/SafeAnalysisNodeVisitor.php @@ -1,11 +1,164 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\NodeVisitor; -class_exists('Twig_NodeVisitor_SafeAnalysis'); +use Twig\Environment; +use Twig\Node\Expression\BlockReferenceExpression; +use Twig\Node\Expression\ConditionalExpression; +use Twig\Node\Expression\ConstantExpression; +use Twig\Node\Expression\FilterExpression; +use Twig\Node\Expression\FunctionExpression; +use Twig\Node\Expression\GetAttrExpression; +use Twig\Node\Expression\MethodCallExpression; +use Twig\Node\Expression\NameExpression; +use Twig\Node\Expression\ParentExpression; +use Twig\Node\Node; + +/** + * @final + */ +class SafeAnalysisNodeVisitor extends AbstractNodeVisitor +{ + protected $data = []; + protected $safeVars = []; + + public function setSafeVars($safeVars) + { + $this->safeVars = $safeVars; + } + + public function getSafe(\Twig_NodeInterface $node) + { + $hash = spl_object_hash($node); + if (!isset($this->data[$hash])) { + return; + } + + foreach ($this->data[$hash] as $bucket) { + if ($bucket['key'] !== $node) { + continue; + } + + if (\in_array('html_attr', $bucket['value'])) { + $bucket['value'][] = 'html'; + } + + return $bucket['value']; + } + } + + protected function setSafe(\Twig_NodeInterface $node, array $safe) + { + $hash = spl_object_hash($node); + if (isset($this->data[$hash])) { + foreach ($this->data[$hash] as &$bucket) { + if ($bucket['key'] === $node) { + $bucket['value'] = $safe; + + return; + } + } + } + $this->data[$hash][] = [ + 'key' => $node, + 'value' => $safe, + ]; + } -if (\false) { - class SafeAnalysisNodeVisitor extends \Twig_NodeVisitor_SafeAnalysis + protected function doEnterNode(Node $node, Environment $env) { + return $node; + } + + protected function doLeaveNode(Node $node, Environment $env) + { + if ($node instanceof ConstantExpression) { + // constants are marked safe for all + $this->setSafe($node, ['all']); + } elseif ($node instanceof BlockReferenceExpression) { + // blocks are safe by definition + $this->setSafe($node, ['all']); + } elseif ($node instanceof ParentExpression) { + // parent block is safe by definition + $this->setSafe($node, ['all']); + } elseif ($node instanceof ConditionalExpression) { + // intersect safeness of both operands + $safe = $this->intersectSafe($this->getSafe($node->getNode('expr2')), $this->getSafe($node->getNode('expr3'))); + $this->setSafe($node, $safe); + } elseif ($node instanceof FilterExpression) { + // filter expression is safe when the filter is safe + $name = $node->getNode('filter')->getAttribute('value'); + $args = $node->getNode('arguments'); + if (false !== $filter = $env->getFilter($name)) { + $safe = $filter->getSafe($args); + if (null === $safe) { + $safe = $this->intersectSafe($this->getSafe($node->getNode('node')), $filter->getPreservesSafety()); + } + $this->setSafe($node, $safe); + } else { + $this->setSafe($node, []); + } + } elseif ($node instanceof FunctionExpression) { + // function expression is safe when the function is safe + $name = $node->getAttribute('name'); + $args = $node->getNode('arguments'); + $function = $env->getFunction($name); + if (false !== $function) { + $this->setSafe($node, $function->getSafe($args)); + } else { + $this->setSafe($node, []); + } + } elseif ($node instanceof MethodCallExpression) { + if ($node->getAttribute('safe')) { + $this->setSafe($node, ['all']); + } else { + $this->setSafe($node, []); + } + } elseif ($node instanceof GetAttrExpression && $node->getNode('node') instanceof NameExpression) { + $name = $node->getNode('node')->getAttribute('name'); + // attributes on template instances are safe + if ('_self' == $name || \in_array($name, $this->safeVars)) { + $this->setSafe($node, ['all']); + } else { + $this->setSafe($node, []); + } + } else { + $this->setSafe($node, []); + } + + return $node; + } + + protected function intersectSafe(array $a = null, array $b = null) + { + if (null === $a || null === $b) { + return []; + } + + if (\in_array('all', $a)) { + return $b; + } + + if (\in_array('all', $b)) { + return $a; + } + + return array_intersect($a, $b); + } + + public function getPriority() + { + return 0; } } + +class_alias('Twig\NodeVisitor\SafeAnalysisNodeVisitor', 'Twig_NodeVisitor_SafeAnalysis'); diff --git a/vendor/twig/twig/src/NodeVisitor/SandboxNodeVisitor.php b/vendor/twig/twig/src/NodeVisitor/SandboxNodeVisitor.php index 1e4632f3c061aae3f12e05a1455b5145e1f4e1f7..c9403398f09a299692ea1c818b3802f73210071e 100644 --- a/vendor/twig/twig/src/NodeVisitor/SandboxNodeVisitor.php +++ b/vendor/twig/twig/src/NodeVisitor/SandboxNodeVisitor.php @@ -1,11 +1,137 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\NodeVisitor; -class_exists('Twig_NodeVisitor_Sandbox'); +use Twig\Environment; +use Twig\Node\CheckSecurityNode; +use Twig\Node\CheckToStringNode; +use Twig\Node\Expression\Binary\ConcatBinary; +use Twig\Node\Expression\Binary\RangeBinary; +use Twig\Node\Expression\FilterExpression; +use Twig\Node\Expression\FunctionExpression; +use Twig\Node\Expression\GetAttrExpression; +use Twig\Node\Expression\NameExpression; +use Twig\Node\ModuleNode; +use Twig\Node\Node; +use Twig\Node\PrintNode; +use Twig\Node\SetNode; + +/** + * @final + * + * @author Fabien Potencier <fabien@symfony.com> + */ +class SandboxNodeVisitor extends AbstractNodeVisitor +{ + protected $inAModule = false; + protected $tags; + protected $filters; + protected $functions; + + private $needsToStringWrap = false; + + protected function doEnterNode(Node $node, Environment $env) + { + if ($node instanceof ModuleNode) { + $this->inAModule = true; + $this->tags = []; + $this->filters = []; + $this->functions = []; + + return $node; + } elseif ($this->inAModule) { + // look for tags + if ($node->getNodeTag() && !isset($this->tags[$node->getNodeTag()])) { + $this->tags[$node->getNodeTag()] = $node; + } + + // look for filters + if ($node instanceof FilterExpression && !isset($this->filters[$node->getNode('filter')->getAttribute('value')])) { + $this->filters[$node->getNode('filter')->getAttribute('value')] = $node; + } + + // look for functions + if ($node instanceof FunctionExpression && !isset($this->functions[$node->getAttribute('name')])) { + $this->functions[$node->getAttribute('name')] = $node; + } + + // the .. operator is equivalent to the range() function + if ($node instanceof RangeBinary && !isset($this->functions['range'])) { + $this->functions['range'] = $node; + } + + if ($node instanceof PrintNode) { + $this->needsToStringWrap = true; + $this->wrapNode($node, 'expr'); + } + + if ($node instanceof SetNode && !$node->getAttribute('capture')) { + $this->needsToStringWrap = true; + } + + // wrap outer nodes that can implicitly call __toString() + if ($this->needsToStringWrap) { + if ($node instanceof ConcatBinary) { + $this->wrapNode($node, 'left'); + $this->wrapNode($node, 'right'); + } + if ($node instanceof FilterExpression) { + $this->wrapNode($node, 'node'); + $this->wrapArrayNode($node, 'arguments'); + } + if ($node instanceof FunctionExpression) { + $this->wrapArrayNode($node, 'arguments'); + } + } + } + + return $node; + } -if (\false) { - class SandboxNodeVisitor extends \Twig_NodeVisitor_Sandbox + protected function doLeaveNode(Node $node, Environment $env) { + if ($node instanceof ModuleNode) { + $this->inAModule = false; + + $node->getNode('constructor_end')->setNode('_security_check', new Node([new CheckSecurityNode($this->filters, $this->tags, $this->functions), $node->getNode('display_start')])); + } elseif ($this->inAModule) { + if ($node instanceof PrintNode || $node instanceof SetNode) { + $this->needsToStringWrap = false; + } + } + + return $node; + } + + private function wrapNode(Node $node, $name) + { + $expr = $node->getNode($name); + if ($expr instanceof NameExpression || $expr instanceof GetAttrExpression) { + $node->setNode($name, new CheckToStringNode($expr)); + } + } + + private function wrapArrayNode(Node $node, $name) + { + $args = $node->getNode($name); + foreach ($args as $name => $_) { + $this->wrapNode($args, $name); + } + } + + public function getPriority() + { + return 0; } } + +class_alias('Twig\NodeVisitor\SandboxNodeVisitor', 'Twig_NodeVisitor_Sandbox'); diff --git a/vendor/twig/twig/src/Parser.php b/vendor/twig/twig/src/Parser.php index 738a4047c9edb6a70436d78dd13fc9a0a2bbadbe..0ea102cc811255d0cde675376e6ba3de84d881fd 100644 --- a/vendor/twig/twig/src/Parser.php +++ b/vendor/twig/twig/src/Parser.php @@ -1,11 +1,439 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * (c) Armin Ronacher + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig; -class_exists('Twig_Parser'); +use Twig\Error\SyntaxError; +use Twig\Node\BlockNode; +use Twig\Node\BlockReferenceNode; +use Twig\Node\BodyNode; +use Twig\Node\Expression\AbstractExpression; +use Twig\Node\MacroNode; +use Twig\Node\ModuleNode; +use Twig\Node\Node; +use Twig\Node\NodeCaptureInterface; +use Twig\Node\NodeOutputInterface; +use Twig\Node\PrintNode; +use Twig\Node\TextNode; +use Twig\NodeVisitor\NodeVisitorInterface; +use Twig\TokenParser\TokenParserInterface; + +/** + * Default parser implementation. + * + * @author Fabien Potencier <fabien@symfony.com> + */ +class Parser implements \Twig_ParserInterface +{ + protected $stack = []; + protected $stream; + protected $parent; + protected $handlers; + protected $visitors; + protected $expressionParser; + protected $blocks; + protected $blockStack; + protected $macros; + protected $env; + protected $reservedMacroNames; + protected $importedSymbols; + protected $traits; + protected $embeddedTemplates = []; + private $varNameSalt = 0; + + public function __construct(Environment $env) + { + $this->env = $env; + } + + /** + * @deprecated since 1.27 (to be removed in 2.0) + */ + public function getEnvironment() + { + @trigger_error('The '.__METHOD__.' method is deprecated since version 1.27 and will be removed in 2.0.', E_USER_DEPRECATED); + + return $this->env; + } + + public function getVarName() + { + return sprintf('__internal_%s', hash('sha256', __METHOD__.$this->stream->getSourceContext()->getCode().$this->varNameSalt++)); + } + + /** + * @deprecated since 1.27 (to be removed in 2.0). Use $parser->getStream()->getSourceContext()->getPath() instead. + */ + public function getFilename() + { + @trigger_error(sprintf('The "%s" method is deprecated since version 1.27 and will be removed in 2.0. Use $parser->getStream()->getSourceContext()->getPath() instead.', __METHOD__), E_USER_DEPRECATED); + + return $this->stream->getSourceContext()->getName(); + } + + public function parse(TokenStream $stream, $test = null, $dropNeedle = false) + { + // push all variables into the stack to keep the current state of the parser + // using get_object_vars() instead of foreach would lead to https://bugs.php.net/71336 + // This hack can be removed when min version if PHP 7.0 + $vars = []; + foreach ($this as $k => $v) { + $vars[$k] = $v; + } + + unset($vars['stack'], $vars['env'], $vars['handlers'], $vars['visitors'], $vars['expressionParser'], $vars['reservedMacroNames']); + $this->stack[] = $vars; + + // tag handlers + if (null === $this->handlers) { + $this->handlers = $this->env->getTokenParsers(); + $this->handlers->setParser($this); + } + + // node visitors + if (null === $this->visitors) { + $this->visitors = $this->env->getNodeVisitors(); + } + + if (null === $this->expressionParser) { + $this->expressionParser = new ExpressionParser($this, $this->env); + } + + $this->stream = $stream; + $this->parent = null; + $this->blocks = []; + $this->macros = []; + $this->traits = []; + $this->blockStack = []; + $this->importedSymbols = [[]]; + $this->embeddedTemplates = []; + $this->varNameSalt = 0; + + try { + $body = $this->subparse($test, $dropNeedle); + + if (null !== $this->parent && null === $body = $this->filterBodyNodes($body)) { + $body = new Node(); + } + } catch (SyntaxError $e) { + if (!$e->getSourceContext()) { + $e->setSourceContext($this->stream->getSourceContext()); + } + + if (!$e->getTemplateLine()) { + $e->setTemplateLine($this->stream->getCurrent()->getLine()); + } + + throw $e; + } + + $node = new ModuleNode(new BodyNode([$body]), $this->parent, new Node($this->blocks), new Node($this->macros), new Node($this->traits), $this->embeddedTemplates, $stream->getSourceContext()); + + $traverser = new NodeTraverser($this->env, $this->visitors); + + $node = $traverser->traverse($node); + + // restore previous stack so previous parse() call can resume working + foreach (array_pop($this->stack) as $key => $val) { + $this->$key = $val; + } + + return $node; + } + + public function subparse($test, $dropNeedle = false) + { + $lineno = $this->getCurrentToken()->getLine(); + $rv = []; + while (!$this->stream->isEOF()) { + switch ($this->getCurrentToken()->getType()) { + case Token::TEXT_TYPE: + $token = $this->stream->next(); + $rv[] = new TextNode($token->getValue(), $token->getLine()); + break; + + case Token::VAR_START_TYPE: + $token = $this->stream->next(); + $expr = $this->expressionParser->parseExpression(); + $this->stream->expect(Token::VAR_END_TYPE); + $rv[] = new PrintNode($expr, $token->getLine()); + break; + + case Token::BLOCK_START_TYPE: + $this->stream->next(); + $token = $this->getCurrentToken(); + + if (Token::NAME_TYPE !== $token->getType()) { + throw new SyntaxError('A block must start with a tag name.', $token->getLine(), $this->stream->getSourceContext()); + } + + if (null !== $test && \call_user_func($test, $token)) { + if ($dropNeedle) { + $this->stream->next(); + } + + if (1 === \count($rv)) { + return $rv[0]; + } + + return new Node($rv, [], $lineno); + } + + $subparser = $this->handlers->getTokenParser($token->getValue()); + if (null === $subparser) { + if (null !== $test) { + $e = new SyntaxError(sprintf('Unexpected "%s" tag', $token->getValue()), $token->getLine(), $this->stream->getSourceContext()); + + if (\is_array($test) && isset($test[0]) && $test[0] instanceof TokenParserInterface) { + $e->appendMessage(sprintf(' (expecting closing tag for the "%s" tag defined near line %s).', $test[0]->getTag(), $lineno)); + } + } else { + $e = new SyntaxError(sprintf('Unknown "%s" tag.', $token->getValue()), $token->getLine(), $this->stream->getSourceContext()); + $e->addSuggestions($token->getValue(), array_keys($this->env->getTags())); + } + + throw $e; + } + + $this->stream->next(); + + $node = $subparser->parse($token); + if (null !== $node) { + $rv[] = $node; + } + break; + + default: + throw new SyntaxError('Lexer or parser ended up in unsupported state.', $this->getCurrentToken()->getLine(), $this->stream->getSourceContext()); + } + } + + if (1 === \count($rv)) { + return $rv[0]; + } + + return new Node($rv, [], $lineno); + } + + /** + * @deprecated since 1.27 (to be removed in 2.0) + */ + public function addHandler($name, $class) + { + @trigger_error('The '.__METHOD__.' method is deprecated since version 1.27 and will be removed in 2.0.', E_USER_DEPRECATED); + + $this->handlers[$name] = $class; + } + + /** + * @deprecated since 1.27 (to be removed in 2.0) + */ + public function addNodeVisitor(NodeVisitorInterface $visitor) + { + @trigger_error('The '.__METHOD__.' method is deprecated since version 1.27 and will be removed in 2.0.', E_USER_DEPRECATED); + + $this->visitors[] = $visitor; + } + + public function getBlockStack() + { + return $this->blockStack; + } + + public function peekBlockStack() + { + return isset($this->blockStack[\count($this->blockStack) - 1]) ? $this->blockStack[\count($this->blockStack) - 1] : null; + } + + public function popBlockStack() + { + array_pop($this->blockStack); + } + + public function pushBlockStack($name) + { + $this->blockStack[] = $name; + } + + public function hasBlock($name) + { + return isset($this->blocks[$name]); + } + + public function getBlock($name) + { + return $this->blocks[$name]; + } + + public function setBlock($name, BlockNode $value) + { + $this->blocks[$name] = new BodyNode([$value], [], $value->getTemplateLine()); + } + + public function hasMacro($name) + { + return isset($this->macros[$name]); + } -if (\false) { - class Parser extends \Twig_Parser + public function setMacro($name, MacroNode $node) { + if ($this->isReservedMacroName($name)) { + throw new SyntaxError(sprintf('"%s" cannot be used as a macro name as it is a reserved keyword.', $name), $node->getTemplateLine(), $this->stream->getSourceContext()); + } + + $this->macros[$name] = $node; + } + + public function isReservedMacroName($name) + { + if (null === $this->reservedMacroNames) { + $this->reservedMacroNames = []; + $r = new \ReflectionClass($this->env->getBaseTemplateClass()); + foreach ($r->getMethods() as $method) { + $methodName = strtolower($method->getName()); + + if ('get' === substr($methodName, 0, 3) && isset($methodName[3])) { + $this->reservedMacroNames[] = substr($methodName, 3); + } + } + } + + return \in_array(strtolower($name), $this->reservedMacroNames); + } + + public function addTrait($trait) + { + $this->traits[] = $trait; + } + + public function hasTraits() + { + return \count($this->traits) > 0; + } + + public function embedTemplate(ModuleNode $template) + { + $template->setIndex(mt_rand()); + + $this->embeddedTemplates[] = $template; + } + + public function addImportedSymbol($type, $alias, $name = null, AbstractExpression $node = null) + { + $this->importedSymbols[0][$type][$alias] = ['name' => $name, 'node' => $node]; + } + + public function getImportedSymbol($type, $alias) + { + if (null !== $this->peekBlockStack()) { + foreach ($this->importedSymbols as $functions) { + if (isset($functions[$type][$alias])) { + if (\count($this->blockStack) > 1) { + return null; + } + + return $functions[$type][$alias]; + } + } + } else { + return isset($this->importedSymbols[0][$type][$alias]) ? $this->importedSymbols[0][$type][$alias] : null; + } + } + + public function isMainScope() + { + return 1 === \count($this->importedSymbols); + } + + public function pushLocalScope() + { + array_unshift($this->importedSymbols, []); + } + + public function popLocalScope() + { + array_shift($this->importedSymbols); + } + + /** + * @return ExpressionParser + */ + public function getExpressionParser() + { + return $this->expressionParser; + } + + public function getParent() + { + return $this->parent; + } + + public function setParent($parent) + { + $this->parent = $parent; + } + + /** + * @return TokenStream + */ + public function getStream() + { + return $this->stream; + } + + /** + * @return Token + */ + public function getCurrentToken() + { + return $this->stream->getCurrent(); + } + + protected function filterBodyNodes(\Twig_NodeInterface $node) + { + // check that the body does not contain non-empty output nodes + if ( + ($node instanceof TextNode && !ctype_space($node->getAttribute('data'))) + || + (!$node instanceof TextNode && !$node instanceof BlockReferenceNode && $node instanceof NodeOutputInterface) + ) { + if (false !== strpos((string) $node, \chr(0xEF).\chr(0xBB).\chr(0xBF))) { + $t = substr($node->getAttribute('data'), 3); + if ('' === $t || ctype_space($t)) { + // bypass empty nodes starting with a BOM + return; + } + } + + throw new SyntaxError('A template that extends another one cannot include content outside Twig blocks. Did you forget to put the content inside a {% block %} tag?', $node->getTemplateLine(), $this->stream->getSourceContext()); + } + + // bypass nodes that will "capture" the output + if ($node instanceof NodeCaptureInterface) { + return $node; + } + + if ($node instanceof NodeOutputInterface) { + return; + } + + foreach ($node as $k => $n) { + if (null !== $n && null === $this->filterBodyNodes($n)) { + $node->removeNode($k); + } + } + + return $node; } } + +class_alias('Twig\Parser', 'Twig_Parser'); diff --git a/vendor/twig/twig/src/Profiler/Dumper/BaseDumper.php b/vendor/twig/twig/src/Profiler/Dumper/BaseDumper.php index 33c32801c99540667f0073e02d3d24f1bb168fb7..d965dc75421e43cafe0b51edea5e25d5e26313c3 100644 --- a/vendor/twig/twig/src/Profiler/Dumper/BaseDumper.php +++ b/vendor/twig/twig/src/Profiler/Dumper/BaseDumper.php @@ -1,11 +1,65 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\Profiler\Dumper; -class_exists('Twig_Profiler_Dumper_Base'); +use Twig\Profiler\Profile; + +/** + * @author Fabien Potencier <fabien@symfony.com> + */ +abstract class BaseDumper +{ + private $root; -if (\false) { - class BaseDumper extends \Twig_Profiler_Dumper_Base + public function dump(Profile $profile) { + return $this->dumpProfile($profile); + } + + abstract protected function formatTemplate(Profile $profile, $prefix); + + abstract protected function formatNonTemplate(Profile $profile, $prefix); + + abstract protected function formatTime(Profile $profile, $percent); + + private function dumpProfile(Profile $profile, $prefix = '', $sibling = false) + { + if ($profile->isRoot()) { + $this->root = $profile->getDuration(); + $start = $profile->getName(); + } else { + if ($profile->isTemplate()) { + $start = $this->formatTemplate($profile, $prefix); + } else { + $start = $this->formatNonTemplate($profile, $prefix); + } + $prefix .= $sibling ? '│ ' : ' '; + } + + $percent = $this->root ? $profile->getDuration() / $this->root * 100 : 0; + + if ($profile->getDuration() * 1000 < 1) { + $str = $start."\n"; + } else { + $str = sprintf("%s %s\n", $start, $this->formatTime($profile, $percent)); + } + + $nCount = \count($profile->getProfiles()); + foreach ($profile as $i => $p) { + $str .= $this->dumpProfile($p, $prefix, $i + 1 !== $nCount); + } + + return $str; } } + +class_alias('Twig\Profiler\Dumper\BaseDumper', 'Twig_Profiler_Dumper_Base'); diff --git a/vendor/twig/twig/src/Profiler/Dumper/BlackfireDumper.php b/vendor/twig/twig/src/Profiler/Dumper/BlackfireDumper.php index afab9394a1f6a17126d3597a50a7124ac1d2db59..a1c3c7bce691b59d4585e666f40716e944648a51 100644 --- a/vendor/twig/twig/src/Profiler/Dumper/BlackfireDumper.php +++ b/vendor/twig/twig/src/Profiler/Dumper/BlackfireDumper.php @@ -1,11 +1,76 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\Profiler\Dumper; -class_exists('Twig_Profiler_Dumper_Blackfire'); +use Twig\Profiler\Profile; -if (\false) { - class BlackfireDumper extends \Twig_Profiler_Dumper_Blackfire +/** + * @author Fabien Potencier <fabien@symfony.com> + * + * @final + */ +class BlackfireDumper +{ + public function dump(Profile $profile) { + $data = []; + $this->dumpProfile('main()', $profile, $data); + $this->dumpChildren('main()', $profile, $data); + + $start = sprintf('%f', microtime(true)); + $str = <<<EOF +file-format: BlackfireProbe +cost-dimensions: wt mu pmu +request-start: {$start} + + +EOF; + + foreach ($data as $name => $values) { + $str .= "{$name}//{$values['ct']} {$values['wt']} {$values['mu']} {$values['pmu']}\n"; + } + + return $str; + } + + private function dumpChildren($parent, Profile $profile, &$data) + { + foreach ($profile as $p) { + if ($p->isTemplate()) { + $name = $p->getTemplate(); + } else { + $name = sprintf('%s::%s(%s)', $p->getTemplate(), $p->getType(), $p->getName()); + } + $this->dumpProfile(sprintf('%s==>%s', $parent, $name), $p, $data); + $this->dumpChildren($name, $p, $data); + } + } + + private function dumpProfile($edge, Profile $profile, &$data) + { + if (isset($data[$edge])) { + ++$data[$edge]['ct']; + $data[$edge]['wt'] += floor($profile->getDuration() * 1000000); + $data[$edge]['mu'] += $profile->getMemoryUsage(); + $data[$edge]['pmu'] += $profile->getPeakMemoryUsage(); + } else { + $data[$edge] = [ + 'ct' => 1, + 'wt' => floor($profile->getDuration() * 1000000), + 'mu' => $profile->getMemoryUsage(), + 'pmu' => $profile->getPeakMemoryUsage(), + ]; + } } } + +class_alias('Twig\Profiler\Dumper\BlackfireDumper', 'Twig_Profiler_Dumper_Blackfire'); diff --git a/vendor/twig/twig/src/Profiler/Dumper/HtmlDumper.php b/vendor/twig/twig/src/Profiler/Dumper/HtmlDumper.php index 51654d2d03988fb529ddea928b16ffb7f28beccb..c70b405b30b5aac7b51933c706f69458eeafa990 100644 --- a/vendor/twig/twig/src/Profiler/Dumper/HtmlDumper.php +++ b/vendor/twig/twig/src/Profiler/Dumper/HtmlDumper.php @@ -1,11 +1,51 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\Profiler\Dumper; -class_exists('Twig_Profiler_Dumper_Html'); +use Twig\Profiler\Profile; + +/** + * @author Fabien Potencier <fabien@symfony.com> + * + * @final + */ +class HtmlDumper extends BaseDumper +{ + private static $colors = [ + 'block' => '#dfd', + 'macro' => '#ddf', + 'template' => '#ffd', + 'big' => '#d44', + ]; + + public function dump(Profile $profile) + { + return '<pre>'.parent::dump($profile).'</pre>'; + } + + protected function formatTemplate(Profile $profile, $prefix) + { + return sprintf('%sâ”” <span style="background-color: %s">%s</span>', $prefix, self::$colors['template'], $profile->getTemplate()); + } + + protected function formatNonTemplate(Profile $profile, $prefix) + { + return sprintf('%sâ”” %s::%s(<span style="background-color: %s">%s</span>)', $prefix, $profile->getTemplate(), $profile->getType(), isset(self::$colors[$profile->getType()]) ? self::$colors[$profile->getType()] : 'auto', $profile->getName()); + } -if (\false) { - class HtmlDumper extends \Twig_Profiler_Dumper_Html + protected function formatTime(Profile $profile, $percent) { + return sprintf('<span style="color: %s">%.2fms/%.0f%%</span>', $percent > 20 ? self::$colors['big'] : 'auto', $profile->getDuration() * 1000, $percent); } } + +class_alias('Twig\Profiler\Dumper\HtmlDumper', 'Twig_Profiler_Dumper_Html'); diff --git a/vendor/twig/twig/src/Profiler/Dumper/TextDumper.php b/vendor/twig/twig/src/Profiler/Dumper/TextDumper.php index a9ec4efacaf2f317a0f6e66507d1463f94c2a098..c6b515891e7d1120e23143c614f506fc7a4cc524 100644 --- a/vendor/twig/twig/src/Profiler/Dumper/TextDumper.php +++ b/vendor/twig/twig/src/Profiler/Dumper/TextDumper.php @@ -1,11 +1,39 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\Profiler\Dumper; -class_exists('Twig_Profiler_Dumper_Text'); +use Twig\Profiler\Profile; + +/** + * @author Fabien Potencier <fabien@symfony.com> + * + * @final + */ +class TextDumper extends BaseDumper +{ + protected function formatTemplate(Profile $profile, $prefix) + { + return sprintf('%sâ”” %s', $prefix, $profile->getTemplate()); + } + + protected function formatNonTemplate(Profile $profile, $prefix) + { + return sprintf('%sâ”” %s::%s(%s)', $prefix, $profile->getTemplate(), $profile->getType(), $profile->getName()); + } -if (\false) { - class TextDumper extends \Twig_Profiler_Dumper_Text + protected function formatTime(Profile $profile, $percent) { + return sprintf('%.2fms/%.0f%%', $profile->getDuration() * 1000, $percent); } } + +class_alias('Twig\Profiler\Dumper\TextDumper', 'Twig_Profiler_Dumper_Text'); diff --git a/vendor/twig/twig/src/Profiler/Node/EnterProfileNode.php b/vendor/twig/twig/src/Profiler/Node/EnterProfileNode.php index 3b9786b2c49bb9217e8a333d9ca77d3f9b0f0d5a..8ffd3dc78c691719d2228da97e2773add58a307a 100644 --- a/vendor/twig/twig/src/Profiler/Node/EnterProfileNode.php +++ b/vendor/twig/twig/src/Profiler/Node/EnterProfileNode.php @@ -1,11 +1,44 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\Profiler\Node; -class_exists('Twig_Profiler_Node_EnterProfile'); +use Twig\Compiler; +use Twig\Node\Node; -if (\false) { - class EnterProfileNode extends \Twig_Profiler_Node_EnterProfile +/** + * Represents a profile enter node. + * + * @author Fabien Potencier <fabien@symfony.com> + */ +class EnterProfileNode extends Node +{ + public function __construct($extensionName, $type, $name, $varName) { + parent::__construct([], ['extension_name' => $extensionName, 'name' => $name, 'type' => $type, 'var_name' => $varName]); + } + + public function compile(Compiler $compiler) + { + $compiler + ->write(sprintf('$%s = $this->env->getExtension(', $this->getAttribute('var_name'))) + ->repr($this->getAttribute('extension_name')) + ->raw(");\n") + ->write(sprintf('$%s->enter($%s = new \Twig\Profiler\Profile($this->getTemplateName(), ', $this->getAttribute('var_name'), $this->getAttribute('var_name').'_prof')) + ->repr($this->getAttribute('type')) + ->raw(', ') + ->repr($this->getAttribute('name')) + ->raw("));\n\n") + ; } } + +class_alias('Twig\Profiler\Node\EnterProfileNode', 'Twig_Profiler_Node_EnterProfile'); diff --git a/vendor/twig/twig/src/Profiler/Node/LeaveProfileNode.php b/vendor/twig/twig/src/Profiler/Node/LeaveProfileNode.php index c4024f3e9ba30f8c2d88b277a77f3c52a8a92107..3b7a74d02638ecce320e34e447049ad59cb99eab 100644 --- a/vendor/twig/twig/src/Profiler/Node/LeaveProfileNode.php +++ b/vendor/twig/twig/src/Profiler/Node/LeaveProfileNode.php @@ -1,11 +1,38 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\Profiler\Node; -class_exists('Twig_Profiler_Node_LeaveProfile'); +use Twig\Compiler; +use Twig\Node\Node; -if (\false) { - class LeaveProfileNode extends \Twig_Profiler_Node_LeaveProfile +/** + * Represents a profile leave node. + * + * @author Fabien Potencier <fabien@symfony.com> + */ +class LeaveProfileNode extends Node +{ + public function __construct($varName) { + parent::__construct([], ['var_name' => $varName]); + } + + public function compile(Compiler $compiler) + { + $compiler + ->write("\n") + ->write(sprintf("\$%s->leave(\$%s);\n\n", $this->getAttribute('var_name'), $this->getAttribute('var_name').'_prof')) + ; } } + +class_alias('Twig\Profiler\Node\LeaveProfileNode', 'Twig_Profiler_Node_LeaveProfile'); diff --git a/vendor/twig/twig/src/Profiler/NodeVisitor/ProfilerNodeVisitor.php b/vendor/twig/twig/src/Profiler/NodeVisitor/ProfilerNodeVisitor.php index 0e401a7312535448ac25fda4220c8f7e1295c0b2..41ca9e1f297df366d67b33cff9a5a590e4495744 100644 --- a/vendor/twig/twig/src/Profiler/NodeVisitor/ProfilerNodeVisitor.php +++ b/vendor/twig/twig/src/Profiler/NodeVisitor/ProfilerNodeVisitor.php @@ -1,11 +1,80 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\Profiler\NodeVisitor; -class_exists('Twig_Profiler_NodeVisitor_Profiler'); +use Twig\Environment; +use Twig\Node\BlockNode; +use Twig\Node\BodyNode; +use Twig\Node\MacroNode; +use Twig\Node\ModuleNode; +use Twig\Node\Node; +use Twig\NodeVisitor\AbstractNodeVisitor; +use Twig\Profiler\Node\EnterProfileNode; +use Twig\Profiler\Node\LeaveProfileNode; +use Twig\Profiler\Profile; + +/** + * @author Fabien Potencier <fabien@symfony.com> + * + * @final + */ +class ProfilerNodeVisitor extends AbstractNodeVisitor +{ + private $extensionName; + + public function __construct($extensionName) + { + $this->extensionName = $extensionName; + } + + protected function doEnterNode(Node $node, Environment $env) + { + return $node; + } + + protected function doLeaveNode(Node $node, Environment $env) + { + if ($node instanceof ModuleNode) { + $varName = $this->getVarName(); + $node->setNode('display_start', new Node([new EnterProfileNode($this->extensionName, Profile::TEMPLATE, $node->getTemplateName(), $varName), $node->getNode('display_start')])); + $node->setNode('display_end', new Node([new LeaveProfileNode($varName), $node->getNode('display_end')])); + } elseif ($node instanceof BlockNode) { + $varName = $this->getVarName(); + $node->setNode('body', new BodyNode([ + new EnterProfileNode($this->extensionName, Profile::BLOCK, $node->getAttribute('name'), $varName), + $node->getNode('body'), + new LeaveProfileNode($varName), + ])); + } elseif ($node instanceof MacroNode) { + $varName = $this->getVarName(); + $node->setNode('body', new BodyNode([ + new EnterProfileNode($this->extensionName, Profile::MACRO, $node->getAttribute('name'), $varName), + $node->getNode('body'), + new LeaveProfileNode($varName), + ])); + } + + return $node; + } + + private function getVarName() + { + return sprintf('__internal_%s', hash('sha256', $this->extensionName)); + } -if (\false) { - class ProfilerNodeVisitor extends \Twig_Profiler_NodeVisitor_Profiler + public function getPriority() { + return 0; } } + +class_alias('Twig\Profiler\NodeVisitor\ProfilerNodeVisitor', 'Twig_Profiler_NodeVisitor_Profiler'); diff --git a/vendor/twig/twig/src/Profiler/Profile.php b/vendor/twig/twig/src/Profiler/Profile.php index b18a7f4c35e856a8baa7bca09af9505084047c88..d83da40af38e2419b11a7c2efad54bb6f823336a 100644 --- a/vendor/twig/twig/src/Profiler/Profile.php +++ b/vendor/twig/twig/src/Profiler/Profile.php @@ -1,11 +1,188 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\Profiler; -class_exists('Twig_Profiler_Profile'); +/** + * @author Fabien Potencier <fabien@symfony.com> + * + * @final + */ +class Profile implements \IteratorAggregate, \Serializable +{ + const ROOT = 'ROOT'; + const BLOCK = 'block'; + const TEMPLATE = 'template'; + const MACRO = 'macro'; + + private $template; + private $name; + private $type; + private $starts = []; + private $ends = []; + private $profiles = []; + + public function __construct($template = 'main', $type = self::ROOT, $name = 'main') + { + $this->template = $template; + $this->type = $type; + $this->name = 0 === strpos($name, '__internal_') ? 'INTERNAL' : $name; + $this->enter(); + } + + public function getTemplate() + { + return $this->template; + } + + public function getType() + { + return $this->type; + } + + public function getName() + { + return $this->name; + } + + public function isRoot() + { + return self::ROOT === $this->type; + } -if (\false) { - class Profile extends \Twig_Profiler_Profile + public function isTemplate() { + return self::TEMPLATE === $this->type; + } + + public function isBlock() + { + return self::BLOCK === $this->type; + } + + public function isMacro() + { + return self::MACRO === $this->type; + } + + public function getProfiles() + { + return $this->profiles; + } + + public function addProfile(self $profile) + { + $this->profiles[] = $profile; + } + + /** + * Returns the duration in microseconds. + * + * @return float + */ + public function getDuration() + { + if ($this->isRoot() && $this->profiles) { + // for the root node with children, duration is the sum of all child durations + $duration = 0; + foreach ($this->profiles as $profile) { + $duration += $profile->getDuration(); + } + + return $duration; + } + + return isset($this->ends['wt']) && isset($this->starts['wt']) ? $this->ends['wt'] - $this->starts['wt'] : 0; + } + + /** + * Returns the memory usage in bytes. + * + * @return int + */ + public function getMemoryUsage() + { + return isset($this->ends['mu']) && isset($this->starts['mu']) ? $this->ends['mu'] - $this->starts['mu'] : 0; + } + + /** + * Returns the peak memory usage in bytes. + * + * @return int + */ + public function getPeakMemoryUsage() + { + return isset($this->ends['pmu']) && isset($this->starts['pmu']) ? $this->ends['pmu'] - $this->starts['pmu'] : 0; + } + + /** + * Starts the profiling. + */ + public function enter() + { + $this->starts = [ + 'wt' => microtime(true), + 'mu' => memory_get_usage(), + 'pmu' => memory_get_peak_usage(), + ]; + } + + /** + * Stops the profiling. + */ + public function leave() + { + $this->ends = [ + 'wt' => microtime(true), + 'mu' => memory_get_usage(), + 'pmu' => memory_get_peak_usage(), + ]; + } + + public function reset() + { + $this->starts = $this->ends = $this->profiles = []; + $this->enter(); + } + + public function getIterator() + { + return new \ArrayIterator($this->profiles); + } + + public function serialize() + { + return serialize($this->__serialize()); + } + + public function unserialize($data) + { + $this->__unserialize(unserialize($data)); + } + + /** + * @internal + */ + public function __serialize() + { + return [$this->template, $this->name, $this->type, $this->starts, $this->ends, $this->profiles]; + } + + /** + * @internal + */ + public function __unserialize(array $data) + { + list($this->template, $this->name, $this->type, $this->starts, $this->ends, $this->profiles) = $data; } } + +class_alias('Twig\Profiler\Profile', 'Twig_Profiler_Profile'); diff --git a/vendor/twig/twig/src/RuntimeLoader/ContainerRuntimeLoader.php b/vendor/twig/twig/src/RuntimeLoader/ContainerRuntimeLoader.php index 35ff7afb1e5816c4cb8b7e64bbcc88d1cb8a4c56..04a6602f2298059964b52cc646845787146ca76d 100644 --- a/vendor/twig/twig/src/RuntimeLoader/ContainerRuntimeLoader.php +++ b/vendor/twig/twig/src/RuntimeLoader/ContainerRuntimeLoader.php @@ -1,11 +1,41 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\RuntimeLoader; -class_exists('Twig_ContainerRuntimeLoader'); +use Psr\Container\ContainerInterface; + +/** + * Lazily loads Twig runtime implementations from a PSR-11 container. + * + * Note that the runtime services MUST use their class names as identifiers. + * + * @author Fabien Potencier <fabien@symfony.com> + * @author Robin Chalas <robin.chalas@gmail.com> + */ +class ContainerRuntimeLoader implements RuntimeLoaderInterface +{ + private $container; + + public function __construct(ContainerInterface $container) + { + $this->container = $container; + } -if (\false) { - class ContainerRuntimeLoader extends \Twig_ContainerRuntimeLoader + public function load($class) { + if ($this->container->has($class)) { + return $this->container->get($class); + } } } + +class_alias('Twig\RuntimeLoader\ContainerRuntimeLoader', 'Twig_ContainerRuntimeLoader'); diff --git a/vendor/twig/twig/src/RuntimeLoader/FactoryRuntimeLoader.php b/vendor/twig/twig/src/RuntimeLoader/FactoryRuntimeLoader.php index bb9880763edc57725fee8b5ca755f6ef7b31a0b5..43b5f24ebac0a7295e09958f21a18d37ca4f9a89 100644 --- a/vendor/twig/twig/src/RuntimeLoader/FactoryRuntimeLoader.php +++ b/vendor/twig/twig/src/RuntimeLoader/FactoryRuntimeLoader.php @@ -1,11 +1,41 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\RuntimeLoader; -class_exists('Twig_FactoryRuntimeLoader'); +/** + * Lazy loads the runtime implementations for a Twig element. + * + * @author Robin Chalas <robin.chalas@gmail.com> + */ +class FactoryRuntimeLoader implements RuntimeLoaderInterface +{ + private $map; + + /** + * @param array $map An array where keys are class names and values factory callables + */ + public function __construct($map = []) + { + $this->map = $map; + } -if (\false) { - class FactoryRuntimeLoader extends \Twig_FactoryRuntimeLoader + public function load($class) { + if (isset($this->map[$class])) { + $runtimeFactory = $this->map[$class]; + + return $runtimeFactory(); + } } } + +class_alias('Twig\RuntimeLoader\FactoryRuntimeLoader', 'Twig_FactoryRuntimeLoader'); diff --git a/vendor/twig/twig/src/RuntimeLoader/RuntimeLoaderInterface.php b/vendor/twig/twig/src/RuntimeLoader/RuntimeLoaderInterface.php index 4721a44746078d6c8fb3d16a43d25cad201a621c..4eb5ad859994065a14826fbdbae4b1b9ee37edd9 100644 --- a/vendor/twig/twig/src/RuntimeLoader/RuntimeLoaderInterface.php +++ b/vendor/twig/twig/src/RuntimeLoader/RuntimeLoaderInterface.php @@ -1,11 +1,31 @@ <?php -namespace Twig\RuntimeLoader; +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ -class_exists('Twig_RuntimeLoaderInterface'); +namespace Twig\RuntimeLoader; -if (\false) { - interface RuntimeLoaderInterface extends \Twig_RuntimeLoaderInterface - { - } +/** + * Creates runtime implementations for Twig elements (filters/functions/tests). + * + * @author Fabien Potencier <fabien@symfony.com> + */ +interface RuntimeLoaderInterface +{ + /** + * Creates the runtime implementation of a Twig element (filter/function/test). + * + * @param string $class A runtime class + * + * @return object|null The runtime instance or null if the loader does not know how to create the runtime for this class + */ + public function load($class); } + +class_alias('Twig\RuntimeLoader\RuntimeLoaderInterface', 'Twig_RuntimeLoaderInterface'); diff --git a/vendor/twig/twig/src/Sandbox/SecurityError.php b/vendor/twig/twig/src/Sandbox/SecurityError.php index e1cd3f06f062a88c92599fb9a6d85cee4e1afbe0..5f96d46bd8458577460fa0f556206078d16f5f1c 100644 --- a/vendor/twig/twig/src/Sandbox/SecurityError.php +++ b/vendor/twig/twig/src/Sandbox/SecurityError.php @@ -1,11 +1,25 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\Sandbox; -class_exists('Twig_Sandbox_SecurityError'); +use Twig\Error\Error; -if (\false) { - class SecurityError extends \Twig_Sandbox_SecurityError - { - } +/** + * Exception thrown when a security error occurs at runtime. + * + * @author Fabien Potencier <fabien@symfony.com> + */ +class SecurityError extends Error +{ } + +class_alias('Twig\Sandbox\SecurityError', 'Twig_Sandbox_SecurityError'); diff --git a/vendor/twig/twig/src/Sandbox/SecurityNotAllowedFilterError.php b/vendor/twig/twig/src/Sandbox/SecurityNotAllowedFilterError.php index b56d2c9b29640de76e62f6b9cec4071238ce6afc..fa0fdee72f30b480e5dc506bc0752b731765cb7b 100644 --- a/vendor/twig/twig/src/Sandbox/SecurityNotAllowedFilterError.php +++ b/vendor/twig/twig/src/Sandbox/SecurityNotAllowedFilterError.php @@ -1,11 +1,35 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\Sandbox; -class_exists('Twig_Sandbox_SecurityNotAllowedFilterError'); +/** + * Exception thrown when a not allowed filter is used in a template. + * + * @author Martin Hasoň <martin.hason@gmail.com> + */ +class SecurityNotAllowedFilterError extends SecurityError +{ + private $filterName; -if (\false) { - class SecurityNotAllowedFilterError extends \Twig_Sandbox_SecurityNotAllowedFilterError + public function __construct($message, $functionName, $lineno = -1, $filename = null, \Exception $previous = null) { + parent::__construct($message, $lineno, $filename, $previous); + $this->filterName = $functionName; + } + + public function getFilterName() + { + return $this->filterName; } } + +class_alias('Twig\Sandbox\SecurityNotAllowedFilterError', 'Twig_Sandbox_SecurityNotAllowedFilterError'); diff --git a/vendor/twig/twig/src/Sandbox/SecurityNotAllowedFunctionError.php b/vendor/twig/twig/src/Sandbox/SecurityNotAllowedFunctionError.php index 1a91764fad47fcca691f7bd574ee67484d599c8a..8f23f93acd98bd986342f8ea2feb04dfff581b1a 100644 --- a/vendor/twig/twig/src/Sandbox/SecurityNotAllowedFunctionError.php +++ b/vendor/twig/twig/src/Sandbox/SecurityNotAllowedFunctionError.php @@ -1,11 +1,35 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\Sandbox; -class_exists('Twig_Sandbox_SecurityNotAllowedFunctionError'); +/** + * Exception thrown when a not allowed function is used in a template. + * + * @author Martin Hasoň <martin.hason@gmail.com> + */ +class SecurityNotAllowedFunctionError extends SecurityError +{ + private $functionName; -if (\false) { - class SecurityNotAllowedFunctionError extends \Twig_Sandbox_SecurityNotAllowedFunctionError + public function __construct($message, $functionName, $lineno = -1, $filename = null, \Exception $previous = null) { + parent::__construct($message, $lineno, $filename, $previous); + $this->functionName = $functionName; + } + + public function getFunctionName() + { + return $this->functionName; } } + +class_alias('Twig\Sandbox\SecurityNotAllowedFunctionError', 'Twig_Sandbox_SecurityNotAllowedFunctionError'); diff --git a/vendor/twig/twig/src/Sandbox/SecurityNotAllowedMethodError.php b/vendor/twig/twig/src/Sandbox/SecurityNotAllowedMethodError.php index 9f81c69e5d71c2a627dac706be7bc7dbb0394b26..62e13f49bde533f31f79e1a64c144bac4bd438d3 100644 --- a/vendor/twig/twig/src/Sandbox/SecurityNotAllowedMethodError.php +++ b/vendor/twig/twig/src/Sandbox/SecurityNotAllowedMethodError.php @@ -1,11 +1,42 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\Sandbox; -class_exists('Twig_Sandbox_SecurityNotAllowedMethodError'); +/** + * Exception thrown when a not allowed class method is used in a template. + * + * @author Kit Burton-Senior <mail@kitbs.com> + */ +class SecurityNotAllowedMethodError extends SecurityError +{ + private $className; + private $methodName; + + public function __construct($message, $className, $methodName, $lineno = -1, $filename = null, \Exception $previous = null) + { + parent::__construct($message, $lineno, $filename, $previous); + $this->className = $className; + $this->methodName = $methodName; + } + + public function getClassName() + { + return $this->className; + } -if (\false) { - class SecurityNotAllowedMethodError extends \Twig_Sandbox_SecurityNotAllowedMethodError + public function getMethodName() { + return $this->methodName; } } + +class_alias('Twig\Sandbox\SecurityNotAllowedMethodError', 'Twig_Sandbox_SecurityNotAllowedMethodError'); diff --git a/vendor/twig/twig/src/Sandbox/SecurityNotAllowedPropertyError.php b/vendor/twig/twig/src/Sandbox/SecurityNotAllowedPropertyError.php index 5a5d4307a38589a0e1bd3e8c3f91e9e03748d4e2..3bf530574f85672e4217ead8f8152d0743f82003 100644 --- a/vendor/twig/twig/src/Sandbox/SecurityNotAllowedPropertyError.php +++ b/vendor/twig/twig/src/Sandbox/SecurityNotAllowedPropertyError.php @@ -1,11 +1,42 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\Sandbox; -class_exists('Twig_Sandbox_SecurityNotAllowedPropertyError'); +/** + * Exception thrown when a not allowed class property is used in a template. + * + * @author Kit Burton-Senior <mail@kitbs.com> + */ +class SecurityNotAllowedPropertyError extends SecurityError +{ + private $className; + private $propertyName; + + public function __construct($message, $className, $propertyName, $lineno = -1, $filename = null, \Exception $previous = null) + { + parent::__construct($message, $lineno, $filename, $previous); + $this->className = $className; + $this->propertyName = $propertyName; + } + + public function getClassName() + { + return $this->className; + } -if (\false) { - class SecurityNotAllowedPropertyError extends \Twig_Sandbox_SecurityNotAllowedPropertyError + public function getPropertyName() { + return $this->propertyName; } } + +class_alias('Twig\Sandbox\SecurityNotAllowedPropertyError', 'Twig_Sandbox_SecurityNotAllowedPropertyError'); diff --git a/vendor/twig/twig/src/Sandbox/SecurityNotAllowedTagError.php b/vendor/twig/twig/src/Sandbox/SecurityNotAllowedTagError.php index 0463f2a38dc908b3799e560063560b6505d5e02b..de283b40cd7e9f96ce1443e3ecde7d6c94b53ecb 100644 --- a/vendor/twig/twig/src/Sandbox/SecurityNotAllowedTagError.php +++ b/vendor/twig/twig/src/Sandbox/SecurityNotAllowedTagError.php @@ -1,11 +1,35 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\Sandbox; -class_exists('Twig_Sandbox_SecurityNotAllowedTagError'); +/** + * Exception thrown when a not allowed tag is used in a template. + * + * @author Martin Hasoň <martin.hason@gmail.com> + */ +class SecurityNotAllowedTagError extends SecurityError +{ + private $tagName; -if (\false) { - class SecurityNotAllowedTagError extends \Twig_Sandbox_SecurityNotAllowedTagError + public function __construct($message, $tagName, $lineno = -1, $filename = null, \Exception $previous = null) { + parent::__construct($message, $lineno, $filename, $previous); + $this->tagName = $tagName; + } + + public function getTagName() + { + return $this->tagName; } } + +class_alias('Twig\Sandbox\SecurityNotAllowedTagError', 'Twig_Sandbox_SecurityNotAllowedTagError'); diff --git a/vendor/twig/twig/src/Sandbox/SecurityPolicy.php b/vendor/twig/twig/src/Sandbox/SecurityPolicy.php index b45b28526f0823c73a8a4c534495940494b56a52..31b6c34833230b7c8a54d0ac16e6b642ad8939aa 100644 --- a/vendor/twig/twig/src/Sandbox/SecurityPolicy.php +++ b/vendor/twig/twig/src/Sandbox/SecurityPolicy.php @@ -1,11 +1,129 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\Sandbox; -class_exists('Twig_Sandbox_SecurityPolicy'); +use Twig\Markup; + +/** + * Represents a security policy which need to be enforced when sandbox mode is enabled. + * + * @final + * + * @author Fabien Potencier <fabien@symfony.com> + */ +class SecurityPolicy implements SecurityPolicyInterface +{ + protected $allowedTags; + protected $allowedFilters; + protected $allowedMethods; + protected $allowedProperties; + protected $allowedFunctions; + + public function __construct(array $allowedTags = [], array $allowedFilters = [], array $allowedMethods = [], array $allowedProperties = [], array $allowedFunctions = []) + { + $this->allowedTags = $allowedTags; + $this->allowedFilters = $allowedFilters; + $this->setAllowedMethods($allowedMethods); + $this->allowedProperties = $allowedProperties; + $this->allowedFunctions = $allowedFunctions; + } + + public function setAllowedTags(array $tags) + { + $this->allowedTags = $tags; + } + + public function setAllowedFilters(array $filters) + { + $this->allowedFilters = $filters; + } + + public function setAllowedMethods(array $methods) + { + $this->allowedMethods = []; + foreach ($methods as $class => $m) { + $this->allowedMethods[$class] = array_map('strtolower', \is_array($m) ? $m : [$m]); + } + } + + public function setAllowedProperties(array $properties) + { + $this->allowedProperties = $properties; + } + + public function setAllowedFunctions(array $functions) + { + $this->allowedFunctions = $functions; + } -if (\false) { - class SecurityPolicy extends \Twig_Sandbox_SecurityPolicy + public function checkSecurity($tags, $filters, $functions) { + foreach ($tags as $tag) { + if (!\in_array($tag, $this->allowedTags)) { + throw new SecurityNotAllowedTagError(sprintf('Tag "%s" is not allowed.', $tag), $tag); + } + } + + foreach ($filters as $filter) { + if (!\in_array($filter, $this->allowedFilters)) { + throw new SecurityNotAllowedFilterError(sprintf('Filter "%s" is not allowed.', $filter), $filter); + } + } + + foreach ($functions as $function) { + if (!\in_array($function, $this->allowedFunctions)) { + throw new SecurityNotAllowedFunctionError(sprintf('Function "%s" is not allowed.', $function), $function); + } + } + } + + public function checkMethodAllowed($obj, $method) + { + if ($obj instanceof \Twig_TemplateInterface || $obj instanceof Markup) { + return; + } + + $allowed = false; + $method = strtolower($method); + foreach ($this->allowedMethods as $class => $methods) { + if ($obj instanceof $class) { + $allowed = \in_array($method, $methods); + + break; + } + } + + if (!$allowed) { + $class = \get_class($obj); + throw new SecurityNotAllowedMethodError(sprintf('Calling "%s" method on a "%s" object is not allowed.', $method, $class), $class, $method); + } + } + + public function checkPropertyAllowed($obj, $property) + { + $allowed = false; + foreach ($this->allowedProperties as $class => $properties) { + if ($obj instanceof $class) { + $allowed = \in_array($property, \is_array($properties) ? $properties : [$properties]); + + break; + } + } + + if (!$allowed) { + $class = \get_class($obj); + throw new SecurityNotAllowedPropertyError(sprintf('Calling "%s" property on a "%s" object is not allowed.', $property, $class), $class, $property); + } } } + +class_alias('Twig\Sandbox\SecurityPolicy', 'Twig_Sandbox_SecurityPolicy'); diff --git a/vendor/twig/twig/src/Sandbox/SecurityPolicyInterface.php b/vendor/twig/twig/src/Sandbox/SecurityPolicyInterface.php index 78a84e387b8f6565b3b829210578d6b52e634e8a..a31863f6c27a4bb3aad3cf443d21571577ea9953 100644 --- a/vendor/twig/twig/src/Sandbox/SecurityPolicyInterface.php +++ b/vendor/twig/twig/src/Sandbox/SecurityPolicyInterface.php @@ -1,11 +1,28 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\Sandbox; -class_exists('Twig_Sandbox_SecurityPolicyInterface'); +/** + * Interface that all security policy classes must implements. + * + * @author Fabien Potencier <fabien@symfony.com> + */ +interface SecurityPolicyInterface +{ + public function checkSecurity($tags, $filters, $functions); + + public function checkMethodAllowed($obj, $method); -if (\false) { - interface SecurityPolicyInterface extends \Twig_Sandbox_SecurityPolicyInterface - { - } + public function checkPropertyAllowed($obj, $method); } + +class_alias('Twig\Sandbox\SecurityPolicyInterface', 'Twig_Sandbox_SecurityPolicyInterface'); diff --git a/vendor/twig/twig/src/Source.php b/vendor/twig/twig/src/Source.php index b4978136110b2189182bf2077b5cfa8665e40a5d..32a82163f4b999734b72c7a687521077f756f5dc 100644 --- a/vendor/twig/twig/src/Source.php +++ b/vendor/twig/twig/src/Source.php @@ -1,11 +1,55 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig; -class_exists('Twig_Source'); +/** + * Holds information about a non-compiled Twig template. + * + * @final + * + * @author Fabien Potencier <fabien@symfony.com> + */ +class Source +{ + private $code; + private $name; + private $path; + + /** + * @param string $code The template source code + * @param string $name The template logical name + * @param string $path The filesystem path of the template if any + */ + public function __construct($code, $name, $path = '') + { + $this->code = $code; + $this->name = $name; + $this->path = $path; + } -if (\false) { - class Source extends \Twig_Source + public function getCode() { + return $this->code; + } + + public function getName() + { + return $this->name; + } + + public function getPath() + { + return $this->path; } } + +class_alias('Twig\Source', 'Twig_Source'); diff --git a/vendor/twig/twig/src/Template.php b/vendor/twig/twig/src/Template.php index 13677f600a44c31720ec482ca7a139b3372ff031..3f7447c126cf5bab09e62ca7f77006d916a17c3e 100644 --- a/vendor/twig/twig/src/Template.php +++ b/vendor/twig/twig/src/Template.php @@ -1,11 +1,733 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * (c) Armin Ronacher + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig; -class_exists('Twig_Template'); +use Twig\Error\Error; +use Twig\Error\LoaderError; +use Twig\Error\RuntimeError; + +/** + * Default base class for compiled templates. + * + * This class is an implementation detail of how template compilation currently + * works, which might change. It should never be used directly. Use $twig->load() + * instead, which returns an instance of \Twig\TemplateWrapper. + * + * @author Fabien Potencier <fabien@symfony.com> + * + * @internal + */ +abstract class Template implements \Twig_TemplateInterface +{ + /** + * @internal + */ + protected static $cache = []; + + protected $parent; + protected $parents = []; + protected $env; + protected $blocks = []; + protected $traits = []; + protected $sandbox; + + public function __construct(Environment $env) + { + $this->env = $env; + } + + /** + * @internal this method will be removed in 2.0 and is only used internally to provide an upgrade path from 1.x to 2.0 + */ + public function __toString() + { + return $this->getTemplateName(); + } + + /** + * Returns the template name. + * + * @return string The template name + */ + abstract public function getTemplateName(); + + /** + * Returns debug information about the template. + * + * @return array Debug information + */ + public function getDebugInfo() + { + return []; + } + + /** + * Returns the template source code. + * + * @return string The template source code + * + * @deprecated since 1.27 (to be removed in 2.0). Use getSourceContext() instead + */ + public function getSource() + { + @trigger_error('The '.__METHOD__.' method is deprecated since version 1.27 and will be removed in 2.0. Use getSourceContext() instead.', E_USER_DEPRECATED); + + return ''; + } + + /** + * Returns information about the original template source code. + * + * @return Source + */ + public function getSourceContext() + { + return new Source('', $this->getTemplateName()); + } + + /** + * @deprecated since 1.20 (to be removed in 2.0) + */ + public function getEnvironment() + { + @trigger_error('The '.__METHOD__.' method is deprecated since version 1.20 and will be removed in 2.0.', E_USER_DEPRECATED); + + return $this->env; + } + + /** + * Returns the parent template. + * + * This method is for internal use only and should never be called + * directly. + * + * @param array $context + * + * @return \Twig_TemplateInterface|TemplateWrapper|false The parent template or false if there is no parent + * + * @internal + */ + public function getParent(array $context) + { + if (null !== $this->parent) { + return $this->parent; + } + + try { + $parent = $this->doGetParent($context); + + if (false === $parent) { + return false; + } + + if ($parent instanceof self || $parent instanceof TemplateWrapper) { + return $this->parents[$parent->getSourceContext()->getName()] = $parent; + } + + if (!isset($this->parents[$parent])) { + $this->parents[$parent] = $this->loadTemplate($parent); + } + } catch (LoaderError $e) { + $e->setSourceContext(null); + $e->guess(); + + throw $e; + } + + return $this->parents[$parent]; + } + + protected function doGetParent(array $context) + { + return false; + } + + public function isTraitable() + { + return true; + } + + /** + * Displays a parent block. + * + * This method is for internal use only and should never be called + * directly. + * + * @param string $name The block name to display from the parent + * @param array $context The context + * @param array $blocks The current set of blocks + */ + public function displayParentBlock($name, array $context, array $blocks = []) + { + $name = (string) $name; + + if (isset($this->traits[$name])) { + $this->traits[$name][0]->displayBlock($name, $context, $blocks, false); + } elseif (false !== $parent = $this->getParent($context)) { + $parent->displayBlock($name, $context, $blocks, false); + } else { + throw new RuntimeError(sprintf('The template has no parent and no traits defining the "%s" block.', $name), -1, $this->getSourceContext()); + } + } + + /** + * Displays a block. + * + * This method is for internal use only and should never be called + * directly. + * + * @param string $name The block name to display + * @param array $context The context + * @param array $blocks The current set of blocks + * @param bool $useBlocks Whether to use the current set of blocks + */ + public function displayBlock($name, array $context, array $blocks = [], $useBlocks = true) + { + $name = (string) $name; + + if ($useBlocks && isset($blocks[$name])) { + $template = $blocks[$name][0]; + $block = $blocks[$name][1]; + } elseif (isset($this->blocks[$name])) { + $template = $this->blocks[$name][0]; + $block = $this->blocks[$name][1]; + } else { + $template = null; + $block = null; + } + + // avoid RCEs when sandbox is enabled + if (null !== $template && !$template instanceof self) { + throw new \LogicException('A block must be a method on a \Twig\Template instance.'); + } + + if (null !== $template) { + try { + $template->$block($context, $blocks); + } catch (Error $e) { + if (!$e->getSourceContext()) { + $e->setSourceContext($template->getSourceContext()); + } + + // this is mostly useful for \Twig\Error\LoaderError exceptions + // see \Twig\Error\LoaderError + if (-1 === $e->getTemplateLine()) { + $e->guess(); + } + + throw $e; + } catch (\Exception $e) { + $e = new RuntimeError(sprintf('An exception has been thrown during the rendering of a template ("%s").', $e->getMessage()), -1, $template->getSourceContext(), $e); + $e->guess(); + + throw $e; + } + } elseif (false !== $parent = $this->getParent($context)) { + $parent->displayBlock($name, $context, array_merge($this->blocks, $blocks), false); + } else { + @trigger_error(sprintf('Silent display of undefined block "%s" in template "%s" is deprecated since version 1.29 and will throw an exception in 2.0. Use the "block(\'%s\') is defined" expression to test for block existence.', $name, $this->getTemplateName(), $name), E_USER_DEPRECATED); + } + } + + /** + * Renders a parent block. + * + * This method is for internal use only and should never be called + * directly. + * + * @param string $name The block name to render from the parent + * @param array $context The context + * @param array $blocks The current set of blocks + * + * @return string The rendered block + */ + public function renderParentBlock($name, array $context, array $blocks = []) + { + if ($this->env->isDebug()) { + ob_start(); + } else { + ob_start(function () { return ''; }); + } + $this->displayParentBlock($name, $context, $blocks); + + return ob_get_clean(); + } + + /** + * Renders a block. + * + * This method is for internal use only and should never be called + * directly. + * + * @param string $name The block name to render + * @param array $context The context + * @param array $blocks The current set of blocks + * @param bool $useBlocks Whether to use the current set of blocks + * + * @return string The rendered block + */ + public function renderBlock($name, array $context, array $blocks = [], $useBlocks = true) + { + if ($this->env->isDebug()) { + ob_start(); + } else { + ob_start(function () { return ''; }); + } + $this->displayBlock($name, $context, $blocks, $useBlocks); + + return ob_get_clean(); + } + + /** + * Returns whether a block exists or not in the current context of the template. + * + * This method checks blocks defined in the current template + * or defined in "used" traits or defined in parent templates. + * + * @param string $name The block name + * @param array $context The context + * @param array $blocks The current set of blocks + * + * @return bool true if the block exists, false otherwise + */ + public function hasBlock($name, array $context = null, array $blocks = []) + { + if (null === $context) { + @trigger_error('The '.__METHOD__.' method is internal and should never be called; calling it directly is deprecated since version 1.28 and won\'t be possible anymore in 2.0.', E_USER_DEPRECATED); + + return isset($this->blocks[(string) $name]); + } + + if (isset($blocks[$name])) { + return $blocks[$name][0] instanceof self; + } + + if (isset($this->blocks[$name])) { + return true; + } + + if (false !== $parent = $this->getParent($context)) { + return $parent->hasBlock($name, $context); + } + + return false; + } + + /** + * Returns all block names in the current context of the template. + * + * This method checks blocks defined in the current template + * or defined in "used" traits or defined in parent templates. + * + * @param array $context The context + * @param array $blocks The current set of blocks + * + * @return array An array of block names + */ + public function getBlockNames(array $context = null, array $blocks = []) + { + if (null === $context) { + @trigger_error('The '.__METHOD__.' method is internal and should never be called; calling it directly is deprecated since version 1.28 and won\'t be possible anymore in 2.0.', E_USER_DEPRECATED); + + return array_keys($this->blocks); + } -if (\false) { - class Template extends \Twig_Template + $names = array_merge(array_keys($blocks), array_keys($this->blocks)); + + if (false !== $parent = $this->getParent($context)) { + $names = array_merge($names, $parent->getBlockNames($context)); + } + + return array_unique($names); + } + + /** + * @return Template|TemplateWrapper + */ + protected function loadTemplate($template, $templateName = null, $line = null, $index = null) + { + try { + if (\is_array($template)) { + return $this->env->resolveTemplate($template); + } + + if ($template instanceof self || $template instanceof TemplateWrapper) { + return $template; + } + + if ($template === $this->getTemplateName()) { + $class = \get_class($this); + if (false !== $pos = strrpos($class, '___', -1)) { + $class = substr($class, 0, $pos); + } + + return $this->env->loadClass($class, $template, $index); + } + + return $this->env->loadTemplate($template, $index); + } catch (Error $e) { + if (!$e->getSourceContext()) { + $e->setSourceContext($templateName ? new Source('', $templateName) : $this->getSourceContext()); + } + + if ($e->getTemplateLine() > 0) { + throw $e; + } + + if (!$line) { + $e->guess(); + } else { + $e->setTemplateLine($line); + } + + throw $e; + } + } + + /** + * @internal + * + * @return Template + */ + protected function unwrap() + { + return $this; + } + + /** + * Returns all blocks. + * + * This method is for internal use only and should never be called + * directly. + * + * @return array An array of blocks + */ + public function getBlocks() + { + return $this->blocks; + } + + public function display(array $context, array $blocks = []) + { + $this->displayWithErrorHandling($this->env->mergeGlobals($context), array_merge($this->blocks, $blocks)); + } + + public function render(array $context) + { + $level = ob_get_level(); + if ($this->env->isDebug()) { + ob_start(); + } else { + ob_start(function () { return ''; }); + } + try { + $this->display($context); + } catch (\Exception $e) { + while (ob_get_level() > $level) { + ob_end_clean(); + } + + throw $e; + } catch (\Throwable $e) { + while (ob_get_level() > $level) { + ob_end_clean(); + } + + throw $e; + } + + return ob_get_clean(); + } + + protected function displayWithErrorHandling(array $context, array $blocks = []) { + try { + $this->doDisplay($context, $blocks); + } catch (Error $e) { + if (!$e->getSourceContext()) { + $e->setSourceContext($this->getSourceContext()); + } + + // this is mostly useful for \Twig\Error\LoaderError exceptions + // see \Twig\Error\LoaderError + if (-1 === $e->getTemplateLine()) { + $e->guess(); + } + + throw $e; + } catch (\Exception $e) { + $e = new RuntimeError(sprintf('An exception has been thrown during the rendering of a template ("%s").', $e->getMessage()), -1, $this->getSourceContext(), $e); + $e->guess(); + + throw $e; + } + } + + /** + * Auto-generated method to display the template with the given context. + * + * @param array $context An array of parameters to pass to the template + * @param array $blocks An array of blocks to pass to the template + */ + abstract protected function doDisplay(array $context, array $blocks = []); + + /** + * Returns a variable from the context. + * + * This method is for internal use only and should never be called + * directly. + * + * This method should not be overridden in a sub-class as this is an + * implementation detail that has been introduced to optimize variable + * access for versions of PHP before 5.4. This is not a way to override + * the way to get a variable value. + * + * @param array $context The context + * @param string $item The variable to return from the context + * @param bool $ignoreStrictCheck Whether to ignore the strict variable check or not + * + * @return mixed The content of the context variable + * + * @throws RuntimeError if the variable does not exist and Twig is running in strict mode + * + * @internal + */ + final protected function getContext($context, $item, $ignoreStrictCheck = false) + { + if (!\array_key_exists($item, $context)) { + if ($ignoreStrictCheck || !$this->env->isStrictVariables()) { + return; + } + + throw new RuntimeError(sprintf('Variable "%s" does not exist.', $item), -1, $this->getSourceContext()); + } + + return $context[$item]; + } + + /** + * Returns the attribute value for a given array/object. + * + * @param mixed $object The object or array from where to get the item + * @param mixed $item The item to get from the array or object + * @param array $arguments An array of arguments to pass if the item is an object method + * @param string $type The type of attribute (@see \Twig\Template constants) + * @param bool $isDefinedTest Whether this is only a defined check + * @param bool $ignoreStrictCheck Whether to ignore the strict attribute check or not + * + * @return mixed The attribute value, or a Boolean when $isDefinedTest is true, or null when the attribute is not set and $ignoreStrictCheck is true + * + * @throws RuntimeError if the attribute does not exist and Twig is running in strict mode and $isDefinedTest is false + * + * @internal + */ + protected function getAttribute($object, $item, array $arguments = [], $type = self::ANY_CALL, $isDefinedTest = false, $ignoreStrictCheck = false) + { + // array + if (self::METHOD_CALL !== $type) { + $arrayItem = \is_bool($item) || \is_float($item) ? (int) $item : $item; + + if (((\is_array($object) || $object instanceof \ArrayObject) && (isset($object[$arrayItem]) || \array_key_exists($arrayItem, (array) $object))) + || ($object instanceof \ArrayAccess && isset($object[$arrayItem])) + ) { + if ($isDefinedTest) { + return true; + } + + return $object[$arrayItem]; + } + + if (self::ARRAY_CALL === $type || !\is_object($object)) { + if ($isDefinedTest) { + return false; + } + + if ($ignoreStrictCheck || !$this->env->isStrictVariables()) { + return; + } + + if ($object instanceof \ArrayAccess) { + $message = sprintf('Key "%s" in object with ArrayAccess of class "%s" does not exist.', $arrayItem, \get_class($object)); + } elseif (\is_object($object)) { + $message = sprintf('Impossible to access a key "%s" on an object of class "%s" that does not implement ArrayAccess interface.', $item, \get_class($object)); + } elseif (\is_array($object)) { + if (empty($object)) { + $message = sprintf('Key "%s" does not exist as the array is empty.', $arrayItem); + } else { + $message = sprintf('Key "%s" for array with keys "%s" does not exist.', $arrayItem, implode(', ', array_keys($object))); + } + } elseif (self::ARRAY_CALL === $type) { + if (null === $object) { + $message = sprintf('Impossible to access a key ("%s") on a null variable.', $item); + } else { + $message = sprintf('Impossible to access a key ("%s") on a %s variable ("%s").', $item, \gettype($object), $object); + } + } elseif (null === $object) { + $message = sprintf('Impossible to access an attribute ("%s") on a null variable.', $item); + } else { + $message = sprintf('Impossible to access an attribute ("%s") on a %s variable ("%s").', $item, \gettype($object), $object); + } + + throw new RuntimeError($message, -1, $this->getSourceContext()); + } + } + + if (!\is_object($object)) { + if ($isDefinedTest) { + return false; + } + + if ($ignoreStrictCheck || !$this->env->isStrictVariables()) { + return; + } + + if (null === $object) { + $message = sprintf('Impossible to invoke a method ("%s") on a null variable.', $item); + } elseif (\is_array($object)) { + $message = sprintf('Impossible to invoke a method ("%s") on an array.', $item); + } else { + $message = sprintf('Impossible to invoke a method ("%s") on a %s variable ("%s").', $item, \gettype($object), $object); + } + + throw new RuntimeError($message, -1, $this->getSourceContext()); + } + + // object property + if (self::METHOD_CALL !== $type && !$object instanceof self) { // \Twig\Template does not have public properties, and we don't want to allow access to internal ones + if (isset($object->$item) || \array_key_exists((string) $item, (array) $object)) { + if ($isDefinedTest) { + return true; + } + + if ($this->env->hasExtension('\Twig\Extension\SandboxExtension')) { + $this->env->getExtension('\Twig\Extension\SandboxExtension')->checkPropertyAllowed($object, $item); + } + + return $object->$item; + } + } + + $class = \get_class($object); + + // object method + if (!isset(self::$cache[$class])) { + // get_class_methods returns all methods accessible in the scope, but we only want public ones to be accessible in templates + if ($object instanceof self) { + $ref = new \ReflectionClass($class); + $methods = []; + + foreach ($ref->getMethods(\ReflectionMethod::IS_PUBLIC) as $refMethod) { + // Accessing the environment from templates is forbidden to prevent untrusted changes to the environment + if ('getenvironment' !== strtolower($refMethod->name)) { + $methods[] = $refMethod->name; + } + } + } else { + $methods = get_class_methods($object); + } + // sort values to have consistent behavior, so that "get" methods win precedence over "is" methods + sort($methods); + + $cache = []; + + foreach ($methods as $method) { + $cache[$method] = $method; + $cache[$lcName = strtolower($method)] = $method; + + if ('g' === $lcName[0] && 0 === strpos($lcName, 'get')) { + $name = substr($method, 3); + $lcName = substr($lcName, 3); + } elseif ('i' === $lcName[0] && 0 === strpos($lcName, 'is')) { + $name = substr($method, 2); + $lcName = substr($lcName, 2); + } else { + continue; + } + + // skip get() and is() methods (in which case, $name is empty) + if ($name) { + if (!isset($cache[$name])) { + $cache[$name] = $method; + } + if (!isset($cache[$lcName])) { + $cache[$lcName] = $method; + } + } + } + self::$cache[$class] = $cache; + } + + $call = false; + if (isset(self::$cache[$class][$item])) { + $method = self::$cache[$class][$item]; + } elseif (isset(self::$cache[$class][$lcItem = strtolower($item)])) { + $method = self::$cache[$class][$lcItem]; + } elseif (isset(self::$cache[$class]['__call'])) { + $method = $item; + $call = true; + } else { + if ($isDefinedTest) { + return false; + } + + if ($ignoreStrictCheck || !$this->env->isStrictVariables()) { + return; + } + + throw new RuntimeError(sprintf('Neither the property "%1$s" nor one of the methods "%1$s()", "get%1$s()"/"is%1$s()" or "__call()" exist and have public access in class "%2$s".', $item, $class), -1, $this->getSourceContext()); + } + + if ($isDefinedTest) { + return true; + } + + if ($this->env->hasExtension('\Twig\Extension\SandboxExtension')) { + $this->env->getExtension('\Twig\Extension\SandboxExtension')->checkMethodAllowed($object, $method); + } + + // Some objects throw exceptions when they have __call, and the method we try + // to call is not supported. If ignoreStrictCheck is true, we should return null. + try { + if (!$arguments) { + $ret = $object->$method(); + } else { + $ret = \call_user_func_array([$object, $method], $arguments); + } + } catch (\BadMethodCallException $e) { + if ($call && ($ignoreStrictCheck || !$this->env->isStrictVariables())) { + return; + } + throw $e; + } + + // @deprecated in 1.28 + if ($object instanceof \Twig_TemplateInterface) { + $self = $object->getTemplateName() === $this->getTemplateName(); + $message = sprintf('Calling "%s" on template "%s" from template "%s" is deprecated since version 1.28 and won\'t be supported anymore in 2.0.', $item, $object->getTemplateName(), $this->getTemplateName()); + if ('renderBlock' === $method || 'displayBlock' === $method) { + $message .= sprintf(' Use block("%s"%s) instead).', $arguments[0], $self ? '' : ', template'); + } elseif ('hasBlock' === $method) { + $message .= sprintf(' Use "block("%s"%s) is defined" instead).', $arguments[0], $self ? '' : ', template'); + } elseif ('render' === $method || 'display' === $method) { + $message .= sprintf(' Use include("%s") instead).', $object->getTemplateName()); + } + @trigger_error($message, E_USER_DEPRECATED); + + return '' === $ret ? '' : new Markup($ret, $this->env->getCharset()); + } + + return $ret; } } + +class_alias('Twig\Template', 'Twig_Template'); diff --git a/vendor/twig/twig/src/TemplateWrapper.php b/vendor/twig/twig/src/TemplateWrapper.php index d11ad81cc660e8b17fbc249a9ca27aa2c63aade3..e2654094e4ec65b756d5a79511fa71ff36a0379e 100644 --- a/vendor/twig/twig/src/TemplateWrapper.php +++ b/vendor/twig/twig/src/TemplateWrapper.php @@ -1,11 +1,161 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig; -class_exists('Twig_TemplateWrapper'); +/** + * Exposes a template to userland. + * + * @author Fabien Potencier <fabien@symfony.com> + */ +final class TemplateWrapper +{ + private $env; + private $template; + + /** + * This method is for internal use only and should never be called + * directly (use Twig\Environment::load() instead). + * + * @internal + */ + public function __construct(Environment $env, Template $template) + { + $this->env = $env; + $this->template = $template; + } + + /** + * Renders the template. + * + * @param array $context An array of parameters to pass to the template + * + * @return string The rendered template + */ + public function render($context = []) + { + // using func_get_args() allows to not expose the blocks argument + // as it should only be used by internal code + return $this->template->render($context, \func_num_args() > 1 ? func_get_arg(1) : []); + } + + /** + * Displays the template. + * + * @param array $context An array of parameters to pass to the template + */ + public function display($context = []) + { + // using func_get_args() allows to not expose the blocks argument + // as it should only be used by internal code + $this->template->display($context, \func_num_args() > 1 ? func_get_arg(1) : []); + } + + /** + * Checks if a block is defined. + * + * @param string $name The block name + * @param array $context An array of parameters to pass to the template + * + * @return bool + */ + public function hasBlock($name, $context = []) + { + return $this->template->hasBlock($name, $context); + } + + /** + * Returns defined block names in the template. + * + * @param array $context An array of parameters to pass to the template + * + * @return string[] An array of defined template block names + */ + public function getBlockNames($context = []) + { + return $this->template->getBlockNames($context); + } + + /** + * Renders a template block. + * + * @param string $name The block name to render + * @param array $context An array of parameters to pass to the template + * + * @return string The rendered block + */ + public function renderBlock($name, $context = []) + { + $context = $this->env->mergeGlobals($context); + $level = ob_get_level(); + if ($this->env->isDebug()) { + ob_start(); + } else { + ob_start(function () { return ''; }); + } + try { + $this->template->displayBlock($name, $context); + } catch (\Exception $e) { + while (ob_get_level() > $level) { + ob_end_clean(); + } + + throw $e; + } catch (\Throwable $e) { + while (ob_get_level() > $level) { + ob_end_clean(); + } + + throw $e; + } + + return ob_get_clean(); + } + + /** + * Displays a template block. + * + * @param string $name The block name to render + * @param array $context An array of parameters to pass to the template + */ + public function displayBlock($name, $context = []) + { + $this->template->displayBlock($name, $this->env->mergeGlobals($context)); + } + + /** + * @return Source + */ + public function getSourceContext() + { + return $this->template->getSourceContext(); + } + + /** + * @return string + */ + public function getTemplateName() + { + return $this->template->getTemplateName(); + } -if (\false) { - class TemplateWrapper extends \Twig_TemplateWrapper + /** + * @internal + * + * @return Template + */ + public function unwrap() { + return $this->template; } } + +class_alias('Twig\TemplateWrapper', 'Twig_TemplateWrapper'); diff --git a/vendor/twig/twig/src/Test/IntegrationTestCase.php b/vendor/twig/twig/src/Test/IntegrationTestCase.php index 50f90ac436b696e6133807d91430246522327103..36b36075867cb7f869ad1f3585a181abb1314f62 100644 --- a/vendor/twig/twig/src/Test/IntegrationTestCase.php +++ b/vendor/twig/twig/src/Test/IntegrationTestCase.php @@ -1,11 +1,257 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\Test; -class_exists('Twig_Test_IntegrationTestCase'); +use PHPUnit\Framework\TestCase; +use Twig\Environment; +use Twig\Error\Error; +use Twig\Extension\ExtensionInterface; +use Twig\Loader\ArrayLoader; +use Twig\Loader\SourceContextLoaderInterface; +use Twig\RuntimeLoader\RuntimeLoaderInterface; +use Twig\Source; +use Twig\TwigFilter; +use Twig\TwigFunction; +use Twig\TwigTest; + +/** + * Integration test helper. + * + * @author Fabien Potencier <fabien@symfony.com> + * @author Karma Dordrak <drak@zikula.org> + */ +abstract class IntegrationTestCase extends TestCase +{ + /** + * @return string + */ + abstract protected function getFixturesDir(); + + /** + * @return RuntimeLoaderInterface[] + */ + protected function getRuntimeLoaders() + { + return []; + } + + /** + * @return ExtensionInterface[] + */ + protected function getExtensions() + { + return []; + } + + /** + * @return TwigFilter[] + */ + protected function getTwigFilters() + { + return []; + } + + /** + * @return TwigFunction[] + */ + protected function getTwigFunctions() + { + return []; + } + + /** + * @return TwigTest[] + */ + protected function getTwigTests() + { + return []; + } + + /** + * @dataProvider getTests + */ + public function testIntegration($file, $message, $condition, $templates, $exception, $outputs) + { + $this->doIntegrationTest($file, $message, $condition, $templates, $exception, $outputs); + } + + /** + * @dataProvider getLegacyTests + * @group legacy + */ + public function testLegacyIntegration($file, $message, $condition, $templates, $exception, $outputs) + { + $this->doIntegrationTest($file, $message, $condition, $templates, $exception, $outputs); + } + + public function getTests($name, $legacyTests = false) + { + $fixturesDir = realpath($this->getFixturesDir()); + $tests = []; + + foreach (new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($fixturesDir), \RecursiveIteratorIterator::LEAVES_ONLY) as $file) { + if (!preg_match('/\.test$/', $file)) { + continue; + } + + if ($legacyTests xor false !== strpos($file->getRealpath(), '.legacy.test')) { + continue; + } + + $test = file_get_contents($file->getRealpath()); + + if (preg_match('/--TEST--\s*(.*?)\s*(?:--CONDITION--\s*(.*))?\s*((?:--TEMPLATE(?:\(.*?\))?--(?:.*?))+)\s*(?:--DATA--\s*(.*))?\s*--EXCEPTION--\s*(.*)/sx', $test, $match)) { + $message = $match[1]; + $condition = $match[2]; + $templates = self::parseTemplates($match[3]); + $exception = $match[5]; + $outputs = [[null, $match[4], null, '']]; + } elseif (preg_match('/--TEST--\s*(.*?)\s*(?:--CONDITION--\s*(.*))?\s*((?:--TEMPLATE(?:\(.*?\))?--(?:.*?))+)--DATA--.*?--EXPECT--.*/s', $test, $match)) { + $message = $match[1]; + $condition = $match[2]; + $templates = self::parseTemplates($match[3]); + $exception = false; + preg_match_all('/--DATA--(.*?)(?:--CONFIG--(.*?))?--EXPECT--(.*?)(?=\-\-DATA\-\-|$)/s', $test, $outputs, PREG_SET_ORDER); + } else { + throw new \InvalidArgumentException(sprintf('Test "%s" is not valid.', str_replace($fixturesDir.'/', '', $file))); + } + + $tests[] = [str_replace($fixturesDir.'/', '', $file), $message, $condition, $templates, $exception, $outputs]; + } -if (\false) { - class IntegrationTestCase extends \Twig_Test_IntegrationTestCase + if ($legacyTests && empty($tests)) { + // add a dummy test to avoid a PHPUnit message + return [['not', '-', '', [], '', []]]; + } + + return $tests; + } + + public function getLegacyTests() + { + return $this->getTests('testLegacyIntegration', true); + } + + protected function doIntegrationTest($file, $message, $condition, $templates, $exception, $outputs) + { + if (!$outputs) { + $this->markTestSkipped('no tests to run'); + } + + if ($condition) { + eval('$ret = '.$condition.';'); + if (!$ret) { + $this->markTestSkipped($condition); + } + } + + $loader = new ArrayLoader($templates); + + foreach ($outputs as $i => $match) { + $config = array_merge([ + 'cache' => false, + 'strict_variables' => true, + ], $match[2] ? eval($match[2].';') : []); + $twig = new Environment($loader, $config); + $twig->addGlobal('global', 'global'); + foreach ($this->getRuntimeLoaders() as $runtimeLoader) { + $twig->addRuntimeLoader($runtimeLoader); + } + + foreach ($this->getExtensions() as $extension) { + $twig->addExtension($extension); + } + + foreach ($this->getTwigFilters() as $filter) { + $twig->addFilter($filter); + } + + foreach ($this->getTwigTests() as $test) { + $twig->addTest($test); + } + + foreach ($this->getTwigFunctions() as $function) { + $twig->addFunction($function); + } + + $p = new \ReflectionProperty($twig, 'templateClassPrefix'); + $p->setAccessible(true); + $p->setValue($twig, '__TwigTemplate_'.hash('sha256', uniqid(mt_rand(), true), false).'_'); + + try { + $template = $twig->load('index.twig'); + } catch (\Exception $e) { + if (false !== $exception) { + $message = $e->getMessage(); + $this->assertSame(trim($exception), trim(sprintf('%s: %s', \get_class($e), $message))); + $last = substr($message, \strlen($message) - 1); + $this->assertTrue('.' === $last || '?' === $last, 'Exception message must end with a dot or a question mark.'); + + return; + } + + throw new Error(sprintf('%s: %s', \get_class($e), $e->getMessage()), -1, null, $e); + } + + try { + $output = trim($template->render(eval($match[1].';')), "\n "); + } catch (\Exception $e) { + if (false !== $exception) { + $this->assertSame(trim($exception), trim(sprintf('%s: %s', \get_class($e), $e->getMessage()))); + + return; + } + + $e = new Error(sprintf('%s: %s', \get_class($e), $e->getMessage()), -1, null, $e); + + $output = trim(sprintf('%s: %s', \get_class($e), $e->getMessage())); + } + + if (false !== $exception) { + list($class) = explode(':', $exception); + $constraintClass = class_exists('PHPUnit\Framework\Constraint\Exception') ? 'PHPUnit\Framework\Constraint\Exception' : 'PHPUnit_Framework_Constraint_Exception'; + $this->assertThat(null, new $constraintClass($class)); + } + + $expected = trim($match[3], "\n "); + + if ($expected !== $output) { + printf("Compiled templates that failed on case %d:\n", $i + 1); + + foreach (array_keys($templates) as $name) { + echo "Template: $name\n"; + $loader = $twig->getLoader(); + if (!$loader instanceof SourceContextLoaderInterface) { + $source = new Source($loader->getSource($name), $name); + } else { + $source = $loader->getSourceContext($name); + } + echo $twig->compile($twig->parse($twig->tokenize($source))); + } + } + $this->assertEquals($expected, $output, $message.' (in '.$file.')'); + } + } + + protected static function parseTemplates($test) { + $templates = []; + preg_match_all('/--TEMPLATE(?:\((.*?)\))?--(.*?)(?=\-\-TEMPLATE|$)/s', $test, $matches, PREG_SET_ORDER); + foreach ($matches as $match) { + $templates[($match[1] ? $match[1] : 'index.twig')] = $match[2]; + } + + return $templates; } } + +class_alias('Twig\Test\IntegrationTestCase', 'Twig_Test_IntegrationTestCase'); diff --git a/vendor/twig/twig/src/Test/NodeTestCase.php b/vendor/twig/twig/src/Test/NodeTestCase.php index bf56b9742f40c7032bba376d42e860755ee3bdb3..f3358cb9a363d848b3756b465813775741982c7e 100644 --- a/vendor/twig/twig/src/Test/NodeTestCase.php +++ b/vendor/twig/twig/src/Test/NodeTestCase.php @@ -1,11 +1,79 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\Test; -class_exists('Twig_Test_NodeTestCase'); +use PHPUnit\Framework\TestCase; +use Twig\Compiler; +use Twig\Environment; +use Twig\Loader\ArrayLoader; +use Twig\Node\Node; + +abstract class NodeTestCase extends TestCase +{ + abstract public function getTests(); + + /** + * @dataProvider getTests + */ + public function testCompile($node, $source, $environment = null, $isPattern = false) + { + $this->assertNodeCompilation($source, $node, $environment, $isPattern); + } + + public function assertNodeCompilation($source, Node $node, Environment $environment = null, $isPattern = false) + { + $compiler = $this->getCompiler($environment); + $compiler->compile($node); + + if ($isPattern) { + $this->assertStringMatchesFormat($source, trim($compiler->getSource())); + } else { + $this->assertEquals($source, trim($compiler->getSource())); + } + } + + protected function getCompiler(Environment $environment = null) + { + return new Compiler(null === $environment ? $this->getEnvironment() : $environment); + } -if (\false) { - class NodeTestCase extends \Twig_Test_NodeTestCase + protected function getEnvironment() { + return new Environment(new ArrayLoader([])); + } + + protected function getVariableGetter($name, $line = false) + { + $line = $line > 0 ? "// line {$line}\n" : ''; + + if (\PHP_VERSION_ID >= 70000) { + return sprintf('%s($context["%s"] ?? null)', $line, $name); + } + + if (\PHP_VERSION_ID >= 50400) { + return sprintf('%s(isset($context["%s"]) ? $context["%s"] : null)', $line, $name, $name); + } + + return sprintf('%s$this->getContext($context, "%s")', $line, $name); + } + + protected function getAttributeGetter() + { + if (\function_exists('twig_template_get_attributes')) { + return 'twig_template_get_attributes($this, '; + } + + return '$this->getAttribute('; } } + +class_alias('Twig\Test\NodeTestCase', 'Twig_Test_NodeTestCase'); diff --git a/vendor/twig/twig/src/Token.php b/vendor/twig/twig/src/Token.php index c7751aa468875a5b67fde8dfb8910e8cb4984839..a0bb11af15eec7eb826175bc376447105ef4e3bf 100644 --- a/vendor/twig/twig/src/Token.php +++ b/vendor/twig/twig/src/Token.php @@ -1,11 +1,215 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * (c) Armin Ronacher + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig; -class_exists('Twig_Token'); +/** + * Represents a Token. + * + * @author Fabien Potencier <fabien@symfony.com> + * + * @final + */ +class Token +{ + protected $value; + protected $type; + protected $lineno; + + const EOF_TYPE = -1; + const TEXT_TYPE = 0; + const BLOCK_START_TYPE = 1; + const VAR_START_TYPE = 2; + const BLOCK_END_TYPE = 3; + const VAR_END_TYPE = 4; + const NAME_TYPE = 5; + const NUMBER_TYPE = 6; + const STRING_TYPE = 7; + const OPERATOR_TYPE = 8; + const PUNCTUATION_TYPE = 9; + const INTERPOLATION_START_TYPE = 10; + const INTERPOLATION_END_TYPE = 11; + const ARROW_TYPE = 12; + + /** + * @param int $type The type of the token + * @param string $value The token value + * @param int $lineno The line position in the source + */ + public function __construct($type, $value, $lineno) + { + $this->type = $type; + $this->value = $value; + $this->lineno = $lineno; + } + + public function __toString() + { + return sprintf('%s(%s)', self::typeToString($this->type, true), $this->value); + } + + /** + * Tests the current token for a type and/or a value. + * + * Parameters may be: + * * just type + * * type and value (or array of possible values) + * * just value (or array of possible values) (NAME_TYPE is used as type) + * + * @param array|string|int $type The type to test + * @param array|string|null $values The token value + * + * @return bool + */ + public function test($type, $values = null) + { + if (null === $values && !\is_int($type)) { + $values = $type; + $type = self::NAME_TYPE; + } + + return ($this->type === $type) && ( + null === $values || + (\is_array($values) && \in_array($this->value, $values)) || + $this->value == $values + ); + } + + /** + * @return int + */ + public function getLine() + { + return $this->lineno; + } -if (\false) { - class Token extends \Twig_Token + /** + * @return int + */ + public function getType() { + return $this->type; + } + + /** + * @return string + */ + public function getValue() + { + return $this->value; + } + + /** + * Returns the constant representation (internal) of a given type. + * + * @param int $type The type as an integer + * @param bool $short Whether to return a short representation or not + * + * @return string The string representation + */ + public static function typeToString($type, $short = false) + { + switch ($type) { + case self::EOF_TYPE: + $name = 'EOF_TYPE'; + break; + case self::TEXT_TYPE: + $name = 'TEXT_TYPE'; + break; + case self::BLOCK_START_TYPE: + $name = 'BLOCK_START_TYPE'; + break; + case self::VAR_START_TYPE: + $name = 'VAR_START_TYPE'; + break; + case self::BLOCK_END_TYPE: + $name = 'BLOCK_END_TYPE'; + break; + case self::VAR_END_TYPE: + $name = 'VAR_END_TYPE'; + break; + case self::NAME_TYPE: + $name = 'NAME_TYPE'; + break; + case self::NUMBER_TYPE: + $name = 'NUMBER_TYPE'; + break; + case self::STRING_TYPE: + $name = 'STRING_TYPE'; + break; + case self::OPERATOR_TYPE: + $name = 'OPERATOR_TYPE'; + break; + case self::PUNCTUATION_TYPE: + $name = 'PUNCTUATION_TYPE'; + break; + case self::INTERPOLATION_START_TYPE: + $name = 'INTERPOLATION_START_TYPE'; + break; + case self::INTERPOLATION_END_TYPE: + $name = 'INTERPOLATION_END_TYPE'; + break; + case self::ARROW_TYPE: + $name = 'ARROW_TYPE'; + break; + default: + throw new \LogicException(sprintf('Token of type "%s" does not exist.', $type)); + } + + return $short ? $name : 'Twig\Token::'.$name; + } + + /** + * Returns the English representation of a given type. + * + * @param int $type The type as an integer + * + * @return string The string representation + */ + public static function typeToEnglish($type) + { + switch ($type) { + case self::EOF_TYPE: + return 'end of template'; + case self::TEXT_TYPE: + return 'text'; + case self::BLOCK_START_TYPE: + return 'begin of statement block'; + case self::VAR_START_TYPE: + return 'begin of print statement'; + case self::BLOCK_END_TYPE: + return 'end of statement block'; + case self::VAR_END_TYPE: + return 'end of print statement'; + case self::NAME_TYPE: + return 'name'; + case self::NUMBER_TYPE: + return 'number'; + case self::STRING_TYPE: + return 'string'; + case self::OPERATOR_TYPE: + return 'operator'; + case self::PUNCTUATION_TYPE: + return 'punctuation'; + case self::INTERPOLATION_START_TYPE: + return 'begin of string interpolation'; + case self::INTERPOLATION_END_TYPE: + return 'end of string interpolation'; + case self::ARROW_TYPE: + return 'arrow function'; + default: + throw new \LogicException(sprintf('Token of type "%s" does not exist.', $type)); + } } } + +class_alias('Twig\Token', 'Twig_Token'); diff --git a/vendor/twig/twig/src/TokenParser/AbstractTokenParser.php b/vendor/twig/twig/src/TokenParser/AbstractTokenParser.php index 6ae78a5967beb89d922e8df2eab3435cd335dfa2..2c2f90b7f117ccf91f5a8cc3ecef28f60ec59354 100644 --- a/vendor/twig/twig/src/TokenParser/AbstractTokenParser.php +++ b/vendor/twig/twig/src/TokenParser/AbstractTokenParser.php @@ -1,11 +1,34 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\TokenParser; -class_exists('Twig_TokenParser'); +use Twig\Parser; + +/** + * Base class for all token parsers. + * + * @author Fabien Potencier <fabien@symfony.com> + */ +abstract class AbstractTokenParser implements TokenParserInterface +{ + /** + * @var Parser + */ + protected $parser; -if (\false) { - class AbstractTokenParser extends \Twig_TokenParser + public function setParser(Parser $parser) { + $this->parser = $parser; } } + +class_alias('Twig\TokenParser\AbstractTokenParser', 'Twig_TokenParser'); diff --git a/vendor/twig/twig/src/TokenParser/ApplyTokenParser.php b/vendor/twig/twig/src/TokenParser/ApplyTokenParser.php new file mode 100644 index 0000000000000000000000000000000000000000..879879a2b010fab2a43e11a863dea4a7b475d2ba --- /dev/null +++ b/vendor/twig/twig/src/TokenParser/ApplyTokenParser.php @@ -0,0 +1,58 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Twig\TokenParser; + +use Twig\Node\Expression\TempNameExpression; +use Twig\Node\Node; +use Twig\Node\PrintNode; +use Twig\Node\SetNode; +use Twig\Token; + +/** + * Applies filters on a section of a template. + * + * {% apply upper %} + * This text becomes uppercase + * {% endapplys %} + */ +final class ApplyTokenParser extends AbstractTokenParser +{ + public function parse(Token $token) + { + $lineno = $token->getLine(); + $name = $this->parser->getVarName(); + + $ref = new TempNameExpression($name, $lineno); + $ref->setAttribute('always_defined', true); + + $filter = $this->parser->getExpressionParser()->parseFilterExpressionRaw($ref, $this->getTag()); + + $this->parser->getStream()->expect(Token::BLOCK_END_TYPE); + $body = $this->parser->subparse([$this, 'decideApplyEnd'], true); + $this->parser->getStream()->expect(Token::BLOCK_END_TYPE); + + return new Node([ + new SetNode(true, $ref, $body, $lineno, $this->getTag()), + new PrintNode($filter, $lineno, $this->getTag()), + ]); + } + + public function decideApplyEnd(Token $token) + { + return $token->test('endapply'); + } + + public function getTag() + { + return 'apply'; + } +} diff --git a/vendor/twig/twig/src/TokenParser/AutoEscapeTokenParser.php b/vendor/twig/twig/src/TokenParser/AutoEscapeTokenParser.php index 68a99da5a490b4c40626882a38570055e2ee6ed9..2cd0cc69d73681e496097c33f150073d3e5c5101 100644 --- a/vendor/twig/twig/src/TokenParser/AutoEscapeTokenParser.php +++ b/vendor/twig/twig/src/TokenParser/AutoEscapeTokenParser.php @@ -1,11 +1,88 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\TokenParser; -class_exists('Twig_TokenParser_AutoEscape'); +use Twig\Error\SyntaxError; +use Twig\Node\AutoEscapeNode; +use Twig\Node\Expression\ConstantExpression; +use Twig\Token; + +/** + * Marks a section of a template to be escaped or not. + * + * {% autoescape true %} + * Everything will be automatically escaped in this block + * {% endautoescape %} + * + * {% autoescape false %} + * Everything will be outputed as is in this block + * {% endautoescape %} + * + * {% autoescape true js %} + * Everything will be automatically escaped in this block + * using the js escaping strategy + * {% endautoescape %} + * + * @final + */ +class AutoEscapeTokenParser extends AbstractTokenParser +{ + public function parse(Token $token) + { + $lineno = $token->getLine(); + $stream = $this->parser->getStream(); + + if ($stream->test(Token::BLOCK_END_TYPE)) { + $value = 'html'; + } else { + $expr = $this->parser->getExpressionParser()->parseExpression(); + if (!$expr instanceof ConstantExpression) { + throw new SyntaxError('An escaping strategy must be a string or a bool.', $stream->getCurrent()->getLine(), $stream->getSourceContext()); + } + $value = $expr->getAttribute('value'); + + $compat = true === $value || false === $value; + + if (true === $value) { + $value = 'html'; + } + + if ($compat && $stream->test(Token::NAME_TYPE)) { + @trigger_error('Using the autoescape tag with "true" or "false" before the strategy name is deprecated since version 1.21.', E_USER_DEPRECATED); + + if (false === $value) { + throw new SyntaxError('Unexpected escaping strategy as you set autoescaping to false.', $stream->getCurrent()->getLine(), $stream->getSourceContext()); + } -if (\false) { - class AutoEscapeTokenParser extends \Twig_TokenParser_AutoEscape + $value = $stream->next()->getValue(); + } + } + + $stream->expect(Token::BLOCK_END_TYPE); + $body = $this->parser->subparse([$this, 'decideBlockEnd'], true); + $stream->expect(Token::BLOCK_END_TYPE); + + return new AutoEscapeNode($value, $body, $lineno, $this->getTag()); + } + + public function decideBlockEnd(Token $token) { + return $token->test('endautoescape'); + } + + public function getTag() + { + return 'autoescape'; } } + +class_alias('Twig\TokenParser\AutoEscapeTokenParser', 'Twig_TokenParser_AutoEscape'); diff --git a/vendor/twig/twig/src/TokenParser/BlockTokenParser.php b/vendor/twig/twig/src/TokenParser/BlockTokenParser.php index 8be168302121f40be9f1548f6e9627b7c36ffd68..caf11f0b7266184549d6d27e755f7aae372ef5fa 100644 --- a/vendor/twig/twig/src/TokenParser/BlockTokenParser.php +++ b/vendor/twig/twig/src/TokenParser/BlockTokenParser.php @@ -1,11 +1,80 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * (c) Armin Ronacher + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\TokenParser; -class_exists('Twig_TokenParser_Block'); +use Twig\Error\SyntaxError; +use Twig\Node\BlockNode; +use Twig\Node\BlockReferenceNode; +use Twig\Node\Node; +use Twig\Node\PrintNode; +use Twig\Token; + +/** + * Marks a section of a template as being reusable. + * + * {% block head %} + * <link rel="stylesheet" href="style.css" /> + * <title>{% block title %}{% endblock %} - My Webpage</title> + * {% endblock %} + * + * @final + */ +class BlockTokenParser extends AbstractTokenParser +{ + public function parse(Token $token) + { + $lineno = $token->getLine(); + $stream = $this->parser->getStream(); + $name = $stream->expect(Token::NAME_TYPE)->getValue(); + if ($this->parser->hasBlock($name)) { + throw new SyntaxError(sprintf("The block '%s' has already been defined line %d.", $name, $this->parser->getBlock($name)->getTemplateLine()), $stream->getCurrent()->getLine(), $stream->getSourceContext()); + } + $this->parser->setBlock($name, $block = new BlockNode($name, new Node([]), $lineno)); + $this->parser->pushLocalScope(); + $this->parser->pushBlockStack($name); + + if ($stream->nextIf(Token::BLOCK_END_TYPE)) { + $body = $this->parser->subparse([$this, 'decideBlockEnd'], true); + if ($token = $stream->nextIf(Token::NAME_TYPE)) { + $value = $token->getValue(); + + if ($value != $name) { + throw new SyntaxError(sprintf('Expected endblock for block "%s" (but "%s" given).', $name, $value), $stream->getCurrent()->getLine(), $stream->getSourceContext()); + } + } + } else { + $body = new Node([ + new PrintNode($this->parser->getExpressionParser()->parseExpression(), $lineno), + ]); + } + $stream->expect(Token::BLOCK_END_TYPE); + + $block->setNode('body', $body); + $this->parser->popBlockStack(); + $this->parser->popLocalScope(); -if (\false) { - class BlockTokenParser extends \Twig_TokenParser_Block + return new BlockReferenceNode($name, $lineno, $this->getTag()); + } + + public function decideBlockEnd(Token $token) + { + return $token->test('endblock'); + } + + public function getTag() { + return 'block'; } } + +class_alias('Twig\TokenParser\BlockTokenParser', 'Twig_TokenParser_Block'); diff --git a/vendor/twig/twig/src/TokenParser/DeprecatedTokenParser.php b/vendor/twig/twig/src/TokenParser/DeprecatedTokenParser.php new file mode 100644 index 0000000000000000000000000000000000000000..6575cff167d21a41512210882ba87f0b19a5bf76 --- /dev/null +++ b/vendor/twig/twig/src/TokenParser/DeprecatedTokenParser.php @@ -0,0 +1,44 @@ +<?php + +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Twig\TokenParser; + +use Twig\Node\DeprecatedNode; +use Twig\Token; + +/** + * Deprecates a section of a template. + * + * {% deprecated 'The "base.twig" template is deprecated, use "layout.twig" instead.' %} + * {% extends 'layout.html.twig' %} + * + * @author Yonel Ceruto <yonelceruto@gmail.com> + * + * @final + */ +class DeprecatedTokenParser extends AbstractTokenParser +{ + public function parse(Token $token) + { + $expr = $this->parser->getExpressionParser()->parseExpression(); + + $this->parser->getStream()->expect(Token::BLOCK_END_TYPE); + + return new DeprecatedNode($expr, $token->getLine(), $this->getTag()); + } + + public function getTag() + { + return 'deprecated'; + } +} + +class_alias('Twig\TokenParser\DeprecatedTokenParser', 'Twig_TokenParser_Deprecated'); diff --git a/vendor/twig/twig/src/TokenParser/DoTokenParser.php b/vendor/twig/twig/src/TokenParser/DoTokenParser.php index a40b166d0e29cb59022c7b2035bb3a785fd05e19..e1eae10f230267258bd4c4a60544e18bfd9fd635 100644 --- a/vendor/twig/twig/src/TokenParser/DoTokenParser.php +++ b/vendor/twig/twig/src/TokenParser/DoTokenParser.php @@ -1,11 +1,39 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\TokenParser; -class_exists('Twig_TokenParser_Do'); +use Twig\Node\DoNode; +use Twig\Token; -if (\false) { - class DoTokenParser extends \Twig_TokenParser_Do +/** + * Evaluates an expression, discarding the returned value. + * + * @final + */ +class DoTokenParser extends AbstractTokenParser +{ + public function parse(Token $token) { + $expr = $this->parser->getExpressionParser()->parseExpression(); + + $this->parser->getStream()->expect(Token::BLOCK_END_TYPE); + + return new DoNode($expr, $token->getLine(), $this->getTag()); + } + + public function getTag() + { + return 'do'; } } + +class_alias('Twig\TokenParser\DoTokenParser', 'Twig_TokenParser_Do'); diff --git a/vendor/twig/twig/src/TokenParser/EmbedTokenParser.php b/vendor/twig/twig/src/TokenParser/EmbedTokenParser.php index f557db9da85796b180a4a675d2b495ad38fbd2c8..973ff2e45b1f55f1e2c1e72db0e3ca6423c51fb6 100644 --- a/vendor/twig/twig/src/TokenParser/EmbedTokenParser.php +++ b/vendor/twig/twig/src/TokenParser/EmbedTokenParser.php @@ -1,11 +1,74 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\TokenParser; -class_exists('Twig_TokenParser_Embed'); +use Twig\Node\EmbedNode; +use Twig\Node\Expression\ConstantExpression; +use Twig\Node\Expression\NameExpression; +use Twig\Token; -if (\false) { - class EmbedTokenParser extends \Twig_TokenParser_Embed +/** + * Embeds a template. + * + * @final + */ +class EmbedTokenParser extends IncludeTokenParser +{ + public function parse(Token $token) { + $stream = $this->parser->getStream(); + + $parent = $this->parser->getExpressionParser()->parseExpression(); + + list($variables, $only, $ignoreMissing) = $this->parseArguments(); + + $parentToken = $fakeParentToken = new Token(Token::STRING_TYPE, '__parent__', $token->getLine()); + if ($parent instanceof ConstantExpression) { + $parentToken = new Token(Token::STRING_TYPE, $parent->getAttribute('value'), $token->getLine()); + } elseif ($parent instanceof NameExpression) { + $parentToken = new Token(Token::NAME_TYPE, $parent->getAttribute('name'), $token->getLine()); + } + + // inject a fake parent to make the parent() function work + $stream->injectTokens([ + new Token(Token::BLOCK_START_TYPE, '', $token->getLine()), + new Token(Token::NAME_TYPE, 'extends', $token->getLine()), + $parentToken, + new Token(Token::BLOCK_END_TYPE, '', $token->getLine()), + ]); + + $module = $this->parser->parse($stream, [$this, 'decideBlockEnd'], true); + + // override the parent with the correct one + if ($fakeParentToken === $parentToken) { + $module->setNode('parent', $parent); + } + + $this->parser->embedTemplate($module); + + $stream->expect(Token::BLOCK_END_TYPE); + + return new EmbedNode($module->getTemplateName(), $module->getAttribute('index'), $variables, $only, $ignoreMissing, $token->getLine(), $this->getTag()); + } + + public function decideBlockEnd(Token $token) + { + return $token->test('endembed'); + } + + public function getTag() + { + return 'embed'; } } + +class_alias('Twig\TokenParser\EmbedTokenParser', 'Twig_TokenParser_Embed'); diff --git a/vendor/twig/twig/src/TokenParser/ExtendsTokenParser.php b/vendor/twig/twig/src/TokenParser/ExtendsTokenParser.php index cf929ab4b9f17a445528eb902779cd4deb33b10a..e66789a7bdc34ae7369d7ce27ecd385d45924470 100644 --- a/vendor/twig/twig/src/TokenParser/ExtendsTokenParser.php +++ b/vendor/twig/twig/src/TokenParser/ExtendsTokenParser.php @@ -1,11 +1,54 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * (c) Armin Ronacher + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\TokenParser; -class_exists('Twig_TokenParser_Extends'); +use Twig\Error\SyntaxError; +use Twig\Node\Node; +use Twig\Token; -if (\false) { - class ExtendsTokenParser extends \Twig_TokenParser_Extends +/** + * Extends a template by another one. + * + * {% extends "base.html" %} + * + * @final + */ +class ExtendsTokenParser extends AbstractTokenParser +{ + public function parse(Token $token) { + $stream = $this->parser->getStream(); + + if ($this->parser->peekBlockStack()) { + throw new SyntaxError('Cannot use "extend" in a block.', $token->getLine(), $stream->getSourceContext()); + } elseif (!$this->parser->isMainScope()) { + throw new SyntaxError('Cannot use "extend" in a macro.', $token->getLine(), $stream->getSourceContext()); + } + + if (null !== $this->parser->getParent()) { + throw new SyntaxError('Multiple extends tags are forbidden.', $token->getLine(), $stream->getSourceContext()); + } + $this->parser->setParent($this->parser->getExpressionParser()->parseExpression()); + + $stream->expect(Token::BLOCK_END_TYPE); + + return new Node(); + } + + public function getTag() + { + return 'extends'; } } + +class_alias('Twig\TokenParser\ExtendsTokenParser', 'Twig_TokenParser_Extends'); diff --git a/vendor/twig/twig/src/TokenParser/FilterTokenParser.php b/vendor/twig/twig/src/TokenParser/FilterTokenParser.php index de9d6ab49e5932a1ae2a9c68386e03ba5a7e72ee..dc07dcfa41ea155a32b30a8ea57ef7fc98cf28ac 100644 --- a/vendor/twig/twig/src/TokenParser/FilterTokenParser.php +++ b/vendor/twig/twig/src/TokenParser/FilterTokenParser.php @@ -1,11 +1,59 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\TokenParser; -class_exists('Twig_TokenParser_Filter'); +use Twig\Node\BlockNode; +use Twig\Node\Expression\BlockReferenceExpression; +use Twig\Node\Expression\ConstantExpression; +use Twig\Node\PrintNode; +use Twig\Token; + +/** + * Filters a section of a template by applying filters. + * + * {% filter upper %} + * This text becomes uppercase + * {% endfilter %} + * + * @final + */ +class FilterTokenParser extends AbstractTokenParser +{ + public function parse(Token $token) + { + $name = $this->parser->getVarName(); + $ref = new BlockReferenceExpression(new ConstantExpression($name, $token->getLine()), null, $token->getLine(), $this->getTag()); + + $filter = $this->parser->getExpressionParser()->parseFilterExpressionRaw($ref, $this->getTag()); + $this->parser->getStream()->expect(Token::BLOCK_END_TYPE); + + $body = $this->parser->subparse([$this, 'decideBlockEnd'], true); + $this->parser->getStream()->expect(Token::BLOCK_END_TYPE); + + $block = new BlockNode($name, $body, $token->getLine()); + $this->parser->setBlock($name, $block); -if (\false) { - class FilterTokenParser extends \Twig_TokenParser_Filter + return new PrintNode($filter, $token->getLine(), $this->getTag()); + } + + public function decideBlockEnd(Token $token) + { + return $token->test('endfilter'); + } + + public function getTag() { + return 'filter'; } } + +class_alias('Twig\TokenParser\FilterTokenParser', 'Twig_TokenParser_Filter'); diff --git a/vendor/twig/twig/src/TokenParser/FlushTokenParser.php b/vendor/twig/twig/src/TokenParser/FlushTokenParser.php index ce1302643ec8ca29d6494f76931d56c06a9ee5a2..b25524fa8da74895583cbf29cfdc6746d32ca1f3 100644 --- a/vendor/twig/twig/src/TokenParser/FlushTokenParser.php +++ b/vendor/twig/twig/src/TokenParser/FlushTokenParser.php @@ -1,11 +1,39 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\TokenParser; -class_exists('Twig_TokenParser_Flush'); +use Twig\Node\FlushNode; +use Twig\Token; + +/** + * Flushes the output to the client. + * + * @see flush() + * + * @final + */ +class FlushTokenParser extends AbstractTokenParser +{ + public function parse(Token $token) + { + $this->parser->getStream()->expect(Token::BLOCK_END_TYPE); + + return new FlushNode($token->getLine(), $this->getTag()); + } -if (\false) { - class FlushTokenParser extends \Twig_TokenParser_Flush + public function getTag() { + return 'flush'; } } + +class_alias('Twig\TokenParser\FlushTokenParser', 'Twig_TokenParser_Flush'); diff --git a/vendor/twig/twig/src/TokenParser/ForTokenParser.php b/vendor/twig/twig/src/TokenParser/ForTokenParser.php index 25ddcea3a2d8d6e711e3d7f1a780aaac0f6f1b1c..69278d98ed3fe8b4988186719985d83023450dc5 100644 --- a/vendor/twig/twig/src/TokenParser/ForTokenParser.php +++ b/vendor/twig/twig/src/TokenParser/ForTokenParser.php @@ -1,11 +1,136 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * (c) Armin Ronacher + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\TokenParser; -class_exists('Twig_TokenParser_For'); +use Twig\Error\SyntaxError; +use Twig\Node\Expression\AssignNameExpression; +use Twig\Node\Expression\ConstantExpression; +use Twig\Node\Expression\GetAttrExpression; +use Twig\Node\Expression\NameExpression; +use Twig\Node\ForNode; +use Twig\Token; +use Twig\TokenStream; + +/** + * Loops over each item of a sequence. + * + * <ul> + * {% for user in users %} + * <li>{{ user.username|e }}</li> + * {% endfor %} + * </ul> + * + * @final + */ +class ForTokenParser extends AbstractTokenParser +{ + public function parse(Token $token) + { + $lineno = $token->getLine(); + $stream = $this->parser->getStream(); + $targets = $this->parser->getExpressionParser()->parseAssignmentExpression(); + $stream->expect(Token::OPERATOR_TYPE, 'in'); + $seq = $this->parser->getExpressionParser()->parseExpression(); + + $ifexpr = null; + if ($stream->nextIf(Token::NAME_TYPE, 'if')) { + $ifexpr = $this->parser->getExpressionParser()->parseExpression(); + } + + $stream->expect(Token::BLOCK_END_TYPE); + $body = $this->parser->subparse([$this, 'decideForFork']); + if ('else' == $stream->next()->getValue()) { + $stream->expect(Token::BLOCK_END_TYPE); + $else = $this->parser->subparse([$this, 'decideForEnd'], true); + } else { + $else = null; + } + $stream->expect(Token::BLOCK_END_TYPE); + + if (\count($targets) > 1) { + $keyTarget = $targets->getNode(0); + $keyTarget = new AssignNameExpression($keyTarget->getAttribute('name'), $keyTarget->getTemplateLine()); + $valueTarget = $targets->getNode(1); + $valueTarget = new AssignNameExpression($valueTarget->getAttribute('name'), $valueTarget->getTemplateLine()); + } else { + $keyTarget = new AssignNameExpression('_key', $lineno); + $valueTarget = $targets->getNode(0); + $valueTarget = new AssignNameExpression($valueTarget->getAttribute('name'), $valueTarget->getTemplateLine()); + } + + if ($ifexpr) { + $this->checkLoopUsageCondition($stream, $ifexpr); + $this->checkLoopUsageBody($stream, $body); + } -if (\false) { - class ForTokenParser extends \Twig_TokenParser_For + return new ForNode($keyTarget, $valueTarget, $seq, $ifexpr, $body, $else, $lineno, $this->getTag()); + } + + public function decideForFork(Token $token) { + return $token->test(['else', 'endfor']); + } + + public function decideForEnd(Token $token) + { + return $token->test('endfor'); + } + + // the loop variable cannot be used in the condition + protected function checkLoopUsageCondition(TokenStream $stream, \Twig_NodeInterface $node) + { + if ($node instanceof GetAttrExpression && $node->getNode('node') instanceof NameExpression && 'loop' == $node->getNode('node')->getAttribute('name')) { + throw new SyntaxError('The "loop" variable cannot be used in a looping condition.', $node->getTemplateLine(), $stream->getSourceContext()); + } + + foreach ($node as $n) { + if (!$n) { + continue; + } + + $this->checkLoopUsageCondition($stream, $n); + } + } + + // check usage of non-defined loop-items + // it does not catch all problems (for instance when a for is included into another or when the variable is used in an include) + protected function checkLoopUsageBody(TokenStream $stream, \Twig_NodeInterface $node) + { + if ($node instanceof GetAttrExpression && $node->getNode('node') instanceof NameExpression && 'loop' == $node->getNode('node')->getAttribute('name')) { + $attribute = $node->getNode('attribute'); + if ($attribute instanceof ConstantExpression && \in_array($attribute->getAttribute('value'), ['length', 'revindex0', 'revindex', 'last'])) { + throw new SyntaxError(sprintf('The "loop.%s" variable is not defined when looping with a condition.', $attribute->getAttribute('value')), $node->getTemplateLine(), $stream->getSourceContext()); + } + } + + // should check for parent.loop.XXX usage + if ($node instanceof ForNode) { + return; + } + + foreach ($node as $n) { + if (!$n) { + continue; + } + + $this->checkLoopUsageBody($stream, $n); + } + } + + public function getTag() + { + return 'for'; } } + +class_alias('Twig\TokenParser\ForTokenParser', 'Twig_TokenParser_For'); diff --git a/vendor/twig/twig/src/TokenParser/FromTokenParser.php b/vendor/twig/twig/src/TokenParser/FromTokenParser.php index 1e5a4bc0bc0dfe2310696d992de60583433a780b..4cce650d6177bc7438e83c5e58b78e7bb16ff544 100644 --- a/vendor/twig/twig/src/TokenParser/FromTokenParser.php +++ b/vendor/twig/twig/src/TokenParser/FromTokenParser.php @@ -1,11 +1,72 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\TokenParser; -class_exists('Twig_TokenParser_From'); +use Twig\Error\SyntaxError; +use Twig\Node\Expression\AssignNameExpression; +use Twig\Node\ImportNode; +use Twig\Token; + +/** + * Imports macros. + * + * {% from 'forms.html' import forms %} + * + * @final + */ +class FromTokenParser extends AbstractTokenParser +{ + public function parse(Token $token) + { + $macro = $this->parser->getExpressionParser()->parseExpression(); + $stream = $this->parser->getStream(); + $stream->expect(Token::NAME_TYPE, 'import'); + + $targets = []; + do { + $name = $stream->expect(Token::NAME_TYPE)->getValue(); + + $alias = $name; + if ($stream->nextIf('as')) { + $alias = $stream->expect(Token::NAME_TYPE)->getValue(); + } + + $targets[$name] = $alias; + + if (!$stream->nextIf(Token::PUNCTUATION_TYPE, ',')) { + break; + } + } while (true); -if (\false) { - class FromTokenParser extends \Twig_TokenParser_From + $stream->expect(Token::BLOCK_END_TYPE); + + $var = new AssignNameExpression($this->parser->getVarName(), $token->getLine()); + $node = new ImportNode($macro, $var, $token->getLine(), $this->getTag()); + + foreach ($targets as $name => $alias) { + if ($this->parser->isReservedMacroName($name)) { + throw new SyntaxError(sprintf('"%s" cannot be an imported macro as it is a reserved keyword.', $name), $token->getLine(), $stream->getSourceContext()); + } + + $this->parser->addImportedSymbol('function', $alias, 'get'.$name, $var); + } + + return $node; + } + + public function getTag() { + return 'from'; } } + +class_alias('Twig\TokenParser\FromTokenParser', 'Twig_TokenParser_From'); diff --git a/vendor/twig/twig/src/TokenParser/IfTokenParser.php b/vendor/twig/twig/src/TokenParser/IfTokenParser.php index 1852cf1e69f8419efab74b5379125c1ecc51c10e..2631a20cec588740580092c4a9e7f2e2f0d88d24 100644 --- a/vendor/twig/twig/src/TokenParser/IfTokenParser.php +++ b/vendor/twig/twig/src/TokenParser/IfTokenParser.php @@ -1,11 +1,91 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * (c) Armin Ronacher + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\TokenParser; -class_exists('Twig_TokenParser_If'); +use Twig\Error\SyntaxError; +use Twig\Node\IfNode; +use Twig\Node\Node; +use Twig\Token; -if (\false) { - class IfTokenParser extends \Twig_TokenParser_If +/** + * Tests a condition. + * + * {% if users %} + * <ul> + * {% for user in users %} + * <li>{{ user.username|e }}</li> + * {% endfor %} + * </ul> + * {% endif %} + * + * @final + */ +class IfTokenParser extends AbstractTokenParser +{ + public function parse(Token $token) { + $lineno = $token->getLine(); + $expr = $this->parser->getExpressionParser()->parseExpression(); + $stream = $this->parser->getStream(); + $stream->expect(Token::BLOCK_END_TYPE); + $body = $this->parser->subparse([$this, 'decideIfFork']); + $tests = [$expr, $body]; + $else = null; + + $end = false; + while (!$end) { + switch ($stream->next()->getValue()) { + case 'else': + $stream->expect(Token::BLOCK_END_TYPE); + $else = $this->parser->subparse([$this, 'decideIfEnd']); + break; + + case 'elseif': + $expr = $this->parser->getExpressionParser()->parseExpression(); + $stream->expect(Token::BLOCK_END_TYPE); + $body = $this->parser->subparse([$this, 'decideIfFork']); + $tests[] = $expr; + $tests[] = $body; + break; + + case 'endif': + $end = true; + break; + + default: + throw new SyntaxError(sprintf('Unexpected end of template. Twig was looking for the following tags "else", "elseif", or "endif" to close the "if" block started at line %d).', $lineno), $stream->getCurrent()->getLine(), $stream->getSourceContext()); + } + } + + $stream->expect(Token::BLOCK_END_TYPE); + + return new IfNode(new Node($tests), $else, $lineno, $this->getTag()); + } + + public function decideIfFork(Token $token) + { + return $token->test(['elseif', 'else', 'endif']); + } + + public function decideIfEnd(Token $token) + { + return $token->test(['endif']); + } + + public function getTag() + { + return 'if'; } } + +class_alias('Twig\TokenParser\IfTokenParser', 'Twig_TokenParser_If'); diff --git a/vendor/twig/twig/src/TokenParser/ImportTokenParser.php b/vendor/twig/twig/src/TokenParser/ImportTokenParser.php index 1a42d0128cc1a27ecd2881cde787d13e865b0d2a..88395b924892a87b9babef9a5165c9cd06a16fb7 100644 --- a/vendor/twig/twig/src/TokenParser/ImportTokenParser.php +++ b/vendor/twig/twig/src/TokenParser/ImportTokenParser.php @@ -1,11 +1,45 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\TokenParser; -class_exists('Twig_TokenParser_Import'); +use Twig\Node\Expression\AssignNameExpression; +use Twig\Node\ImportNode; +use Twig\Token; -if (\false) { - class ImportTokenParser extends \Twig_TokenParser_Import +/** + * Imports macros. + * + * {% import 'forms.html' as forms %} + * + * @final + */ +class ImportTokenParser extends AbstractTokenParser +{ + public function parse(Token $token) { + $macro = $this->parser->getExpressionParser()->parseExpression(); + $this->parser->getStream()->expect(Token::NAME_TYPE, 'as'); + $var = new AssignNameExpression($this->parser->getStream()->expect(Token::NAME_TYPE)->getValue(), $token->getLine()); + $this->parser->getStream()->expect(Token::BLOCK_END_TYPE); + + $this->parser->addImportedSymbol('template', $var->getAttribute('name')); + + return new ImportNode($macro, $var, $token->getLine(), $this->getTag()); + } + + public function getTag() + { + return 'import'; } } + +class_alias('Twig\TokenParser\ImportTokenParser', 'Twig_TokenParser_Import'); diff --git a/vendor/twig/twig/src/TokenParser/IncludeTokenParser.php b/vendor/twig/twig/src/TokenParser/IncludeTokenParser.php index 7f8c061fd70ef7a5c28551df919cd79a133e2cb6..57aa4cf41afe9273b5a4e76768678daddf6f259c 100644 --- a/vendor/twig/twig/src/TokenParser/IncludeTokenParser.php +++ b/vendor/twig/twig/src/TokenParser/IncludeTokenParser.php @@ -1,11 +1,68 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * (c) Armin Ronacher + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\TokenParser; -class_exists('Twig_TokenParser_Include'); +use Twig\Node\IncludeNode; +use Twig\Token; + +/** + * Includes a template. + * + * {% include 'header.html' %} + * Body + * {% include 'footer.html' %} + */ +class IncludeTokenParser extends AbstractTokenParser +{ + public function parse(Token $token) + { + $expr = $this->parser->getExpressionParser()->parseExpression(); + + list($variables, $only, $ignoreMissing) = $this->parseArguments(); + + return new IncludeNode($expr, $variables, $only, $ignoreMissing, $token->getLine(), $this->getTag()); + } + + protected function parseArguments() + { + $stream = $this->parser->getStream(); + + $ignoreMissing = false; + if ($stream->nextIf(Token::NAME_TYPE, 'ignore')) { + $stream->expect(Token::NAME_TYPE, 'missing'); + + $ignoreMissing = true; + } + + $variables = null; + if ($stream->nextIf(Token::NAME_TYPE, 'with')) { + $variables = $this->parser->getExpressionParser()->parseExpression(); + } + + $only = false; + if ($stream->nextIf(Token::NAME_TYPE, 'only')) { + $only = true; + } -if (\false) { - class IncludeTokenParser extends \Twig_TokenParser_Include + $stream->expect(Token::BLOCK_END_TYPE); + + return [$variables, $only, $ignoreMissing]; + } + + public function getTag() { + return 'include'; } } + +class_alias('Twig\TokenParser\IncludeTokenParser', 'Twig_TokenParser_Include'); diff --git a/vendor/twig/twig/src/TokenParser/MacroTokenParser.php b/vendor/twig/twig/src/TokenParser/MacroTokenParser.php index 152fb2672db4e73e027a0fdadea1d3202c907233..a0d66e7bea802c42a053f10ddd0d956f151e94a2 100644 --- a/vendor/twig/twig/src/TokenParser/MacroTokenParser.php +++ b/vendor/twig/twig/src/TokenParser/MacroTokenParser.php @@ -1,11 +1,68 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\TokenParser; -class_exists('Twig_TokenParser_Macro'); +use Twig\Error\SyntaxError; +use Twig\Node\BodyNode; +use Twig\Node\MacroNode; +use Twig\Node\Node; +use Twig\Token; -if (\false) { - class MacroTokenParser extends \Twig_TokenParser_Macro +/** + * Defines a macro. + * + * {% macro input(name, value, type, size) %} + * <input type="{{ type|default('text') }}" name="{{ name }}" value="{{ value|e }}" size="{{ size|default(20) }}" /> + * {% endmacro %} + * + * @final + */ +class MacroTokenParser extends AbstractTokenParser +{ + public function parse(Token $token) { + $lineno = $token->getLine(); + $stream = $this->parser->getStream(); + $name = $stream->expect(Token::NAME_TYPE)->getValue(); + + $arguments = $this->parser->getExpressionParser()->parseArguments(true, true); + + $stream->expect(Token::BLOCK_END_TYPE); + $this->parser->pushLocalScope(); + $body = $this->parser->subparse([$this, 'decideBlockEnd'], true); + if ($token = $stream->nextIf(Token::NAME_TYPE)) { + $value = $token->getValue(); + + if ($value != $name) { + throw new SyntaxError(sprintf('Expected endmacro for macro "%s" (but "%s" given).', $name, $value), $stream->getCurrent()->getLine(), $stream->getSourceContext()); + } + } + $this->parser->popLocalScope(); + $stream->expect(Token::BLOCK_END_TYPE); + + $this->parser->setMacro($name, new MacroNode($name, new BodyNode([$body]), $arguments, $lineno, $this->getTag())); + + return new Node(); + } + + public function decideBlockEnd(Token $token) + { + return $token->test('endmacro'); + } + + public function getTag() + { + return 'macro'; } } + +class_alias('Twig\TokenParser\MacroTokenParser', 'Twig_TokenParser_Macro'); diff --git a/vendor/twig/twig/src/TokenParser/SandboxTokenParser.php b/vendor/twig/twig/src/TokenParser/SandboxTokenParser.php index e54c315a1866fffad26d306dbf740521ad51023d..0f3ad9e3e6c70aef58348322c36034fe9ef27df8 100644 --- a/vendor/twig/twig/src/TokenParser/SandboxTokenParser.php +++ b/vendor/twig/twig/src/TokenParser/SandboxTokenParser.php @@ -1,11 +1,67 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\TokenParser; -class_exists('Twig_TokenParser_Sandbox'); +use Twig\Error\SyntaxError; +use Twig\Node\IncludeNode; +use Twig\Node\SandboxNode; +use Twig\Node\TextNode; +use Twig\Token; -if (\false) { - class SandboxTokenParser extends \Twig_TokenParser_Sandbox +/** + * Marks a section of a template as untrusted code that must be evaluated in the sandbox mode. + * + * {% sandbox %} + * {% include 'user.html' %} + * {% endsandbox %} + * + * @see https://twig.symfony.com/doc/api.html#sandbox-extension for details + * + * @final + */ +class SandboxTokenParser extends AbstractTokenParser +{ + public function parse(Token $token) { + $stream = $this->parser->getStream(); + $stream->expect(Token::BLOCK_END_TYPE); + $body = $this->parser->subparse([$this, 'decideBlockEnd'], true); + $stream->expect(Token::BLOCK_END_TYPE); + + // in a sandbox tag, only include tags are allowed + if (!$body instanceof IncludeNode) { + foreach ($body as $node) { + if ($node instanceof TextNode && ctype_space($node->getAttribute('data'))) { + continue; + } + + if (!$node instanceof IncludeNode) { + throw new SyntaxError('Only "include" tags are allowed within a "sandbox" section.', $node->getTemplateLine(), $stream->getSourceContext()); + } + } + } + + return new SandboxNode($body, $token->getLine(), $this->getTag()); + } + + public function decideBlockEnd(Token $token) + { + return $token->test('endsandbox'); + } + + public function getTag() + { + return 'sandbox'; } } + +class_alias('Twig\TokenParser\SandboxTokenParser', 'Twig_TokenParser_Sandbox'); diff --git a/vendor/twig/twig/src/TokenParser/SetTokenParser.php b/vendor/twig/twig/src/TokenParser/SetTokenParser.php index a9d04d7dc4a726d01c07522496bcee7c6de507e0..eebebc698513f9031fa8b808ed0dc974975269fe 100644 --- a/vendor/twig/twig/src/TokenParser/SetTokenParser.php +++ b/vendor/twig/twig/src/TokenParser/SetTokenParser.php @@ -1,11 +1,74 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\TokenParser; -class_exists('Twig_TokenParser_Set'); +use Twig\Error\SyntaxError; +use Twig\Node\SetNode; +use Twig\Token; -if (\false) { - class SetTokenParser extends \Twig_TokenParser_Set +/** + * Defines a variable. + * + * {% set foo = 'foo' %} + * {% set foo = [1, 2] %} + * {% set foo = {'foo': 'bar'} %} + * {% set foo = 'foo' ~ 'bar' %} + * {% set foo, bar = 'foo', 'bar' %} + * {% set foo %}Some content{% endset %} + * + * @final + */ +class SetTokenParser extends AbstractTokenParser +{ + public function parse(Token $token) { + $lineno = $token->getLine(); + $stream = $this->parser->getStream(); + $names = $this->parser->getExpressionParser()->parseAssignmentExpression(); + + $capture = false; + if ($stream->nextIf(Token::OPERATOR_TYPE, '=')) { + $values = $this->parser->getExpressionParser()->parseMultitargetExpression(); + + $stream->expect(Token::BLOCK_END_TYPE); + + if (\count($names) !== \count($values)) { + throw new SyntaxError('When using set, you must have the same number of variables and assignments.', $stream->getCurrent()->getLine(), $stream->getSourceContext()); + } + } else { + $capture = true; + + if (\count($names) > 1) { + throw new SyntaxError('When using set with a block, you cannot have a multi-target.', $stream->getCurrent()->getLine(), $stream->getSourceContext()); + } + + $stream->expect(Token::BLOCK_END_TYPE); + + $values = $this->parser->subparse([$this, 'decideBlockEnd'], true); + $stream->expect(Token::BLOCK_END_TYPE); + } + + return new SetNode($capture, $names, $values, $lineno, $this->getTag()); + } + + public function decideBlockEnd(Token $token) + { + return $token->test('endset'); + } + + public function getTag() + { + return 'set'; } } + +class_alias('Twig\TokenParser\SetTokenParser', 'Twig_TokenParser_Set'); diff --git a/vendor/twig/twig/src/TokenParser/SpacelessTokenParser.php b/vendor/twig/twig/src/TokenParser/SpacelessTokenParser.php index 5e7e3dd93a3d046bff2189d9321191109f7939ac..5b5656bc64fe54a5798207655a8df75a806d17c9 100644 --- a/vendor/twig/twig/src/TokenParser/SpacelessTokenParser.php +++ b/vendor/twig/twig/src/TokenParser/SpacelessTokenParser.php @@ -1,11 +1,53 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\TokenParser; -class_exists('Twig_TokenParser_Spaceless'); +use Twig\Node\SpacelessNode; +use Twig\Token; + +/** + * Remove whitespaces between HTML tags. + * + * {% spaceless %} + * <div> + * <strong>foo</strong> + * </div> + * {% endspaceless %} + * {# output will be <div><strong>foo</strong></div> #} + * + * @final + */ +class SpacelessTokenParser extends AbstractTokenParser +{ + public function parse(Token $token) + { + $lineno = $token->getLine(); + + $this->parser->getStream()->expect(Token::BLOCK_END_TYPE); + $body = $this->parser->subparse([$this, 'decideSpacelessEnd'], true); + $this->parser->getStream()->expect(Token::BLOCK_END_TYPE); + + return new SpacelessNode($body, $lineno, $this->getTag()); + } -if (\false) { - class SpacelessTokenParser extends \Twig_TokenParser_Spaceless + public function decideSpacelessEnd(Token $token) { + return $token->test('endspaceless'); + } + + public function getTag() + { + return 'spaceless'; } } + +class_alias('Twig\TokenParser\SpacelessTokenParser', 'Twig_TokenParser_Spaceless'); diff --git a/vendor/twig/twig/src/TokenParser/TokenParserInterface.php b/vendor/twig/twig/src/TokenParser/TokenParserInterface.php index 08ab0c92622c5330323723537a11545020a0da08..4b603b213ff826d3bbd792d5901acacc0ab989be 100644 --- a/vendor/twig/twig/src/TokenParser/TokenParserInterface.php +++ b/vendor/twig/twig/src/TokenParser/TokenParserInterface.php @@ -1,11 +1,51 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\TokenParser; -class_exists('Twig_TokenParserInterface'); +use Twig\Error\SyntaxError; +use Twig\Parser; +use Twig\Token; + +/** + * Interface implemented by token parsers. + * + * @author Fabien Potencier <fabien@symfony.com> + */ +interface TokenParserInterface +{ + /** + * Sets the parser associated with this token parser. + */ + public function setParser(Parser $parser); + + /** + * Parses a token and returns a node. + * + * @return \Twig_NodeInterface + * + * @throws SyntaxError + */ + public function parse(Token $token); -if (\false) { - interface TokenParserInterface extends \Twig_TokenParserInterface - { - } + /** + * Gets the tag name associated with this token parser. + * + * @return string The tag name + */ + public function getTag(); } + +class_alias('Twig\TokenParser\TokenParserInterface', 'Twig_TokenParserInterface'); + +// Ensure that the aliased name is loaded to keep BC for classes implementing the typehint with the old aliased name. +class_exists('Twig\Token'); +class_exists('Twig\Parser'); diff --git a/vendor/twig/twig/src/TokenParser/UseTokenParser.php b/vendor/twig/twig/src/TokenParser/UseTokenParser.php index db58a6050cbd7530fa60600598382ac9f664b5af..d2e39aabeeacd7530bb210e950ebed2c4be97f8c 100644 --- a/vendor/twig/twig/src/TokenParser/UseTokenParser.php +++ b/vendor/twig/twig/src/TokenParser/UseTokenParser.php @@ -1,11 +1,75 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\TokenParser; -class_exists('Twig_TokenParser_Use'); +use Twig\Error\SyntaxError; +use Twig\Node\Expression\ConstantExpression; +use Twig\Node\Node; +use Twig\Token; -if (\false) { - class UseTokenParser extends \Twig_TokenParser_Use +/** + * Imports blocks defined in another template into the current template. + * + * {% extends "base.html" %} + * + * {% use "blocks.html" %} + * + * {% block title %}{% endblock %} + * {% block content %}{% endblock %} + * + * @see https://twig.symfony.com/doc/templates.html#horizontal-reuse for details. + * + * @final + */ +class UseTokenParser extends AbstractTokenParser +{ + public function parse(Token $token) { + $template = $this->parser->getExpressionParser()->parseExpression(); + $stream = $this->parser->getStream(); + + if (!$template instanceof ConstantExpression) { + throw new SyntaxError('The template references in a "use" statement must be a string.', $stream->getCurrent()->getLine(), $stream->getSourceContext()); + } + + $targets = []; + if ($stream->nextIf('with')) { + do { + $name = $stream->expect(Token::NAME_TYPE)->getValue(); + + $alias = $name; + if ($stream->nextIf('as')) { + $alias = $stream->expect(Token::NAME_TYPE)->getValue(); + } + + $targets[$name] = new ConstantExpression($alias, -1); + + if (!$stream->nextIf(Token::PUNCTUATION_TYPE, ',')) { + break; + } + } while (true); + } + + $stream->expect(Token::BLOCK_END_TYPE); + + $this->parser->addTrait(new Node(['template' => $template, 'targets' => new Node($targets)])); + + return new Node(); + } + + public function getTag() + { + return 'use'; } } + +class_alias('Twig\TokenParser\UseTokenParser', 'Twig_TokenParser_Use'); diff --git a/vendor/twig/twig/src/TokenParser/WithTokenParser.php b/vendor/twig/twig/src/TokenParser/WithTokenParser.php index 518d6f59afbb00dea3b2d44e366a22f5f7565e75..411e2b4a139d846b82b4fb3b521f218ebea121ad 100644 --- a/vendor/twig/twig/src/TokenParser/WithTokenParser.php +++ b/vendor/twig/twig/src/TokenParser/WithTokenParser.php @@ -1,11 +1,57 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\TokenParser; -class_exists('Twig_TokenParser_With'); +use Twig\Node\WithNode; +use Twig\Token; -if (\false) { - class WithTokenParser extends \Twig_TokenParser_With +/** + * Creates a nested scope. + * + * @author Fabien Potencier <fabien@symfony.com> + * + * @final + */ +class WithTokenParser extends AbstractTokenParser +{ + public function parse(Token $token) { + $stream = $this->parser->getStream(); + + $variables = null; + $only = false; + if (!$stream->test(Token::BLOCK_END_TYPE)) { + $variables = $this->parser->getExpressionParser()->parseExpression(); + $only = $stream->nextIf(Token::NAME_TYPE, 'only'); + } + + $stream->expect(Token::BLOCK_END_TYPE); + + $body = $this->parser->subparse([$this, 'decideWithEnd'], true); + + $stream->expect(Token::BLOCK_END_TYPE); + + return new WithNode($body, $variables, $only, $token->getLine(), $this->getTag()); + } + + public function decideWithEnd(Token $token) + { + return $token->test('endwith'); + } + + public function getTag() + { + return 'with'; } } + +class_alias('Twig\TokenParser\WithTokenParser', 'Twig_TokenParser_With'); diff --git a/vendor/twig/twig/src/TokenStream.php b/vendor/twig/twig/src/TokenStream.php index 2dcf38ea140d21053ddb339cd5c54dd2937b6e72..4597816959b7204d862b6f1129685581f8685b96 100644 --- a/vendor/twig/twig/src/TokenStream.php +++ b/vendor/twig/twig/src/TokenStream.php @@ -1,11 +1,201 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * (c) Armin Ronacher + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig; -class_exists('Twig_TokenStream'); +use Twig\Error\SyntaxError; + +/** + * Represents a token stream. + * + * @final + * + * @author Fabien Potencier <fabien@symfony.com> + */ +class TokenStream +{ + protected $tokens; + protected $current = 0; + protected $filename; + + private $source; + + /** + * @param array $tokens An array of tokens + * @param string|null $name The name of the template which tokens are associated with + * @param string|null $source The source code associated with the tokens + */ + public function __construct(array $tokens, $name = null, $source = null) + { + if (!$name instanceof Source) { + if (null !== $name || null !== $source) { + @trigger_error(sprintf('Passing a string as the $name argument of %s() is deprecated since version 1.27. Pass a \Twig\Source instance instead.', __METHOD__), E_USER_DEPRECATED); + } + $this->source = new Source($source, $name); + } else { + $this->source = $name; + } + + $this->tokens = $tokens; + + // deprecated, not used anymore, to be removed in 2.0 + $this->filename = $this->source->getName(); + } + + public function __toString() + { + return implode("\n", $this->tokens); + } + + public function injectTokens(array $tokens) + { + $this->tokens = array_merge(\array_slice($this->tokens, 0, $this->current), $tokens, \array_slice($this->tokens, $this->current)); + } + + /** + * Sets the pointer to the next token and returns the old one. + * + * @return Token + */ + public function next() + { + if (!isset($this->tokens[++$this->current])) { + throw new SyntaxError('Unexpected end of template.', $this->tokens[$this->current - 1]->getLine(), $this->source); + } + + return $this->tokens[$this->current - 1]; + } -if (\false) { - class TokenStream extends \Twig_TokenStream + /** + * Tests a token, sets the pointer to the next one and returns it or throws a syntax error. + * + * @return Token|null The next token if the condition is true, null otherwise + */ + public function nextIf($primary, $secondary = null) { + if ($this->tokens[$this->current]->test($primary, $secondary)) { + return $this->next(); + } + } + + /** + * Tests a token and returns it or throws a syntax error. + * + * @return Token + */ + public function expect($type, $value = null, $message = null) + { + $token = $this->tokens[$this->current]; + if (!$token->test($type, $value)) { + $line = $token->getLine(); + throw new SyntaxError(sprintf('%sUnexpected token "%s"%s ("%s" expected%s).', + $message ? $message.'. ' : '', + Token::typeToEnglish($token->getType()), + $token->getValue() ? sprintf(' of value "%s"', $token->getValue()) : '', + Token::typeToEnglish($type), $value ? sprintf(' with value "%s"', $value) : ''), + $line, + $this->source + ); + } + $this->next(); + + return $token; + } + + /** + * Looks at the next token. + * + * @param int $number + * + * @return Token + */ + public function look($number = 1) + { + if (!isset($this->tokens[$this->current + $number])) { + throw new SyntaxError('Unexpected end of template.', $this->tokens[$this->current + $number - 1]->getLine(), $this->source); + } + + return $this->tokens[$this->current + $number]; + } + + /** + * Tests the current token. + * + * @return bool + */ + public function test($primary, $secondary = null) + { + return $this->tokens[$this->current]->test($primary, $secondary); + } + + /** + * Checks if end of stream was reached. + * + * @return bool + */ + public function isEOF() + { + return Token::EOF_TYPE === $this->tokens[$this->current]->getType(); + } + + /** + * @return Token + */ + public function getCurrent() + { + return $this->tokens[$this->current]; + } + + /** + * Gets the name associated with this stream (null if not defined). + * + * @return string|null + * + * @deprecated since 1.27 (to be removed in 2.0) + */ + public function getFilename() + { + @trigger_error(sprintf('The %s() method is deprecated since version 1.27 and will be removed in 2.0. Use getSourceContext() instead.', __METHOD__), E_USER_DEPRECATED); + + return $this->source->getName(); + } + + /** + * Gets the source code associated with this stream. + * + * @return string + * + * @internal Don't use this as it might be empty depending on the environment configuration + * + * @deprecated since 1.27 (to be removed in 2.0) + */ + public function getSource() + { + @trigger_error(sprintf('The %s() method is deprecated since version 1.27 and will be removed in 2.0. Use getSourceContext() instead.', __METHOD__), E_USER_DEPRECATED); + + return $this->source->getCode(); + } + + /** + * Gets the source associated with this stream. + * + * @return Source + * + * @internal + */ + public function getSourceContext() + { + return $this->source; } } + +class_alias('Twig\TokenStream', 'Twig_TokenStream'); diff --git a/vendor/twig/twig/src/TwigFilter.php b/vendor/twig/twig/src/TwigFilter.php index 8207048f0286f271a9772339e85d8fe85def613f..089a6d1b8895e8daf80b7eed12152778c8577473 100644 --- a/vendor/twig/twig/src/TwigFilter.php +++ b/vendor/twig/twig/src/TwigFilter.php @@ -1,11 +1,128 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig; -class_exists('Twig_SimpleFilter'); +use Twig\Node\Node; + +/** + * Represents a template filter. + * + * @final + * + * @author Fabien Potencier <fabien@symfony.com> + */ +class TwigFilter +{ + protected $name; + protected $callable; + protected $options; + protected $arguments = []; + + public function __construct($name, $callable, array $options = []) + { + $this->name = $name; + $this->callable = $callable; + $this->options = array_merge([ + 'needs_environment' => false, + 'needs_context' => false, + 'is_variadic' => false, + 'is_safe' => null, + 'is_safe_callback' => null, + 'pre_escape' => null, + 'preserves_safety' => null, + 'node_class' => '\Twig\Node\Expression\FilterExpression', + 'deprecated' => false, + 'alternative' => null, + ], $options); + } + + public function getName() + { + return $this->name; + } + + public function getCallable() + { + return $this->callable; + } + + public function getNodeClass() + { + return $this->options['node_class']; + } + + public function setArguments($arguments) + { + $this->arguments = $arguments; + } + + public function getArguments() + { + return $this->arguments; + } + + public function needsEnvironment() + { + return $this->options['needs_environment']; + } -if (\false) { - class TwigFilter extends \Twig_SimpleFilter + public function needsContext() { + return $this->options['needs_context']; + } + + public function getSafe(Node $filterArgs) + { + if (null !== $this->options['is_safe']) { + return $this->options['is_safe']; + } + + if (null !== $this->options['is_safe_callback']) { + return \call_user_func($this->options['is_safe_callback'], $filterArgs); + } + } + + public function getPreservesSafety() + { + return $this->options['preserves_safety']; + } + + public function getPreEscape() + { + return $this->options['pre_escape']; + } + + public function isVariadic() + { + return $this->options['is_variadic']; + } + + public function isDeprecated() + { + return (bool) $this->options['deprecated']; + } + + public function getDeprecatedVersion() + { + return $this->options['deprecated']; + } + + public function getAlternative() + { + return $this->options['alternative']; } } + +class_alias('Twig\TwigFilter', 'Twig_SimpleFilter'); + +// Ensure that the aliased name is loaded to keep BC for classes implementing the typehint with the old aliased name. +class_exists('Twig\Node\Node'); diff --git a/vendor/twig/twig/src/TwigFunction.php b/vendor/twig/twig/src/TwigFunction.php index d8b8605f1a873f352bcf7affa58644ed9c4dd4aa..374f07071e6738b6cf01e3313deab6865f23bdb3 100644 --- a/vendor/twig/twig/src/TwigFunction.php +++ b/vendor/twig/twig/src/TwigFunction.php @@ -1,11 +1,118 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig; -class_exists('Twig_SimpleFunction'); +use Twig\Node\Node; + +/** + * Represents a template function. + * + * @final + * + * @author Fabien Potencier <fabien@symfony.com> + */ +class TwigFunction +{ + protected $name; + protected $callable; + protected $options; + protected $arguments = []; + + public function __construct($name, $callable, array $options = []) + { + $this->name = $name; + $this->callable = $callable; + $this->options = array_merge([ + 'needs_environment' => false, + 'needs_context' => false, + 'is_variadic' => false, + 'is_safe' => null, + 'is_safe_callback' => null, + 'node_class' => '\Twig\Node\Expression\FunctionExpression', + 'deprecated' => false, + 'alternative' => null, + ], $options); + } + + public function getName() + { + return $this->name; + } + + public function getCallable() + { + return $this->callable; + } + + public function getNodeClass() + { + return $this->options['node_class']; + } + + public function setArguments($arguments) + { + $this->arguments = $arguments; + } + + public function getArguments() + { + return $this->arguments; + } + + public function needsEnvironment() + { + return $this->options['needs_environment']; + } -if (\false) { - class TwigFunction extends \Twig_SimpleFunction + public function needsContext() { + return $this->options['needs_context']; + } + + public function getSafe(Node $functionArgs) + { + if (null !== $this->options['is_safe']) { + return $this->options['is_safe']; + } + + if (null !== $this->options['is_safe_callback']) { + return \call_user_func($this->options['is_safe_callback'], $functionArgs); + } + + return []; + } + + public function isVariadic() + { + return $this->options['is_variadic']; + } + + public function isDeprecated() + { + return (bool) $this->options['deprecated']; + } + + public function getDeprecatedVersion() + { + return $this->options['deprecated']; + } + + public function getAlternative() + { + return $this->options['alternative']; } } + +class_alias('Twig\TwigFunction', 'Twig_SimpleFunction'); + +// Ensure that the aliased name is loaded to keep BC for classes implementing the typehint with the old aliased name. +class_exists('Twig\Node\Node'); diff --git a/vendor/twig/twig/src/TwigTest.php b/vendor/twig/twig/src/TwigTest.php index 11248827e7b1e066beb0924028d86d8692d6db78..5054965fe9ae66fbc9fd73fdebc523d7451043db 100644 --- a/vendor/twig/twig/src/TwigTest.php +++ b/vendor/twig/twig/src/TwigTest.php @@ -1,11 +1,87 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig; -class_exists('Twig_SimpleTest'); +/** + * Represents a template test. + * + * @final + * + * @author Fabien Potencier <fabien@symfony.com> + */ +class TwigTest +{ + protected $name; + protected $callable; + protected $options; + + private $arguments = []; + + public function __construct($name, $callable, array $options = []) + { + $this->name = $name; + $this->callable = $callable; + $this->options = array_merge([ + 'is_variadic' => false, + 'node_class' => '\Twig\Node\Expression\TestExpression', + 'deprecated' => false, + 'alternative' => null, + ], $options); + } + + public function getName() + { + return $this->name; + } + + public function getCallable() + { + return $this->callable; + } + + public function getNodeClass() + { + return $this->options['node_class']; + } + + public function isVariadic() + { + return $this->options['is_variadic']; + } + + public function isDeprecated() + { + return (bool) $this->options['deprecated']; + } + + public function getDeprecatedVersion() + { + return $this->options['deprecated']; + } -if (\false) { - class TwigTest extends \Twig_SimpleTest + public function getAlternative() { + return $this->options['alternative']; + } + + public function setArguments($arguments) + { + $this->arguments = $arguments; + } + + public function getArguments() + { + return $this->arguments; } } + +class_alias('Twig\TwigTest', 'Twig_SimpleTest'); diff --git a/vendor/twig/twig/src/Util/DeprecationCollector.php b/vendor/twig/twig/src/Util/DeprecationCollector.php index 002713f187644b7f04d88741baf5946b35d9b244..09917e927c1ab735793dedc53b3b46a2081157ee 100644 --- a/vendor/twig/twig/src/Util/DeprecationCollector.php +++ b/vendor/twig/twig/src/Util/DeprecationCollector.php @@ -1,11 +1,92 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\Util; -class_exists('Twig_Util_DeprecationCollector'); +use Twig\Environment; +use Twig\Error\SyntaxError; +use Twig\Source; + +/** + * @author Fabien Potencier <fabien@symfony.com> + * + * @final + */ +class DeprecationCollector +{ + private $twig; + private $deprecations; + + public function __construct(Environment $twig) + { + $this->twig = $twig; + } + + /** + * Returns deprecations for templates contained in a directory. + * + * @param string $dir A directory where templates are stored + * @param string $ext Limit the loaded templates by extension + * + * @return array An array of deprecations + */ + public function collectDir($dir, $ext = '.twig') + { + $iterator = new \RegexIterator( + new \RecursiveIteratorIterator( + new \RecursiveDirectoryIterator($dir), \RecursiveIteratorIterator::LEAVES_ONLY + ), '{'.preg_quote($ext).'$}' + ); + + return $this->collect(new TemplateDirIterator($iterator)); + } + + /** + * Returns deprecations for passed templates. + * + * @param \Traversable $iterator An iterator of templates (where keys are template names and values the contents of the template) + * + * @return array An array of deprecations + */ + public function collect(\Traversable $iterator) + { + $this->deprecations = []; + + set_error_handler([$this, 'errorHandler']); + + foreach ($iterator as $name => $contents) { + try { + $this->twig->parse($this->twig->tokenize(new Source($contents, $name))); + } catch (SyntaxError $e) { + // ignore templates containing syntax errors + } + } + + restore_error_handler(); -if (\false) { - class DeprecationCollector extends \Twig_Util_DeprecationCollector + $deprecations = $this->deprecations; + $this->deprecations = []; + + return $deprecations; + } + + /** + * @internal + */ + public function errorHandler($type, $msg) { + if (E_USER_DEPRECATED === $type) { + $this->deprecations[] = $msg; + } } } + +class_alias('Twig\Util\DeprecationCollector', 'Twig_Util_DeprecationCollector'); diff --git a/vendor/twig/twig/src/Util/TemplateDirIterator.php b/vendor/twig/twig/src/Util/TemplateDirIterator.php index 0e1352cc496809b2cf5261de3d2ea49d3d3a45a0..1ab0dac59d59359f2856757b70a6047e25c6704b 100644 --- a/vendor/twig/twig/src/Util/TemplateDirIterator.php +++ b/vendor/twig/twig/src/Util/TemplateDirIterator.php @@ -1,11 +1,30 @@ <?php +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + namespace Twig\Util; -class_exists('Twig_Util_TemplateDirIterator'); +/** + * @author Fabien Potencier <fabien@symfony.com> + */ +class TemplateDirIterator extends \IteratorIterator +{ + public function current() + { + return file_get_contents(parent::current()); + } -if (\false) { - class TemplateDirIterator extends \Twig_Util_TemplateDirIterator + public function key() { + return (string) parent::key(); } } + +class_alias('Twig\Util\TemplateDirIterator', 'Twig_Util_TemplateDirIterator'); diff --git a/vendor/twig/twig/test/Twig/Tests/CustomExtensionTest.php b/vendor/twig/twig/test/Twig/Tests/CustomExtensionTest.php deleted file mode 100644 index f9d44fda5e248a0293807c37197a4e94d48c6419..0000000000000000000000000000000000000000 --- a/vendor/twig/twig/test/Twig/Tests/CustomExtensionTest.php +++ /dev/null @@ -1,93 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -class CustomExtensionTest extends \PHPUnit\Framework\TestCase -{ - /** - * @requires PHP 5.3 - * @dataProvider provideInvalidExtensions - */ - public function testGetInvalidOperators(Twig_ExtensionInterface $extension, $expectedExceptionMessage) - { - if (method_exists($this, 'expectException')) { - $this->expectException('InvalidArgumentException'); - $this->expectExceptionMessage($expectedExceptionMessage); - } else { - $this->setExpectedException('InvalidArgumentException', $expectedExceptionMessage); - } - - $env = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock()); - $env->addExtension($extension); - $env->getUnaryOperators(); - } - - public function provideInvalidExtensions() - { - return array( - array(new InvalidOperatorExtension(new stdClass()), '"InvalidOperatorExtension::getOperators()" must return an array with operators, got "stdClass".'), - array(new InvalidOperatorExtension(array(1, 2, 3)), '"InvalidOperatorExtension::getOperators()" must return an array of 2 elements, got 3.'), - ); - } -} - -class InvalidOperatorExtension implements Twig_ExtensionInterface -{ - private $operators; - - public function __construct($operators) - { - $this->operators = $operators; - } - - public function initRuntime(Twig_Environment $environment) - { - } - - public function getTokenParsers() - { - return array(); - } - - public function getNodeVisitors() - { - return array(); - } - - public function getFilters() - { - return array(); - } - - public function getTests() - { - return array(); - } - - public function getFunctions() - { - return array(); - } - - public function getGlobals() - { - return array(); - } - - public function getOperators() - { - return $this->operators; - } - - public function getName() - { - return __CLASS__; - } -} diff --git a/vendor/twig/twig/test/Twig/Tests/ExpressionParserTest.php b/vendor/twig/twig/test/Twig/Tests/ExpressionParserTest.php deleted file mode 100644 index 3a173f035f7c4f28d09131749a343f1774e6254b..0000000000000000000000000000000000000000 --- a/vendor/twig/twig/test/Twig/Tests/ExpressionParserTest.php +++ /dev/null @@ -1,377 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -class Twig_Tests_ExpressionParserTest extends \PHPUnit\Framework\TestCase -{ - /** - * @expectedException Twig_Error_Syntax - * @dataProvider getFailingTestsForAssignment - */ - public function testCanOnlyAssignToNames($template) - { - $env = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock(), array('cache' => false, 'autoescape' => false)); - $parser = new Twig_Parser($env); - - $parser->parse($env->tokenize(new Twig_Source($template, 'index'))); - } - - public function getFailingTestsForAssignment() - { - return array( - array('{% set false = "foo" %}'), - array('{% set FALSE = "foo" %}'), - array('{% set true = "foo" %}'), - array('{% set TRUE = "foo" %}'), - array('{% set none = "foo" %}'), - array('{% set NONE = "foo" %}'), - array('{% set null = "foo" %}'), - array('{% set NULL = "foo" %}'), - array('{% set 3 = "foo" %}'), - array('{% set 1 + 2 = "foo" %}'), - array('{% set "bar" = "foo" %}'), - array('{% set %}{% endset %}'), - ); - } - - /** - * @dataProvider getTestsForArray - */ - public function testArrayExpression($template, $expected) - { - $env = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock(), array('cache' => false, 'autoescape' => false)); - $stream = $env->tokenize(new Twig_Source($template, '')); - $parser = new Twig_Parser($env); - - $this->assertEquals($expected, $parser->parse($stream)->getNode('body')->getNode(0)->getNode('expr')); - } - - /** - * @expectedException Twig_Error_Syntax - * @dataProvider getFailingTestsForArray - */ - public function testArraySyntaxError($template) - { - $env = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock(), array('cache' => false, 'autoescape' => false)); - $parser = new Twig_Parser($env); - - $parser->parse($env->tokenize(new Twig_Source($template, 'index'))); - } - - public function getFailingTestsForArray() - { - return array( - array('{{ [1, "a": "b"] }}'), - array('{{ {"a": "b", 2} }}'), - ); - } - - public function getTestsForArray() - { - return array( - // simple array - array('{{ [1, 2] }}', new Twig_Node_Expression_Array(array( - new Twig_Node_Expression_Constant(0, 1), - new Twig_Node_Expression_Constant(1, 1), - - new Twig_Node_Expression_Constant(1, 1), - new Twig_Node_Expression_Constant(2, 1), - ), 1), - ), - - // array with trailing , - array('{{ [1, 2, ] }}', new Twig_Node_Expression_Array(array( - new Twig_Node_Expression_Constant(0, 1), - new Twig_Node_Expression_Constant(1, 1), - - new Twig_Node_Expression_Constant(1, 1), - new Twig_Node_Expression_Constant(2, 1), - ), 1), - ), - - // simple hash - array('{{ {"a": "b", "b": "c"} }}', new Twig_Node_Expression_Array(array( - new Twig_Node_Expression_Constant('a', 1), - new Twig_Node_Expression_Constant('b', 1), - - new Twig_Node_Expression_Constant('b', 1), - new Twig_Node_Expression_Constant('c', 1), - ), 1), - ), - - // hash with trailing , - array('{{ {"a": "b", "b": "c", } }}', new Twig_Node_Expression_Array(array( - new Twig_Node_Expression_Constant('a', 1), - new Twig_Node_Expression_Constant('b', 1), - - new Twig_Node_Expression_Constant('b', 1), - new Twig_Node_Expression_Constant('c', 1), - ), 1), - ), - - // hash in an array - array('{{ [1, {"a": "b", "b": "c"}] }}', new Twig_Node_Expression_Array(array( - new Twig_Node_Expression_Constant(0, 1), - new Twig_Node_Expression_Constant(1, 1), - - new Twig_Node_Expression_Constant(1, 1), - new Twig_Node_Expression_Array(array( - new Twig_Node_Expression_Constant('a', 1), - new Twig_Node_Expression_Constant('b', 1), - - new Twig_Node_Expression_Constant('b', 1), - new Twig_Node_Expression_Constant('c', 1), - ), 1), - ), 1), - ), - - // array in a hash - array('{{ {"a": [1, 2], "b": "c"} }}', new Twig_Node_Expression_Array(array( - new Twig_Node_Expression_Constant('a', 1), - new Twig_Node_Expression_Array(array( - new Twig_Node_Expression_Constant(0, 1), - new Twig_Node_Expression_Constant(1, 1), - - new Twig_Node_Expression_Constant(1, 1), - new Twig_Node_Expression_Constant(2, 1), - ), 1), - new Twig_Node_Expression_Constant('b', 1), - new Twig_Node_Expression_Constant('c', 1), - ), 1), - ), - ); - } - - /** - * @expectedException Twig_Error_Syntax - */ - public function testStringExpressionDoesNotConcatenateTwoConsecutiveStrings() - { - $env = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock(), array('cache' => false, 'autoescape' => false, 'optimizations' => 0)); - $stream = $env->tokenize(new Twig_Source('{{ "a" "b" }}', 'index')); - $parser = new Twig_Parser($env); - - $parser->parse($stream); - } - - /** - * @dataProvider getTestsForString - */ - public function testStringExpression($template, $expected) - { - $env = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock(), array('cache' => false, 'autoescape' => false, 'optimizations' => 0)); - $stream = $env->tokenize(new Twig_Source($template, '')); - $parser = new Twig_Parser($env); - - $this->assertEquals($expected, $parser->parse($stream)->getNode('body')->getNode(0)->getNode('expr')); - } - - public function getTestsForString() - { - return array( - array( - '{{ "foo" }}', new Twig_Node_Expression_Constant('foo', 1), - ), - array( - '{{ "foo #{bar}" }}', new Twig_Node_Expression_Binary_Concat( - new Twig_Node_Expression_Constant('foo ', 1), - new Twig_Node_Expression_Name('bar', 1), - 1 - ), - ), - array( - '{{ "foo #{bar} baz" }}', new Twig_Node_Expression_Binary_Concat( - new Twig_Node_Expression_Binary_Concat( - new Twig_Node_Expression_Constant('foo ', 1), - new Twig_Node_Expression_Name('bar', 1), - 1 - ), - new Twig_Node_Expression_Constant(' baz', 1), - 1 - ), - ), - - array( - '{{ "foo #{"foo #{bar} baz"} baz" }}', new Twig_Node_Expression_Binary_Concat( - new Twig_Node_Expression_Binary_Concat( - new Twig_Node_Expression_Constant('foo ', 1), - new Twig_Node_Expression_Binary_Concat( - new Twig_Node_Expression_Binary_Concat( - new Twig_Node_Expression_Constant('foo ', 1), - new Twig_Node_Expression_Name('bar', 1), - 1 - ), - new Twig_Node_Expression_Constant(' baz', 1), - 1 - ), - 1 - ), - new Twig_Node_Expression_Constant(' baz', 1), - 1 - ), - ), - ); - } - - /** - * @expectedException Twig_Error_Syntax - */ - public function testAttributeCallDoesNotSupportNamedArguments() - { - $env = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock(), array('cache' => false, 'autoescape' => false)); - $parser = new Twig_Parser($env); - - $parser->parse($env->tokenize(new Twig_Source('{{ foo.bar(name="Foo") }}', 'index'))); - } - - /** - * @expectedException Twig_Error_Syntax - */ - public function testMacroCallDoesNotSupportNamedArguments() - { - $env = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock(), array('cache' => false, 'autoescape' => false)); - $parser = new Twig_Parser($env); - - $parser->parse($env->tokenize(new Twig_Source('{% from _self import foo %}{% macro foo() %}{% endmacro %}{{ foo(name="Foo") }}', 'index'))); - } - - /** - * @expectedException Twig_Error_Syntax - * @expectedExceptionMessage An argument must be a name. Unexpected token "string" of value "a" ("name" expected) in "index" at line 1. - */ - public function testMacroDefinitionDoesNotSupportNonNameVariableName() - { - $env = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock(), array('cache' => false, 'autoescape' => false)); - $parser = new Twig_Parser($env); - - $parser->parse($env->tokenize(new Twig_Source('{% macro foo("a") %}{% endmacro %}', 'index'))); - } - - /** - * @expectedException Twig_Error_Syntax - * @expectedExceptionMessage A default value for an argument must be a constant (a boolean, a string, a number, or an array) in "index" at line 1 - * @dataProvider getMacroDefinitionDoesNotSupportNonConstantDefaultValues - */ - public function testMacroDefinitionDoesNotSupportNonConstantDefaultValues($template) - { - $env = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock(), array('cache' => false, 'autoescape' => false)); - $parser = new Twig_Parser($env); - - $parser->parse($env->tokenize(new Twig_Source($template, 'index'))); - } - - public function getMacroDefinitionDoesNotSupportNonConstantDefaultValues() - { - return array( - array('{% macro foo(name = "a #{foo} a") %}{% endmacro %}'), - array('{% macro foo(name = [["b", "a #{foo} a"]]) %}{% endmacro %}'), - ); - } - - /** - * @dataProvider getMacroDefinitionSupportsConstantDefaultValues - */ - public function testMacroDefinitionSupportsConstantDefaultValues($template) - { - $env = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock(), array('cache' => false, 'autoescape' => false)); - $parser = new Twig_Parser($env); - - $parser->parse($env->tokenize(new Twig_Source($template, 'index'))); - - // add a dummy assertion here to satisfy PHPUnit, the only thing we want to test is that the code above - // can be executed without throwing any exceptions - $this->addToAssertionCount(1); - } - - public function getMacroDefinitionSupportsConstantDefaultValues() - { - return array( - array('{% macro foo(name = "aa") %}{% endmacro %}'), - array('{% macro foo(name = 12) %}{% endmacro %}'), - array('{% macro foo(name = true) %}{% endmacro %}'), - array('{% macro foo(name = ["a"]) %}{% endmacro %}'), - array('{% macro foo(name = [["a"]]) %}{% endmacro %}'), - array('{% macro foo(name = {a: "a"}) %}{% endmacro %}'), - array('{% macro foo(name = {a: {b: "a"}}) %}{% endmacro %}'), - ); - } - - /** - * @expectedException Twig_Error_Syntax - * @expectedExceptionMessage Unknown "cycl" function. Did you mean "cycle" in "index" at line 1? - */ - public function testUnknownFunction() - { - $env = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock(), array('cache' => false, 'autoescape' => false)); - $parser = new Twig_Parser($env); - - $parser->parse($env->tokenize(new Twig_Source('{{ cycl() }}', 'index'))); - } - - /** - * @expectedException Twig_Error_Syntax - * @expectedExceptionMessage Unknown "foobar" function in "index" at line 1. - */ - public function testUnknownFunctionWithoutSuggestions() - { - $env = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock(), array('cache' => false, 'autoescape' => false)); - $parser = new Twig_Parser($env); - - $parser->parse($env->tokenize(new Twig_Source('{{ foobar() }}', 'index'))); - } - - /** - * @expectedException Twig_Error_Syntax - * @expectedExceptionMessage Unknown "lowe" filter. Did you mean "lower" in "index" at line 1? - */ - public function testUnknownFilter() - { - $env = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock(), array('cache' => false, 'autoescape' => false)); - $parser = new Twig_Parser($env); - - $parser->parse($env->tokenize(new Twig_Source('{{ 1|lowe }}', 'index'))); - } - - /** - * @expectedException Twig_Error_Syntax - * @expectedExceptionMessage Unknown "foobar" filter in "index" at line 1. - */ - public function testUnknownFilterWithoutSuggestions() - { - $env = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock(), array('cache' => false, 'autoescape' => false)); - $parser = new Twig_Parser($env); - - $parser->parse($env->tokenize(new Twig_Source('{{ 1|foobar }}', 'index'))); - } - - /** - * @expectedException Twig_Error_Syntax - * @expectedExceptionMessage Unknown "nul" test. Did you mean "null" in "index" at line 1 - */ - public function testUnknownTest() - { - $env = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock(), array('cache' => false, 'autoescape' => false)); - $parser = new Twig_Parser($env); - $stream = $env->tokenize(new Twig_Source('{{ 1 is nul }}', 'index')); - $parser->parse($stream); - } - - /** - * @expectedException Twig_Error_Syntax - * @expectedExceptionMessage Unknown "foobar" test in "index" at line 1. - */ - public function testUnknownTestWithoutSuggestions() - { - $env = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock(), array('cache' => false, 'autoescape' => false)); - $parser = new Twig_Parser($env); - - $parser->parse($env->tokenize(new Twig_Source('{{ 1 is foobar }}', 'index'))); - } -} diff --git a/vendor/twig/twig/test/Twig/Tests/Extension/CoreTest.php b/vendor/twig/twig/test/Twig/Tests/Extension/CoreTest.php deleted file mode 100644 index ca69b4af65034f6c090b4256cb9ce9b43900f865..0000000000000000000000000000000000000000 --- a/vendor/twig/twig/test/Twig/Tests/Extension/CoreTest.php +++ /dev/null @@ -1,355 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -class Twig_Tests_Extension_CoreTest extends \PHPUnit\Framework\TestCase -{ - /** - * @dataProvider getRandomFunctionTestData - */ - public function testRandomFunction($value, $expectedInArray) - { - $env = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock()); - - for ($i = 0; $i < 100; ++$i) { - $this->assertTrue(in_array(twig_random($env, $value), $expectedInArray, true)); // assertContains() would not consider the type - } - } - - public function getRandomFunctionTestData() - { - return array( - array(// array - array('apple', 'orange', 'citrus'), - array('apple', 'orange', 'citrus'), - ), - array(// Traversable - new ArrayObject(array('apple', 'orange', 'citrus')), - array('apple', 'orange', 'citrus'), - ), - array(// unicode string - 'Ä€é', - array('Ä', '€', 'é'), - ), - array(// numeric but string - '123', - array('1', '2', '3'), - ), - array(// integer - 5, - range(0, 5, 1), - ), - array(// float - 5.9, - range(0, 5, 1), - ), - array(// negative - -2, - array(0, -1, -2), - ), - ); - } - - public function testRandomFunctionWithoutParameter() - { - $max = mt_getrandmax(); - - for ($i = 0; $i < 100; ++$i) { - $val = twig_random(new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock())); - $this->assertTrue(is_int($val) && $val >= 0 && $val <= $max); - } - } - - public function testRandomFunctionReturnsAsIs() - { - $this->assertSame('', twig_random(new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock()), '')); - $this->assertSame('', twig_random(new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock(), array('charset' => null)), '')); - - $instance = new stdClass(); - $this->assertSame($instance, twig_random(new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock()), $instance)); - } - - /** - * @expectedException Twig_Error_Runtime - */ - public function testRandomFunctionOfEmptyArrayThrowsException() - { - twig_random(new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock()), array()); - } - - public function testRandomFunctionOnNonUTF8String() - { - if (!function_exists('iconv') && !function_exists('mb_convert_encoding')) { - $this->markTestSkipped('needs iconv or mbstring'); - } - - $twig = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock()); - $twig->setCharset('ISO-8859-1'); - - $text = twig_convert_encoding('Äé', 'ISO-8859-1', 'UTF-8'); - for ($i = 0; $i < 30; ++$i) { - $rand = twig_random($twig, $text); - $this->assertTrue(in_array(twig_convert_encoding($rand, 'UTF-8', 'ISO-8859-1'), array('Ä', 'é'), true)); - } - } - - public function testReverseFilterOnNonUTF8String() - { - if (!function_exists('iconv') && !function_exists('mb_convert_encoding')) { - $this->markTestSkipped('needs iconv or mbstring'); - } - - $twig = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock()); - $twig->setCharset('ISO-8859-1'); - - $input = twig_convert_encoding('Äé', 'ISO-8859-1', 'UTF-8'); - $output = twig_convert_encoding(twig_reverse_filter($twig, $input), 'UTF-8', 'ISO-8859-1'); - - $this->assertEquals($output, 'éÄ'); - } - - /** - * @dataProvider provideCustomEscaperCases - */ - public function testCustomEscaper($expected, $string, $strategy) - { - $twig = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock()); - $twig->getExtension('Twig_Extension_Core')->setEscaper('foo', 'foo_escaper_for_test'); - - $this->assertSame($expected, twig_escape_filter($twig, $string, $strategy)); - } - - public function provideCustomEscaperCases() - { - return array( - array('fooUTF-8', 'foo', 'foo'), - array('UTF-8', null, 'foo'), - array('42UTF-8', 42, 'foo'), - ); - } - - /** - * @expectedException Twig_Error_Runtime - */ - public function testUnknownCustomEscaper() - { - twig_escape_filter(new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock()), 'foo', 'bar'); - } - - /** - * @dataProvider provideTwigFirstCases - */ - public function testTwigFirst($expected, $input) - { - $twig = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock()); - $this->assertSame($expected, twig_first($twig, $input)); - } - - public function provideTwigFirstCases() - { - $i = array(1 => 'a', 2 => 'b', 3 => 'c'); - - return array( - array('a', 'abc'), - array(1, array(1, 2, 3)), - array('', null), - array('', ''), - array('a', new CoreTestIterator($i, array_keys($i), true, 3)), - ); - } - - /** - * @dataProvider provideTwigLastCases - */ - public function testTwigLast($expected, $input) - { - $twig = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock()); - $this->assertSame($expected, twig_last($twig, $input)); - } - - public function provideTwigLastCases() - { - $i = array(1 => 'a', 2 => 'b', 3 => 'c'); - - return array( - array('c', 'abc'), - array(3, array(1, 2, 3)), - array('', null), - array('', ''), - array('c', new CoreTestIterator($i, array_keys($i), true)), - ); - } - - /** - * @dataProvider provideArrayKeyCases - */ - public function testArrayKeysFilter(array $expected, $input) - { - $this->assertSame($expected, twig_get_array_keys_filter($input)); - } - - public function provideArrayKeyCases() - { - $array = array('a' => 'a1', 'b' => 'b1', 'c' => 'c1'); - $keys = array_keys($array); - - return array( - array($keys, $array), - array($keys, new CoreTestIterator($array, $keys)), - array($keys, new CoreTestIteratorAggregate($array, $keys)), - array($keys, new CoreTestIteratorAggregateAggregate($array, $keys)), - array(array(), null), - array(array('a'), new SimpleXMLElement('<xml><a></a></xml>')), - ); - } - - /** - * @dataProvider provideInFilterCases - */ - public function testInFilter($expected, $value, $compare) - { - $this->assertSame($expected, twig_in_filter($value, $compare)); - } - - public function provideInFilterCases() - { - $array = array(1, 2, 'a' => 3, 5, 6, 7); - $keys = array_keys($array); - - return array( - array(true, 1, $array), - array(true, '3', $array), - array(true, '3', 'abc3def'), - array(true, 1, new CoreTestIterator($array, $keys, true, 1)), - array(true, '3', new CoreTestIterator($array, $keys, true, 3)), - array(true, '3', new CoreTestIteratorAggregateAggregate($array, $keys, true, 3)), - array(false, 4, $array), - array(false, 4, new CoreTestIterator($array, $keys, true)), - array(false, 4, new CoreTestIteratorAggregateAggregate($array, $keys, true)), - array(false, 1, 1), - array(true, 'b', new SimpleXMLElement('<xml><a>b</a></xml>')), - ); - } - - /** - * @dataProvider provideSliceFilterCases - */ - public function testSliceFilter($expected, $input, $start, $length = null, $preserveKeys = false) - { - $twig = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock()); - $this->assertSame($expected, twig_slice($twig, $input, $start, $length, $preserveKeys)); - } - - public function provideSliceFilterCases() - { - $i = array('a' => 1, 'b' => 2, 'c' => 3, 'd' => 4); - $keys = array_keys($i); - - return array( - array(array('a' => 1), $i, 0, 1, true), - array(array('a' => 1), $i, 0, 1, false), - array(array('b' => 2, 'c' => 3), $i, 1, 2), - array(array(1), array(1, 2, 3, 4), 0, 1), - array(array(2, 3), array(1, 2, 3, 4), 1, 2), - array(array(2, 3), new CoreTestIterator($i, $keys, true), 1, 2), - array(array('c' => 3, 'd' => 4), new CoreTestIteratorAggregate($i, $keys, true), 2, null, true), - array($i, new CoreTestIterator($i, $keys, true), 0, count($keys) + 10, true), - array(array(), new CoreTestIterator($i, $keys, true), count($keys) + 10), - array('de', 'abcdef', 3, 2), - array(array(), new SimpleXMLElement('<items><item>1</item><item>2</item></items>'), 3), - array(array(), new ArrayIterator(array(1, 2)), 3), - ); - } -} - -function foo_escaper_for_test(Twig_Environment $env, $string, $charset) -{ - return $string.$charset; -} - -final class CoreTestIteratorAggregate implements IteratorAggregate -{ - private $iterator; - - public function __construct(array $array, array $keys, $allowAccess = false, $maxPosition = false) - { - $this->iterator = new CoreTestIterator($array, $keys, $allowAccess, $maxPosition); - } - - public function getIterator() - { - return $this->iterator; - } -} - -final class CoreTestIteratorAggregateAggregate implements IteratorAggregate -{ - private $iterator; - - public function __construct(array $array, array $keys, $allowValueAccess = false, $maxPosition = false) - { - $this->iterator = new CoreTestIteratorAggregate($array, $keys, $allowValueAccess, $maxPosition); - } - - public function getIterator() - { - return $this->iterator; - } -} - -final class CoreTestIterator implements Iterator -{ - private $position; - private $array; - private $arrayKeys; - private $allowValueAccess; - private $maxPosition; - - public function __construct(array $values, array $keys, $allowValueAccess = false, $maxPosition = false) - { - $this->array = $values; - $this->arrayKeys = $keys; - $this->position = 0; - $this->allowValueAccess = $allowValueAccess; - $this->maxPosition = false === $maxPosition ? count($values) + 1 : $maxPosition; - } - - public function rewind() - { - $this->position = 0; - } - - public function current() - { - if ($this->allowValueAccess) { - return $this->array[$this->key()]; - } - - throw new LogicException('Code should only use the keys, not the values provided by iterator.'); - } - - public function key() - { - return $this->arrayKeys[$this->position]; - } - - public function next() - { - ++$this->position; - if ($this->position === $this->maxPosition) { - throw new LogicException(sprintf('Code should not iterate beyond %d.', $this->maxPosition)); - } - } - - public function valid() - { - return isset($this->arrayKeys[$this->position]); - } -} diff --git a/vendor/twig/twig/test/Twig/Tests/Extension/SandboxTest.php b/vendor/twig/twig/test/Twig/Tests/Extension/SandboxTest.php deleted file mode 100644 index 9d90e0ea7467bb735647c615210714345f070337..0000000000000000000000000000000000000000 --- a/vendor/twig/twig/test/Twig/Tests/Extension/SandboxTest.php +++ /dev/null @@ -1,304 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -class Twig_Tests_Extension_SandboxTest extends \PHPUnit\Framework\TestCase -{ - protected static $params; - protected static $templates; - - protected function setUp() - { - self::$params = array( - 'name' => 'Fabien', - 'obj' => new FooObject(), - 'arr' => array('obj' => new FooObject()), - ); - - self::$templates = array( - '1_basic1' => '{{ obj.foo }}', - '1_basic2' => '{{ name|upper }}', - '1_basic3' => '{% if name %}foo{% endif %}', - '1_basic4' => '{{ obj.bar }}', - '1_basic5' => '{{ obj }}', - '1_basic6' => '{{ arr.obj }}', - '1_basic7' => '{{ cycle(["foo","bar"], 1) }}', - '1_basic8' => '{{ obj.getfoobar }}{{ obj.getFooBar }}', - '1_basic9' => '{{ obj.foobar }}{{ obj.fooBar }}', - '1_basic' => '{% if obj.foo %}{{ obj.foo|upper }}{% endif %}', - '1_layout' => '{% block content %}{% endblock %}', - '1_child' => "{% extends \"1_layout\" %}\n{% block content %}\n{{ \"a\"|json_encode }}\n{% endblock %}", - '1_include' => '{{ include("1_basic1", sandboxed=true) }}', - ); - } - - /** - * @expectedException Twig_Sandbox_SecurityError - * @expectedExceptionMessage Filter "json_encode" is not allowed in "1_child" at line 3. - */ - public function testSandboxWithInheritance() - { - $twig = $this->getEnvironment(true, array(), self::$templates, array('block')); - $twig->loadTemplate('1_child')->render(array()); - } - - public function testSandboxGloballySet() - { - $twig = $this->getEnvironment(false, array(), self::$templates); - $this->assertEquals('FOO', $twig->loadTemplate('1_basic')->render(self::$params), 'Sandbox does nothing if it is disabled globally'); - } - - public function testSandboxUnallowedMethodAccessor() - { - $twig = $this->getEnvironment(true, array(), self::$templates); - try { - $twig->loadTemplate('1_basic1')->render(self::$params); - $this->fail('Sandbox throws a SecurityError exception if an unallowed method is called'); - } catch (Twig_Sandbox_SecurityError $e) { - $this->assertInstanceOf('Twig_Sandbox_SecurityNotAllowedMethodError', $e, 'Exception should be an instance of Twig_Sandbox_SecurityNotAllowedMethodError'); - $this->assertEquals('FooObject', $e->getClassName(), 'Exception should be raised on the "FooObject" class'); - $this->assertEquals('foo', $e->getMethodName(), 'Exception should be raised on the "foo" method'); - } - } - - public function testSandboxUnallowedFilter() - { - $twig = $this->getEnvironment(true, array(), self::$templates); - try { - $twig->loadTemplate('1_basic2')->render(self::$params); - $this->fail('Sandbox throws a SecurityError exception if an unallowed filter is called'); - } catch (Twig_Sandbox_SecurityError $e) { - $this->assertInstanceOf('Twig_Sandbox_SecurityNotAllowedFilterError', $e, 'Exception should be an instance of Twig_Sandbox_SecurityNotAllowedFilterError'); - $this->assertEquals('upper', $e->getFilterName(), 'Exception should be raised on the "upper" filter'); - } - } - - public function testSandboxUnallowedTag() - { - $twig = $this->getEnvironment(true, array(), self::$templates); - try { - $twig->loadTemplate('1_basic3')->render(self::$params); - $this->fail('Sandbox throws a SecurityError exception if an unallowed tag is used in the template'); - } catch (Twig_Sandbox_SecurityError $e) { - $this->assertInstanceOf('Twig_Sandbox_SecurityNotAllowedTagError', $e, 'Exception should be an instance of Twig_Sandbox_SecurityNotAllowedTagError'); - $this->assertEquals('if', $e->getTagName(), 'Exception should be raised on the "if" tag'); - } - } - - public function testSandboxUnallowedProperty() - { - $twig = $this->getEnvironment(true, array(), self::$templates); - try { - $twig->loadTemplate('1_basic4')->render(self::$params); - $this->fail('Sandbox throws a SecurityError exception if an unallowed property is called in the template'); - } catch (Twig_Sandbox_SecurityError $e) { - $this->assertInstanceOf('Twig_Sandbox_SecurityNotAllowedPropertyError', $e, 'Exception should be an instance of Twig_Sandbox_SecurityNotAllowedPropertyError'); - $this->assertEquals('FooObject', $e->getClassName(), 'Exception should be raised on the "FooObject" class'); - $this->assertEquals('bar', $e->getPropertyName(), 'Exception should be raised on the "bar" property'); - } - } - - public function testSandboxUnallowedToString() - { - $twig = $this->getEnvironment(true, array(), self::$templates); - try { - $twig->loadTemplate('1_basic5')->render(self::$params); - $this->fail('Sandbox throws a SecurityError exception if an unallowed method (__toString()) is called in the template'); - } catch (Twig_Sandbox_SecurityError $e) { - $this->assertInstanceOf('Twig_Sandbox_SecurityNotAllowedMethodError', $e, 'Exception should be an instance of Twig_Sandbox_SecurityNotAllowedMethodError'); - $this->assertEquals('FooObject', $e->getClassName(), 'Exception should be raised on the "FooObject" class'); - $this->assertEquals('__tostring', $e->getMethodName(), 'Exception should be raised on the "__toString" method'); - } - } - - public function testSandboxUnallowedToStringArray() - { - $twig = $this->getEnvironment(true, array(), self::$templates); - try { - $twig->loadTemplate('1_basic6')->render(self::$params); - $this->fail('Sandbox throws a SecurityError exception if an unallowed method (__toString()) is called in the template'); - } catch (Twig_Sandbox_SecurityError $e) { - $this->assertInstanceOf('Twig_Sandbox_SecurityNotAllowedMethodError', $e, 'Exception should be an instance of Twig_Sandbox_SecurityNotAllowedMethodError'); - $this->assertEquals('FooObject', $e->getClassName(), 'Exception should be raised on the "FooObject" class'); - $this->assertEquals('__tostring', $e->getMethodName(), 'Exception should be raised on the "__toString" method'); - } - } - - public function testSandboxUnallowedFunction() - { - $twig = $this->getEnvironment(true, array(), self::$templates); - try { - $twig->loadTemplate('1_basic7')->render(self::$params); - $this->fail('Sandbox throws a SecurityError exception if an unallowed function is called in the template'); - } catch (Twig_Sandbox_SecurityError $e) { - $this->assertInstanceOf('Twig_Sandbox_SecurityNotAllowedFunctionError', $e, 'Exception should be an instance of Twig_Sandbox_SecurityNotAllowedFunctionError'); - $this->assertEquals('cycle', $e->getFunctionName(), 'Exception should be raised on the "cycle" function'); - } - } - - public function testSandboxAllowMethodFoo() - { - $twig = $this->getEnvironment(true, array(), self::$templates, array(), array(), array('FooObject' => 'foo')); - FooObject::reset(); - $this->assertEquals('foo', $twig->loadTemplate('1_basic1')->render(self::$params), 'Sandbox allow some methods'); - $this->assertEquals(1, FooObject::$called['foo'], 'Sandbox only calls method once'); - } - - public function testSandboxAllowMethodToString() - { - $twig = $this->getEnvironment(true, array(), self::$templates, array(), array(), array('FooObject' => '__toString')); - FooObject::reset(); - $this->assertEquals('foo', $twig->loadTemplate('1_basic5')->render(self::$params), 'Sandbox allow some methods'); - $this->assertEquals(1, FooObject::$called['__toString'], 'Sandbox only calls method once'); - } - - public function testSandboxAllowMethodToStringDisabled() - { - $twig = $this->getEnvironment(false, array(), self::$templates); - FooObject::reset(); - $this->assertEquals('foo', $twig->loadTemplate('1_basic5')->render(self::$params), 'Sandbox allows __toString when sandbox disabled'); - $this->assertEquals(1, FooObject::$called['__toString'], 'Sandbox only calls method once'); - } - - public function testSandboxAllowFilter() - { - $twig = $this->getEnvironment(true, array(), self::$templates, array(), array('upper')); - $this->assertEquals('FABIEN', $twig->loadTemplate('1_basic2')->render(self::$params), 'Sandbox allow some filters'); - } - - public function testSandboxAllowTag() - { - $twig = $this->getEnvironment(true, array(), self::$templates, array('if')); - $this->assertEquals('foo', $twig->loadTemplate('1_basic3')->render(self::$params), 'Sandbox allow some tags'); - } - - public function testSandboxAllowProperty() - { - $twig = $this->getEnvironment(true, array(), self::$templates, array(), array(), array(), array('FooObject' => 'bar')); - $this->assertEquals('bar', $twig->loadTemplate('1_basic4')->render(self::$params), 'Sandbox allow some properties'); - } - - public function testSandboxAllowFunction() - { - $twig = $this->getEnvironment(true, array(), self::$templates, array(), array(), array(), array(), array('cycle')); - $this->assertEquals('bar', $twig->loadTemplate('1_basic7')->render(self::$params), 'Sandbox allow some functions'); - } - - public function testSandboxAllowFunctionsCaseInsensitive() - { - foreach (array('getfoobar', 'getFoobar', 'getFooBar') as $name) { - $twig = $this->getEnvironment(true, array(), self::$templates, array(), array(), array('FooObject' => $name)); - FooObject::reset(); - $this->assertEquals('foobarfoobar', $twig->loadTemplate('1_basic8')->render(self::$params), 'Sandbox allow methods in a case-insensitive way'); - $this->assertEquals(2, FooObject::$called['getFooBar'], 'Sandbox only calls method once'); - - $this->assertEquals('foobarfoobar', $twig->loadTemplate('1_basic9')->render(self::$params), 'Sandbox allow methods via shortcut names (ie. without get/set)'); - } - } - - public function testSandboxLocallySetForAnInclude() - { - self::$templates = array( - '2_basic' => '{{ obj.foo }}{% include "2_included" %}{{ obj.foo }}', - '2_included' => '{% if obj.foo %}{{ obj.foo|upper }}{% endif %}', - ); - - $twig = $this->getEnvironment(false, array(), self::$templates); - $this->assertEquals('fooFOOfoo', $twig->loadTemplate('2_basic')->render(self::$params), 'Sandbox does nothing if disabled globally and sandboxed not used for the include'); - - self::$templates = array( - '3_basic' => '{{ obj.foo }}{% sandbox %}{% include "3_included" %}{% endsandbox %}{{ obj.foo }}', - '3_included' => '{% if obj.foo %}{{ obj.foo|upper }}{% endif %}', - ); - - $twig = $this->getEnvironment(true, array(), self::$templates); - try { - $twig->loadTemplate('3_basic')->render(self::$params); - $this->fail('Sandbox throws a SecurityError exception when the included file is sandboxed'); - } catch (Twig_Sandbox_SecurityError $e) { - $this->assertInstanceOf('Twig_Sandbox_SecurityNotAllowedTagError', $e, 'Exception should be an instance of Twig_Sandbox_SecurityNotAllowedTagError'); - $this->assertEquals('sandbox', $e->getTagName()); - } - } - - public function testMacrosInASandbox() - { - $twig = $this->getEnvironment(true, array('autoescape' => 'html'), array('index' => <<<EOF -{%- import _self as macros %} - -{%- macro test(text) %}<p>{{ text }}</p>{% endmacro %} - -{{- macros.test('username') }} -EOF - ), array('macro', 'import'), array('escape')); - - $this->assertEquals('<p>username</p>', $twig->loadTemplate('index')->render(array())); - } - - public function testSandboxDisabledAfterIncludeFunctionError() - { - $twig = $this->getEnvironment(false, array(), self::$templates); - - $e = null; - try { - $twig->loadTemplate('1_include')->render(self::$params); - } catch (Throwable $e) { - } catch (Exception $e) { - } - if ($e === null) { - $this->fail('An exception should be thrown for this test to be valid.'); - } - - $this->assertFalse($twig->getExtension('Twig_Extension_Sandbox')->isSandboxed(), 'Sandboxed include() function call should not leave Sandbox enabled when an error occurs.'); - } - - protected function getEnvironment($sandboxed, $options, $templates, $tags = array(), $filters = array(), $methods = array(), $properties = array(), $functions = array()) - { - $loader = new Twig_Loader_Array($templates); - $twig = new Twig_Environment($loader, array_merge(array('debug' => true, 'cache' => false, 'autoescape' => false), $options)); - $policy = new Twig_Sandbox_SecurityPolicy($tags, $filters, $methods, $properties, $functions); - $twig->addExtension(new Twig_Extension_Sandbox($policy, $sandboxed)); - - return $twig; - } -} - -class FooObject -{ - public static $called = array('__toString' => 0, 'foo' => 0, 'getFooBar' => 0); - - public $bar = 'bar'; - - public static function reset() - { - self::$called = array('__toString' => 0, 'foo' => 0, 'getFooBar' => 0); - } - - public function __toString() - { - ++self::$called['__toString']; - - return 'foo'; - } - - public function foo() - { - ++self::$called['foo']; - - return 'foo'; - } - - public function getFooBar() - { - ++self::$called['getFooBar']; - - return 'foobar'; - } -} diff --git a/vendor/twig/twig/test/Twig/Tests/FileExtensionEscapingStrategyTest.php b/vendor/twig/twig/test/Twig/Tests/FileExtensionEscapingStrategyTest.php deleted file mode 100644 index a983a47c85877727e299f5f39b603723fd4b0c06..0000000000000000000000000000000000000000 --- a/vendor/twig/twig/test/Twig/Tests/FileExtensionEscapingStrategyTest.php +++ /dev/null @@ -1,51 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -class Twig_Tests_FileExtensionEscapingStrategyTest extends \PHPUnit\Framework\TestCase -{ - /** - * @dataProvider getGuessData - */ - public function testGuess($strategy, $filename) - { - $this->assertSame($strategy, Twig_FileExtensionEscapingStrategy::guess($filename)); - } - - public function getGuessData() - { - return array( - // default - array('html', 'foo.html'), - array('html', 'foo.html.twig'), - array('html', 'foo'), - array('html', 'foo.bar.twig'), - array('html', 'foo.txt/foo'), - array('html', 'foo.txt/foo.js/'), - - // css - array('css', 'foo.css'), - array('css', 'foo.css.twig'), - array('css', 'foo.twig.css'), - array('css', 'foo.js.css'), - array('css', 'foo.js.css.twig'), - - // js - array('js', 'foo.js'), - array('js', 'foo.js.twig'), - array('js', 'foo.txt/foo.js'), - array('js', 'foo.txt.twig/foo.js'), - - // txt - array(false, 'foo.txt'), - array(false, 'foo.txt.twig'), - ); - } -} diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/exceptions/child_contents_outside_blocks.test b/vendor/twig/twig/test/Twig/Tests/Fixtures/exceptions/child_contents_outside_blocks.test deleted file mode 100644 index a3f0b50ffc2aff64ad47b557ef78de73d0337867..0000000000000000000000000000000000000000 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/exceptions/child_contents_outside_blocks.test +++ /dev/null @@ -1,15 +0,0 @@ ---TEST-- -Exception for child templates defining contents outside blocks defined by parent ---TEMPLATE-- -{% extends 'base.twig' %} - -Content outside a block. - -{% block sidebar %} - Content inside a block. -{% endblock %} ---TEMPLATE(base.twig)-- -{% block sidebar %} -{% endblock %} ---EXCEPTION-- -Twig_Error_Syntax: A template that extends another one cannot include contents outside Twig blocks. Did you forget to put the contents inside a {% block %} tag in "index.twig" at line 3? diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/exceptions/multiline_function_with_unknown_argument.test b/vendor/twig/twig/test/Twig/Tests/Fixtures/exceptions/multiline_function_with_unknown_argument.test deleted file mode 100644 index 64761fcf12e983121d8827305ead9e91378bc289..0000000000000000000000000000000000000000 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/exceptions/multiline_function_with_unknown_argument.test +++ /dev/null @@ -1,9 +0,0 @@ ---TEST-- -Exception for multiline function with unknown argument ---TEMPLATE-- -{{ include('foo', - with_context=True, - invalid=False -) }} ---EXCEPTION-- -Twig_Error_Syntax: Unknown argument "invalid" for function "include(template, variables, with_context, ignore_missing, sandboxed)" in "index.twig" at line 4. diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/join.test b/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/join.test deleted file mode 100644 index b342c174c9858c59f9570cd0f4aae9dd5c9d5070..0000000000000000000000000000000000000000 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/join.test +++ /dev/null @@ -1,12 +0,0 @@ ---TEST-- -"join" filter ---TEMPLATE-- -{{ ["foo", "bar"]|join(', ') }} -{{ foo|join(', ') }} -{{ bar|join(', ') }} ---DATA-- -return array('foo' => new TwigTestFoo(), 'bar' => new ArrayObject(array(3, 4))) ---EXPECT-- -foo, bar -1, 2 -3, 4 diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/length.test b/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/length.test deleted file mode 100644 index a7f1e50318c4809fafd69d40209cc767d2ddb5a8..0000000000000000000000000000000000000000 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/length.test +++ /dev/null @@ -1,31 +0,0 @@ ---TEST-- -"length" filter ---TEMPLATE-- -{{ array|length }} -{{ string|length }} -{{ number|length }} -{{ to_string_able|length }} -{{ countable|length }} -{{ null|length }} -{{ magic|length }} -{{ non_countable|length }} ---DATA-- -return array( - 'array' => array(1, 4), - 'string' => 'foo', - 'number' => 1000, - 'to_string_able' => new ToStringStub('foobar'), - 'countable' => new CountableStub(42), /* also asserts we do *not* call __toString() */ - 'null' => null, - 'magic' => new MagicCallStub(), /* used to assert we do *not* call __call */ - 'non_countable' => new \StdClass(), -); ---EXPECT-- -2 -3 -4 -6 -42 -0 -1 -1 diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/replace_invalid_arg.test b/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/replace_invalid_arg.test deleted file mode 100644 index 2143a869096620ea90da6077431c5db092a5fca3..0000000000000000000000000000000000000000 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/replace_invalid_arg.test +++ /dev/null @@ -1,8 +0,0 @@ ---TEST-- -Exception for invalid argument type in replace call ---TEMPLATE-- -{{ 'test %foo%'|replace(stdClass) }} ---DATA-- -return array('stdClass' => new stdClass()) ---EXCEPTION-- -Twig_Error_Runtime: The "replace" filter expects an array or "Traversable" as replace values, got "stdClass" in "index.twig" at line 2. diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/functions/include/missing.test b/vendor/twig/twig/test/Twig/Tests/Fixtures/functions/include/missing.test deleted file mode 100644 index 4d2f6cf136ce43682dafc754c226ffe9b44b96b0..0000000000000000000000000000000000000000 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/functions/include/missing.test +++ /dev/null @@ -1,8 +0,0 @@ ---TEST-- -"include" function ---TEMPLATE-- -{{ include("foo.twig") }} ---DATA-- -return array(); ---EXCEPTION-- -Twig_Error_Loader: Template "foo.twig" is not defined in "index.twig" at line 2. diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/macros/varargs_argument.test b/vendor/twig/twig/test/Twig/Tests/Fixtures/macros/varargs_argument.test deleted file mode 100644 index 800c262e7905c8fd8e3e49ba67c9b27c85f95720..0000000000000000000000000000000000000000 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/macros/varargs_argument.test +++ /dev/null @@ -1,7 +0,0 @@ ---TEST-- -macro with varargs argument ---TEMPLATE-- -{% macro test(varargs) %} -{% endmacro %} ---EXCEPTION-- -Twig_Error_Syntax: The argument "varargs" in macro "test" cannot be defined because the variable "varargs" is reserved for arbitrary arguments in "index.twig" at line 2. diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/autoescape/literal.test b/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/autoescape/literal.test deleted file mode 100644 index e389d4dd536db703938098edbca5cde7cceb79b6..0000000000000000000000000000000000000000 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/autoescape/literal.test +++ /dev/null @@ -1,45 +0,0 @@ ---TEST-- -"autoescape" tag does not apply escaping on literals ---TEMPLATE-- -{% autoescape 'html' %} - -1. Simple literal -{{ "<br />" }} - -2. Conditional expression with only literals -{{ true ? "<br />" : "<br>" }} - -3. Conditional expression with a variable -{{ true ? "<br />" : someVar }} - -4. Nested conditionals with only literals -{{ true ? (true ? "<br />" : "<br>") : "\n" }} - -5. Nested conditionals with a variable -{{ true ? (true ? "<br />" : someVar) : "\n" }} - -6. Nested conditionals with a variable marked safe -{{ true ? (true ? "<br />" : someVar|raw) : "\n" }} - -{% endautoescape %} ---DATA-- -return array() ---EXPECT-- - -1. Simple literal -<br /> - -2. Conditional expression with only literals -<br /> - -3. Conditional expression with a variable -<br /> - -4. Nested conditionals with only literals -<br /> - -5. Nested conditionals with a variable -<br /> - -6. Nested conditionals with a variable marked safe -<br /> diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/for/loop_not_defined.test b/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/for/loop_not_defined.test deleted file mode 100644 index 6a2af63b617e7b4e7127f3cfda599698b3757064..0000000000000000000000000000000000000000 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/for/loop_not_defined.test +++ /dev/null @@ -1,10 +0,0 @@ ---TEST-- -"for" tag ---TEMPLATE-- -{% for i, item in items if i > 0 %} - {{ loop.last }} -{% endfor %} ---DATA-- -return array('items' => array('a', 'b')) ---EXCEPTION-- -Twig_Error_Syntax: The "loop.last" variable is not defined when looping with a condition in "index.twig" at line 3. diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/for/loop_not_defined_cond.test b/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/for/loop_not_defined_cond.test deleted file mode 100644 index 1e819ca0a135f16ed3540e350b3218cc1a6d43b3..0000000000000000000000000000000000000000 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/for/loop_not_defined_cond.test +++ /dev/null @@ -1,9 +0,0 @@ ---TEST-- -"for" tag ---TEMPLATE-- -{% for i, item in items if loop.last > 0 %} -{% endfor %} ---DATA-- -return array('items' => array('a', 'b')) ---EXCEPTION-- -Twig_Error_Syntax: The "loop" variable cannot be used in a looping condition in "index.twig" at line 2. diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/include/missing.test b/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/include/missing.test deleted file mode 100644 index f25e8715517bae404a6d30a0feb5fe7fbd534631..0000000000000000000000000000000000000000 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/include/missing.test +++ /dev/null @@ -1,8 +0,0 @@ ---TEST-- -"include" tag ---TEMPLATE-- -{% include "foo.twig" %} ---DATA-- -return array(); ---EXCEPTION-- -Twig_Error_Loader: Template "foo.twig" is not defined in "index.twig" at line 2. diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/include/only.test b/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/include/only.test deleted file mode 100644 index 77760a09eb9ffb6f14cea8cf2f7edff510f89ee2..0000000000000000000000000000000000000000 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/include/only.test +++ /dev/null @@ -1,16 +0,0 @@ ---TEST-- -"include" tag accept variables and only ---TEMPLATE-- -{% include "foo.twig" %} -{% include "foo.twig" only %} -{% include "foo.twig" with {'foo1': 'bar'} %} -{% include "foo.twig" with {'foo1': 'bar'} only %} ---TEMPLATE(foo.twig)-- -{% for k, v in _context %}{{ k }},{% endfor %} ---DATA-- -return array('foo' => 'bar') ---EXPECT-- -foo,global,_parent, -global,_parent, -foo,global,foo1,_parent, -foo1,global,_parent, diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/include/template_instance.test b/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/include/template_instance.test deleted file mode 100644 index 6ba064a388398b221795bd17eb3c38d1269426a9..0000000000000000000000000000000000000000 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/include/template_instance.test +++ /dev/null @@ -1,10 +0,0 @@ ---TEST-- -"include" tag accepts Twig_Template instance ---TEMPLATE-- -{% include foo %} FOO ---TEMPLATE(foo.twig)-- -BAR ---DATA-- -return array('foo' => $twig->loadTemplate('foo.twig')) ---EXPECT-- -BAR FOO diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/inheritance/parent_in_a_block.test b/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/inheritance/parent_in_a_block.test deleted file mode 100644 index cca6dbc9b86b692e2eac84a4a9fb621ff0df4af4..0000000000000000000000000000000000000000 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/inheritance/parent_in_a_block.test +++ /dev/null @@ -1,8 +0,0 @@ ---TEST-- -"extends" tag ---TEMPLATE-- -{% block content %} - {% extends "foo.twig" %} -{% endblock %} ---EXCEPTION-- -Twig_Error_Syntax: Cannot extend from a block in "index.twig" at line 3. diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/inheritance/parent_without_extends.test b/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/inheritance/parent_without_extends.test deleted file mode 100644 index e29b1ac4b5bb73177b019ef2f517b7f2843b4e6b..0000000000000000000000000000000000000000 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/inheritance/parent_without_extends.test +++ /dev/null @@ -1,8 +0,0 @@ ---TEST-- -"parent" tag ---TEMPLATE-- -{% block content %} - {{ parent() }} -{% endblock %} ---EXCEPTION-- -Twig_Error_Syntax: Calling "parent" on a template that does not extend nor "use" another template is forbidden in "index.twig" at line 3. diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/macro/from_with_reserved_name.test b/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/macro/from_with_reserved_name.test deleted file mode 100644 index 2de9765ff0398aa5ca23f6a596f4958e1af20a16..0000000000000000000000000000000000000000 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/macro/from_with_reserved_name.test +++ /dev/null @@ -1,9 +0,0 @@ ---TEST-- -"from" tag with reserved name ---TEMPLATE-- -{% from 'forms.twig' import templateName %} ---TEMPLATE(forms.twig)-- ---DATA-- -return array() ---EXCEPTION-- -Twig_Error_Syntax: "templateName" cannot be an imported macro as it is a reserved keyword in "index.twig" at line 2. diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/macro/import_with_reserved_nam.test b/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/macro/import_with_reserved_nam.test deleted file mode 100644 index 7bd93c62dff6b45d82894b76a2672c6b6c7bbd7c..0000000000000000000000000000000000000000 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/macro/import_with_reserved_nam.test +++ /dev/null @@ -1,11 +0,0 @@ ---TEST-- -"from" tag with reserved name ---TEMPLATE-- -{% import 'forms.twig' as macros %} - -{{ macros.parent() }} ---TEMPLATE(forms.twig)-- ---DATA-- -return array() ---EXCEPTION-- -Twig_Error_Syntax: "parent" cannot be called as macro as it is a reserved keyword in "index.twig" at line 4. diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/raw/mixed_usage_with_raw.legacy.test b/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/raw/mixed_usage_with_raw.legacy.test deleted file mode 100644 index 99deefc32a6ac89c1d9cb1e75342a344432943b2..0000000000000000000000000000000000000000 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/raw/mixed_usage_with_raw.legacy.test +++ /dev/null @@ -1,10 +0,0 @@ ---TEST-- -"raw" tag ---TEMPLATE-- -{% raw %} -{{ foo }} -{% endverbatim %} ---DATA-- -return array() ---EXCEPTION-- -Twig_Error_Syntax: Unexpected end of file: Unclosed "raw" block in "index.twig" at line 2. diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/verbatim/mixed_usage_with_raw.test b/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/verbatim/mixed_usage_with_raw.test deleted file mode 100644 index 28626a816afdea01f9e3f2e6d15c77643d69f7e6..0000000000000000000000000000000000000000 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/verbatim/mixed_usage_with_raw.test +++ /dev/null @@ -1,10 +0,0 @@ ---TEST-- -"verbatim" tag ---TEMPLATE-- -{% verbatim %} -{{ foo }} -{% endraw %} ---DATA-- -return array() ---EXCEPTION-- -Twig_Error_Syntax: Unexpected end of file: Unclosed "verbatim" block in "index.twig" at line 2. diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tests/array.test b/vendor/twig/twig/test/Twig/Tests/Fixtures/tests/array.test deleted file mode 100644 index 1429d3753c974e13bde2f533041226dcb89d0b9e..0000000000000000000000000000000000000000 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tests/array.test +++ /dev/null @@ -1,24 +0,0 @@ ---TEST-- -array index test ---TEMPLATE-- -{% for key, value in days %} -{{ key }} -{% endfor %} ---DATA-- -return array('days' => array( - 1 => array('money' => 9), - 2 => array('money' => 21), - 3 => array('money' => 38), - 4 => array('money' => 6), - 18 => array('money' => 6), - 19 => array('money' => 3), - 31 => array('money' => 11), -)); ---EXPECT-- -1 -2 -3 -4 -18 -19 -31 diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tests/constant.test b/vendor/twig/twig/test/Twig/Tests/Fixtures/tests/constant.test deleted file mode 100644 index 60218ac04c0c72655368ffd31186a2a7eaa911d8..0000000000000000000000000000000000000000 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tests/constant.test +++ /dev/null @@ -1,14 +0,0 @@ ---TEST-- -"const" test ---TEMPLATE-- -{{ 8 is constant('E_NOTICE') ? 'ok' : 'no' }} -{{ 'bar' is constant('TwigTestFoo::BAR_NAME') ? 'ok' : 'no' }} -{{ value is constant('TwigTestFoo::BAR_NAME') ? 'ok' : 'no' }} -{{ 2 is constant('ARRAY_AS_PROPS', object) ? 'ok' : 'no' }} ---DATA-- -return array('value' => 'bar', 'object' => new ArrayObject(array('hi'))); ---EXPECT-- -ok -ok -ok -ok \ No newline at end of file diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tests/empty.test b/vendor/twig/twig/test/Twig/Tests/Fixtures/tests/empty.test deleted file mode 100644 index 807c0ed4ae13db7e3cc2d794352024e4e6bec021..0000000000000000000000000000000000000000 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tests/empty.test +++ /dev/null @@ -1,42 +0,0 @@ ---TEST-- -"empty" test ---TEMPLATE-- -{{ string_empty is empty ? 'ok' : 'ko' }} -{{ string_zero is empty ? 'ko' : 'ok' }} -{{ value_null is empty ? 'ok' : 'ko' }} -{{ value_false is empty ? 'ok' : 'ko' }} -{{ value_int_zero is empty ? 'ko' : 'ok' }} -{{ array_empty is empty ? 'ok' : 'ko' }} -{{ array_not_empty is empty ? 'ko' : 'ok' }} -{{ magically_callable is empty ? 'ko' : 'ok' }} -{{ countable_empty is empty ? 'ok' : 'ko' }} -{{ countable_not_empty is empty ? 'ko' : 'ok' }} -{{ tostring_empty is empty ? 'ok' : 'ko' }} -{{ tostring_not_empty is empty ? 'ko' : 'ok' }} -{{ markup_empty is empty ? 'ok' : 'ko' }} -{{ markup_not_empty is empty ? 'ko' : 'ok' }} ---DATA-- -return array( - 'string_empty' => '', 'string_zero' => '0', - 'value_null' => null, 'value_false' => false, 'value_int_zero' => 0, - 'array_empty' => array(), 'array_not_empty' => array(1, 2), - 'magically_callable' => new MagicCallStub(), - 'countable_empty' => new CountableStub(array()), 'countable_not_empty' => new CountableStub(array(1, 2)), - 'tostring_empty' => new ToStringStub(''), 'tostring_not_empty' => new ToStringStub('0' /* edge case of using "0" as the string */), - 'markup_empty' => new Twig_Markup('', 'UTF-8'), 'markup_not_empty' => new Twig_Markup('test', 'UTF-8'), -); ---EXPECT-- -ok -ok -ok -ok -ok -ok -ok -ok -ok -ok -ok -ok -ok -ok diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tests/in.test b/vendor/twig/twig/test/Twig/Tests/Fixtures/tests/in.test deleted file mode 100644 index 545f51f81fefea98647f55ac7a856eb7f7648eeb..0000000000000000000000000000000000000000 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tests/in.test +++ /dev/null @@ -1,128 +0,0 @@ ---TEST-- -Twig supports the in operator ---TEMPLATE-- -{% if bar in foo %} -TRUE -{% endif %} -{% if not (bar in foo) %} -{% else %} -TRUE -{% endif %} -{% if bar not in foo %} -{% else %} -TRUE -{% endif %} -{% if 'a' in bar %} -TRUE -{% endif %} -{% if 'c' not in bar %} -TRUE -{% endif %} -{% if '' in bar %} -TRUE -{% endif %} -{% if '' in '' %} -TRUE -{% endif %} -{% if '0' not in '' %} -TRUE -{% endif %} -{% if 'a' not in '0' %} -TRUE -{% endif %} -{% if '0' in '0' %} -TRUE -{% endif %} - -{{ false in [0, 1] ? 'TRUE' : 'FALSE' }} -{{ true in [0, 1] ? 'TRUE' : 'FALSE' }} -{{ '0' in [0, 1] ? 'TRUE' : 'FALSE' }} -{{ '' in [0, 1] ? 'TRUE' : 'FALSE' }} -{{ 0 in ['', 1] ? 'TRUE' : 'FALSE' }} - -{{ '' in 'foo' ? 'TRUE' : 'FALSE' }} -{{ 0 in 'foo' ? 'TRUE' : 'FALSE' }} -{{ false in 'foo' ? 'TRUE' : 'FALSE' }} -{{ false in '100' ? 'TRUE' : 'FALSE' }} -{{ true in '100' ? 'TRUE' : 'FALSE' }} - -{{ [] in [true, false] ? 'TRUE' : 'FALSE' }} -{{ [] in [true, ''] ? 'TRUE' : 'FALSE' }} -{{ [] in [true, []] ? 'TRUE' : 'FALSE' }} - -{{ resource ? 'TRUE' : 'FALSE' }} -{{ resource in 'foo'~resource ? 'TRUE' : 'FALSE' }} -{{ object in 'stdClass' ? 'TRUE' : 'FALSE' }} -{{ [] in 'Array' ? 'TRUE' : 'FALSE' }} -{{ dir_object in 'foo'~dir_object ? 'TRUE' : 'FALSE' }} - -{{ ''~resource in resource ? 'TRUE' : 'FALSE' }} -{{ 'stdClass' in object ? 'TRUE' : 'FALSE' }} -{{ 'Array' in [] ? 'TRUE' : 'FALSE' }} -{{ ''~dir_object in dir_object ? 'TRUE' : 'FALSE' }} - -{{ resource in [''~resource] ? 'TRUE' : 'FALSE' }} -{{ resource in [resource + 1 - 1] ? 'TRUE' : 'FALSE' }} -{{ dir_object in [''~dir_object] ? 'TRUE' : 'FALSE' }} - -{{ 5 in 125 ? 'TRUE' : 'FALSE' }} -{{ 5 in '125' ? 'TRUE' : 'FALSE' }} -{{ '5' in 125 ? 'TRUE' : 'FALSE' }} -{{ '5' in '125' ? 'TRUE' : 'FALSE' }} - -{{ 5.5 in 125.5 ? 'TRUE' : 'FALSE' }} -{{ 5.5 in '125.5' ? 'TRUE' : 'FALSE' }} -{{ '5.5' in 125.5 ? 'TRUE' : 'FALSE' }} ---DATA-- -return array('bar' => 'bar', 'foo' => array('bar' => 'bar'), 'dir_object' => new SplFileInfo(dirname(__FILE__)), 'object' => new stdClass(), 'resource' => opendir(dirname(__FILE__))) ---EXPECT-- -TRUE -TRUE -TRUE -TRUE -TRUE -TRUE -TRUE -TRUE -TRUE -TRUE - -TRUE -TRUE -TRUE -TRUE -TRUE - -TRUE -FALSE -FALSE -FALSE -FALSE - -TRUE -FALSE -TRUE - -TRUE -FALSE -FALSE -FALSE -FALSE - -FALSE -FALSE -FALSE -FALSE - -FALSE -FALSE -FALSE - -FALSE -TRUE -FALSE -TRUE - -FALSE -TRUE -FALSE diff --git a/vendor/twig/twig/test/Twig/Tests/LexerTest.php b/vendor/twig/twig/test/Twig/Tests/LexerTest.php deleted file mode 100644 index ffe9a235bf39077609cce3e408cd0a7093883e05..0000000000000000000000000000000000000000 --- a/vendor/twig/twig/test/Twig/Tests/LexerTest.php +++ /dev/null @@ -1,347 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ -class Twig_Tests_LexerTest extends \PHPUnit\Framework\TestCase -{ - /** - * @group legacy - */ - public function testLegacyConstructorSignature() - { - $lexer = new Twig_Lexer(new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock())); - $stream = $lexer->tokenize('{{ foo }}', 'foo'); - $this->assertEquals('foo', $stream->getFilename()); - $this->assertEquals('{{ foo }}', $stream->getSource()); - } - - public function testNameLabelForTag() - { - $template = '{% § %}'; - - $lexer = new Twig_Lexer(new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock())); - $stream = $lexer->tokenize(new Twig_Source($template, 'index')); - - $stream->expect(Twig_Token::BLOCK_START_TYPE); - $this->assertSame('§', $stream->expect(Twig_Token::NAME_TYPE)->getValue()); - } - - public function testNameLabelForFunction() - { - $template = '{{ §() }}'; - - $lexer = new Twig_Lexer(new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock())); - $stream = $lexer->tokenize(new Twig_Source($template, 'index')); - - $stream->expect(Twig_Token::VAR_START_TYPE); - $this->assertSame('§', $stream->expect(Twig_Token::NAME_TYPE)->getValue()); - } - - public function testBracketsNesting() - { - $template = '{{ {"a":{"b":"c"}} }}'; - - $this->assertEquals(2, $this->countToken($template, Twig_Token::PUNCTUATION_TYPE, '{')); - $this->assertEquals(2, $this->countToken($template, Twig_Token::PUNCTUATION_TYPE, '}')); - } - - protected function countToken($template, $type, $value = null) - { - $lexer = new Twig_Lexer(new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock())); - $stream = $lexer->tokenize(new Twig_Source($template, 'index')); - - $count = 0; - while (!$stream->isEOF()) { - $token = $stream->next(); - if ($type === $token->getType()) { - if (null === $value || $value === $token->getValue()) { - ++$count; - } - } - } - - return $count; - } - - public function testLineDirective() - { - $template = "foo\n" - ."bar\n" - ."{% line 10 %}\n" - ."{{\n" - ."baz\n" - ."}}\n"; - - $lexer = new Twig_Lexer(new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock())); - $stream = $lexer->tokenize(new Twig_Source($template, 'index')); - - // foo\nbar\n - $this->assertSame(1, $stream->expect(Twig_Token::TEXT_TYPE)->getLine()); - // \n (after {% line %}) - $this->assertSame(10, $stream->expect(Twig_Token::TEXT_TYPE)->getLine()); - // {{ - $this->assertSame(11, $stream->expect(Twig_Token::VAR_START_TYPE)->getLine()); - // baz - $this->assertSame(12, $stream->expect(Twig_Token::NAME_TYPE)->getLine()); - } - - public function testLineDirectiveInline() - { - $template = "foo\n" - ."bar{% line 10 %}{{\n" - ."baz\n" - ."}}\n"; - - $lexer = new Twig_Lexer(new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock())); - $stream = $lexer->tokenize(new Twig_Source($template, 'index')); - - // foo\nbar - $this->assertSame(1, $stream->expect(Twig_Token::TEXT_TYPE)->getLine()); - // {{ - $this->assertSame(10, $stream->expect(Twig_Token::VAR_START_TYPE)->getLine()); - // baz - $this->assertSame(11, $stream->expect(Twig_Token::NAME_TYPE)->getLine()); - } - - public function testLongComments() - { - $template = '{# '.str_repeat('*', 100000).' #}'; - - $lexer = new Twig_Lexer(new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock())); - $lexer->tokenize(new Twig_Source($template, 'index')); - - // add a dummy assertion here to satisfy PHPUnit, the only thing we want to test is that the code above - // can be executed without throwing any exceptions - $this->addToAssertionCount(1); - } - - public function testLongVerbatim() - { - $template = '{% verbatim %}'.str_repeat('*', 100000).'{% endverbatim %}'; - - $lexer = new Twig_Lexer(new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock())); - $lexer->tokenize(new Twig_Source($template, 'index')); - - // add a dummy assertion here to satisfy PHPUnit, the only thing we want to test is that the code above - // can be executed without throwing any exceptions - $this->addToAssertionCount(1); - } - - public function testLongVar() - { - $template = '{{ '.str_repeat('x', 100000).' }}'; - - $lexer = new Twig_Lexer(new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock())); - $lexer->tokenize(new Twig_Source($template, 'index')); - - // add a dummy assertion here to satisfy PHPUnit, the only thing we want to test is that the code above - // can be executed without throwing any exceptions - $this->addToAssertionCount(1); - } - - public function testLongBlock() - { - $template = '{% '.str_repeat('x', 100000).' %}'; - - $lexer = new Twig_Lexer(new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock())); - $lexer->tokenize(new Twig_Source($template, 'index')); - - // add a dummy assertion here to satisfy PHPUnit, the only thing we want to test is that the code above - // can be executed without throwing any exceptions - $this->addToAssertionCount(1); - } - - public function testBigNumbers() - { - $template = '{{ 922337203685477580700 }}'; - - $lexer = new Twig_Lexer(new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock())); - $stream = $lexer->tokenize(new Twig_Source($template, 'index')); - $stream->next(); - $node = $stream->next(); - $this->assertEquals('922337203685477580700', $node->getValue()); - } - - public function testStringWithEscapedDelimiter() - { - $tests = array( - "{{ 'foo \' bar' }}" => 'foo \' bar', - '{{ "foo \" bar" }}' => 'foo " bar', - ); - $lexer = new Twig_Lexer(new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock())); - foreach ($tests as $template => $expected) { - $stream = $lexer->tokenize(new Twig_Source($template, 'index')); - $stream->expect(Twig_Token::VAR_START_TYPE); - $stream->expect(Twig_Token::STRING_TYPE, $expected); - - // add a dummy assertion here to satisfy PHPUnit, the only thing we want to test is that the code above - // can be executed without throwing any exceptions - $this->addToAssertionCount(1); - } - } - - public function testStringWithInterpolation() - { - $template = 'foo {{ "bar #{ baz + 1 }" }}'; - - $lexer = new Twig_Lexer(new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock())); - $stream = $lexer->tokenize(new Twig_Source($template, 'index')); - $stream->expect(Twig_Token::TEXT_TYPE, 'foo '); - $stream->expect(Twig_Token::VAR_START_TYPE); - $stream->expect(Twig_Token::STRING_TYPE, 'bar '); - $stream->expect(Twig_Token::INTERPOLATION_START_TYPE); - $stream->expect(Twig_Token::NAME_TYPE, 'baz'); - $stream->expect(Twig_Token::OPERATOR_TYPE, '+'); - $stream->expect(Twig_Token::NUMBER_TYPE, '1'); - $stream->expect(Twig_Token::INTERPOLATION_END_TYPE); - $stream->expect(Twig_Token::VAR_END_TYPE); - - // add a dummy assertion here to satisfy PHPUnit, the only thing we want to test is that the code above - // can be executed without throwing any exceptions - $this->addToAssertionCount(1); - } - - public function testStringWithEscapedInterpolation() - { - $template = '{{ "bar \#{baz+1}" }}'; - - $lexer = new Twig_Lexer(new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock())); - $stream = $lexer->tokenize(new Twig_Source($template, 'index')); - $stream->expect(Twig_Token::VAR_START_TYPE); - $stream->expect(Twig_Token::STRING_TYPE, 'bar #{baz+1}'); - $stream->expect(Twig_Token::VAR_END_TYPE); - - // add a dummy assertion here to satisfy PHPUnit, the only thing we want to test is that the code above - // can be executed without throwing any exceptions - $this->addToAssertionCount(1); - } - - public function testStringWithHash() - { - $template = '{{ "bar # baz" }}'; - - $lexer = new Twig_Lexer(new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock())); - $stream = $lexer->tokenize(new Twig_Source($template, 'index')); - $stream->expect(Twig_Token::VAR_START_TYPE); - $stream->expect(Twig_Token::STRING_TYPE, 'bar # baz'); - $stream->expect(Twig_Token::VAR_END_TYPE); - - // add a dummy assertion here to satisfy PHPUnit, the only thing we want to test is that the code above - // can be executed without throwing any exceptions - $this->addToAssertionCount(1); - } - - /** - * @expectedException Twig_Error_Syntax - * @expectedExceptionMessage Unclosed """ - */ - public function testStringWithUnterminatedInterpolation() - { - $template = '{{ "bar #{x" }}'; - - $lexer = new Twig_Lexer(new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock())); - $lexer->tokenize(new Twig_Source($template, 'index')); - } - - public function testStringWithNestedInterpolations() - { - $template = '{{ "bar #{ "foo#{bar}" }" }}'; - - $lexer = new Twig_Lexer(new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock())); - $stream = $lexer->tokenize(new Twig_Source($template, 'index')); - $stream->expect(Twig_Token::VAR_START_TYPE); - $stream->expect(Twig_Token::STRING_TYPE, 'bar '); - $stream->expect(Twig_Token::INTERPOLATION_START_TYPE); - $stream->expect(Twig_Token::STRING_TYPE, 'foo'); - $stream->expect(Twig_Token::INTERPOLATION_START_TYPE); - $stream->expect(Twig_Token::NAME_TYPE, 'bar'); - $stream->expect(Twig_Token::INTERPOLATION_END_TYPE); - $stream->expect(Twig_Token::INTERPOLATION_END_TYPE); - $stream->expect(Twig_Token::VAR_END_TYPE); - - // add a dummy assertion here to satisfy PHPUnit, the only thing we want to test is that the code above - // can be executed without throwing any exceptions - $this->addToAssertionCount(1); - } - - public function testStringWithNestedInterpolationsInBlock() - { - $template = '{% foo "bar #{ "foo#{bar}" }" %}'; - - $lexer = new Twig_Lexer(new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock())); - $stream = $lexer->tokenize(new Twig_Source($template, 'index')); - $stream->expect(Twig_Token::BLOCK_START_TYPE); - $stream->expect(Twig_Token::NAME_TYPE, 'foo'); - $stream->expect(Twig_Token::STRING_TYPE, 'bar '); - $stream->expect(Twig_Token::INTERPOLATION_START_TYPE); - $stream->expect(Twig_Token::STRING_TYPE, 'foo'); - $stream->expect(Twig_Token::INTERPOLATION_START_TYPE); - $stream->expect(Twig_Token::NAME_TYPE, 'bar'); - $stream->expect(Twig_Token::INTERPOLATION_END_TYPE); - $stream->expect(Twig_Token::INTERPOLATION_END_TYPE); - $stream->expect(Twig_Token::BLOCK_END_TYPE); - - // add a dummy assertion here to satisfy PHPUnit, the only thing we want to test is that the code above - // can be executed without throwing any exceptions - $this->addToAssertionCount(1); - } - - public function testOperatorEndingWithALetterAtTheEndOfALine() - { - $template = "{{ 1 and\n0}}"; - - $lexer = new Twig_Lexer(new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock())); - $stream = $lexer->tokenize(new Twig_Source($template, 'index')); - $stream->expect(Twig_Token::VAR_START_TYPE); - $stream->expect(Twig_Token::NUMBER_TYPE, 1); - $stream->expect(Twig_Token::OPERATOR_TYPE, 'and'); - - // add a dummy assertion here to satisfy PHPUnit, the only thing we want to test is that the code above - // can be executed without throwing any exceptions - $this->addToAssertionCount(1); - } - - /** - * @expectedException Twig_Error_Syntax - * @expectedExceptionMessage Unclosed "variable" in "index" at line 3 - */ - public function testUnterminatedVariable() - { - $template = ' - -{{ - -bar - - -'; - - $lexer = new Twig_Lexer(new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock())); - $lexer->tokenize(new Twig_Source($template, 'index')); - } - - /** - * @expectedException Twig_Error_Syntax - * @expectedExceptionMessage Unclosed "block" in "index" at line 3 - */ - public function testUnterminatedBlock() - { - $template = ' - -{% - -bar - - -'; - - $lexer = new Twig_Lexer(new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock())); - $lexer->tokenize(new Twig_Source($template, 'index')); - } -} diff --git a/vendor/twig/twig/test/Twig/Tests/Loader/FilesystemTest.php b/vendor/twig/twig/test/Twig/Tests/Loader/FilesystemTest.php deleted file mode 100644 index bd2acbd75f45c83d7e23a6b4eae3e555ad106946..0000000000000000000000000000000000000000 --- a/vendor/twig/twig/test/Twig/Tests/Loader/FilesystemTest.php +++ /dev/null @@ -1,226 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -class Twig_Tests_Loader_FilesystemTest extends \PHPUnit\Framework\TestCase -{ - public function testGetSourceContext() - { - $path = dirname(__FILE__).'/../Fixtures'; - $loader = new Twig_Loader_Filesystem(array($path)); - $this->assertEquals('errors/index.html', $loader->getSourceContext('errors/index.html')->getName()); - $this->assertEquals(realpath($path.'/errors/index.html'), realpath($loader->getSourceContext('errors/index.html')->getPath())); - } - - /** - * @dataProvider getSecurityTests - */ - public function testSecurity($template) - { - $loader = new Twig_Loader_Filesystem(array(dirname(__FILE__).'/../Fixtures')); - - try { - $loader->getCacheKey($template); - $this->fail(); - } catch (Twig_Error_Loader $e) { - $this->assertNotContains('Unable to find template', $e->getMessage()); - } - } - - public function getSecurityTests() - { - return array( - array("AutoloaderTest\0.php"), - array('..\\AutoloaderTest.php'), - array('..\\\\\\AutoloaderTest.php'), - array('../AutoloaderTest.php'), - array('..////AutoloaderTest.php'), - array('./../AutoloaderTest.php'), - array('.\\..\\AutoloaderTest.php'), - array('././././././../AutoloaderTest.php'), - array('.\\./.\\./.\\./../AutoloaderTest.php'), - array('foo/../../AutoloaderTest.php'), - array('foo\\..\\..\\AutoloaderTest.php'), - array('foo/../bar/../../AutoloaderTest.php'), - array('foo/bar/../../../AutoloaderTest.php'), - array('filters/../../AutoloaderTest.php'), - array('filters//..//..//AutoloaderTest.php'), - array('filters\\..\\..\\AutoloaderTest.php'), - array('filters\\\\..\\\\..\\\\AutoloaderTest.php'), - array('filters\\//../\\/\\..\\AutoloaderTest.php'), - array('/../AutoloaderTest.php'), - ); - } - - /** - * @dataProvider getBasePaths - */ - public function testPaths($basePath, $cacheKey, $rootPath) - { - $loader = new Twig_Loader_Filesystem(array($basePath.'/normal', $basePath.'/normal_bis'), $rootPath); - $loader->setPaths(array($basePath.'/named', $basePath.'/named_bis'), 'named'); - $loader->addPath($basePath.'/named_ter', 'named'); - $loader->addPath($basePath.'/normal_ter'); - $loader->prependPath($basePath.'/normal_final'); - $loader->prependPath($basePath.'/named/../named_quater', 'named'); - $loader->prependPath($basePath.'/named_final', 'named'); - - $this->assertEquals(array( - $basePath.'/normal_final', - $basePath.'/normal', - $basePath.'/normal_bis', - $basePath.'/normal_ter', - ), $loader->getPaths()); - $this->assertEquals(array( - $basePath.'/named_final', - $basePath.'/named/../named_quater', - $basePath.'/named', - $basePath.'/named_bis', - $basePath.'/named_ter', - ), $loader->getPaths('named')); - - // do not use realpath here as it would make the test unuseful - $this->assertEquals($cacheKey, str_replace('\\', '/', $loader->getCacheKey('@named/named_absolute.html'))); - $this->assertEquals("path (final)\n", $loader->getSourceContext('index.html')->getCode()); - $this->assertEquals("path (final)\n", $loader->getSourceContext('@__main__/index.html')->getCode()); - $this->assertEquals("named path (final)\n", $loader->getSourceContext('@named/index.html')->getCode()); - } - - public function getBasePaths() - { - return array( - array( - dirname(__FILE__).'/Fixtures', - 'test/Twig/Tests/Loader/Fixtures/named_quater/named_absolute.html', - null, - ), - array( - dirname(__FILE__).'/Fixtures/../Fixtures', - 'test/Twig/Tests/Loader/Fixtures/named_quater/named_absolute.html', - null, - ), - array( - 'test/Twig/Tests/Loader/Fixtures', - 'test/Twig/Tests/Loader/Fixtures/named_quater/named_absolute.html', - getcwd(), - ), - array( - 'Fixtures', - 'Fixtures/named_quater/named_absolute.html', - getcwd().'/test/Twig/Tests/Loader', - ), - array( - 'Fixtures', - 'Fixtures/named_quater/named_absolute.html', - getcwd().'/test/../test/Twig/Tests/Loader', - ), - ); - } - - public function testEmptyConstructor() - { - $loader = new Twig_Loader_Filesystem(); - $this->assertEquals(array(), $loader->getPaths()); - } - - public function testGetNamespaces() - { - $loader = new Twig_Loader_Filesystem(sys_get_temp_dir()); - $this->assertEquals(array(Twig_Loader_Filesystem::MAIN_NAMESPACE), $loader->getNamespaces()); - - $loader->addPath(sys_get_temp_dir(), 'named'); - $this->assertEquals(array(Twig_Loader_Filesystem::MAIN_NAMESPACE, 'named'), $loader->getNamespaces()); - } - - public function testFindTemplateExceptionNamespace() - { - $basePath = dirname(__FILE__).'/Fixtures'; - - $loader = new Twig_Loader_Filesystem(array($basePath.'/normal')); - $loader->addPath($basePath.'/named', 'named'); - - try { - $loader->getSourceContext('@named/nowhere.html'); - } catch (Exception $e) { - $this->assertInstanceof('Twig_Error_Loader', $e); - $this->assertContains('Unable to find template "@named/nowhere.html"', $e->getMessage()); - } - } - - public function testFindTemplateWithCache() - { - $basePath = dirname(__FILE__).'/Fixtures'; - - $loader = new Twig_Loader_Filesystem(array($basePath.'/normal')); - $loader->addPath($basePath.'/named', 'named'); - - // prime the cache for index.html in the named namespace - $namedSource = $loader->getSourceContext('@named/index.html')->getCode(); - $this->assertEquals("named path\n", $namedSource); - - // get index.html from the main namespace - $this->assertEquals("path\n", $loader->getSourceContext('index.html')->getCode()); - } - - public function testLoadTemplateAndRenderBlockWithCache() - { - $loader = new Twig_Loader_Filesystem(array()); - $loader->addPath(dirname(__FILE__).'/Fixtures/themes/theme2'); - $loader->addPath(dirname(__FILE__).'/Fixtures/themes/theme1'); - $loader->addPath(dirname(__FILE__).'/Fixtures/themes/theme1', 'default_theme'); - - $twig = new Twig_Environment($loader); - - $template = $twig->loadTemplate('blocks.html.twig'); - $this->assertSame('block from theme 1', $template->renderBlock('b1', array())); - - $template = $twig->loadTemplate('blocks.html.twig'); - $this->assertSame('block from theme 2', $template->renderBlock('b2', array())); - } - - public function getArrayInheritanceTests() - { - return array( - 'valid array inheritance' => array('array_inheritance_valid_parent.html.twig'), - 'array inheritance with null first template' => array('array_inheritance_null_parent.html.twig'), - 'array inheritance with empty first template' => array('array_inheritance_empty_parent.html.twig'), - 'array inheritance with non-existent first template' => array('array_inheritance_nonexistent_parent.html.twig'), - ); - } - - /** - * @dataProvider getArrayInheritanceTests - * - * @param $templateName string Template name with array inheritance - */ - public function testArrayInheritance($templateName) - { - $loader = new Twig_Loader_Filesystem(array()); - $loader->addPath(dirname(__FILE__).'/Fixtures/inheritance'); - - $twig = new Twig_Environment($loader); - - $template = $twig->loadTemplate($templateName); - $this->assertSame('VALID Child', $template->renderBlock('body', array())); - } - - /** - * @requires PHP 5.3 - */ - public function testLoadTemplateFromPhar() - { - $loader = new Twig_Loader_Filesystem(array()); - // phar-sample.phar was created with the following script: - // $f = new Phar('phar-test.phar'); - // $f->addFromString('hello.twig', 'hello from phar'); - $loader->addPath('phar://'.dirname(__FILE__).'/Fixtures/phar/phar-sample.phar'); - $this->assertSame('hello from phar', $loader->getSourceContext('hello.twig')->getCode()); - } -} diff --git a/vendor/twig/twig/test/Twig/Tests/Node/AutoEscapeTest.php b/vendor/twig/twig/test/Twig/Tests/Node/AutoEscapeTest.php deleted file mode 100644 index 25d16023f2790c4c218c38d831fbd1acddd993b4..0000000000000000000000000000000000000000 --- a/vendor/twig/twig/test/Twig/Tests/Node/AutoEscapeTest.php +++ /dev/null @@ -1,32 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -class Twig_Tests_Node_AutoEscapeTest extends Twig_Test_NodeTestCase -{ - public function testConstructor() - { - $body = new Twig_Node(array(new Twig_Node_Text('foo', 1))); - $node = new Twig_Node_AutoEscape(true, $body, 1); - - $this->assertEquals($body, $node->getNode('body')); - $this->assertTrue($node->getAttribute('value')); - } - - public function getTests() - { - $body = new Twig_Node(array(new Twig_Node_Text('foo', 1))); - $node = new Twig_Node_AutoEscape(true, $body, 1); - - return array( - array($node, "// line 1\necho \"foo\";"), - ); - } -} diff --git a/vendor/twig/twig/test/Twig/Tests/Node/Expression/ArrayTest.php b/vendor/twig/twig/test/Twig/Tests/Node/Expression/ArrayTest.php deleted file mode 100644 index 4f83ab176f3238d0ccbb7fd61b997095668ed102..0000000000000000000000000000000000000000 --- a/vendor/twig/twig/test/Twig/Tests/Node/Expression/ArrayTest.php +++ /dev/null @@ -1,37 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -class Twig_Tests_Node_Expression_ArrayTest extends Twig_Test_NodeTestCase -{ - public function testConstructor() - { - $elements = array(new Twig_Node_Expression_Constant('foo', 1), $foo = new Twig_Node_Expression_Constant('bar', 1)); - $node = new Twig_Node_Expression_Array($elements, 1); - - $this->assertEquals($foo, $node->getNode(1)); - } - - public function getTests() - { - $elements = array( - new Twig_Node_Expression_Constant('foo', 1), - new Twig_Node_Expression_Constant('bar', 1), - - new Twig_Node_Expression_Constant('bar', 1), - new Twig_Node_Expression_Constant('foo', 1), - ); - $node = new Twig_Node_Expression_Array($elements, 1); - - return array( - array($node, 'array("foo" => "bar", "bar" => "foo")'), - ); - } -} diff --git a/vendor/twig/twig/test/Twig/Tests/Node/Expression/Binary/AddTest.php b/vendor/twig/twig/test/Twig/Tests/Node/Expression/Binary/AddTest.php deleted file mode 100644 index 02310a1b03f698c44cb83dab48ed7402cc608459..0000000000000000000000000000000000000000 --- a/vendor/twig/twig/test/Twig/Tests/Node/Expression/Binary/AddTest.php +++ /dev/null @@ -1,34 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -class Twig_Tests_Node_Expression_Binary_AddTest extends Twig_Test_NodeTestCase -{ - public function testConstructor() - { - $left = new Twig_Node_Expression_Constant(1, 1); - $right = new Twig_Node_Expression_Constant(2, 1); - $node = new Twig_Node_Expression_Binary_Add($left, $right, 1); - - $this->assertEquals($left, $node->getNode('left')); - $this->assertEquals($right, $node->getNode('right')); - } - - public function getTests() - { - $left = new Twig_Node_Expression_Constant(1, 1); - $right = new Twig_Node_Expression_Constant(2, 1); - $node = new Twig_Node_Expression_Binary_Add($left, $right, 1); - - return array( - array($node, '(1 + 2)'), - ); - } -} diff --git a/vendor/twig/twig/test/Twig/Tests/Node/Expression/Binary/AndTest.php b/vendor/twig/twig/test/Twig/Tests/Node/Expression/Binary/AndTest.php deleted file mode 100644 index 2df3c8e459663697e947e3eef8ea18c895ec6076..0000000000000000000000000000000000000000 --- a/vendor/twig/twig/test/Twig/Tests/Node/Expression/Binary/AndTest.php +++ /dev/null @@ -1,34 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -class Twig_Tests_Node_Expression_Binary_AndTest extends Twig_Test_NodeTestCase -{ - public function testConstructor() - { - $left = new Twig_Node_Expression_Constant(1, 1); - $right = new Twig_Node_Expression_Constant(2, 1); - $node = new Twig_Node_Expression_Binary_And($left, $right, 1); - - $this->assertEquals($left, $node->getNode('left')); - $this->assertEquals($right, $node->getNode('right')); - } - - public function getTests() - { - $left = new Twig_Node_Expression_Constant(1, 1); - $right = new Twig_Node_Expression_Constant(2, 1); - $node = new Twig_Node_Expression_Binary_And($left, $right, 1); - - return array( - array($node, '(1 && 2)'), - ); - } -} diff --git a/vendor/twig/twig/test/Twig/Tests/Node/Expression/Binary/ConcatTest.php b/vendor/twig/twig/test/Twig/Tests/Node/Expression/Binary/ConcatTest.php deleted file mode 100644 index 759e482898cc779589b2803abe59b371841c78ce..0000000000000000000000000000000000000000 --- a/vendor/twig/twig/test/Twig/Tests/Node/Expression/Binary/ConcatTest.php +++ /dev/null @@ -1,34 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -class Twig_Tests_Node_Expression_Binary_ConcatTest extends Twig_Test_NodeTestCase -{ - public function testConstructor() - { - $left = new Twig_Node_Expression_Constant(1, 1); - $right = new Twig_Node_Expression_Constant(2, 1); - $node = new Twig_Node_Expression_Binary_Concat($left, $right, 1); - - $this->assertEquals($left, $node->getNode('left')); - $this->assertEquals($right, $node->getNode('right')); - } - - public function getTests() - { - $left = new Twig_Node_Expression_Constant(1, 1); - $right = new Twig_Node_Expression_Constant(2, 1); - $node = new Twig_Node_Expression_Binary_Concat($left, $right, 1); - - return array( - array($node, '(1 . 2)'), - ); - } -} diff --git a/vendor/twig/twig/test/Twig/Tests/Node/Expression/Binary/DivTest.php b/vendor/twig/twig/test/Twig/Tests/Node/Expression/Binary/DivTest.php deleted file mode 100644 index 0e54b10a39c328293f6c2791d5afb0678a84afd1..0000000000000000000000000000000000000000 --- a/vendor/twig/twig/test/Twig/Tests/Node/Expression/Binary/DivTest.php +++ /dev/null @@ -1,34 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -class Twig_Tests_Node_Expression_Binary_DivTest extends Twig_Test_NodeTestCase -{ - public function testConstructor() - { - $left = new Twig_Node_Expression_Constant(1, 1); - $right = new Twig_Node_Expression_Constant(2, 1); - $node = new Twig_Node_Expression_Binary_Div($left, $right, 1); - - $this->assertEquals($left, $node->getNode('left')); - $this->assertEquals($right, $node->getNode('right')); - } - - public function getTests() - { - $left = new Twig_Node_Expression_Constant(1, 1); - $right = new Twig_Node_Expression_Constant(2, 1); - $node = new Twig_Node_Expression_Binary_Div($left, $right, 1); - - return array( - array($node, '(1 / 2)'), - ); - } -} diff --git a/vendor/twig/twig/test/Twig/Tests/Node/Expression/Binary/FloorDivTest.php b/vendor/twig/twig/test/Twig/Tests/Node/Expression/Binary/FloorDivTest.php deleted file mode 100644 index 5813dce6ee94b651a275fcbd59b8b5077a5d3f21..0000000000000000000000000000000000000000 --- a/vendor/twig/twig/test/Twig/Tests/Node/Expression/Binary/FloorDivTest.php +++ /dev/null @@ -1,34 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -class Twig_Tests_Node_Expression_Binary_FloorDivTest extends Twig_Test_NodeTestCase -{ - public function testConstructor() - { - $left = new Twig_Node_Expression_Constant(1, 1); - $right = new Twig_Node_Expression_Constant(2, 1); - $node = new Twig_Node_Expression_Binary_FloorDiv($left, $right, 1); - - $this->assertEquals($left, $node->getNode('left')); - $this->assertEquals($right, $node->getNode('right')); - } - - public function getTests() - { - $left = new Twig_Node_Expression_Constant(1, 1); - $right = new Twig_Node_Expression_Constant(2, 1); - $node = new Twig_Node_Expression_Binary_FloorDiv($left, $right, 1); - - return array( - array($node, '(int) floor((1 / 2))'), - ); - } -} diff --git a/vendor/twig/twig/test/Twig/Tests/Node/Expression/Binary/ModTest.php b/vendor/twig/twig/test/Twig/Tests/Node/Expression/Binary/ModTest.php deleted file mode 100644 index 4c663c7877b2f3ba5859c78da938a6bed3d9e38a..0000000000000000000000000000000000000000 --- a/vendor/twig/twig/test/Twig/Tests/Node/Expression/Binary/ModTest.php +++ /dev/null @@ -1,34 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -class Twig_Tests_Node_Expression_Binary_ModTest extends Twig_Test_NodeTestCase -{ - public function testConstructor() - { - $left = new Twig_Node_Expression_Constant(1, 1); - $right = new Twig_Node_Expression_Constant(2, 1); - $node = new Twig_Node_Expression_Binary_Mod($left, $right, 1); - - $this->assertEquals($left, $node->getNode('left')); - $this->assertEquals($right, $node->getNode('right')); - } - - public function getTests() - { - $left = new Twig_Node_Expression_Constant(1, 1); - $right = new Twig_Node_Expression_Constant(2, 1); - $node = new Twig_Node_Expression_Binary_Mod($left, $right, 1); - - return array( - array($node, '(1 % 2)'), - ); - } -} diff --git a/vendor/twig/twig/test/Twig/Tests/Node/Expression/Binary/MulTest.php b/vendor/twig/twig/test/Twig/Tests/Node/Expression/Binary/MulTest.php deleted file mode 100644 index e92c95e640132aa82c308ddb2e3efb7a0491c26c..0000000000000000000000000000000000000000 --- a/vendor/twig/twig/test/Twig/Tests/Node/Expression/Binary/MulTest.php +++ /dev/null @@ -1,34 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -class Twig_Tests_Node_Expression_Binary_MulTest extends Twig_Test_NodeTestCase -{ - public function testConstructor() - { - $left = new Twig_Node_Expression_Constant(1, 1); - $right = new Twig_Node_Expression_Constant(2, 1); - $node = new Twig_Node_Expression_Binary_Mul($left, $right, 1); - - $this->assertEquals($left, $node->getNode('left')); - $this->assertEquals($right, $node->getNode('right')); - } - - public function getTests() - { - $left = new Twig_Node_Expression_Constant(1, 1); - $right = new Twig_Node_Expression_Constant(2, 1); - $node = new Twig_Node_Expression_Binary_Mul($left, $right, 1); - - return array( - array($node, '(1 * 2)'), - ); - } -} diff --git a/vendor/twig/twig/test/Twig/Tests/Node/Expression/Binary/OrTest.php b/vendor/twig/twig/test/Twig/Tests/Node/Expression/Binary/OrTest.php deleted file mode 100644 index ec37c83ebbfaf48a2ef5d6ea1c8662908daed5e8..0000000000000000000000000000000000000000 --- a/vendor/twig/twig/test/Twig/Tests/Node/Expression/Binary/OrTest.php +++ /dev/null @@ -1,34 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -class Twig_Tests_Node_Expression_Binary_OrTest extends Twig_Test_NodeTestCase -{ - public function testConstructor() - { - $left = new Twig_Node_Expression_Constant(1, 1); - $right = new Twig_Node_Expression_Constant(2, 1); - $node = new Twig_Node_Expression_Binary_Or($left, $right, 1); - - $this->assertEquals($left, $node->getNode('left')); - $this->assertEquals($right, $node->getNode('right')); - } - - public function getTests() - { - $left = new Twig_Node_Expression_Constant(1, 1); - $right = new Twig_Node_Expression_Constant(2, 1); - $node = new Twig_Node_Expression_Binary_Or($left, $right, 1); - - return array( - array($node, '(1 || 2)'), - ); - } -} diff --git a/vendor/twig/twig/test/Twig/Tests/Node/Expression/Binary/SubTest.php b/vendor/twig/twig/test/Twig/Tests/Node/Expression/Binary/SubTest.php deleted file mode 100644 index 061cb270f459057aae8a23a3a9aa8367f07382f3..0000000000000000000000000000000000000000 --- a/vendor/twig/twig/test/Twig/Tests/Node/Expression/Binary/SubTest.php +++ /dev/null @@ -1,34 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -class Twig_Tests_Node_Expression_Binary_SubTest extends Twig_Test_NodeTestCase -{ - public function testConstructor() - { - $left = new Twig_Node_Expression_Constant(1, 1); - $right = new Twig_Node_Expression_Constant(2, 1); - $node = new Twig_Node_Expression_Binary_Sub($left, $right, 1); - - $this->assertEquals($left, $node->getNode('left')); - $this->assertEquals($right, $node->getNode('right')); - } - - public function getTests() - { - $left = new Twig_Node_Expression_Constant(1, 1); - $right = new Twig_Node_Expression_Constant(2, 1); - $node = new Twig_Node_Expression_Binary_Sub($left, $right, 1); - - return array( - array($node, '(1 - 2)'), - ); - } -} diff --git a/vendor/twig/twig/test/Twig/Tests/Node/Expression/CallTest.php b/vendor/twig/twig/test/Twig/Tests/Node/Expression/CallTest.php deleted file mode 100644 index 883bb61273ccacda639eb2f5808d4f95d8f25e62..0000000000000000000000000000000000000000 --- a/vendor/twig/twig/test/Twig/Tests/Node/Expression/CallTest.php +++ /dev/null @@ -1,143 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -class Twig_Tests_Node_Expression_CallTest extends \PHPUnit\Framework\TestCase -{ - public function testGetArguments() - { - $node = new Twig_Tests_Node_Expression_Call(array(), array('type' => 'function', 'name' => 'date')); - $this->assertEquals(array('U', null), $node->getArguments('date', array('format' => 'U', 'timestamp' => null))); - } - - /** - * @expectedException Twig_Error_Syntax - * @expectedExceptionMessage Positional arguments cannot be used after named arguments for function "date". - */ - public function testGetArgumentsWhenPositionalArgumentsAfterNamedArguments() - { - $node = new Twig_Tests_Node_Expression_Call(array(), array('type' => 'function', 'name' => 'date')); - $node->getArguments('date', array('timestamp' => 123456, 'Y-m-d')); - } - - /** - * @expectedException Twig_Error_Syntax - * @expectedExceptionMessage Argument "format" is defined twice for function "date". - */ - public function testGetArgumentsWhenArgumentIsDefinedTwice() - { - $node = new Twig_Tests_Node_Expression_Call(array(), array('type' => 'function', 'name' => 'date')); - $node->getArguments('date', array('Y-m-d', 'format' => 'U')); - } - - /** - * @expectedException Twig_Error_Syntax - * @expectedExceptionMessage Unknown argument "unknown" for function "date(format, timestamp)". - */ - public function testGetArgumentsWithWrongNamedArgumentName() - { - $node = new Twig_Tests_Node_Expression_Call(array(), array('type' => 'function', 'name' => 'date')); - $node->getArguments('date', array('Y-m-d', 'timestamp' => null, 'unknown' => '')); - } - - /** - * @expectedException Twig_Error_Syntax - * @expectedExceptionMessage Unknown arguments "unknown1", "unknown2" for function "date(format, timestamp)". - */ - public function testGetArgumentsWithWrongNamedArgumentNames() - { - $node = new Twig_Tests_Node_Expression_Call(array(), array('type' => 'function', 'name' => 'date')); - $node->getArguments('date', array('Y-m-d', 'timestamp' => null, 'unknown1' => '', 'unknown2' => '')); - } - - /** - * @expectedException Twig_Error_Syntax - * @expectedExceptionMessage Argument "case_sensitivity" could not be assigned for function "substr_compare(main_str, str, offset, length, case_sensitivity)" because it is mapped to an internal PHP function which cannot determine default value for optional argument "length". - */ - public function testResolveArgumentsWithMissingValueForOptionalArgument() - { - $node = new Twig_Tests_Node_Expression_Call(array(), array('type' => 'function', 'name' => 'substr_compare')); - $node->getArguments('substr_compare', array('abcd', 'bc', 'offset' => 1, 'case_sensitivity' => true)); - } - - public function testResolveArgumentsOnlyNecessaryArgumentsForCustomFunction() - { - $node = new Twig_Tests_Node_Expression_Call(array(), array('type' => 'function', 'name' => 'custom_function')); - - $this->assertEquals(array('arg1'), $node->getArguments(array($this, 'customFunction'), array('arg1' => 'arg1'))); - } - - public function testGetArgumentsForStaticMethod() - { - $node = new Twig_Tests_Node_Expression_Call(array(), array('type' => 'function', 'name' => 'custom_static_function')); - $this->assertEquals(array('arg1'), $node->getArguments(__CLASS__.'::customStaticFunction', array('arg1' => 'arg1'))); - } - - /** - * @expectedException LogicException - * @expectedExceptionMessage The last parameter of "Twig_Tests_Node_Expression_CallTest::customFunctionWithArbitraryArguments" for function "foo" must be an array with default value, eg. "array $arg = array()". - */ - public function testResolveArgumentsWithMissingParameterForArbitraryArguments() - { - $node = new Twig_Tests_Node_Expression_Call(array(), array('type' => 'function', 'name' => 'foo', 'is_variadic' => true)); - $node->getArguments(array($this, 'customFunctionWithArbitraryArguments'), array()); - } - - public static function customStaticFunction($arg1, $arg2 = 'default', $arg3 = array()) - { - } - - public function customFunction($arg1, $arg2 = 'default', $arg3 = array()) - { - } - - public function customFunctionWithArbitraryArguments() - { - } - - /** - * @expectedException LogicException - * @expectedExceptionMessageRegExp #^The last parameter of "custom_Twig_Tests_Node_Expression_CallTest_function" for function "foo" must be an array with default value, eg\. "array \$arg \= array\(\)"\.$# - */ - public function testResolveArgumentsWithMissingParameterForArbitraryArgumentsOnFunction() - { - $node = new Twig_Tests_Node_Expression_Call(array(), array('type' => 'function', 'name' => 'foo', 'is_variadic' => true)); - $node->getArguments('custom_Twig_Tests_Node_Expression_CallTest_function', array()); - } - - /** - * @expectedException LogicException - * @expectedExceptionMessageRegExp #^The last parameter of "CallableTestClass\:\:__invoke" for function "foo" must be an array with default value, eg\. "array \$arg \= array\(\)"\.$# - */ - public function testResolveArgumentsWithMissingParameterForArbitraryArgumentsOnObject() - { - $node = new Twig_Tests_Node_Expression_Call(array(), array('type' => 'function', 'name' => 'foo', 'is_variadic' => true)); - $node->getArguments(new CallableTestClass(), array()); - } -} - -class Twig_Tests_Node_Expression_Call extends Twig_Node_Expression_Call -{ - public function getArguments($callable, $arguments) - { - return parent::getArguments($callable, $arguments); - } -} - -class CallableTestClass -{ - public function __invoke($required) - { - } -} - -function custom_Twig_Tests_Node_Expression_CallTest_function($required) -{ -} diff --git a/vendor/twig/twig/test/Twig/Tests/Node/Expression/ConditionalTest.php b/vendor/twig/twig/test/Twig/Tests/Node/Expression/ConditionalTest.php deleted file mode 100644 index a3e8badffa21fc677a9bfec7caa858739b73a299..0000000000000000000000000000000000000000 --- a/vendor/twig/twig/test/Twig/Tests/Node/Expression/ConditionalTest.php +++ /dev/null @@ -1,38 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -class Twig_Tests_Node_Expression_ConditionalTest extends Twig_Test_NodeTestCase -{ - public function testConstructor() - { - $expr1 = new Twig_Node_Expression_Constant(1, 1); - $expr2 = new Twig_Node_Expression_Constant(2, 1); - $expr3 = new Twig_Node_Expression_Constant(3, 1); - $node = new Twig_Node_Expression_Conditional($expr1, $expr2, $expr3, 1); - - $this->assertEquals($expr1, $node->getNode('expr1')); - $this->assertEquals($expr2, $node->getNode('expr2')); - $this->assertEquals($expr3, $node->getNode('expr3')); - } - - public function getTests() - { - $tests = array(); - - $expr1 = new Twig_Node_Expression_Constant(1, 1); - $expr2 = new Twig_Node_Expression_Constant(2, 1); - $expr3 = new Twig_Node_Expression_Constant(3, 1); - $node = new Twig_Node_Expression_Conditional($expr1, $expr2, $expr3, 1); - $tests[] = array($node, '((1) ? (2) : (3))'); - - return $tests; - } -} diff --git a/vendor/twig/twig/test/Twig/Tests/Node/Expression/FilterTest.php b/vendor/twig/twig/test/Twig/Tests/Node/Expression/FilterTest.php deleted file mode 100644 index 773375c941634dd51f0db0b3ecb2db65e327f5b3..0000000000000000000000000000000000000000 --- a/vendor/twig/twig/test/Twig/Tests/Node/Expression/FilterTest.php +++ /dev/null @@ -1,154 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -class Twig_Tests_Node_Expression_FilterTest extends Twig_Test_NodeTestCase -{ - public function testConstructor() - { - $expr = new Twig_Node_Expression_Constant('foo', 1); - $name = new Twig_Node_Expression_Constant('upper', 1); - $args = new Twig_Node(); - $node = new Twig_Node_Expression_Filter($expr, $name, $args, 1); - - $this->assertEquals($expr, $node->getNode('node')); - $this->assertEquals($name, $node->getNode('filter')); - $this->assertEquals($args, $node->getNode('arguments')); - } - - public function getTests() - { - $environment = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock()); - $environment->addFilter(new Twig_SimpleFilter('bar', 'bar', array('needs_environment' => true))); - $environment->addFilter(new Twig_SimpleFilter('barbar', 'twig_tests_filter_barbar', array('needs_context' => true, 'is_variadic' => true))); - - $tests = array(); - - $expr = new Twig_Node_Expression_Constant('foo', 1); - $node = $this->createFilter($expr, 'upper'); - $node = $this->createFilter($node, 'number_format', array(new Twig_Node_Expression_Constant(2, 1), new Twig_Node_Expression_Constant('.', 1), new Twig_Node_Expression_Constant(',', 1))); - - if (function_exists('mb_get_info')) { - $tests[] = array($node, 'twig_number_format_filter($this->env, twig_upper_filter($this->env, "foo"), 2, ".", ",")'); - } else { - $tests[] = array($node, 'twig_number_format_filter($this->env, strtoupper("foo"), 2, ".", ",")'); - } - - // named arguments - $date = new Twig_Node_Expression_Constant(0, 1); - $node = $this->createFilter($date, 'date', array( - 'timezone' => new Twig_Node_Expression_Constant('America/Chicago', 1), - 'format' => new Twig_Node_Expression_Constant('d/m/Y H:i:s P', 1), - )); - $tests[] = array($node, 'twig_date_format_filter($this->env, 0, "d/m/Y H:i:s P", "America/Chicago")'); - - // skip an optional argument - $date = new Twig_Node_Expression_Constant(0, 1); - $node = $this->createFilter($date, 'date', array( - 'timezone' => new Twig_Node_Expression_Constant('America/Chicago', 1), - )); - $tests[] = array($node, 'twig_date_format_filter($this->env, 0, null, "America/Chicago")'); - - // underscores vs camelCase for named arguments - $string = new Twig_Node_Expression_Constant('abc', 1); - $node = $this->createFilter($string, 'reverse', array( - 'preserve_keys' => new Twig_Node_Expression_Constant(true, 1), - )); - $tests[] = array($node, 'twig_reverse_filter($this->env, "abc", true)'); - $node = $this->createFilter($string, 'reverse', array( - 'preserveKeys' => new Twig_Node_Expression_Constant(true, 1), - )); - $tests[] = array($node, 'twig_reverse_filter($this->env, "abc", true)'); - - // filter as an anonymous function - if (PHP_VERSION_ID >= 50300) { - $node = $this->createFilter(new Twig_Node_Expression_Constant('foo', 1), 'anonymous'); - $tests[] = array($node, 'call_user_func_array($this->env->getFilter(\'anonymous\')->getCallable(), array("foo"))'); - } - - // needs environment - $node = $this->createFilter($string, 'bar'); - $tests[] = array($node, 'bar($this->env, "abc")', $environment); - - $node = $this->createFilter($string, 'bar', array(new Twig_Node_Expression_Constant('bar', 1))); - $tests[] = array($node, 'bar($this->env, "abc", "bar")', $environment); - - // arbitrary named arguments - $node = $this->createFilter($string, 'barbar'); - $tests[] = array($node, 'twig_tests_filter_barbar($context, "abc")', $environment); - - $node = $this->createFilter($string, 'barbar', array('foo' => new Twig_Node_Expression_Constant('bar', 1))); - $tests[] = array($node, 'twig_tests_filter_barbar($context, "abc", null, null, array("foo" => "bar"))', $environment); - - $node = $this->createFilter($string, 'barbar', array('arg2' => new Twig_Node_Expression_Constant('bar', 1))); - $tests[] = array($node, 'twig_tests_filter_barbar($context, "abc", null, "bar")', $environment); - - $node = $this->createFilter($string, 'barbar', array( - new Twig_Node_Expression_Constant('1', 1), - new Twig_Node_Expression_Constant('2', 1), - new Twig_Node_Expression_Constant('3', 1), - 'foo' => new Twig_Node_Expression_Constant('bar', 1), - )); - $tests[] = array($node, 'twig_tests_filter_barbar($context, "abc", "1", "2", array(0 => "3", "foo" => "bar"))', $environment); - - return $tests; - } - - /** - * @expectedException Twig_Error_Syntax - * @expectedExceptionMessage Unknown argument "foobar" for filter "date(format, timezone)" at line 1. - */ - public function testCompileWithWrongNamedArgumentName() - { - $date = new Twig_Node_Expression_Constant(0, 1); - $node = $this->createFilter($date, 'date', array( - 'foobar' => new Twig_Node_Expression_Constant('America/Chicago', 1), - )); - - $compiler = $this->getCompiler(); - $compiler->compile($node); - } - - /** - * @expectedException Twig_Error_Syntax - * @expectedExceptionMessage Value for argument "from" is required for filter "replace". - */ - public function testCompileWithMissingNamedArgument() - { - $value = new Twig_Node_Expression_Constant(0, 1); - $node = $this->createFilter($value, 'replace', array( - 'to' => new Twig_Node_Expression_Constant('foo', 1), - )); - - $compiler = $this->getCompiler(); - $compiler->compile($node); - } - - protected function createFilter($node, $name, array $arguments = array()) - { - $name = new Twig_Node_Expression_Constant($name, 1); - $arguments = new Twig_Node($arguments); - - return new Twig_Node_Expression_Filter($node, $name, $arguments, 1); - } - - protected function getEnvironment() - { - if (PHP_VERSION_ID >= 50300) { - return include 'PHP53/FilterInclude.php'; - } - - return parent::getEnvironment(); - } -} - -function twig_tests_filter_barbar($context, $string, $arg1 = null, $arg2 = null, array $args = array()) -{ -} diff --git a/vendor/twig/twig/test/Twig/Tests/Node/Expression/FunctionTest.php b/vendor/twig/twig/test/Twig/Tests/Node/Expression/FunctionTest.php deleted file mode 100644 index 2e82e2f11527429a5d4d8a6a6283f84c2636211a..0000000000000000000000000000000000000000 --- a/vendor/twig/twig/test/Twig/Tests/Node/Expression/FunctionTest.php +++ /dev/null @@ -1,110 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -class Twig_Tests_Node_Expression_FunctionTest extends Twig_Test_NodeTestCase -{ - public function testConstructor() - { - $name = 'function'; - $args = new Twig_Node(); - $node = new Twig_Node_Expression_Function($name, $args, 1); - - $this->assertEquals($name, $node->getAttribute('name')); - $this->assertEquals($args, $node->getNode('arguments')); - } - - public function getTests() - { - $environment = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock()); - $environment->addFunction(new Twig_SimpleFunction('foo', 'foo', array())); - $environment->addFunction(new Twig_SimpleFunction('bar', 'bar', array('needs_environment' => true))); - $environment->addFunction(new Twig_SimpleFunction('foofoo', 'foofoo', array('needs_context' => true))); - $environment->addFunction(new Twig_SimpleFunction('foobar', 'foobar', array('needs_environment' => true, 'needs_context' => true))); - $environment->addFunction(new Twig_SimpleFunction('barbar', 'twig_tests_function_barbar', array('is_variadic' => true))); - - $tests = array(); - - $node = $this->createFunction('foo'); - $tests[] = array($node, 'foo()', $environment); - - $node = $this->createFunction('foo', array(new Twig_Node_Expression_Constant('bar', 1), new Twig_Node_Expression_Constant('foobar', 1))); - $tests[] = array($node, 'foo("bar", "foobar")', $environment); - - $node = $this->createFunction('bar'); - $tests[] = array($node, 'bar($this->env)', $environment); - - $node = $this->createFunction('bar', array(new Twig_Node_Expression_Constant('bar', 1))); - $tests[] = array($node, 'bar($this->env, "bar")', $environment); - - $node = $this->createFunction('foofoo'); - $tests[] = array($node, 'foofoo($context)', $environment); - - $node = $this->createFunction('foofoo', array(new Twig_Node_Expression_Constant('bar', 1))); - $tests[] = array($node, 'foofoo($context, "bar")', $environment); - - $node = $this->createFunction('foobar'); - $tests[] = array($node, 'foobar($this->env, $context)', $environment); - - $node = $this->createFunction('foobar', array(new Twig_Node_Expression_Constant('bar', 1))); - $tests[] = array($node, 'foobar($this->env, $context, "bar")', $environment); - - // named arguments - $node = $this->createFunction('date', array( - 'timezone' => new Twig_Node_Expression_Constant('America/Chicago', 1), - 'date' => new Twig_Node_Expression_Constant(0, 1), - )); - $tests[] = array($node, 'twig_date_converter($this->env, 0, "America/Chicago")'); - - // arbitrary named arguments - $node = $this->createFunction('barbar'); - $tests[] = array($node, 'twig_tests_function_barbar()', $environment); - - $node = $this->createFunction('barbar', array('foo' => new Twig_Node_Expression_Constant('bar', 1))); - $tests[] = array($node, 'twig_tests_function_barbar(null, null, array("foo" => "bar"))', $environment); - - $node = $this->createFunction('barbar', array('arg2' => new Twig_Node_Expression_Constant('bar', 1))); - $tests[] = array($node, 'twig_tests_function_barbar(null, "bar")', $environment); - - $node = $this->createFunction('barbar', array( - new Twig_Node_Expression_Constant('1', 1), - new Twig_Node_Expression_Constant('2', 1), - new Twig_Node_Expression_Constant('3', 1), - 'foo' => new Twig_Node_Expression_Constant('bar', 1), - )); - $tests[] = array($node, 'twig_tests_function_barbar("1", "2", array(0 => "3", "foo" => "bar"))', $environment); - - // function as an anonymous function - if (PHP_VERSION_ID >= 50300) { - $node = $this->createFunction('anonymous', array(new Twig_Node_Expression_Constant('foo', 1))); - $tests[] = array($node, 'call_user_func_array($this->env->getFunction(\'anonymous\')->getCallable(), array("foo"))'); - } - - return $tests; - } - - protected function createFunction($name, array $arguments = array()) - { - return new Twig_Node_Expression_Function($name, new Twig_Node($arguments), 1); - } - - protected function getEnvironment() - { - if (PHP_VERSION_ID >= 50300) { - return include 'PHP53/FunctionInclude.php'; - } - - return parent::getEnvironment(); - } -} - -function twig_tests_function_barbar($arg1 = null, $arg2 = null, array $args = array()) -{ -} diff --git a/vendor/twig/twig/test/Twig/Tests/Node/Expression/GetAttrTest.php b/vendor/twig/twig/test/Twig/Tests/Node/Expression/GetAttrTest.php deleted file mode 100644 index 2764478c413d18b39f28a68fd109a9db1e535d21..0000000000000000000000000000000000000000 --- a/vendor/twig/twig/test/Twig/Tests/Node/Expression/GetAttrTest.php +++ /dev/null @@ -1,50 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -class Twig_Tests_Node_Expression_GetAttrTest extends Twig_Test_NodeTestCase -{ - public function testConstructor() - { - $expr = new Twig_Node_Expression_Name('foo', 1); - $attr = new Twig_Node_Expression_Constant('bar', 1); - $args = new Twig_Node_Expression_Array(array(), 1); - $args->addElement(new Twig_Node_Expression_Name('foo', 1)); - $args->addElement(new Twig_Node_Expression_Constant('bar', 1)); - $node = new Twig_Node_Expression_GetAttr($expr, $attr, $args, Twig_Template::ARRAY_CALL, 1); - - $this->assertEquals($expr, $node->getNode('node')); - $this->assertEquals($attr, $node->getNode('attribute')); - $this->assertEquals($args, $node->getNode('arguments')); - $this->assertEquals(Twig_Template::ARRAY_CALL, $node->getAttribute('type')); - } - - public function getTests() - { - $tests = array(); - - $expr = new Twig_Node_Expression_Name('foo', 1); - $attr = new Twig_Node_Expression_Constant('bar', 1); - $args = new Twig_Node_Expression_Array(array(), 1); - $node = new Twig_Node_Expression_GetAttr($expr, $attr, $args, Twig_Template::ANY_CALL, 1); - $tests[] = array($node, sprintf('%s%s, "bar", array())', $this->getAttributeGetter(), $this->getVariableGetter('foo', 1))); - - $node = new Twig_Node_Expression_GetAttr($expr, $attr, $args, Twig_Template::ARRAY_CALL, 1); - $tests[] = array($node, sprintf('%s%s, "bar", array(), "array")', $this->getAttributeGetter(), $this->getVariableGetter('foo', 1))); - - $args = new Twig_Node_Expression_Array(array(), 1); - $args->addElement(new Twig_Node_Expression_Name('foo', 1)); - $args->addElement(new Twig_Node_Expression_Constant('bar', 1)); - $node = new Twig_Node_Expression_GetAttr($expr, $attr, $args, Twig_Template::METHOD_CALL, 1); - $tests[] = array($node, sprintf('%s%s, "bar", array(0 => %s, 1 => "bar"), "method")', $this->getAttributeGetter(), $this->getVariableGetter('foo', 1), $this->getVariableGetter('foo'))); - - return $tests; - } -} diff --git a/vendor/twig/twig/test/Twig/Tests/Node/Expression/NameTest.php b/vendor/twig/twig/test/Twig/Tests/Node/Expression/NameTest.php deleted file mode 100644 index 70721a8bf6679b1918b239f0b88b39a8ce045592..0000000000000000000000000000000000000000 --- a/vendor/twig/twig/test/Twig/Tests/Node/Expression/NameTest.php +++ /dev/null @@ -1,43 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -class Twig_Tests_Node_Expression_NameTest extends Twig_Test_NodeTestCase -{ - public function testConstructor() - { - $node = new Twig_Node_Expression_Name('foo', 1); - - $this->assertEquals('foo', $node->getAttribute('name')); - } - - public function getTests() - { - $node = new Twig_Node_Expression_Name('foo', 1); - $context = new Twig_Node_Expression_Name('_context', 1); - - $env = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock(), array('strict_variables' => true)); - $env1 = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock(), array('strict_variables' => false)); - - if (PHP_VERSION_ID >= 70000) { - $output = '($context["foo"] ?? $this->getContext($context, "foo"))'; - } elseif (PHP_VERSION_ID >= 50400) { - $output = '(isset($context["foo"]) ? $context["foo"] : $this->getContext($context, "foo"))'; - } else { - $output = '$this->getContext($context, "foo")'; - } - - return array( - array($node, "// line 1\n".$output, $env), - array($node, $this->getVariableGetter('foo', 1), $env1), - array($context, "// line 1\n\$context"), - ); - } -} diff --git a/vendor/twig/twig/test/Twig/Tests/Node/Expression/NullCoalesceTest.php b/vendor/twig/twig/test/Twig/Tests/Node/Expression/NullCoalesceTest.php deleted file mode 100644 index a37490baf2946430032c3be87c6a2b1699882e5b..0000000000000000000000000000000000000000 --- a/vendor/twig/twig/test/Twig/Tests/Node/Expression/NullCoalesceTest.php +++ /dev/null @@ -1,31 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -class Twig_Tests_Node_Expression_NullCoalesceTest extends Twig_Test_NodeTestCase -{ - public function getTests() - { - $tests = array(); - - $left = new Twig_Node_Expression_Name('foo', 1); - $right = new Twig_Node_Expression_Constant(2, 1); - $node = new Twig_Node_Expression_NullCoalesce($left, $right, 1); - if (PHP_VERSION_ID >= 70000) { - $tests[] = array($node, "((// line 1\n\$context[\"foo\"]) ?? (2))"); - } elseif (PHP_VERSION_ID >= 50400) { - $tests[] = array($node, "(((// line 1\narray_key_exists(\"foo\", \$context) && !(null === (isset(\$context[\"foo\"]) ? \$context[\"foo\"] : null)))) ? ((isset(\$context[\"foo\"]) ? \$context[\"foo\"] : null)) : (2))"); - } else { - $tests[] = array($node, "(((// line 1\narray_key_exists(\"foo\", \$context) && !(null === \$this->getContext(\$context, \"foo\")))) ? (\$this->getContext(\$context, \"foo\")) : (2))"); - } - - return $tests; - } -} diff --git a/vendor/twig/twig/test/Twig/Tests/Node/Expression/PHP53/FilterInclude.php b/vendor/twig/twig/test/Twig/Tests/Node/Expression/PHP53/FilterInclude.php deleted file mode 100644 index b5394bcf42656b8085447bab6efc641d65a0ca47..0000000000000000000000000000000000000000 --- a/vendor/twig/twig/test/Twig/Tests/Node/Expression/PHP53/FilterInclude.php +++ /dev/null @@ -1,6 +0,0 @@ -<?php - -$env = new Twig_Environment(new Twig_Loader_Array(array())); -$env->addFilter(new Twig_SimpleFilter('anonymous', function () {})); - -return $env; diff --git a/vendor/twig/twig/test/Twig/Tests/Node/Expression/PHP53/FunctionInclude.php b/vendor/twig/twig/test/Twig/Tests/Node/Expression/PHP53/FunctionInclude.php deleted file mode 100644 index e8f68c7288c32607e219df0a48f193e8c3dacd09..0000000000000000000000000000000000000000 --- a/vendor/twig/twig/test/Twig/Tests/Node/Expression/PHP53/FunctionInclude.php +++ /dev/null @@ -1,6 +0,0 @@ -<?php - -$env = new Twig_Environment(new Twig_Loader_Array(array())); -$env->addFunction(new Twig_SimpleFunction('anonymous', function () {})); - -return $env; diff --git a/vendor/twig/twig/test/Twig/Tests/Node/Expression/PHP53/TestInclude.php b/vendor/twig/twig/test/Twig/Tests/Node/Expression/PHP53/TestInclude.php deleted file mode 100644 index 9f818bc411aa619e457d000e5565d58f1eef5fd0..0000000000000000000000000000000000000000 --- a/vendor/twig/twig/test/Twig/Tests/Node/Expression/PHP53/TestInclude.php +++ /dev/null @@ -1,6 +0,0 @@ -<?php - -$env = new Twig_Environment(new Twig_Loader_Array(array())); -$env->addTest(new Twig_SimpleTest('anonymous', function () {})); - -return $env; diff --git a/vendor/twig/twig/test/Twig/Tests/Node/Expression/TestTest.php b/vendor/twig/twig/test/Twig/Tests/Node/Expression/TestTest.php deleted file mode 100644 index a5f96d245113ec8362c2e498311fa21d7f397892..0000000000000000000000000000000000000000 --- a/vendor/twig/twig/test/Twig/Tests/Node/Expression/TestTest.php +++ /dev/null @@ -1,82 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -class Twig_Tests_Node_Expression_TestTest extends Twig_Test_NodeTestCase -{ - public function testConstructor() - { - $expr = new Twig_Node_Expression_Constant('foo', 1); - $name = new Twig_Node_Expression_Constant('null', 1); - $args = new Twig_Node(); - $node = new Twig_Node_Expression_Test($expr, $name, $args, 1); - - $this->assertEquals($expr, $node->getNode('node')); - $this->assertEquals($args, $node->getNode('arguments')); - $this->assertEquals($name, $node->getAttribute('name')); - } - - public function getTests() - { - $environment = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock()); - $environment->addTest(new Twig_SimpleTest('barbar', 'twig_tests_test_barbar', array('is_variadic' => true, 'need_context' => true))); - - $tests = array(); - - $expr = new Twig_Node_Expression_Constant('foo', 1); - $node = new Twig_Node_Expression_Test_Null($expr, 'null', new Twig_Node(array()), 1); - $tests[] = array($node, '(null === "foo")'); - - // test as an anonymous function - if (PHP_VERSION_ID >= 50300) { - $node = $this->createTest(new Twig_Node_Expression_Constant('foo', 1), 'anonymous', array(new Twig_Node_Expression_Constant('foo', 1))); - $tests[] = array($node, 'call_user_func_array($this->env->getTest(\'anonymous\')->getCallable(), array("foo", "foo"))'); - } - - // arbitrary named arguments - $string = new Twig_Node_Expression_Constant('abc', 1); - $node = $this->createTest($string, 'barbar'); - $tests[] = array($node, 'twig_tests_test_barbar("abc")', $environment); - - $node = $this->createTest($string, 'barbar', array('foo' => new Twig_Node_Expression_Constant('bar', 1))); - $tests[] = array($node, 'twig_tests_test_barbar("abc", null, null, array("foo" => "bar"))', $environment); - - $node = $this->createTest($string, 'barbar', array('arg2' => new Twig_Node_Expression_Constant('bar', 1))); - $tests[] = array($node, 'twig_tests_test_barbar("abc", null, "bar")', $environment); - - $node = $this->createTest($string, 'barbar', array( - new Twig_Node_Expression_Constant('1', 1), - new Twig_Node_Expression_Constant('2', 1), - new Twig_Node_Expression_Constant('3', 1), - 'foo' => new Twig_Node_Expression_Constant('bar', 1), - )); - $tests[] = array($node, 'twig_tests_test_barbar("abc", "1", "2", array(0 => "3", "foo" => "bar"))', $environment); - - return $tests; - } - - protected function createTest($node, $name, array $arguments = array()) - { - return new Twig_Node_Expression_Test($node, $name, new Twig_Node($arguments), 1); - } - - protected function getEnvironment() - { - if (PHP_VERSION_ID >= 50300) { - return include 'PHP53/TestInclude.php'; - } - - return parent::getEnvironment(); - } -} - -function twig_tests_test_barbar($string, $arg1 = null, $arg2 = null, array $args = array()) -{ -} diff --git a/vendor/twig/twig/test/Twig/Tests/Node/Expression/Unary/NegTest.php b/vendor/twig/twig/test/Twig/Tests/Node/Expression/Unary/NegTest.php deleted file mode 100644 index b63337117d9edd10f9966638e7012dc759c3d25f..0000000000000000000000000000000000000000 --- a/vendor/twig/twig/test/Twig/Tests/Node/Expression/Unary/NegTest.php +++ /dev/null @@ -1,32 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -class Twig_Tests_Node_Expression_Unary_NegTest extends Twig_Test_NodeTestCase -{ - public function testConstructor() - { - $expr = new Twig_Node_Expression_Constant(1, 1); - $node = new Twig_Node_Expression_Unary_Neg($expr, 1); - - $this->assertEquals($expr, $node->getNode('node')); - } - - public function getTests() - { - $node = new Twig_Node_Expression_Constant(1, 1); - $node = new Twig_Node_Expression_Unary_Neg($node, 1); - - return array( - array($node, '-1'), - array(new Twig_Node_Expression_Unary_Neg($node, 1), '- -1'), - ); - } -} diff --git a/vendor/twig/twig/test/Twig/Tests/Node/Expression/Unary/NotTest.php b/vendor/twig/twig/test/Twig/Tests/Node/Expression/Unary/NotTest.php deleted file mode 100644 index d7c6f85e789b273afdff3b7f4988858773fe62f2..0000000000000000000000000000000000000000 --- a/vendor/twig/twig/test/Twig/Tests/Node/Expression/Unary/NotTest.php +++ /dev/null @@ -1,31 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -class Twig_Tests_Node_Expression_Unary_NotTest extends Twig_Test_NodeTestCase -{ - public function testConstructor() - { - $expr = new Twig_Node_Expression_Constant(1, 1); - $node = new Twig_Node_Expression_Unary_Not($expr, 1); - - $this->assertEquals($expr, $node->getNode('node')); - } - - public function getTests() - { - $node = new Twig_Node_Expression_Constant(1, 1); - $node = new Twig_Node_Expression_Unary_Not($node, 1); - - return array( - array($node, '!1'), - ); - } -} diff --git a/vendor/twig/twig/test/Twig/Tests/Node/Expression/Unary/PosTest.php b/vendor/twig/twig/test/Twig/Tests/Node/Expression/Unary/PosTest.php deleted file mode 100644 index 057250f376565d12cdec00f0c638208e4fe29f69..0000000000000000000000000000000000000000 --- a/vendor/twig/twig/test/Twig/Tests/Node/Expression/Unary/PosTest.php +++ /dev/null @@ -1,31 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -class Twig_Tests_Node_Expression_Unary_PosTest extends Twig_Test_NodeTestCase -{ - public function testConstructor() - { - $expr = new Twig_Node_Expression_Constant(1, 1); - $node = new Twig_Node_Expression_Unary_Pos($expr, 1); - - $this->assertEquals($expr, $node->getNode('node')); - } - - public function getTests() - { - $node = new Twig_Node_Expression_Constant(1, 1); - $node = new Twig_Node_Expression_Unary_Pos($node, 1); - - return array( - array($node, '+1'), - ); - } -} diff --git a/vendor/twig/twig/test/Twig/Tests/Node/IfTest.php b/vendor/twig/twig/test/Twig/Tests/Node/IfTest.php deleted file mode 100644 index 4ab0e4cc71c970eb04e13d699eb7fcb0f5a1518e..0000000000000000000000000000000000000000 --- a/vendor/twig/twig/test/Twig/Tests/Node/IfTest.php +++ /dev/null @@ -1,88 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -class Twig_Tests_Node_IfTest extends Twig_Test_NodeTestCase -{ - public function testConstructor() - { - $t = new Twig_Node(array( - new Twig_Node_Expression_Constant(true, 1), - new Twig_Node_Print(new Twig_Node_Expression_Name('foo', 1), 1), - ), array(), 1); - $else = null; - $node = new Twig_Node_If($t, $else, 1); - - $this->assertEquals($t, $node->getNode('tests')); - $this->assertFalse($node->hasNode('else')); - - $else = new Twig_Node_Print(new Twig_Node_Expression_Name('bar', 1), 1); - $node = new Twig_Node_If($t, $else, 1); - $this->assertEquals($else, $node->getNode('else')); - } - - public function getTests() - { - $tests = array(); - - $t = new Twig_Node(array( - new Twig_Node_Expression_Constant(true, 1), - new Twig_Node_Print(new Twig_Node_Expression_Name('foo', 1), 1), - ), array(), 1); - $else = null; - $node = new Twig_Node_If($t, $else, 1); - - $tests[] = array($node, <<<EOF -// line 1 -if (true) { - echo {$this->getVariableGetter('foo')}; -} -EOF - ); - - $t = new Twig_Node(array( - new Twig_Node_Expression_Constant(true, 1), - new Twig_Node_Print(new Twig_Node_Expression_Name('foo', 1), 1), - new Twig_Node_Expression_Constant(false, 1), - new Twig_Node_Print(new Twig_Node_Expression_Name('bar', 1), 1), - ), array(), 1); - $else = null; - $node = new Twig_Node_If($t, $else, 1); - - $tests[] = array($node, <<<EOF -// line 1 -if (true) { - echo {$this->getVariableGetter('foo')}; -} elseif (false) { - echo {$this->getVariableGetter('bar')}; -} -EOF - ); - - $t = new Twig_Node(array( - new Twig_Node_Expression_Constant(true, 1), - new Twig_Node_Print(new Twig_Node_Expression_Name('foo', 1), 1), - ), array(), 1); - $else = new Twig_Node_Print(new Twig_Node_Expression_Name('bar', 1), 1); - $node = new Twig_Node_If($t, $else, 1); - - $tests[] = array($node, <<<EOF -// line 1 -if (true) { - echo {$this->getVariableGetter('foo')}; -} else { - echo {$this->getVariableGetter('bar')}; -} -EOF - ); - - return $tests; - } -} diff --git a/vendor/twig/twig/test/Twig/Tests/Node/ImportTest.php b/vendor/twig/twig/test/Twig/Tests/Node/ImportTest.php deleted file mode 100644 index 36525b251f88eea2ed88c0778bd49ab6afe2dc47..0000000000000000000000000000000000000000 --- a/vendor/twig/twig/test/Twig/Tests/Node/ImportTest.php +++ /dev/null @@ -1,40 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -class Twig_Tests_Node_ImportTest extends Twig_Test_NodeTestCase -{ - public function testConstructor() - { - $macro = new Twig_Node_Expression_Constant('foo.twig', 1); - $var = new Twig_Node_Expression_AssignName('macro', 1); - $node = new Twig_Node_Import($macro, $var, 1); - - $this->assertEquals($macro, $node->getNode('expr')); - $this->assertEquals($var, $node->getNode('var')); - } - - public function getTests() - { - $tests = array(); - - $macro = new Twig_Node_Expression_Constant('foo.twig', 1); - $var = new Twig_Node_Expression_AssignName('macro', 1); - $node = new Twig_Node_Import($macro, $var, 1); - - $tests[] = array($node, <<<EOF -// line 1 -\$context["macro"] = \$this->loadTemplate("foo.twig", null, 1); -EOF - ); - - return $tests; - } -} diff --git a/vendor/twig/twig/test/Twig/Tests/Node/IncludeTest.php b/vendor/twig/twig/test/Twig/Tests/Node/IncludeTest.php deleted file mode 100644 index d801f3387eb7bf714e97c92e5ab34c030603146b..0000000000000000000000000000000000000000 --- a/vendor/twig/twig/test/Twig/Tests/Node/IncludeTest.php +++ /dev/null @@ -1,83 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -class Twig_Tests_Node_IncludeTest extends Twig_Test_NodeTestCase -{ - public function testConstructor() - { - $expr = new Twig_Node_Expression_Constant('foo.twig', 1); - $node = new Twig_Node_Include($expr, null, false, false, 1); - - $this->assertFalse($node->hasNode('variables')); - $this->assertEquals($expr, $node->getNode('expr')); - $this->assertFalse($node->getAttribute('only')); - - $vars = new Twig_Node_Expression_Array(array(new Twig_Node_Expression_Constant('foo', 1), new Twig_Node_Expression_Constant(true, 1)), 1); - $node = new Twig_Node_Include($expr, $vars, true, false, 1); - $this->assertEquals($vars, $node->getNode('variables')); - $this->assertTrue($node->getAttribute('only')); - } - - public function getTests() - { - $tests = array(); - - $expr = new Twig_Node_Expression_Constant('foo.twig', 1); - $node = new Twig_Node_Include($expr, null, false, false, 1); - $tests[] = array($node, <<<EOF -// line 1 -\$this->loadTemplate("foo.twig", null, 1)->display(\$context); -EOF - ); - - $expr = new Twig_Node_Expression_Conditional( - new Twig_Node_Expression_Constant(true, 1), - new Twig_Node_Expression_Constant('foo', 1), - new Twig_Node_Expression_Constant('foo', 1), - 0 - ); - $node = new Twig_Node_Include($expr, null, false, false, 1); - $tests[] = array($node, <<<EOF -// line 1 -\$this->loadTemplate(((true) ? ("foo") : ("foo")), null, 1)->display(\$context); -EOF - ); - - $expr = new Twig_Node_Expression_Constant('foo.twig', 1); - $vars = new Twig_Node_Expression_Array(array(new Twig_Node_Expression_Constant('foo', 1), new Twig_Node_Expression_Constant(true, 1)), 1); - $node = new Twig_Node_Include($expr, $vars, false, false, 1); - $tests[] = array($node, <<<EOF -// line 1 -\$this->loadTemplate("foo.twig", null, 1)->display(array_merge(\$context, array("foo" => true))); -EOF - ); - - $node = new Twig_Node_Include($expr, $vars, true, false, 1); - $tests[] = array($node, <<<EOF -// line 1 -\$this->loadTemplate("foo.twig", null, 1)->display(array("foo" => true)); -EOF - ); - - $node = new Twig_Node_Include($expr, $vars, true, true, 1); - $tests[] = array($node, <<<EOF -// line 1 -try { - \$this->loadTemplate("foo.twig", null, 1)->display(array("foo" => true)); -} catch (Twig_Error_Loader \$e) { - // ignore missing template -} -EOF - ); - - return $tests; - } -} diff --git a/vendor/twig/twig/test/Twig/Tests/Node/MacroTest.php b/vendor/twig/twig/test/Twig/Tests/Node/MacroTest.php deleted file mode 100644 index c7edfa251641d7b52a118af2ebbd179902683ae2..0000000000000000000000000000000000000000 --- a/vendor/twig/twig/test/Twig/Tests/Node/MacroTest.php +++ /dev/null @@ -1,74 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -class Twig_Tests_Node_MacroTest extends Twig_Test_NodeTestCase -{ - public function testConstructor() - { - $body = new Twig_Node_Text('foo', 1); - $arguments = new Twig_Node(array(new Twig_Node_Expression_Name('foo', 1)), array(), 1); - $node = new Twig_Node_Macro('foo', $body, $arguments, 1); - - $this->assertEquals($body, $node->getNode('body')); - $this->assertEquals($arguments, $node->getNode('arguments')); - $this->assertEquals('foo', $node->getAttribute('name')); - } - - public function getTests() - { - $body = new Twig_Node_Text('foo', 1); - $arguments = new Twig_Node(array( - 'foo' => new Twig_Node_Expression_Constant(null, 1), - 'bar' => new Twig_Node_Expression_Constant('Foo', 1), - ), array(), 1); - $node = new Twig_Node_Macro('foo', $body, $arguments, 1); - - if (PHP_VERSION_ID >= 50600) { - $declaration = ', ...$__varargs__'; - $varargs = '$__varargs__'; - } else { - $declaration = ''; - $varargs = 'func_num_args() > 2 ? array_slice(func_get_args(), 2) : array()'; - } - - return array( - array($node, <<<EOF -// line 1 -public function getfoo(\$__foo__ = null, \$__bar__ = "Foo"$declaration) -{ - \$context = \$this->env->mergeGlobals(array( - "foo" => \$__foo__, - "bar" => \$__bar__, - "varargs" => $varargs, - )); - - \$blocks = array(); - - ob_start(); - try { - echo "foo"; - } catch (Exception \$e) { - ob_end_clean(); - - throw \$e; - } catch (Throwable \$e) { - ob_end_clean(); - - throw \$e; - } - - return ('' === \$tmp = ob_get_clean()) ? '' : new Twig_Markup(\$tmp, \$this->env->getCharset()); -} -EOF - ), - ); - } -} diff --git a/vendor/twig/twig/test/Twig/Tests/Node/ModuleTest.php b/vendor/twig/twig/test/Twig/Tests/Node/ModuleTest.php deleted file mode 100644 index 54a8989c73c9f433692aee80a2f280c5471f4f22..0000000000000000000000000000000000000000 --- a/vendor/twig/twig/test/Twig/Tests/Node/ModuleTest.php +++ /dev/null @@ -1,223 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -class Twig_Tests_Node_ModuleTest extends Twig_Test_NodeTestCase -{ - public function testConstructor() - { - $body = new Twig_Node_Text('foo', 1); - $parent = new Twig_Node_Expression_Constant('layout.twig', 1); - $blocks = new Twig_Node(); - $macros = new Twig_Node(); - $traits = new Twig_Node(); - $source = new Twig_Source('{{ foo }}', 'foo.twig'); - $node = new Twig_Node_Module($body, $parent, $blocks, $macros, $traits, new Twig_Node(array()), $source); - - $this->assertEquals($body, $node->getNode('body')); - $this->assertEquals($blocks, $node->getNode('blocks')); - $this->assertEquals($macros, $node->getNode('macros')); - $this->assertEquals($parent, $node->getNode('parent')); - $this->assertEquals($source->getName(), $node->getTemplateName()); - } - - public function getTests() - { - $twig = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock()); - - $tests = array(); - - $body = new Twig_Node_Text('foo', 1); - $extends = null; - $blocks = new Twig_Node(); - $macros = new Twig_Node(); - $traits = new Twig_Node(); - $source = new Twig_Source('{{ foo }}', 'foo.twig'); - - $node = new Twig_Node_Module($body, $extends, $blocks, $macros, $traits, new Twig_Node(array()), $source); - $tests[] = array($node, <<<EOF -<?php - -/* foo.twig */ -class __TwigTemplate_%x extends Twig_Template -{ - public function __construct(Twig_Environment \$env) - { - parent::__construct(\$env); - - \$this->parent = false; - - \$this->blocks = array( - ); - } - - protected function doDisplay(array \$context, array \$blocks = array()) - { - // line 1 - echo "foo"; - } - - public function getTemplateName() - { - return "foo.twig"; - } - - public function getDebugInfo() - { - return array ( 19 => 1,); - } - - /** @deprecated since 1.27 (to be removed in 2.0). Use getSourceContext() instead */ - public function getSource() - { - @trigger_error('The '.__METHOD__.' method is deprecated since version 1.27 and will be removed in 2.0. Use getSourceContext() instead.', E_USER_DEPRECATED); - - return \$this->getSourceContext()->getCode(); - } - - public function getSourceContext() - { - return new Twig_Source("", "foo.twig", ""); - } -} -EOF - , $twig, true); - - $import = new Twig_Node_Import(new Twig_Node_Expression_Constant('foo.twig', 1), new Twig_Node_Expression_AssignName('macro', 1), 2); - - $body = new Twig_Node(array($import)); - $extends = new Twig_Node_Expression_Constant('layout.twig', 1); - - $node = new Twig_Node_Module($body, $extends, $blocks, $macros, $traits, new Twig_Node(array()), $source); - $tests[] = array($node, <<<EOF -<?php - -/* foo.twig */ -class __TwigTemplate_%x extends Twig_Template -{ - public function __construct(Twig_Environment \$env) - { - parent::__construct(\$env); - - // line 1 - \$this->parent = \$this->loadTemplate("layout.twig", "foo.twig", 1); - \$this->blocks = array( - ); - } - - protected function doGetParent(array \$context) - { - return "layout.twig"; - } - - protected function doDisplay(array \$context, array \$blocks = array()) - { - // line 2 - \$context["macro"] = \$this->loadTemplate("foo.twig", "foo.twig", 2); - // line 1 - \$this->parent->display(\$context, array_merge(\$this->blocks, \$blocks)); - } - - public function getTemplateName() - { - return "foo.twig"; - } - - public function isTraitable() - { - return false; - } - - public function getDebugInfo() - { - return array ( 26 => 1, 24 => 2, 11 => 1,); - } - - /** @deprecated since 1.27 (to be removed in 2.0). Use getSourceContext() instead */ - public function getSource() - { - @trigger_error('The '.__METHOD__.' method is deprecated since version 1.27 and will be removed in 2.0. Use getSourceContext() instead.', E_USER_DEPRECATED); - - return \$this->getSourceContext()->getCode(); - } - - public function getSourceContext() - { - return new Twig_Source("", "foo.twig", ""); - } -} -EOF - , $twig, true); - - $set = new Twig_Node_Set(false, new Twig_Node(array(new Twig_Node_Expression_AssignName('foo', 4))), new Twig_Node(array(new Twig_Node_Expression_Constant('foo', 4))), 4); - $body = new Twig_Node(array($set)); - $extends = new Twig_Node_Expression_Conditional( - new Twig_Node_Expression_Constant(true, 2), - new Twig_Node_Expression_Constant('foo', 2), - new Twig_Node_Expression_Constant('foo', 2), - 2 - ); - - $twig = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock(), array('debug' => true)); - $node = new Twig_Node_Module($body, $extends, $blocks, $macros, $traits, new Twig_Node(array()), $source); - $tests[] = array($node, <<<EOF -<?php - -/* foo.twig */ -class __TwigTemplate_%x extends Twig_Template -{ - protected function doGetParent(array \$context) - { - // line 2 - return \$this->loadTemplate(((true) ? ("foo") : ("foo")), "foo.twig", 2); - } - - protected function doDisplay(array \$context, array \$blocks = array()) - { - // line 4 - \$context["foo"] = "foo"; - // line 2 - \$this->getParent(\$context)->display(\$context, array_merge(\$this->blocks, \$blocks)); - } - - public function getTemplateName() - { - return "foo.twig"; - } - - public function isTraitable() - { - return false; - } - - public function getDebugInfo() - { - return array ( 17 => 2, 15 => 4, 9 => 2,); - } - - /** @deprecated since 1.27 (to be removed in 2.0). Use getSourceContext() instead */ - public function getSource() - { - @trigger_error('The '.__METHOD__.' method is deprecated since version 1.27 and will be removed in 2.0. Use getSourceContext() instead.', E_USER_DEPRECATED); - - return \$this->getSourceContext()->getCode(); - } - - public function getSourceContext() - { - return new Twig_Source("{{ foo }}", "foo.twig", ""); - } -} -EOF - , $twig, true); - - return $tests; - } -} diff --git a/vendor/twig/twig/test/Twig/Tests/Node/PrintTest.php b/vendor/twig/twig/test/Twig/Tests/Node/PrintTest.php deleted file mode 100644 index 4e0990facce6cb53dc5ded191fb6d4f829f224d9..0000000000000000000000000000000000000000 --- a/vendor/twig/twig/test/Twig/Tests/Node/PrintTest.php +++ /dev/null @@ -1,29 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -class Twig_Tests_Node_PrintTest extends Twig_Test_NodeTestCase -{ - public function testConstructor() - { - $expr = new Twig_Node_Expression_Constant('foo', 1); - $node = new Twig_Node_Print($expr, 1); - - $this->assertEquals($expr, $node->getNode('expr')); - } - - public function getTests() - { - $tests = array(); - $tests[] = array(new Twig_Node_Print(new Twig_Node_Expression_Constant('foo', 1), 1), "// line 1\necho \"foo\";"); - - return $tests; - } -} diff --git a/vendor/twig/twig/test/Twig/Tests/Node/SandboxTest.php b/vendor/twig/twig/test/Twig/Tests/Node/SandboxTest.php deleted file mode 100644 index 56f48773027707a7be099fa8c2c3008d49c2a749..0000000000000000000000000000000000000000 --- a/vendor/twig/twig/test/Twig/Tests/Node/SandboxTest.php +++ /dev/null @@ -1,44 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -class Twig_Tests_Node_SandboxTest extends Twig_Test_NodeTestCase -{ - public function testConstructor() - { - $body = new Twig_Node_Text('foo', 1); - $node = new Twig_Node_Sandbox($body, 1); - - $this->assertEquals($body, $node->getNode('body')); - } - - public function getTests() - { - $tests = array(); - - $body = new Twig_Node_Text('foo', 1); - $node = new Twig_Node_Sandbox($body, 1); - - $tests[] = array($node, <<<EOF -// line 1 -\$sandbox = \$this->env->getExtension('Twig_Extension_Sandbox'); -if (!\$alreadySandboxed = \$sandbox->isSandboxed()) { - \$sandbox->enableSandbox(); -} -echo "foo"; -if (!\$alreadySandboxed) { - \$sandbox->disableSandbox(); -} -EOF - ); - - return $tests; - } -} diff --git a/vendor/twig/twig/test/Twig/Tests/Node/SandboxedPrintTest.php b/vendor/twig/twig/test/Twig/Tests/Node/SandboxedPrintTest.php deleted file mode 100644 index 8bc8a755c1f3668ef28bca09af18b6498cfba9ca..0000000000000000000000000000000000000000 --- a/vendor/twig/twig/test/Twig/Tests/Node/SandboxedPrintTest.php +++ /dev/null @@ -1,33 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -class Twig_Tests_Node_SandboxedPrintTest extends Twig_Test_NodeTestCase -{ - public function testConstructor() - { - $node = new Twig_Node_SandboxedPrint($expr = new Twig_Node_Expression_Constant('foo', 1), 1); - - $this->assertEquals($expr, $node->getNode('expr')); - } - - public function getTests() - { - $tests = array(); - - $tests[] = array(new Twig_Node_SandboxedPrint(new Twig_Node_Expression_Constant('foo', 1), 1), <<<EOF -// line 1 -echo \$this->env->getExtension('Twig_Extension_Sandbox')->ensureToStringAllowed("foo"); -EOF - ); - - return $tests; - } -} diff --git a/vendor/twig/twig/test/Twig/Tests/Node/SetTest.php b/vendor/twig/twig/test/Twig/Tests/Node/SetTest.php deleted file mode 100644 index 62ad2803ea24d7108288448d46dc1c99762d27fd..0000000000000000000000000000000000000000 --- a/vendor/twig/twig/test/Twig/Tests/Node/SetTest.php +++ /dev/null @@ -1,69 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -class Twig_Tests_Node_SetTest extends Twig_Test_NodeTestCase -{ - public function testConstructor() - { - $names = new Twig_Node(array(new Twig_Node_Expression_AssignName('foo', 1)), array(), 1); - $values = new Twig_Node(array(new Twig_Node_Expression_Constant('foo', 1)), array(), 1); - $node = new Twig_Node_Set(false, $names, $values, 1); - - $this->assertEquals($names, $node->getNode('names')); - $this->assertEquals($values, $node->getNode('values')); - $this->assertFalse($node->getAttribute('capture')); - } - - public function getTests() - { - $tests = array(); - - $names = new Twig_Node(array(new Twig_Node_Expression_AssignName('foo', 1)), array(), 1); - $values = new Twig_Node(array(new Twig_Node_Expression_Constant('foo', 1)), array(), 1); - $node = new Twig_Node_Set(false, $names, $values, 1); - $tests[] = array($node, <<<EOF -// line 1 -\$context["foo"] = "foo"; -EOF - ); - - $names = new Twig_Node(array(new Twig_Node_Expression_AssignName('foo', 1)), array(), 1); - $values = new Twig_Node(array(new Twig_Node_Print(new Twig_Node_Expression_Constant('foo', 1), 1)), array(), 1); - $node = new Twig_Node_Set(true, $names, $values, 1); - $tests[] = array($node, <<<EOF -// line 1 -ob_start(); -echo "foo"; -\$context["foo"] = ('' === \$tmp = ob_get_clean()) ? '' : new Twig_Markup(\$tmp, \$this->env->getCharset()); -EOF - ); - - $names = new Twig_Node(array(new Twig_Node_Expression_AssignName('foo', 1)), array(), 1); - $values = new Twig_Node_Text('foo', 1); - $node = new Twig_Node_Set(true, $names, $values, 1); - $tests[] = array($node, <<<EOF -// line 1 -\$context["foo"] = ('' === \$tmp = "foo") ? '' : new Twig_Markup(\$tmp, \$this->env->getCharset()); -EOF - ); - - $names = new Twig_Node(array(new Twig_Node_Expression_AssignName('foo', 1), new Twig_Node_Expression_AssignName('bar', 1)), array(), 1); - $values = new Twig_Node(array(new Twig_Node_Expression_Constant('foo', 1), new Twig_Node_Expression_Name('bar', 1)), array(), 1); - $node = new Twig_Node_Set(false, $names, $values, 1); - $tests[] = array($node, <<<EOF -// line 1 -list(\$context["foo"], \$context["bar"]) = array("foo", {$this->getVariableGetter('bar')}); -EOF - ); - - return $tests; - } -} diff --git a/vendor/twig/twig/test/Twig/Tests/Node/SpacelessTest.php b/vendor/twig/twig/test/Twig/Tests/Node/SpacelessTest.php deleted file mode 100644 index 222ca0920730fc68ad112a8012e1f4f30070fd92..0000000000000000000000000000000000000000 --- a/vendor/twig/twig/test/Twig/Tests/Node/SpacelessTest.php +++ /dev/null @@ -1,37 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -class Twig_Tests_Node_SpacelessTest extends Twig_Test_NodeTestCase -{ - public function testConstructor() - { - $body = new Twig_Node(array(new Twig_Node_Text('<div> <div> foo </div> </div>', 1))); - $node = new Twig_Node_Spaceless($body, 1); - - $this->assertEquals($body, $node->getNode('body')); - } - - public function getTests() - { - $body = new Twig_Node(array(new Twig_Node_Text('<div> <div> foo </div> </div>', 1))); - $node = new Twig_Node_Spaceless($body, 1); - - return array( - array($node, <<<EOF -// line 1 -ob_start(); -echo "<div> <div> foo </div> </div>"; -echo trim(preg_replace('/>\s+</', '><', ob_get_clean())); -EOF - ), - ); - } -} diff --git a/vendor/twig/twig/test/Twig/Tests/NodeVisitor/OptimizerTest.php b/vendor/twig/twig/test/Twig/Tests/NodeVisitor/OptimizerTest.php deleted file mode 100644 index 92c0ecac79d1501f046184c6c42e197c016fabe3..0000000000000000000000000000000000000000 --- a/vendor/twig/twig/test/Twig/Tests/NodeVisitor/OptimizerTest.php +++ /dev/null @@ -1,124 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ -class Twig_Tests_NodeVisitor_OptimizerTest extends \PHPUnit\Framework\TestCase -{ - public function testRenderBlockOptimizer() - { - $env = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock(), array('cache' => false, 'autoescape' => false)); - - $stream = $env->parse($env->tokenize(new Twig_Source('{{ block("foo") }}', 'index'))); - - $node = $stream->getNode('body')->getNode(0); - - $this->assertEquals('Twig_Node_Expression_BlockReference', get_class($node)); - $this->assertTrue($node->getAttribute('output')); - } - - public function testRenderParentBlockOptimizer() - { - $env = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock(), array('cache' => false, 'autoescape' => false)); - - $stream = $env->parse($env->tokenize(new Twig_Source('{% extends "foo" %}{% block content %}{{ parent() }}{% endblock %}', 'index'))); - - $node = $stream->getNode('blocks')->getNode('content')->getNode(0)->getNode('body'); - - $this->assertEquals('Twig_Node_Expression_Parent', get_class($node)); - $this->assertTrue($node->getAttribute('output')); - } - - public function testRenderVariableBlockOptimizer() - { - if (PHP_VERSION_ID >= 50400) { - $this->markTestSkipped('not needed on PHP >= 5.4'); - } - - $env = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock(), array('cache' => false, 'autoescape' => false)); - $stream = $env->parse($env->tokenize(new Twig_Source('{{ block(name|lower) }}', 'index'))); - - $node = $stream->getNode('body')->getNode(0)->getNode(1); - - $this->assertEquals('Twig_Node_Expression_BlockReference', get_class($node)); - $this->assertTrue($node->getAttribute('output')); - } - - /** - * @dataProvider getTestsForForOptimizer - */ - public function testForOptimizer($template, $expected) - { - $env = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock(), array('cache' => false)); - - $stream = $env->parse($env->tokenize(new Twig_Source($template, 'index'))); - - foreach ($expected as $target => $withLoop) { - $this->assertTrue($this->checkForConfiguration($stream, $target, $withLoop), sprintf('variable %s is %soptimized', $target, $withLoop ? 'not ' : '')); - } - } - - public function getTestsForForOptimizer() - { - return array( - array('{% for i in foo %}{% endfor %}', array('i' => false)), - - array('{% for i in foo %}{{ loop.index }}{% endfor %}', array('i' => true)), - - array('{% for i in foo %}{% for j in foo %}{% endfor %}{% endfor %}', array('i' => false, 'j' => false)), - - array('{% for i in foo %}{% include "foo" %}{% endfor %}', array('i' => true)), - - array('{% for i in foo %}{% include "foo" only %}{% endfor %}', array('i' => false)), - - array('{% for i in foo %}{% include "foo" with { "foo": "bar" } only %}{% endfor %}', array('i' => false)), - - array('{% for i in foo %}{% include "foo" with { "foo": loop.index } only %}{% endfor %}', array('i' => true)), - - array('{% for i in foo %}{% for j in foo %}{{ loop.index }}{% endfor %}{% endfor %}', array('i' => false, 'j' => true)), - - array('{% for i in foo %}{% for j in foo %}{{ loop.parent.loop.index }}{% endfor %}{% endfor %}', array('i' => true, 'j' => true)), - - array('{% for i in foo %}{% set l = loop %}{% for j in foo %}{{ l.index }}{% endfor %}{% endfor %}', array('i' => true, 'j' => false)), - - array('{% for i in foo %}{% for j in foo %}{{ foo.parent.loop.index }}{% endfor %}{% endfor %}', array('i' => false, 'j' => false)), - - array('{% for i in foo %}{% for j in foo %}{{ loop["parent"].loop.index }}{% endfor %}{% endfor %}', array('i' => true, 'j' => true)), - - array('{% for i in foo %}{{ include("foo") }}{% endfor %}', array('i' => true)), - - array('{% for i in foo %}{{ include("foo", with_context = false) }}{% endfor %}', array('i' => false)), - - array('{% for i in foo %}{{ include("foo", with_context = true) }}{% endfor %}', array('i' => true)), - - array('{% for i in foo %}{{ include("foo", { "foo": "bar" }, with_context = false) }}{% endfor %}', array('i' => false)), - - array('{% for i in foo %}{{ include("foo", { "foo": loop.index }, with_context = false) }}{% endfor %}', array('i' => true)), - ); - } - - public function checkForConfiguration(Twig_NodeInterface $node = null, $target, $withLoop) - { - if (null === $node) { - return; - } - - foreach ($node as $n) { - if ($n instanceof Twig_Node_For) { - if ($target === $n->getNode('value_target')->getAttribute('name')) { - return $withLoop == $n->getAttribute('with_loop'); - } - } - - $ret = $this->checkForConfiguration($n, $target, $withLoop); - if (null !== $ret) { - return $ret; - } - } - } -} diff --git a/vendor/twig/twig/test/Twig/Tests/ParserTest.php b/vendor/twig/twig/test/Twig/Tests/ParserTest.php deleted file mode 100644 index 342fb7bab78bcd69b3ef09d1ebe5b933f9c53f5f..0000000000000000000000000000000000000000 --- a/vendor/twig/twig/test/Twig/Tests/ParserTest.php +++ /dev/null @@ -1,198 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ -class Twig_Tests_ParserTest extends \PHPUnit\Framework\TestCase -{ - /** - * @expectedException Twig_Error_Syntax - */ - public function testSetMacroThrowsExceptionOnReservedMethods() - { - $parser = $this->getParser(); - $parser->setMacro('parent', $this->getMockBuilder('Twig_Node_Macro')->disableOriginalConstructor()->getMock()); - } - - /** - * @expectedException Twig_Error_Syntax - * @expectedExceptionMessage Unknown "foo" tag. Did you mean "for" at line 1? - */ - public function testUnknownTag() - { - $stream = new Twig_TokenStream(array( - new Twig_Token(Twig_Token::BLOCK_START_TYPE, '', 1), - new Twig_Token(Twig_Token::NAME_TYPE, 'foo', 1), - new Twig_Token(Twig_Token::BLOCK_END_TYPE, '', 1), - new Twig_Token(Twig_Token::EOF_TYPE, '', 1), - )); - $parser = new Twig_Parser(new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock())); - $parser->parse($stream); - } - - /** - * @expectedException Twig_Error_Syntax - * @expectedExceptionMessage Unknown "foobar" tag at line 1. - */ - public function testUnknownTagWithoutSuggestions() - { - $stream = new Twig_TokenStream(array( - new Twig_Token(Twig_Token::BLOCK_START_TYPE, '', 1), - new Twig_Token(Twig_Token::NAME_TYPE, 'foobar', 1), - new Twig_Token(Twig_Token::BLOCK_END_TYPE, '', 1), - new Twig_Token(Twig_Token::EOF_TYPE, '', 1), - )); - $parser = new Twig_Parser(new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock())); - $parser->parse($stream); - } - - /** - * @dataProvider getFilterBodyNodesData - */ - public function testFilterBodyNodes($input, $expected) - { - $parser = $this->getParser(); - - $this->assertEquals($expected, $parser->filterBodyNodes($input)); - } - - public function getFilterBodyNodesData() - { - return array( - array( - new Twig_Node(array(new Twig_Node_Text(' ', 1))), - new Twig_Node(array()), - ), - array( - $input = new Twig_Node(array(new Twig_Node_Set(false, new Twig_Node(), new Twig_Node(), 1))), - $input, - ), - array( - $input = new Twig_Node(array(new Twig_Node_Set(true, new Twig_Node(), new Twig_Node(array(new Twig_Node(array(new Twig_Node_Text('foo', 1))))), 1))), - $input, - ), - ); - } - - /** - * @dataProvider getFilterBodyNodesDataThrowsException - * @expectedException Twig_Error_Syntax - */ - public function testFilterBodyNodesThrowsException($input) - { - $parser = $this->getParser(); - - $parser->filterBodyNodes($input); - } - - public function getFilterBodyNodesDataThrowsException() - { - return array( - array(new Twig_Node_Text('foo', 1)), - array(new Twig_Node(array(new Twig_Node(array(new Twig_Node_Text('foo', 1)))))), - ); - } - - /** - * @expectedException Twig_Error_Syntax - * @expectedExceptionMessage A template that extends another one cannot start with a byte order mark (BOM); it must be removed at line 1 - */ - public function testFilterBodyNodesWithBOM() - { - $parser = $this->getParser(); - $parser->filterBodyNodes(new Twig_Node_Text(chr(0xEF).chr(0xBB).chr(0xBF), 1)); - } - - public function testParseIsReentrant() - { - $twig = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock(), array( - 'autoescape' => false, - 'optimizations' => 0, - )); - $twig->addTokenParser(new TestTokenParser()); - - $parser = new Twig_Parser($twig); - - $parser->parse(new Twig_TokenStream(array( - new Twig_Token(Twig_Token::BLOCK_START_TYPE, '', 1), - new Twig_Token(Twig_Token::NAME_TYPE, 'test', 1), - new Twig_Token(Twig_Token::BLOCK_END_TYPE, '', 1), - new Twig_Token(Twig_Token::VAR_START_TYPE, '', 1), - new Twig_Token(Twig_Token::NAME_TYPE, 'foo', 1), - new Twig_Token(Twig_Token::VAR_END_TYPE, '', 1), - new Twig_Token(Twig_Token::EOF_TYPE, '', 1), - ))); - - $this->assertNull($parser->getParent()); - } - - public function testGetVarName() - { - $twig = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock(), array( - 'autoescape' => false, - 'optimizations' => 0, - )); - - $twig->parse($twig->tokenize(new Twig_Source(<<<EOF -{% from _self import foo %} - -{% macro foo() %} - {{ foo }} -{% endmacro %} -EOF - , 'index'))); - - // The getVarName() must not depend on the template loaders, - // If this test does not throw any exception, that's good. - // see https://github.com/symfony/symfony/issues/4218 - $this->addToAssertionCount(1); - } - - protected function getParser() - { - $parser = new TestParser(new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock())); - $parser->setParent(new Twig_Node()); - $parser->stream = new Twig_TokenStream(array()); - - return $parser; - } -} - -class TestParser extends Twig_Parser -{ - public $stream; - - public function filterBodyNodes(Twig_NodeInterface $node) - { - return parent::filterBodyNodes($node); - } -} - -class TestTokenParser extends Twig_TokenParser -{ - public function parse(Twig_Token $token) - { - // simulate the parsing of another template right in the middle of the parsing of the current template - $this->parser->parse(new Twig_TokenStream(array( - new Twig_Token(Twig_Token::BLOCK_START_TYPE, '', 1), - new Twig_Token(Twig_Token::NAME_TYPE, 'extends', 1), - new Twig_Token(Twig_Token::STRING_TYPE, 'base', 1), - new Twig_Token(Twig_Token::BLOCK_END_TYPE, '', 1), - new Twig_Token(Twig_Token::EOF_TYPE, '', 1), - ))); - - $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE); - - return new Twig_Node(array()); - } - - public function getTag() - { - return 'test'; - } -} diff --git a/vendor/twig/twig/test/Twig/Tests/Profiler/Dumper/AbstractTest.php b/vendor/twig/twig/test/Twig/Tests/Profiler/Dumper/AbstractTest.php deleted file mode 100644 index a71b97b972d5976a06b2cf7508315a3b2f8ea5e8..0000000000000000000000000000000000000000 --- a/vendor/twig/twig/test/Twig/Tests/Profiler/Dumper/AbstractTest.php +++ /dev/null @@ -1,101 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -abstract class Twig_Tests_Profiler_Dumper_AbstractTest extends \PHPUnit\Framework\TestCase -{ - protected function getProfile() - { - $profile = $this->getMockBuilder('Twig_Profiler_Profile')->disableOriginalConstructor()->getMock(); - - $profile->expects($this->any())->method('isRoot')->will($this->returnValue(true)); - $profile->expects($this->any())->method('getName')->will($this->returnValue('main')); - $profile->expects($this->any())->method('getDuration')->will($this->returnValue(1)); - $profile->expects($this->any())->method('getMemoryUsage')->will($this->returnValue(0)); - $profile->expects($this->any())->method('getPeakMemoryUsage')->will($this->returnValue(0)); - - $subProfiles = array( - $this->getIndexProfile( - array( - $this->getEmbeddedBlockProfile(), - $this->getEmbeddedTemplateProfile( - array( - $this->getIncludedTemplateProfile(), - ) - ), - $this->getMacroProfile(), - $this->getEmbeddedTemplateProfile( - array( - $this->getIncludedTemplateProfile(), - ) - ), - ) - ), - ); - - $profile->expects($this->any())->method('getProfiles')->will($this->returnValue($subProfiles)); - $profile->expects($this->any())->method('getIterator')->will($this->returnValue(new ArrayIterator($subProfiles))); - - return $profile; - } - - private function getIndexProfile(array $subProfiles = array()) - { - return $this->generateProfile('main', 1, true, 'template', 'index.twig', $subProfiles); - } - - private function getEmbeddedBlockProfile(array $subProfiles = array()) - { - return $this->generateProfile('body', 0.0001, false, 'block', 'embedded.twig', $subProfiles); - } - - private function getEmbeddedTemplateProfile(array $subProfiles = array()) - { - return $this->generateProfile('main', 0.0001, true, 'template', 'embedded.twig', $subProfiles); - } - - private function getIncludedTemplateProfile(array $subProfiles = array()) - { - return $this->generateProfile('main', 0.0001, true, 'template', 'included.twig', $subProfiles); - } - - private function getMacroProfile(array $subProfiles = array()) - { - return $this->generateProfile('foo', 0.0001, false, 'macro', 'index.twig', $subProfiles); - } - - /** - * @param string $name - * @param float $duration - * @param bool $isTemplate - * @param string $type - * @param string $templateName - * @param array $subProfiles - * - * @return Twig_Profiler_Profile - */ - private function generateProfile($name, $duration, $isTemplate, $type, $templateName, array $subProfiles = array()) - { - $profile = $this->getMockBuilder('Twig_Profiler_Profile')->disableOriginalConstructor()->getMock(); - - $profile->expects($this->any())->method('isRoot')->will($this->returnValue(false)); - $profile->expects($this->any())->method('getName')->will($this->returnValue($name)); - $profile->expects($this->any())->method('getDuration')->will($this->returnValue($duration)); - $profile->expects($this->any())->method('getMemoryUsage')->will($this->returnValue(0)); - $profile->expects($this->any())->method('getPeakMemoryUsage')->will($this->returnValue(0)); - $profile->expects($this->any())->method('isTemplate')->will($this->returnValue($isTemplate)); - $profile->expects($this->any())->method('getType')->will($this->returnValue($type)); - $profile->expects($this->any())->method('getTemplate')->will($this->returnValue($templateName)); - $profile->expects($this->any())->method('getProfiles')->will($this->returnValue($subProfiles)); - $profile->expects($this->any())->method('getIterator')->will($this->returnValue(new ArrayIterator($subProfiles))); - - return $profile; - } -} diff --git a/vendor/twig/twig/test/Twig/Tests/Util/DeprecationCollectorTest.php b/vendor/twig/twig/test/Twig/Tests/Util/DeprecationCollectorTest.php deleted file mode 100644 index 887a90afaa1600bdb3a830beb597903581fc853c..0000000000000000000000000000000000000000 --- a/vendor/twig/twig/test/Twig/Tests/Util/DeprecationCollectorTest.php +++ /dev/null @@ -1,42 +0,0 @@ -<?php - -/* - * This file is part of Twig. - * - * (c) Fabien Potencier - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -class Twig_Tests_Util_DeprecationCollectorTest extends \PHPUnit\Framework\TestCase -{ - /** - * @requires PHP 5.3 - */ - public function testCollect() - { - $twig = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock()); - $twig->addFunction(new Twig_SimpleFunction('deprec', array($this, 'deprec'), array('deprecated' => true))); - - $collector = new Twig_Util_DeprecationCollector($twig); - $deprecations = $collector->collect(new Twig_Tests_Util_Iterator()); - - $this->assertEquals(array('Twig Function "deprec" is deprecated in deprec.twig at line 1.'), $deprecations); - } - - public function deprec() - { - } -} - -class Twig_Tests_Util_Iterator implements IteratorAggregate -{ - public function getIterator() - { - return new ArrayIterator(array( - 'ok.twig' => '{{ foo }}', - 'deprec.twig' => '{{ deprec("foo") }}', - )); - } -} diff --git a/vendor/twig/twig/test/Twig/Tests/AutoloaderTest.php b/vendor/twig/twig/tests/AutoloaderTest.php similarity index 81% rename from vendor/twig/twig/test/Twig/Tests/AutoloaderTest.php rename to vendor/twig/twig/tests/AutoloaderTest.php index 42529402e417dc4b6c4f3d36593924e1ce13c4b4..9bf538aee239f2711a1ed6767864ecad239fb5b5 100644 --- a/vendor/twig/twig/test/Twig/Tests/AutoloaderTest.php +++ b/vendor/twig/twig/tests/AutoloaderTest.php @@ -1,5 +1,7 @@ <?php +namespace Twig\Tests; + /* * This file is part of Twig. * @@ -9,7 +11,7 @@ * file that was distributed with this source code. */ -class Twig_Tests_AutoloaderTest extends \PHPUnit\Framework\TestCase +class AutoloaderTest extends \PHPUnit\Framework\TestCase { /** * @group legacy @@ -18,7 +20,7 @@ class Twig_Tests_AutoloaderTest extends \PHPUnit\Framework\TestCase { $this->assertFalse(class_exists('FooBarFoo'), '->autoload() does not try to load classes that does not begin with Twig'); - $autoloader = new Twig_Autoloader(); + $autoloader = new \Twig_Autoloader(); $this->assertNull($autoloader->autoload('Foo'), '->autoload() returns false if it is not able to load a class'); } } diff --git a/vendor/twig/twig/test/Twig/Tests/Cache/FilesystemTest.php b/vendor/twig/twig/tests/Cache/FilesystemTest.php similarity index 73% rename from vendor/twig/twig/test/Twig/Tests/Cache/FilesystemTest.php rename to vendor/twig/twig/tests/Cache/FilesystemTest.php index e9e600c1f23263b67ec65d7cb436c7c63519e0f3..c810caed988206b707555cff634a0ef265d9559a 100644 --- a/vendor/twig/twig/test/Twig/Tests/Cache/FilesystemTest.php +++ b/vendor/twig/twig/tests/Cache/FilesystemTest.php @@ -1,5 +1,7 @@ <?php +namespace Twig\Tests\Cache; + /* * This file is part of Twig. * @@ -9,9 +11,10 @@ * file that was distributed with this source code. */ -require_once dirname(dirname(__FILE__)).'/FilesystemHelper.php'; +use Twig\Cache\FilesystemCache; +use Twig\Tests\FilesystemHelper; -class Twig_Tests_Cache_FilesystemTest extends \PHPUnit\Framework\TestCase +class FilesystemTest extends \PHPUnit\Framework\TestCase { private $classname; private $directory; @@ -22,13 +25,13 @@ class Twig_Tests_Cache_FilesystemTest extends \PHPUnit\Framework\TestCase $nonce = hash('sha256', uniqid(mt_rand(), true)); $this->classname = '__Twig_Tests_Cache_FilesystemTest_Template_'.$nonce; $this->directory = sys_get_temp_dir().'/twig-test'; - $this->cache = new Twig_Cache_Filesystem($this->directory); + $this->cache = new FilesystemCache($this->directory); } protected function tearDown() { if (file_exists($this->directory)) { - Twig_Tests_FilesystemHelper::removeDir($this->directory); + FilesystemHelper::removeDir($this->directory); } } @@ -36,9 +39,9 @@ class Twig_Tests_Cache_FilesystemTest extends \PHPUnit\Framework\TestCase { $key = $this->directory.'/cache/cachefile.php'; - $dir = dirname($key); + $dir = \dirname($key); @mkdir($dir, 0777, true); - $this->assertTrue(is_dir($dir)); + $this->assertDirectoryExists($dir); $this->assertFalse(class_exists($this->classname, false)); $content = $this->generateSource(); @@ -75,13 +78,12 @@ class Twig_Tests_Cache_FilesystemTest extends \PHPUnit\Framework\TestCase $this->assertSame(file_get_contents($key), $content); } - /** - * @expectedException RuntimeException - * @expectedExceptionMessage Unable to create the cache directory - */ public function testWriteFailMkdir() { - if (defined('PHP_WINDOWS_VERSION_BUILD')) { + $this->expectException('\RuntimeException'); + $this->expectExceptionMessage('Unable to create the cache directory'); + + if (\defined('PHP_WINDOWS_VERSION_BUILD')) { $this->markTestSkipped('Read-only directories not possible on Windows.'); } @@ -92,18 +94,17 @@ class Twig_Tests_Cache_FilesystemTest extends \PHPUnit\Framework\TestCase // Create read-only root directory. @mkdir($this->directory, 0555, true); - $this->assertTrue(is_dir($this->directory)); + $this->assertDirectoryExists($this->directory); $this->cache->write($key, $content); } - /** - * @expectedException RuntimeException - * @expectedExceptionMessage Unable to write in the cache directory - */ public function testWriteFailDirWritable() { - if (defined('PHP_WINDOWS_VERSION_BUILD')) { + $this->expectException('\RuntimeException'); + $this->expectExceptionMessage('Unable to write in the cache directory'); + + if (\defined('PHP_WINDOWS_VERSION_BUILD')) { $this->markTestSkipped('Read-only directories not possible on Windows.'); } @@ -116,17 +117,16 @@ class Twig_Tests_Cache_FilesystemTest extends \PHPUnit\Framework\TestCase @mkdir($this->directory, 0777, true); // Create read-only subdirectory. @mkdir($this->directory.'/cache', 0555); - $this->assertTrue(is_dir($this->directory.'/cache')); + $this->assertDirectoryExists($this->directory.'/cache'); $this->cache->write($key, $content); } - /** - * @expectedException RuntimeException - * @expectedExceptionMessage Failed to write cache file - */ public function testWriteFailWriteFile() { + $this->expectException('\RuntimeException'); + $this->expectExceptionMessage('Failed to write cache file'); + $key = $this->directory.'/cache/cachefile.php'; $content = $this->generateSource(); @@ -134,7 +134,7 @@ class Twig_Tests_Cache_FilesystemTest extends \PHPUnit\Framework\TestCase // Create a directory in the place of the cache file. @mkdir($key, 0777, true); - $this->assertTrue(is_dir($key)); + $this->assertDirectoryExists($key); $this->cache->write($key, $content); } @@ -143,9 +143,9 @@ class Twig_Tests_Cache_FilesystemTest extends \PHPUnit\Framework\TestCase { $key = $this->directory.'/cache/cachefile.php'; - $dir = dirname($key); + $dir = \dirname($key); @mkdir($dir, 0777, true); - $this->assertTrue(is_dir($dir)); + $this->assertDirectoryExists($dir); // Create the file with a specific modification time. touch($key, 1234567890); @@ -166,28 +166,28 @@ class Twig_Tests_Cache_FilesystemTest extends \PHPUnit\Framework\TestCase */ public function testGenerateKey($expected, $input) { - $cache = new Twig_Cache_Filesystem($input); - $this->assertRegExp($expected, $cache->generateKey('_test_', get_class($this))); + $cache = new FilesystemCache($input); + $this->assertRegExp($expected, $cache->generateKey('_test_', \get_class($this))); } public function provideDirectories() { $pattern = '#a/b/[a-zA-Z0-9]+/[a-zA-Z0-9]+.php$#'; - return array( - array($pattern, 'a/b'), - array($pattern, 'a/b/'), - array($pattern, 'a/b\\'), - array($pattern, 'a/b\\/'), - array($pattern, 'a/b\\//'), - array('#/'.substr($pattern, 1), '/a/b'), - ); + return [ + [$pattern, 'a/b'], + [$pattern, 'a/b/'], + [$pattern, 'a/b\\'], + [$pattern, 'a/b\\/'], + [$pattern, 'a/b\\//'], + ['#/'.substr($pattern, 1), '/a/b'], + ]; } private function generateSource() { - return strtr('<?php class {{classname}} {}', array( + return strtr('<?php class {{classname}} {}', [ '{{classname}}' => $this->classname, - )); + ]); } } diff --git a/vendor/twig/twig/test/Twig/Tests/CompilerTest.php b/vendor/twig/twig/tests/CompilerTest.php similarity index 63% rename from vendor/twig/twig/test/Twig/Tests/CompilerTest.php rename to vendor/twig/twig/tests/CompilerTest.php index 4d4b8df9e375786d4cae374fbda16c062dc13b11..cc462c25199c76a659255cf93378e37bf1f38dc4 100644 --- a/vendor/twig/twig/test/Twig/Tests/CompilerTest.php +++ b/vendor/twig/twig/tests/CompilerTest.php @@ -1,5 +1,7 @@ <?php +namespace Twig\Tests; + /* * This file is part of Twig. * @@ -9,24 +11,27 @@ * file that was distributed with this source code. */ -class Twig_Tests_CompilerTest extends \PHPUnit\Framework\TestCase +use Twig\Compiler; +use Twig\Environment; + +class CompilerTest extends \PHPUnit\Framework\TestCase { public function testReprNumericValueWithLocale() { - $compiler = new Twig_Compiler(new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock())); + $compiler = new Compiler(new Environment($this->createMock('\Twig\Loader\LoaderInterface'))); $locale = setlocale(LC_NUMERIC, 0); if (false === $locale) { $this->markTestSkipped('Your platform does not support locales.'); } - $required_locales = array('fr_FR.UTF-8', 'fr_FR.UTF8', 'fr_FR.utf-8', 'fr_FR.utf8', 'French_France.1252'); + $required_locales = ['fr_FR.UTF-8', 'fr_FR.UTF8', 'fr_FR.utf-8', 'fr_FR.utf8', 'French_France.1252']; if (false === setlocale(LC_NUMERIC, $required_locales)) { $this->markTestSkipped('Could not set any of required locales: '.implode(', ', $required_locales)); } $this->assertEquals('1.2', $compiler->repr(1.2)->getSource()); - $this->assertContains('fr', strtolower(setlocale(LC_NUMERIC, 0))); + $this->assertStringContainsString('fr', strtolower(setlocale(LC_NUMERIC, 0))); setlocale(LC_NUMERIC, $locale); } diff --git a/vendor/twig/twig/test/Twig/Tests/ContainerRuntimeLoaderTest.php b/vendor/twig/twig/tests/ContainerRuntimeLoaderTest.php similarity index 64% rename from vendor/twig/twig/test/Twig/Tests/ContainerRuntimeLoaderTest.php rename to vendor/twig/twig/tests/ContainerRuntimeLoaderTest.php index c111f9284b39d6b596185de60e134fdd8711f263..c85648342f39ca4a9627a2d28db34ea3cf99035f 100644 --- a/vendor/twig/twig/test/Twig/Tests/ContainerRuntimeLoaderTest.php +++ b/vendor/twig/twig/tests/ContainerRuntimeLoaderTest.php @@ -1,5 +1,7 @@ <?php +namespace Twig\Tests; + /* * This file is part of Twig. * @@ -9,18 +11,20 @@ * file that was distributed with this source code. */ -class Twig_Tests_ContainerRuntimeLoaderTest extends \PHPUnit\Framework\TestCase +use Twig\RuntimeLoader\ContainerRuntimeLoader; + +class ContainerRuntimeLoaderTest extends \PHPUnit\Framework\TestCase { /** * @requires PHP 5.3 */ public function testLoad() { - $container = $this->getMockBuilder('Psr\Container\ContainerInterface')->getMock(); + $container = $this->createMock('Psr\Container\ContainerInterface'); $container->expects($this->once())->method('has')->with('stdClass')->willReturn(true); - $container->expects($this->once())->method('get')->with('stdClass')->willReturn(new stdClass()); + $container->expects($this->once())->method('get')->with('stdClass')->willReturn(new \stdClass()); - $loader = new Twig_ContainerRuntimeLoader($container); + $loader = new ContainerRuntimeLoader($container); $this->assertInstanceOf('stdClass', $loader->load('stdClass')); } @@ -30,11 +34,11 @@ class Twig_Tests_ContainerRuntimeLoaderTest extends \PHPUnit\Framework\TestCase */ public function testLoadUnknownRuntimeReturnsNull() { - $container = $this->getMockBuilder('Psr\Container\ContainerInterface')->getMock(); + $container = $this->createMock('Psr\Container\ContainerInterface'); $container->expects($this->once())->method('has')->with('Foo'); $container->expects($this->never())->method('get'); - $loader = new Twig_ContainerRuntimeLoader($container); + $loader = new ContainerRuntimeLoader($container); $this->assertNull($loader->load('Foo')); } } diff --git a/vendor/twig/twig/tests/CustomExtensionTest.php b/vendor/twig/twig/tests/CustomExtensionTest.php new file mode 100644 index 0000000000000000000000000000000000000000..b45e1434f25157d3c5dc1526bd7c3a89bf24cd67 --- /dev/null +++ b/vendor/twig/twig/tests/CustomExtensionTest.php @@ -0,0 +1,94 @@ +<?php + +namespace Twig\Tests; + +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use Twig\Environment; +use Twig\Extension\ExtensionInterface; + +class CustomExtensionTest extends \PHPUnit\Framework\TestCase +{ + /** + * @requires PHP 5.3 + * @dataProvider provideInvalidExtensions + */ + public function testGetInvalidOperators(ExtensionInterface $extension, $expectedExceptionMessage) + { + $this->expectException('InvalidArgumentException'); + $this->expectExceptionMessage($expectedExceptionMessage); + + $env = new Environment($this->createMock('\Twig\Loader\LoaderInterface')); + $env->addExtension($extension); + $env->getUnaryOperators(); + } + + public function provideInvalidExtensions() + { + return [ + [new InvalidOperatorExtension(new \stdClass()), '"Twig\Tests\InvalidOperatorExtension::getOperators()" must return an array with operators, got "stdClass".'], + [new InvalidOperatorExtension([1, 2, 3]), '"Twig\Tests\InvalidOperatorExtension::getOperators()" must return an array of 2 elements, got 3.'], + ]; + } +} + +class InvalidOperatorExtension implements ExtensionInterface +{ + private $operators; + + public function __construct($operators) + { + $this->operators = $operators; + } + + public function initRuntime(Environment $environment) + { + } + + public function getTokenParsers() + { + return []; + } + + public function getNodeVisitors() + { + return []; + } + + public function getFilters() + { + return []; + } + + public function getTests() + { + return []; + } + + public function getFunctions() + { + return []; + } + + public function getGlobals() + { + return []; + } + + public function getOperators() + { + return $this->operators; + } + + public function getName() + { + return __CLASS__; + } +} diff --git a/vendor/twig/twig/test/Twig/Tests/EnvironmentTest.php b/vendor/twig/twig/tests/EnvironmentTest.php similarity index 52% rename from vendor/twig/twig/test/Twig/Tests/EnvironmentTest.php rename to vendor/twig/twig/tests/EnvironmentTest.php index ca9f2cf8aced58799bfe03dbb0c9070f9e68dcf5..54a894506cba8735c5c34b0fe6ee6a898a88ca01 100644 --- a/vendor/twig/twig/test/Twig/Tests/EnvironmentTest.php +++ b/vendor/twig/twig/tests/EnvironmentTest.php @@ -1,5 +1,7 @@ <?php +namespace Twig\Tests; + /* * This file is part of Twig. * @@ -9,18 +11,32 @@ * file that was distributed with this source code. */ -require_once dirname(__FILE__).'/FilesystemHelper.php'; - -class Twig_Tests_EnvironmentTest extends \PHPUnit\Framework\TestCase +use Twig\Cache\FilesystemCache; +use Twig\Environment; +use Twig\Extension\AbstractExtension; +use Twig\Extension\GlobalsInterface; +use Twig\Extension\InitRuntimeInterface; +use Twig\Loader\ArrayLoader; +use Twig\Loader\LoaderInterface; +use Twig\Loader\SourceContextLoaderInterface; +use Twig\NodeVisitor\NodeVisitorInterface; +use Twig\Source; +use Twig\Token; +use Twig\TokenParser\AbstractTokenParser; +use Twig\TwigFilter; +use Twig\TwigFunction; +use Twig\TwigTest; + +class EnvironmentTest extends \PHPUnit\Framework\TestCase { - private $deprecations = array(); + private $deprecations = []; /** * @group legacy */ public function testLegacyTokenizeSignature() { - $env = new Twig_Environment(); + $env = new Environment(); $stream = $env->tokenize('{{ foo }}', 'foo'); $this->assertEquals('{{ foo }}', $stream->getSource()); $this->assertEquals('foo', $stream->getFilename()); @@ -31,37 +47,38 @@ class Twig_Tests_EnvironmentTest extends \PHPUnit\Framework\TestCase */ public function testLegacyCompileSourceSignature() { - $loader = new Twig_Loader_Array(array('foo' => '{{ foo }}')); - $env = new Twig_Environment($loader); - $this->assertContains('getTemplateName', $env->compileSource('{{ foo }}', 'foo')); + $loader = new ArrayLoader(['foo' => '{{ foo }}']); + $env = new Environment($loader); + $this->assertStringContainsString('getTemplateName', $env->compileSource('{{ foo }}', 'foo')); } /** - * @expectedException LogicException - * @expectedExceptionMessage You must set a loader first. * @group legacy */ public function testRenderNoLoader() { - $env = new Twig_Environment(); + $this->expectException('\LogicException'); + $this->expectExceptionMessage('You must set a loader first.'); + + $env = new Environment(); $env->render('test'); } public function testAutoescapeOption() { - $loader = new Twig_Loader_Array(array( + $loader = new ArrayLoader([ 'html' => '{{ foo }} {{ foo }}', 'js' => '{{ bar }} {{ bar }}', - )); + ]); - $twig = new Twig_Environment($loader, array( + $twig = new Environment($loader, [ 'debug' => true, 'cache' => false, - 'autoescape' => array($this, 'escapingStrategyCallback'), - )); + 'autoescape' => [$this, 'escapingStrategyCallback'], + ]); - $this->assertEquals('foo<br/ > foo<br/ >', $twig->render('html', array('foo' => 'foo<br/ >'))); - $this->assertEquals('foo\x3Cbr\x2F\x20\x3E foo\x3Cbr\x2F\x20\x3E', $twig->render('js', array('bar' => 'foo<br/ >'))); + $this->assertEquals('foo<br/ > foo<br/ >', $twig->render('html', ['foo' => 'foo<br/ >'])); + $this->assertEquals('foo\u003Cbr\/\u0020\u003E foo\u003Cbr\/\u0020\u003E', $twig->render('js', ['bar' => 'foo<br/ >'])); } public function escapingStrategyCallback($name) @@ -72,13 +89,13 @@ class Twig_Tests_EnvironmentTest extends \PHPUnit\Framework\TestCase public function testGlobals() { // to be removed in 2.0 - $loader = $this->getMockBuilder('Twig_EnvironmentTestLoaderInterface')->getMock(); - //$loader = $this->getMockBuilder(array('Twig_LoaderInterface', 'Twig_SourceContextLoaderInterface'))->getMock(); - $loader->expects($this->any())->method('getSourceContext')->will($this->returnValue(new Twig_Source('', ''))); + $loader = $this->createMock('\Twig\Tests\EnvironmentTestLoaderInterface'); + //$loader = $this->createMock(['\Twig\Loader\LoaderInterface', '\Twig\Loader\SourceContextLoaderInterface']); + $loader->expects($this->any())->method('getSourceContext')->willReturn(new Source('', '')); // globals can be added after calling getGlobals - $twig = new Twig_Environment($loader); + $twig = new Environment($loader); $twig->addGlobal('foo', 'foo'); $twig->getGlobals(); $twig->addGlobal('foo', 'bar'); @@ -86,16 +103,16 @@ class Twig_Tests_EnvironmentTest extends \PHPUnit\Framework\TestCase $this->assertEquals('bar', $globals['foo']); // globals can be modified after a template has been loaded - $twig = new Twig_Environment($loader); + $twig = new Environment($loader); $twig->addGlobal('foo', 'foo'); $twig->getGlobals(); - $twig->loadTemplate('index'); + $twig->load('index'); $twig->addGlobal('foo', 'bar'); $globals = $twig->getGlobals(); $this->assertEquals('bar', $globals['foo']); // globals can be modified after extensions init - $twig = new Twig_Environment($loader); + $twig = new Environment($loader); $twig->addGlobal('foo', 'foo'); $twig->getGlobals(); $twig->getFunctions(); @@ -104,67 +121,67 @@ class Twig_Tests_EnvironmentTest extends \PHPUnit\Framework\TestCase $this->assertEquals('bar', $globals['foo']); // globals can be modified after extensions and a template has been loaded - $arrayLoader = new Twig_Loader_Array(array('index' => '{{foo}}')); - $twig = new Twig_Environment($arrayLoader); + $arrayLoader = new ArrayLoader(['index' => '{{foo}}']); + $twig = new Environment($arrayLoader); $twig->addGlobal('foo', 'foo'); $twig->getGlobals(); $twig->getFunctions(); - $twig->loadTemplate('index'); + $twig->load('index'); $twig->addGlobal('foo', 'bar'); $globals = $twig->getGlobals(); $this->assertEquals('bar', $globals['foo']); - $twig = new Twig_Environment($arrayLoader); + $twig = new Environment($arrayLoader); $twig->getGlobals(); $twig->addGlobal('foo', 'bar'); - $template = $twig->loadTemplate('index'); - $this->assertEquals('bar', $template->render(array())); + $template = $twig->load('index'); + $this->assertEquals('bar', $template->render([])); /* to be uncomment in Twig 2.0 // globals cannot be added after a template has been loaded - $twig = new Twig_Environment($loader); + $twig = new Environment($loader); $twig->addGlobal('foo', 'foo'); $twig->getGlobals(); - $twig->loadTemplate('index'); + $twig->load('index'); try { $twig->addGlobal('bar', 'bar'); $this->fail(); - } catch (LogicException $e) { + } catch (\LogicException $e) { $this->assertFalse(array_key_exists('bar', $twig->getGlobals())); } // globals cannot be added after extensions init - $twig = new Twig_Environment($loader); + $twig = new Environment($loader); $twig->addGlobal('foo', 'foo'); $twig->getGlobals(); $twig->getFunctions(); try { $twig->addGlobal('bar', 'bar'); $this->fail(); - } catch (LogicException $e) { + } catch (\LogicException $e) { $this->assertFalse(array_key_exists('bar', $twig->getGlobals())); } // globals cannot be added after extensions and a template has been loaded - $twig = new Twig_Environment($loader); + $twig = new Environment($loader); $twig->addGlobal('foo', 'foo'); $twig->getGlobals(); $twig->getFunctions(); - $twig->loadTemplate('index'); + $twig->load('index'); try { $twig->addGlobal('bar', 'bar'); $this->fail(); - } catch (LogicException $e) { + } catch (\LogicException $e) { $this->assertFalse(array_key_exists('bar', $twig->getGlobals())); } // test adding globals after a template has been loaded without call to getGlobals - $twig = new Twig_Environment($loader); - $twig->loadTemplate('index'); + $twig = new Environment($loader); + $twig->load('index'); try { $twig->addGlobal('bar', 'bar'); $this->fail(); - } catch (LogicException $e) { + } catch (\LogicException $e) { $this->assertFalse(array_key_exists('bar', $twig->getGlobals())); } */ @@ -172,30 +189,30 @@ class Twig_Tests_EnvironmentTest extends \PHPUnit\Framework\TestCase public function testExtensionsAreNotInitializedWhenRenderingACompiledTemplate() { - $cache = new Twig_Cache_Filesystem($dir = sys_get_temp_dir().'/twig'); - $options = array('cache' => $cache, 'auto_reload' => false, 'debug' => false); + $cache = new FilesystemCache($dir = sys_get_temp_dir().'/twig'); + $options = ['cache' => $cache, 'auto_reload' => false, 'debug' => false]; // force compilation - $twig = new Twig_Environment($loader = new Twig_Loader_Array(array('index' => '{{ foo }}')), $options); + $twig = new Environment($loader = new ArrayLoader(['index' => '{{ foo }}']), $options); $key = $cache->generateKey('index', $twig->getTemplateClass('index')); - $cache->write($key, $twig->compileSource(new Twig_Source('{{ foo }}', 'index'))); + $cache->write($key, $twig->compileSource(new Source('{{ foo }}', 'index'))); // check that extensions won't be initialized when rendering a template that is already in the cache $twig = $this - ->getMockBuilder('Twig_Environment') - ->setConstructorArgs(array($loader, $options)) - ->setMethods(array('initExtensions')) + ->getMockBuilder('\Twig\Environment') + ->setConstructorArgs([$loader, $options]) + ->setMethods(['initExtensions']) ->getMock() ; $twig->expects($this->never())->method('initExtensions'); // render template - $output = $twig->render('index', array('foo' => 'bar')); + $output = $twig->render('index', ['foo' => 'bar']); $this->assertEquals('bar', $output); - Twig_Tests_FilesystemHelper::removeDir($dir); + FilesystemHelper::removeDir($dir); } public function testAutoReloadCacheMiss() @@ -203,18 +220,18 @@ class Twig_Tests_EnvironmentTest extends \PHPUnit\Framework\TestCase $templateName = __FUNCTION__; $templateContent = __FUNCTION__; - $cache = $this->getMockBuilder('Twig_CacheInterface')->getMock(); + $cache = $this->createMock('\Twig\Cache\CacheInterface'); $loader = $this->getMockLoader($templateName, $templateContent); - $twig = new Twig_Environment($loader, array('cache' => $cache, 'auto_reload' => true, 'debug' => false)); + $twig = new Environment($loader, ['cache' => $cache, 'auto_reload' => true, 'debug' => false]); // Cache miss: getTimestamp returns 0 and as a result the load() is // skipped. $cache->expects($this->once()) ->method('generateKey') - ->will($this->returnValue('key')); + ->willReturn('key'); $cache->expects($this->once()) ->method('getTimestamp') - ->will($this->returnValue(0)); + ->willReturn(0); $loader->expects($this->never()) ->method('isFresh'); $cache->expects($this->once()) @@ -222,7 +239,7 @@ class Twig_Tests_EnvironmentTest extends \PHPUnit\Framework\TestCase $cache->expects($this->once()) ->method('load'); - $twig->loadTemplate($templateName); + $twig->load($templateName); } public function testAutoReloadCacheHit() @@ -230,9 +247,9 @@ class Twig_Tests_EnvironmentTest extends \PHPUnit\Framework\TestCase $templateName = __FUNCTION__; $templateContent = __FUNCTION__; - $cache = $this->getMockBuilder('Twig_CacheInterface')->getMock(); + $cache = $this->createMock('\Twig\Cache\CacheInterface'); $loader = $this->getMockLoader($templateName, $templateContent); - $twig = new Twig_Environment($loader, array('cache' => $cache, 'auto_reload' => true, 'debug' => false)); + $twig = new Environment($loader, ['cache' => $cache, 'auto_reload' => true, 'debug' => false]); $now = time(); @@ -240,17 +257,17 @@ class Twig_Tests_EnvironmentTest extends \PHPUnit\Framework\TestCase // the loader returns true for isFresh(). $cache->expects($this->once()) ->method('generateKey') - ->will($this->returnValue('key')); + ->willReturn('key'); $cache->expects($this->once()) ->method('getTimestamp') - ->will($this->returnValue($now)); + ->willReturn($now); $loader->expects($this->once()) ->method('isFresh') - ->will($this->returnValue(true)); + ->willReturn(true); $cache->expects($this->atLeastOnce()) ->method('load'); - $twig->loadTemplate($templateName); + $twig->load($templateName); } public function testAutoReloadOutdatedCacheHit() @@ -258,27 +275,27 @@ class Twig_Tests_EnvironmentTest extends \PHPUnit\Framework\TestCase $templateName = __FUNCTION__; $templateContent = __FUNCTION__; - $cache = $this->getMockBuilder('Twig_CacheInterface')->getMock(); + $cache = $this->createMock('\Twig\Cache\CacheInterface'); $loader = $this->getMockLoader($templateName, $templateContent); - $twig = new Twig_Environment($loader, array('cache' => $cache, 'auto_reload' => true, 'debug' => false)); + $twig = new Environment($loader, ['cache' => $cache, 'auto_reload' => true, 'debug' => false]); $now = time(); $cache->expects($this->once()) ->method('generateKey') - ->will($this->returnValue('key')); + ->willReturn('key'); $cache->expects($this->once()) ->method('getTimestamp') - ->will($this->returnValue($now)); + ->willReturn($now); $loader->expects($this->once()) ->method('isFresh') - ->will($this->returnValue(false)); + ->willReturn(false); $cache->expects($this->once()) ->method('write'); $cache->expects($this->once()) ->method('load'); - $twig->loadTemplate($templateName); + $twig->load($templateName); } /** @@ -286,17 +303,17 @@ class Twig_Tests_EnvironmentTest extends \PHPUnit\Framework\TestCase */ public function testHasGetExtensionWithDynamicName() { - $twig = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock()); + $twig = new Environment($this->createMock('\Twig\Loader\LoaderInterface')); - $ext1 = new Twig_Tests_EnvironmentTest_Extension_DynamicWithDeprecatedName('ext1'); - $ext2 = new Twig_Tests_EnvironmentTest_Extension_DynamicWithDeprecatedName('ext2'); + $ext1 = new EnvironmentTest_Extension_DynamicWithDeprecatedName('ext1'); + $ext2 = new EnvironmentTest_Extension_DynamicWithDeprecatedName('ext2'); $twig->addExtension($ext1); $twig->addExtension($ext2); $this->assertTrue($twig->hasExtension('ext1')); $this->assertTrue($twig->hasExtension('ext2')); - $this->assertTrue($twig->hasExtension('Twig_Tests_EnvironmentTest_Extension_DynamicWithDeprecatedName')); + $this->assertTrue($twig->hasExtension('Twig\Tests\EnvironmentTest_Extension_DynamicWithDeprecatedName')); $this->assertSame($ext1, $twig->getExtension('ext1')); $this->assertSame($ext2, $twig->getExtension('ext2')); @@ -304,13 +321,13 @@ class Twig_Tests_EnvironmentTest extends \PHPUnit\Framework\TestCase public function testHasGetExtensionByClassName() { - $twig = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock()); - $twig->addExtension($ext = new Twig_Tests_EnvironmentTest_Extension()); - $this->assertTrue($twig->hasExtension('Twig_Tests_EnvironmentTest_Extension')); - $this->assertTrue($twig->hasExtension('\Twig_Tests_EnvironmentTest_Extension')); + $twig = new Environment($this->createMock('\Twig\Loader\LoaderInterface')); + $twig->addExtension($ext = new EnvironmentTest_Extension()); + $this->assertTrue($twig->hasExtension('Twig\Tests\EnvironmentTest_Extension')); + $this->assertTrue($twig->hasExtension('\Twig\Tests\EnvironmentTest_Extension')); - $this->assertSame($ext, $twig->getExtension('Twig_Tests_EnvironmentTest_Extension')); - $this->assertSame($ext, $twig->getExtension('\Twig_Tests_EnvironmentTest_Extension')); + $this->assertSame($ext, $twig->getExtension('Twig\Tests\EnvironmentTest_Extension')); + $this->assertSame($ext, $twig->getExtension('\Twig\Tests\EnvironmentTest_Extension')); $this->assertTrue($twig->hasExtension('Twig\Tests\EnvironmentTest\Extension')); $this->assertSame($ext, $twig->getExtension('Twig\Tests\EnvironmentTest\Extension')); @@ -318,8 +335,8 @@ class Twig_Tests_EnvironmentTest extends \PHPUnit\Framework\TestCase public function testAddExtension() { - $twig = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock()); - $twig->addExtension(new Twig_Tests_EnvironmentTest_Extension()); + $twig = new Environment($this->createMock('\Twig\Loader\LoaderInterface')); + $twig->addExtension(new EnvironmentTest_Extension()); $this->assertArrayHasKey('test', $twig->getTags()); $this->assertArrayHasKey('foo_filter', $twig->getFilters()); @@ -331,7 +348,7 @@ class Twig_Tests_EnvironmentTest extends \PHPUnit\Framework\TestCase $visitors = $twig->getNodeVisitors(); $found = false; foreach ($visitors as $visitor) { - if ($visitor instanceof Twig_Tests_EnvironmentTest_NodeVisitor) { + if ($visitor instanceof EnvironmentTest_NodeVisitor) { $found = true; } } @@ -343,16 +360,16 @@ class Twig_Tests_EnvironmentTest extends \PHPUnit\Framework\TestCase */ public function testAddExtensionWithDeprecatedGetGlobals() { - $twig = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock()); - $twig->addExtension(new Twig_Tests_EnvironmentTest_Extension_WithGlobals()); + $twig = new Environment($this->createMock('\Twig\Loader\LoaderInterface')); + $twig->addExtension(new EnvironmentTest_Extension_WithGlobals()); - $this->deprecations = array(); - set_error_handler(array($this, 'handleError')); + $this->deprecations = []; + set_error_handler([$this, 'handleError']); $this->assertArrayHasKey('foo_global', $twig->getGlobals()); $this->assertCount(1, $this->deprecations); - $this->assertContains('Defining the getGlobals() method in the "Twig_Tests_EnvironmentTest_Extension_WithGlobals" extension ', $this->deprecations[0]); + $this->assertStringContainsString('Defining the getGlobals() method in the "Twig\Tests\EnvironmentTest_Extension_WithGlobals" extension ', $this->deprecations[0]); restore_error_handler(); } @@ -362,8 +379,8 @@ class Twig_Tests_EnvironmentTest extends \PHPUnit\Framework\TestCase */ public function testRemoveExtension() { - $twig = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock()); - $twig->addExtension(new Twig_Tests_EnvironmentTest_Extension_WithDeprecatedName()); + $twig = new Environment($this->createMock('\Twig\Loader\LoaderInterface')); + $twig->addExtension(new EnvironmentTest_Extension_WithDeprecatedName()); $twig->removeExtension('environment_test'); $this->assertArrayNotHasKey('test', $twig->getTags()); @@ -379,28 +396,30 @@ class Twig_Tests_EnvironmentTest extends \PHPUnit\Framework\TestCase public function testAddMockExtension() { // should be replaced by the following in 2.0 (this current code is just to avoid a dep notice) - // $extension = $this->getMockBuilder('Twig_Extension')->getMock(); + // $extension = $this->createMock('\Twig\Extension\AbstractExtension'); $extension = eval(<<<EOF -class Twig_Tests_EnvironmentTest_ExtensionInEval extends Twig_Extension +use Twig\Extension\AbstractExtension; + +class EnvironmentTest_ExtensionInEval extends AbstractExtension { } EOF ); - $extension = new Twig_Tests_EnvironmentTest_ExtensionInEval(); + $extension = new \EnvironmentTest_ExtensionInEval(); - $loader = new Twig_Loader_Array(array('page' => 'hey')); + $loader = new ArrayLoader(['page' => 'hey']); - $twig = new Twig_Environment($loader); + $twig = new Environment($loader); $twig->addExtension($extension); - $this->assertInstanceOf('Twig_ExtensionInterface', $twig->getExtension(get_class($extension))); + $this->assertInstanceOf('\Twig\Extension\ExtensionInterface', $twig->getExtension(\get_class($extension))); $this->assertTrue($twig->isTemplateFresh('page', time())); } public function testInitRuntimeWithAnExtensionUsingInitRuntimeNoDeprecation() { - $twig = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock()); - $twig->addExtension(new Twig_Tests_EnvironmentTest_ExtensionWithoutDeprecationInitRuntime()); + $twig = new Environment($this->createMock('\Twig\Loader\LoaderInterface')); + $twig->addExtension(new EnvironmentTest_ExtensionWithoutDeprecationInitRuntime()); $twig->initRuntime(); // add a dummy assertion here to satisfy PHPUnit, the only thing we want to test is that the code above @@ -413,16 +432,16 @@ EOF */ public function testInitRuntimeWithAnExtensionUsingInitRuntimeDeprecation() { - $twig = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock()); - $twig->addExtension(new Twig_Tests_EnvironmentTest_ExtensionWithDeprecationInitRuntime()); + $twig = new Environment($this->createMock('\Twig\Loader\LoaderInterface')); + $twig->addExtension(new EnvironmentTest_ExtensionWithDeprecationInitRuntime()); - $this->deprecations = array(); - set_error_handler(array($this, 'handleError')); + $this->deprecations = []; + set_error_handler([$this, 'handleError']); $twig->initRuntime(); $this->assertCount(1, $this->deprecations); - $this->assertContains('Defining the initRuntime() method in the "Twig_Tests_EnvironmentTest_ExtensionWithDeprecationInitRuntime" extension is deprecated since version 1.23.', $this->deprecations[0]); + $this->assertStringContainsString('Defining the initRuntime() method in the "Twig\Tests\EnvironmentTest_ExtensionWithDeprecationInitRuntime" extension is deprecated since version 1.23.', $this->deprecations[0]); restore_error_handler(); } @@ -439,37 +458,37 @@ EOF */ public function testOverrideExtension() { - $twig = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock()); - $twig->addExtension(new Twig_Tests_EnvironmentTest_ExtensionWithDeprecationInitRuntime()); + $twig = new Environment($this->createMock('\Twig\Loader\LoaderInterface')); + $twig->addExtension(new EnvironmentTest_ExtensionWithDeprecationInitRuntime()); - $this->deprecations = array(); - set_error_handler(array($this, 'handleError')); + $this->deprecations = []; + set_error_handler([$this, 'handleError']); - $twig->addExtension(new Twig_Tests_EnvironmentTest_Extension_WithDeprecatedName()); - $twig->addExtension(new Twig_Tests_EnvironmentTest_Extension_WithDeprecatedName()); + $twig->addExtension(new EnvironmentTest_Extension_WithDeprecatedName()); + $twig->addExtension(new EnvironmentTest_Extension_WithDeprecatedName()); $this->assertCount(1, $this->deprecations); - $this->assertContains('The possibility to register the same extension twice', $this->deprecations[0]); + $this->assertStringContainsString('The possibility to register the same extension twice', $this->deprecations[0]); restore_error_handler(); } public function testAddRuntimeLoader() { - $runtimeLoader = $this->getMockBuilder('Twig_RuntimeLoaderInterface')->getMock(); - $runtimeLoader->expects($this->any())->method('load')->will($this->returnValue(new Twig_Tests_EnvironmentTest_Runtime())); + $runtimeLoader = $this->createMock('\Twig\RuntimeLoader\RuntimeLoaderInterface'); + $runtimeLoader->expects($this->any())->method('load')->willReturn(new EnvironmentTest_Runtime()); - $loader = new Twig_Loader_Array(array( + $loader = new ArrayLoader([ 'func_array' => '{{ from_runtime_array("foo") }}', 'func_array_default' => '{{ from_runtime_array() }}', 'func_array_named_args' => '{{ from_runtime_array(name="foo") }}', 'func_string' => '{{ from_runtime_string("foo") }}', 'func_string_default' => '{{ from_runtime_string() }}', 'func_string_named_args' => '{{ from_runtime_string(name="foo") }}', - )); + ]); - $twig = new Twig_Environment($loader); - $twig->addExtension(new Twig_Tests_EnvironmentTest_ExtensionWithoutRuntime()); + $twig = new Environment($loader); + $twig->addExtension(new EnvironmentTest_ExtensionWithoutRuntime()); $twig->addRuntimeLoader($runtimeLoader); $this->assertEquals('foo', $twig->render('func_array')); @@ -480,116 +499,89 @@ EOF $this->assertEquals('foo', $twig->render('func_string_named_args')); } - /** - * @expectedException Twig_Error_Runtime - * @expectedExceptionMessage Circular reference detected for Twig template "base.html.twig", path: base.html.twig -> base.html.twig in "base.html.twig" at line 1 - */ - public function testFailLoadTemplateOnCircularReference() - { - $twig = new Twig_Environment(new Twig_Loader_Array(array( - 'base.html.twig' => '{% extends "base.html.twig" %}', - ))); - - $twig->loadTemplate('base.html.twig'); - } - - /** - * @expectedException Twig_Error_Runtime - * @expectedExceptionMessage Circular reference detected for Twig template "base1.html.twig", path: base1.html.twig -> base2.html.twig -> base1.html.twig in "base1.html.twig" at line 1 - */ - public function testFailLoadTemplateOnComplexCircularReference() - { - $twig = new Twig_Environment(new Twig_Loader_Array(array( - 'base1.html.twig' => '{% extends "base2.html.twig" %}', - 'base2.html.twig' => '{% extends "base1.html.twig" %}', - ))); - - $twig->loadTemplate('base1.html.twig'); - } - protected function getMockLoader($templateName, $templateContent) { // to be removed in 2.0 - $loader = $this->getMockBuilder('Twig_EnvironmentTestLoaderInterface')->getMock(); - //$loader = $this->getMockBuilder(array('Twig_LoaderInterface', 'Twig_SourceContextLoaderInterface'))->getMock(); + $loader = $this->createMock('Twig\Tests\EnvironmentTestLoaderInterface'); + //$loader = $this->createMock(['\Twig\Loader\LoaderInterface', '\Twig\Loader\SourceContextLoaderInterface']); $loader->expects($this->any()) ->method('getSourceContext') ->with($templateName) - ->will($this->returnValue(new Twig_Source($templateContent, $templateName))); + ->willReturn(new Source($templateContent, $templateName)); $loader->expects($this->any()) ->method('getCacheKey') ->with($templateName) - ->will($this->returnValue($templateName)); + ->willReturn($templateName); return $loader; } } -class Twig_Tests_EnvironmentTest_Extension_WithGlobals extends Twig_Extension +class EnvironmentTest_Extension_WithGlobals extends AbstractExtension { public function getGlobals() { - return array( + return [ 'foo_global' => 'foo_global', - ); + ]; } } -class Twig_Tests_EnvironmentTest_Extension extends Twig_Extension implements Twig_Extension_GlobalsInterface +class EnvironmentTest_Extension extends AbstractExtension implements GlobalsInterface { public function getTokenParsers() { - return array( - new Twig_Tests_EnvironmentTest_TokenParser(), - ); + return [ + new EnvironmentTest_TokenParser(), + ]; } public function getNodeVisitors() { - return array( - new Twig_Tests_EnvironmentTest_NodeVisitor(), - ); + return [ + new EnvironmentTest_NodeVisitor(), + ]; } public function getFilters() { - return array( - new Twig_SimpleFilter('foo_filter', 'foo_filter'), - ); + return [ + new TwigFilter('foo_filter', 'foo_filter'), + ]; } public function getTests() { - return array( - new Twig_SimpleTest('foo_test', 'foo_test'), - ); + return [ + new TwigTest('foo_test', 'foo_test'), + ]; } public function getFunctions() { - return array( - new Twig_SimpleFunction('foo_function', 'foo_function'), - ); + return [ + new TwigFunction('foo_function', 'foo_function'), + ]; } public function getOperators() { - return array( - array('foo_unary' => array()), - array('foo_binary' => array()), - ); + return [ + ['foo_unary' => []], + ['foo_binary' => []], + ]; } public function getGlobals() { - return array( + return [ 'foo_global' => 'foo_global', - ); + ]; } } -class_alias('Twig_Tests_EnvironmentTest_Extension', 'Twig\Tests\EnvironmentTest\Extension', false); +class_alias('\Twig\Tests\EnvironmentTest_Extension', 'Twig\Tests\EnvironmentTest\Extension', false); -class Twig_Tests_EnvironmentTest_Extension_WithDeprecatedName extends Twig_Extension +class EnvironmentTest_Extension_WithDeprecatedName extends AbstractExtension { public function getName() { @@ -597,7 +589,7 @@ class Twig_Tests_EnvironmentTest_Extension_WithDeprecatedName extends Twig_Exten } } -class Twig_Tests_EnvironmentTest_Extension_DynamicWithDeprecatedName extends Twig_Extension +class EnvironmentTest_Extension_DynamicWithDeprecatedName extends AbstractExtension { private $name; @@ -612,9 +604,9 @@ class Twig_Tests_EnvironmentTest_Extension_DynamicWithDeprecatedName extends Twi } } -class Twig_Tests_EnvironmentTest_TokenParser extends Twig_TokenParser +class EnvironmentTest_TokenParser extends AbstractTokenParser { - public function parse(Twig_Token $token) + public function parse(Token $token) { } @@ -624,14 +616,14 @@ class Twig_Tests_EnvironmentTest_TokenParser extends Twig_TokenParser } } -class Twig_Tests_EnvironmentTest_NodeVisitor implements Twig_NodeVisitorInterface +class EnvironmentTest_NodeVisitor implements NodeVisitorInterface { - public function enterNode(Twig_NodeInterface $node, Twig_Environment $env) + public function enterNode(\Twig_NodeInterface $node, Environment $env) { return $node; } - public function leaveNode(Twig_NodeInterface $node, Twig_Environment $env) + public function leaveNode(\Twig_NodeInterface $node, Environment $env) { return $node; } @@ -642,28 +634,28 @@ class Twig_Tests_EnvironmentTest_NodeVisitor implements Twig_NodeVisitorInterfac } } -class Twig_Tests_EnvironmentTest_ExtensionWithDeprecationInitRuntime extends Twig_Extension +class EnvironmentTest_ExtensionWithDeprecationInitRuntime extends AbstractExtension { - public function initRuntime(Twig_Environment $env) + public function initRuntime(Environment $env) { } } -class Twig_Tests_EnvironmentTest_ExtensionWithoutDeprecationInitRuntime extends Twig_Extension implements Twig_Extension_InitRuntimeInterface +class EnvironmentTest_ExtensionWithoutDeprecationInitRuntime extends AbstractExtension implements InitRuntimeInterface { - public function initRuntime(Twig_Environment $env) + public function initRuntime(Environment $env) { } } -class Twig_Tests_EnvironmentTest_ExtensionWithoutRuntime extends Twig_Extension +class EnvironmentTest_ExtensionWithoutRuntime extends AbstractExtension { public function getFunctions() { - return array( - new Twig_SimpleFunction('from_runtime_array', array('Twig_Tests_EnvironmentTest_Runtime', 'fromRuntime')), - new Twig_SimpleFunction('from_runtime_string', 'Twig_Tests_EnvironmentTest_Runtime::fromRuntime'), - ); + return [ + new TwigFunction('from_runtime_array', ['Twig\Tests\EnvironmentTest_Runtime', 'fromRuntime']), + new TwigFunction('from_runtime_string', 'Twig\Tests\EnvironmentTest_Runtime::fromRuntime'), + ]; } public function getName() @@ -672,7 +664,7 @@ class Twig_Tests_EnvironmentTest_ExtensionWithoutRuntime extends Twig_Extension } } -class Twig_Tests_EnvironmentTest_Runtime +class EnvironmentTest_Runtime { public function fromRuntime($name = 'bar') { @@ -681,6 +673,6 @@ class Twig_Tests_EnvironmentTest_Runtime } // to be removed in 2.0 -interface Twig_EnvironmentTestLoaderInterface extends Twig_LoaderInterface, Twig_SourceContextLoaderInterface +interface EnvironmentTestLoaderInterface extends LoaderInterface, SourceContextLoaderInterface { } diff --git a/vendor/twig/twig/test/Twig/Tests/ErrorTest.php b/vendor/twig/twig/tests/ErrorTest.php similarity index 59% rename from vendor/twig/twig/test/Twig/Tests/ErrorTest.php rename to vendor/twig/twig/tests/ErrorTest.php index 3ec572ab2deaaf7cf4e878401c02e605bc654ef8..a84da2eea65f5b68c67354bbf02e4aa4cdeea565 100644 --- a/vendor/twig/twig/test/Twig/Tests/ErrorTest.php +++ b/vendor/twig/twig/tests/ErrorTest.php @@ -1,5 +1,7 @@ <?php +namespace Twig\Tests; + /* * This file is part of Twig. * @@ -9,27 +11,34 @@ * file that was distributed with this source code. */ -class Twig_Tests_ErrorTest extends \PHPUnit\Framework\TestCase +use Twig\Environment; +use Twig\Error\Error; +use Twig\Error\RuntimeError; +use Twig\Loader\ArrayLoader; +use Twig\Loader\FilesystemLoader; +use Twig\Source; + +class ErrorTest extends \PHPUnit\Framework\TestCase { public function testErrorWithObjectFilename() { - $error = new Twig_Error('foo'); - $error->setSourceContext(new Twig_Source('', new SplFileInfo(__FILE__))); + $error = new Error('foo'); + $error->setSourceContext(new Source('', new \SplFileInfo(__FILE__))); - $this->assertContains('test'.DIRECTORY_SEPARATOR.'Twig'.DIRECTORY_SEPARATOR.'Tests'.DIRECTORY_SEPARATOR.'ErrorTest.php', $error->getMessage()); + $this->assertStringContainsString('tests'.\DIRECTORY_SEPARATOR.'ErrorTest.php', $error->getMessage()); } public function testErrorWithArrayFilename() { - $error = new Twig_Error('foo'); - $error->setSourceContext(new Twig_Source('', array('foo' => 'bar'))); + $error = new Error('foo'); + $error->setSourceContext(new Source('', ['foo' => 'bar'])); $this->assertEquals('foo in {"foo":"bar"}', $error->getMessage()); } public function testTwigExceptionGuessWithMissingVarAndArrayLoader() { - $loader = new Twig_Loader_Array(array( + $loader = new ArrayLoader([ 'base.html' => '{% block content %}{% endblock %}', 'index.html' => <<<EOHTML {% extends 'base.html' %} @@ -40,15 +49,15 @@ class Twig_Tests_ErrorTest extends \PHPUnit\Framework\TestCase {{ foo.bar }} {% endblock %} EOHTML - )); - $twig = new Twig_Environment($loader, array('strict_variables' => true, 'debug' => true, 'cache' => false)); + ]); + $twig = new Environment($loader, ['strict_variables' => true, 'debug' => true, 'cache' => false]); - $template = $twig->loadTemplate('index.html'); + $template = $twig->load('index.html'); try { - $template->render(array()); + $template->render([]); $this->fail(); - } catch (Twig_Error_Runtime $e) { + } catch (RuntimeError $e) { $this->assertEquals('Variable "foo" does not exist in "index.html" at line 3.', $e->getMessage()); $this->assertEquals(3, $e->getTemplateLine()); $this->assertEquals('index.html', $e->getSourceContext()->getName()); @@ -57,7 +66,7 @@ EOHTML public function testTwigExceptionGuessWithExceptionAndArrayLoader() { - $loader = new Twig_Loader_Array(array( + $loader = new ArrayLoader([ 'base.html' => '{% block content %}{% endblock %}', 'index.html' => <<<EOHTML {% extends 'base.html' %} @@ -68,15 +77,15 @@ EOHTML {{ foo.bar }} {% endblock %} EOHTML - )); - $twig = new Twig_Environment($loader, array('strict_variables' => true, 'debug' => true, 'cache' => false)); + ]); + $twig = new Environment($loader, ['strict_variables' => true, 'debug' => true, 'cache' => false]); - $template = $twig->loadTemplate('index.html'); + $template = $twig->load('index.html'); try { - $template->render(array('foo' => new Twig_Tests_ErrorTest_Foo())); + $template->render(['foo' => new ErrorTest_Foo()]); $this->fail(); - } catch (Twig_Error_Runtime $e) { + } catch (RuntimeError $e) { $this->assertEquals('An exception has been thrown during the rendering of a template ("Runtime error...") in "index.html" at line 3.', $e->getMessage()); $this->assertEquals(3, $e->getTemplateLine()); $this->assertEquals('index.html', $e->getSourceContext()->getName()); @@ -85,39 +94,39 @@ EOHTML public function testTwigExceptionGuessWithMissingVarAndFilesystemLoader() { - $loader = new Twig_Loader_Filesystem(dirname(__FILE__).'/Fixtures/errors'); - $twig = new Twig_Environment($loader, array('strict_variables' => true, 'debug' => true, 'cache' => false)); + $loader = new FilesystemLoader(__DIR__.'/Fixtures/errors'); + $twig = new Environment($loader, ['strict_variables' => true, 'debug' => true, 'cache' => false]); - $template = $twig->loadTemplate('index.html'); + $template = $twig->load('index.html'); try { - $template->render(array()); + $template->render([]); $this->fail(); - } catch (Twig_Error_Runtime $e) { + } catch (RuntimeError $e) { $this->assertEquals('Variable "foo" does not exist.', $e->getMessage()); $this->assertEquals(3, $e->getTemplateLine()); $this->assertEquals('index.html', $e->getSourceContext()->getName()); $this->assertEquals(3, $e->getLine()); - $this->assertEquals(strtr(dirname(__FILE__).'/Fixtures/errors/index.html', '/', DIRECTORY_SEPARATOR), $e->getFile()); + $this->assertEquals(strtr(__DIR__.'/Fixtures/errors/index.html', '/', \DIRECTORY_SEPARATOR), $e->getFile()); } } public function testTwigExceptionGuessWithExceptionAndFilesystemLoader() { - $loader = new Twig_Loader_Filesystem(dirname(__FILE__).'/Fixtures/errors'); - $twig = new Twig_Environment($loader, array('strict_variables' => true, 'debug' => true, 'cache' => false)); + $loader = new FilesystemLoader(__DIR__.'/Fixtures/errors'); + $twig = new Environment($loader, ['strict_variables' => true, 'debug' => true, 'cache' => false]); - $template = $twig->loadTemplate('index.html'); + $template = $twig->load('index.html'); try { - $template->render(array('foo' => new Twig_Tests_ErrorTest_Foo())); + $template->render(['foo' => new ErrorTest_Foo()]); $this->fail(); - } catch (Twig_Error_Runtime $e) { + } catch (RuntimeError $e) { $this->assertEquals('An exception has been thrown during the rendering of a template ("Runtime error...").', $e->getMessage()); $this->assertEquals(3, $e->getTemplateLine()); $this->assertEquals('index.html', $e->getSourceContext()->getName()); $this->assertEquals(3, $e->getLine()); - $this->assertEquals(strtr(dirname(__FILE__).'/Fixtures/errors/index.html', '/', DIRECTORY_SEPARATOR), $e->getFile()); + $this->assertEquals(strtr(__DIR__.'/Fixtures/errors/index.html', '/', \DIRECTORY_SEPARATOR), $e->getFile()); } } @@ -126,26 +135,26 @@ EOHTML */ public function testTwigExceptionAddsFileAndLine($templates, $name, $line) { - $loader = new Twig_Loader_Array($templates); - $twig = new Twig_Environment($loader, array('strict_variables' => true, 'debug' => true, 'cache' => false)); + $loader = new ArrayLoader($templates); + $twig = new Environment($loader, ['strict_variables' => true, 'debug' => true, 'cache' => false]); - $template = $twig->loadTemplate('index'); + $template = $twig->load('index'); try { - $template->render(array()); + $template->render([]); $this->fail(); - } catch (Twig_Error_Runtime $e) { + } catch (RuntimeError $e) { $this->assertEquals(sprintf('Variable "foo" does not exist in "%s" at line %d.', $name, $line), $e->getMessage()); $this->assertEquals($line, $e->getTemplateLine()); $this->assertEquals($name, $e->getSourceContext()->getName()); } try { - $template->render(array('foo' => new Twig_Tests_ErrorTest_Foo())); + $template->render(['foo' => new ErrorTest_Foo()]); $this->fail(); - } catch (Twig_Error_Runtime $e) { + } catch (RuntimeError $e) { $this->assertEquals(sprintf('An exception has been thrown during the rendering of a template ("Runtime error...") in "%s" at line %d.', $name, $line), $e->getMessage()); $this->assertEquals($line, $e->getTemplateLine()); $this->assertEquals($name, $e->getSourceContext()->getName()); @@ -154,39 +163,39 @@ EOHTML public function getErroredTemplates() { - return array( + return [ // error occurs in a template - array( - array( + [ + [ 'index' => "\n\n{{ foo.bar }}\n\n\n{{ 'foo' }}", - ), + ], 'index', 3, - ), + ], // error occurs in an included template - array( - array( + [ + [ 'index' => "{% include 'partial' %}", 'partial' => '{{ foo.bar }}', - ), + ], 'partial', 1, - ), + ], // error occurs in a parent block when called via parent() - array( - array( + [ + [ 'index' => "{% extends 'base' %} {% block content %} {{ parent() }} {% endblock %}", 'base' => '{% block content %}{{ foo.bar }}{% endblock %}', - ), + ], 'base', 1, - ), + ], // error occurs in a block from the child - array( - array( + [ + [ 'index' => "{% extends 'base' %} {% block content %} {{ foo.bar }} @@ -195,17 +204,31 @@ EOHTML {{ foo.bar }} {% endblock %}", 'base' => '{% block content %}{% endblock %}', - ), + ], 'index', 3, - ), - ); + ], + ]; + } + + public function testTwigLeakOutputInDebugMode() + { + $output = exec(sprintf('%s %s debug', \PHP_BINARY, escapeshellarg(__DIR__.'/Fixtures/errors/leak-output.php'))); + + $this->assertSame('Hello OOPS', $output); + } + + public function testDoesNotTwigLeakOutput() + { + $output = exec(sprintf('%s %s', \PHP_BINARY, escapeshellarg(__DIR__.'/Fixtures/errors/leak-output.php'))); + + $this->assertSame('', $output); } } -class Twig_Tests_ErrorTest_Foo +class ErrorTest_Foo { public function bar() { - throw new Exception('Runtime error...'); + throw new \Exception('Runtime error...'); } } diff --git a/vendor/twig/twig/tests/ExpressionParserTest.php b/vendor/twig/twig/tests/ExpressionParserTest.php new file mode 100644 index 0000000000000000000000000000000000000000..ef31fd7152c382e29f9d1f1213e30706040be7a3 --- /dev/null +++ b/vendor/twig/twig/tests/ExpressionParserTest.php @@ -0,0 +1,382 @@ +<?php + +namespace Twig\Tests; + +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use Twig\Environment; +use Twig\Node\Expression\ArrayExpression; +use Twig\Node\Expression\Binary\ConcatBinary; +use Twig\Node\Expression\ConstantExpression; +use Twig\Node\Expression\NameExpression; +use Twig\Parser; +use Twig\Source; + +class ExpressionParserTest extends \PHPUnit\Framework\TestCase +{ + /** + * @dataProvider getFailingTestsForAssignment + */ + public function testCanOnlyAssignToNames($template) + { + $this->expectException('\Twig\Error\SyntaxError'); + + $env = new Environment($this->createMock('\Twig\Loader\LoaderInterface'), ['cache' => false, 'autoescape' => false]); + $parser = new Parser($env); + + $parser->parse($env->tokenize(new Source($template, 'index'))); + } + + public function getFailingTestsForAssignment() + { + return [ + ['{% set false = "foo" %}'], + ['{% set FALSE = "foo" %}'], + ['{% set true = "foo" %}'], + ['{% set TRUE = "foo" %}'], + ['{% set none = "foo" %}'], + ['{% set NONE = "foo" %}'], + ['{% set null = "foo" %}'], + ['{% set NULL = "foo" %}'], + ['{% set 3 = "foo" %}'], + ['{% set 1 + 2 = "foo" %}'], + ['{% set "bar" = "foo" %}'], + ['{% set %}{% endset %}'], + ]; + } + + /** + * @dataProvider getTestsForArray + */ + public function testArrayExpression($template, $expected) + { + $env = new Environment($this->createMock('\Twig\Loader\LoaderInterface'), ['cache' => false, 'autoescape' => false]); + $stream = $env->tokenize($source = new Source($template, '')); + $parser = new Parser($env); + $expected->setSourceContext($source); + + $this->assertEquals($expected, $parser->parse($stream)->getNode('body')->getNode(0)->getNode('expr')); + } + + /** + * @dataProvider getFailingTestsForArray + */ + public function testArraySyntaxError($template) + { + $this->expectException('\Twig\Error\SyntaxError'); + + $env = new Environment($this->createMock('\Twig\Loader\LoaderInterface'), ['cache' => false, 'autoescape' => false]); + $parser = new Parser($env); + + $parser->parse($env->tokenize(new Source($template, 'index'))); + } + + public function getFailingTestsForArray() + { + return [ + ['{{ [1, "a": "b"] }}'], + ['{{ {"a": "b", 2} }}'], + ]; + } + + public function getTestsForArray() + { + return [ + // simple array + ['{{ [1, 2] }}', new ArrayExpression([ + new ConstantExpression(0, 1), + new ConstantExpression(1, 1), + + new ConstantExpression(1, 1), + new ConstantExpression(2, 1), + ], 1), + ], + + // array with trailing , + ['{{ [1, 2, ] }}', new ArrayExpression([ + new ConstantExpression(0, 1), + new ConstantExpression(1, 1), + + new ConstantExpression(1, 1), + new ConstantExpression(2, 1), + ], 1), + ], + + // simple hash + ['{{ {"a": "b", "b": "c"} }}', new ArrayExpression([ + new ConstantExpression('a', 1), + new ConstantExpression('b', 1), + + new ConstantExpression('b', 1), + new ConstantExpression('c', 1), + ], 1), + ], + + // hash with trailing , + ['{{ {"a": "b", "b": "c", } }}', new ArrayExpression([ + new ConstantExpression('a', 1), + new ConstantExpression('b', 1), + + new ConstantExpression('b', 1), + new ConstantExpression('c', 1), + ], 1), + ], + + // hash in an array + ['{{ [1, {"a": "b", "b": "c"}] }}', new ArrayExpression([ + new ConstantExpression(0, 1), + new ConstantExpression(1, 1), + + new ConstantExpression(1, 1), + new ArrayExpression([ + new ConstantExpression('a', 1), + new ConstantExpression('b', 1), + + new ConstantExpression('b', 1), + new ConstantExpression('c', 1), + ], 1), + ], 1), + ], + + // array in a hash + ['{{ {"a": [1, 2], "b": "c"} }}', new ArrayExpression([ + new ConstantExpression('a', 1), + new ArrayExpression([ + new ConstantExpression(0, 1), + new ConstantExpression(1, 1), + + new ConstantExpression(1, 1), + new ConstantExpression(2, 1), + ], 1), + new ConstantExpression('b', 1), + new ConstantExpression('c', 1), + ], 1), + ], + ]; + } + + public function testStringExpressionDoesNotConcatenateTwoConsecutiveStrings() + { + $this->expectException('\Twig\Error\SyntaxError'); + + $env = new Environment($this->createMock('\Twig\Loader\LoaderInterface'), ['cache' => false, 'autoescape' => false, 'optimizations' => 0]); + $stream = $env->tokenize(new Source('{{ "a" "b" }}', 'index')); + $parser = new Parser($env); + + $parser->parse($stream); + } + + /** + * @dataProvider getTestsForString + */ + public function testStringExpression($template, $expected) + { + $env = new Environment($this->createMock('\Twig\Loader\LoaderInterface'), ['cache' => false, 'autoescape' => false, 'optimizations' => 0]); + $stream = $env->tokenize($source = new Source($template, '')); + $parser = new Parser($env); + $expected->setSourceContext($source); + + $this->assertEquals($expected, $parser->parse($stream)->getNode('body')->getNode(0)->getNode('expr')); + } + + public function getTestsForString() + { + return [ + [ + '{{ "foo" }}', new ConstantExpression('foo', 1), + ], + [ + '{{ "foo #{bar}" }}', new ConcatBinary( + new ConstantExpression('foo ', 1), + new NameExpression('bar', 1), + 1 + ), + ], + [ + '{{ "foo #{bar} baz" }}', new ConcatBinary( + new ConcatBinary( + new ConstantExpression('foo ', 1), + new NameExpression('bar', 1), + 1 + ), + new ConstantExpression(' baz', 1), + 1 + ), + ], + + [ + '{{ "foo #{"foo #{bar} baz"} baz" }}', new ConcatBinary( + new ConcatBinary( + new ConstantExpression('foo ', 1), + new ConcatBinary( + new ConcatBinary( + new ConstantExpression('foo ', 1), + new NameExpression('bar', 1), + 1 + ), + new ConstantExpression(' baz', 1), + 1 + ), + 1 + ), + new ConstantExpression(' baz', 1), + 1 + ), + ], + ]; + } + + public function testAttributeCallDoesNotSupportNamedArguments() + { + $this->expectException('\Twig\Error\SyntaxError'); + + $env = new Environment($this->createMock('\Twig\Loader\LoaderInterface'), ['cache' => false, 'autoescape' => false]); + $parser = new Parser($env); + + $parser->parse($env->tokenize(new Source('{{ foo.bar(name="Foo") }}', 'index'))); + } + + public function testMacroCallDoesNotSupportNamedArguments() + { + $this->expectException('\Twig\Error\SyntaxError'); + + $env = new Environment($this->createMock('\Twig\Loader\LoaderInterface'), ['cache' => false, 'autoescape' => false]); + $parser = new Parser($env); + + $parser->parse($env->tokenize(new Source('{% from _self import foo %}{% macro foo() %}{% endmacro %}{{ foo(name="Foo") }}', 'index'))); + } + + public function testMacroDefinitionDoesNotSupportNonNameVariableName() + { + $this->expectException('\Twig\Error\SyntaxError'); + $this->expectExceptionMessage('An argument must be a name. Unexpected token "string" of value "a" ("name" expected) in "index" at line 1.'); + + $env = new Environment($this->createMock('\Twig\Loader\LoaderInterface'), ['cache' => false, 'autoescape' => false]); + $parser = new Parser($env); + + $parser->parse($env->tokenize(new Source('{% macro foo("a") %}{% endmacro %}', 'index'))); + } + + /** + * @dataProvider getMacroDefinitionDoesNotSupportNonConstantDefaultValues + */ + public function testMacroDefinitionDoesNotSupportNonConstantDefaultValues($template) + { + $this->expectException('\Twig\Error\SyntaxError'); + $this->expectExceptionMessage('A default value for an argument must be a constant (a boolean, a string, a number, or an array) in "index" at line 1'); + + $env = new Environment($this->createMock('\Twig\Loader\LoaderInterface'), ['cache' => false, 'autoescape' => false]); + $parser = new Parser($env); + + $parser->parse($env->tokenize(new Source($template, 'index'))); + } + + public function getMacroDefinitionDoesNotSupportNonConstantDefaultValues() + { + return [ + ['{% macro foo(name = "a #{foo} a") %}{% endmacro %}'], + ['{% macro foo(name = [["b", "a #{foo} a"]]) %}{% endmacro %}'], + ]; + } + + /** + * @dataProvider getMacroDefinitionSupportsConstantDefaultValues + */ + public function testMacroDefinitionSupportsConstantDefaultValues($template) + { + $env = new Environment($this->createMock('\Twig\Loader\LoaderInterface'), ['cache' => false, 'autoescape' => false]); + $parser = new Parser($env); + + $parser->parse($env->tokenize(new Source($template, 'index'))); + + // add a dummy assertion here to satisfy PHPUnit, the only thing we want to test is that the code above + // can be executed without throwing any exceptions + $this->addToAssertionCount(1); + } + + public function getMacroDefinitionSupportsConstantDefaultValues() + { + return [ + ['{% macro foo(name = "aa") %}{% endmacro %}'], + ['{% macro foo(name = 12) %}{% endmacro %}'], + ['{% macro foo(name = true) %}{% endmacro %}'], + ['{% macro foo(name = ["a"]) %}{% endmacro %}'], + ['{% macro foo(name = [["a"]]) %}{% endmacro %}'], + ['{% macro foo(name = {a: "a"}) %}{% endmacro %}'], + ['{% macro foo(name = {a: {b: "a"}}) %}{% endmacro %}'], + ]; + } + + public function testUnknownFunction() + { + $this->expectException('\Twig\Error\SyntaxError'); + $this->expectExceptionMessage('Unknown "cycl" function. Did you mean "cycle" in "index" at line 1?'); + + $env = new Environment($this->createMock('\Twig\Loader\LoaderInterface'), ['cache' => false, 'autoescape' => false]); + $parser = new Parser($env); + + $parser->parse($env->tokenize(new Source('{{ cycl() }}', 'index'))); + } + + public function testUnknownFunctionWithoutSuggestions() + { + $this->expectException('\Twig\Error\SyntaxError'); + $this->expectExceptionMessage('Unknown "foobar" function in "index" at line 1.'); + + $env = new Environment($this->createMock('\Twig\Loader\LoaderInterface'), ['cache' => false, 'autoescape' => false]); + $parser = new Parser($env); + + $parser->parse($env->tokenize(new Source('{{ foobar() }}', 'index'))); + } + + public function testUnknownFilter() + { + $this->expectException('\Twig\Error\SyntaxError'); + $this->expectExceptionMessage('Unknown "lowe" filter. Did you mean "lower" in "index" at line 1?'); + + $env = new Environment($this->createMock('\Twig\Loader\LoaderInterface'), ['cache' => false, 'autoescape' => false]); + $parser = new Parser($env); + + $parser->parse($env->tokenize(new Source('{{ 1|lowe }}', 'index'))); + } + + public function testUnknownFilterWithoutSuggestions() + { + $this->expectException('\Twig\Error\SyntaxError'); + $this->expectExceptionMessage('Unknown "foobar" filter in "index" at line 1.'); + + $env = new Environment($this->createMock('\Twig\Loader\LoaderInterface'), ['cache' => false, 'autoescape' => false]); + $parser = new Parser($env); + + $parser->parse($env->tokenize(new Source('{{ 1|foobar }}', 'index'))); + } + + public function testUnknownTest() + { + $this->expectException('\Twig\Error\SyntaxError'); + $this->expectExceptionMessage('Unknown "nul" test. Did you mean "null" in "index" at line 1'); + + $env = new Environment($this->createMock('\Twig\Loader\LoaderInterface'), ['cache' => false, 'autoescape' => false]); + $parser = new Parser($env); + $stream = $env->tokenize(new Source('{{ 1 is nul }}', 'index')); + $parser->parse($stream); + } + + public function testUnknownTestWithoutSuggestions() + { + $this->expectException('\Twig\Error\SyntaxError'); + $this->expectExceptionMessage('Unknown "foobar" test in "index" at line 1.'); + + $env = new Environment($this->createMock('\Twig\Loader\LoaderInterface'), ['cache' => false, 'autoescape' => false]); + $parser = new Parser($env); + + $parser->parse($env->tokenize(new Source('{{ 1 is foobar }}', 'index'))); + } +} diff --git a/vendor/twig/twig/tests/Extension/CoreTest.php b/vendor/twig/twig/tests/Extension/CoreTest.php new file mode 100644 index 0000000000000000000000000000000000000000..66c32ff150e92ac1fa2ab8e5439acd8c80850bff --- /dev/null +++ b/vendor/twig/twig/tests/Extension/CoreTest.php @@ -0,0 +1,371 @@ +<?php + +namespace Twig\Tests\Extension; + +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use Twig\Environment; + +class CoreTest extends \PHPUnit\Framework\TestCase +{ + /** + * @dataProvider getRandomFunctionTestData + */ + public function testRandomFunction(array $expectedInArray, $value1, $value2 = null) + { + $env = new Environment($this->createMock('Twig_LoaderInterface')); + for ($i = 0; $i < 100; ++$i) { + $this->assertTrue(\in_array(twig_random($env, $value1, $value2), $expectedInArray, true)); // assertContains() would not consider the type + } + } + + public function getRandomFunctionTestData() + { + return [ + 'array' => [ + ['apple', 'orange', 'citrus'], + ['apple', 'orange', 'citrus'], + ], + 'Traversable' => [ + ['apple', 'orange', 'citrus'], + new \ArrayObject(['apple', 'orange', 'citrus']), + ], + 'unicode string' => [ + ['Ä', '€', 'é'], + 'Ä€é', + ], + 'numeric but string' => [ + ['1', '2', '3'], + '123', + ], + 'integer' => [ + range(0, 5, 1), + 5, + ], + 'float' => [ + range(0, 5, 1), + 5.9, + ], + 'negative' => [ + [0, -1, -2], + -2, + ], + 'min max int' => [ + range(50, 100), + 50, + 100, + ], + 'min max float' => [ + range(-10, 10), + -9.5, + 9.5, + ], + 'min null' => [ + range(0, 100), + null, + 100, + ], + ]; + } + + public function testRandomFunctionWithoutParameter() + { + $max = mt_getrandmax(); + + for ($i = 0; $i < 100; ++$i) { + $val = twig_random(new Environment($this->createMock('\Twig\Loader\LoaderInterface'))); + $this->assertTrue(\is_int($val) && $val >= 0 && $val <= $max); + } + } + + public function testRandomFunctionReturnsAsIs() + { + $this->assertSame('', twig_random(new Environment($this->createMock('\Twig\Loader\LoaderInterface')), '')); + $this->assertSame('', twig_random(new Environment($this->createMock('\Twig\Loader\LoaderInterface'), ['charset' => null]), '')); + + $instance = new \stdClass(); + $this->assertSame($instance, twig_random(new Environment($this->createMock('\Twig\Loader\LoaderInterface')), $instance)); + } + + public function testRandomFunctionOfEmptyArrayThrowsException() + { + $this->expectException('\Twig\Error\RuntimeError'); + + twig_random(new Environment($this->createMock('\Twig\Loader\LoaderInterface')), []); + } + + public function testRandomFunctionOnNonUTF8String() + { + if (!\function_exists('iconv') && !\function_exists('mb_convert_encoding')) { + $this->markTestSkipped('needs iconv or mbstring'); + } + + $twig = new Environment($this->createMock('\Twig\Loader\LoaderInterface')); + $twig->setCharset('ISO-8859-1'); + + $text = twig_convert_encoding('Äé', 'ISO-8859-1', 'UTF-8'); + for ($i = 0; $i < 30; ++$i) { + $rand = twig_random($twig, $text); + $this->assertTrue(\in_array(twig_convert_encoding($rand, 'UTF-8', 'ISO-8859-1'), ['Ä', 'é'], true)); + } + } + + public function testReverseFilterOnNonUTF8String() + { + if (!\function_exists('iconv') && !\function_exists('mb_convert_encoding')) { + $this->markTestSkipped('needs iconv or mbstring'); + } + + $twig = new Environment($this->createMock('\Twig\Loader\LoaderInterface')); + $twig->setCharset('ISO-8859-1'); + + $input = twig_convert_encoding('Äé', 'ISO-8859-1', 'UTF-8'); + $output = twig_convert_encoding(twig_reverse_filter($twig, $input), 'UTF-8', 'ISO-8859-1'); + + $this->assertEquals($output, 'éÄ'); + } + + /** + * @dataProvider provideCustomEscaperCases + */ + public function testCustomEscaper($expected, $string, $strategy) + { + $twig = new Environment($this->createMock('\Twig\Loader\LoaderInterface')); + $twig->getExtension('\Twig\Extension\CoreExtension')->setEscaper('foo', '\Twig\Tests\Extension\foo_escaper_for_test'); + + $this->assertSame($expected, twig_escape_filter($twig, $string, $strategy)); + } + + public function provideCustomEscaperCases() + { + return [ + ['fooUTF-8', 'foo', 'foo'], + ['UTF-8', null, 'foo'], + ['42UTF-8', 42, 'foo'], + ]; + } + + public function testUnknownCustomEscaper() + { + $this->expectException('\Twig\Error\RuntimeError'); + + twig_escape_filter(new Environment($this->createMock('\Twig\Loader\LoaderInterface')), 'foo', 'bar'); + } + + /** + * @dataProvider provideTwigFirstCases + */ + public function testTwigFirst($expected, $input) + { + $twig = new Environment($this->createMock('\Twig\Loader\LoaderInterface')); + $this->assertSame($expected, twig_first($twig, $input)); + } + + public function provideTwigFirstCases() + { + $i = [1 => 'a', 2 => 'b', 3 => 'c']; + + return [ + ['a', 'abc'], + [1, [1, 2, 3]], + ['', null], + ['', ''], + ['a', new CoreTestIterator($i, array_keys($i), true, 3)], + ]; + } + + /** + * @dataProvider provideTwigLastCases + */ + public function testTwigLast($expected, $input) + { + $twig = new Environment($this->createMock('\Twig\Loader\LoaderInterface')); + $this->assertSame($expected, twig_last($twig, $input)); + } + + public function provideTwigLastCases() + { + $i = [1 => 'a', 2 => 'b', 3 => 'c']; + + return [ + ['c', 'abc'], + [3, [1, 2, 3]], + ['', null], + ['', ''], + ['c', new CoreTestIterator($i, array_keys($i), true)], + ]; + } + + /** + * @dataProvider provideArrayKeyCases + */ + public function testArrayKeysFilter(array $expected, $input) + { + $this->assertSame($expected, twig_get_array_keys_filter($input)); + } + + public function provideArrayKeyCases() + { + $array = ['a' => 'a1', 'b' => 'b1', 'c' => 'c1']; + $keys = array_keys($array); + + return [ + [$keys, $array], + [$keys, new CoreTestIterator($array, $keys)], + [$keys, new CoreTestIteratorAggregate($array, $keys)], + [$keys, new CoreTestIteratorAggregateAggregate($array, $keys)], + [[], null], + [['a'], new \SimpleXMLElement('<xml><a></a></xml>')], + ]; + } + + /** + * @dataProvider provideInFilterCases + */ + public function testInFilter($expected, $value, $compare) + { + $this->assertSame($expected, twig_in_filter($value, $compare)); + } + + public function provideInFilterCases() + { + $array = [1, 2, 'a' => 3, 5, 6, 7]; + $keys = array_keys($array); + + return [ + [true, 1, $array], + [true, '3', $array], + [true, '3', 'abc3def'], + [true, 1, new CoreTestIterator($array, $keys, true, 1)], + [true, '3', new CoreTestIterator($array, $keys, true, 3)], + [true, '3', new CoreTestIteratorAggregateAggregate($array, $keys, true, 3)], + [false, 4, $array], + [false, 4, new CoreTestIterator($array, $keys, true)], + [false, 4, new CoreTestIteratorAggregateAggregate($array, $keys, true)], + [false, 1, 1], + [true, 'b', new \SimpleXMLElement('<xml><a>b</a></xml>')], + ]; + } + + /** + * @dataProvider provideSliceFilterCases + */ + public function testSliceFilter($expected, $input, $start, $length = null, $preserveKeys = false) + { + $twig = new Environment($this->createMock('\Twig\Loader\LoaderInterface')); + $this->assertSame($expected, twig_slice($twig, $input, $start, $length, $preserveKeys)); + } + + public function provideSliceFilterCases() + { + $i = ['a' => 1, 'b' => 2, 'c' => 3, 'd' => 4]; + $keys = array_keys($i); + + return [ + [['a' => 1], $i, 0, 1, true], + [['a' => 1], $i, 0, 1, false], + [['b' => 2, 'c' => 3], $i, 1, 2], + [[1], [1, 2, 3, 4], 0, 1], + [[2, 3], [1, 2, 3, 4], 1, 2], + [[2, 3], new CoreTestIterator($i, $keys, true), 1, 2], + [['c' => 3, 'd' => 4], new CoreTestIteratorAggregate($i, $keys, true), 2, null, true], + [$i, new CoreTestIterator($i, $keys, true), 0, \count($keys) + 10, true], + [[], new CoreTestIterator($i, $keys, true), \count($keys) + 10], + ['de', 'abcdef', 3, 2], + [[], new \SimpleXMLElement('<items><item>1</item><item>2</item></items>'), 3], + [[], new \ArrayIterator([1, 2]), 3], + ]; + } +} + +function foo_escaper_for_test(Environment $env, $string, $charset) +{ + return $string.$charset; +} + +final class CoreTestIteratorAggregate implements \IteratorAggregate +{ + private $iterator; + + public function __construct(array $array, array $keys, $allowAccess = false, $maxPosition = false) + { + $this->iterator = new CoreTestIterator($array, $keys, $allowAccess, $maxPosition); + } + + public function getIterator() + { + return $this->iterator; + } +} + +final class CoreTestIteratorAggregateAggregate implements \IteratorAggregate +{ + private $iterator; + + public function __construct(array $array, array $keys, $allowValueAccess = false, $maxPosition = false) + { + $this->iterator = new CoreTestIteratorAggregate($array, $keys, $allowValueAccess, $maxPosition); + } + + public function getIterator() + { + return $this->iterator; + } +} + +final class CoreTestIterator implements \Iterator +{ + private $position; + private $array; + private $arrayKeys; + private $allowValueAccess; + private $maxPosition; + + public function __construct(array $values, array $keys, $allowValueAccess = false, $maxPosition = false) + { + $this->array = $values; + $this->arrayKeys = $keys; + $this->position = 0; + $this->allowValueAccess = $allowValueAccess; + $this->maxPosition = false === $maxPosition ? \count($values) + 1 : $maxPosition; + } + + public function rewind() + { + $this->position = 0; + } + + public function current() + { + if ($this->allowValueAccess) { + return $this->array[$this->key()]; + } + + throw new \LogicException('Code should only use the keys, not the values provided by iterator.'); + } + + public function key() + { + return $this->arrayKeys[$this->position]; + } + + public function next() + { + ++$this->position; + if ($this->position === $this->maxPosition) { + throw new \LogicException(sprintf('Code should not iterate beyond %d.', $this->maxPosition)); + } + } + + public function valid() + { + return isset($this->arrayKeys[$this->position]); + } +} diff --git a/vendor/twig/twig/tests/Extension/SandboxTest.php b/vendor/twig/twig/tests/Extension/SandboxTest.php new file mode 100644 index 0000000000000000000000000000000000000000..fe0f32ff55d5a395d3fe6c397c3d6c179132223b --- /dev/null +++ b/vendor/twig/twig/tests/Extension/SandboxTest.php @@ -0,0 +1,365 @@ +<?php + +namespace Twig\Tests\Extension; + +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use Twig\Environment; +use Twig\Extension\SandboxExtension; +use Twig\Loader\ArrayLoader; +use Twig\Sandbox\SecurityError; +use Twig\Sandbox\SecurityPolicy; + +class SandboxTest extends \PHPUnit\Framework\TestCase +{ + protected static $params; + protected static $templates; + + protected function setUp() + { + self::$params = [ + 'name' => 'Fabien', + 'obj' => new FooObject(), + 'arr' => ['obj' => new FooObject()], + ]; + + self::$templates = [ + '1_basic1' => '{{ obj.foo }}', + '1_basic2' => '{{ name|upper }}', + '1_basic3' => '{% if name %}foo{% endif %}', + '1_basic4' => '{{ obj.bar }}', + '1_basic5' => '{{ obj }}', + '1_basic7' => '{{ cycle(["foo","bar"], 1) }}', + '1_basic8' => '{{ obj.getfoobar }}{{ obj.getFooBar }}', + '1_basic9' => '{{ obj.foobar }}{{ obj.fooBar }}', + '1_basic' => '{% if obj.foo %}{{ obj.foo|upper }}{% endif %}', + '1_layout' => '{% block content %}{% endblock %}', + '1_child' => "{% extends \"1_layout\" %}\n{% block content %}\n{{ \"a\"|json_encode }}\n{% endblock %}", + '1_include' => '{{ include("1_basic1", sandboxed=true) }}', + '1_range_operator' => '{{ (1..2)[0] }}', + ]; + } + + public function testSandboxWithInheritance() + { + $this->expectException('\Twig\Sandbox\SecurityError'); + $this->expectExceptionMessage('Filter "json_encode" is not allowed in "1_child" at line 3.'); + + $twig = $this->getEnvironment(true, [], self::$templates, ['block']); + $twig->load('1_child')->render([]); + } + + public function testSandboxGloballySet() + { + $twig = $this->getEnvironment(false, [], self::$templates); + $this->assertEquals('FOO', $twig->load('1_basic')->render(self::$params), 'Sandbox does nothing if it is disabled globally'); + } + + public function testSandboxUnallowedMethodAccessor() + { + $twig = $this->getEnvironment(true, [], self::$templates); + try { + $twig->load('1_basic1')->render(self::$params); + $this->fail('Sandbox throws a SecurityError exception if an unallowed method is called'); + } catch (SecurityError $e) { + $this->assertInstanceOf('\Twig\Sandbox\SecurityNotAllowedMethodError', $e, 'Exception should be an instance of Twig_Sandbox_SecurityNotAllowedMethodError'); + $this->assertEquals('Twig\Tests\Extension\FooObject', $e->getClassName(), 'Exception should be raised on the "Twig\Tests\Extension\FooObject" class'); + $this->assertEquals('foo', $e->getMethodName(), 'Exception should be raised on the "foo" method'); + } + } + + public function testSandboxUnallowedFilter() + { + $twig = $this->getEnvironment(true, [], self::$templates); + try { + $twig->load('1_basic2')->render(self::$params); + $this->fail('Sandbox throws a SecurityError exception if an unallowed filter is called'); + } catch (SecurityError $e) { + $this->assertInstanceOf('\Twig\Sandbox\SecurityNotAllowedFilterError', $e, 'Exception should be an instance of Twig_Sandbox_SecurityNotAllowedFilterError'); + $this->assertEquals('upper', $e->getFilterName(), 'Exception should be raised on the "upper" filter'); + } + } + + public function testSandboxUnallowedTag() + { + $twig = $this->getEnvironment(true, [], self::$templates); + try { + $twig->load('1_basic3')->render(self::$params); + $this->fail('Sandbox throws a SecurityError exception if an unallowed tag is used in the template'); + } catch (SecurityError $e) { + $this->assertInstanceOf('\Twig\Sandbox\SecurityNotAllowedTagError', $e, 'Exception should be an instance of Twig_Sandbox_SecurityNotAllowedTagError'); + $this->assertEquals('if', $e->getTagName(), 'Exception should be raised on the "if" tag'); + } + } + + public function testSandboxUnallowedProperty() + { + $twig = $this->getEnvironment(true, [], self::$templates); + try { + $twig->load('1_basic4')->render(self::$params); + $this->fail('Sandbox throws a SecurityError exception if an unallowed property is called in the template'); + } catch (SecurityError $e) { + $this->assertInstanceOf('\Twig\Sandbox\SecurityNotAllowedPropertyError', $e, 'Exception should be an instance of Twig_Sandbox_SecurityNotAllowedPropertyError'); + $this->assertEquals('Twig\Tests\Extension\FooObject', $e->getClassName(), 'Exception should be raised on the "Twig\Tests\Extension\FooObject" class'); + $this->assertEquals('bar', $e->getPropertyName(), 'Exception should be raised on the "bar" property'); + } + } + + /** + * @dataProvider getSandboxUnallowedToStringTests + */ + public function testSandboxUnallowedToString($template) + { + $twig = $this->getEnvironment(true, [], ['index' => $template], [], ['upper'], ['Twig\Tests\Extension\FooObject' => 'getAnotherFooObject'], [], ['random']); + try { + $twig->load('index')->render(self::$params); + $this->fail('Sandbox throws a SecurityError exception if an unallowed method (__toString()) is called in the template'); + } catch (SecurityError $e) { + $this->assertInstanceOf('\Twig\Sandbox\SecurityNotAllowedMethodError', $e, 'Exception should be an instance of Twig_Sandbox_SecurityNotAllowedMethodError'); + $this->assertEquals('Twig\Tests\Extension\FooObject', $e->getClassName(), 'Exception should be raised on the "Twig\Tests\Extension\FooObject" class'); + $this->assertEquals('__tostring', $e->getMethodName(), 'Exception should be raised on the "__toString" method'); + } + } + + public function getSandboxUnallowedToStringTests() + { + return [ + 'simple' => ['{{ obj }}'], + 'object_from_array' => ['{{ arr.obj }}'], + 'object_chain' => ['{{ obj.anotherFooObject }}'], + 'filter' => ['{{ obj|upper }}'], + 'filter_from_array' => ['{{ arr.obj|upper }}'], + 'function' => ['{{ random(obj) }}'], + 'function_from_array' => ['{{ random(arr.obj) }}'], + 'function_and_filter' => ['{{ random(obj|upper) }}'], + 'function_and_filter_from_array' => ['{{ random(arr.obj|upper) }}'], + 'object_chain_and_filter' => ['{{ obj.anotherFooObject|upper }}'], + 'object_chain_and_function' => ['{{ random(obj.anotherFooObject) }}'], + 'concat' => ['{{ obj ~ "" }}'], + 'concat_again' => ['{{ "" ~ obj }}'], + ]; + } + + /** + * @dataProvider getSandboxAllowedToStringTests + */ + public function testSandboxAllowedToString($template, $output) + { + $twig = $this->getEnvironment(true, [], ['index' => $template], ['set'], [], ['Twig\Tests\Extension\FooObject' => ['foo', 'getAnotherFooObject']]); + $this->assertEquals($output, $twig->load('index')->render(self::$params)); + } + + public function getSandboxAllowedToStringTests() + { + return [ + 'constant_test' => ['{{ obj is constant("PHP_INT_MAX") }}', ''], + 'set_object' => ['{% set a = obj.anotherFooObject %}{{ a.foo }}', 'foo'], + 'is_defined' => ['{{ obj.anotherFooObject is defined }}', '1'], + 'is_null' => ['{{ obj is null }}', ''], + 'is_sameas' => ['{{ obj is same as(obj) }}', '1'], + 'is_sameas_from_array' => ['{{ arr.obj is same as(arr.obj) }}', '1'], + 'is_sameas_from_another_method' => ['{{ obj.anotherFooObject is same as(obj.anotherFooObject) }}', ''], + ]; + } + + public function testSandboxAllowMethodToString() + { + $twig = $this->getEnvironment(true, [], self::$templates, [], [], ['Twig\Tests\Extension\FooObject' => '__toString']); + FooObject::reset(); + $this->assertEquals('foo', $twig->load('1_basic5')->render(self::$params), 'Sandbox allow some methods'); + $this->assertEquals(1, FooObject::$called['__toString'], 'Sandbox only calls method once'); + } + + public function testSandboxAllowMethodToStringDisabled() + { + $twig = $this->getEnvironment(false, [], self::$templates); + FooObject::reset(); + $this->assertEquals('foo', $twig->load('1_basic5')->render(self::$params), 'Sandbox allows __toString when sandbox disabled'); + $this->assertEquals(1, FooObject::$called['__toString'], 'Sandbox only calls method once'); + } + + public function testSandboxUnallowedFunction() + { + $twig = $this->getEnvironment(true, [], self::$templates); + try { + $twig->load('1_basic7')->render(self::$params); + $this->fail('Sandbox throws a SecurityError exception if an unallowed function is called in the template'); + } catch (SecurityError $e) { + $this->assertInstanceOf('\Twig\Sandbox\SecurityNotAllowedFunctionError', $e, 'Exception should be an instance of Twig_Sandbox_SecurityNotAllowedFunctionError'); + $this->assertEquals('cycle', $e->getFunctionName(), 'Exception should be raised on the "cycle" function'); + } + } + + public function testSandboxUnallowedRangeOperator() + { + $twig = $this->getEnvironment(true, [], self::$templates); + try { + $twig->load('1_range_operator')->render(self::$params); + $this->fail('Sandbox throws a SecurityError exception if the unallowed range operator is called'); + } catch (SecurityError $e) { + $this->assertInstanceOf('\Twig\Sandbox\SecurityNotAllowedFunctionError', $e, 'Exception should be an instance of Twig_Sandbox_SecurityNotAllowedFunctionError'); + $this->assertEquals('range', $e->getFunctionName(), 'Exception should be raised on the "range" function'); + } + } + + public function testSandboxAllowMethodFoo() + { + $twig = $this->getEnvironment(true, [], self::$templates, [], [], ['Twig\Tests\Extension\FooObject' => 'foo']); + FooObject::reset(); + $this->assertEquals('foo', $twig->load('1_basic1')->render(self::$params), 'Sandbox allow some methods'); + $this->assertEquals(1, FooObject::$called['foo'], 'Sandbox only calls method once'); + } + + public function testSandboxAllowFilter() + { + $twig = $this->getEnvironment(true, [], self::$templates, [], ['upper']); + $this->assertEquals('FABIEN', $twig->load('1_basic2')->render(self::$params), 'Sandbox allow some filters'); + } + + public function testSandboxAllowTag() + { + $twig = $this->getEnvironment(true, [], self::$templates, ['if']); + $this->assertEquals('foo', $twig->load('1_basic3')->render(self::$params), 'Sandbox allow some tags'); + } + + public function testSandboxAllowProperty() + { + $twig = $this->getEnvironment(true, [], self::$templates, [], [], [], ['Twig\Tests\Extension\FooObject' => 'bar']); + $this->assertEquals('bar', $twig->load('1_basic4')->render(self::$params), 'Sandbox allow some properties'); + } + + public function testSandboxAllowFunction() + { + $twig = $this->getEnvironment(true, [], self::$templates, [], [], [], [], ['cycle']); + $this->assertEquals('bar', $twig->load('1_basic7')->render(self::$params), 'Sandbox allow some functions'); + } + + public function testSandboxAllowRangeOperator() + { + $twig = $this->getEnvironment(true, [], self::$templates, [], [], [], [], ['range']); + $this->assertEquals('1', $twig->load('1_range_operator')->render(self::$params), 'Sandbox allow the range operator'); + } + + public function testSandboxAllowFunctionsCaseInsensitive() + { + foreach (['getfoobar', 'getFoobar', 'getFooBar'] as $name) { + $twig = $this->getEnvironment(true, [], self::$templates, [], [], ['Twig\Tests\Extension\FooObject' => $name]); + FooObject::reset(); + $this->assertEquals('foobarfoobar', $twig->load('1_basic8')->render(self::$params), 'Sandbox allow methods in a case-insensitive way'); + $this->assertEquals(2, FooObject::$called['getFooBar'], 'Sandbox only calls method once'); + + $this->assertEquals('foobarfoobar', $twig->load('1_basic9')->render(self::$params), 'Sandbox allow methods via shortcut names (ie. without get/set)'); + } + } + + public function testSandboxLocallySetForAnInclude() + { + self::$templates = [ + '2_basic' => '{{ obj.foo }}{% include "2_included" %}{{ obj.foo }}', + '2_included' => '{% if obj.foo %}{{ obj.foo|upper }}{% endif %}', + ]; + + $twig = $this->getEnvironment(false, [], self::$templates); + $this->assertEquals('fooFOOfoo', $twig->load('2_basic')->render(self::$params), 'Sandbox does nothing if disabled globally and sandboxed not used for the include'); + + self::$templates = [ + '3_basic' => '{{ obj.foo }}{% sandbox %}{% include "3_included" %}{% endsandbox %}{{ obj.foo }}', + '3_included' => '{% if obj.foo %}{{ obj.foo|upper }}{% endif %}', + ]; + + $twig = $this->getEnvironment(true, [], self::$templates); + try { + $twig->load('3_basic')->render(self::$params); + $this->fail('Sandbox throws a SecurityError exception when the included file is sandboxed'); + } catch (SecurityError $e) { + $this->assertInstanceOf('\Twig\Sandbox\SecurityNotAllowedTagError', $e, 'Exception should be an instance of Twig_Sandbox_SecurityNotAllowedTagError'); + $this->assertEquals('sandbox', $e->getTagName()); + } + } + + public function testMacrosInASandbox() + { + $twig = $this->getEnvironment(true, ['autoescape' => 'html'], ['index' => <<<EOF +{%- import _self as macros %} + +{%- macro test(text) %}<p>{{ text }}</p>{% endmacro %} + +{{- macros.test('username') }} +EOF + ], ['macro', 'import'], ['escape']); + + $this->assertEquals('<p>username</p>', $twig->load('index')->render([])); + } + + public function testSandboxDisabledAfterIncludeFunctionError() + { + $twig = $this->getEnvironment(false, [], self::$templates); + + $e = null; + try { + $twig->load('1_include')->render(self::$params); + } catch (\Throwable $e) { + } catch (\Exception $e) { + } + if (null === $e) { + $this->fail('An exception should be thrown for this test to be valid.'); + } + + $this->assertFalse($twig->getExtension('\Twig\Extension\SandboxExtension')->isSandboxed(), 'Sandboxed include() function call should not leave Sandbox enabled when an error occurs.'); + } + + protected function getEnvironment($sandboxed, $options, $templates, $tags = [], $filters = [], $methods = [], $properties = [], $functions = []) + { + $loader = new ArrayLoader($templates); + $twig = new Environment($loader, array_merge(['debug' => true, 'cache' => false, 'autoescape' => false], $options)); + $policy = new SecurityPolicy($tags, $filters, $methods, $properties, $functions); + $twig->addExtension(new SandboxExtension($policy, $sandboxed)); + + return $twig; + } +} + +class FooObject +{ + public static $called = ['__toString' => 0, 'foo' => 0, 'getFooBar' => 0]; + + public $bar = 'bar'; + + public static function reset() + { + self::$called = ['__toString' => 0, 'foo' => 0, 'getFooBar' => 0]; + } + + public function __toString() + { + ++self::$called['__toString']; + + return 'foo'; + } + + public function foo() + { + ++self::$called['foo']; + + return 'foo'; + } + + public function getFooBar() + { + ++self::$called['getFooBar']; + + return 'foobar'; + } + + public function getAnotherFooObject() + { + return new self(); + } +} diff --git a/vendor/twig/twig/test/Twig/Tests/FactoryRuntimeLoaderTest.php b/vendor/twig/twig/tests/FactoryRuntimeLoaderTest.php similarity index 61% rename from vendor/twig/twig/test/Twig/Tests/FactoryRuntimeLoaderTest.php rename to vendor/twig/twig/tests/FactoryRuntimeLoaderTest.php index f97d30694b9584f35d42f04bb32e28bd5090680d..32e61d15204d319a627bfe273035a6ffacfd1555 100644 --- a/vendor/twig/twig/test/Twig/Tests/FactoryRuntimeLoaderTest.php +++ b/vendor/twig/twig/tests/FactoryRuntimeLoaderTest.php @@ -1,5 +1,7 @@ <?php +namespace Twig\Tests; + /* * This file is part of Twig. * @@ -9,18 +11,20 @@ * file that was distributed with this source code. */ -class Twig_Tests_FactoryRuntimeLoaderTest extends \PHPUnit\Framework\TestCase +use Twig\RuntimeLoader\FactoryRuntimeLoader; + +class FactoryRuntimeLoaderTest extends \PHPUnit\Framework\TestCase { public function testLoad() { - $loader = new Twig_FactoryRuntimeLoader(array('stdClass' => 'getRuntime')); + $loader = new FactoryRuntimeLoader(['stdClass' => '\Twig\Tests\getRuntime']); $this->assertInstanceOf('stdClass', $loader->load('stdClass')); } public function testLoadReturnsNullForUnmappedRuntime() { - $loader = new Twig_FactoryRuntimeLoader(); + $loader = new FactoryRuntimeLoader(); $this->assertNull($loader->load('stdClass')); } @@ -28,5 +32,5 @@ class Twig_Tests_FactoryRuntimeLoaderTest extends \PHPUnit\Framework\TestCase function getRuntime() { - return new stdClass(); + return new \stdClass(); } diff --git a/vendor/twig/twig/test/Twig/Tests/FileCachingTest.php b/vendor/twig/twig/tests/FileCachingTest.php similarity index 75% rename from vendor/twig/twig/test/Twig/Tests/FileCachingTest.php rename to vendor/twig/twig/tests/FileCachingTest.php index e8a23eade978b382d255a1ec53a9bdde62bd1cac..e1fa3a4b52a00ce779886839b54a2793675498be 100644 --- a/vendor/twig/twig/test/Twig/Tests/FileCachingTest.php +++ b/vendor/twig/twig/tests/FileCachingTest.php @@ -1,5 +1,7 @@ <?php +namespace Twig\Tests; + /* * This file is part of Twig. * @@ -9,9 +11,10 @@ * file that was distributed with this source code. */ -require_once dirname(__FILE__).'/FilesystemHelper.php'; +use Twig\Environment; +use Twig\Loader\ArrayLoader; -class Twig_Tests_FileCachingTest extends \PHPUnit\Framework\TestCase +class FileCachingTest extends \PHPUnit\Framework\TestCase { private $env; private $tmpDir; @@ -27,12 +30,12 @@ class Twig_Tests_FileCachingTest extends \PHPUnit\Framework\TestCase $this->markTestSkipped(sprintf('Unable to run the tests as "%s" is not writable.', $this->tmpDir)); } - $this->env = new Twig_Environment(new Twig_Loader_Array(array('index' => 'index', 'index2' => 'index2')), array('cache' => $this->tmpDir)); + $this->env = new Environment(new ArrayLoader(['index' => 'index', 'index2' => 'index2']), ['cache' => $this->tmpDir]); } protected function tearDown() { - Twig_Tests_FilesystemHelper::removeDir($this->tmpDir); + FilesystemHelper::removeDir($this->tmpDir); } /** @@ -41,7 +44,7 @@ class Twig_Tests_FileCachingTest extends \PHPUnit\Framework\TestCase public function testWritingCacheFiles() { $name = 'index'; - $this->env->loadTemplate($name); + $this->env->load($name); $cacheFileName = $this->env->getCacheFilename($name); $this->assertFileExists($cacheFileName, 'Cache file does not exist.'); @@ -53,7 +56,7 @@ class Twig_Tests_FileCachingTest extends \PHPUnit\Framework\TestCase public function testClearingCacheFiles() { $name = 'index2'; - $this->env->loadTemplate($name); + $this->env->load($name); $cacheFileName = $this->env->getCacheFilename($name); $this->assertFileExists($cacheFileName, 'Cache file does not exist.'); diff --git a/vendor/twig/twig/tests/FileExtensionEscapingStrategyTest.php b/vendor/twig/twig/tests/FileExtensionEscapingStrategyTest.php new file mode 100644 index 0000000000000000000000000000000000000000..26e14135019dfa6bb5d9dc6a8ea37a5db6bfaa09 --- /dev/null +++ b/vendor/twig/twig/tests/FileExtensionEscapingStrategyTest.php @@ -0,0 +1,55 @@ +<?php + +namespace Twig\Tests; + +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use Twig\FileExtensionEscapingStrategy; + +class FileExtensionEscapingStrategyTest extends \PHPUnit\Framework\TestCase +{ + /** + * @dataProvider getGuessData + */ + public function testGuess($strategy, $filename) + { + $this->assertSame($strategy, FileExtensionEscapingStrategy::guess($filename)); + } + + public function getGuessData() + { + return [ + // default + ['html', 'foo.html'], + ['html', 'foo.html.twig'], + ['html', 'foo'], + ['html', 'foo.bar.twig'], + ['html', 'foo.txt/foo'], + ['html', 'foo.txt/foo.js/'], + + // css + ['css', 'foo.css'], + ['css', 'foo.css.twig'], + ['css', 'foo.twig.css'], + ['css', 'foo.js.css'], + ['css', 'foo.js.css.twig'], + + // js + ['js', 'foo.js'], + ['js', 'foo.js.twig'], + ['js', 'foo.txt/foo.js'], + ['js', 'foo.txt.twig/foo.js'], + + // txt + [false, 'foo.txt'], + [false, 'foo.txt.twig'], + ]; + } +} diff --git a/vendor/twig/twig/test/Twig/Tests/FilesystemHelper.php b/vendor/twig/twig/tests/FilesystemHelper.php similarity index 70% rename from vendor/twig/twig/test/Twig/Tests/FilesystemHelper.php rename to vendor/twig/twig/tests/FilesystemHelper.php index 0e315e8f7739c2e41dbbd22dfda8864e49484cf9..76f75afc73de039ebda0ea11cadb7bdc7ae7830d 100644 --- a/vendor/twig/twig/test/Twig/Tests/FilesystemHelper.php +++ b/vendor/twig/twig/tests/FilesystemHelper.php @@ -1,5 +1,7 @@ <?php +namespace Twig\Tests; + /* * This file is part of Twig. * @@ -9,11 +11,11 @@ * file that was distributed with this source code. */ -class Twig_Tests_FilesystemHelper +class FilesystemHelper { public static function removeDir($dir) { - $iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($dir, PHP_VERSION_ID < 50300 ? 0 : FilesystemIterator::SKIP_DOTS), RecursiveIteratorIterator::CHILD_FIRST); + $iterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($dir, \PHP_VERSION_ID < 50300 ? 0 : \FilesystemIterator::SKIP_DOTS), \RecursiveIteratorIterator::CHILD_FIRST); foreach ($iterator as $filename => $fileInfo) { if ($iterator->isDot()) { continue; diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/autoescape/block.test b/vendor/twig/twig/tests/Fixtures/autoescape/block.test similarity index 86% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/autoescape/block.test rename to vendor/twig/twig/tests/Fixtures/autoescape/block.test index 1290973a5113a6243ec4890935ab629d64f4c2fd..a80b80c376e5fd8e6824588209132a983ecad374 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/autoescape/block.test +++ b/vendor/twig/twig/tests/Fixtures/autoescape/block.test @@ -14,8 +14,8 @@ blocks and autoescape {% set _content = block('content')|raw %} {{ _content|raw }} --DATA-- -return array('br' => '<br />') +return ['br' => '<br />'] --CONFIG-- -return array('autoescape' => 'name') +return ['autoescape' => 'name'] --EXPECT-- <br /> diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/autoescape/name.test b/vendor/twig/twig/tests/Fixtures/autoescape/name.test similarity index 79% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/autoescape/name.test rename to vendor/twig/twig/tests/Fixtures/autoescape/name.test index 04299bed3566ff69fd2b85981098e73ecc0dc465..5ad573cf0aa492029a268c071a473095a36d08db 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/autoescape/name.test +++ b/vendor/twig/twig/tests/Fixtures/autoescape/name.test @@ -12,11 +12,11 @@ --TEMPLATE(index.txt.twig)-- {{ br -}} --DATA-- -return array('br' => '<br />') +return ['br' => '<br />'] --CONFIG-- -return array('autoescape' => 'name') +return ['autoescape' => 'name'] --EXPECT-- <br /> -\x3Cbr\x20\x2F\x3E +\u003Cbr\u0020\/\u003E <br /> <br /> diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/errors/base.html b/vendor/twig/twig/tests/Fixtures/errors/base.html similarity index 100% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/errors/base.html rename to vendor/twig/twig/tests/Fixtures/errors/base.html diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/errors/index.html b/vendor/twig/twig/tests/Fixtures/errors/index.html similarity index 100% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/errors/index.html rename to vendor/twig/twig/tests/Fixtures/errors/index.html diff --git a/vendor/twig/twig/tests/Fixtures/errors/leak-output.php b/vendor/twig/twig/tests/Fixtures/errors/leak-output.php new file mode 100644 index 0000000000000000000000000000000000000000..985c39a8eb72581cabff8c14bef38444d6354c21 --- /dev/null +++ b/vendor/twig/twig/tests/Fixtures/errors/leak-output.php @@ -0,0 +1,33 @@ +<?php + +namespace Twig\Tests\Fixtures\errors; + +require __DIR__.'/../../../vendor/autoload.php'; + +use Twig\Environment; +use Twig\Extension\AbstractExtension; +use Twig\Loader\ArrayLoader; +use Twig\TwigFilter; + +class BrokenExtension extends AbstractExtension +{ + public function getFilters() + { + return [ + new TwigFilter('broken', [$this, 'broken']), + ]; + } + + public function broken() + { + die('OOPS'); + } +} + +$loader = new ArrayLoader([ + 'index.html.twig' => 'Hello {{ "world"|broken }}', +]); +$twig = new Environment($loader, ['debug' => isset($argv[1])]); +$twig->addExtension(new BrokenExtension()); + +echo $twig->render('index.html.twig'); diff --git a/vendor/twig/twig/tests/Fixtures/exceptions/child_contents_outside_blocks.test b/vendor/twig/twig/tests/Fixtures/exceptions/child_contents_outside_blocks.test new file mode 100644 index 0000000000000000000000000000000000000000..74a1cc2833c21e402368f62fb4514b6b63c6c02c --- /dev/null +++ b/vendor/twig/twig/tests/Fixtures/exceptions/child_contents_outside_blocks.test @@ -0,0 +1,15 @@ +--TEST-- +Exception for child templates defining content outside blocks defined by parent +--TEMPLATE-- +{% extends 'base.twig' %} + +Content outside a block. + +{% block sidebar %} + Content inside a block. +{% endblock %} +--TEMPLATE(base.twig)-- +{% block sidebar %} +{% endblock %} +--EXCEPTION-- +Twig\Error\SyntaxError: A template that extends another one cannot include content outside Twig blocks. Did you forget to put the content inside a {% block %} tag in "index.twig" at line 3? diff --git a/vendor/twig/twig/tests/Fixtures/exceptions/exception_in_extension_extends.test b/vendor/twig/twig/tests/Fixtures/exceptions/exception_in_extension_extends.test new file mode 100644 index 0000000000000000000000000000000000000000..2ab298059d32122c029bce571693de2722fa2a52 --- /dev/null +++ b/vendor/twig/twig/tests/Fixtures/exceptions/exception_in_extension_extends.test @@ -0,0 +1,12 @@ +--TEST-- +Exception thrown from a child for an extension error +--TEMPLATE-- +{% extends 'base.twig' %} +--TEMPLATE(base.twig)-- + + +{{ random([]) }} +--DATA-- +return [] +--EXCEPTION-- +Twig\Error\RuntimeError: The random function cannot pick from an empty array in "base.twig" at line 4. diff --git a/vendor/twig/twig/tests/Fixtures/exceptions/exception_in_extension_include.test b/vendor/twig/twig/tests/Fixtures/exceptions/exception_in_extension_include.test new file mode 100644 index 0000000000000000000000000000000000000000..e2281b2903bd3cbbf26db74282d5d554f813b191 --- /dev/null +++ b/vendor/twig/twig/tests/Fixtures/exceptions/exception_in_extension_include.test @@ -0,0 +1,12 @@ +--TEST-- +Exception thrown from an include for an extension error +--TEMPLATE-- +{% include 'content.twig' %} +--TEMPLATE(content.twig)-- + + +{{ random([]) }} +--DATA-- +return [] +--EXCEPTION-- +Twig\Error\RuntimeError: The random function cannot pick from an empty array in "content.twig" at line 4. diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/exceptions/multiline_array_with_undefined_variable.test b/vendor/twig/twig/tests/Fixtures/exceptions/multiline_array_with_undefined_variable.test similarity index 62% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/exceptions/multiline_array_with_undefined_variable.test rename to vendor/twig/twig/tests/Fixtures/exceptions/multiline_array_with_undefined_variable.test index 7ff2eedb7406974be157b46428f6714bbb62877b..66784292c9106ee55b9f076f703146fe7df88efb 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/exceptions/multiline_array_with_undefined_variable.test +++ b/vendor/twig/twig/tests/Fixtures/exceptions/multiline_array_with_undefined_variable.test @@ -13,6 +13,6 @@ Exception for multiline array with undefined variable foo2: foo2, } %} --DATA-- -return array('foobar' => 'foobar') +return ['foobar' => 'foobar'] --EXCEPTION-- -Twig_Error_Runtime: Variable "foo2" does not exist in "index.twig" at line 11. +Twig\Error\RuntimeError: Variable "foo2" does not exist in "index.twig" at line 11. diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/exceptions/multiline_array_with_undefined_variable_again.test b/vendor/twig/twig/tests/Fixtures/exceptions/multiline_array_with_undefined_variable_again.test similarity index 66% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/exceptions/multiline_array_with_undefined_variable_again.test rename to vendor/twig/twig/tests/Fixtures/exceptions/multiline_array_with_undefined_variable_again.test index c425069bf8135b3674d508714132467a0258154f..7f5e96b0491bd5ec1d2fc58eb18a6e9ec152c5c5 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/exceptions/multiline_array_with_undefined_variable_again.test +++ b/vendor/twig/twig/tests/Fixtures/exceptions/multiline_array_with_undefined_variable_again.test @@ -13,6 +13,6 @@ Exception for multiline array with undefined variable foo2: foo2, } %} --DATA-- -return array() +return [] --EXCEPTION-- -Twig_Error_Runtime: Variable "foobar" does not exist in "index.twig" at line 7. +Twig\Error\RuntimeError: Variable "foobar" does not exist in "index.twig" at line 7. diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/exceptions/multiline_function_with_undefined_variable.test b/vendor/twig/twig/tests/Fixtures/exceptions/multiline_function_with_undefined_variable.test similarity index 63% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/exceptions/multiline_function_with_undefined_variable.test rename to vendor/twig/twig/tests/Fixtures/exceptions/multiline_function_with_undefined_variable.test index 2f94a5ee9db1d8bed6660844639017438d1e6bb0..8bc524ef1816d2e175cbff5970ece90b5a7c7cdd 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/exceptions/multiline_function_with_undefined_variable.test +++ b/vendor/twig/twig/tests/Fixtures/exceptions/multiline_function_with_undefined_variable.test @@ -7,6 +7,6 @@ Exception for multile function with undefined variable --TEMPLATE(foo)-- Foo --DATA-- -return array() +return [] --EXCEPTION-- -Twig_Error_Runtime: Variable "with_context" does not exist in "index.twig" at line 3. +Twig\Error\RuntimeError: Variable "with_context" does not exist in "index.twig" at line 3. diff --git a/vendor/twig/twig/tests/Fixtures/exceptions/multiline_function_with_unknown_argument.test b/vendor/twig/twig/tests/Fixtures/exceptions/multiline_function_with_unknown_argument.test new file mode 100644 index 0000000000000000000000000000000000000000..5f413d406afbb686ead7f2cc4ac37d177c30b95c --- /dev/null +++ b/vendor/twig/twig/tests/Fixtures/exceptions/multiline_function_with_unknown_argument.test @@ -0,0 +1,9 @@ +--TEST-- +Exception for multiline function with unknown argument +--TEMPLATE-- +{{ include('foo', + with_context=True, + invalid=False +) }} +--EXCEPTION-- +Twig\Error\SyntaxError: Unknown argument "invalid" for function "include(template, variables, with_context, ignore_missing, sandboxed)" in "index.twig" at line 4. diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/exceptions/multiline_tag_with_undefined_variable.test b/vendor/twig/twig/tests/Fixtures/exceptions/multiline_tag_with_undefined_variable.test similarity index 62% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/exceptions/multiline_tag_with_undefined_variable.test rename to vendor/twig/twig/tests/Fixtures/exceptions/multiline_tag_with_undefined_variable.test index 7b3b1daf967e517235e33809a2cb7453cf4a56bc..032ad831ec5515a5efdd16ce699cfadfd51f5306 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/exceptions/multiline_tag_with_undefined_variable.test +++ b/vendor/twig/twig/tests/Fixtures/exceptions/multiline_tag_with_undefined_variable.test @@ -7,6 +7,6 @@ Exception for multiline tag with undefined variable --TEMPLATE(foo)-- Foo --DATA-- -return array() +return [] --EXCEPTION-- -Twig_Error_Runtime: Variable "vars" does not exist in "index.twig" at line 3. +Twig\Error\RuntimeError: Variable "vars" does not exist in "index.twig" at line 3. diff --git a/vendor/twig/twig/tests/Fixtures/exceptions/strict_comparison_operator.test b/vendor/twig/twig/tests/Fixtures/exceptions/strict_comparison_operator.test new file mode 100644 index 0000000000000000000000000000000000000000..e14beb672dde80c9499fca0398debc90ef26b4f5 --- /dev/null +++ b/vendor/twig/twig/tests/Fixtures/exceptions/strict_comparison_operator.test @@ -0,0 +1,6 @@ +--TEST-- +The PHP === strict comparison operator is not supported +--TEMPLATE-- +{{ 1 === 2 }} +--EXCEPTION-- +Twig\Error\SyntaxError: Unexpected operator of value "=". Did you try to use "===" or "!==" for strict comparison? Use "is same as(value)" instead in "index.twig" at line 2. diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/exceptions/syntax_error_in_reused_template.test b/vendor/twig/twig/tests/Fixtures/exceptions/syntax_error_in_reused_template.test similarity index 59% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/exceptions/syntax_error_in_reused_template.test rename to vendor/twig/twig/tests/Fixtures/exceptions/syntax_error_in_reused_template.test index 9ca418b2254c9d6a4b391ff7dd8fb073a1fefbda..4ce06854fb7d2b629006a39e62d5de0b5b3090e9 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/exceptions/syntax_error_in_reused_template.test +++ b/vendor/twig/twig/tests/Fixtures/exceptions/syntax_error_in_reused_template.test @@ -7,4 +7,4 @@ Exception for syntax error in reused template {% do node.data = 5 %} {% endblock %} --EXCEPTION-- -Twig_Error_Syntax: Unexpected token "operator" of value "=" ("end of statement block" expected) in "foo.twig" at line 3. +Twig\Error\SyntaxError: Unexpected token "operator" of value "=" ("end of statement block" expected) in "foo.twig" at line 3. diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/exceptions/unclosed_tag.test b/vendor/twig/twig/tests/Fixtures/exceptions/unclosed_tag.test similarity index 55% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/exceptions/unclosed_tag.test rename to vendor/twig/twig/tests/Fixtures/exceptions/unclosed_tag.test index 2c35ad56492101fde928ccd8d31d3d9626ba17f3..b4fc169167632eb1d58f70494dd21a143eafba0e 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/exceptions/unclosed_tag.test +++ b/vendor/twig/twig/tests/Fixtures/exceptions/unclosed_tag.test @@ -17,4 +17,4 @@ Exception for an unclosed tag {% endblock %} --EXCEPTION-- -Twig_Error_Syntax: Unexpected "endblock" tag (expecting closing tag for the "if" tag defined near line 4) in "index.twig" at line 16. +Twig\Error\SyntaxError: Unexpected "endblock" tag (expecting closing tag for the "if" tag defined near line 4) in "index.twig" at line 16. diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/exceptions/undefined_parent.test b/vendor/twig/twig/tests/Fixtures/exceptions/undefined_parent.test similarity index 52% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/exceptions/undefined_parent.test rename to vendor/twig/twig/tests/Fixtures/exceptions/undefined_parent.test index c8e7a097363575f5eb66ccfd6d1d89b9af84019b..07f855a3feb650b047d0b21e81ac91db17d59284 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/exceptions/undefined_parent.test +++ b/vendor/twig/twig/tests/Fixtures/exceptions/undefined_parent.test @@ -4,5 +4,7 @@ Exception for an undefined parent {% extends 'foo.html' %} {% set foo = "foo" %} +--DATA-- +return [] --EXCEPTION-- -Twig_Error_Loader: Template "foo.html" is not defined in "index.twig" at line 2. +Twig\Error\LoaderError: Template "foo.html" is not defined in "index.twig" at line 2. diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/exceptions/undefined_template_in_child_template.test b/vendor/twig/twig/tests/Fixtures/exceptions/undefined_template_in_child_template.test similarity index 71% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/exceptions/undefined_template_in_child_template.test rename to vendor/twig/twig/tests/Fixtures/exceptions/undefined_template_in_child_template.test index 1992510b269dd259b669fc63d10b7ad233e3d99b..904faa50ad433995693a09491cac760438af57e4 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/exceptions/undefined_template_in_child_template.test +++ b/vendor/twig/twig/tests/Fixtures/exceptions/undefined_template_in_child_template.test @@ -10,6 +10,6 @@ Exception for an undefined template in a child template {% block sidebar %} {% endblock %} --DATA-- -return array() +return [] --EXCEPTION-- -Twig_Error_Loader: Template "include.twig" is not defined in "index.twig" at line 5. +Twig\Error\LoaderError: Template "include.twig" is not defined in "index.twig" at line 5. diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/exceptions/undefined_trait.test b/vendor/twig/twig/tests/Fixtures/exceptions/undefined_trait.test similarity index 61% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/exceptions/undefined_trait.test rename to vendor/twig/twig/tests/Fixtures/exceptions/undefined_trait.test index 6679fbe132dc0f417d7d2afa77529c9f1d0b49ec..5bfdd07e6125439b0c20555f1b7fa7b6cfb2b42f 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/exceptions/undefined_trait.test +++ b/vendor/twig/twig/tests/Fixtures/exceptions/undefined_trait.test @@ -6,4 +6,4 @@ Exception for an undefined trait {% block bar %} {% endblock %} --EXCEPTION-- -Twig_Error_Runtime: Block "foobar" is not defined in trait "foo" in "index.twig" at line 2. +Twig\Error\RuntimeError: Block "foobar" is not defined in trait "foo" in "index.twig" at line 2. diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/expressions/_self.test b/vendor/twig/twig/tests/Fixtures/expressions/_self.test similarity index 86% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/expressions/_self.test rename to vendor/twig/twig/tests/Fixtures/expressions/_self.test index 32fed8fd078fc2dde623021dfde6138ce06327c2..fb88f4c859d1c6d732747dd244b4f45de86a645f 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/expressions/_self.test +++ b/vendor/twig/twig/tests/Fixtures/expressions/_self.test @@ -3,6 +3,6 @@ _self returns the template name --TEMPLATE-- {{ _self }} --DATA-- -return array() +return [] --EXPECT-- index.twig diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/expressions/array.test b/vendor/twig/twig/tests/Fixtures/expressions/array.test similarity index 94% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/expressions/array.test rename to vendor/twig/twig/tests/Fixtures/expressions/array.test index c69b1192fbabeebc6c5923a82d150673af980f48..bf6033356a1c5bd3cbf44e7677b562ccf566fa8e 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/expressions/array.test +++ b/vendor/twig/twig/tests/Fixtures/expressions/array.test @@ -38,7 +38,7 @@ Twig supports array notation {{ ary|keys|join(',') }} {{ ary|join(',') }} --DATA-- -return array('bar' => 'bar', 'foo' => array('bar' => 'bar')) +return ['bar' => 'bar', 'foo' => ['bar' => 'bar']] --EXPECT-- 1,2 foo,bar diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/expressions/array_call.test b/vendor/twig/twig/tests/Fixtures/expressions/array_call.test similarity index 67% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/expressions/array_call.test rename to vendor/twig/twig/tests/Fixtures/expressions/array_call.test index f3df328fe3c7715f5cb800642d5853cfcbe892d2..8c7a2ee7cb8f6f0e1a9fce0072d18c04b35a58ec 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/expressions/array_call.test +++ b/vendor/twig/twig/tests/Fixtures/expressions/array_call.test @@ -6,7 +6,7 @@ Twig supports method calls {{ items[foo] }} {{ items[items[foo]] }} --DATA-- -return array('foo' => 'bar', 'items' => array('foo' => 'bar', 'bar' => 'foo')) +return ['foo' => 'bar', 'items' => ['foo' => 'bar', 'bar' => 'foo']] --EXPECT-- bar bar diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/expressions/binary.test b/vendor/twig/twig/tests/Fixtures/expressions/binary.test similarity index 90% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/expressions/binary.test rename to vendor/twig/twig/tests/Fixtures/expressions/binary.test index f5e68456d78a8c9edbc53d84ef55adf1e43cba74..b4e8be58d3ccb4e09f5e71b7a0a3916953758b1f 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/expressions/binary.test +++ b/vendor/twig/twig/tests/Fixtures/expressions/binary.test @@ -22,7 +22,7 @@ Twig supports binary operations (+, -, *, /, ~, %, and, or) {{ foo ~ bar }} {{ 20 // 7 }} --DATA-- -return array('foo' => 'bar', 'bar' => 'foo') +return ['foo' => 'bar', 'bar' => 'foo'] --EXPECT-- 2 1 diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/expressions/bitwise.test b/vendor/twig/twig/tests/Fixtures/expressions/bitwise.test similarity index 92% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/expressions/bitwise.test rename to vendor/twig/twig/tests/Fixtures/expressions/bitwise.test index 74fe6cabb7d06bfaf0f822b13766bb8ba1597dd7..c2bda1cc6b61d050904e36912294ec43a6f301d5 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/expressions/bitwise.test +++ b/vendor/twig/twig/tests/Fixtures/expressions/bitwise.test @@ -6,7 +6,7 @@ Twig supports bitwise operations {{ 1 b-xor 5 }} {{ (1 and 0 b-or 0) is same as(1 and (0 b-or 0)) ? 'ok' : 'ko' }} --DATA-- -return array() +return [] --EXPECT-- 1 5 diff --git a/vendor/twig/twig/tests/Fixtures/expressions/call_argument_defined_twice.test b/vendor/twig/twig/tests/Fixtures/expressions/call_argument_defined_twice.test new file mode 100644 index 0000000000000000000000000000000000000000..36539a6d1324960aa41d2c13872de5da3f8e22df --- /dev/null +++ b/vendor/twig/twig/tests/Fixtures/expressions/call_argument_defined_twice.test @@ -0,0 +1,8 @@ +--TEST-- +Argument is defined twice in a call +--TEMPLATE-- +{{ date(987654, date = 123456) }} +--DATA-- +return [] +--EXCEPTION-- +Twig\Error\SyntaxError: Argument "date" is defined twice for function "date" in "index.twig" at line 2. diff --git a/vendor/twig/twig/tests/Fixtures/expressions/call_positional_arg_after_named_arg.test b/vendor/twig/twig/tests/Fixtures/expressions/call_positional_arg_after_named_arg.test new file mode 100644 index 0000000000000000000000000000000000000000..729c6748597bc7e6e40a6452f0c92795770ca2df --- /dev/null +++ b/vendor/twig/twig/tests/Fixtures/expressions/call_positional_arg_after_named_arg.test @@ -0,0 +1,8 @@ +--TEST-- +Positional arguments after named arguments in a call +--TEMPLATE-- +{{ date(date = 123456, 'Y-m-d') }} +--DATA-- +return [] +--EXCEPTION-- +Twig\Error\SyntaxError: Positional arguments cannot be used after named arguments for function "date" in "index.twig" at line 2. diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/expressions/comparison.test b/vendor/twig/twig/tests/Fixtures/expressions/comparison.test similarity index 94% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/expressions/comparison.test rename to vendor/twig/twig/tests/Fixtures/expressions/comparison.test index 726b85075d4f09f18a182994ae39ff475ada649a..2811634f76aeec591c926c26debff2fe056fbca6 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/expressions/comparison.test +++ b/vendor/twig/twig/tests/Fixtures/expressions/comparison.test @@ -6,7 +6,7 @@ Twig supports comparison operators (==, !=, <, >, >=, <=) {{ 1 == 1 }}/{{ 1 == 2 }} {{ 1 != 1 }}/{{ 1 != 2 }} --DATA-- -return array() +return [] --EXPECT-- ///1 1//1/1 diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/expressions/divisibleby.test b/vendor/twig/twig/tests/Fixtures/expressions/divisibleby.test similarity index 94% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/expressions/divisibleby.test rename to vendor/twig/twig/tests/Fixtures/expressions/divisibleby.test index 238dd279039fc9de23aa1909d38ee7cd53b90407..f1bf5681e59389476732670212836133020a999a 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/expressions/divisibleby.test +++ b/vendor/twig/twig/tests/Fixtures/expressions/divisibleby.test @@ -9,7 +9,7 @@ Twig supports the "divisible by" operator by (3) ? 'OK' }} --DATA-- -return array() +return [] --EXPECT-- OK OK diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/expressions/dotdot.test b/vendor/twig/twig/tests/Fixtures/expressions/dotdot.test similarity index 93% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/expressions/dotdot.test rename to vendor/twig/twig/tests/Fixtures/expressions/dotdot.test index 9cd0676ce7354309b00e9ffefad05377d504a2fe..0efa9305694208f36d0849fe6c0606c10a781877 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/expressions/dotdot.test +++ b/vendor/twig/twig/tests/Fixtures/expressions/dotdot.test @@ -11,7 +11,7 @@ Twig supports the .. operator {% for i in 0 + 1 .. 10 - 1 %}{{ i }} {% endfor %} --DATA-- -return array('foo' => array(1, 10)) +return ['foo' => [1, 10]] --EXPECT-- 0 1 2 3 4 5 6 7 8 9 10 a b c d e f g h i j k l m n o p q r s t u v w x y z diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/expressions/ends_with.test b/vendor/twig/twig/tests/Fixtures/expressions/ends_with.test similarity index 97% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/expressions/ends_with.test rename to vendor/twig/twig/tests/Fixtures/expressions/ends_with.test index 9ad5e5e8ebf29d656854287abe5d55e9a7b4053c..c8086d6d4c283c5b71128462efb3c8ad4fabc579 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/expressions/ends_with.test +++ b/vendor/twig/twig/tests/Fixtures/expressions/ends_with.test @@ -12,7 +12,7 @@ Twig supports the "ends with" operator {{ false ends with false ? 'OK' : 'KO' }} {{ false ends with '' ? 'OK' : 'KO' }} --DATA-- -return array() +return [] --EXPECT-- OK OK diff --git a/vendor/twig/twig/tests/Fixtures/expressions/floats.test b/vendor/twig/twig/tests/Fixtures/expressions/floats.test new file mode 100644 index 0000000000000000000000000000000000000000..cdf871cde15dbd1ea7bdaf0da4fd6a0ba1c2451e --- /dev/null +++ b/vendor/twig/twig/tests/Fixtures/expressions/floats.test @@ -0,0 +1,16 @@ +--TEST-- +Twig compiles floats properly +--CONDITION-- +version_compare(phpversion(), '7.0.0', '>=') +--TEMPLATE-- +{% set val2 = 0.0 %} + +{{ val is same as (0.0) ? 'Yes' : 'No' }} +{{ val2 is same as (0.0) ? 'Yes' : 'No' }} +{{ val is same as (val2) ? 'Yes' : 'No' }} +--DATA-- +return ['val' => 0.0] +--EXPECT-- +Yes +Yes +Yes diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/expressions/grouping.test b/vendor/twig/twig/tests/Fixtures/expressions/grouping.test similarity index 86% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/expressions/grouping.test rename to vendor/twig/twig/tests/Fixtures/expressions/grouping.test index 79f8e0b0d35e806e759c93f1f0db328505de27b8..069ebf793d10429a4f9cd30dbe66be1e07240a63 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/expressions/grouping.test +++ b/vendor/twig/twig/tests/Fixtures/expressions/grouping.test @@ -3,6 +3,6 @@ Twig supports grouping of expressions --TEMPLATE-- {{ (2 + 2) / 2 }} --DATA-- -return array() +return [] --EXPECT-- 2 diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/expressions/literals.test b/vendor/twig/twig/tests/Fixtures/expressions/literals.test similarity index 92% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/expressions/literals.test rename to vendor/twig/twig/tests/Fixtures/expressions/literals.test index 7ae3bae9598732d3f0e35d28d8ad3bb0034fb86c..308e8df2ac6b734a4744862429647f4ef0aa3408 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/expressions/literals.test +++ b/vendor/twig/twig/tests/Fixtures/expressions/literals.test @@ -10,7 +10,7 @@ Twig supports literals 7 {{ null }} 8 {{ NULL }} --DATA-- -return array() +return [] --EXPECT-- 1 1 2 1 diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/expressions/magic_call.test b/vendor/twig/twig/tests/Fixtures/expressions/magic_call.test similarity index 87% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/expressions/magic_call.test rename to vendor/twig/twig/tests/Fixtures/expressions/magic_call.test index 1a27a2d6fa90a436a987f0f01465ab747f8af2ea..60417e04ffd0fffc22aac1dedfec44dfb68e4a78 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/expressions/magic_call.test +++ b/vendor/twig/twig/tests/Fixtures/expressions/magic_call.test @@ -21,7 +21,7 @@ class TestClassForMagicCallAttributes } } -return array('foo' => new TestClassForMagicCallAttributes()) +return ['foo' => new TestClassForMagicCallAttributes()] --EXPECT-- foo_from_call bar_from_getbar diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/expressions/matches.test b/vendor/twig/twig/tests/Fixtures/expressions/matches.test similarity index 93% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/expressions/matches.test rename to vendor/twig/twig/tests/Fixtures/expressions/matches.test index b6c771657a7c525185a30112bd61536b4c7628a3..95459c3b0f28ee16136bea9462f6e3780b4d17a7 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/expressions/matches.test +++ b/vendor/twig/twig/tests/Fixtures/expressions/matches.test @@ -5,7 +5,7 @@ Twig supports the "matches" operator {{ 'foo' matches '/^fo/' ? 'OK' : 'KO' }} {{ 'foo' matches '/O/i' ? 'OK' : 'KO' }} --DATA-- -return array() +return [] --EXPECT-- OK OK diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/expressions/method_call.test b/vendor/twig/twig/tests/Fixtures/expressions/method_call.test similarity index 72% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/expressions/method_call.test rename to vendor/twig/twig/tests/Fixtures/expressions/method_call.test index 5f801e6354a06d688cf02afff08d8ba0b1038fa8..bf49f389e005c6b4b6b84a475eda32ec247cef4a 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/expressions/method_call.test +++ b/vendor/twig/twig/tests/Fixtures/expressions/method_call.test @@ -12,9 +12,9 @@ Twig supports method calls {{ items.foo.in }} {{ items.foo.not }} --DATA-- -return array('foo' => 'bar', 'items' => array('foo' => new TwigTestFoo(), 'bar' => 'foo')) +return ['foo' => 'bar', 'items' => ['foo' => new Twig\Tests\TwigTestFoo(), 'bar' => 'foo']] --CONFIG-- -return array('strict_variables' => false) +return ['strict_variables' => false] --EXPECT-- foo foo diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/expressions/negative_numbers.test b/vendor/twig/twig/tests/Fixtures/expressions/negative_numbers.test similarity index 91% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/expressions/negative_numbers.test rename to vendor/twig/twig/tests/Fixtures/expressions/negative_numbers.test index 1853b1b0637d8599eb6ffa670f7ec3b1520e9b2c..c2a6e340245bf32153d7a2bc761c010e09c965d6 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/expressions/negative_numbers.test +++ b/vendor/twig/twig/tests/Fixtures/expressions/negative_numbers.test @@ -8,7 +8,7 @@ Twig manages negative numbers correctly {{ 5 + -1 }} {{ 5 + - 1 }} --DATA-- -return array() +return [] --EXPECT-- -1 -1 diff --git a/vendor/twig/twig/tests/Fixtures/expressions/not_arrow_fn.test b/vendor/twig/twig/tests/Fixtures/expressions/not_arrow_fn.test new file mode 100644 index 0000000000000000000000000000000000000000..af82c47cf5c64538edd95624fef3c84a3cbe0d94 --- /dev/null +++ b/vendor/twig/twig/tests/Fixtures/expressions/not_arrow_fn.test @@ -0,0 +1,8 @@ +--TEST-- +A string in parentheses cannot be confused with an arrow function +--TEMPLATE-- +{{ ["foo", "bar"]|join(("f")) }} +--DATA-- +return [] +--EXPECT-- +foofbar diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/expressions/operators_as_variables.test b/vendor/twig/twig/tests/Fixtures/expressions/operators_as_variables.test similarity index 72% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/expressions/operators_as_variables.test rename to vendor/twig/twig/tests/Fixtures/expressions/operators_as_variables.test index fe29d08bbf7228d0c85f58b64f30fb2f7f51242f..fa9a843c0fa9f1eddd45685a2eac65729d696e85 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/expressions/operators_as_variables.test +++ b/vendor/twig/twig/tests/Fixtures/expressions/operators_as_variables.test @@ -7,7 +7,7 @@ Twig allows to use named operators as variable names {{ in }} {{ is }} --DATA-- -return array('matches' => array(1, 2, 3), 'in' => 'in', 'is' => 'is') +return ['matches' => [1, 2, 3], 'in' => 'in', 'is' => 'is'] --EXPECT-- 1 2 diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/expressions/postfix.test b/vendor/twig/twig/tests/Fixtures/expressions/postfix.test similarity index 94% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/expressions/postfix.test rename to vendor/twig/twig/tests/Fixtures/expressions/postfix.test index 542c3504611258181a98651d5915e2d2e5720555..276cbf197d1ebe2827d58b892749b70f2596883a 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/expressions/postfix.test +++ b/vendor/twig/twig/tests/Fixtures/expressions/postfix.test @@ -12,7 +12,7 @@ Twig parses postfix expressions {{ macros.foo() }} {{ (macros).foo() }} --DATA-- -return array(); +return [] --EXPECT-- a A diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/expressions/power.test b/vendor/twig/twig/tests/Fixtures/expressions/power.test similarity index 84% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/expressions/power.test rename to vendor/twig/twig/tests/Fixtures/expressions/power.test index eacc98f86fc6359ddae601bfa1ffc6c417f99862..84fd23692ce4edf6acd8370747fbab5ede1a6957 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/expressions/power.test +++ b/vendor/twig/twig/tests/Fixtures/expressions/power.test @@ -9,7 +9,7 @@ Twig parses power expressions {{ b ** a }} {{ b ** b }} --DATA-- -return array('a' => 4, 'b' => -2); +return ['a' => 4, 'b' => -2] --EXPECT-- 8 -8 diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/expressions/sameas.test b/vendor/twig/twig/tests/Fixtures/expressions/sameas.test similarity index 95% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/expressions/sameas.test rename to vendor/twig/twig/tests/Fixtures/expressions/sameas.test index 601201deb384eff3cb34b053a50b3b269d5cefce..83f3691f97277b76d46938e99a7c40c717963e92 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/expressions/sameas.test +++ b/vendor/twig/twig/tests/Fixtures/expressions/sameas.test @@ -11,7 +11,7 @@ Twig supports the "same as" operator as (true) ? 'OK' }} --DATA-- -return array() +return [] --EXPECT-- OK OK diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/expressions/starts_with.test b/vendor/twig/twig/tests/Fixtures/expressions/starts_with.test similarity index 97% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/expressions/starts_with.test rename to vendor/twig/twig/tests/Fixtures/expressions/starts_with.test index 75d331e90a89cf3065f0f9a7e665af59ba33f8cc..a78ff1eac714184589eab0ec68babc5574fcdac3 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/expressions/starts_with.test +++ b/vendor/twig/twig/tests/Fixtures/expressions/starts_with.test @@ -13,7 +13,7 @@ with 'f' ? 'OK' : 'KO' }} {{ 'a' starts with false ? 'OK' : 'KO' }} {{ false starts with '' ? 'OK' : 'KO' }} --DATA-- -return array() +return [] --EXPECT-- OK OK diff --git a/vendor/twig/twig/tests/Fixtures/expressions/string_operator_as_var_assignment.test b/vendor/twig/twig/tests/Fixtures/expressions/string_operator_as_var_assignment.test new file mode 100644 index 0000000000000000000000000000000000000000..478d4eb5e54beedc02af286cbf28a47cc4bcf63a --- /dev/null +++ b/vendor/twig/twig/tests/Fixtures/expressions/string_operator_as_var_assignment.test @@ -0,0 +1,18 @@ +--TEST-- +Twig supports the string operators as variable names in assignments +--TEMPLATE-- +{% for matches in [1, 2] %} + {{- matches }} +{% endfor %} + +{% set matches = [1, 2] %} + +OK +--DATA-- +return [] +--EXPECT-- +1 +2 + + +OK diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/expressions/strings.test b/vendor/twig/twig/tests/Fixtures/expressions/strings.test similarity index 85% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/expressions/strings.test rename to vendor/twig/twig/tests/Fixtures/expressions/strings.test index a9116613e9421dd218e4ebd8d4847c58e2e37f74..f402c8939916a93080fa8457a3367c59b90f07b3 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/expressions/strings.test +++ b/vendor/twig/twig/tests/Fixtures/expressions/strings.test @@ -4,7 +4,7 @@ Twig supports string interpolation {{ "foo #{"foo #{bar} baz"} baz" }} {{ "foo #{bar}#{bar} baz" }} --DATA-- -return array('bar' => 'BAR'); +return ['bar' => 'BAR'] --EXPECT-- foo foo BAR baz baz foo BARBAR baz diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/expressions/ternary_operator.test b/vendor/twig/twig/tests/Fixtures/expressions/ternary_operator.test similarity index 87% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/expressions/ternary_operator.test rename to vendor/twig/twig/tests/Fixtures/expressions/ternary_operator.test index 0e6fa96e254fab5f1a6a36c513f5bea0be7de937..37eccc0f545955f35b14fd99bacb6a3f5f2eb0d5 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/expressions/ternary_operator.test +++ b/vendor/twig/twig/tests/Fixtures/expressions/ternary_operator.test @@ -8,7 +8,7 @@ Twig supports the ternary operator {{ 1 == 1 ? 'foo<br />':'' }} {{ foo ~ (bar ? ('-' ~ bar) : '') }} --DATA-- -return array('foo' => 'foo', 'bar' => 'bar') +return ['foo' => 'foo', 'bar' => 'bar'] --EXPECT-- YES NO diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/expressions/ternary_operator_noelse.test b/vendor/twig/twig/tests/Fixtures/expressions/ternary_operator_noelse.test similarity index 88% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/expressions/ternary_operator_noelse.test rename to vendor/twig/twig/tests/Fixtures/expressions/ternary_operator_noelse.test index fdc660fc5e7368af5b8d9d268e66a3c2ebd038b9..8b0f7284b9b235f1f3eb3573dadaaa07c57f2cb9 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/expressions/ternary_operator_noelse.test +++ b/vendor/twig/twig/tests/Fixtures/expressions/ternary_operator_noelse.test @@ -4,7 +4,7 @@ Twig supports the ternary operator {{ 1 ? 'YES' }} {{ 0 ? 'YES' }} --DATA-- -return array() +return [] --EXPECT-- YES diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/expressions/ternary_operator_nothen.test b/vendor/twig/twig/tests/Fixtures/expressions/ternary_operator_nothen.test similarity index 88% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/expressions/ternary_operator_nothen.test rename to vendor/twig/twig/tests/Fixtures/expressions/ternary_operator_nothen.test index 9057e837018b694dec29290387c70af4b9af6cdb..ecd6b7546563de086095574ec7cb20e345e1be44 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/expressions/ternary_operator_nothen.test +++ b/vendor/twig/twig/tests/Fixtures/expressions/ternary_operator_nothen.test @@ -4,7 +4,7 @@ Twig supports the ternary operator {{ 'YES' ?: 'NO' }} {{ 0 ?: 'NO' }} --DATA-- -return array() +return [] --EXPECT-- YES NO diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/expressions/two_word_operators_as_variables.test b/vendor/twig/twig/tests/Fixtures/expressions/two_word_operators_as_variables.test similarity index 54% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/expressions/two_word_operators_as_variables.test rename to vendor/twig/twig/tests/Fixtures/expressions/two_word_operators_as_variables.test index 0eaabb446e4655aa294e64cfb8ac462a2e3314ef..eca3b285bbe5993fe235afaa8d6be6df1cff6542 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/expressions/two_word_operators_as_variables.test +++ b/vendor/twig/twig/tests/Fixtures/expressions/two_word_operators_as_variables.test @@ -3,6 +3,6 @@ Twig does not allow to use two-word named operators as variable names --TEMPLATE-- {{ starts with }} --DATA-- -return array() +return [] --EXCEPTION-- -Twig_Error_Syntax: Unexpected token "operator" of value "starts with" in "index.twig" at line 2. +Twig\Error\SyntaxError: Unexpected token "operator" of value "starts with" in "index.twig" at line 2. diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/expressions/unary.test b/vendor/twig/twig/tests/Fixtures/expressions/unary.test similarity index 91% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/expressions/unary.test rename to vendor/twig/twig/tests/Fixtures/expressions/unary.test index b79219a2aa51d4a623e2813884ab85a18ceed0df..54225311903ec6dfe7586a525c37c15a1bd6602b 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/expressions/unary.test +++ b/vendor/twig/twig/tests/Fixtures/expressions/unary.test @@ -5,7 +5,7 @@ Twig supports unary operators (not, -, +) {{ +1 + 1 }}/{{ -1 - 1 }} {{ not (false or true) }} --DATA-- -return array() +return [] --EXPECT-- /1 2/-2 diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/expressions/unary_macro_arguments.test b/vendor/twig/twig/tests/Fixtures/expressions/unary_macro_arguments.test similarity index 97% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/expressions/unary_macro_arguments.test rename to vendor/twig/twig/tests/Fixtures/expressions/unary_macro_arguments.test index ad84a9c26b17d3fdceced601c783c5102c724e63..27deba3ef519db1f0bb62a06a2d4dcaa16dabdb7 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/expressions/unary_macro_arguments.test +++ b/vendor/twig/twig/tests/Fixtures/expressions/unary_macro_arguments.test @@ -13,7 +13,7 @@ Twig manages negative numbers as default parameters {% macro positive_number1(nb = +1) %}{{ nb }}{% endmacro %} {% macro positive_number2(nb = ++1) %}{{ nb }}{% endmacro %} --DATA-- -return array() +return [] --EXPECT-- -1 1 diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/expressions/unary_precedence.test b/vendor/twig/twig/tests/Fixtures/expressions/unary_precedence.test similarity index 90% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/expressions/unary_precedence.test rename to vendor/twig/twig/tests/Fixtures/expressions/unary_precedence.test index cc6eef8d2a078cb824a3d6418aa2e9648147ea51..9c56ab12c0f1f648a2a76ef557ed96ade530392e 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/expressions/unary_precedence.test +++ b/vendor/twig/twig/tests/Fixtures/expressions/unary_precedence.test @@ -6,7 +6,7 @@ Twig unary operators precedence {{ -1 * -1 }} {{ 4 / -1 * 5 }} --DATA-- -return array() +return [] --EXPECT-- -2 0 diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/abs.test b/vendor/twig/twig/tests/Fixtures/filters/abs.test similarity index 70% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/filters/abs.test rename to vendor/twig/twig/tests/Fixtures/filters/abs.test index 27e93fd638129486eb23b36d65f110931c365e96..7518769d4a06fcec199c034f264439533cac0d60 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/abs.test +++ b/vendor/twig/twig/tests/Fixtures/filters/abs.test @@ -14,7 +14,7 @@ {{ number5|abs }} {{ number6|abs }} --DATA-- -return array('number1' => -5.5, 'number2' => -5, 'number3' => -0, 'number4' => 0, 'number5' => 5, 'number6' => 5.5) +return ['number1' => -5.5, 'number2' => -5, 'number3' => -0, 'number4' => 0, 'number5' => 5, 'number6' => 5.5] --EXPECT-- 5.5 5 diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/batch.test b/vendor/twig/twig/tests/Fixtures/filters/batch.test similarity index 88% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/filters/batch.test rename to vendor/twig/twig/tests/Fixtures/filters/batch.test index cb6de7f97e963d3aadd4765878b87c6d985556fc..0acf25bd6144eef88ae05019b13e3bc1db0c4bcf 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/batch.test +++ b/vendor/twig/twig/tests/Fixtures/filters/batch.test @@ -9,7 +9,7 @@ </div> {% endfor %} --DATA-- -return array('items' => array('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j')) +return ['items' => ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j']] --EXPECT-- <div class=row> <div class=item>a</div> diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/batch_float.test b/vendor/twig/twig/tests/Fixtures/filters/batch_float.test similarity index 88% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/filters/batch_float.test rename to vendor/twig/twig/tests/Fixtures/filters/batch_float.test index e2ec4beb21535d69b70c5c3a3bd393ce7157a2d4..dad004ec2c5558f10a0a785072f1a7296d7a44ee 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/batch_float.test +++ b/vendor/twig/twig/tests/Fixtures/filters/batch_float.test @@ -9,7 +9,7 @@ </div> {% endfor %} --DATA-- -return array('items' => array('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j')) +return ['items' => ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j']] --EXPECT-- <div class=row> <div class=item>a</div> diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/batch_with_empty_fill.test b/vendor/twig/twig/tests/Fixtures/filters/batch_with_empty_fill.test similarity index 85% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/filters/batch_with_empty_fill.test rename to vendor/twig/twig/tests/Fixtures/filters/batch_with_empty_fill.test index af996f2469b0fa2bd6ff56f7097c72ee1ce24f98..411b4fc749913585fd7184ffddae07375b65a77b 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/batch_with_empty_fill.test +++ b/vendor/twig/twig/tests/Fixtures/filters/batch_with_empty_fill.test @@ -11,7 +11,7 @@ {% endfor %} </table> --DATA-- -return array('items' => array('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j')) +return ['items' => ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j']] --EXPECT-- <table> <tr> diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/batch_with_exact_elements.test b/vendor/twig/twig/tests/Fixtures/filters/batch_with_exact_elements.test similarity index 88% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/filters/batch_with_exact_elements.test rename to vendor/twig/twig/tests/Fixtures/filters/batch_with_exact_elements.test index 72483f4b5a442060507de6f8e0395e3c6417600c..750d1557aab1c087a23af76293b71dabb3792e23 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/batch_with_exact_elements.test +++ b/vendor/twig/twig/tests/Fixtures/filters/batch_with_exact_elements.test @@ -9,7 +9,7 @@ </div> {% endfor %} --DATA-- -return array('items' => array('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l')) +return ['items' => ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l']] --EXPECT-- <div class=row> <div class=item>a</div> diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/batch_with_fill.test b/vendor/twig/twig/tests/Fixtures/filters/batch_with_fill.test similarity index 86% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/filters/batch_with_fill.test rename to vendor/twig/twig/tests/Fixtures/filters/batch_with_fill.test index 746295f1b24452400523e07763309bf73e11c2fa..5d470d005b12cd41b4ebe1f92d7cf774c6df255a 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/batch_with_fill.test +++ b/vendor/twig/twig/tests/Fixtures/filters/batch_with_fill.test @@ -11,7 +11,7 @@ {% endfor %} </table> --DATA-- -return array('items' => array('a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j')) +return ['items' => ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j']] --EXPECT-- <table> <tr> diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/batch_with_keys.test b/vendor/twig/twig/tests/Fixtures/filters/batch_with_keys.test similarity index 87% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/filters/batch_with_keys.test rename to vendor/twig/twig/tests/Fixtures/filters/batch_with_keys.test index 6015380e2a14c7ae9ad15b38f274b7c5cb9c9659..e56cd79bbc923df292d875c0672185ea7d2ec7d1 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/batch_with_keys.test +++ b/vendor/twig/twig/tests/Fixtures/filters/batch_with_keys.test @@ -1,10 +1,10 @@ --TEST-- "batch" filter preserves array keys --TEMPLATE-- -{{ {'foo': 'bar', 'key': 'value'}|batch(4)|first|keys|join(',') }} -{{ {'foo': 'bar', 'key': 'value'}|batch(4, 'fill')|first|keys|join(',') }} +{{ {'foo': 'bar', 'key': 'value'}|batch(4)|first|keys|join(',') }} +{{ {'foo': 'bar', 'key': 'value'}|batch(4, 'fill')|first|keys|join(',') }} --DATA-- -return array() +return [] --EXPECT-- foo,key foo,key,0,1 diff --git a/vendor/twig/twig/tests/Fixtures/filters/batch_with_more_elements.test b/vendor/twig/twig/tests/Fixtures/filters/batch_with_more_elements.test new file mode 100644 index 0000000000000000000000000000000000000000..90f4de6859d8d2976e47c42eb616bb4afe737de3 --- /dev/null +++ b/vendor/twig/twig/tests/Fixtures/filters/batch_with_more_elements.test @@ -0,0 +1,23 @@ +--TEST-- +"batch" filter +--TEMPLATE-- +{% for row in items|batch(3, 'fill') %} + <div class=row> + {% for key, column in row %} + <div class={{ key }}>{{ column }}</div> + {% endfor %} + </div> +{% endfor %} +--DATA-- +return ['items' => ['a' => 'a', 'b' => 'b', 'c' => 'c', 'd' => 'd', '123' => 'e']] +--EXPECT-- +<div class=row> + <div class=a>a</div> + <div class=b>b</div> + <div class=c>c</div> + </div> + <div class=row> + <div class=d>d</div> + <div class=123>e</div> + <div class=124>fill</div> + </div> diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/batch_with_zero_elements.test b/vendor/twig/twig/tests/Fixtures/filters/batch_with_zero_elements.test similarity index 90% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/filters/batch_with_zero_elements.test rename to vendor/twig/twig/tests/Fixtures/filters/batch_with_zero_elements.test index b9c058d6b25e28a8287a63924f45464c632a8196..bc303da8ab6082be4fcf0606bd9dc66266691b5d 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/batch_with_zero_elements.test +++ b/vendor/twig/twig/tests/Fixtures/filters/batch_with_zero_elements.test @@ -4,7 +4,7 @@ {{ []|batch(3)|length }} {{ []|batch(3, 'fill')|length }} --DATA-- -return array() +return [] --EXPECT-- 0 0 diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/convert_encoding.test b/vendor/twig/twig/tests/Fixtures/filters/convert_encoding.test similarity index 95% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/filters/convert_encoding.test rename to vendor/twig/twig/tests/Fixtures/filters/convert_encoding.test index 380b04bb86984bf584d8b5687f35b1fb44bd48de..db8acedef5ed72273c49f2c01ef38e9a18bbec1c 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/convert_encoding.test +++ b/vendor/twig/twig/tests/Fixtures/filters/convert_encoding.test @@ -5,6 +5,6 @@ function_exists('iconv') || function_exists('mb_convert_encoding') --TEMPLATE-- {{ "æ„›ã—ã¦ã„ã¾ã™ã‹ï¼Ÿ"|convert_encoding('ISO-2022-JP', 'UTF-8')|convert_encoding('UTF-8', 'ISO-2022-JP') }} --DATA-- -return array() +return [] --EXPECT-- æ„›ã—ã¦ã„ã¾ã™ã‹ï¼Ÿ diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/date.test b/vendor/twig/twig/tests/Fixtures/filters/date.test similarity index 78% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/filters/date.test rename to vendor/twig/twig/tests/Fixtures/filters/date.test index d17e5e2f07260703f1b5903f36779acefed26c74..16816aa994806eae8b62969055af433b51b1002b 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/date.test +++ b/vendor/twig/twig/tests/Fixtures/filters/date.test @@ -40,16 +40,16 @@ {{ '2010-01-28 15:00:00'|date(timezone="Asia/Hong_Kong") }} --DATA-- date_default_timezone_set('Europe/Paris'); -return array( +return [ 'date1' => mktime(13, 45, 0, 10, 4, 2010), - 'date2' => new DateTime('2010-10-04 13:45'), + 'date2' => new \DateTime('2010-10-04 13:45'), 'date3' => '2010-10-04 13:45', - 'date4' => 1286199900, // DateTime::createFromFormat('Y-m-d H:i', '2010-10-04 13:45', new DateTimeZone('UTC'))->getTimestamp() -- A unixtimestamp is always GMT - 'date5' => -189291360, // DateTime::createFromFormat('Y-m-d H:i', '1964-01-02 03:04', new DateTimeZone('UTC'))->getTimestamp(), - 'date6' => new DateTime('2010-10-04 13:45', new DateTimeZone('America/New_York')), + 'date4' => 1286199900, // \DateTime::createFromFormat('Y-m-d H:i', '2010-10-04 13:45', new \DateTimeZone('UTC'))->getTimestamp() -- A unixtimestamp is always GMT + 'date5' => -189291360, // \DateTime::createFromFormat('Y-m-d H:i', '1964-01-02 03:04', new \DateTimeZone('UTC'))->getTimestamp(), + 'date6' => new \DateTime('2010-10-04 13:45', new \DateTimeZone('America/New_York')), 'date7' => '2010-01-28T15:00:00+04:00', - 'timezone1' => new DateTimeZone('America/New_York'), -) + 'timezone1' => new \DateTimeZone('America/New_York'), +] --EXPECT-- October 4, 2010 13:45 04/10/2010 diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/date_default_format.test b/vendor/twig/twig/tests/Fixtures/filters/date_default_format.test similarity index 64% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/filters/date_default_format.test rename to vendor/twig/twig/tests/Fixtures/filters/date_default_format.test index 6ad504cdf0e0de330bc896322bde9b26907a73d2..c6e81302df657a86c81cdcc082c061fe854ca4d2 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/date_default_format.test +++ b/vendor/twig/twig/tests/Fixtures/filters/date_default_format.test @@ -5,10 +5,10 @@ {{ date1|date('d/m/Y') }} --DATA-- date_default_timezone_set('UTC'); -$twig->getExtension('Twig_Extension_Core')->setDateFormat('Y-m-d', '%d days %h hours'); -return array( +$twig->getExtension('\Twig\Extension\CoreExtension')->setDateFormat('Y-m-d', '%d days %h hours'); +return [ 'date1' => mktime(13, 45, 0, 10, 4, 2010), -) +] --EXPECT-- 2010-10-04 04/10/2010 diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/date_default_format_interval.test b/vendor/twig/twig/tests/Fixtures/filters/date_default_format_interval.test similarity index 62% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/filters/date_default_format_interval.test rename to vendor/twig/twig/tests/Fixtures/filters/date_default_format_interval.test index be4a642e7145962405b30361c9b9a5e0df2826b6..a72fb81d629669e2234f144a0d8137b964b36912 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/date_default_format_interval.test +++ b/vendor/twig/twig/tests/Fixtures/filters/date_default_format_interval.test @@ -7,10 +7,10 @@ version_compare(phpversion(), '5.3.0', '>=') {{ date2|date('%d days') }} --DATA-- date_default_timezone_set('UTC'); -$twig->getExtension('Twig_Extension_Core')->setDateFormat('Y-m-d', '%d days %h hours'); -return array( - 'date2' => new DateInterval('P2D'), -) +$twig->getExtension('\Twig\Extension\CoreExtension')->setDateFormat('Y-m-d', '%d days %h hours'); +return [ + 'date2' => new \DateInterval('P2D'), +] --EXPECT-- 2 days 0 hours 2 days diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/date_immutable.test b/vendor/twig/twig/tests/Fixtures/filters/date_immutable.test similarity index 78% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/filters/date_immutable.test rename to vendor/twig/twig/tests/Fixtures/filters/date_immutable.test index 4e183256209011a1ddc68662b1cdda9e99f002b8..2414db5015b39b268f14fba7f06ce27d7e0bc367 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/date_immutable.test +++ b/vendor/twig/twig/tests/Fixtures/filters/date_immutable.test @@ -17,11 +17,11 @@ version_compare(phpversion(), '5.5.0', '>=') {{ date2|date('e', false) }} --DATA-- date_default_timezone_set('Europe/Paris'); -return array( - 'date1' => new DateTimeImmutable('2010-10-04 13:45'), - 'date2' => new DateTimeImmutable('2010-10-04 13:45', new DateTimeZone('America/New_York')), - 'timezone1' => new DateTimeZone('America/New_York'), -) +return [ + 'date1' => new \DateTimeImmutable('2010-10-04 13:45'), + 'date2' => new \DateTimeImmutable('2010-10-04 13:45', new \DateTimeZone('America/New_York')), + 'timezone1' => new \DateTimeZone('America/New_York'), +] --EXPECT-- October 4, 2010 13:45 04/10/2010 diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/date_interval.test b/vendor/twig/twig/tests/Fixtures/filters/date_interval.test similarity index 64% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/filters/date_interval.test rename to vendor/twig/twig/tests/Fixtures/filters/date_interval.test index 0c8c6f1a28cc20700b87d7c30e16a5cc14646c5f..c3333f565bf79ce56966a719d77a14d57ac306ac 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/date_interval.test +++ b/vendor/twig/twig/tests/Fixtures/filters/date_interval.test @@ -8,11 +8,11 @@ version_compare(phpversion(), '5.3.0', '>=') {{ date1|date('%d days %h hours', timezone1) }} --DATA-- date_default_timezone_set('UTC'); -return array( - 'date1' => new DateInterval('P2D'), - // This should have no effect on DateInterval formatting - 'timezone1' => new DateTimeZone('America/New_York'), -) +return [ + 'date1' => new \DateInterval('P2D'), + // This should have no effect on \DateInterval formatting + 'timezone1' => new \DateTimeZone('America/New_York'), +] --EXPECT-- 2 days 2 days 0 hours diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/date_modify.test b/vendor/twig/twig/tests/Fixtures/filters/date_modify.test similarity index 81% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/filters/date_modify.test rename to vendor/twig/twig/tests/Fixtures/filters/date_modify.test index 53d3a69cdf4080e65dc5462b4f958e0bd67c0cdd..d7f8fdf42a1d5a913a1f3ab354d304d89f8e58f8 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/date_modify.test +++ b/vendor/twig/twig/tests/Fixtures/filters/date_modify.test @@ -5,10 +5,10 @@ {{ date2|date_modify('-1day')|date('Y-m-d H:i:s') }} --DATA-- date_default_timezone_set('UTC'); -return array( +return [ 'date1' => '2010-10-04 13:45', - 'date2' => new DateTime('2010-10-04 13:45'), -) + 'date2' => new \DateTime('2010-10-04 13:45'), +] --EXPECT-- 2010-10-03 13:45:00 2010-10-03 13:45:00 diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/date_namedargs.test b/vendor/twig/twig/tests/Fixtures/filters/date_namedargs.test similarity index 86% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/filters/date_namedargs.test rename to vendor/twig/twig/tests/Fixtures/filters/date_namedargs.test index 4ecde8a185c79e652ad27d2c9cb2d9471e2140d5..2d1aa134496c3eab54315588205b53862bf84c18 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/date_namedargs.test +++ b/vendor/twig/twig/tests/Fixtures/filters/date_namedargs.test @@ -6,7 +6,7 @@ {{ date|date('d/m/Y H:i:s P', timezone='America/Chicago') }} --DATA-- date_default_timezone_set('UTC'); -return array('date' => mktime(13, 45, 0, 10, 4, 2010)) +return ['date' => mktime(13, 45, 0, 10, 4, 2010)] --EXPECT-- 04/10/2010 08:45:00 -05:00 04/10/2010 08:45:00 -05:00 diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/default.test b/vendor/twig/twig/tests/Fixtures/filters/default.test similarity index 91% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/filters/default.test rename to vendor/twig/twig/tests/Fixtures/filters/default.test index b8d1d66f5ed2f24e7ec0bb060fa0142c543a64aa..b01a62d2fb3a64ccfdf8de2272b08364736df30d 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/default.test +++ b/vendor/twig/twig/tests/Fixtures/filters/default.test @@ -39,22 +39,22 @@ Deep nested: {{ object.self.undefinedMethod |default('default') is same as('default') ? 'ok' : 'ko' }} {{ object.undefinedMethod.self |default('default') is same as('default') ? 'ok' : 'ko' }} --DATA-- -return array( +return [ 'definedVar' => 'defined', 'zeroVar' => 0, 'emptyVar' => '', 'nullVar' => null, - 'nested' => array( + 'nested' => [ 'definedVar' => 'defined', 'zeroVar' => 0, 'emptyVar' => '', 'nullVar' => null, - 'definedArray' => array(0), - ), - 'object' => new TwigTestFoo(), -) + 'definedArray' => [0], + ], + 'object' => new Twig\Tests\TwigTestFoo(), +] --CONFIG-- -return array('strict_variables' => false) +return ['strict_variables' => false] --EXPECT-- Variable: ok @@ -94,22 +94,22 @@ ok ok ok --DATA-- -return array( +return [ 'definedVar' => 'defined', 'zeroVar' => 0, 'emptyVar' => '', 'nullVar' => null, - 'nested' => array( + 'nested' => [ 'definedVar' => 'defined', 'zeroVar' => 0, 'emptyVar' => '', 'nullVar' => null, - 'definedArray' => array(0), - ), - 'object' => new TwigTestFoo(), -) + 'definedArray' => [0], + ], + 'object' => new Twig\Tests\TwigTestFoo(), +] --CONFIG-- -return array('strict_variables' => true) +return ['strict_variables' => true] --EXPECT-- Variable: ok diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/dynamic_filter.test b/vendor/twig/twig/tests/Fixtures/filters/dynamic_filter.test similarity index 88% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/filters/dynamic_filter.test rename to vendor/twig/twig/tests/Fixtures/filters/dynamic_filter.test index 93c5913f2beb8695daba670be24d4de94024cfe1..27dc8784c6b64aa8f8472d84aa0205d680be11bb 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/dynamic_filter.test +++ b/vendor/twig/twig/tests/Fixtures/filters/dynamic_filter.test @@ -4,7 +4,7 @@ dynamic filter {{ 'bar'|foo_path }} {{ 'bar'|a_foo_b_bar }} --DATA-- -return array() +return [] --EXPECT-- foo/bar a/b/bar diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/escape.test b/vendor/twig/twig/tests/Fixtures/filters/escape.test similarity index 86% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/filters/escape.test rename to vendor/twig/twig/tests/Fixtures/filters/escape.test index a606c10650d7006a26fe11be2c8d45f68d8c7320..131f5b4e72b76badd09fcd26786b467b433b49b6 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/escape.test +++ b/vendor/twig/twig/tests/Fixtures/filters/escape.test @@ -3,6 +3,6 @@ --TEMPLATE-- {{ "foo <br />"|e }} --DATA-- -return array() +return [] --EXPECT-- foo <br /> diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/escape_html_attr.test b/vendor/twig/twig/tests/Fixtures/filters/escape_html_attr.test similarity index 92% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/filters/escape_html_attr.test rename to vendor/twig/twig/tests/Fixtures/filters/escape_html_attr.test index 009a24532fd9c43550d2ffa51a7b6bc2d75c04b0..10e3275542102d8a0d8e5b60b1dc88619bf881b4 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/escape_html_attr.test +++ b/vendor/twig/twig/tests/Fixtures/filters/escape_html_attr.test @@ -3,6 +3,6 @@ --TEMPLATE-- {{ '<br />'|escape('html_attr') }} --DATA-- -return array() +return [] --EXPECT-- <br /> diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/escape_javascript.test b/vendor/twig/twig/tests/Fixtures/filters/escape_javascript.test similarity index 64% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/filters/escape_javascript.test rename to vendor/twig/twig/tests/Fixtures/filters/escape_javascript.test index 647147a439dc4c1ce4bfe4c48491cdd208a87ff3..4c2fb7a3668257beba238933252c17cc8831abab 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/escape_javascript.test +++ b/vendor/twig/twig/tests/Fixtures/filters/escape_javascript.test @@ -3,6 +3,6 @@ --TEMPLATE-- {{ "é ♜ ðŒ†"|e('js') }} --DATA-- -return array() +return [] --EXPECT-- -\u00E9\x20\u265C\x20\uD834\uDF06 +\u00E9\u0020\u265C\u0020\uD834\uDF06 diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/escape_non_supported_charset.test b/vendor/twig/twig/tests/Fixtures/filters/escape_non_supported_charset.test similarity index 90% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/filters/escape_non_supported_charset.test rename to vendor/twig/twig/tests/Fixtures/filters/escape_non_supported_charset.test index bba26a0df424cc62b7822a86fa7ff72d7277a8be..93f34297b09bb5a1b2f1cb5334c75ee0148db0c0 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/escape_non_supported_charset.test +++ b/vendor/twig/twig/tests/Fixtures/filters/escape_non_supported_charset.test @@ -3,6 +3,6 @@ --TEMPLATE-- {{ "æ„›ã—ã¦ã„ã¾ã™ã‹ï¼Ÿ <br />"|e }} --DATA-- -return array() +return [] --EXPECT-- æ„›ã—ã¦ã„ã¾ã™ã‹ï¼Ÿ <br /> diff --git a/vendor/twig/twig/tests/Fixtures/filters/filter.test b/vendor/twig/twig/tests/Fixtures/filters/filter.test new file mode 100644 index 0000000000000000000000000000000000000000..fe44d80ed7e52e4f19bbab6b951333225d956cbb --- /dev/null +++ b/vendor/twig/twig/tests/Fixtures/filters/filter.test @@ -0,0 +1,46 @@ +--TEST-- +"filter" filter +--TEMPLATE-- +{% set offset = 3 %} + +{% for k, v in [1, 5, 3, 4, 5]|filter((v) => v > offset) -%} + {{ k }} = {{ v }} +{% endfor %} + +{% for k, v in {a: 1, b: 2, c: 5, d: 8}|filter(v => v > offset) -%} + {{ k }} = {{ v }} +{% endfor %} + +{% for k, v in [1, 5, 3, 4, 5]|filter(v => v > offset) -%} + {{ k }} = {{ v }} +{% endfor %} + +{% for k, v in it|filter((v) => v > offset) -%} + {{ k }} = {{ v }} +{% endfor %} + +{% for k, v in ita|filter(v => v > offset) -%} + {{ k }} = {{ v }} +{% endfor %} +--DATA-- +return [ + 'it' => new \ArrayIterator(['a' => 1, 'b' => 2, 'c' => 5, 'd' => 8]), + 'ita' => new Twig\Tests\IteratorAggregateStub(['a' => 1, 'b' => 2, 'c' => 5, 'd' => 8]), +] +--EXPECT-- +1 = 5 +3 = 4 +4 = 5 + +c = 5 +d = 8 + +1 = 5 +3 = 4 +4 = 5 + +c = 5 +d = 8 + +c = 5 +d = 8 diff --git a/vendor/twig/twig/tests/Fixtures/filters/filter_php_55.test b/vendor/twig/twig/tests/Fixtures/filters/filter_php_55.test new file mode 100644 index 0000000000000000000000000000000000000000..6684139a1a7bc8e136b0f90889354166d37681e0 --- /dev/null +++ b/vendor/twig/twig/tests/Fixtures/filters/filter_php_55.test @@ -0,0 +1,23 @@ +--TEST-- +"filter" filter (PHP 5.5 required) +--CONDITION-- +version_compare(phpversion(), '5.5.0', '>=') +--TEMPLATE-- +{% for k, v in xml|filter(x => true) %} +{{ k }}/{{ v }} +{% endfor %} + +{# we can iterate more than once #} +{% for k, v in xml|filter(x => true) %} +{{ k }}/{{ v }} +{% endfor %} +--DATA-- +return ['xml' => new \SimpleXMLElement('<?xml version="1.0" encoding="UTF-8"?><doc><elem>foo</elem><elem>bar</elem><elem>baz</elem></doc>')] +--EXPECT-- +elem/foo +elem/bar +elem/baz + +elem/foo +elem/bar +elem/baz diff --git a/vendor/twig/twig/tests/Fixtures/filters/filter_php_56.test b/vendor/twig/twig/tests/Fixtures/filters/filter_php_56.test new file mode 100644 index 0000000000000000000000000000000000000000..0daf4083ad4cc2ce158f1d66a30ae33a72d80d7a --- /dev/null +++ b/vendor/twig/twig/tests/Fixtures/filters/filter_php_56.test @@ -0,0 +1,27 @@ +--TEST-- +"filter" filter (PHP 5.6 required) +--CONDITION-- +version_compare(phpversion(), '5.6.0', '>=') +--TEMPLATE-- +{% set offset = 3 %} + +{% for k, v in {a: 1, b: 2, c: 5, d: 8}|filter((v, k) => (v > offset) and (k != "d")) -%} + {{ k }} = {{ v }} +{% endfor %} + +{% for k, v in it|filter((v, k) => (v > offset) and (k != "d")) -%} + {{ k }} = {{ v }} +{% endfor %} + +{# we can iterate more than once #} +{% for k, v in it|filter((v, k) => (v > offset) and (k != "d")) -%} + {{ k }} = {{ v }} +{% endfor %} +--DATA-- +return ['it' => new \ArrayIterator(['a' => 1, 'b' => 2, 'c' => 5, 'd' => 8])] +--EXPECT-- +c = 5 + +c = 5 + +c = 5 diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/first.test b/vendor/twig/twig/tests/Fixtures/filters/first.test similarity index 77% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/filters/first.test rename to vendor/twig/twig/tests/Fixtures/filters/first.test index aa54645c38da342177ed6e8665b7f7176cdb9b00..b19f2eed7bdeaa7e9661fef1b4284ce399bc9b55 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/first.test +++ b/vendor/twig/twig/tests/Fixtures/filters/first.test @@ -8,7 +8,7 @@ {{ 'Ä€é'|first }} {{ ''|first }} --DATA-- -return array('arr' => new ArrayObject(array(1, 2, 3, 4))) +return ['arr' => new \ArrayObject([1, 2, 3, 4])] --EXPECT-- 1 1 diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/force_escape.test b/vendor/twig/twig/tests/Fixtures/filters/force_escape.test similarity index 78% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/filters/force_escape.test rename to vendor/twig/twig/tests/Fixtures/filters/force_escape.test index 85a9b7172bdd49691b01232ead6d5ddf51f3f0cc..7efbe3200a673f3ba9ccfd11c318b5ae1b654df1 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/force_escape.test +++ b/vendor/twig/twig/tests/Fixtures/filters/force_escape.test @@ -11,8 +11,8 @@ {{ foo }} {% endautoescape %} --DATA-- -return array() +return [] --EXPECT-- foo<br /> -\x20\x20\x20\x20foo\x3Cbr\x20\x2F\x3E\x0A +\u0020\u0020\u0020\u0020foo\u003Cbr\u0020\/\u003E\n foo<br /> diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/format.test b/vendor/twig/twig/tests/Fixtures/filters/format.test similarity index 64% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/filters/format.test rename to vendor/twig/twig/tests/Fixtures/filters/format.test index 97221ff80ee2b20ac1dc02ea46eed6ab82cc55d1..efaf8317a3c2f8341b620d720f5631452ba2119d 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/format.test +++ b/vendor/twig/twig/tests/Fixtures/filters/format.test @@ -3,6 +3,6 @@ --TEMPLATE-- {{ string|format(foo, 3) }} --DATA-- -return array('string' => '%s/%d', 'foo' => 'bar') +return ['string' => '%s/%d', 'foo' => 'bar'] --EXPECT-- bar/3 diff --git a/vendor/twig/twig/tests/Fixtures/filters/join.test b/vendor/twig/twig/tests/Fixtures/filters/join.test new file mode 100644 index 0000000000000000000000000000000000000000..3127ea1a7123170e39ab7c5f7ca46a89062f7d12 --- /dev/null +++ b/vendor/twig/twig/tests/Fixtures/filters/join.test @@ -0,0 +1,38 @@ +--TEST-- +"join" filter +--TEMPLATE-- +{{ ["foo", "bar"]|join(', ') }} +{{ foo|join(', ') }} +{{ bar|join(', ') }} + +{{ ["foo", "bar"]|join(', ', ' and ') }} +{{ foo|join(', ', ' and ') }} +{{ bar|join(', ', ' and ') }} +{{ ["one", "two", "three"]|join(', ', ' and ') }} +{{ ["a", "b", "c"]|join('','-') }} +{{ ["a", "b", "c"]|join('-','-') }} +{{ ["a", "b", "c"]|join('-','') }} +{{ ["hello"]|join('|','-') }} + +{{ {"a": "w", "b": "x", "c": "y", "d": "z"}|join }} +{{ {"a": "w", "b": "x", "c": "y", "d": "z"}|join(',') }} +{{ {"a": "w", "b": "x", "c": "y", "d": "z"}|join(',','-') }} +--DATA-- +return ['foo' => new Twig\Tests\TwigTestFoo(), 'bar' => new \ArrayObject([3, 4])] +--EXPECT-- +foo, bar +1, 2 +3, 4 + +foo and bar +1 and 2 +3 and 4 +one, two and three +ab-c +a-b-c +a-bc +hello + +wxyz +w,x,y,z +w,x,y-z diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/json_encode.test b/vendor/twig/twig/tests/Fixtures/filters/json_encode.test similarity index 76% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/filters/json_encode.test rename to vendor/twig/twig/tests/Fixtures/filters/json_encode.test index 1738d40cdfb79bb6f2aea41c2433b7708677635c..902f90b337743bbbb0610b6a0b07cad5c058c73b 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/json_encode.test +++ b/vendor/twig/twig/tests/Fixtures/filters/json_encode.test @@ -5,7 +5,7 @@ {{ foo|json_encode|raw }} {{ [foo, "foo"]|json_encode|raw }} --DATA-- -return array('foo' => new Twig_Markup('foo', 'UTF-8')) +return ['foo' => new \Twig\Markup('foo', 'UTF-8')] --EXPECT-- "foo" "foo" diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/last.test b/vendor/twig/twig/tests/Fixtures/filters/last.test similarity index 77% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/filters/last.test rename to vendor/twig/twig/tests/Fixtures/filters/last.test index 1b8031ee840a92e0734f2d9971424c4f3bf134cb..f71896c77f6434a9e0a2b689aaa3e6af143b96b5 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/last.test +++ b/vendor/twig/twig/tests/Fixtures/filters/last.test @@ -8,7 +8,7 @@ {{ 'Ä€é'|last }} {{ ''|last }} --DATA-- -return array('arr' => new ArrayObject(array(1, 2, 3, 4))) +return ['arr' => new \ArrayObject([1, 2, 3, 4])] --EXPECT-- 4 4 diff --git a/vendor/twig/twig/tests/Fixtures/filters/length.test b/vendor/twig/twig/tests/Fixtures/filters/length.test new file mode 100644 index 0000000000000000000000000000000000000000..eb3f02334f37c54ea0e0410535fa5c001a37625e --- /dev/null +++ b/vendor/twig/twig/tests/Fixtures/filters/length.test @@ -0,0 +1,40 @@ +--TEST-- +"length" filter +--TEMPLATE-- +{{ array|length }} +{{ string|length }} +{{ number|length }} +{{ to_string_able|length }} +{{ countable|length }} +{{ iterator_aggregate|length }} +{{ null|length }} +{{ magic|length }} +{{ non_countable|length }} +{{ simple_xml_element|length }} +{{ iterator|length }} +--DATA-- +return [ + 'array' => [1, 4], + 'string' => 'foo', + 'number' => 1000, + 'to_string_able' => new Twig\Tests\ToStringStub('foobar'), + 'countable' => new Twig\Tests\CountableStub(42), /* also asserts we do *not* call __toString() */ + 'iterator_aggregate' => new Twig\Tests\IteratorAggregateStub(['a', 'b', 'c']), /* also asserts we do *not* call __toString() */ + 'null' => null, + 'magic' => new Twig\Tests\MagicCallStub(), /* used to assert we do *not* call __call */ + 'non_countable' => new \StdClass(), + 'simple_xml_element' => new \SimpleXMLElement('<?xml version="1.0" encoding="UTF-8"?><doc><elem/><elem/></doc>'), + 'iterator' => new Twig\Tests\SimpleIteratorForTesting() +] +--EXPECT-- +2 +3 +4 +6 +42 +3 +0 +1 +1 +2 +7 diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/length_utf8.test b/vendor/twig/twig/tests/Fixtures/filters/length_utf8.test similarity index 65% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/filters/length_utf8.test rename to vendor/twig/twig/tests/Fixtures/filters/length_utf8.test index 5d5e243616d76c494987afb2c9e75682d8e48fba..b1e9681a5d556e528593d513356debe044a62645 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/length_utf8.test +++ b/vendor/twig/twig/tests/Fixtures/filters/length_utf8.test @@ -6,7 +6,7 @@ function_exists('mb_get_info') {{ string|length }} {{ markup|length }} --DATA-- -return array('string' => 'été', 'markup' => new Twig_Markup('foo', 'UTF-8')) +return ['string' => 'été', 'markup' => new \Twig\Markup('foo', 'UTF-8')] --EXPECT-- 3 3 diff --git a/vendor/twig/twig/tests/Fixtures/filters/map.test b/vendor/twig/twig/tests/Fixtures/filters/map.test new file mode 100644 index 0000000000000000000000000000000000000000..5552f816683d5465d27b722c52e107bec5c98447 --- /dev/null +++ b/vendor/twig/twig/tests/Fixtures/filters/map.test @@ -0,0 +1,41 @@ +--TEST-- +"map" filter +--TEMPLATE-- +{% set offset = 3 %} + +{% for k, v in [1, 2]|map((item) => item + 2 ) -%} + {{ k }} = {{ v }} +{% endfor %} + +{% for k, v in {a: 1, b: 2}|map((item) => item ~ "*" ) -%} + {{ k }} = {{ v }} +{% endfor %} + +{% for k, v in {a: 1, b: 2}|map((item, k) => item ~ "*" ~ k ) -%} + {{ k }} = {{ v }} +{% endfor %} + +{% for k, v in [1, 2]|map(item => item + 2 ) -%} + {{ k }} = {{ v }} +{% endfor %} + +{% for k, v in it|map(item => item + 2 ) -%} + {{ k }} = {{ v }} +{% endfor %} +--DATA-- +return ['it' => new \ArrayIterator([1, 2])] +--EXPECT-- +0 = 3 +1 = 4 + +a = 1* +b = 2* + +a = 1*a +b = 2*b + +0 = 3 +1 = 4 + +0 = 3 +1 = 4 diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/merge.test b/vendor/twig/twig/tests/Fixtures/filters/merge.test similarity index 62% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/filters/merge.test rename to vendor/twig/twig/tests/Fixtures/filters/merge.test index 81371a41b94fd7d69f9739df91a6f0040035fbe5..8877501d4cc1227ff0dded4afb5680ca5c0df403 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/merge.test +++ b/vendor/twig/twig/tests/Fixtures/filters/merge.test @@ -8,7 +8,14 @@ {{ numerics|merge([4, 5, 6])|join }} {{ traversable.a|merge(traversable.b)|join }} --DATA-- -return array('items' => array('foo' => 'bar'), 'numerics' => array(1, 2, 3), 'traversable' => array('a' => new ArrayObject(array(0 => 1, 1 => 2, 2 => 3)), 'b' => new ArrayObject(array('a' => 'b')))) +return [ + 'items' => ['foo' => 'bar'], + 'numerics' => [1, 2, 3], + 'traversable' => [ + 'a' => new \ArrayObject([0 => 1, 1 => 2, 2 => 3]), + 'b' => new \ArrayObject(['a' => 'b']) + ] +] --EXPECT-- barfoo foobar diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/nl2br.test b/vendor/twig/twig/tests/Fixtures/filters/nl2br.test similarity index 77% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/filters/nl2br.test rename to vendor/twig/twig/tests/Fixtures/filters/nl2br.test index 6545a9bb0104e76fe9062df592ab1566319e8fe9..524ec45f9630367a5c5f8b6a5dcd044d8251a798 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/nl2br.test +++ b/vendor/twig/twig/tests/Fixtures/filters/nl2br.test @@ -4,7 +4,7 @@ {{ "I like Twig.\nYou will like it too.\n\nEverybody like it!"|nl2br }} {{ text|nl2br }} --DATA-- -return array('text' => "If you have some <strong>HTML</strong>\nit will be escaped.") +return ['text' => "If you have some <strong>HTML</strong>\nit will be escaped."] --EXPECT-- I like Twig.<br /> You will like it too.<br /> diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/number_format.test b/vendor/twig/twig/tests/Fixtures/filters/number_format.test similarity index 94% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/filters/number_format.test rename to vendor/twig/twig/tests/Fixtures/filters/number_format.test index 639a8659f0d4af012416d8fa5faff16fc540fa47..7f1e2e16a288e52db5c47e0270fd0ed370a6053a 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/number_format.test +++ b/vendor/twig/twig/tests/Fixtures/filters/number_format.test @@ -8,7 +8,7 @@ {{ 1020.25|number_format(2, ',') }} {{ 1020.25|number_format(2, ',', '.') }} --DATA-- -return array(); +return [] --EXPECT-- 20 20 diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/number_format_default.test b/vendor/twig/twig/tests/Fixtures/filters/number_format_default.test similarity index 78% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/filters/number_format_default.test rename to vendor/twig/twig/tests/Fixtures/filters/number_format_default.test index 65c1cdb4862b03d012f9ffb0fd4e1f49c832a365..beedd901a090379d7657b5757d07d1b6a911e92d 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/number_format_default.test +++ b/vendor/twig/twig/tests/Fixtures/filters/number_format_default.test @@ -9,8 +9,8 @@ {{ 1020.25|number_format(2, ',') }} {{ 1020.25|number_format(2, ',', '.') }} --DATA-- -$twig->getExtension('Twig_Extension_Core')->setNumberFormat(2, '!', '='); -return array(); +$twig->getExtension('\Twig\Extension\CoreExtension')->setNumberFormat(2, '!', '='); +return [] --EXPECT-- 20!00 20!25 diff --git a/vendor/twig/twig/tests/Fixtures/filters/reduce.test b/vendor/twig/twig/tests/Fixtures/filters/reduce.test new file mode 100644 index 0000000000000000000000000000000000000000..73cad4168671f7cf99066f9c1e8305b353f74b00 --- /dev/null +++ b/vendor/twig/twig/tests/Fixtures/filters/reduce.test @@ -0,0 +1,14 @@ +--TEST-- +"reduce" filter +--TEMPLATE-- +{% set offset = 3 %} + +{{ [1, -1, 4]|reduce((carry, item) => carry + item + offset, 10) }} + +{{ it|reduce((carry, item) => carry + item + offset, 10) }} +--DATA-- +return ['it' => new \ArrayIterator([1, -1, 4])] +--EXPECT-- +23 + +23 diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/replace.test b/vendor/twig/twig/tests/Fixtures/filters/replace.test similarity index 79% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/filters/replace.test rename to vendor/twig/twig/tests/Fixtures/filters/replace.test index 06be7e270aefd08b58d2b27b3982580eb600140f..1b9670a17b38e6480f8e7902990383949de353af 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/replace.test +++ b/vendor/twig/twig/tests/Fixtures/filters/replace.test @@ -5,7 +5,7 @@ {{ 'I like single replace operation only %that%'|replace({'%that%' : '%that%1'}) }} {{ 'I like %this% and %that%.'|replace(traversable) }} --DATA-- -return array('traversable' => new ArrayObject(array('%this%' => 'foo', '%that%' => 'bar'))) +return ['traversable' => new \ArrayObject(['%this%' => 'foo', '%that%' => 'bar'])] --EXPECT-- I liké foo and bar. I like single replace operation only %that%1 diff --git a/vendor/twig/twig/tests/Fixtures/filters/replace_invalid_arg.test b/vendor/twig/twig/tests/Fixtures/filters/replace_invalid_arg.test new file mode 100644 index 0000000000000000000000000000000000000000..ba6fea4125a2eb3c18b6cce12b2e8b5f801b1760 --- /dev/null +++ b/vendor/twig/twig/tests/Fixtures/filters/replace_invalid_arg.test @@ -0,0 +1,8 @@ +--TEST-- +Exception for invalid argument type in replace call +--TEMPLATE-- +{{ 'test %foo%'|replace(stdClass) }} +--DATA-- +return ['stdClass' => new \stdClass()] +--EXCEPTION-- +Twig\Error\RuntimeError: The "replace" filter expects an array or "Traversable" as replace values, got "stdClass" in "index.twig" at line 2. diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/reverse.test b/vendor/twig/twig/tests/Fixtures/filters/reverse.test similarity index 86% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/filters/reverse.test rename to vendor/twig/twig/tests/Fixtures/filters/reverse.test index 7948ac45fece15b5811347c66b1272925bffa888..904e5839b02971e6c08e1c4a78b34e13e78513d5 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/reverse.test +++ b/vendor/twig/twig/tests/Fixtures/filters/reverse.test @@ -8,7 +8,7 @@ {{ {'a': 'c', 'b': 'a'}|reverse(preserveKeys=true)|join(glue=',') }} {{ {'a': 'c', 'b': 'a'}|reverse(preserve_keys=true)|join(glue=',') }} --DATA-- -return array('arr' => new ArrayObject(array(1, 2, 3, 4))) +return ['arr' => new \ArrayObject([1, 2, 3, 4])] --EXPECT-- 4321 tnemenèvé4321 diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/round.test b/vendor/twig/twig/tests/Fixtures/filters/round.test similarity index 94% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/filters/round.test rename to vendor/twig/twig/tests/Fixtures/filters/round.test index 57806b619717f8a086ce82936b181c4b12024592..709237543a4c62e358ac92eff1e5c89b4353d5b7 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/round.test +++ b/vendor/twig/twig/tests/Fixtures/filters/round.test @@ -10,7 +10,7 @@ {{ 21.3|round(-1, 'ceil')}} {{ 21.3|round(-1, 'floor')}} --DATA-- -return array() +return [] --EXPECT-- 3 2 diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/slice.test b/vendor/twig/twig/tests/Fixtures/filters/slice.test similarity index 83% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/filters/slice.test rename to vendor/twig/twig/tests/Fixtures/filters/slice.test index b49b89fe56d25cedd39bb89822786a85806bd6b3..fc975d7bb186d7f9079f46f7ae7b844b9cc07af2 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/slice.test +++ b/vendor/twig/twig/tests/Fixtures/filters/slice.test @@ -26,7 +26,7 @@ {{ arr[2:]|join('') }} {{ xml|slice(1)|join('')}} --DATA-- -return array('start' => 1, 'length' => 2, 'arr' => new ArrayObject(array(1, 2, 3, 4)), 'xml' => new SimpleXMLElement('<items><item>1</item><item>2</item></items>')) +return ['start' => 1, 'length' => 2, 'arr' => new \ArrayObject([1, 2, 3, 4]), 'xml' => new \SimpleXMLElement('<items><item>1</item><item>2</item></items>')] --EXPECT-- 23 23 diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/sort.test b/vendor/twig/twig/tests/Fixtures/filters/sort.test similarity index 51% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/filters/sort.test rename to vendor/twig/twig/tests/Fixtures/filters/sort.test index c67c18ea90a3f9cf2a7fd7e7ac9d187831a2a814..c3b2c70dd4ae670e69954eb54ff76fcf0b590ef1 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/sort.test +++ b/vendor/twig/twig/tests/Fixtures/filters/sort.test @@ -5,7 +5,7 @@ {{ array2|sort|join }} {{ traversable|sort|join }} --DATA-- -return array('array1' => array(4, 1), 'array2' => array('foo', 'bar'), 'traversable' => new ArrayObject(array(0 => 3, 1 => 2, 2 => 1))) +return ['array1' => [4, 1], 'array2' => ['foo', 'bar'], 'traversable' => new \ArrayObject([0 => 3, 1 => 2, 2 => 1])] --EXPECT-- 14 barfoo diff --git a/vendor/twig/twig/tests/Fixtures/filters/spaceless.test b/vendor/twig/twig/tests/Fixtures/filters/spaceless.test new file mode 100644 index 0000000000000000000000000000000000000000..eadc1d4962a3e87c517b8b42dce03736e71e9712 --- /dev/null +++ b/vendor/twig/twig/tests/Fixtures/filters/spaceless.test @@ -0,0 +1,8 @@ +--TEST-- +"spaceless" filter +--TEMPLATE-- +{{ " <div> <div> foo </div> </div>"|spaceless }} +--DATA-- +return [] +--EXPECT-- +<div><div> foo </div></div> diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/special_chars.test b/vendor/twig/twig/tests/Fixtures/filters/special_chars.test similarity index 84% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/filters/special_chars.test rename to vendor/twig/twig/tests/Fixtures/filters/special_chars.test index dbaf7dc979bf1d5bfe5872dd730b6e9777023b97..9869ec91c345b3432516527c44a239018094ec3b 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/special_chars.test +++ b/vendor/twig/twig/tests/Fixtures/filters/special_chars.test @@ -3,6 +3,6 @@ --TEMPLATE-- {{ 'foo'|§ }} --DATA-- -return array() +return [] --EXPECT-- §foo§ diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/split.test b/vendor/twig/twig/tests/Fixtures/filters/split.test similarity index 75% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/filters/split.test rename to vendor/twig/twig/tests/Fixtures/filters/split.test index a093ed79b5a584d1e6fedbfa484742585be8ba18..2bd46afa36dc94535f8b1cb5f8f97f1588b4b738 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/split.test +++ b/vendor/twig/twig/tests/Fixtures/filters/split.test @@ -8,8 +8,9 @@ {{ baz|split('', 1)|join('-') }} {{ baz|split('', 2)|join('-') }} {{ foo|split(',', -2)|join('-') }} +{{ "hello0world"|split('0')|join('-') }} --DATA-- -return array('foo' => "one,two,three,four,five", 'baz' => '12345',) +return ['foo' => "one,two,three,four,five", 'baz' => '12345',] --EXPECT-- one-two-three-four-five one-two-three-four-five @@ -17,4 +18,5 @@ one-two-three,four,five 1-2-3-4-5 1-2-3-4-5 12-34-5 -one-two-three \ No newline at end of file +one-two-three +hello-world \ No newline at end of file diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/split_utf8.test b/vendor/twig/twig/tests/Fixtures/filters/split_utf8.test similarity index 88% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/filters/split_utf8.test rename to vendor/twig/twig/tests/Fixtures/filters/split_utf8.test index 305e162feacfda508329da5eeaecf677d784da22..bf52e6df76173ea13e48c87f6eea45b5dac10e7d 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/split_utf8.test +++ b/vendor/twig/twig/tests/Fixtures/filters/split_utf8.test @@ -12,7 +12,7 @@ function_exists('mb_get_info') {{ baz|split('', 1)|join('-') }} {{ baz|split('', 2)|join('-') }} --DATA-- -return array('foo' => 'Ä,é,Äã»', 'baz' => 'éÄßã”a',) +return ['foo' => 'Ä,é,Äã»', 'baz' => 'éÄßã”a',] --EXPECT-- é Ä-é-Ä㻠diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/static_calls.test b/vendor/twig/twig/tests/Fixtures/filters/static_calls.test similarity index 83% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/filters/static_calls.test rename to vendor/twig/twig/tests/Fixtures/filters/static_calls.test index 4e17b7726cb71f1df8c1d93634f0b61d0d05098e..1626db0c97298765d39d45006b24c41910ba2e3a 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/static_calls.test +++ b/vendor/twig/twig/tests/Fixtures/filters/static_calls.test @@ -4,7 +4,7 @@ Filters as static method calls {{ 'foo'|static_call_string }} {{ 'foo'|static_call_array }} --DATA-- -return array('foo' => 'foo') +return ['foo' => 'foo'] --EXPECT-- *foo* *foo* diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/trim.test b/vendor/twig/twig/tests/Fixtures/filters/trim.test similarity index 87% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/filters/trim.test rename to vendor/twig/twig/tests/Fixtures/filters/trim.test index b1ef7b473128365aa40486cd65df0086ca411b87..432989ff165f06a3cde1dd13acf44f770fdd821b 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/trim.test +++ b/vendor/twig/twig/tests/Fixtures/filters/trim.test @@ -11,7 +11,7 @@ {{ "/ foo/"|trim(character_mask="/", side="left") }} {{ " do nothing. "|trim("", "right") }} --DATA-- -return array('text' => " If you have some <strong>HTML</strong> it will be escaped. ") +return ['text' => " If you have some <strong>HTML</strong> it will be escaped. "] --EXPECT-- I like Twig. If you have some <strong>HTML</strong> it will be escaped. diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/urlencode.test b/vendor/twig/twig/tests/Fixtures/filters/urlencode.test similarity index 97% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/filters/urlencode.test rename to vendor/twig/twig/tests/Fixtures/filters/urlencode.test index 8726159db0668a03502bdaddd4ddea7d4a1fc35a..66a682dd397ce2da5cad04837ab781125b87015d 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/urlencode.test +++ b/vendor/twig/twig/tests/Fixtures/filters/urlencode.test @@ -8,7 +8,7 @@ defined('PHP_QUERY_RFC3986') {{ {}|url_encode|default("default") }} {{ 'spéßi%le%c0d@dspa ce'|url_encode }} --DATA-- -return array() +return [] --EXPECT-- foo=bar&number=3&sp%C3%A9%C3%9Fi%25l=e%25c0d%40d&spa%20ce= foo=bar&number=3&sp%C3%A9%C3%9Fi%25l=e%25c0d%40d&spa%20ce= diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/urlencode_deprecated.test b/vendor/twig/twig/tests/Fixtures/filters/urlencode_deprecated.test similarity index 97% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/filters/urlencode_deprecated.test rename to vendor/twig/twig/tests/Fixtures/filters/urlencode_deprecated.test index 35e50390d57c89bcae1bf7dff1207d5dc74673b0..38d726492aad5b0600e568997e442d9dfe98ad1d 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/filters/urlencode_deprecated.test +++ b/vendor/twig/twig/tests/Fixtures/filters/urlencode_deprecated.test @@ -8,7 +8,7 @@ defined('PHP_QUERY_RFC3986') {{ {}|url_encode|default("default") }} {{ 'spéßi%le%c0d@dspa ce'|url_encode }} --DATA-- -return array() +return [] --EXPECT-- foo=bar&number=3&sp%C3%A9%C3%9Fi%25l=e%25c0d%40d&spa%20ce= foo=bar&number=3&sp%C3%A9%C3%9Fi%25l=e%25c0d%40d&spa%20ce= diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/functions/attribute.test b/vendor/twig/twig/tests/Fixtures/functions/attribute.test similarity index 67% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/functions/attribute.test rename to vendor/twig/twig/tests/Fixtures/functions/attribute.test index 71b2038aa9402e1376aaa29c4d9bdadedfb6eaea..4499ad4bdee3d8dd8c3f1c96b5dde9d4c6fa56d2 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/functions/attribute.test +++ b/vendor/twig/twig/tests/Fixtures/functions/attribute.test @@ -8,7 +8,7 @@ {{ attribute(obj, method) is defined ? 'ok' : 'ko' }} {{ attribute(obj, nonmethod) is defined ? 'ok' : 'ko' }} --DATA-- -return array('obj' => new TwigTestFoo(), 'method' => 'foo', 'array' => array('foo' => 'bar'), 'item' => 'foo', 'nonmethod' => 'xxx', 'arguments' => array('a', 'b')) +return ['obj' => new Twig\Tests\TwigTestFoo(), 'method' => 'foo', 'array' => ['foo' => 'bar'], 'item' => 'foo', 'nonmethod' => 'xxx', 'arguments' => ['a', 'b']] --EXPECT-- foo bar diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/functions/block.test b/vendor/twig/twig/tests/Fixtures/functions/block.test similarity index 94% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/functions/block.test rename to vendor/twig/twig/tests/Fixtures/functions/block.test index 8e54059aee1ba1adfd2e0bc5f7f8a524066e3eaa..1a4fd5492f859c8b46b9955c3b2fcf7c941a37b3 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/functions/block.test +++ b/vendor/twig/twig/tests/Fixtures/functions/block.test @@ -7,6 +7,6 @@ {% block foo %}{{ block('bar') }}{% endblock %} {% block bar %}BAR_BASE{% endblock %} --DATA-- -return array() +return [] --EXPECT-- BARBAR diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/functions/block_with_template.test b/vendor/twig/twig/tests/Fixtures/functions/block_with_template.test similarity index 83% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/functions/block_with_template.test rename to vendor/twig/twig/tests/Fixtures/functions/block_with_template.test index 8305eb67fcfdd220ee92a5930920013c3c03df9b..37cb7a4813fcf0d1ff2870d41730fd300a9bfebe 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/functions/block_with_template.test +++ b/vendor/twig/twig/tests/Fixtures/functions/block_with_template.test @@ -10,10 +10,10 @@ --TEMPLATE(included.twig)-- {% block foo %}FOO{% endblock %} --DATA-- -return array( +return [ 'included_loaded' => $twig->load('included.twig'), - 'included_loaded_internal' => $twig->loadTemplate('included.twig'), -) + 'included_loaded_internal' => $twig->load('included.twig'), +] --EXPECT-- FOO FOO diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/functions/block_without_name.test b/vendor/twig/twig/tests/Fixtures/functions/block_without_name.test similarity index 67% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/functions/block_without_name.test rename to vendor/twig/twig/tests/Fixtures/functions/block_without_name.test index 665cc87e584eef28c0c0761ad9e50f9139cc4def..236df945109f46142e602e6fe814d6460df14378 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/functions/block_without_name.test +++ b/vendor/twig/twig/tests/Fixtures/functions/block_without_name.test @@ -7,6 +7,6 @@ {% block foo %}{{ block() }}{% endblock %} {% block bar %}BAR_BASE{% endblock %} --DATA-- -return array() +return [] --EXCEPTION-- -Twig_Error_Syntax: The "block" function takes one argument (the block name) in "base.twig" at line 2. +Twig\Error\SyntaxError: The "block" function takes one argument (the block name) in "base.twig" at line 2. diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/functions/constant.test b/vendor/twig/twig/tests/Fixtures/functions/constant.test similarity index 68% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/functions/constant.test rename to vendor/twig/twig/tests/Fixtures/functions/constant.test index 63128791f5573177f7e046625993b0a3dd034d00..fd6dd06111667f0391410cbaccb3e6252fb2c8d4 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/functions/constant.test +++ b/vendor/twig/twig/tests/Fixtures/functions/constant.test @@ -4,7 +4,7 @@ {{ constant('DATE_W3C') == expect ? 'true' : 'false' }} {{ constant('ARRAY_AS_PROPS', object) }} --DATA-- -return array('expect' => DATE_W3C, 'object' => new ArrayObject(array('hi'))); +return ['expect' => DATE_W3C, 'object' => new \ArrayObject(['hi'])] --EXPECT-- true 2 diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/functions/cycle.test b/vendor/twig/twig/tests/Fixtures/functions/cycle.test similarity index 69% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/functions/cycle.test rename to vendor/twig/twig/tests/Fixtures/functions/cycle.test index 522a63b85f5a0f576c3ae3012675629b412cf07f..0ac6dccd3aee48f744065e8bd03e7c65f3c1c092 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/functions/cycle.test +++ b/vendor/twig/twig/tests/Fixtures/functions/cycle.test @@ -5,7 +5,7 @@ {{ cycle(array1, i) }}-{{ cycle(array2, i) }} {% endfor %} --DATA-- -return array('array1' => array('odd', 'even'), 'array2' => array('apple', 'orange', 'citrus')) +return ['array1' => ['odd', 'even'], 'array2' => ['apple', 'orange', 'citrus']] --EXPECT-- odd-apple even-orange diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/functions/date.test b/vendor/twig/twig/tests/Fixtures/functions/date.test similarity index 62% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/functions/date.test rename to vendor/twig/twig/tests/Fixtures/functions/date.test index c9f46446805d491e9dd2d7618bfba1a47b597b0e..c879da3cfd8d2ea67af0aa40c1fe0e0ee026670f 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/functions/date.test +++ b/vendor/twig/twig/tests/Fixtures/functions/date.test @@ -10,13 +10,13 @@ {{ date() > date('-1day') ? 'OK' : 'KO' }} --DATA-- date_default_timezone_set('UTC'); -return array( +return [ 'date1' => mktime(13, 45, 0, 10, 4, 2010), - 'date2' => new DateTime('2010-10-04 13:45'), + 'date2' => new \DateTime('2010-10-04 13:45'), 'date3' => '2010-10-04 13:45', - 'date4' => 1286199900, // DateTime::createFromFormat('Y-m-d H:i', '2010-10-04 13:45', new DateTimeZone('UTC'))->getTimestamp() -- A unixtimestamp is always GMT - 'date5' => -189291360, // DateTime::createFromFormat('Y-m-d H:i', '1964-01-02 03:04', new DateTimeZone('UTC'))->getTimestamp(), -) + 'date4' => 1286199900, // \DateTime::createFromFormat('Y-m-d H:i', '2010-10-04 13:45', new \DateTimeZone('UTC'))->getTimestamp() -- A unixtimestamp is always GMT + 'date5' => -189291360, // \DateTime::createFromFormat('Y-m-d H:i', '1964-01-02 03:04', new \DateTimeZone('UTC'))->getTimestamp(), +] --EXPECT-- OK OK diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/functions/date_namedargs.test b/vendor/twig/twig/tests/Fixtures/functions/date_namedargs.test similarity index 84% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/functions/date_namedargs.test rename to vendor/twig/twig/tests/Fixtures/functions/date_namedargs.test index b9dd9e38329f6bf8fef6ecdfb62e67ade95dab2e..11f60ee8bf2ee393960132a5d99ea8cfcc9269f0 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/functions/date_namedargs.test +++ b/vendor/twig/twig/tests/Fixtures/functions/date_namedargs.test @@ -5,7 +5,7 @@ {{ date(timezone="America/New_York", date=date)|date('d/m/Y H:i:s P', false) }} --DATA-- date_default_timezone_set('UTC'); -return array('date' => mktime(13, 45, 0, 10, 4, 2010)) +return ['date' => mktime(13, 45, 0, 10, 4, 2010)] --EXPECT-- 04/10/2010 09:45:00 -04:00 04/10/2010 09:45:00 -04:00 diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/functions/dump.test b/vendor/twig/twig/tests/Fixtures/functions/dump.test similarity index 67% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/functions/dump.test rename to vendor/twig/twig/tests/Fixtures/functions/dump.test index f4072375a808f738b0930ce2ea6ac6a07f66a445..691a3abea9bdb16de4611222463e628f05e370ab 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/functions/dump.test +++ b/vendor/twig/twig/tests/Fixtures/functions/dump.test @@ -6,9 +6,9 @@ {{ dump('foo') }} {{ dump('foo', 'bar') }} --DATA-- -return array('foo' => 'foo', 'bar' => 'bar') +return ['foo' => 'foo', 'bar' => 'bar'] --CONFIG-- -return array('debug' => true, 'autoescape' => false); +return ['debug' => true, 'autoescape' => false] --EXPECT-- string(3) "foo" diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/functions/dump_array.test b/vendor/twig/twig/tests/Fixtures/functions/dump_array.test similarity index 53% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/functions/dump_array.test rename to vendor/twig/twig/tests/Fixtures/functions/dump_array.test index 889b7a922e60ed439080a1a2739890de87f8df5d..5fd9383cd6ad44683039940a8bd5e7306bc0ccaf 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/functions/dump_array.test +++ b/vendor/twig/twig/tests/Fixtures/functions/dump_array.test @@ -1,13 +1,13 @@ --TEST-- "dump" function, xdebug is not loaded or xdebug <2.2-dev is loaded --CONDITION-- -!extension_loaded('xdebug') || (($r = new ReflectionExtension('xdebug')) && version_compare($r->getVersion(), '2.2-dev', '<')) +!extension_loaded('xdebug') || (($r = new \ReflectionExtension('xdebug')) && version_compare($r->getVersion(), '2.2-dev', '<')) --TEMPLATE-- {{ dump() }} --DATA-- -return array('foo' => 'foo', 'bar' => 'bar') +return ['foo' => 'foo', 'bar' => 'bar'] --CONFIG-- -return array('debug' => true, 'autoescape' => false); +return ['debug' => true, 'autoescape' => false] --EXPECT-- array(3) { ["foo"]=> diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/functions/dynamic_function.test b/vendor/twig/twig/tests/Fixtures/functions/dynamic_function.test similarity index 89% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/functions/dynamic_function.test rename to vendor/twig/twig/tests/Fixtures/functions/dynamic_function.test index 913fbc99595aab3e0a07dc07880e559f32950b00..c7b3539c4026a1561affacf871637c8ef4fc60cf 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/functions/dynamic_function.test +++ b/vendor/twig/twig/tests/Fixtures/functions/dynamic_function.test @@ -4,7 +4,7 @@ dynamic function {{ foo_path('bar') }} {{ a_foo_b_bar('bar') }} --DATA-- -return array() +return [] --EXPECT-- foo/bar a/b/bar diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/functions/include/assignment.test b/vendor/twig/twig/tests/Fixtures/functions/include/assignment.test similarity index 91% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/functions/include/assignment.test rename to vendor/twig/twig/tests/Fixtures/functions/include/assignment.test index b7653b4ef683b556c9803ae31e205d0f23019e07..c9ce8123feae7288f39daf4c8da69dad62f41a7a 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/functions/include/assignment.test +++ b/vendor/twig/twig/tests/Fixtures/functions/include/assignment.test @@ -7,7 +7,7 @@ FOO{{ tmp }}BAR --TEMPLATE(foo.twig)-- FOOBAR --DATA-- -return array() +return [] --EXPECT-- FOO FOOBARBAR diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/functions/include/autoescaping.test b/vendor/twig/twig/tests/Fixtures/functions/include/autoescaping.test similarity index 91% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/functions/include/autoescaping.test rename to vendor/twig/twig/tests/Fixtures/functions/include/autoescaping.test index 56f8f3b5a33cf4c5c5e5fb302bd9da17e9851006..a3666261f3953aef38c96e9a628c3a57506b5efb 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/functions/include/autoescaping.test +++ b/vendor/twig/twig/tests/Fixtures/functions/include/autoescaping.test @@ -5,6 +5,6 @@ --TEMPLATE(foo.twig)-- <p>Test</p> --DATA-- -return array() +return [] --EXPECT-- <p>Test</p> diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/functions/include/basic.test b/vendor/twig/twig/tests/Fixtures/functions/include/basic.test similarity index 90% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/functions/include/basic.test rename to vendor/twig/twig/tests/Fixtures/functions/include/basic.test index a434182a214b517206a736dfb4ebaa74a0d18303..f90983c02f3901f0deb0caa12e3502e0e8f60d93 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/functions/include/basic.test +++ b/vendor/twig/twig/tests/Fixtures/functions/include/basic.test @@ -8,7 +8,7 @@ BAR --TEMPLATE(foo.twig)-- FOOBAR --DATA-- -return array() +return [] --EXPECT-- FOO diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/functions/include/expression.test b/vendor/twig/twig/tests/Fixtures/functions/include/expression.test similarity index 84% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/functions/include/expression.test rename to vendor/twig/twig/tests/Fixtures/functions/include/expression.test index aba30ce3fcb963f5bcb83004197bed938f874a38..c6d3d1c5331e6fb49dd0a75f8cca49bb56092d55 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/functions/include/expression.test +++ b/vendor/twig/twig/tests/Fixtures/functions/include/expression.test @@ -8,7 +8,7 @@ BAR --TEMPLATE(foo.twig)-- FOOBAR --DATA-- -return array('foo' => 'foo.twig') +return ['foo' => 'foo.twig'] --EXPECT-- FOO diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/functions/include/ignore_missing.test b/vendor/twig/twig/tests/Fixtures/functions/include/ignore_missing.test similarity index 95% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/functions/include/ignore_missing.test rename to vendor/twig/twig/tests/Fixtures/functions/include/ignore_missing.test index 43a2ccc2c8957efee4e76d6d5a9406277670e4f1..c05b43e140315a123d36f761f1aeea1fa394542f 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/functions/include/ignore_missing.test +++ b/vendor/twig/twig/tests/Fixtures/functions/include/ignore_missing.test @@ -6,5 +6,5 @@ {{ include("foo.twig", ignore_missing = true, variables = {}) }} {{ include("foo.twig", ignore_missing = true, variables = {}, with_context = true) }} --DATA-- -return array() +return [] --EXPECT-- diff --git a/vendor/twig/twig/tests/Fixtures/functions/include/ignore_missing_exists.test b/vendor/twig/twig/tests/Fixtures/functions/include/ignore_missing_exists.test new file mode 100644 index 0000000000000000000000000000000000000000..fc2d211ad8614aaba958767138bd275931f7f5e1 --- /dev/null +++ b/vendor/twig/twig/tests/Fixtures/functions/include/ignore_missing_exists.test @@ -0,0 +1,11 @@ +--TEST-- +"include" function +--TEMPLATE-- +{{ include("included.twig", ignore_missing = true) }} +NOT DISPLAYED +--TEMPLATE(included.twig)-- +{{ include("DOES NOT EXIST") }} +--DATA-- +return [] +--EXCEPTION-- +Twig\Error\LoaderError: Template "DOES NOT EXIST" is not defined in "included.twig" at line 2. diff --git a/vendor/twig/twig/tests/Fixtures/functions/include/include_missing_extends.test b/vendor/twig/twig/tests/Fixtures/functions/include/include_missing_extends.test new file mode 100644 index 0000000000000000000000000000000000000000..810ae8248000c20fc6a6a6bac58512eadfdecf70 --- /dev/null +++ b/vendor/twig/twig/tests/Fixtures/functions/include/include_missing_extends.test @@ -0,0 +1,13 @@ +--TEST-- +"include" function +--TEMPLATE-- +{{ include(['bad.twig', 'good.twig'], ignore_missing = true) }} +NOT DISPLAYED +--TEMPLATE(bad.twig)-- +{% extends 'DOES NOT EXIST' %} +--TEMPLATE(good.twig)-- +NOT DISPLAYED +--DATA-- +return [] +--EXCEPTION-- +Twig\Error\LoaderError: Template "DOES NOT EXIST" is not defined in "bad.twig" at line 2. diff --git a/vendor/twig/twig/tests/Fixtures/functions/include/missing.test b/vendor/twig/twig/tests/Fixtures/functions/include/missing.test new file mode 100644 index 0000000000000000000000000000000000000000..1d50f7ac2feed6ff24da39d443758007ad28fd27 --- /dev/null +++ b/vendor/twig/twig/tests/Fixtures/functions/include/missing.test @@ -0,0 +1,8 @@ +--TEST-- +"include" function +--TEMPLATE-- +{{ include("foo.twig") }} +--DATA-- +return [] +--EXCEPTION-- +Twig\Error\LoaderError: Template "foo.twig" is not defined in "index.twig" at line 2. diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/functions/include/missing_nested.test b/vendor/twig/twig/tests/Fixtures/functions/include/missing_nested.test similarity index 70% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/functions/include/missing_nested.test rename to vendor/twig/twig/tests/Fixtures/functions/include/missing_nested.test index 78fddc7a683a4c0883d9a105f4e7aa7d9d30ca70..9ae8c9ee75935298bf77046f3e37eebe7a6adc07 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/functions/include/missing_nested.test +++ b/vendor/twig/twig/tests/Fixtures/functions/include/missing_nested.test @@ -11,6 +11,6 @@ {{ include("foo.twig") }} {% endblock %} --DATA-- -return array(); +return [] --EXCEPTION-- -Twig_Error_Loader: Template "foo.twig" is not defined in "base.twig" at line 3. +Twig\Error\LoaderError: Template "foo.twig" is not defined in "base.twig" at line 3. diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/functions/include/sandbox.test b/vendor/twig/twig/tests/Fixtures/functions/include/sandbox.test similarity index 70% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/functions/include/sandbox.test rename to vendor/twig/twig/tests/Fixtures/functions/include/sandbox.test index 7b9ccaca81f12f51c48e0bc879ec9681e0154161..ebfdb1eb8fff038b42071ce9e2a6bcedae1f6327 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/functions/include/sandbox.test +++ b/vendor/twig/twig/tests/Fixtures/functions/include/sandbox.test @@ -8,6 +8,6 @@ {{ foo|e }} {{ foo|e }} --DATA-- -return array() +return [] --EXCEPTION-- -Twig_Sandbox_SecurityNotAllowedFilterError: Filter "e" is not allowed in "foo.twig" at line 4. +Twig\Sandbox\SecurityNotAllowedFilterError: Filter "e" is not allowed in "foo.twig" at line 4. diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/functions/include/sandbox_disabling.test b/vendor/twig/twig/tests/Fixtures/functions/include/sandbox_disabling.test similarity index 86% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/functions/include/sandbox_disabling.test rename to vendor/twig/twig/tests/Fixtures/functions/include/sandbox_disabling.test index 8ffc49225e1b3954f6e6b5d09d8ba9196000f0eb..1206b67fe319bcb593a097a45329d00529ae8765 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/functions/include/sandbox_disabling.test +++ b/vendor/twig/twig/tests/Fixtures/functions/include/sandbox_disabling.test @@ -8,7 +8,7 @@ foo --TEMPLATE(bar.twig)-- {{ foo|e }} --DATA-- -return array('foo' => 'bar<br />') +return ['foo' => 'bar<br />'] --EXPECT-- foo diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/functions/include/sandbox_disabling_ignore_missing.test b/vendor/twig/twig/tests/Fixtures/functions/include/sandbox_disabling_ignore_missing.test similarity index 86% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/functions/include/sandbox_disabling_ignore_missing.test rename to vendor/twig/twig/tests/Fixtures/functions/include/sandbox_disabling_ignore_missing.test index 8bf6e102d9e4c81202c829ba9f8f8b29f8e6af51..c5be0088af646fee6f1489f9bd952b6ac9ca5fd0 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/functions/include/sandbox_disabling_ignore_missing.test +++ b/vendor/twig/twig/tests/Fixtures/functions/include/sandbox_disabling_ignore_missing.test @@ -6,7 +6,7 @@ --TEMPLATE(bar.twig)-- {{ foo|e }} --DATA-- -return array('foo' => 'bar<br />') +return ['foo' => 'bar<br />'] --EXPECT-- diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/functions/include/template_instance.test b/vendor/twig/twig/tests/Fixtures/functions/include/template_instance.test similarity index 73% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/functions/include/template_instance.test rename to vendor/twig/twig/tests/Fixtures/functions/include/template_instance.test index 18d405a02e3a33394775a590ebc9865a755697a3..4c8b450835c1ef6ba2f6009612bcd89afc00a9fd 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/functions/include/template_instance.test +++ b/vendor/twig/twig/tests/Fixtures/functions/include/template_instance.test @@ -5,6 +5,6 @@ --TEMPLATE(foo.twig)-- BAR --DATA-- -return array('foo' => $twig->loadTemplate('foo.twig')) +return ['foo' => $twig->load('foo.twig')] --EXPECT-- BAR FOO diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/functions/include/templates_as_array.test b/vendor/twig/twig/tests/Fixtures/functions/include/templates_as_array.test similarity index 92% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/functions/include/templates_as_array.test rename to vendor/twig/twig/tests/Fixtures/functions/include/templates_as_array.test index 1a8100687cd3de1e10817c583dbc1f2f42c7eaa1..21e5bb2efd20dfa6793d20e13dbebfc5be48f4bc 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/functions/include/templates_as_array.test +++ b/vendor/twig/twig/tests/Fixtures/functions/include/templates_as_array.test @@ -6,7 +6,7 @@ --TEMPLATE(foo.twig)-- foo --DATA-- -return array() +return [] --EXPECT-- foo foo diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/functions/include/with_context.test b/vendor/twig/twig/tests/Fixtures/functions/include/with_context.test similarity index 93% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/functions/include/with_context.test rename to vendor/twig/twig/tests/Fixtures/functions/include/with_context.test index 35611fbb9c68ea89ab9113c93966b39b6a11f3f3..46ac8c79bdc28854c5282b631f9751c2ffc2ea77 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/functions/include/with_context.test +++ b/vendor/twig/twig/tests/Fixtures/functions/include/with_context.test @@ -8,7 +8,7 @@ --TEMPLATE(foo.twig)-- {% for k, v in _context %}{{ k }},{% endfor %} --DATA-- -return array('foo' => 'bar') +return ['foo' => 'bar'] --EXPECT-- foo,global,_parent, global,_parent, diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/functions/include/with_variables.test b/vendor/twig/twig/tests/Fixtures/functions/include/with_variables.test similarity index 80% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/functions/include/with_variables.test rename to vendor/twig/twig/tests/Fixtures/functions/include/with_variables.test index b2ace940e955812440cb474bd37eb66276bb64d3..0ed98fed02f664d305732a97a67a574c0718f575 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/functions/include/with_variables.test +++ b/vendor/twig/twig/tests/Fixtures/functions/include/with_variables.test @@ -6,7 +6,7 @@ --TEMPLATE(foo.twig)-- {{ foo }} --DATA-- -return array('vars' => array('foo' => 'bar')) +return ['vars' => ['foo' => 'bar']] --EXPECT-- bar bar diff --git a/vendor/twig/twig/tests/Fixtures/functions/include_template_from_string.test b/vendor/twig/twig/tests/Fixtures/functions/include_template_from_string.test new file mode 100644 index 0000000000000000000000000000000000000000..8d9ba60ce6661d7d7a448430926ff883e0b4a4a4 --- /dev/null +++ b/vendor/twig/twig/tests/Fixtures/functions/include_template_from_string.test @@ -0,0 +1,11 @@ +--TEST-- +"template_from_string" function works in an "include" +--TEMPLATE-- +{% set embed = '{% embed "embed.twig" %}{% endembed %}' %} +{{ include(template_from_string(embed)) }} +--TEMPLATE(embed.twig)-- +Cool +--DATA-- +return [] +--EXPECT-- +Cool diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/functions/magic_call.test b/vendor/twig/twig/tests/Fixtures/functions/magic_call.test similarity index 85% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/functions/magic_call.test rename to vendor/twig/twig/tests/Fixtures/functions/magic_call.test index 9335443128d3faa753841acd16b75964525d8d72..4dd5e27042b0455033a4f913dba71a0cf95baec7 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/functions/magic_call.test +++ b/vendor/twig/twig/tests/Fixtures/functions/magic_call.test @@ -3,6 +3,6 @@ __call calls --TEMPLATE-- {{ 'foo'|magic_call }} --DATA-- -return array() +return [] --EXPECT-- magic_foo diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/functions/magic_call53.test b/vendor/twig/twig/tests/Fixtures/functions/magic_call53.test similarity index 93% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/functions/magic_call53.test rename to vendor/twig/twig/tests/Fixtures/functions/magic_call53.test index a0f55e11601ec3afff8c8767bd2f4c037d5771ed..a7c65bf6765121e927b768a826e277cee546d0e4 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/functions/magic_call53.test +++ b/vendor/twig/twig/tests/Fixtures/functions/magic_call53.test @@ -6,7 +6,7 @@ version_compare(phpversion(), '5.3.0', '>=') {{ 'foo'|magic_call_string }} {{ 'foo'|magic_call_array }} --DATA-- -return array() +return [] --EXPECT-- static_magic_foo static_magic_foo diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/functions/max.test b/vendor/twig/twig/tests/Fixtures/functions/max.test similarity index 92% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/functions/max.test rename to vendor/twig/twig/tests/Fixtures/functions/max.test index e6c94af635b45d42874ef602b2e7f83ea59317dd..6d2de000d5e323dabd52390b41ac1f7cec498b76 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/functions/max.test +++ b/vendor/twig/twig/tests/Fixtures/functions/max.test @@ -5,7 +5,7 @@ {{ max(2, 1, 3, 5, 4) }} {{ max({2:"two", 1:"one", 3:"three", 5:"five", 4:"for"}) }} --DATA-- -return array() +return [] --EXPECT-- 5 5 diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/functions/min.test b/vendor/twig/twig/tests/Fixtures/functions/min.test similarity index 92% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/functions/min.test rename to vendor/twig/twig/tests/Fixtures/functions/min.test index 660471c0007ac65d627ae393095ea5830b73e000..1fe5446b7ca6c1531fb1dbd395d5e43efe90b2df 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/functions/min.test +++ b/vendor/twig/twig/tests/Fixtures/functions/min.test @@ -5,7 +5,7 @@ {{ min([2, 1, 3, 5, 4]) }} {{ min({2:"two", 1:"one", 3:"three", 5:"five", 4:"for"}) }} --DATA-- -return array() +return [] --EXPECT-- 1 1 diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/functions/range.test b/vendor/twig/twig/tests/Fixtures/functions/range.test similarity index 88% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/functions/range.test rename to vendor/twig/twig/tests/Fixtures/functions/range.test index e0377c8d41d3b22e477b4f8eaded310b185e3d89..2927333b97fca0b3818bc3d3783f5d533ec7df43 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/functions/range.test +++ b/vendor/twig/twig/tests/Fixtures/functions/range.test @@ -3,6 +3,6 @@ --TEMPLATE-- {{ range(low=0+1, high=10+0, step=2)|join(',') }} --DATA-- -return array() +return [] --EXPECT-- 1,3,5,7,9 diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/functions/recursive_block_with_inheritance.test b/vendor/twig/twig/tests/Fixtures/functions/recursive_block_with_inheritance.test similarity index 92% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/functions/recursive_block_with_inheritance.test rename to vendor/twig/twig/tests/Fixtures/functions/recursive_block_with_inheritance.test index bf0556d245dc2f34279d0383cdb64919e683dd80..1c3fffb5dabb72d36f8ae629b95cef75b89dcbc3 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/functions/recursive_block_with_inheritance.test +++ b/vendor/twig/twig/tests/Fixtures/functions/recursive_block_with_inheritance.test @@ -16,6 +16,6 @@ --TEMPLATE(base.twig)-- {{ block('list') }} --DATA-- -return array('item' => array('1', '2', array('3.1', array('3.2.1', '3.2.2'), '3.4'))) +return ['item' => ['1', '2', ['3.1', ['3.2.1', '3.2.2'], '3.4']]] --EXPECT-- <ol class="b"><li>"1"</li><li>"2"</li><li><ol class="b"><li>"3.1"</li><li><ol class="b"><li>"3.2.1"</li><li>"3.2.2"</li></ol></li><li>"3.4"</li></ol></li></ol> diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/functions/source.test b/vendor/twig/twig/tests/Fixtures/functions/source.test similarity index 91% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/functions/source.test rename to vendor/twig/twig/tests/Fixtures/functions/source.test index 0e094c3b2e178cf72928cca62183737f8c783b0f..b691ce7bcd9ee45fd067fdb934b0ede31e41df10 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/functions/source.test +++ b/vendor/twig/twig/tests/Fixtures/functions/source.test @@ -8,7 +8,7 @@ BAR --TEMPLATE(foo.twig)-- {{ foo }}<br /> --DATA-- -return array() +return [] --EXPECT-- FOO diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/functions/special_chars.test b/vendor/twig/twig/tests/Fixtures/functions/special_chars.test similarity index 85% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/functions/special_chars.test rename to vendor/twig/twig/tests/Fixtures/functions/special_chars.test index 30c3df516801284c95578447b93bb2b8413b72cd..9c9e249455ea8126dd1ad1142ce6cc8386e2ff44 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/functions/special_chars.test +++ b/vendor/twig/twig/tests/Fixtures/functions/special_chars.test @@ -3,6 +3,6 @@ --TEMPLATE-- {{ §('foo') }} --DATA-- -return array() +return [] --EXPECT-- §foo§ diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/functions/static_calls.test b/vendor/twig/twig/tests/Fixtures/functions/static_calls.test similarity index 83% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/functions/static_calls.test rename to vendor/twig/twig/tests/Fixtures/functions/static_calls.test index 57e5be392d63809d99c750c8297a6fe462941f82..dd13abb0bc56901af37fefa3148143d4d57e5454 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/functions/static_calls.test +++ b/vendor/twig/twig/tests/Fixtures/functions/static_calls.test @@ -4,7 +4,7 @@ Functions as static method calls {{ static_call_string('foo') }} {{ static_call_array('foo') }} --DATA-- -return array('foo' => 'foo') +return ['foo' => 'foo'] --EXPECT-- *foo* *foo* diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/functions/template_from_string.test b/vendor/twig/twig/tests/Fixtures/functions/template_from_string.test similarity index 85% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/functions/template_from_string.test rename to vendor/twig/twig/tests/Fixtures/functions/template_from_string.test index 3d3b9587453cb6f59fda50e733bc68ea723633a3..33b0e40d7c31a98d96effd8a7ee4c69f7ea8b13e 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/functions/template_from_string.test +++ b/vendor/twig/twig/tests/Fixtures/functions/template_from_string.test @@ -8,7 +8,7 @@ --TEMPLATE(parent.twig)-- {% block content %}{% endblock %} --DATA-- -return array('name' => 'Fabien', 'template' => "Hello {{ name }}") +return ['name' => 'Fabien', 'template' => "Hello {{ name }}"] --EXPECT-- Hello Fabien Hello Fabien diff --git a/vendor/twig/twig/tests/Fixtures/functions/template_from_string_error.test b/vendor/twig/twig/tests/Fixtures/functions/template_from_string_error.test new file mode 100644 index 0000000000000000000000000000000000000000..900d238bd2bc8f8a584a3ea9e297c0fe6d8d3ad5 --- /dev/null +++ b/vendor/twig/twig/tests/Fixtures/functions/template_from_string_error.test @@ -0,0 +1,8 @@ +--TEST-- +"template_from_string" function +--TEMPLATE-- +{% include template_from_string("{{ not a Twig template ", "foo.twig") %} +--DATA-- +return [] +--EXCEPTION-- +Twig\Error\SyntaxError: Unclosed "variable" in "foo.twig (string template 4900163d56b1af4b704c6b0afee7f98ba53418ce7a93d37a3af1882735baf9cd)" at line 1. diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/macros/default_values.test b/vendor/twig/twig/tests/Fixtures/macros/default_values.test similarity index 92% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/macros/default_values.test rename to vendor/twig/twig/tests/Fixtures/macros/default_values.test index 4ccff7b6701738959855a9d9a97f75abdcf7e0eb..18bba524ad94134dc644155c4d1d0a96851c5061 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/macros/default_values.test +++ b/vendor/twig/twig/tests/Fixtures/macros/default_values.test @@ -10,7 +10,7 @@ macro {{ test('foo') }} {{ test('bar', 'foo') }} --DATA-- -return array(); +return [] --EXPECT-- foobar barfoo diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/macros/nested_calls.test b/vendor/twig/twig/tests/Fixtures/macros/nested_calls.test similarity index 93% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/macros/nested_calls.test rename to vendor/twig/twig/tests/Fixtures/macros/nested_calls.test index cd25428108c4b467f769721dce41af82385c60b1..4577286d0cbfb87c8a7538904d8af1769c3b36a8 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/macros/nested_calls.test +++ b/vendor/twig/twig/tests/Fixtures/macros/nested_calls.test @@ -13,6 +13,6 @@ macro {{ macros.foo(macros.bar()) }} --DATA-- -return array(); +return [] --EXPECT-- <br /> diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/macros/reserved_variables.test b/vendor/twig/twig/tests/Fixtures/macros/reserved_variables.test similarity index 83% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/macros/reserved_variables.test rename to vendor/twig/twig/tests/Fixtures/macros/reserved_variables.test index cbfb921b2cba2a24653f6edd3c3a02ed0218e830..05dd9213008a5fa0772dd2f14134e7e115a22ece 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/macros/reserved_variables.test +++ b/vendor/twig/twig/tests/Fixtures/macros/reserved_variables.test @@ -9,6 +9,6 @@ macro {{ test(this) }} --DATA-- -return array('this' => 'foo'); +return ['this' => 'foo'] --EXPECT-- foo diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/macros/simple.test b/vendor/twig/twig/tests/Fixtures/macros/simple.test similarity index 95% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/macros/simple.test rename to vendor/twig/twig/tests/Fixtures/macros/simple.test index 6a366cdf1b39c64fbb34da54d0a00b5aaaa7e49d..8fc6b477fb2d4348ee1bb4bc3f3bd37a5de1adca 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/macros/simple.test +++ b/vendor/twig/twig/tests/Fixtures/macros/simple.test @@ -14,7 +14,7 @@ macro {{ test.test(1, "c") }} {{ test(1, "c") }} --DATA-- -return array(); +return [] --EXPECT-- a<br />b<br /> a<br />b<br /> diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/macros/varargs.test b/vendor/twig/twig/tests/Fixtures/macros/varargs.test similarity index 95% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/macros/varargs.test rename to vendor/twig/twig/tests/Fixtures/macros/varargs.test index 412c90fae4e2ad8413bbedee5fbc822ecfad41e3..dd4b5c9f4710f2d172322168707979693bac039f 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/macros/varargs.test +++ b/vendor/twig/twig/tests/Fixtures/macros/varargs.test @@ -14,7 +14,7 @@ macro with arbitrary arguments {{ test1("foo", "bar", "foobar") }} {{ test2("foo", "bar", "foobar") }} --DATA-- -return array(); +return [] --EXPECT-- foo: bar, foobar diff --git a/vendor/twig/twig/tests/Fixtures/macros/varargs_argument.test b/vendor/twig/twig/tests/Fixtures/macros/varargs_argument.test new file mode 100644 index 0000000000000000000000000000000000000000..1ad368bf1e1b30d329656292140be931a75fac41 --- /dev/null +++ b/vendor/twig/twig/tests/Fixtures/macros/varargs_argument.test @@ -0,0 +1,7 @@ +--TEST-- +macro with varargs argument +--TEMPLATE-- +{% macro test(varargs) %} +{% endmacro %} +--EXCEPTION-- +Twig\Error\SyntaxError: The argument "varargs" in macro "test" cannot be defined because the variable "varargs" is reserved for arbitrary arguments in "index.twig" at line 2. diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/macros/with_filters.test b/vendor/twig/twig/tests/Fixtures/macros/with_filters.test similarity index 92% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/macros/with_filters.test rename to vendor/twig/twig/tests/Fixtures/macros/with_filters.test index 685626f2aca45cd6343a585ded458150035cad8e..96064ba0123b9c40f9a51e8819d31f503a8f82b4 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/macros/with_filters.test +++ b/vendor/twig/twig/tests/Fixtures/macros/with_filters.test @@ -9,6 +9,6 @@ macro with a filter {{ test.test() }} --DATA-- -return array(); +return [] --EXPECT-- foo<br /> diff --git a/vendor/twig/twig/tests/Fixtures/regression/block_names_unicity.test b/vendor/twig/twig/tests/Fixtures/regression/block_names_unicity.test new file mode 100644 index 0000000000000000000000000000000000000000..df0747072430fd6b44ddc97defe77da41b9fdc2c --- /dev/null +++ b/vendor/twig/twig/tests/Fixtures/regression/block_names_unicity.test @@ -0,0 +1,19 @@ +--TEST-- +Block names are unique per template +--TEMPLATE-- +{% extends 'layout' %} +{% block content -%} + {% filter title -%} + second + {% endfilter %} +{% endblock %} +--TEMPLATE(layout)-- +{% filter title -%} + first +{% endfilter %} +{% block content %}{% endblock %} +--DATA-- +return [] +--EXPECT-- +First +Second diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/regression/combined_debug_info.test b/vendor/twig/twig/tests/Fixtures/regression/combined_debug_info.test similarity index 57% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/regression/combined_debug_info.test rename to vendor/twig/twig/tests/Fixtures/regression/combined_debug_info.test index ff977ad62718008246dd582c372de876e32e96a8..6426d2c1d858d94b68092e529dd567dd3720c730 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/regression/combined_debug_info.test +++ b/vendor/twig/twig/tests/Fixtures/regression/combined_debug_info.test @@ -10,6 +10,6 @@ index foo {{ foo.bar }} --DATA-- -return array('foo' => 'foo'); +return ['foo' => 'foo'] --EXCEPTION-- -Twig_Error_Runtime: Impossible to access an attribute ("bar") on a string variable ("foo") in "foo" at line 3. +Twig\Error\RuntimeError: Impossible to access an attribute ("bar") on a string variable ("foo") in "foo" at line 3. diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/regression/empty_token.test b/vendor/twig/twig/tests/Fixtures/regression/empty_token.test similarity index 77% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/regression/empty_token.test rename to vendor/twig/twig/tests/Fixtures/regression/empty_token.test index 65f6cd2b8618fb7a9ccb0723f509489598f0bd8c..25bdc9e407c86c929ae79865d0036cf0e164c75e 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/regression/empty_token.test +++ b/vendor/twig/twig/tests/Fixtures/regression/empty_token.test @@ -3,6 +3,6 @@ Twig outputs 0 nodes correctly --TEMPLATE-- {{ foo }}0{{ foo }} --DATA-- -return array('foo' => 'foo') +return ['foo' => 'foo'] --EXPECT-- foo0foo diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/regression/issue_1143.test b/vendor/twig/twig/tests/Fixtures/regression/issue_1143.test similarity index 70% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/regression/issue_1143.test rename to vendor/twig/twig/tests/Fixtures/regression/issue_1143.test index ff7c8bb70454113bf8a316813ba8aa5c05c10d59..e2ab950e18353e45d656ff5dc7bdb3e80bf3c424 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/regression/issue_1143.test +++ b/vendor/twig/twig/tests/Fixtures/regression/issue_1143.test @@ -8,7 +8,7 @@ class House const REGION_S = 1; const REGION_P = 2; - public static $regionChoices = array(self::REGION_S => 'house.region.s', self::REGION_P => 'house.region.p'); + public static $regionChoices = [self::REGION_S => 'house.region.s', self::REGION_P => 'house.region.p']; public function getRegionChoices() { @@ -18,6 +18,6 @@ class House $object = new House(); $object->region = 1; -return array('object' => $object) +return ['object' => $object] --EXPECT-- house.region.s diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/regression/multi_word_tests.test b/vendor/twig/twig/tests/Fixtures/regression/multi_word_tests.test similarity index 92% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/regression/multi_word_tests.test rename to vendor/twig/twig/tests/Fixtures/regression/multi_word_tests.test index 269a30571d6acee82d1759ea62e205bbf6ce7fa5..96ca5517a144ff79a17e2b3400a67fc4f03a24a9 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/regression/multi_word_tests.test +++ b/vendor/twig/twig/tests/Fixtures/regression/multi_word_tests.test @@ -4,7 +4,7 @@ Twig allows multi-word tests without a custom node class {{ 'foo' is multi word ? 'yes' : 'no' }} {{ 'foo bar' is multi word ? 'yes' : 'no' }} --DATA-- -return array() +return [] --EXPECT-- no yes diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/regression/simple_xml_element.test b/vendor/twig/twig/tests/Fixtures/regression/simple_xml_element.test similarity index 72% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/regression/simple_xml_element.test rename to vendor/twig/twig/tests/Fixtures/regression/simple_xml_element.test index 60c3c51d71188a56acce4626a1bf34b3c77bd6fb..b6e62c8d7e15e67724ebcc28b3850119d6ca99a3 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/regression/simple_xml_element.test +++ b/vendor/twig/twig/tests/Fixtures/regression/simple_xml_element.test @@ -10,7 +10,7 @@ Hello '{{ images.image.0.group }}'! - {{ image.group }} {% endfor %} --DATA-- -return array('images' => new SimpleXMLElement('<images><image><group myattr="example">foo</group></image><image><group>bar</group></image></images>')) +return ['images' => new \SimpleXMLElement('<images><image><group myattr="example">foo</group></image><image><group>bar</group></image></images>')] --EXPECT-- Hello 'foo'! example diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/regression/strings_like_numbers.test b/vendor/twig/twig/tests/Fixtures/regression/strings_like_numbers.test similarity index 72% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/regression/strings_like_numbers.test rename to vendor/twig/twig/tests/Fixtures/regression/strings_like_numbers.test index e18e110792db3460edeb941a13c62580d318d800..62fe884858740eba24d41661de3486f14538a23a 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/regression/strings_like_numbers.test +++ b/vendor/twig/twig/tests/Fixtures/regression/strings_like_numbers.test @@ -3,6 +3,6 @@ Twig does not confuse strings with integers in getAttribute() --TEMPLATE-- {{ hash['2e2'] }} --DATA-- -return array('hash' => array('2e2' => 'works')) +return ['hash' => ['2e2' => 'works']] --EXPECT-- works diff --git a/vendor/twig/twig/tests/Fixtures/tags/apply/basic.test b/vendor/twig/twig/tests/Fixtures/tags/apply/basic.test new file mode 100644 index 0000000000000000000000000000000000000000..4848ee0259795af952e1a8ca76e78678e0fd80eb --- /dev/null +++ b/vendor/twig/twig/tests/Fixtures/tags/apply/basic.test @@ -0,0 +1,10 @@ +--TEST-- +"apply" tag applies a filter on its children +--TEMPLATE-- +{% apply upper %} +Some text with a {{ var }} +{% endapply %} +--DATA-- +return ['var' => 'var'] +--EXPECT-- +SOME TEXT WITH A VAR diff --git a/vendor/twig/twig/tests/Fixtures/tags/apply/json_encode.test b/vendor/twig/twig/tests/Fixtures/tags/apply/json_encode.test new file mode 100644 index 0000000000000000000000000000000000000000..8a590b44ac49ba85930c35e09f73999a010bbd11 --- /dev/null +++ b/vendor/twig/twig/tests/Fixtures/tags/apply/json_encode.test @@ -0,0 +1,8 @@ +--TEST-- +"apply" tag applies a filter on its children +--TEMPLATE-- +{% apply json_encode|raw %}test{% endapply %} +--DATA-- +return [] +--EXPECT-- +"test" diff --git a/vendor/twig/twig/tests/Fixtures/tags/apply/multiple.test b/vendor/twig/twig/tests/Fixtures/tags/apply/multiple.test new file mode 100644 index 0000000000000000000000000000000000000000..e16998a52607fd9f97ef7f169850e27feb5227a0 --- /dev/null +++ b/vendor/twig/twig/tests/Fixtures/tags/apply/multiple.test @@ -0,0 +1,10 @@ +--TEST-- +"apply" tags accept multiple chained filters +--TEMPLATE-- +{% apply lower|title %} + {{ var }} +{% endapply %} +--DATA-- +return ['var' => 'VAR'] +--EXPECT-- + Var diff --git a/vendor/twig/twig/tests/Fixtures/tags/apply/nested.test b/vendor/twig/twig/tests/Fixtures/tags/apply/nested.test new file mode 100644 index 0000000000000000000000000000000000000000..b64a6914c535f181f521956e90a769f9300b20d3 --- /dev/null +++ b/vendor/twig/twig/tests/Fixtures/tags/apply/nested.test @@ -0,0 +1,16 @@ +--TEST-- +"apply" tags can be nested at will +--TEMPLATE-- +{% apply lower|title %} + {{ var }} + {% apply upper %} + {{ var }} + {% endapply %} + {{ var }} +{% endapply %} +--DATA-- +return ['var' => 'var'] +--EXPECT-- + Var + Var + Var diff --git a/vendor/twig/twig/tests/Fixtures/tags/apply/scope.test b/vendor/twig/twig/tests/Fixtures/tags/apply/scope.test new file mode 100644 index 0000000000000000000000000000000000000000..a87ff9116ba93994179b1617cf331c780f8c909c --- /dev/null +++ b/vendor/twig/twig/tests/Fixtures/tags/apply/scope.test @@ -0,0 +1,15 @@ +--TEST-- +"apply" tag does not create a new scope +--TEMPLATE-- +{% set foo = 'baz' %} +{% apply spaceless %} + {% set foo = 'foo' %} + {% set bar = 'bar' %} +{% endapply %} +{{ 'foo' == foo ? 'OK ' ~ foo : 'KO' }} +{{ 'bar' == bar ? 'OK ' ~ bar : 'KO' }} +--DATA-- +return [] +--EXPECT-- +OK foo +OK bar diff --git a/vendor/twig/twig/tests/Fixtures/tags/apply/with_for_tag.test b/vendor/twig/twig/tests/Fixtures/tags/apply/with_for_tag.test new file mode 100644 index 0000000000000000000000000000000000000000..4453880b596763c8d81253273a41eaa1aeee2775 --- /dev/null +++ b/vendor/twig/twig/tests/Fixtures/tags/apply/with_for_tag.test @@ -0,0 +1,13 @@ +--TEST-- +"apply" tag applies the filter on "for" tags +--TEMPLATE-- +{% apply upper %} +{% for item in items %} +{{ item }} +{% endfor %} +{% endapply %} +--DATA-- +return ['items' => ['a', 'b']] +--EXPECT-- +A +B diff --git a/vendor/twig/twig/tests/Fixtures/tags/apply/with_if_tag.test b/vendor/twig/twig/tests/Fixtures/tags/apply/with_if_tag.test new file mode 100644 index 0000000000000000000000000000000000000000..ca7a592cbaa5773b6eca8d3bd125c44aef962155 --- /dev/null +++ b/vendor/twig/twig/tests/Fixtures/tags/apply/with_if_tag.test @@ -0,0 +1,29 @@ +--TEST-- +"apply" tag applies the filter on "if" tags +--TEMPLATE-- +{% apply upper %} +{% if items %} +{{ items|join(', ') }} +{% endif %} + +{% if items.3 is defined %} +FOO +{% else %} +{{ items.1 }} +{% endif %} + +{% if items.3 is defined %} +FOO +{% elseif items.1 %} +{{ items.0 }} +{% endif %} + +{% endapply %} +--DATA-- +return ['items' => ['a', 'b']] +--EXPECT-- +A, B + +B + +A diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/autoescape/basic.test b/vendor/twig/twig/tests/Fixtures/tags/autoescape/basic.test similarity index 93% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/tags/autoescape/basic.test rename to vendor/twig/twig/tests/Fixtures/tags/autoescape/basic.test index 2f6a3e1a06483886143646e6c03967b126cd07a3..5979725e38d6769695462823add2ee9ea74bb2cf 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/autoescape/basic.test +++ b/vendor/twig/twig/tests/Fixtures/tags/autoescape/basic.test @@ -17,7 +17,7 @@ {{ var }}<br /> {% endautoescape %} --DATA-- -return array('var' => '<br />') +return ['var' => '<br />'] --EXPECT-- <br /><br /> <br /><br /> diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/autoescape/blocks.test b/vendor/twig/twig/tests/Fixtures/tags/autoescape/blocks.test similarity index 86% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/tags/autoescape/blocks.test rename to vendor/twig/twig/tests/Fixtures/tags/autoescape/blocks.test index 05ab83ce39e3e1f0234162fcb3848033b048ff9b..292e1b4167cef9a545ba9d894b9a153a548b05df 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/autoescape/blocks.test +++ b/vendor/twig/twig/tests/Fixtures/tags/autoescape/blocks.test @@ -7,6 +7,6 @@ {% endblock %} {% endautoescape %} --DATA-- -return array('var' => '<br />') +return ['var' => '<br />'] --EXPECT-- <br /> diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/autoescape/double_escaping.test b/vendor/twig/twig/tests/Fixtures/tags/autoescape/double_escaping.test similarity index 82% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/tags/autoescape/double_escaping.test rename to vendor/twig/twig/tests/Fixtures/tags/autoescape/double_escaping.test index 9c0972462b3d3241c5a18b6189731620cbe87d4d..1724b48787fcfdc979f3c5968b4154ade8c88611 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/autoescape/double_escaping.test +++ b/vendor/twig/twig/tests/Fixtures/tags/autoescape/double_escaping.test @@ -5,6 +5,6 @@ {{ var|escape }} {% endautoescape %} --DATA-- -return array('var' => '<br />') +return ['var' => '<br />'] --EXPECT-- <br /> diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/autoescape/functions.test b/vendor/twig/twig/tests/Fixtures/tags/autoescape/functions.test similarity index 96% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/tags/autoescape/functions.test rename to vendor/twig/twig/tests/Fixtures/tags/autoescape/functions.test index ce7ea789ebb21c77e6b635a8e2bb72e1e2da6d85..170e7074edece9534552efa295a80b56f6be41d3 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/autoescape/functions.test +++ b/vendor/twig/twig/tests/Fixtures/tags/autoescape/functions.test @@ -44,7 +44,7 @@ safe_br {% endautoescape %} --DATA-- -return array() +return [] --EXPECT-- autoescape false @@ -80,4 +80,4 @@ unsafe_br()|escape autoescape js safe_br -\x3Cbr\x20\x2F\x3E +\u003Cbr\u0020\/\u003E diff --git a/vendor/twig/twig/tests/Fixtures/tags/autoescape/literal.test b/vendor/twig/twig/tests/Fixtures/tags/autoescape/literal.test new file mode 100644 index 0000000000000000000000000000000000000000..3d8d4f8fdd2598ba829beaf7358255a12504208a --- /dev/null +++ b/vendor/twig/twig/tests/Fixtures/tags/autoescape/literal.test @@ -0,0 +1,87 @@ +--TEST-- +"autoescape" tag does not apply escaping on literals +--TEMPLATE-- +{% autoescape 'html' %} + +1. Simple literal +{{ "<br />" }} + +2. Conditional expression with only literals +{{ true ? "<br />" : "<br>" }} + +3. Conditional expression with a variable +{{ true ? "<br />" : someVar }} +{{ false ? "<br />" : someVar }} +{{ true ? someVar : "<br />" }} +{{ false ? someVar : "<br />" }} + +4. Nested conditionals with only literals +{{ true ? (true ? "<br />" : "<br>") : "\n" }} + +5. Nested conditionals with a variable +{{ true ? (true ? "<br />" : someVar) : "\n" }} +{{ true ? (false ? "<br />" : someVar) : "\n" }} +{{ true ? (true ? someVar : "<br />") : "\n" }} +{{ true ? (false ? someVar : "<br />") : "\n" }} +{{ false ? "\n" : (true ? someVar : "<br />") }} +{{ false ? "\n" : (false ? someVar : "<br />") }} + +6. Nested conditionals with a variable marked safe +{{ true ? (true ? "<br />" : someVar|raw) : "\n" }} +{{ true ? (false ? "<br />" : someVar|raw) : "\n" }} +{{ true ? (true ? someVar|raw : "<br />") : "\n" }} +{{ true ? (false ? someVar|raw : "<br />") : "\n" }} +{{ false ? "\n" : (true ? someVar|raw : "<br />") }} +{{ false ? "\n" : (false ? someVar|raw : "<br />") }} + +7. Without then clause +{{ "<br />" ?: someVar }} +{{ someFalseVar ?: "<br />" }} + +8. NullCoalesce +{{ aaaa ?? "<br />" }} +{{ "<br />" ?? someVar }} + +{% endautoescape %} +--DATA-- +return ['someVar' => '<br />', 'someFalseVar' => false] +--EXPECT-- + +1. Simple literal +<br /> + +2. Conditional expression with only literals +<br /> + +3. Conditional expression with a variable +<br /> +<br /> +<br /> +<br /> + +4. Nested conditionals with only literals +<br /> + +5. Nested conditionals with a variable +<br /> +<br /> +<br /> +<br /> +<br /> +<br /> + +6. Nested conditionals with a variable marked safe +<br /> +<br /> +<br /> +<br /> +<br /> +<br /> + +7. Without then clause +<br /> +<br /> + +8. NullCoalesce +<br /> +<br /> diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/autoescape/nested.test b/vendor/twig/twig/tests/Fixtures/tags/autoescape/nested.test similarity index 92% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/tags/autoescape/nested.test rename to vendor/twig/twig/tests/Fixtures/tags/autoescape/nested.test index 798e6feaf0220100272c558ee7f461989f35224f..0d88c7e3a2e4779247e27882e7e8e26b22d3ad4e 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/autoescape/nested.test +++ b/vendor/twig/twig/tests/Fixtures/tags/autoescape/nested.test @@ -15,7 +15,7 @@ {% endautoescape %} {{ var }} --DATA-- -return array('var' => '<br />') +return ['var' => '<br />'] --EXPECT-- <br /> <br /> diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/autoescape/objects.test b/vendor/twig/twig/tests/Fixtures/tags/autoescape/objects.test similarity index 88% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/tags/autoescape/objects.test rename to vendor/twig/twig/tests/Fixtures/tags/autoescape/objects.test index e896aa41cadd2cf6430c86ab6afe9a7a97b7a3ad..9d959b22b4fa5018adcc6eda178812eb90c22b1d 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/autoescape/objects.test +++ b/vendor/twig/twig/tests/Fixtures/tags/autoescape/objects.test @@ -19,7 +19,7 @@ class UserForAutoEscapeTest return 'Fabien<br />'; } } -return array('user' => new UserForAutoEscapeTest()) +return ['user' => new UserForAutoEscapeTest()] --EXPECT-- Fabien<br /> fabien<br /> diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/autoescape/raw.test b/vendor/twig/twig/tests/Fixtures/tags/autoescape/raw.test similarity index 84% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/tags/autoescape/raw.test rename to vendor/twig/twig/tests/Fixtures/tags/autoescape/raw.test index 9f1cedd3abf145ebdd09398aa7f4b7dd8aacb817..187327c8017be5fcaa9cebc00cb447b9e5dff126 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/autoescape/raw.test +++ b/vendor/twig/twig/tests/Fixtures/tags/autoescape/raw.test @@ -5,6 +5,6 @@ {{ var|raw }} {% endautoescape %} --DATA-- -return array('var' => '<br />') +return ['var' => '<br />'] --EXPECT-- <br /> diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/autoescape/strategy.legacy.test b/vendor/twig/twig/tests/Fixtures/tags/autoescape/strategy.legacy.test similarity index 79% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/tags/autoescape/strategy.legacy.test rename to vendor/twig/twig/tests/Fixtures/tags/autoescape/strategy.legacy.test index bbf1356e731cd7bcb86453d14e36a32d88ae95c1..289f2b1743327495d75982b0a084898f507df0f9 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/autoescape/strategy.legacy.test +++ b/vendor/twig/twig/tests/Fixtures/tags/autoescape/strategy.legacy.test @@ -5,7 +5,7 @@ {% autoescape true html %}{{ var }}{% endautoescape %} --DATA-- -return array('var' => '<br />"') +return ['var' => '<br />"'] --EXPECT-- -\x3Cbr\x20\x2F\x3E\x22 +\u003Cbr\u0020\/\u003E\u0022 <br />" diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/autoescape/strategy.test b/vendor/twig/twig/tests/Fixtures/tags/autoescape/strategy.test similarity index 78% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/tags/autoescape/strategy.test rename to vendor/twig/twig/tests/Fixtures/tags/autoescape/strategy.test index e496f60818ec6ef40af21d8a3c86a2d95f3f11d6..9a0137ee27ec67f8fcddafa411780aca1cee10f2 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/autoescape/strategy.test +++ b/vendor/twig/twig/tests/Fixtures/tags/autoescape/strategy.test @@ -5,7 +5,7 @@ {% autoescape 'html' %}{{ var }}{% endautoescape %} --DATA-- -return array('var' => '<br />"') +return ['var' => '<br />"'] --EXPECT-- -\x3Cbr\x20\x2F\x3E\x22 +\u003Cbr\u0020\/\u003E\u0022 <br />" diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/autoescape/type.test b/vendor/twig/twig/tests/Fixtures/tags/autoescape/type.test similarity index 76% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/tags/autoescape/type.test rename to vendor/twig/twig/tests/Fixtures/tags/autoescape/type.test index 4f415201db1e45e066d13de18a740de2936726a1..9ae8d7bf9921e180caf80fc9c3e1874b388c6dab 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/autoescape/type.test +++ b/vendor/twig/twig/tests/Fixtures/tags/autoescape/type.test @@ -39,20 +39,20 @@ escape types {% endautoescape %} --DATA-- -return array('msg' => "<>\n'\"") +return ['msg' => "<>\n'\""] --EXPECT-- 1. autoescape 'html' |escape('js') -<a onclick="alert("\x3C\x3E\x0A\x27\x22")"></a> +<a onclick="alert("\u003C\u003E\n\u0027\u0022")"></a> 2. autoescape 'html' |escape('js') -<a onclick="alert("\x3C\x3E\x0A\x27\x22")"></a> +<a onclick="alert("\u003C\u003E\n\u0027\u0022")"></a> 3. autoescape 'js' |escape('js') -<a onclick="alert("\x3C\x3E\x0A\x27\x22")"></a> +<a onclick="alert("\u003C\u003E\n\u0027\u0022")"></a> 4. no escape @@ -61,9 +61,9 @@ return array('msg' => "<>\n'\"") 5. |escape('js')|escape('html') -<a onclick="alert("\x3C\x3E\x0A\x27\x22")"></a> +<a onclick="alert("\u003C\u003E\n\u0027\u0022")"></a> 6. autoescape 'html' |escape('js')|escape('html') -<a onclick="alert("\x3C\x3E\x0A\x27\x22")"></a> +<a onclick="alert("\u003C\u003E\n\u0027\u0022")"></a> diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/autoescape/with_filters.test b/vendor/twig/twig/tests/Fixtures/tags/autoescape/with_filters.test similarity index 98% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/tags/autoescape/with_filters.test rename to vendor/twig/twig/tests/Fixtures/tags/autoescape/with_filters.test index 7821a9aafd7e06a11dcb84879a01ac16e7ac94fc..f97105bbd1b009a7f2f08d4c6f1d2d9d66df9553 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/autoescape/with_filters.test +++ b/vendor/twig/twig/tests/Fixtures/tags/autoescape/with_filters.test @@ -61,7 +61,7 @@ {% endautoescape %} --DATA-- -return array('var' => "<Fabien>\nTwig") +return ['var' => "<Fabien>\nTwig"] --EXPECT-- (escape_and_nl2br is an escaper filter) diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/autoescape/with_filters_arguments.test b/vendor/twig/twig/tests/Fixtures/tags/autoescape/with_filters_arguments.test similarity index 87% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/tags/autoescape/with_filters_arguments.test rename to vendor/twig/twig/tests/Fixtures/tags/autoescape/with_filters_arguments.test index f58a1e09c69a616de7d3784356c95f0a0ba6301a..50f72d83a1ee7888446673bdb7c722ecb2571dc8 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/autoescape/with_filters_arguments.test +++ b/vendor/twig/twig/tests/Fixtures/tags/autoescape/with_filters_arguments.test @@ -9,7 +9,7 @@ {{ var|nl2br(sep|escape) }} {% endautoescape %} --DATA-- -return array('var' => "<Fabien>\nTwig", 'sep' => '<br />') +return ['var' => "<Fabien>\nTwig", 'sep' => '<br />'] --EXPECT-- <Fabien><br /> Twig diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/autoescape/with_pre_escape_filters.test b/vendor/twig/twig/tests/Fixtures/tags/autoescape/with_pre_escape_filters.test similarity index 97% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/tags/autoescape/with_pre_escape_filters.test rename to vendor/twig/twig/tests/Fixtures/tags/autoescape/with_pre_escape_filters.test index 134c77ea815b4f39c1c9a22b1ffe462e0d89470a..c9c738055dfcef96e635fa6f75b84c97bf7d43ce 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/autoescape/with_pre_escape_filters.test +++ b/vendor/twig/twig/tests/Fixtures/tags/autoescape/with_pre_escape_filters.test @@ -31,7 +31,7 @@ {% endautoescape %} --DATA-- -return array('var' => "<Fabien>\nTwig") +return ['var' => "<Fabien>\nTwig"] --EXPECT-- (nl2br is pre_escaped for "html" and declared safe for "html") diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/autoescape/with_preserves_safety_filters.test b/vendor/twig/twig/tests/Fixtures/tags/autoescape/with_preserves_safety_filters.test similarity index 96% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/tags/autoescape/with_preserves_safety_filters.test rename to vendor/twig/twig/tests/Fixtures/tags/autoescape/with_preserves_safety_filters.test index 32d3943b5733464303ddf11187c4bba4cb70fb0a..c764d434b099903c4347838017a69d15f43c853a 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/autoescape/with_preserves_safety_filters.test +++ b/vendor/twig/twig/tests/Fixtures/tags/autoescape/with_preserves_safety_filters.test @@ -23,7 +23,7 @@ {% endautoescape %} --DATA-- -return array('var' => "<Fabien>\nTwig") +return ['var' => "<Fabien>\nTwig"] --EXPECT-- (preserves_safety is preserving safety for "html") diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/block/basic.test b/vendor/twig/twig/tests/Fixtures/tags/block/basic.test similarity index 86% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/tags/block/basic.test rename to vendor/twig/twig/tests/Fixtures/tags/block/basic.test index 360dcf0302ee2f66929f5237e61bbeafbb8995cb..988b09ce863a8a22883d1bf03222508a1fb78a1b 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/block/basic.test +++ b/vendor/twig/twig/tests/Fixtures/tags/block/basic.test @@ -6,6 +6,6 @@ --TEMPLATE(foo.twig)-- {% block content %}{% endblock %} --DATA-- -return array('foo' => 'bar') +return ['foo' => 'bar'] --EXPECT-- FOObar diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/block/block_unique_name.test b/vendor/twig/twig/tests/Fixtures/tags/block/block_unique_name.test similarity index 54% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/tags/block/block_unique_name.test rename to vendor/twig/twig/tests/Fixtures/tags/block/block_unique_name.test index bc89ec820258ef1821f789cf04035077da58c1e4..3009f8b4201eb5f6f0d859f85bbd92d7e8ed5d4a 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/block/block_unique_name.test +++ b/vendor/twig/twig/tests/Fixtures/tags/block/block_unique_name.test @@ -6,6 +6,6 @@ {% endblock %} {% endblock %} --DATA-- -return array() +return [] --EXCEPTION-- -Twig_Error_Syntax: The block 'content' has already been defined line 2 in "index.twig" at line 3. +Twig\Error\SyntaxError: The block 'content' has already been defined line 2 in "index.twig" at line 3. diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/block/special_chars.test b/vendor/twig/twig/tests/Fixtures/tags/block/special_chars.test similarity index 88% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/tags/block/special_chars.test rename to vendor/twig/twig/tests/Fixtures/tags/block/special_chars.test index be17fedf3721c1f4446aa9077c5f5c7907c47823..e8e240eb77e0d35a4e2055863f9755962b150273 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/block/special_chars.test +++ b/vendor/twig/twig/tests/Fixtures/tags/block/special_chars.test @@ -5,6 +5,6 @@ § {% endblock § %} --DATA-- -return array() +return [] --EXPECT-- § diff --git a/vendor/twig/twig/tests/Fixtures/tags/deprecated/block.legacy.test b/vendor/twig/twig/tests/Fixtures/tags/deprecated/block.legacy.test new file mode 100644 index 0000000000000000000000000000000000000000..53729dd1f70043190c05037a6e4f26be70d288f2 --- /dev/null +++ b/vendor/twig/twig/tests/Fixtures/tags/deprecated/block.legacy.test @@ -0,0 +1,20 @@ +--TEST-- +Deprecating a block with "deprecated" tag +--TEMPLATE-- +{% use 'greeting.twig' %} + +{{ block('welcome') }} + +--TEMPLATE(greeting.twig)-- +{% block welcome %} + {% deprecated 'The "welcome" block is deprecated, use "hello" instead.' %} + {{ block('hello') }} +{% endblock %} + +{% block hello %} +Hello Fabien +{% endblock %} +--DATA-- +return [] +--EXPECT-- + Hello Fabien diff --git a/vendor/twig/twig/tests/Fixtures/tags/deprecated/macro.legacy.test b/vendor/twig/twig/tests/Fixtures/tags/deprecated/macro.legacy.test new file mode 100644 index 0000000000000000000000000000000000000000..5cc48dd873baf587edf45a579d4d43bf44181e60 --- /dev/null +++ b/vendor/twig/twig/tests/Fixtures/tags/deprecated/macro.legacy.test @@ -0,0 +1,21 @@ +--TEST-- +Deprecating a macro with "deprecated" tag +--TEMPLATE-- +{% import 'greeting.twig' as greeting %} + +{{ greeting.welcome('Fabien') }} + +--TEMPLATE(greeting.twig)-- +{% macro welcome(name) %} + {% deprecated 'The "welcome" macro is deprecated, use "hello" instead.' %} + {% import _self as self %} + {{ self.hello(name) }} +{% endmacro %} + +{% macro hello(name) %} +Hello {{ name }} +{% endmacro %} +--DATA-- +return [] +--EXPECT-- + Hello Fabien diff --git a/vendor/twig/twig/tests/Fixtures/tags/deprecated/template.legacy.test b/vendor/twig/twig/tests/Fixtures/tags/deprecated/template.legacy.test new file mode 100644 index 0000000000000000000000000000000000000000..7f786d57fc3555b7bbe8834d413e8d3a9a52ebda --- /dev/null +++ b/vendor/twig/twig/tests/Fixtures/tags/deprecated/template.legacy.test @@ -0,0 +1,12 @@ +--TEST-- +Deprecating a template with "deprecated" tag +--TEMPLATE-- +{% extends 'greeting.twig' %} + +{% deprecated 'The "index.twig" template is deprecated, use "greeting.twig" instead.' %} +--TEMPLATE(greeting.twig)-- +Hello Fabien +--DATA-- +return [] +--EXPECT-- +Hello Fabien diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/embed/basic.test b/vendor/twig/twig/tests/Fixtures/tags/embed/basic.test similarity index 96% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/tags/embed/basic.test rename to vendor/twig/twig/tests/Fixtures/tags/embed/basic.test index f44296ea01740d4f86a41f2b95aea4034f275ef4..16781e4186abdf2554d885b620d2326fb26ee290 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/embed/basic.test +++ b/vendor/twig/twig/tests/Fixtures/tags/embed/basic.test @@ -21,7 +21,7 @@ B {% endblock %} C --DATA-- -return array() +return [] --EXPECT-- FOO diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/embed/complex_dynamic_parent.test b/vendor/twig/twig/tests/Fixtures/tags/embed/complex_dynamic_parent.test similarity index 92% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/tags/embed/complex_dynamic_parent.test rename to vendor/twig/twig/tests/Fixtures/tags/embed/complex_dynamic_parent.test index de5ea7eea3d8c5530f32ed091382b1eab9e73a62..b799a8c95f8cc2ec4898b51f1acf8c20e91ee92b 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/embed/complex_dynamic_parent.test +++ b/vendor/twig/twig/tests/Fixtures/tags/embed/complex_dynamic_parent.test @@ -21,7 +21,7 @@ B {% endblock %} C --DATA-- -return array('foo' => 'foo') +return ['foo' => 'foo'] --EXPECT-- FOO diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/embed/dynamic_parent.test b/vendor/twig/twig/tests/Fixtures/tags/embed/dynamic_parent.test similarity index 91% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/tags/embed/dynamic_parent.test rename to vendor/twig/twig/tests/Fixtures/tags/embed/dynamic_parent.test index 2a125e6b588b06e36b213ee71d40756e4211258d..6f0879e28dce54d1f44db6e235cd5714138b0a16 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/embed/dynamic_parent.test +++ b/vendor/twig/twig/tests/Fixtures/tags/embed/dynamic_parent.test @@ -21,7 +21,7 @@ B {% endblock %} C --DATA-- -return array('foo' => 'foo.twig') +return ['foo' => 'foo.twig'] --EXPECT-- FOO diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/embed/error_line.test b/vendor/twig/twig/tests/Fixtures/tags/embed/error_line.test similarity index 70% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/tags/embed/error_line.test rename to vendor/twig/twig/tests/Fixtures/tags/embed/error_line.test index 431473707b7267d627c71babeb7402e93d2ef19e..b1c6c85e6112d165b81436eb39d9ff2c04854c01 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/embed/error_line.test +++ b/vendor/twig/twig/tests/Fixtures/tags/embed/error_line.test @@ -11,6 +11,6 @@ BAR --TEMPLATE(foo.twig)-- {% block c1 %}{% endblock %} --DATA-- -return array() +return [] --EXCEPTION-- -Twig_Error_Runtime: Variable "nothing" does not exist in "index.twig" at line 5. +Twig\Error\RuntimeError: Variable "nothing" does not exist in "index.twig" at line 5. diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/embed/multiple.test b/vendor/twig/twig/tests/Fixtures/tags/embed/multiple.test similarity index 97% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/tags/embed/multiple.test rename to vendor/twig/twig/tests/Fixtures/tags/embed/multiple.test index da161e6d4387737fa7836d33d32b52f30fff6c03..9f7b52f1d827be751059a540e9db446576505363 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/embed/multiple.test +++ b/vendor/twig/twig/tests/Fixtures/tags/embed/multiple.test @@ -28,7 +28,7 @@ B {% endblock %} C --DATA-- -return array() +return [] --EXPECT-- FOO diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/embed/nested.test b/vendor/twig/twig/tests/Fixtures/tags/embed/nested.test similarity index 97% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/tags/embed/nested.test rename to vendor/twig/twig/tests/Fixtures/tags/embed/nested.test index 81563dcef7a2c9a15fdf1f68f539ccde85eee1b2..9f33723366d939962e855d2b666ff6bf60ced730 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/embed/nested.test +++ b/vendor/twig/twig/tests/Fixtures/tags/embed/nested.test @@ -24,7 +24,7 @@ B {% endblock %} C --DATA-- -return array() +return [] --EXPECT-- A block1 diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/embed/with_extends.test b/vendor/twig/twig/tests/Fixtures/tags/embed/with_extends.test similarity index 98% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/tags/embed/with_extends.test rename to vendor/twig/twig/tests/Fixtures/tags/embed/with_extends.test index 2c1dd584cbb011f72f1dd9a4a32c51b927aed1f0..ce726ac00927ec91b137dc66ed42ef35736732e9 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/embed/with_extends.test +++ b/vendor/twig/twig/tests/Fixtures/tags/embed/with_extends.test @@ -39,7 +39,7 @@ B {% endblock %} C --DATA-- -return array() +return [] --EXPECT-- A blockc1base diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/filter/basic.test b/vendor/twig/twig/tests/Fixtures/tags/filter/basic.test similarity index 85% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/tags/filter/basic.test rename to vendor/twig/twig/tests/Fixtures/tags/filter/basic.test index 82094f2f02c76cfc9927fb7b5c32ff4bb90f11ce..866171ecc5ded2e1b14df5fa9cc1a9f06108f80c 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/filter/basic.test +++ b/vendor/twig/twig/tests/Fixtures/tags/filter/basic.test @@ -5,6 +5,6 @@ Some text with a {{ var }} {% endfilter %} --DATA-- -return array('var' => 'var') +return ['var' => 'var'] --EXPECT-- SOME TEXT WITH A VAR diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/filter/json_encode.test b/vendor/twig/twig/tests/Fixtures/tags/filter/json_encode.test similarity index 90% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/tags/filter/json_encode.test rename to vendor/twig/twig/tests/Fixtures/tags/filter/json_encode.test index 3e7148bf41ba5dc73c2a5af630dff1247714aa49..a2562b995be01b417994f6b5a83d61f5ba2fb4d6 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/filter/json_encode.test +++ b/vendor/twig/twig/tests/Fixtures/tags/filter/json_encode.test @@ -3,6 +3,6 @@ --TEMPLATE-- {% filter json_encode|raw %}test{% endfilter %} --DATA-- -return array() +return [] --EXPECT-- "test" diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/filter/multiple.test b/vendor/twig/twig/tests/Fixtures/tags/filter/multiple.test similarity index 83% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/tags/filter/multiple.test rename to vendor/twig/twig/tests/Fixtures/tags/filter/multiple.test index 75512ef96564f1571e234f706b7e3cf5f72aa105..8eb3cbdd7d28e8f76fbfe99e7ed7eda4976e1c8d 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/filter/multiple.test +++ b/vendor/twig/twig/tests/Fixtures/tags/filter/multiple.test @@ -5,6 +5,6 @@ {{ var }} {% endfilter %} --DATA-- -return array('var' => 'VAR') +return ['var' => 'VAR'] --EXPECT-- Var diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/filter/nested.test b/vendor/twig/twig/tests/Fixtures/tags/filter/nested.test similarity index 88% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/tags/filter/nested.test rename to vendor/twig/twig/tests/Fixtures/tags/filter/nested.test index 7e4e4eb33b2f6017b06d6b3a72713db931142b59..6d18e1af08cbdf35d8cd9b2150a9deea24f504e8 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/filter/nested.test +++ b/vendor/twig/twig/tests/Fixtures/tags/filter/nested.test @@ -9,7 +9,7 @@ {{ var }} {% endfilter %} --DATA-- -return array('var' => 'var') +return ['var' => 'var'] --EXPECT-- Var Var diff --git a/vendor/twig/twig/tests/Fixtures/tags/filter/scope.test b/vendor/twig/twig/tests/Fixtures/tags/filter/scope.test new file mode 100644 index 0000000000000000000000000000000000000000..889a46f6a218515954b6572be8acdfeb941e20fa --- /dev/null +++ b/vendor/twig/twig/tests/Fixtures/tags/filter/scope.test @@ -0,0 +1,11 @@ +--TEST-- +"scope" tag creates a new scope +--TEMPLATE-- +{% filter spaceless %} +{% set item = 'foo' %} +{% endfilter %} +{{ item }} +--DATA-- +return [] +--EXCEPTION-- +Twig\Error\RuntimeError: Variable "item" does not exist in "index.twig" at line 5. diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/filter/with_for_tag.test b/vendor/twig/twig/tests/Fixtures/tags/filter/with_for_tag.test similarity index 81% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/tags/filter/with_for_tag.test rename to vendor/twig/twig/tests/Fixtures/tags/filter/with_for_tag.test index 22745eadf322441a89be879b1472db6af6ff8a79..d2d87cfda38a9d847e882d8ac7335a897fdd1fed 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/filter/with_for_tag.test +++ b/vendor/twig/twig/tests/Fixtures/tags/filter/with_for_tag.test @@ -7,7 +7,7 @@ {% endfor %} {% endfilter %} --DATA-- -return array('items' => array('a', 'b')) +return ['items' => ['a', 'b']] --EXPECT-- A B diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/filter/with_if_tag.test b/vendor/twig/twig/tests/Fixtures/tags/filter/with_if_tag.test similarity index 89% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/tags/filter/with_if_tag.test rename to vendor/twig/twig/tests/Fixtures/tags/filter/with_if_tag.test index afd95b2962198c39cec93ef15a4e57be976283f1..f2e804bfb105bff4875fa50af30fb0362424e897 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/filter/with_if_tag.test +++ b/vendor/twig/twig/tests/Fixtures/tags/filter/with_if_tag.test @@ -20,7 +20,7 @@ FOO {% endfilter %} --DATA-- -return array('items' => array('a', 'b')) +return ['items' => ['a', 'b']] --EXPECT-- A, B diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/for/condition.test b/vendor/twig/twig/tests/Fixtures/tags/for/condition.test similarity index 68% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/tags/for/condition.test rename to vendor/twig/twig/tests/Fixtures/tags/for/condition.test index 380531f7809ee0ab546b609bc26ba140e41eeebc..b1ad22fd53fa11e82b50fca04a53ce013e99c342 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/for/condition.test +++ b/vendor/twig/twig/tests/Fixtures/tags/for/condition.test @@ -5,9 +5,9 @@ {{ loop.index }}.{{ i }}{{ foo.bar }} {% endfor %} --DATA-- -return array('foo' => array('bar' => 'X')) +return ['foo' => ['bar' => 'X']] --CONFIG-- -return array('strict_variables' => false) +return ['strict_variables' => false] --EXPECT-- 1.1X 2.3X diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/for/context.test b/vendor/twig/twig/tests/Fixtures/tags/for/context.test similarity index 85% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/tags/for/context.test rename to vendor/twig/twig/tests/Fixtures/tags/for/context.test index ddc69307b33c8163025eaa3bf45ad1bdd6f6437c..3cdd575c83e68113802756b381fb478e456adcdc 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/for/context.test +++ b/vendor/twig/twig/tests/Fixtures/tags/for/context.test @@ -8,7 +8,7 @@ * {{ item }} {% endfor %} --DATA-- -return array('items' => array('a', 'b')) +return ['items' => ['a', 'b']] --EXPECT-- * a * b diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/for/else.test b/vendor/twig/twig/tests/Fixtures/tags/for/else.test similarity index 64% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/tags/for/else.test rename to vendor/twig/twig/tests/Fixtures/tags/for/else.test index 20ccc880c5ed97188dd51277714e9045206a7439..86ec9c28d3ea952d83306579e24b54c91eb75799 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/for/else.test +++ b/vendor/twig/twig/tests/Fixtures/tags/for/else.test @@ -7,17 +7,17 @@ no item {% endfor %} --DATA-- -return array('items' => array('a', 'b')) +return ['items' => ['a', 'b']] --EXPECT-- * a * b --DATA-- -return array('items' => array()) +return ['items' => []] --EXPECT-- no item --DATA-- -return array() +return [] --CONFIG-- -return array('strict_variables' => false) +return ['strict_variables' => false] --EXPECT-- no item diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/for/inner_variables.test b/vendor/twig/twig/tests/Fixtures/tags/for/inner_variables.test similarity index 92% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/tags/for/inner_variables.test rename to vendor/twig/twig/tests/Fixtures/tags/for/inner_variables.test index 49fb9ca6f6f4b88b02b5bc4b0ed7cd685ef82567..e1ad3c73567c9756719329b441ceaacc32422325 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/for/inner_variables.test +++ b/vendor/twig/twig/tests/Fixtures/tags/for/inner_variables.test @@ -7,7 +7,7 @@ {% endfor %} {% endfor %} --DATA-- -return array('k' => 0) +return ['k' => 0] --EXPECT-- 0 1 1 1 diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/for/keys.test b/vendor/twig/twig/tests/Fixtures/tags/for/keys.test similarity index 77% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/tags/for/keys.test rename to vendor/twig/twig/tests/Fixtures/tags/for/keys.test index 4e22cb473f9ccce9be856b1197ca709440a0365c..92135575f630427fad458861536d0f2dec292ea9 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/for/keys.test +++ b/vendor/twig/twig/tests/Fixtures/tags/for/keys.test @@ -5,7 +5,7 @@ * {{ key }} {% endfor %} --DATA-- -return array('items' => array('a', 'b')) +return ['items' => ['a', 'b']] --EXPECT-- * 0 * 1 diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/for/keys_and_values.test b/vendor/twig/twig/tests/Fixtures/tags/for/keys_and_values.test similarity index 80% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/tags/for/keys_and_values.test rename to vendor/twig/twig/tests/Fixtures/tags/for/keys_and_values.test index 4c211689d7ecf37c8e7ede916df0928928aa356c..ab39ddf210c31e8b4ceb9e9c1c00d8d95e47c7a3 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/for/keys_and_values.test +++ b/vendor/twig/twig/tests/Fixtures/tags/for/keys_and_values.test @@ -5,7 +5,7 @@ * {{ key }}/{{ item }} {% endfor %} --DATA-- -return array('items' => array('a', 'b')) +return ['items' => ['a', 'b']] --EXPECT-- * 0/a * 1/b diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/for/loop_context.test b/vendor/twig/twig/tests/Fixtures/tags/for/loop_context.test similarity index 88% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/tags/for/loop_context.test rename to vendor/twig/twig/tests/Fixtures/tags/for/loop_context.test index 93bc76a1f80596e357d8273eafee792618261642..56a60c2e6eefe1922e1b25940645964d9dd95dbb 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/for/loop_context.test +++ b/vendor/twig/twig/tests/Fixtures/tags/for/loop_context.test @@ -8,7 +8,7 @@ {% endfor %} --DATA-- -return array('items' => array('a', 'b')) +return ['items' => ['a', 'b']] --EXPECT-- * 1/0 * 2/1 diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/for/loop_context_local.test b/vendor/twig/twig/tests/Fixtures/tags/for/loop_context_local.test similarity index 84% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/tags/for/loop_context_local.test rename to vendor/twig/twig/tests/Fixtures/tags/for/loop_context_local.test index 58af2c3269ee66e447e244880c06176302546a36..58e5a9b34511fbaa64f350192a38ab8f07704830 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/for/loop_context_local.test +++ b/vendor/twig/twig/tests/Fixtures/tags/for/loop_context_local.test @@ -5,6 +5,6 @@ {% endfor %} {% if loop is not defined %}WORKS{% endif %} --DATA-- -return array('items' => array()) +return ['items' => []] --EXPECT-- WORKS diff --git a/vendor/twig/twig/tests/Fixtures/tags/for/loop_not_defined.test b/vendor/twig/twig/tests/Fixtures/tags/for/loop_not_defined.test new file mode 100644 index 0000000000000000000000000000000000000000..2d8c0b87389f7f8dc67ab6e6e1e13d77a48a2dee --- /dev/null +++ b/vendor/twig/twig/tests/Fixtures/tags/for/loop_not_defined.test @@ -0,0 +1,10 @@ +--TEST-- +"for" tag +--TEMPLATE-- +{% for i, item in items if i > 0 %} + {{ loop.last }} +{% endfor %} +--DATA-- +return ['items' => ['a', 'b']] +--EXCEPTION-- +Twig\Error\SyntaxError: The "loop.last" variable is not defined when looping with a condition in "index.twig" at line 3. diff --git a/vendor/twig/twig/tests/Fixtures/tags/for/loop_not_defined_cond.test b/vendor/twig/twig/tests/Fixtures/tags/for/loop_not_defined_cond.test new file mode 100644 index 0000000000000000000000000000000000000000..e90e96b4ae2b6502e469b1c6f35561f7c107337f --- /dev/null +++ b/vendor/twig/twig/tests/Fixtures/tags/for/loop_not_defined_cond.test @@ -0,0 +1,9 @@ +--TEST-- +"for" tag +--TEMPLATE-- +{% for i, item in items if loop.last > 0 %} +{% endfor %} +--DATA-- +return ['items' => ['a', 'b']] +--EXCEPTION-- +Twig\Error\SyntaxError: The "loop" variable cannot be used in a looping condition in "index.twig" at line 2. diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/for/nested_else.test b/vendor/twig/twig/tests/Fixtures/tags/for/nested_else.test similarity index 79% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/tags/for/nested_else.test rename to vendor/twig/twig/tests/Fixtures/tags/for/nested_else.test index f8b9f6bc181cbe01ada06ed49db757a9e734be97..df1bb07ac04a81ea22e3b55c493f020f2b3988e8 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/for/nested_else.test +++ b/vendor/twig/twig/tests/Fixtures/tags/for/nested_else.test @@ -11,7 +11,7 @@ no item1 {% endfor %} --DATA-- -return array('items' => array('a', 'b'), 'items1' => array()) +return ['items' => ['a', 'b'], 'items1' => []] --EXPECT-- no a no b diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/for/objects.test b/vendor/twig/twig/tests/Fixtures/tags/for/objects.test similarity index 87% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/tags/for/objects.test rename to vendor/twig/twig/tests/Fixtures/tags/for/objects.test index 5034437921563a5a3cb8acce1d46c73a9f054a59..2ba2d92c2cc2bc8ecc4a8a9adb6d8b309d806f39 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/for/objects.test +++ b/vendor/twig/twig/tests/Fixtures/tags/for/objects.test @@ -18,14 +18,14 @@ --DATA-- class ItemsIterator implements Iterator { - protected $values = array('foo' => 'bar', 'bar' => 'foo'); + protected $values = ['foo' => 'bar', 'bar' => 'foo']; public function current() { return current($this->values); } public function key() { return key($this->values); } public function next() { return next($this->values); } public function rewind() { return reset($this->values); } public function valid() { return false !== current($this->values); } } -return array('items' => new ItemsIterator()) +return ['items' => new ItemsIterator()] --EXPECT-- * bar * 1/0 diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/for/objects_countable.test b/vendor/twig/twig/tests/Fixtures/tags/for/objects_countable.test similarity index 83% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/tags/for/objects_countable.test rename to vendor/twig/twig/tests/Fixtures/tags/for/objects_countable.test index 4a1ff6119088a6f399eb0fb100e48cd2ad2fb3ac..99146bde36fd3845993997a87ce0fc85d07dbcd6 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/for/objects_countable.test +++ b/vendor/twig/twig/tests/Fixtures/tags/for/objects_countable.test @@ -17,9 +17,9 @@ * {{ key }} {% endfor %} --DATA-- -class ItemsIteratorCountable implements Iterator, Countable +class ItemsIteratorCountable implements Iterator, \Countable { - protected $values = array('foo' => 'bar', 'bar' => 'foo'); + protected $values = ['foo' => 'bar', 'bar' => 'foo']; public function current() { return current($this->values); } public function key() { return key($this->values); } public function next() { return next($this->values); } @@ -27,7 +27,7 @@ class ItemsIteratorCountable implements Iterator, Countable public function valid() { return false !== current($this->values); } public function count() { return count($this->values); } } -return array('items' => new ItemsIteratorCountable()) +return ['items' => new ItemsIteratorCountable()] --EXPECT-- * bar * 1/0 diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/for/recursive.test b/vendor/twig/twig/tests/Fixtures/tags/for/recursive.test similarity index 76% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/tags/for/recursive.test rename to vendor/twig/twig/tests/Fixtures/tags/for/recursive.test index 17b2e222390d9906cb93cb558c76e74dda9e2a50..3b677d60ffb9a3be25aa27fcf5d83359b8c05621 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/for/recursive.test +++ b/vendor/twig/twig/tests/Fixtures/tags/for/recursive.test @@ -8,7 +8,7 @@ {% endfor %} {% endfor %} --DATA-- -return array('items' => array('a' => array('a1', 'a2', 'a3'), 'b' => array('b1'))) +return ['items' => ['a' => ['a1', 'a2', 'a3'], 'b' => ['b1']]] --EXPECT-- * a (2): * a1 (3) diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/for/values.test b/vendor/twig/twig/tests/Fixtures/tags/for/values.test similarity index 77% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/tags/for/values.test rename to vendor/twig/twig/tests/Fixtures/tags/for/values.test index 82f2ae8a44d43e33f39796d5a01a3408fbb6d051..384c41b288678702d6dc8688b2de55fe50d0bdf5 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/for/values.test +++ b/vendor/twig/twig/tests/Fixtures/tags/for/values.test @@ -5,7 +5,7 @@ * {{ item }} {% endfor %} --DATA-- -return array('items' => array('a', 'b')) +return ['items' => ['a', 'b']] --EXPECT-- * a * b diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/from.test b/vendor/twig/twig/tests/Fixtures/tags/from.test similarity index 93% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/tags/from.test rename to vendor/twig/twig/tests/Fixtures/tags/from.test index 5f5da0ec158f1369f4987cfc9a4b40f630556de7..1d3c9e2b58ccb8a884256ee3c6cea9133944d705 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/from.test +++ b/vendor/twig/twig/tests/Fixtures/tags/from.test @@ -9,6 +9,6 @@ global variables called foobar {% endmacro %} --DATA-- -return array(); +return [] --EXPECT-- called foobar diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/if/basic.test b/vendor/twig/twig/tests/Fixtures/tags/if/basic.test similarity index 77% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/tags/if/basic.test rename to vendor/twig/twig/tests/Fixtures/tags/if/basic.test index c1c3d27681fc80b0ea4b2eebceba54529a2c6f68..a02165e539e92943f2363462e27802679f6add87 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/if/basic.test +++ b/vendor/twig/twig/tests/Fixtures/tags/if/basic.test @@ -9,14 +9,14 @@ NOTHING {% endif %} --DATA-- -return array('a' => 'a') +return ['a' => 'a'] --EXPECT-- a --DATA-- -return array('b' => 'b') +return ['b' => 'b'] --EXPECT-- b --DATA-- -return array() +return [] --EXPECT-- NOTHING diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/if/expression.test b/vendor/twig/twig/tests/Fixtures/tags/if/expression.test similarity index 74% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/tags/if/expression.test rename to vendor/twig/twig/tests/Fixtures/tags/if/expression.test index edfb73df4fecf7c2c7b025d64ef1bc67e664cd92..eb65083c615e01d80a01056ddf5b988c9911e499 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/if/expression.test +++ b/vendor/twig/twig/tests/Fixtures/tags/if/expression.test @@ -9,14 +9,14 @@ A3 {% endif %} --DATA-- -return array('a' => 1) +return ['a' => 1] --EXPECT-- A1 --DATA-- -return array('a' => 12) +return ['a' => 12] --EXPECT-- A2 --DATA-- -return array('a' => 7) +return ['a' => 7] --EXPECT-- A3 diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/include/basic.test b/vendor/twig/twig/tests/Fixtures/tags/include/basic.test similarity index 90% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/tags/include/basic.test rename to vendor/twig/twig/tests/Fixtures/tags/include/basic.test index 8fe1a6c1355b7daa7e04f417bdd7ccf6ac125c91..9982b039d02ee8bfbfe88050150932ac46408673 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/include/basic.test +++ b/vendor/twig/twig/tests/Fixtures/tags/include/basic.test @@ -8,7 +8,7 @@ BAR --TEMPLATE(foo.twig)-- FOOBAR --DATA-- -return array() +return [] --EXPECT-- FOO diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/include/expression.test b/vendor/twig/twig/tests/Fixtures/tags/include/expression.test similarity index 83% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/tags/include/expression.test rename to vendor/twig/twig/tests/Fixtures/tags/include/expression.test index eaeeb112e95fbb02bb8c42cad4b8a7db46b20ca3..23db181238909af98abaa2138ab73fa01ca8cd90 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/include/expression.test +++ b/vendor/twig/twig/tests/Fixtures/tags/include/expression.test @@ -8,7 +8,7 @@ BAR --TEMPLATE(foo.twig)-- FOOBAR --DATA-- -return array('foo' => 'foo.twig') +return ['foo' => 'foo.twig'] --EXPECT-- FOO diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/include/ignore_missing.test b/vendor/twig/twig/tests/Fixtures/tags/include/ignore_missing.test similarity index 94% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/tags/include/ignore_missing.test rename to vendor/twig/twig/tests/Fixtures/tags/include/ignore_missing.test index 24aed06de2c110ced37d2ec4b4e96cfa8304ee40..6c8bdb1e92b37a6ca6c96be98219caf09ed8d74e 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/include/ignore_missing.test +++ b/vendor/twig/twig/tests/Fixtures/tags/include/ignore_missing.test @@ -6,5 +6,5 @@ {% include "foo.twig" ignore missing with {} %} {% include "foo.twig" ignore missing with {} only %} --DATA-- -return array() +return [] --EXPECT-- diff --git a/vendor/twig/twig/tests/Fixtures/tags/include/ignore_missing_exists.test b/vendor/twig/twig/tests/Fixtures/tags/include/ignore_missing_exists.test new file mode 100644 index 0000000000000000000000000000000000000000..1af012210e4dac336bf13c4709f314e29bdd6f2e --- /dev/null +++ b/vendor/twig/twig/tests/Fixtures/tags/include/ignore_missing_exists.test @@ -0,0 +1,11 @@ +--TEST-- +"include" tag +--TEMPLATE-- +{% include "included.twig" ignore missing %} +NOT DISPLAYED +--TEMPLATE(included.twig)-- +{% include "DOES NOT EXIST" %} +--DATA-- +return [] +--EXCEPTION-- +Twig\Error\LoaderError: Template "DOES NOT EXIST" is not defined in "included.twig" at line 2. diff --git a/vendor/twig/twig/tests/Fixtures/tags/include/include_missing_extends.test b/vendor/twig/twig/tests/Fixtures/tags/include/include_missing_extends.test new file mode 100644 index 0000000000000000000000000000000000000000..d0d1bfe5907a0ef5c7d1f5480e70402085c073de --- /dev/null +++ b/vendor/twig/twig/tests/Fixtures/tags/include/include_missing_extends.test @@ -0,0 +1,13 @@ +--TEST-- +"include" tag +--TEMPLATE-- +{% include ['bad.twig', 'good.twig'] ignore missing %} +NOT DISPLAYED +--TEMPLATE(bad.twig)-- +{% extends 'DOES NOT EXIST' %} +--TEMPLATE(good.twig)-- +NOT DISPLAYED +--DATA-- +return [] +--EXCEPTION-- +Twig\Error\LoaderError: Template "DOES NOT EXIST" is not defined in "bad.twig" at line 2. diff --git a/vendor/twig/twig/tests/Fixtures/tags/include/missing.test b/vendor/twig/twig/tests/Fixtures/tags/include/missing.test new file mode 100644 index 0000000000000000000000000000000000000000..ac72838e8493e65fbddf4658fe19b89bb0278bcd --- /dev/null +++ b/vendor/twig/twig/tests/Fixtures/tags/include/missing.test @@ -0,0 +1,8 @@ +--TEST-- +"include" tag +--TEMPLATE-- +{% include "foo.twig" %} +--DATA-- +return [] +--EXCEPTION-- +Twig\Error\LoaderError: Template "foo.twig" is not defined in "index.twig" at line 2. diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/include/missing_nested.test b/vendor/twig/twig/tests/Fixtures/tags/include/missing_nested.test similarity index 70% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/tags/include/missing_nested.test rename to vendor/twig/twig/tests/Fixtures/tags/include/missing_nested.test index 86c1864446859fb542a7aa660cad72fbc1a37cbd..0ee51b78622a90580798a17ff4c7174c66245776 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/include/missing_nested.test +++ b/vendor/twig/twig/tests/Fixtures/tags/include/missing_nested.test @@ -11,6 +11,6 @@ {% include "foo.twig" %} {% endblock %} --DATA-- -return array(); +return [] --EXCEPTION-- -Twig_Error_Loader: Template "foo.twig" is not defined in "base.twig" at line 3. +Twig\Error\LoaderError: Template "foo.twig" is not defined in "base.twig" at line 3. diff --git a/vendor/twig/twig/tests/Fixtures/tags/include/only.test b/vendor/twig/twig/tests/Fixtures/tags/include/only.test new file mode 100644 index 0000000000000000000000000000000000000000..8da402f7a83e32d07e6c5f5add9c6987bf91bcba --- /dev/null +++ b/vendor/twig/twig/tests/Fixtures/tags/include/only.test @@ -0,0 +1,20 @@ +--TEST-- +"include" tag accept variables and only +--TEMPLATE-- +{% include "foo.twig" %} +{% include "foo.twig" only %} +{% include "foo.twig" with vars1 %} +{% include "foo.twig" with vars1 only %} +{% include "foo.twig" with vars2 %} +{% include "foo.twig" with vars2 only %} +--TEMPLATE(foo.twig)-- +{% for k, v in _context %}{{ k }},{% endfor %} +--DATA-- +return ['vars1' => ['foo1' => 'bar'], 'vars2' => new ArrayObject(['foo2' => 'bar'])] +--EXPECT-- +vars1,vars2,global,_parent, +global,_parent, +vars1,vars2,global,foo1,_parent, +foo1,global,_parent, +vars1,vars2,global,foo2,_parent, +foo2,global,_parent, diff --git a/vendor/twig/twig/tests/Fixtures/tags/include/template_instance.test b/vendor/twig/twig/tests/Fixtures/tags/include/template_instance.test new file mode 100644 index 0000000000000000000000000000000000000000..4fb862a175c195b7d747194cafc75646c18c2636 --- /dev/null +++ b/vendor/twig/twig/tests/Fixtures/tags/include/template_instance.test @@ -0,0 +1,10 @@ +--TEST-- +"include" tag accepts \Twig\TemplateWrapper instance +--TEMPLATE-- +{% include foo %} FOO +--TEMPLATE(foo.twig)-- +BAR +--DATA-- +return ['foo' => $twig->load('foo.twig')] +--EXPECT-- +BAR FOO diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/include/templates_as_array.test b/vendor/twig/twig/tests/Fixtures/tags/include/templates_as_array.test similarity index 91% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/tags/include/templates_as_array.test rename to vendor/twig/twig/tests/Fixtures/tags/include/templates_as_array.test index ab670ee06d049467103d04f9373500fdcadf07a8..38063952d41aa60a74e5318e43bedf1cb0d0b7d2 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/include/templates_as_array.test +++ b/vendor/twig/twig/tests/Fixtures/tags/include/templates_as_array.test @@ -6,7 +6,7 @@ --TEMPLATE(foo.twig)-- foo --DATA-- -return array() +return [] --EXPECT-- foo foo diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/include/with_variables.test b/vendor/twig/twig/tests/Fixtures/tags/include/with_variables.test similarity index 50% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/tags/include/with_variables.test rename to vendor/twig/twig/tests/Fixtures/tags/include/with_variables.test index 41384ac7c4a30d43ef8f80281479f4d1415cbb3e..45a05199ec61c6445b1324ee7d2567c62a15cabe 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/include/with_variables.test +++ b/vendor/twig/twig/tests/Fixtures/tags/include/with_variables.test @@ -2,11 +2,13 @@ "include" tag accept variables --TEMPLATE-- {% include "foo.twig" with {'foo': 'bar'} %} -{% include "foo.twig" with vars %} +{% include "foo.twig" with vars1 %} +{% include "foo.twig" with vars2 %} --TEMPLATE(foo.twig)-- {{ foo }} --DATA-- -return array('vars' => array('foo' => 'bar')) +return ['vars1' => ['foo' => 'bar'], 'vars2' => new ArrayObject(['foo' => 'bar'])] --EXPECT-- bar bar +bar diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/inheritance/basic.test b/vendor/twig/twig/tests/Fixtures/tags/inheritance/basic.test similarity index 92% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/tags/inheritance/basic.test rename to vendor/twig/twig/tests/Fixtures/tags/inheritance/basic.test index 0778a4b49be13516b2e1f0db9e1c16d93d8230cb..703b61be176557b82a769ecc098c2d8e1c1e0eff 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/inheritance/basic.test +++ b/vendor/twig/twig/tests/Fixtures/tags/inheritance/basic.test @@ -9,6 +9,6 @@ FOO --TEMPLATE(foo.twig)-- {% block content %}{% endblock %} --DATA-- -return array() +return [] --EXPECT-- FOO diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/inheritance/block_expr.test b/vendor/twig/twig/tests/Fixtures/tags/inheritance/block_expr.test similarity index 81% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/tags/inheritance/block_expr.test rename to vendor/twig/twig/tests/Fixtures/tags/inheritance/block_expr.test index 9a81499ab3cd56a3071712f3144132fe657b76e5..0b82d4cf2ddb24de10ba92a8162d812fe36001af 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/inheritance/block_expr.test +++ b/vendor/twig/twig/tests/Fixtures/tags/inheritance/block_expr.test @@ -8,7 +8,6 @@ block_expr {{- parent() -}} {% endblock %} --TEMPLATE(base.twig)-- -{% spaceless %} {% block element -%} <div> {%- if item.children is defined %} @@ -18,15 +17,14 @@ block_expr {%- endif -%} </div> {%- endblock %} -{% endspaceless %} --DATA-- -return array( - 'item' => array( - 'children' => array( +return [ + 'item' => [ + 'children' => [ null, null, - ) - ) -) + ] + ] +] --EXPECT-- Element:<div>Element:<div></div>Element:<div></div></div> diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/inheritance/block_expr2.test b/vendor/twig/twig/tests/Fixtures/tags/inheritance/block_expr2.test similarity index 82% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/tags/inheritance/block_expr2.test rename to vendor/twig/twig/tests/Fixtures/tags/inheritance/block_expr2.test index 3e868c0da7d51df9b873d1d11d9a22d88b698e5e..18f6604113e8650b79a26c19a893fed8115b544c 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/inheritance/block_expr2.test +++ b/vendor/twig/twig/tests/Fixtures/tags/inheritance/block_expr2.test @@ -10,7 +10,6 @@ block_expr2 --TEMPLATE(base2.twig)-- {% extends "base.twig" %} --TEMPLATE(base.twig)-- -{% spaceless %} {% block element -%} <div> {%- if item.children is defined %} @@ -20,15 +19,14 @@ block_expr2 {%- endif -%} </div> {%- endblock %} -{% endspaceless %} --DATA-- -return array( - 'item' => array( - 'children' => array( +return [ + 'item' => [ + 'children' => [ null, null, - ) - ) -) + ] + ] +] --EXPECT-- Element:<div>Element:<div></div>Element:<div></div></div> diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/inheritance/conditional.test b/vendor/twig/twig/tests/Fixtures/tags/inheritance/conditional.test similarity index 83% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/tags/inheritance/conditional.test rename to vendor/twig/twig/tests/Fixtures/tags/inheritance/conditional.test index 8576e773a9f9cced374b2e79e15539dae290344e..bd28248d137731dd99d25b0dad05ba6124e535cc 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/inheritance/conditional.test +++ b/vendor/twig/twig/tests/Fixtures/tags/inheritance/conditional.test @@ -9,6 +9,6 @@ --TEMPLATE(bar.twig)-- {% block content %}BAR{% endblock %} --DATA-- -return array('foo' => 'foo.twig', 'standalone' => true) +return ['foo' => 'foo.twig', 'standalone' => true] --EXPECT-- FOOFOO diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/inheritance/dynamic.test b/vendor/twig/twig/tests/Fixtures/tags/inheritance/dynamic.test similarity index 83% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/tags/inheritance/dynamic.test rename to vendor/twig/twig/tests/Fixtures/tags/inheritance/dynamic.test index ee06ddce31184fd2f969b6df7dd64806fc6b766d..e6a0f017280fa58e20d22ba45026e5401f14897d 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/inheritance/dynamic.test +++ b/vendor/twig/twig/tests/Fixtures/tags/inheritance/dynamic.test @@ -9,6 +9,6 @@ FOO --TEMPLATE(foo.twig)-- {% block content %}{% endblock %} --DATA-- -return array('foo' => 'foo.twig') +return ['foo' => 'foo.twig'] --EXPECT-- FOO diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/inheritance/empty.test b/vendor/twig/twig/tests/Fixtures/tags/inheritance/empty.test similarity index 90% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/tags/inheritance/empty.test rename to vendor/twig/twig/tests/Fixtures/tags/inheritance/empty.test index 784f35718c95dd5798948d26ffd203223d5e6287..ca11bf20d1b2109d22c9a779ae7d55890a6c1f7e 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/inheritance/empty.test +++ b/vendor/twig/twig/tests/Fixtures/tags/inheritance/empty.test @@ -5,6 +5,6 @@ --TEMPLATE(foo.twig)-- {% block content %}FOO{% endblock %} --DATA-- -return array() +return [] --EXPECT-- FOO diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/inheritance/extends_as_array.test b/vendor/twig/twig/tests/Fixtures/tags/inheritance/extends_as_array.test similarity index 91% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/tags/inheritance/extends_as_array.test rename to vendor/twig/twig/tests/Fixtures/tags/inheritance/extends_as_array.test index a1cb1ce8a34541bf86e2c7b62f0d798a2224fa78..4d2cb6c65724d30c3d95ddc27388a124329377b3 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/inheritance/extends_as_array.test +++ b/vendor/twig/twig/tests/Fixtures/tags/inheritance/extends_as_array.test @@ -7,6 +7,6 @@ foo {% endblock %} --DATA-- -return array() +return [] --EXPECT-- foo diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/inheritance/extends_as_array_with_empty_name.test b/vendor/twig/twig/tests/Fixtures/tags/inheritance/extends_as_array_with_empty_name.test similarity index 91% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/tags/inheritance/extends_as_array_with_empty_name.test rename to vendor/twig/twig/tests/Fixtures/tags/inheritance/extends_as_array_with_empty_name.test index acc74f6a148dacc741a06ff757ed05508c25b478..5108651103bcb5b4954e538559529e5c1d050b59 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/inheritance/extends_as_array_with_empty_name.test +++ b/vendor/twig/twig/tests/Fixtures/tags/inheritance/extends_as_array_with_empty_name.test @@ -7,6 +7,6 @@ foo {% endblock %} --DATA-- -return array() +return [] --EXPECT-- foo diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/inheritance/extends_as_array_with_null_name.test b/vendor/twig/twig/tests/Fixtures/tags/inheritance/extends_as_array_with_null_name.test similarity index 91% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/tags/inheritance/extends_as_array_with_null_name.test rename to vendor/twig/twig/tests/Fixtures/tags/inheritance/extends_as_array_with_null_name.test index cfa648d419ea8255a28b22da69457cafba4c54c0..c5ee6f193b7d77a47eaa23cbcc378d17cfd6e72a 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/inheritance/extends_as_array_with_null_name.test +++ b/vendor/twig/twig/tests/Fixtures/tags/inheritance/extends_as_array_with_null_name.test @@ -7,6 +7,6 @@ foo {% endblock %} --DATA-- -return array() +return [] --EXPECT-- foo diff --git a/vendor/twig/twig/tests/Fixtures/tags/inheritance/extends_in_block.test b/vendor/twig/twig/tests/Fixtures/tags/inheritance/extends_in_block.test new file mode 100644 index 0000000000000000000000000000000000000000..a372ea1c81ec000b4f79999fcea4449becb00f0f --- /dev/null +++ b/vendor/twig/twig/tests/Fixtures/tags/inheritance/extends_in_block.test @@ -0,0 +1,10 @@ +--TEST-- +"extends" tag in a block +--TEMPLATE-- +{% block foo %} + {% extends "foo.twig" %} +{% endblock %} +--DATA-- +return [] +--EXCEPTION-- +Twig\Error\SyntaxError: Cannot use "extend" in a block in "index.twig" at line 3. diff --git a/vendor/twig/twig/tests/Fixtures/tags/inheritance/extends_in_macro.test b/vendor/twig/twig/tests/Fixtures/tags/inheritance/extends_in_macro.test new file mode 100644 index 0000000000000000000000000000000000000000..dc87b2a8c2dd086cacf5fd31807245c606743804 --- /dev/null +++ b/vendor/twig/twig/tests/Fixtures/tags/inheritance/extends_in_macro.test @@ -0,0 +1,10 @@ +--TEST-- +"extends" tag in a macro +--TEMPLATE-- +{% macro foo() %} + {% extends "foo.twig" %} +{% endmacro %} +--DATA-- +return [] +--EXCEPTION-- +Twig\Error\SyntaxError: Cannot use "extend" in a macro in "index.twig" at line 3. diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/inheritance/multiple.test b/vendor/twig/twig/tests/Fixtures/tags/inheritance/multiple.test similarity index 95% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/tags/inheritance/multiple.test rename to vendor/twig/twig/tests/Fixtures/tags/inheritance/multiple.test index dfc2b6c4943b0f717b480fce87e9a72daaf41fb3..fc25badd34f1d4c35dacd728d2ee8c471b62e9aa 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/inheritance/multiple.test +++ b/vendor/twig/twig/tests/Fixtures/tags/inheritance/multiple.test @@ -7,6 +7,6 @@ --TEMPLATE(base.twig)-- {% block content %}base {% endblock %} --DATA-- -return array() +return [] --EXPECT-- base layout index diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/inheritance/multiple_dynamic.test b/vendor/twig/twig/tests/Fixtures/tags/inheritance/multiple_dynamic.test similarity index 96% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/tags/inheritance/multiple_dynamic.test rename to vendor/twig/twig/tests/Fixtures/tags/inheritance/multiple_dynamic.test index 1d3e639ca0b06cea01dacdfae9e1b4ce1e0affb7..fa887177bd31aca407c2385fdabb74d1d0079479 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/inheritance/multiple_dynamic.test +++ b/vendor/twig/twig/tests/Fixtures/tags/inheritance/multiple_dynamic.test @@ -13,7 +13,7 @@ --TEMPLATE(2_parent.twig)-- {% block content %}2{% endblock %} --DATA-- -return array() +return [] --EXPECT-- 1 parent diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/inheritance/nested_blocks.test b/vendor/twig/twig/tests/Fixtures/tags/inheritance/nested_blocks.test similarity index 96% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/tags/inheritance/nested_blocks.test rename to vendor/twig/twig/tests/Fixtures/tags/inheritance/nested_blocks.test index faca92591391b8b260974ec2f9759f8ff4d8cecc..abea2e9d4730ba1aad960001d8efd72ef361d757 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/inheritance/nested_blocks.test +++ b/vendor/twig/twig/tests/Fixtures/tags/inheritance/nested_blocks.test @@ -17,6 +17,6 @@ {% endblock %} {% endblock %} --DATA-- -return array() +return [] --EXPECT-- SUBSUBCONTENT diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/inheritance/nested_blocks_parent_only.test b/vendor/twig/twig/tests/Fixtures/tags/inheritance/nested_blocks_parent_only.test similarity index 94% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/tags/inheritance/nested_blocks_parent_only.test rename to vendor/twig/twig/tests/Fixtures/tags/inheritance/nested_blocks_parent_only.test index 0ad11d0c025e27af1e18f177be38f18760a4f71e..20b7848f8d329776d1c8d2d40b775852c4ce6aaa 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/inheritance/nested_blocks_parent_only.test +++ b/vendor/twig/twig/tests/Fixtures/tags/inheritance/nested_blocks_parent_only.test @@ -10,6 +10,6 @@ {% endblock %} --TEMPLATE(foo.twig)-- --DATA-- -return array() +return [] --EXPECT-- CONTENTSUBCONTENTENDCONTENT diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/inheritance/nested_inheritance.test b/vendor/twig/twig/tests/Fixtures/tags/inheritance/nested_inheritance.test similarity index 95% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/tags/inheritance/nested_inheritance.test rename to vendor/twig/twig/tests/Fixtures/tags/inheritance/nested_inheritance.test index 71e3cdfd4f90af5f5db089df5034e13159fcb990..0b585b4809cbeba1935d04ea2080edee72aa7774 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/inheritance/nested_inheritance.test +++ b/vendor/twig/twig/tests/Fixtures/tags/inheritance/nested_inheritance.test @@ -11,6 +11,6 @@ --TEMPLATE(base.twig)-- {% block body '' %} --DATA-- -return array() +return [] --EXPECT-- INSIDE diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/inheritance/parent.test b/vendor/twig/twig/tests/Fixtures/tags/inheritance/parent.test similarity index 93% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/tags/inheritance/parent.test rename to vendor/twig/twig/tests/Fixtures/tags/inheritance/parent.test index 4f975db80d4c96383fa3fca132bc84b8bb1363ac..73f4c0ec5eb54b323b3e4cbb81cd964abf541792 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/inheritance/parent.test +++ b/vendor/twig/twig/tests/Fixtures/tags/inheritance/parent.test @@ -7,6 +7,6 @@ --TEMPLATE(foo.twig)-- {% block content %}BAR{% endblock %} --DATA-- -return array() +return [] --EXPECT-- BARFOOBAR diff --git a/vendor/twig/twig/tests/Fixtures/tags/inheritance/parent_as_template_wrapper.test b/vendor/twig/twig/tests/Fixtures/tags/inheritance/parent_as_template_wrapper.test new file mode 100644 index 0000000000000000000000000000000000000000..1aaed556c5761bfe4f6032cb9a717f4d6472fb08 --- /dev/null +++ b/vendor/twig/twig/tests/Fixtures/tags/inheritance/parent_as_template_wrapper.test @@ -0,0 +1,12 @@ +--TEST-- +"extends" tag with a parent as a Twig_TemplateWrapper instance +--TEMPLATE-- +{% extends foo %} + +{% block content %}New{% endblock %} +--TEMPLATE(foo.twig)-- +{% block content %}Default{% endblock %} +--DATA-- +return ['foo' => $twig->load('foo.twig')] +--EXPECT-- +New diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/inheritance/parent_change.test b/vendor/twig/twig/tests/Fixtures/tags/inheritance/parent_change.test similarity index 76% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/tags/inheritance/parent_change.test rename to vendor/twig/twig/tests/Fixtures/tags/inheritance/parent_change.test index a8bc90cefd171fcb08e10bb58e3c676cddab9adb..01bd544f83c21e00b76fe7695ad18b767fe1c8b0 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/inheritance/parent_change.test +++ b/vendor/twig/twig/tests/Fixtures/tags/inheritance/parent_change.test @@ -7,10 +7,10 @@ FOO --TEMPLATE(bar.twig)-- BAR --DATA-- -return array('foo' => true) +return ['foo' => true] --EXPECT-- FOO --DATA-- -return array('foo' => false) +return ['foo' => false] --EXPECT-- BAR diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/inheritance/parent_isolation.test b/vendor/twig/twig/tests/Fixtures/tags/inheritance/parent_isolation.test similarity index 96% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/tags/inheritance/parent_isolation.test rename to vendor/twig/twig/tests/Fixtures/tags/inheritance/parent_isolation.test index 628167135220e187538de97cf354429bba7f1e6d..58a37bd9021a6b4ad58d4155f26b4136d4665ecb 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/inheritance/parent_isolation.test +++ b/vendor/twig/twig/tests/Fixtures/tags/inheritance/parent_isolation.test @@ -13,7 +13,7 @@ {% block footer %}Default Footer{% endblock %} --DATA-- -return array() +return [] --EXPECT-- Included Content Default Footer diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/inheritance/parent_nested.test b/vendor/twig/twig/tests/Fixtures/tags/inheritance/parent_nested.test similarity index 95% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/tags/inheritance/parent_nested.test rename to vendor/twig/twig/tests/Fixtures/tags/inheritance/parent_nested.test index 71e7c2080ab29ea47c3edd2f179a6e1456978f4b..d4347bac4f8b4bd54c154bd2d4b12218652657d4 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/inheritance/parent_nested.test +++ b/vendor/twig/twig/tests/Fixtures/tags/inheritance/parent_nested.test @@ -17,7 +17,7 @@ BAR {% endblock %} --DATA-- -return array() +return [] --EXPECT-- INSIDE OVERRIDDEN diff --git a/vendor/twig/twig/tests/Fixtures/tags/inheritance/parent_without_extends.test b/vendor/twig/twig/tests/Fixtures/tags/inheritance/parent_without_extends.test new file mode 100644 index 0000000000000000000000000000000000000000..6d98891553d07630f4cb015f23c73bb12ae8b954 --- /dev/null +++ b/vendor/twig/twig/tests/Fixtures/tags/inheritance/parent_without_extends.test @@ -0,0 +1,8 @@ +--TEST-- +"parent" tag +--TEMPLATE-- +{% block content %} + {{ parent() }} +{% endblock %} +--EXCEPTION-- +Twig\Error\SyntaxError: Calling "parent" on a template that does not extend nor "use" another template is forbidden in "index.twig" at line 3. diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/inheritance/parent_without_extends_but_traits.test b/vendor/twig/twig/tests/Fixtures/tags/inheritance/parent_without_extends_but_traits.test similarity index 92% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/tags/inheritance/parent_without_extends_but_traits.test rename to vendor/twig/twig/tests/Fixtures/tags/inheritance/parent_without_extends_but_traits.test index 63c730550b8bb5d99be0d51b32b579fe60d9a051..39882b8b39d3714e35d1a87eca28505e97742ffd 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/inheritance/parent_without_extends_but_traits.test +++ b/vendor/twig/twig/tests/Fixtures/tags/inheritance/parent_without_extends_but_traits.test @@ -9,6 +9,6 @@ --TEMPLATE(foo.twig)-- {% block content %}BAR{% endblock %} --DATA-- -return array() +return [] --EXPECT-- BAR diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/inheritance/template_instance.test b/vendor/twig/twig/tests/Fixtures/tags/inheritance/template_instance.test similarity index 80% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/tags/inheritance/template_instance.test rename to vendor/twig/twig/tests/Fixtures/tags/inheritance/template_instance.test index d1876a52df6546918df18ece470fdc4159f448c2..a5a223886dc640742a579ff9326c3c061b6e4b5c 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/inheritance/template_instance.test +++ b/vendor/twig/twig/tests/Fixtures/tags/inheritance/template_instance.test @@ -9,6 +9,6 @@ --TEMPLATE(foo.twig)-- {% block content %}BAR{% endblock %} --DATA-- -return array('foo' => $twig->loadTemplate('foo.twig')) +return ['foo' => $twig->load('foo.twig')] --EXPECT-- BARFOO diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/inheritance/use.test b/vendor/twig/twig/tests/Fixtures/tags/inheritance/use.test similarity index 98% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/tags/inheritance/use.test rename to vendor/twig/twig/tests/Fixtures/tags/inheritance/use.test index 8f9ece7ce91f8170ac96b28a534bb1b342386e46..4df32ee9d3f24b8d0aecc96f843adec898c36d58 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/inheritance/use.test +++ b/vendor/twig/twig/tests/Fixtures/tags/inheritance/use.test @@ -35,7 +35,7 @@ {% block content_use2 'content_use2' %} {% block content_use2_only 'content_use2_only' %} --DATA-- -return array() +return [] --EXPECT-- content_parent content_use1 diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/macro/basic.test b/vendor/twig/twig/tests/Fixtures/tags/macro/basic.test similarity index 96% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/tags/macro/basic.test rename to vendor/twig/twig/tests/Fixtures/tags/macro/basic.test index eef0c10d591a7607b669762ce718d1a5a20f390c..ae090f9a06911e925230150cc5294e874e0f44fe 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/macro/basic.test +++ b/vendor/twig/twig/tests/Fixtures/tags/macro/basic.test @@ -10,7 +10,7 @@ <input type="{{ type|default("text") }}" name="{{ name }}" value="{{ value|e|default('') }}" size="{{ size|default(20) }}"> {% endmacro %} --DATA-- -return array() +return [] --EXPECT-- <input type="text" name="username" value="" size="20"> diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/macro/endmacro_name.test b/vendor/twig/twig/tests/Fixtures/tags/macro/endmacro_name.test similarity index 93% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/tags/macro/endmacro_name.test rename to vendor/twig/twig/tests/Fixtures/tags/macro/endmacro_name.test index ae6203bb64f2c547387a91fc370dedaf59a6c1d3..3f3caf7773b30878d21152a594d0efbb66dc096e 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/macro/endmacro_name.test +++ b/vendor/twig/twig/tests/Fixtures/tags/macro/endmacro_name.test @@ -9,7 +9,7 @@ {% macro foo() %}foo{% endmacro %} {% macro bar() %}bar{% endmacro bar %} --DATA-- -return array() +return [] --EXPECT-- foo bar diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/macro/external.test b/vendor/twig/twig/tests/Fixtures/tags/macro/external.test similarity index 97% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/tags/macro/external.test rename to vendor/twig/twig/tests/Fixtures/tags/macro/external.test index 5cd3dae66e662319e468af65bc7c75da5738392e..b28ca19f029ebe1f945cde0c8584197f0bb886b3 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/macro/external.test +++ b/vendor/twig/twig/tests/Fixtures/tags/macro/external.test @@ -10,7 +10,7 @@ <input type="{{ type|default("text") }}" name="{{ name }}" value="{{ value|e|default('') }}" size="{{ size|default(20) }}"> {% endmacro %} --DATA-- -return array() +return [] --EXPECT-- <input type="text" name="username" value="" size="20"> diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/macro/from.test b/vendor/twig/twig/tests/Fixtures/tags/macro/from.test similarity index 95% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/tags/macro/from.test rename to vendor/twig/twig/tests/Fixtures/tags/macro/from.test index 205f59182aa9590865f00fb3fe577bf531239f2e..8b9aae87890f34e791425ac62b42bfcb743addd8 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/macro/from.test +++ b/vendor/twig/twig/tests/Fixtures/tags/macro/from.test @@ -11,7 +11,7 @@ {% macro foo(name) %}foo{{ name }}{% endmacro %} {% macro bar(name) %}bar{{ name }}{% endmacro %} --DATA-- -return array() +return [] --EXPECT-- foofoo foofoo diff --git a/vendor/twig/twig/tests/Fixtures/tags/macro/from_in_block_is_local.test b/vendor/twig/twig/tests/Fixtures/tags/macro/from_in_block_is_local.test new file mode 100644 index 0000000000000000000000000000000000000000..0c89ce62a8f5cf9fdbb4dd89e58213b2b05a26b5 --- /dev/null +++ b/vendor/twig/twig/tests/Fixtures/tags/macro/from_in_block_is_local.test @@ -0,0 +1,18 @@ +--TEST-- +"macro" tag +--TEMPLATE-- +{% block foo %} + {%- from _self import input as linput %} +{% endblock %} + +{% block bar %} + {{- linput('username') }} +{% endblock %} + +{% macro input(name) -%} + <input name="{{ name }}"> +{% endmacro %} +--DATA-- +return [] +--EXCEPTION-- +Twig\Error\SyntaxError: Unknown "linput" function in "index.twig" at line 7. diff --git a/vendor/twig/twig/tests/Fixtures/tags/macro/from_local_override.test b/vendor/twig/twig/tests/Fixtures/tags/macro/from_local_override.test new file mode 100644 index 0000000000000000000000000000000000000000..27bfbaee1f19c63e8b57e211ed6e6de0b9e84846 --- /dev/null +++ b/vendor/twig/twig/tests/Fixtures/tags/macro/from_local_override.test @@ -0,0 +1,28 @@ +--TEST-- +"macro" tag +--TEMPLATE-- +{%- from _self import input %} + +{% block foo %} + {%- from "macros" import input %} + {{- input('username') }} +{% endblock %} + +{% block bar %} + {{- input('username') }} +{% endblock %} + +{% macro input(name) -%} + <input name="{{ name }}"> +{% endmacro %} +--TEMPLATE(macros)-- +{% macro input(name) %} + <input name="{{ name }}" value="local"> +{% endmacro %} +--DATA-- +return [] +--EXPECT-- +<input name="username" value="local"> + + +<input name="username"> diff --git a/vendor/twig/twig/tests/Fixtures/tags/macro/from_macro_in_a_macro.test b/vendor/twig/twig/tests/Fixtures/tags/macro/from_macro_in_a_macro.test new file mode 100644 index 0000000000000000000000000000000000000000..87ac25c3103003bad44e03236e3ee98e0b30a4c2 --- /dev/null +++ b/vendor/twig/twig/tests/Fixtures/tags/macro/from_macro_in_a_macro.test @@ -0,0 +1,18 @@ +--TEST-- +"from" tag with syntax error +--TEMPLATE-- +{% from _self import another, foo %} + +{{ foo() }} + +{% macro foo() %} + {{ another() }} +{% endmacro %} + +{% macro another() %} + OK +{% endmacro %} +--DATA-- +return [] +--EXCEPTION-- +Twig\Error\SyntaxError: Unknown "another" function in "index.twig" at line 7. diff --git a/vendor/twig/twig/tests/Fixtures/tags/macro/from_nested_blocks.test b/vendor/twig/twig/tests/Fixtures/tags/macro/from_nested_blocks.test new file mode 100644 index 0000000000000000000000000000000000000000..8ede5db5094fac92ecc2f6fcce9e5b7552059b82 --- /dev/null +++ b/vendor/twig/twig/tests/Fixtures/tags/macro/from_nested_blocks.test @@ -0,0 +1,18 @@ +--TEST-- +"macro" tag +--TEMPLATE-- +{% block foo %} + {%- from _self import input as linput %} + + {% block bar %} + {{- linput('username') }} + {% endblock %} +{% endblock %} + +{% macro input(name) -%} + <input name="{{ name }}"> +{% endmacro %} +--DATA-- +return [] +--EXCEPTION-- +Twig\Error\SyntaxError: Unknown "linput" function in "index.twig" at line 6. diff --git a/vendor/twig/twig/tests/Fixtures/tags/macro/from_nested_blocks_with_global_macro.test b/vendor/twig/twig/tests/Fixtures/tags/macro/from_nested_blocks_with_global_macro.test new file mode 100644 index 0000000000000000000000000000000000000000..f737bf0d8b5e06fdffd03c627ae4d44988846862 --- /dev/null +++ b/vendor/twig/twig/tests/Fixtures/tags/macro/from_nested_blocks_with_global_macro.test @@ -0,0 +1,18 @@ +--TEST-- +"macro" tag +--TEMPLATE-- +{%- from _self import input %} + +{% block foo %} + {% block bar %} + {{- input('username') }} + {% endblock %} +{% endblock %} + +{% macro input(name) -%} + <input name="{{ name }}"> +{% endmacro %} +--DATA-- +return [] +--EXCEPTION-- +Twig\Error\SyntaxError: Unknown "input" function in "index.twig" at line 6. diff --git a/vendor/twig/twig/tests/Fixtures/tags/macro/from_syntax_error.test b/vendor/twig/twig/tests/Fixtures/tags/macro/from_syntax_error.test new file mode 100644 index 0000000000000000000000000000000000000000..6223cfe947a8261e6c5decb8b0b1396d3023adf3 --- /dev/null +++ b/vendor/twig/twig/tests/Fixtures/tags/macro/from_syntax_error.test @@ -0,0 +1,8 @@ +--TEST-- +"from" tag with syntax error +--TEMPLATE-- +{% from 'forms.twig' %} +--DATA-- +return [] +--EXCEPTION-- +Twig\Error\SyntaxError: Unexpected token "end of statement block" ("name" expected with value "import") in "index.twig" at line 2. diff --git a/vendor/twig/twig/tests/Fixtures/tags/macro/from_with_reserved_name.test b/vendor/twig/twig/tests/Fixtures/tags/macro/from_with_reserved_name.test new file mode 100644 index 0000000000000000000000000000000000000000..19adb9df4cec1113a211559c4139c550ac40a5aa --- /dev/null +++ b/vendor/twig/twig/tests/Fixtures/tags/macro/from_with_reserved_name.test @@ -0,0 +1,8 @@ +--TEST-- +"from" tag with reserved name +--TEMPLATE-- +{% from 'forms.twig' import templateName %} +--DATA-- +return [] +--EXCEPTION-- +Twig\Error\SyntaxError: "templateName" cannot be an imported macro as it is a reserved keyword in "index.twig" at line 2. diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/macro/global.test b/vendor/twig/twig/tests/Fixtures/tags/macro/global.test similarity index 94% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/tags/macro/global.test rename to vendor/twig/twig/tests/Fixtures/tags/macro/global.test index 6b371768e0ac6e52e57d2e3d4dd66d945cf63d55..832740eac5612f57ea35e9ef0de43c0fb8162014 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/macro/global.test +++ b/vendor/twig/twig/tests/Fixtures/tags/macro/global.test @@ -8,7 +8,7 @@ --TEMPLATE(forms.twig)-- {% macro foo(name) %}{{ name|default('foo') }}{{ global }}{% endmacro %} --DATA-- -return array() +return [] --EXPECT-- fooglobal fooglobal diff --git a/vendor/twig/twig/tests/Fixtures/tags/macro/import_and_blocks.test b/vendor/twig/twig/tests/Fixtures/tags/macro/import_and_blocks.test new file mode 100644 index 0000000000000000000000000000000000000000..721f5506a5ab2a442596e4acabc37e9255bb6529 --- /dev/null +++ b/vendor/twig/twig/tests/Fixtures/tags/macro/import_and_blocks.test @@ -0,0 +1,36 @@ +--TEST-- +"macro" tag +--TEMPLATE-- +{% import _self as macros %} +{% from _self import input %} + +{% block foo %} + {{- macros.input('username') }} + {{- input('username') }} + + {%- import _self as lmacros %} + {%- from _self import input as linput %} + + {{- lmacros.input('username') }} + {{- linput('username') }} +{% endblock %} + +{% block bar %} + {{- macros.input('username') }} + {{- input('username') }} +{% endblock %} + +{% macro input(name) -%} + <input name="{{ name }}"> +{% endmacro %} +--DATA-- +return [] +--EXPECT-- +<input name="username"> +<input name="username"> +<input name="username"> +<input name="username"> + + +<input name="username"> +<input name="username"> diff --git a/vendor/twig/twig/tests/Fixtures/tags/macro/import_from_string_template.test b/vendor/twig/twig/tests/Fixtures/tags/macro/import_from_string_template.test new file mode 100644 index 0000000000000000000000000000000000000000..6c1817be7db40f04059847cc0729aa25cff41c42 --- /dev/null +++ b/vendor/twig/twig/tests/Fixtures/tags/macro/import_from_string_template.test @@ -0,0 +1,10 @@ +--TEST-- +"import" tag with a template as string +--TEMPLATE-- +{% import template_from_string("{% macro test() %}ok{% endmacro %}") as m %} +{{ m.test() }} +--TEMPLATE(forms.twig)-- +--DATA-- +return [] +--EXPECT-- +ok diff --git a/vendor/twig/twig/tests/Fixtures/tags/macro/import_in_block_is_local.test b/vendor/twig/twig/tests/Fixtures/tags/macro/import_in_block_is_local.test new file mode 100644 index 0000000000000000000000000000000000000000..9443e122215446fc1942dbc9677013fe5c2f06fd --- /dev/null +++ b/vendor/twig/twig/tests/Fixtures/tags/macro/import_in_block_is_local.test @@ -0,0 +1,18 @@ +--TEST-- +"macro" tag +--TEMPLATE-- +{% block foo %} + {%- import _self as lmacros %} +{% endblock %} + +{% block bar %} + {{- lmacros.input('username') }} +{% endblock %} + +{% macro input(name) -%} + <input name="{{ name }}"> +{% endmacro %} +--DATA-- +return [] +--EXCEPTION-- +Twig\Error\RuntimeError: Variable "lmacros" does not exist in "index.twig" at line 7. diff --git a/vendor/twig/twig/tests/Fixtures/tags/macro/import_local_override.test b/vendor/twig/twig/tests/Fixtures/tags/macro/import_local_override.test new file mode 100644 index 0000000000000000000000000000000000000000..7cf0552f836ce5a36d2b2612614b8d2ce664457c --- /dev/null +++ b/vendor/twig/twig/tests/Fixtures/tags/macro/import_local_override.test @@ -0,0 +1,28 @@ +--TEST-- +"macro" tag +--TEMPLATE-- +{%- import _self as macros %} + +{% block foo %} + {%- import "macros" as macros %} + {{- macros.input('username') }} +{% endblock %} + +{% block bar %} + {{- macros.input('username') }} +{% endblock %} + +{% macro input(name) -%} + <input name="{{ name }}"> +{% endmacro %} +--TEMPLATE(macros)-- +{% macro input(name) %} + <input name="{{ name }}" value="local"> +{% endmacro %} +--DATA-- +return [] +--EXPECT-- +<input name="username" value="local"> + + +<input name="username"> diff --git a/vendor/twig/twig/tests/Fixtures/tags/macro/import_macro_in_a_macro.test b/vendor/twig/twig/tests/Fixtures/tags/macro/import_macro_in_a_macro.test new file mode 100644 index 0000000000000000000000000000000000000000..d224482e197725c6c7daac9eba4dc79dd4e25014 --- /dev/null +++ b/vendor/twig/twig/tests/Fixtures/tags/macro/import_macro_in_a_macro.test @@ -0,0 +1,18 @@ +--TEST-- +"import" tag with syntax error +--TEMPLATE-- +{% import _self as foo %} + +{{ foo.foo() }} + +{% macro foo() %} + {{ foo.another() }} +{% endmacro %} + +{% macro another() %} + OK +{% endmacro %} +--DATA-- +return [] +--EXCEPTION-- +Twig\Error\RuntimeError: Variable "foo" does not exist in "index.twig" at line 7. diff --git a/vendor/twig/twig/tests/Fixtures/tags/macro/import_nested_blocks.legacy.test b/vendor/twig/twig/tests/Fixtures/tags/macro/import_nested_blocks.legacy.test new file mode 100644 index 0000000000000000000000000000000000000000..e822c7ff48258b49891decf44520f15087ed2b1c --- /dev/null +++ b/vendor/twig/twig/tests/Fixtures/tags/macro/import_nested_blocks.legacy.test @@ -0,0 +1,18 @@ +--TEST-- +"macro" tag +--TEMPLATE-- +{% block foo %} + {%- import _self as lmacros %} + + {% block bar %} + {{- lmacros.input('username') }} + {% endblock %} +{% endblock %} + +{% macro input(name) -%} + <input name="{{ name }}"> +{% endmacro %} +--DATA-- +return [] +--EXPECT-- +<input name="username"> diff --git a/vendor/twig/twig/tests/Fixtures/tags/macro/import_nested_blocks_with_global_macro.legacy.test b/vendor/twig/twig/tests/Fixtures/tags/macro/import_nested_blocks_with_global_macro.legacy.test new file mode 100644 index 0000000000000000000000000000000000000000..697d665f84f523677eedaf550637ac0f8009905c --- /dev/null +++ b/vendor/twig/twig/tests/Fixtures/tags/macro/import_nested_blocks_with_global_macro.legacy.test @@ -0,0 +1,18 @@ +--TEST-- +"macro" tag +--TEMPLATE-- +{%- import _self as macros %} + +{% block foo %} + {% block bar %} + {{- macros.input('username') }} + {% endblock %} +{% endblock %} + +{% macro input(name) -%} + <input name="{{ name }}"> +{% endmacro %} +--DATA-- +return [] +--EXPECT-- +<input name="username"> diff --git a/vendor/twig/twig/tests/Fixtures/tags/macro/import_self_parent.test b/vendor/twig/twig/tests/Fixtures/tags/macro/import_self_parent.test new file mode 100644 index 0000000000000000000000000000000000000000..24a8cdb50b7d22c0e12158a6f2e60ee3d0769802 --- /dev/null +++ b/vendor/twig/twig/tests/Fixtures/tags/macro/import_self_parent.test @@ -0,0 +1,23 @@ +--TEST-- +"macro" tag +--TEMPLATE-- +{% extends "parent" %} +{% import _self as me %} + +{% block test %} + {{ me.hello() }} +{% endblock test %} +--TEMPLATE(parent)-- +{% import _self as me %} + +{% block test %} +Hello +{% endblock test %} + +{% macro hello() %} + Test +{% endmacro %} +--DATA-- +return [] +--EXPECT-- +Test diff --git a/vendor/twig/twig/tests/Fixtures/tags/macro/import_syntax_error.test b/vendor/twig/twig/tests/Fixtures/tags/macro/import_syntax_error.test new file mode 100644 index 0000000000000000000000000000000000000000..b9817f0eed63523308d37f1e8e5a0041aed30a8f --- /dev/null +++ b/vendor/twig/twig/tests/Fixtures/tags/macro/import_syntax_error.test @@ -0,0 +1,10 @@ +--TEST-- +"import" tag with reserved name +--TEMPLATE-- +{% import 'forms.twig' %} + +{{ macros.parent() }} +--DATA-- +return [] +--EXCEPTION-- +Twig\Error\SyntaxError: Unexpected token "end of statement block" ("name" expected with value "as") in "index.twig" at line 2. diff --git a/vendor/twig/twig/tests/Fixtures/tags/macro/import_with_reserved_name.test b/vendor/twig/twig/tests/Fixtures/tags/macro/import_with_reserved_name.test new file mode 100644 index 0000000000000000000000000000000000000000..34b8d43a25ae24fa9deb80e816f085148d025db1 --- /dev/null +++ b/vendor/twig/twig/tests/Fixtures/tags/macro/import_with_reserved_name.test @@ -0,0 +1,10 @@ +--TEST-- +"from" tag with reserved name +--TEMPLATE-- +{% import 'forms.twig' as macros %} + +{{ macros.parent() }} +--DATA-- +return [] +--EXCEPTION-- +Twig\Error\SyntaxError: "parent" cannot be called as macro as it is a reserved keyword in "index.twig" at line 4. diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/macro/reserved_name.test b/vendor/twig/twig/tests/Fixtures/tags/macro/reserved_name.test similarity index 50% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/tags/macro/reserved_name.test rename to vendor/twig/twig/tests/Fixtures/tags/macro/reserved_name.test index f7c102f0292ff97420dc1d0111013c87c331b18b..e58dd7caccbc18162ac9e5ac56e3907d3dd09bcc 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/macro/reserved_name.test +++ b/vendor/twig/twig/tests/Fixtures/tags/macro/reserved_name.test @@ -5,6 +5,6 @@ parent {% endmacro %} --DATA-- -return array() +return [] --EXCEPTION-- -Twig_Error_Syntax: "parent" cannot be used as a macro name as it is a reserved keyword in "index.twig" at line 2. +Twig\Error\SyntaxError: "parent" cannot be used as a macro name as it is a reserved keyword in "index.twig" at line 2. diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/macro/self_import.test b/vendor/twig/twig/tests/Fixtures/tags/macro/self_import.test similarity index 96% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/tags/macro/self_import.test rename to vendor/twig/twig/tests/Fixtures/tags/macro/self_import.test index 17756cb6c6a4449df36b98b3545276a8a985a08c..ca3157dd88451a0a605e7b16a2d45d2a9b90aa11 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/macro/self_import.test +++ b/vendor/twig/twig/tests/Fixtures/tags/macro/self_import.test @@ -10,7 +10,7 @@ <input type="{{ type|default("text") }}" name="{{ name }}" value="{{ value|e|default('') }}" size="{{ size|default(20) }}"> {% endmacro %} --DATA-- -return array() +return [] --EXPECT-- <input type="text" name="username" value="" size="20"> diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/macro/special_chars.test b/vendor/twig/twig/tests/Fixtures/tags/macro/special_chars.test similarity index 92% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/tags/macro/special_chars.test rename to vendor/twig/twig/tests/Fixtures/tags/macro/special_chars.test index 3721770730d00cb5ede96b7849235ed71e291f62..491e91e80d70c1659455a13d72602bfe26c6a647 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/macro/special_chars.test +++ b/vendor/twig/twig/tests/Fixtures/tags/macro/special_chars.test @@ -9,6 +9,6 @@ §{{ foo }}§ {% endmacro %} --DATA-- -return array() +return [] --EXPECT-- §foo§ diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/macro/super_globals.test b/vendor/twig/twig/tests/Fixtures/tags/macro/super_globals.test similarity index 92% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/tags/macro/super_globals.test rename to vendor/twig/twig/tests/Fixtures/tags/macro/super_globals.test index 5679462819dfb1d326142b10cdb88a5465bda74f..643697ce28cabfee458c56229a6b50d69c197361 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/macro/super_globals.test +++ b/vendor/twig/twig/tests/Fixtures/tags/macro/super_globals.test @@ -9,6 +9,6 @@ Super globals as macro arguments {{ GET }} {% endmacro %} --DATA-- -return array() +return [] --EXPECT-- foo diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/raw/basic.legacy.test b/vendor/twig/twig/tests/Fixtures/tags/raw/basic.legacy.test similarity index 86% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/tags/raw/basic.legacy.test rename to vendor/twig/twig/tests/Fixtures/tags/raw/basic.legacy.test index 0445e853057d489e36fdaddbb20c8899549aaf72..7875b2af72331d977a5cd9decb386c8c1686d028 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/raw/basic.legacy.test +++ b/vendor/twig/twig/tests/Fixtures/tags/raw/basic.legacy.test @@ -5,6 +5,6 @@ {{ foo }} {% endraw %} --DATA-- -return array() +return [] --EXPECT-- {{ foo }} diff --git a/vendor/twig/twig/tests/Fixtures/tags/raw/mixed_usage_with_raw.legacy.test b/vendor/twig/twig/tests/Fixtures/tags/raw/mixed_usage_with_raw.legacy.test new file mode 100644 index 0000000000000000000000000000000000000000..d4c8dd2cd1fc07fea17a0446ce6e078d864771d7 --- /dev/null +++ b/vendor/twig/twig/tests/Fixtures/tags/raw/mixed_usage_with_raw.legacy.test @@ -0,0 +1,10 @@ +--TEST-- +"raw" tag +--TEMPLATE-- +{% raw %} +{{ foo }} +{% endverbatim %} +--DATA-- +return [] +--EXCEPTION-- +Twig\Error\SyntaxError: Unexpected end of file: Unclosed "raw" block in "index.twig" at line 2. diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/raw/whitespace_control.legacy.test b/vendor/twig/twig/tests/Fixtures/tags/raw/whitespace_control.legacy.test similarity index 96% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/tags/raw/whitespace_control.legacy.test rename to vendor/twig/twig/tests/Fixtures/tags/raw/whitespace_control.legacy.test index 352bb1876e678a124e4d51a01f775e06a31b184a..11f42025e13d2c08680a017cd6a42a0a1d5815db 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/raw/whitespace_control.legacy.test +++ b/vendor/twig/twig/tests/Fixtures/tags/raw/whitespace_control.legacy.test @@ -37,7 +37,7 @@ 5*** --DATA-- -return array() +return [] --EXPECT-- 1*** {{ 'bla' }} diff --git a/vendor/twig/twig/tests/Fixtures/tags/sandbox/array.test b/vendor/twig/twig/tests/Fixtures/tags/sandbox/array.test new file mode 100644 index 0000000000000000000000000000000000000000..b432427e4a638079edf4d67fb76d570081078d56 --- /dev/null +++ b/vendor/twig/twig/tests/Fixtures/tags/sandbox/array.test @@ -0,0 +1,16 @@ +--TEST-- +sandbox tag +--TEMPLATE-- +{%- sandbox %} + {%- include "foo.twig" %} +{%- endsandbox %} +--TEMPLATE(foo.twig)-- +{{ [a][0] }} +{{ dump([a][0]) }} +--DATA-- +return ['a' => 'b'] +--CONFIG-- +return ['autoescape' => false, 'debug' => true] +--EXPECT-- +b +string(1) "b" diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/sandbox/not_valid1.test b/vendor/twig/twig/tests/Fixtures/tags/sandbox/not_valid1.test similarity index 56% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/tags/sandbox/not_valid1.test rename to vendor/twig/twig/tests/Fixtures/tags/sandbox/not_valid1.test index dfddc1513bb271b81d1bd0aa3591fcd9c3a8fc5d..e26a78bc1576df3d70fc79230ab2a2b52246573d 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/sandbox/not_valid1.test +++ b/vendor/twig/twig/tests/Fixtures/tags/sandbox/not_valid1.test @@ -8,4 +8,4 @@ sandbox tag --TEMPLATE(foo.twig)-- foo --EXCEPTION-- -Twig_Error_Syntax: Only "include" tags are allowed within a "sandbox" section in "index.twig" at line 4. +Twig\Error\SyntaxError: Only "include" tags are allowed within a "sandbox" section in "index.twig" at line 4. diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/sandbox/not_valid2.test b/vendor/twig/twig/tests/Fixtures/tags/sandbox/not_valid2.test similarity index 64% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/tags/sandbox/not_valid2.test rename to vendor/twig/twig/tests/Fixtures/tags/sandbox/not_valid2.test index a33a13ee6e1e2d393cfd24d9ffc040c80437a7e5..bb2a329715aa20d74484396ef9afc9fa9b430279 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/sandbox/not_valid2.test +++ b/vendor/twig/twig/tests/Fixtures/tags/sandbox/not_valid2.test @@ -11,4 +11,4 @@ sandbox tag --TEMPLATE(foo.twig)-- foo --EXCEPTION-- -Twig_Error_Syntax: Only "include" tags are allowed within a "sandbox" section in "index.twig" at line 5. +Twig\Error\SyntaxError: Only "include" tags are allowed within a "sandbox" section in "index.twig" at line 5. diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/sandbox/simple.test b/vendor/twig/twig/tests/Fixtures/tags/sandbox/simple.test similarity index 95% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/tags/sandbox/simple.test rename to vendor/twig/twig/tests/Fixtures/tags/sandbox/simple.test index de20f3dba711923149ba8cc37ab401fc54812cfa..4d232d8bbd2447d00d79dcb7a0edc2c4a144ab1f 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/sandbox/simple.test +++ b/vendor/twig/twig/tests/Fixtures/tags/sandbox/simple.test @@ -14,7 +14,7 @@ sandbox tag --TEMPLATE(foo.twig)-- foo --DATA-- -return array() +return [] --EXPECT-- foo foo diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/set/basic.test b/vendor/twig/twig/tests/Fixtures/tags/set/basic.test similarity index 93% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/tags/set/basic.test rename to vendor/twig/twig/tests/Fixtures/tags/set/basic.test index a5a9f830ec5a3d93d9235b837ababbb96c061b3f..aae1427e8103cd7617a82c53b5d7e74ce29f9d08 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/set/basic.test +++ b/vendor/twig/twig/tests/Fixtures/tags/set/basic.test @@ -11,7 +11,7 @@ {{ foo }}{{ bar }} --DATA-- -return array() +return [] --EXPECT-- foo foo<br /> diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/set/capture-empty.test b/vendor/twig/twig/tests/Fixtures/tags/set/capture-empty.test similarity index 89% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/tags/set/capture-empty.test rename to vendor/twig/twig/tests/Fixtures/tags/set/capture-empty.test index ec657f0058a0bb8c5a86985ce389cd2a83abcee4..97fc43cc2ab57f7a01b0599776d5c06ab9a70c9d 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/set/capture-empty.test +++ b/vendor/twig/twig/tests/Fixtures/tags/set/capture-empty.test @@ -5,5 +5,5 @@ {% if foo %}FAIL{% endif %} --DATA-- -return array() +return [] --EXPECT-- diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/set/capture.test b/vendor/twig/twig/tests/Fixtures/tags/set/capture.test similarity index 89% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/tags/set/capture.test rename to vendor/twig/twig/tests/Fixtures/tags/set/capture.test index f156a1a7f3c3e0c8bb70c79a2b4a0d004ac7d0df..c3faf250038f5b20b6b7a175de4d332dcd2f0791 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/set/capture.test +++ b/vendor/twig/twig/tests/Fixtures/tags/set/capture.test @@ -5,6 +5,6 @@ {{ foo }} --DATA-- -return array() +return [] --EXPECT-- f<br />o<br />o diff --git a/vendor/twig/twig/tests/Fixtures/tags/set/capture_scope.test b/vendor/twig/twig/tests/Fixtures/tags/set/capture_scope.test new file mode 100644 index 0000000000000000000000000000000000000000..bb2bbebaf0eb94acdeb9e7b5773b9828cfd0d752 --- /dev/null +++ b/vendor/twig/twig/tests/Fixtures/tags/set/capture_scope.test @@ -0,0 +1,10 @@ +--TEST-- +"set" tag block capture +--TEMPLATE-- +{% set foo %}{{ foo }}{% endset %} + +{{ foo }} +--DATA-- +return ['foo' => 'foo'] +--EXPECT-- +foo diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/set/expression.test b/vendor/twig/twig/tests/Fixtures/tags/set/expression.test similarity index 90% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/tags/set/expression.test rename to vendor/twig/twig/tests/Fixtures/tags/set/expression.test index 8ff434a013c49d259f9939e18d0da06f42ce3f05..bd472771a66c69311c06a4d94ab227bec8e4aaae 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/set/expression.test +++ b/vendor/twig/twig/tests/Fixtures/tags/set/expression.test @@ -6,7 +6,7 @@ {{ foo }} {{ bar }} --DATA-- -return array() +return [] --EXPECT-- foobar barfoo diff --git a/vendor/twig/twig/tests/Fixtures/tags/set/inheritance.test b/vendor/twig/twig/tests/Fixtures/tags/set/inheritance.test new file mode 100644 index 0000000000000000000000000000000000000000..79e89ce79b7d1c21c436050e6e0dbc3f9c438d6f --- /dev/null +++ b/vendor/twig/twig/tests/Fixtures/tags/set/inheritance.test @@ -0,0 +1,24 @@ +--TEST-- +"set" tag with inheritance +--TEMPLATE-- +{% extends "layout.twig" %} + +{% set bar %}bar{% endset %} + +{% block var_from_child %} + {{- bar -}} +{% endblock %} +--TEMPLATE(layout.twig)-- +{% set foo %}foo{% endset %} + +{% block var_from_layout %} + {{- foo -}} +{% endblock %} + +{% block var_from_child %} +{% endblock %} +--DATA-- +return [] +--EXPECT-- +foo +bar diff --git a/vendor/twig/twig/tests/Fixtures/tags/set/inheritance_overriding.test b/vendor/twig/twig/tests/Fixtures/tags/set/inheritance_overriding.test new file mode 100644 index 0000000000000000000000000000000000000000..2d23c83ae6725b5aaa0953a038009cdf5c060e38 --- /dev/null +++ b/vendor/twig/twig/tests/Fixtures/tags/set/inheritance_overriding.test @@ -0,0 +1,24 @@ +--TEST-- +"set" tag with inheritance +--TEMPLATE-- +{% extends "layout.twig" %} + +{% set foo %}bar{% endset %} + +{% block var_from_child %} + {{- foo -}} +{% endblock %} +--TEMPLATE(layout.twig)-- +{% set foo %}foo{% endset %} + +{% block var_from_layout %} + {{- foo -}} +{% endblock %} + +{% block var_from_child %} +{% endblock %} +--DATA-- +return [] +--EXPECT-- +foo +foo diff --git a/vendor/twig/twig/tests/Fixtures/tags/set/mutating.test b/vendor/twig/twig/tests/Fixtures/tags/set/mutating.test new file mode 100644 index 0000000000000000000000000000000000000000..ae388bb873a3f3f059698ede4c29e7eb498851f4 --- /dev/null +++ b/vendor/twig/twig/tests/Fixtures/tags/set/mutating.test @@ -0,0 +1,17 @@ +--TEST-- +"set" tag +--TEMPLATE-- +{% set foo = "foo" %} + +{% set bar %} + {%- set foo = "bar" -%} + bar +{% endset %} + +{{ foo }} +{{ bar }} +--DATA-- +return [] +--EXPECT-- +bar +bar diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/spaceless/simple.test b/vendor/twig/twig/tests/Fixtures/tags/spaceless/simple.test similarity index 93% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/tags/spaceless/simple.test rename to vendor/twig/twig/tests/Fixtures/tags/spaceless/simple.test index dd06dec25a048b0ac6f14840b79cf4bcfd23b5f7..98bd27a13a7bf460c1e730ea8f2dcbc6a8e27434 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/spaceless/simple.test +++ b/vendor/twig/twig/tests/Fixtures/tags/spaceless/simple.test @@ -7,6 +7,6 @@ {% endspaceless %} --DATA-- -return array() +return [] --EXPECT-- <div><div> foo </div></div> diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/special_chars.test b/vendor/twig/twig/tests/Fixtures/tags/special_chars.test similarity index 82% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/tags/special_chars.test rename to vendor/twig/twig/tests/Fixtures/tags/special_chars.test index 789b4ba8052fd30be3a2fd142161bf1ac7b0bd65..64ffd1d76bf70c56809c91c0435bea52b4b00f7c 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/special_chars.test +++ b/vendor/twig/twig/tests/Fixtures/tags/special_chars.test @@ -3,6 +3,6 @@ --TEMPLATE-- {% § %} --DATA-- -return array() +return [] --EXPECT-- § diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/use/aliases.test b/vendor/twig/twig/tests/Fixtures/tags/use/aliases.test similarity index 91% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/tags/use/aliases.test rename to vendor/twig/twig/tests/Fixtures/tags/use/aliases.test index f887006f666313f441db39ca7bd5a2332bff2f98..b6b1d5c668894281f540162e4e79409b19344438 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/use/aliases.test +++ b/vendor/twig/twig/tests/Fixtures/tags/use/aliases.test @@ -7,6 +7,6 @@ --TEMPLATE(blocks.twig)-- {% block content 'foo' %} --DATA-- -return array() +return [] --EXPECT-- foo diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/use/basic.test b/vendor/twig/twig/tests/Fixtures/tags/use/basic.test similarity index 91% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/tags/use/basic.test rename to vendor/twig/twig/tests/Fixtures/tags/use/basic.test index 7364d76de2de57f18872539958872af0b677141d..be622a10e20424baa57ea56cefbfa309eaa2541f 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/use/basic.test +++ b/vendor/twig/twig/tests/Fixtures/tags/use/basic.test @@ -7,6 +7,6 @@ --TEMPLATE(blocks.twig)-- {% block content 'foo' %} --DATA-- -return array() +return [] --EXPECT-- foo diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/use/deep.test b/vendor/twig/twig/tests/Fixtures/tags/use/deep.test similarity index 95% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/tags/use/deep.test rename to vendor/twig/twig/tests/Fixtures/tags/use/deep.test index b551a1e60d3ce6df7da0a6406401ce6cae04adc6..771ba642b905dfeefffe4ea2ec0d2111b6bd3039 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/use/deep.test +++ b/vendor/twig/twig/tests/Fixtures/tags/use/deep.test @@ -15,7 +15,7 @@ {% block content 'bar' %} {% block bar 'bar' %} --DATA-- -return array() +return [] --EXPECT-- foo foo diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/use/deep_empty.test b/vendor/twig/twig/tests/Fixtures/tags/use/deep_empty.test similarity index 90% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/tags/use/deep_empty.test rename to vendor/twig/twig/tests/Fixtures/tags/use/deep_empty.test index 05cca682effc589120c6f405fb4aab4b4862efbd..f14ce83de5e7e75b1a6eec7ddd620f710604b471 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/use/deep_empty.test +++ b/vendor/twig/twig/tests/Fixtures/tags/use/deep_empty.test @@ -6,5 +6,5 @@ {% use "bar.twig" %} --TEMPLATE(bar.twig)-- --DATA-- -return array() +return [] --EXPECT-- diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/use/inheritance.test b/vendor/twig/twig/tests/Fixtures/tags/use/inheritance.test similarity index 97% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/tags/use/inheritance.test rename to vendor/twig/twig/tests/Fixtures/tags/use/inheritance.test index 0d0d470ee652701a4ab079e29e0831d02f6abb33..1edeaa1115d06f632796b8b80c216b1ff66fb801 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/use/inheritance.test +++ b/vendor/twig/twig/tests/Fixtures/tags/use/inheritance.test @@ -19,7 +19,7 @@ <div class="sub_container">sub_container</div> {% endblock %} --DATA-- -return array() +return [] --EXPECT-- <div class="container"> <div class="overridden_sub_container">overridden sub_container</div> </div> diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/use/inheritance2.test b/vendor/twig/twig/tests/Fixtures/tags/use/inheritance2.test similarity index 97% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/tags/use/inheritance2.test rename to vendor/twig/twig/tests/Fixtures/tags/use/inheritance2.test index df95599ce15a6ae2f319dab13203a9e3477d16f6..accec5094b1aae0c68a0975ecc98135d31962c5a 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/use/inheritance2.test +++ b/vendor/twig/twig/tests/Fixtures/tags/use/inheritance2.test @@ -18,7 +18,7 @@ <div class="sub_container">sub_container</div> {% endblock %} --DATA-- -return array() +return [] --EXPECT-- <div class="container"> <div class="overridden_sub_container">overridden sub_container</div> </div> diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/use/multiple.test b/vendor/twig/twig/tests/Fixtures/tags/use/multiple.test similarity index 95% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/tags/use/multiple.test rename to vendor/twig/twig/tests/Fixtures/tags/use/multiple.test index 198be0c5cda3fa2ee55c590447225660fc604265..85a63958dfc46b6474f0a5c43c3d2d5a20476a40 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/use/multiple.test +++ b/vendor/twig/twig/tests/Fixtures/tags/use/multiple.test @@ -14,7 +14,7 @@ {% block content 'bar' %} {% block bar 'bar' %} --DATA-- -return array() +return [] --EXPECT-- bar foo diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/use/multiple_aliases.test b/vendor/twig/twig/tests/Fixtures/tags/use/multiple_aliases.test similarity index 96% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/tags/use/multiple_aliases.test rename to vendor/twig/twig/tests/Fixtures/tags/use/multiple_aliases.test index 8de871a8a55527255d7ade373fd5a260c9196e76..413bdfa4ddf33657c870cfaf2ae5edc05f207657 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/use/multiple_aliases.test +++ b/vendor/twig/twig/tests/Fixtures/tags/use/multiple_aliases.test @@ -15,7 +15,7 @@ {% block content 'bar' %} {% block bar 'bar' %} --DATA-- -return array() +return [] --EXPECT-- bar foo diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/use/parent_block.test b/vendor/twig/twig/tests/Fixtures/tags/use/parent_block.test similarity index 97% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/tags/use/parent_block.test rename to vendor/twig/twig/tests/Fixtures/tags/use/parent_block.test index 59db23d955f975072776a3a42c8b6d69d14fcfe7..49328f6e87b0bca7d4f14b8ca8acf6df16740c43 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/use/parent_block.test +++ b/vendor/twig/twig/tests/Fixtures/tags/use/parent_block.test @@ -17,7 +17,7 @@ Content of block {% endblock foobar %} --DATA-- -return array() +return [] --EXPECT-- Content of block Content of block (first override) diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/use/parent_block2.test b/vendor/twig/twig/tests/Fixtures/tags/use/parent_block2.test similarity index 97% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/tags/use/parent_block2.test rename to vendor/twig/twig/tests/Fixtures/tags/use/parent_block2.test index d3f302df042d77c989b59124cd9dd4b0861717ca..274baa82166ab99704d66b93a69fef40a6803348 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/use/parent_block2.test +++ b/vendor/twig/twig/tests/Fixtures/tags/use/parent_block2.test @@ -17,7 +17,7 @@ Content of block {% endblock foobar %} --DATA-- -return array() +return [] --EXPECT-- Content of block Content of block (first override) diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/use/parent_block3.test b/vendor/twig/twig/tests/Fixtures/tags/use/parent_block3.test similarity index 98% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/tags/use/parent_block3.test rename to vendor/twig/twig/tests/Fixtures/tags/use/parent_block3.test index 95b55a4690eaaa5a9961e23dbc9260e4aff8ea41..f6f221273f2b65c450284f4197c36e8219048a1c 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/use/parent_block3.test +++ b/vendor/twig/twig/tests/Fixtures/tags/use/parent_block3.test @@ -29,7 +29,7 @@ Content of bar {% endblock bar %} --DATA-- -return array() +return [] --EXPECT-- Content of foo Content of foo (first override) diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/use/use_with_parent.test b/vendor/twig/twig/tests/Fixtures/tags/use/use_with_parent.test similarity index 96% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/tags/use/use_with_parent.test rename to vendor/twig/twig/tests/Fixtures/tags/use/use_with_parent.test index 3fe2ad83cf3c59114d8c81fb4d3b790687dd01eb..fad9a2d18964989910271ac57eb6db61e7c60baf 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/use/use_with_parent.test +++ b/vendor/twig/twig/tests/Fixtures/tags/use/use_with_parent.test @@ -17,7 +17,7 @@ --TEMPLATE(blocks.twig)-- {% block content 'BLOCK' %} --DATA-- -return array() +return [] --EXPECT-- PARENT CHILD diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/verbatim/basic.test b/vendor/twig/twig/tests/Fixtures/tags/verbatim/basic.test similarity index 88% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/tags/verbatim/basic.test rename to vendor/twig/twig/tests/Fixtures/tags/verbatim/basic.test index a95be5572adfaa1d56feaa6c3a7cc138ad685582..9b60abc49fd79e11e2cd3331a36879f77a30ac24 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/verbatim/basic.test +++ b/vendor/twig/twig/tests/Fixtures/tags/verbatim/basic.test @@ -5,6 +5,6 @@ {{ foo }} {% endverbatim %} --DATA-- -return array() +return [] --EXPECT-- {{ foo }} diff --git a/vendor/twig/twig/tests/Fixtures/tags/verbatim/mixed_usage_with_raw.test b/vendor/twig/twig/tests/Fixtures/tags/verbatim/mixed_usage_with_raw.test new file mode 100644 index 0000000000000000000000000000000000000000..2177538d51b40f88ab26e1e90b042ff2cfa95af3 --- /dev/null +++ b/vendor/twig/twig/tests/Fixtures/tags/verbatim/mixed_usage_with_raw.test @@ -0,0 +1,10 @@ +--TEST-- +"verbatim" tag +--TEMPLATE-- +{% verbatim %} +{{ foo }} +{% endraw %} +--DATA-- +return [] +--EXCEPTION-- +Twig\Error\SyntaxError: Unexpected end of file: Unclosed "verbatim" block in "index.twig" at line 2. diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/verbatim/whitespace_control.test b/vendor/twig/twig/tests/Fixtures/tags/verbatim/whitespace_control.test similarity index 97% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/tags/verbatim/whitespace_control.test rename to vendor/twig/twig/tests/Fixtures/tags/verbatim/whitespace_control.test index eb610444604beeff3f1e963f16b8d0f399b9ae28..501922bddd29eca528ccc8dae049e60bf2f3f526 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/verbatim/whitespace_control.test +++ b/vendor/twig/twig/tests/Fixtures/tags/verbatim/whitespace_control.test @@ -37,7 +37,7 @@ 5*** --DATA-- -return array() +return [] --EXPECT-- 1*** {{ 'bla' }} diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/with/basic.test b/vendor/twig/twig/tests/Fixtures/tags/with/basic.test similarity index 78% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/tags/with/basic.test rename to vendor/twig/twig/tests/Fixtures/tags/with/basic.test index 264ca5e7e3f476534d86c5f2f69980ff52f57133..7c2abd0f9bb20e194a80a24383df28f7a8c013fd 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/with/basic.test +++ b/vendor/twig/twig/tests/Fixtures/tags/with/basic.test @@ -7,7 +7,7 @@ {% endwith %} {{ foo }}{{ bar }} --DATA-- -return array('foo' => 'foo', 'bar' => 'bar') +return ['foo' => 'foo', 'bar' => 'bar'] --EXPECT-- fooBAZ foobar diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/with/expression.test b/vendor/twig/twig/tests/Fixtures/tags/with/expression.test similarity index 83% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/tags/with/expression.test rename to vendor/twig/twig/tests/Fixtures/tags/with/expression.test index 32ed0916c97f8e465d2e772cc7bb328bdf4e6c02..e4433d44c8c614e8f3ed48b271d7e3f270057c39 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/with/expression.test +++ b/vendor/twig/twig/tests/Fixtures/tags/with/expression.test @@ -5,6 +5,6 @@ {{ foo }}{{ bar }} {% endwith %} --DATA-- -return array('foo' => 'baz') +return ['foo' => 'baz'] --EXPECT-- fooBAZ diff --git a/vendor/twig/twig/tests/Fixtures/tags/with/globals.test b/vendor/twig/twig/tests/Fixtures/tags/with/globals.test new file mode 100644 index 0000000000000000000000000000000000000000..b030e7eff3fe8895331b30563b5cadcaa1b6e4ef --- /dev/null +++ b/vendor/twig/twig/tests/Fixtures/tags/with/globals.test @@ -0,0 +1,10 @@ +--TEST-- +"with" tag +--TEMPLATE-- +{% with [] only %} + {{ global }} +{% endwith %} +--DATA-- +return [] +--EXPECT-- +global diff --git a/vendor/twig/twig/tests/Fixtures/tags/with/iterable.test b/vendor/twig/twig/tests/Fixtures/tags/with/iterable.test new file mode 100644 index 0000000000000000000000000000000000000000..1b0cbc63e5e92135239a75ce698b73815d394809 --- /dev/null +++ b/vendor/twig/twig/tests/Fixtures/tags/with/iterable.test @@ -0,0 +1,10 @@ +--TEST-- +"with" tag with an iterable expression +--TEMPLATE-- +{% with vars %} + {{ foo }}{{ bar }} +{% endwith %} +--DATA-- +return ['vars' => new ArrayObject(['foo' => 'baz', 'bar' => 'qux'])] +--EXPECT-- +bazqux diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/with/nested.test b/vendor/twig/twig/tests/Fixtures/tags/with/nested.test similarity index 94% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/tags/with/nested.test rename to vendor/twig/twig/tests/Fixtures/tags/with/nested.test index 98e3aef43d112bf4bda9bdd01fd1650c0243d3d7..33ca390b2a8c034bb59206748b5f0c794199c146 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/with/nested.test +++ b/vendor/twig/twig/tests/Fixtures/tags/with/nested.test @@ -9,7 +9,7 @@ nested "with" tags {% endwith %} {{ foo }}{{ bar }} --DATA-- -return array() +return [] --EXPECT-- FOOBAZ foobar diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/with/with_no_hash.test b/vendor/twig/twig/tests/Fixtures/tags/with/with_no_hash.test similarity index 52% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/tags/with/with_no_hash.test rename to vendor/twig/twig/tests/Fixtures/tags/with/with_no_hash.test index 93689f42c1e7c7acbb13e853af82f6e73923883e..7083050b42e08ab997234fb7eabbd2418f555857 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/with/with_no_hash.test +++ b/vendor/twig/twig/tests/Fixtures/tags/with/with_no_hash.test @@ -5,6 +5,6 @@ {{ foo }}{{ bar }} {% endwith %} --DATA-- -return array('vars' => 'no-hash') +return ['vars' => 'no-hash'] --EXCEPTION-- -Twig_Error_Runtime: Variables passed to the "with" tag must be a hash in "index.twig" at line 2. +Twig\Error\RuntimeError: Variables passed to the "with" tag must be a hash in "index.twig" at line 2. diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/with/with_only.test b/vendor/twig/twig/tests/Fixtures/tags/with/with_only.test similarity index 57% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/tags/with/with_only.test rename to vendor/twig/twig/tests/Fixtures/tags/with/with_only.test index 6247617e3be25e3dba740562cd8c3628ee938f59..1aca34fc15572ae3082d0da98371b1b1d229d224 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/with/with_only.test +++ b/vendor/twig/twig/tests/Fixtures/tags/with/with_only.test @@ -5,6 +5,6 @@ {{ foo }}{{ bar }}{{ baz }} {% endwith %} --DATA-- -return array('foo' => 'baz', 'baz' => 'baz') +return ['foo' => 'baz', 'baz' => 'baz'] --EXCEPTION-- -Twig_Error_Runtime: Variable "baz" does not exist in "index.twig" at line 3. +Twig\Error\RuntimeError: Variable "baz" does not exist in "index.twig" at line 3. diff --git a/vendor/twig/twig/tests/Fixtures/tests/array.test b/vendor/twig/twig/tests/Fixtures/tests/array.test new file mode 100644 index 0000000000000000000000000000000000000000..7c9a6c80aa9fa992ba0e92fd4d9e25cbbd728a03 --- /dev/null +++ b/vendor/twig/twig/tests/Fixtures/tests/array.test @@ -0,0 +1,24 @@ +--TEST-- +array index test +--TEMPLATE-- +{% for key, value in days %} +{{ key }} +{% endfor %} +--DATA-- +return ['days' => [ + 1 => ['money' => 9], + 2 => ['money' => 21], + 3 => ['money' => 38], + 4 => ['money' => 6], + 18 => ['money' => 6], + 19 => ['money' => 3], + 31 => ['money' => 11], +]] +--EXPECT-- +1 +2 +3 +4 +18 +19 +31 diff --git a/vendor/twig/twig/tests/Fixtures/tests/constant.test b/vendor/twig/twig/tests/Fixtures/tests/constant.test new file mode 100644 index 0000000000000000000000000000000000000000..d4a9be7764b2324f8e510e01b93c481995d318d5 --- /dev/null +++ b/vendor/twig/twig/tests/Fixtures/tests/constant.test @@ -0,0 +1,14 @@ +--TEST-- +"const" test +--TEMPLATE-- +{{ 8 is constant('E_NOTICE') ? 'ok' : 'no' }} +{{ 'bar' is constant('Twig\\Tests\\TwigTestFoo::BAR_NAME') ? 'ok' : 'no' }} +{{ value is constant('Twig\\Tests\\TwigTestFoo::BAR_NAME') ? 'ok' : 'no' }} +{{ 2 is constant('ARRAY_AS_PROPS', object) ? 'ok' : 'no' }} +--DATA-- +return ['value' => 'bar', 'object' => new \ArrayObject(['hi'])] +--EXPECT-- +ok +ok +ok +ok \ No newline at end of file diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tests/defined.test b/vendor/twig/twig/tests/Fixtures/tests/defined.test similarity index 90% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/tests/defined.test rename to vendor/twig/twig/tests/Fixtures/tests/defined.test index d4e204efa766d85868e4c10627565affcb167142..1648c66fbaac4bb5ef3c0914d23aa56a51f1c3c0 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tests/defined.test +++ b/vendor/twig/twig/tests/Fixtures/tests/defined.test @@ -34,18 +34,18 @@ {{ [1, 2] is defined ? 'ok' : 'ko' }} {{ { foo: "bar" } is defined ? 'ok' : 'ko' }} --DATA-- -return array( +return [ 'definedVar' => 'defined', 'zeroVar' => 0, 'nullVar' => null, - 'nested' => array( + 'nested' => [ 'definedVar' => 'defined', 'zeroVar' => 0, 'nullVar' => null, - 'definedArray' => array(0), - ), - 'object' => new TwigTestFoo(), -); + 'definedArray' => [0], + ], + 'object' => new Twig\Tests\TwigTestFoo(), +] --EXPECT-- ok ok @@ -80,20 +80,20 @@ ok ok ok --DATA-- -return array( +return [ 'definedVar' => 'defined', 'zeroVar' => 0, 'nullVar' => null, - 'nested' => array( + 'nested' => [ 'definedVar' => 'defined', 'zeroVar' => 0, 'nullVar' => null, - 'definedArray' => array(0), - ), - 'object' => new TwigTestFoo(), -); + 'definedArray' => [0], + ], + 'object' => new Twig\Tests\TwigTestFoo(), +] --CONFIG-- -return array('strict_variables' => false) +return ['strict_variables' => false] --EXPECT-- ok ok diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tests/defined_for_attribute.test b/vendor/twig/twig/tests/Fixtures/tests/defined_for_attribute.test similarity index 82% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/tests/defined_for_attribute.test rename to vendor/twig/twig/tests/Fixtures/tests/defined_for_attribute.test index 4a5b8dcdbadee367bf4266c342d53f3a499997d0..5fd2fe3f2d2c601d0dd9d942a2acc813da3eeab2 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tests/defined_for_attribute.test +++ b/vendor/twig/twig/tests/Fixtures/tests/defined_for_attribute.test @@ -6,28 +6,28 @@ {{ attribute(nested, definedVarName) is defined ? 'ok' : 'ko' }} {{ attribute(nested, undefinedVarName) is not defined ? 'ok' : 'ko' }} --DATA-- -return array( - 'nested' => array( +return [ + 'nested' => [ 'definedVar' => 'defined', - ), + ], 'definedVarName' => 'definedVar', 'undefinedVarName' => 'undefinedVar', -); +] --EXPECT-- ok ok ok ok --DATA-- -return array( - 'nested' => array( +return [ + 'nested' => [ 'definedVar' => 'defined', - ), + ], 'definedVarName' => 'definedVar', 'undefinedVarName' => 'undefinedVar', -); +] --CONFIG-- -return array('strict_variables' => false) +return ['strict_variables' => false] --EXPECT-- ok ok diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tests/defined_for_blocks.test b/vendor/twig/twig/tests/Fixtures/tests/defined_for_blocks.test similarity index 98% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/tests/defined_for_blocks.test rename to vendor/twig/twig/tests/Fixtures/tests/defined_for_blocks.test index 64d7d0431b21f397799ffa72ac75d07f863e13df..c8b90f8c9c421738db103af758378c59a8f557a0 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tests/defined_for_blocks.test +++ b/vendor/twig/twig/tests/Fixtures/tests/defined_for_blocks.test @@ -26,7 +26,7 @@ --TEMPLATE(blocks)-- {% block block1 %}{%endblock %} --DATA-- -return array() +return [] --EXPECT-- ok ko diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tests/defined_for_blocks_with_template.test b/vendor/twig/twig/tests/Fixtures/tests/defined_for_blocks_with_template.test similarity index 82% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/tests/defined_for_blocks_with_template.test rename to vendor/twig/twig/tests/Fixtures/tests/defined_for_blocks_with_template.test index 2c651657e3bccce111a6341e8254b0d3abdc6a05..68540de7aa364f3865ba4ba2be43182b4be74cb7 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tests/defined_for_blocks_with_template.test +++ b/vendor/twig/twig/tests/Fixtures/tests/defined_for_blocks_with_template.test @@ -7,10 +7,10 @@ --TEMPLATE(included.twig)-- {% block foo %}FOO{% endblock %} --DATA-- -return array( +return [ 'included_loaded' => $twig->load('included.twig'), - 'included_loaded_internal' => $twig->loadTemplate('included.twig'), -) + 'included_loaded_internal' => $twig->load('included.twig'), +] --EXPECT-- ok ok diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tests/defined_for_constants.test b/vendor/twig/twig/tests/Fixtures/tests/defined_for_constants.test similarity index 80% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/tests/defined_for_constants.test rename to vendor/twig/twig/tests/Fixtures/tests/defined_for_constants.test index 2fa9929d35eace0ec548f898374cd2f6c4593c6a..62172e4f1f5e6153d11e1a22d2c9d4ff14dce1ab 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tests/defined_for_constants.test +++ b/vendor/twig/twig/tests/Fixtures/tests/defined_for_constants.test @@ -6,7 +6,7 @@ {{ constant('FOOBAR') is not defined ? 'ok' : 'ko' }} {{ constant('FOOBAR', object) is not defined ? 'ok' : 'ko' }} --DATA-- -return array('expect' => DATE_W3C, 'object' => new ArrayObject(array('hi'))); +return ['expect' => DATE_W3C, 'object' => new \ArrayObject(['hi'])] --EXPECT-- ok ok diff --git a/vendor/twig/twig/tests/Fixtures/tests/defined_on_complex_expr.test b/vendor/twig/twig/tests/Fixtures/tests/defined_on_complex_expr.test new file mode 100644 index 0000000000000000000000000000000000000000..2d0615832f4f1416177c94eee35b9acdc83d2af2 --- /dev/null +++ b/vendor/twig/twig/tests/Fixtures/tests/defined_on_complex_expr.test @@ -0,0 +1,8 @@ +--TEST-- +"defined" support for "complex" expressions +--TEMPLATE-- +{{ (1 + 2) is defined ? 'ok' : 'ko' }} +--DATA-- +return [] +--EXCEPTION-- +Twig\Error\SyntaxError: The "defined" test only works with simple variables in "index.twig" at line 2. diff --git a/vendor/twig/twig/tests/Fixtures/tests/dynamic_test.test b/vendor/twig/twig/tests/Fixtures/tests/dynamic_test.test new file mode 100644 index 0000000000000000000000000000000000000000..41625f6af1e71af15d36c83a3a7a815311d532df --- /dev/null +++ b/vendor/twig/twig/tests/Fixtures/tests/dynamic_test.test @@ -0,0 +1,14 @@ +--TEST-- +dynamic test +--TEMPLATE-- +{{ 'bar' is test_bar ? '1' :'0' }} +{{ 'foo' is test_foo ? '1' :'0' }} +{{ 'bar' is test_foo ? '1' :'0' }} +{{ 'foo' is test_bar ? '1' :'0' }} +--DATA-- +return [] +--EXPECT-- +1 +1 +0 +0 diff --git a/vendor/twig/twig/tests/Fixtures/tests/empty.test b/vendor/twig/twig/tests/Fixtures/tests/empty.test new file mode 100644 index 0000000000000000000000000000000000000000..ffcd518708d1f57cd14092a14f9e696d416173d5 --- /dev/null +++ b/vendor/twig/twig/tests/Fixtures/tests/empty.test @@ -0,0 +1,54 @@ +--TEST-- +"empty" test +--TEMPLATE-- +{{ string_empty is empty ? 'ok' : 'ko' }} +{{ string_zero is empty ? 'ko' : 'ok' }} +{{ value_null is empty ? 'ok' : 'ko' }} +{{ value_false is empty ? 'ok' : 'ko' }} +{{ value_int_zero is empty ? 'ko' : 'ok' }} +{{ array_empty is empty ? 'ok' : 'ko' }} +{{ array_not_empty is empty ? 'ko' : 'ok' }} +{{ magically_callable is empty ? 'ko' : 'ok' }} +{{ countable_empty is empty ? 'ok' : 'ko' }} +{{ countable_not_empty is empty ? 'ko' : 'ok' }} +{{ tostring_empty is empty ? 'ok' : 'ko' }} +{{ tostring_not_empty is empty ? 'ko' : 'ok' }} +{{ markup_empty is empty ? 'ok' : 'ko' }} +{{ markup_not_empty is empty ? 'ko' : 'ok' }} +{{ iterator is empty ? 'ko' : 'ok' }} +{{ empty_iterator is empty ? 'ok' : 'ko' }} +{{ callback_iterator is empty ? 'ko' : 'ok' }} +{{ empty_callback_iterator is empty ? 'ok' : 'ko' }} +--DATA-- +return [ + 'string_empty' => '', 'string_zero' => '0', + 'value_null' => null, 'value_false' => false, 'value_int_zero' => 0, + 'array_empty' => [], 'array_not_empty' => [1, 2], + 'magically_callable' => new \Twig\Tests\MagicCallStub(), + 'countable_empty' => new \Twig\Tests\CountableStub([]), 'countable_not_empty' => new \Twig\Tests\CountableStub([1, 2]), + 'tostring_empty' => new \Twig\Tests\ToStringStub(''), 'tostring_not_empty' => new \Twig\Tests\ToStringStub('0' /* edge case of using "0" as the string */), + 'markup_empty' => new \Twig\Markup('', 'UTF-8'), 'markup_not_empty' => new \Twig\Markup('test', 'UTF-8'), + 'iterator' => $iter = new \ArrayIterator(['bar', 'foo']), + 'empty_iterator' => new \ArrayIterator(), + 'callback_iterator' => new \CallbackFilterIterator($iter, function ($el) { return true; }), + 'empty_callback_iterator' => new \CallbackFilterIterator($iter, function ($el) { return false; }), +] +--EXPECT-- +ok +ok +ok +ok +ok +ok +ok +ok +ok +ok +ok +ok +ok +ok +ok +ok +ok +ok diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tests/even.test b/vendor/twig/twig/tests/Fixtures/tests/even.test similarity index 92% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/tests/even.test rename to vendor/twig/twig/tests/Fixtures/tests/even.test index 695b4c2f8430926ec7f283751a348f869016c0cd..5c73b01e908feb6c8b10a1a8f263113ced04da2b 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tests/even.test +++ b/vendor/twig/twig/tests/Fixtures/tests/even.test @@ -6,7 +6,7 @@ {{ 1 is not even ? 'ok' : 'ko' }} {{ 2 is not even ? 'ko' : 'ok' }} --DATA-- -return array() +return [] --EXPECT-- ok ok diff --git a/vendor/twig/twig/tests/Fixtures/tests/in.test b/vendor/twig/twig/tests/Fixtures/tests/in.test new file mode 100644 index 0000000000000000000000000000000000000000..f7b172e8d0cea5b39bd2eb837822905ecb75d13d --- /dev/null +++ b/vendor/twig/twig/tests/Fixtures/tests/in.test @@ -0,0 +1,118 @@ +--TEST-- +Twig supports the in operator +--TEMPLATE-- +{{ bar in foo ? 'OK' : 'KO' }} +{{ not (bar in foo) ? 'KO' : 'OK' }} +{{ bar not in foo ? 'KO' : 'OK' }} +{{ 'a' in bar ? 'OK' : 'KO' }} +{{ 'c' not in bar ? 'OK' : 'KO' }} +{{ '' in bar ? 'OK' : 'KO' }} +{{ '' in '' ? 'OK' : 'KO' }} +{{ '0' not in '' ? 'OK' : 'KO' }} +{{ 'a' not in '0' ? 'OK' : 'KO' }} +{{ '0' in '0' ? 'OK' : 'KO' }} + +{{ false in [0, 1] ? 'OK' : 'KO' }} +{{ true in [0, 1] ? 'OK' : 'KO' }} +{{ '0' in [0, 1] ? 'OK' : 'KO' }} +{{ '0' in [1, 0] ? 'OK' : 'KO' }} +{{ '' in [0, 1] ? 'OK' : 'KO' }} +{{ '' in [1, 0] ? 'OK' : 'KO' }} +{{ 0 in ['', 1] ? 'OK' : 'KO' }} +{{ 0 in [1, ''] ? 'OK' : 'KO' }} + +{{ '' in 'foo' ? 'OK' : 'KO' }} +{{ 0 in 'foo' ? 'KO' : 'OK' }} +{{ false in 'foo' ? 'KO' : 'OK' }} +{{ false in '100' ? 'KO' : 'OK' }} +{{ true in '100' ? 'KO' : 'OK' }} + +{{ [] in [true, false] ? 'OK' : 'KO' }} +{{ [] in [true, ''] ? 'KO' : 'OK' }} +{{ [] in [true, []] ? 'OK' : 'KO' }} + +{{ resource ? 'OK' : 'KO' }} +{{ resource in 'foo'~resource ? 'KO' : 'OK' }} +{{ object in 'stdClass' ? 'KO' : 'OK' }} +{{ [] in 'Array' ? 'KO' : 'OK' }} +{{ dir_object in 'foo'~dir_object ? 'KO' : 'OK' }} + +{{ ''~resource in resource ? 'KO' : 'OK' }} +{{ 'stdClass' in object ? 'KO' : 'OK' }} +{{ 'Array' in [] ? 'KO' : 'OK' }} +{{ ''~dir_object in dir_object ? 'KO' : 'OK' }} + +{{ resource in [''~resource] ? 'KO' : 'OK' }} +{{ resource in [resource + 1 - 1] ? 'KO' : 'OK' }} +{{ dir_object in [''~dir_object] ? 'KO' : 'OK' }} + +{{ 5 in 125 ? 'KO' : 'OK' }} +{{ 5 in '125' ? 'OK' : 'KO' }} +{{ '5' in 125 ? 'KO' : 'OK' }} +{{ '5' in '125' ? 'OK' : 'KO' }} + +{{ 5.5 in 125.5 ? 'KO' : 'OK' }} +{{ 5.5 in '125.5' ? 'OK' : 'KO' }} +{{ '5.5' in 125.5 ? 'KO' : 'OK' }} + +{{ safe in ['foo', 'bar'] ? 'OK' : 'KO' }} +{{ 'fo' in safe ? 'OK' : 'KO' }} +--DATA-- +return ['bar' => 'bar', 'foo' => ['bar' => 'bar'], 'dir_object' => new \SplFileInfo(dirname(__FILE__)), 'object' => new \stdClass(), 'resource' => opendir(dirname(__FILE__)), 'safe' => new \Twig\Markup('foo', 'UTF-8')] +--EXPECT-- +OK +OK +OK +OK +OK +OK +OK +OK +OK +OK + +OK +OK +OK +OK +OK +OK +OK +OK + +OK +OK +OK +OK +OK + +OK +OK +OK + +OK +OK +OK +OK +OK + +OK +OK +OK +OK + +OK +OK +OK + +OK +OK +OK +OK + +OK +OK +OK + +OK +OK diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tests/in_with_objects.test b/vendor/twig/twig/tests/Fixtures/tests/in_with_objects.test similarity index 64% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/tests/in_with_objects.test rename to vendor/twig/twig/tests/Fixtures/tests/in_with_objects.test index 8e08061bb58042bbc322788c7f6e315fbad5443a..1f9fc6393a2380bd440c30023e5d7616010d838c 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tests/in_with_objects.test +++ b/vendor/twig/twig/tests/Fixtures/tests/in_with_objects.test @@ -5,15 +5,15 @@ Twig supports the in operator when using objects TRUE {% endif %} --DATA-- -$foo = new TwigTestFoo(); -$foo1 = new TwigTestFoo(); +$foo = new Twig\Tests\TwigTestFoo(); +$foo1 = new Twig\Tests\TwigTestFoo(); $foo->position = $foo1; $foo1->position = $foo; -return array( +return [ 'object' => $foo, - 'object_list' => array($foo1, $foo), -); + 'object_list' => [$foo1, $foo], +] --EXPECT-- TRUE diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tests/iterable.test b/vendor/twig/twig/tests/Fixtures/tests/iterable.test similarity index 67% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/tests/iterable.test rename to vendor/twig/twig/tests/Fixtures/tests/iterable.test index ec52550134808fa51865eb035549838aa8a9b4ed..75b5756e1e64a651ed02156ea63c2a091fc6f013 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tests/iterable.test +++ b/vendor/twig/twig/tests/Fixtures/tests/iterable.test @@ -6,12 +6,12 @@ {{ obj is iterable ? 'ok' : 'ko' }} {{ val is iterable ? 'ok' : 'ko' }} --DATA-- -return array( - 'foo' => array(), - 'traversable' => new ArrayIterator(array()), - 'obj' => new stdClass(), +return [ + 'foo' => [], + 'traversable' => new \ArrayIterator([]), + 'obj' => new \stdClass(), 'val' => 'test', -); +] --EXPECT-- ok ok diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tests/null_coalesce.test b/vendor/twig/twig/tests/Fixtures/tests/null_coalesce.test similarity index 87% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/tests/null_coalesce.test rename to vendor/twig/twig/tests/Fixtures/tests/null_coalesce.test index 3d148c893da9b453957ded2fb35834cdbcf5ec51..7af3255d61d3b5e9552f49261d0722af36ced0bd 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tests/null_coalesce.test +++ b/vendor/twig/twig/tests/Fixtures/tests/null_coalesce.test @@ -14,7 +14,7 @@ Twig supports the ?? operator {{ 1 + nope ?? nada ?? 2 }} {{ 1 + nope ?? 3 + nada ?? 2 }} --DATA-- -return array('bar' => 'OK', 'foo' => array('bar' => 'OK')) +return ['bar' => 'OK', 'foo' => ['bar' => 'OK']] --EXPECT-- OK OK diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tests/odd.test b/vendor/twig/twig/tests/Fixtures/tests/odd.test similarity index 88% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/tests/odd.test rename to vendor/twig/twig/tests/Fixtures/tests/odd.test index 1b8311e3dc356210af249ee9f2790bea71c50dc0..ec88bb519c1f6ac42c15ff62b584e346ef30fad2 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tests/odd.test +++ b/vendor/twig/twig/tests/Fixtures/tests/odd.test @@ -4,7 +4,7 @@ {{ 1 is odd ? 'ok' : 'ko' }} {{ 2 is odd ? 'ko' : 'ok' }} --DATA-- -return array() +return [] --EXPECT-- ok ok \ No newline at end of file diff --git a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/trim_block.test b/vendor/twig/twig/tests/Fixtures/whitespace/trim_block.test similarity index 83% rename from vendor/twig/twig/test/Twig/Tests/Fixtures/tags/trim_block.test rename to vendor/twig/twig/tests/Fixtures/whitespace/trim_block.test index 1d2273f88a7e1420934e37125a82a9d76dab13f3..346a11076c34d71854091957e7070255375ae00f 100644 --- a/vendor/twig/twig/test/Twig/Tests/Fixtures/tags/trim_block.test +++ b/vendor/twig/twig/tests/Fixtures/whitespace/trim_block.test @@ -1,9 +1,6 @@ --TEST-- Whitespace trimming on tags. --TEMPLATE-- -{{ 5 * '{#-'|length }} -{{ '{{-'|length * 5 + '{%-'|length }} - Trim on control tag: {% for i in range(1, 9) -%} {{ i }} @@ -51,11 +48,8 @@ Combined: end --DATA-- -return array('leading' => 'leading space', 'trailing' => 'trailing space', 'both' => 'both') +return ['leading' => 'leading space', 'trailing' => 'trailing space', 'both' => 'both'] --EXPECT-- -15 -18 - Trim on control tag: 123456789 diff --git a/vendor/twig/twig/tests/Fixtures/whitespace/trim_delimiter_as_strings.test b/vendor/twig/twig/tests/Fixtures/whitespace/trim_delimiter_as_strings.test new file mode 100644 index 0000000000000000000000000000000000000000..a58818dde479345cab39f568bfc0422a172d24ca --- /dev/null +++ b/vendor/twig/twig/tests/Fixtures/whitespace/trim_delimiter_as_strings.test @@ -0,0 +1,10 @@ +--TEST-- +Whitespace trimming as strings. +--TEMPLATE-- +{{ 5 * '{#-'|length }} +{{ '{{-'|length * 5 + '{%-'|length }} +--DATA-- +return [] +--EXPECT-- +15 +18 diff --git a/vendor/twig/twig/tests/Fixtures/whitespace/trim_left.test b/vendor/twig/twig/tests/Fixtures/whitespace/trim_left.test new file mode 100644 index 0000000000000000000000000000000000000000..75d0f80319367777be0cc602a4f164b51abbfdd4 --- /dev/null +++ b/vendor/twig/twig/tests/Fixtures/whitespace/trim_left.test @@ -0,0 +1,32 @@ +--TEST-- +Whitespace trimming on tags (left side). +--TEMPLATE-- +**{% if true %} +foo + + {%- endif %}** + +** + + {{- 'foo' }}** + +** + + +{#- comment #}** + +**{% verbatim %} +foo + + {%- endverbatim %}** +--DATA-- +return [] +--EXPECT-- +**foo** + +**foo** + +**** + +** +foo** diff --git a/vendor/twig/twig/tests/Fixtures/whitespace/trim_line_left.test b/vendor/twig/twig/tests/Fixtures/whitespace/trim_line_left.test new file mode 100644 index 0000000000000000000000000000000000000000..e5e845f08b77b76657bfe7e23ebaa97b9ce58090 --- /dev/null +++ b/vendor/twig/twig/tests/Fixtures/whitespace/trim_line_left.test @@ -0,0 +1,33 @@ +--TEST-- +Line whitespace trimming on tags (left side). +--TEMPLATE-- +**{% if true %} +foo + {%~ endif %}** + +** + {{~ 'foo' }}** + +** + {#~ comment #}** + +**{% verbatim %} +foo + + {%~ endverbatim %}** +--DATA-- +return [] +--EXPECT-- +**foo +** + +** +foo** + +** +** + +** +foo + +** diff --git a/vendor/twig/twig/tests/Fixtures/whitespace/trim_line_right.test b/vendor/twig/twig/tests/Fixtures/whitespace/trim_line_right.test new file mode 100644 index 0000000000000000000000000000000000000000..e7b510c85d8e1d21f6c30c3edabbb6bf140b0824 --- /dev/null +++ b/vendor/twig/twig/tests/Fixtures/whitespace/trim_line_right.test @@ -0,0 +1,32 @@ +--TEST-- +Line whitespace trimming on tags (right side). +--TEMPLATE-- +**{% if true ~%} +foo{% endif %}** + +**{{ 'foo' ~}} +foo +** + +**{# comment ~#} + foo +** + +**{% verbatim ~%} + foo{% endverbatim %}** +--DATA-- +return [] +--EXPECT-- +** +foo** + +**foo +foo +** + +** + foo +** + +** + foo** diff --git a/vendor/twig/twig/tests/Fixtures/whitespace/trim_right.test b/vendor/twig/twig/tests/Fixtures/whitespace/trim_right.test new file mode 100644 index 0000000000000000000000000000000000000000..0ec3b0ceaa90904207471a422da3668b54832f09 --- /dev/null +++ b/vendor/twig/twig/tests/Fixtures/whitespace/trim_right.test @@ -0,0 +1,28 @@ +--TEST-- +Whitespace trimming on tags (right side). +--TEMPLATE-- +**{% if true -%} + + foo{% endif %}** + +**{{ 'foo' -}} + +** + +**{# comment -#} + +** + +**{% verbatim -%} + +foo{% endverbatim %}** +--DATA-- +return [] +--EXPECT-- +**foo** + +**foo** + +**** + +**foo** diff --git a/vendor/twig/twig/test/Twig/Tests/IntegrationTest.php b/vendor/twig/twig/tests/IntegrationTest.php similarity index 50% rename from vendor/twig/twig/test/Twig/Tests/IntegrationTest.php rename to vendor/twig/twig/tests/IntegrationTest.php index 5d20112de30e8118375d0e25d1b3005a873bda91..243aadb2bfec439c897bc17cf0349ac155edc2b0 100644 --- a/vendor/twig/twig/test/Twig/Tests/IntegrationTest.php +++ b/vendor/twig/twig/tests/IntegrationTest.php @@ -1,5 +1,7 @@ <?php +namespace Twig\Tests; + /* * This file is part of Twig. * @@ -9,6 +11,20 @@ * file that was distributed with this source code. */ +use Twig\Extension\AbstractExtension; +use Twig\Extension\DebugExtension; +use Twig\Extension\SandboxExtension; +use Twig\Extension\StringLoaderExtension; +use Twig\Node\Expression\ConstantExpression; +use Twig\Node\PrintNode; +use Twig\Sandbox\SecurityPolicy; +use Twig\Test\IntegrationTestCase; +use Twig\Token; +use Twig\TokenParser\AbstractTokenParser; +use Twig\TwigFilter; +use Twig\TwigFunction; +use Twig\TwigTest; + // This function is defined to check that escaping strategies // like html works even if a function with the same name is defined. function html() @@ -16,23 +32,23 @@ function html() return 'foo'; } -class Twig_Tests_IntegrationTest extends Twig_Test_IntegrationTestCase +class IntegrationTest extends IntegrationTestCase { public function getExtensions() { - $policy = new Twig_Sandbox_SecurityPolicy(array(), array(), array(), array(), array()); + $policy = new SecurityPolicy([], [], [], [], ['dump']); - return array( - new Twig_Extension_Debug(), - new Twig_Extension_Sandbox($policy, false), - new Twig_Extension_StringLoader(), + return [ + new DebugExtension(), + new SandboxExtension($policy, false), + new StringLoaderExtension(), new TwigTestExtension(), - ); + ]; } public function getFixturesDir() { - return dirname(__FILE__).'/Fixtures/'; + return __DIR__.'/Fixtures/'; } } @@ -41,12 +57,12 @@ function test_foo($value = 'foo') return $value; } -class TwigTestFoo implements Iterator +class TwigTestFoo implements \Iterator { const BAR_NAME = 'bar'; public $position = 0; - public $array = array(1, 2); + public $array = [1, 2]; public function bar($param1 = null, $param2 = null) { @@ -109,13 +125,13 @@ class TwigTestFoo implements Iterator } } -class TwigTestTokenParser_§ extends Twig_TokenParser +class TwigTestTokenParser_§ extends AbstractTokenParser { - public function parse(Twig_Token $token) + public function parse(Token $token) { - $this->parser->getStream()->expect(Twig_Token::BLOCK_END_TYPE); + $this->parser->getStream()->expect(Token::BLOCK_END_TYPE); - return new Twig_Node_Print(new Twig_Node_Expression_Constant('§', -1), -1); + return new PrintNode(new ConstantExpression('§', -1), -1); } public function getTag() @@ -124,51 +140,52 @@ class TwigTestTokenParser_§ extends Twig_TokenParser } } -class TwigTestExtension extends Twig_Extension +class TwigTestExtension extends AbstractExtension { public function getTokenParsers() { - return array( + return [ new TwigTestTokenParser_§(), - ); + ]; } public function getFilters() { - return array( - new Twig_SimpleFilter('§', array($this, '§Filter')), - new Twig_SimpleFilter('escape_and_nl2br', array($this, 'escape_and_nl2br'), array('needs_environment' => true, 'is_safe' => array('html'))), - new Twig_SimpleFilter('nl2br', array($this, 'nl2br'), array('pre_escape' => 'html', 'is_safe' => array('html'))), - new Twig_SimpleFilter('escape_something', array($this, 'escape_something'), array('is_safe' => array('something'))), - new Twig_SimpleFilter('preserves_safety', array($this, 'preserves_safety'), array('preserves_safety' => array('html'))), - new Twig_SimpleFilter('static_call_string', 'TwigTestExtension::staticCall'), - new Twig_SimpleFilter('static_call_array', array('TwigTestExtension', 'staticCall')), - new Twig_SimpleFilter('magic_call', array($this, 'magicCall')), - new Twig_SimpleFilter('magic_call_string', 'TwigTestExtension::magicStaticCall'), - new Twig_SimpleFilter('magic_call_array', array('TwigTestExtension', 'magicStaticCall')), - new Twig_SimpleFilter('*_path', array($this, 'dynamic_path')), - new Twig_SimpleFilter('*_foo_*_bar', array($this, 'dynamic_foo')), - ); + return [ + new TwigFilter('§', [$this, '§Filter']), + new TwigFilter('escape_and_nl2br', [$this, 'escape_and_nl2br'], ['needs_environment' => true, 'is_safe' => ['html']]), + new TwigFilter('nl2br', [$this, 'nl2br'], ['pre_escape' => 'html', 'is_safe' => ['html']]), + new TwigFilter('escape_something', [$this, 'escape_something'], ['is_safe' => ['something']]), + new TwigFilter('preserves_safety', [$this, 'preserves_safety'], ['preserves_safety' => ['html']]), + new TwigFilter('static_call_string', 'Twig\Tests\TwigTestExtension::staticCall'), + new TwigFilter('static_call_array', ['Twig\Tests\TwigTestExtension', 'staticCall']), + new TwigFilter('magic_call', [$this, 'magicCall']), + new TwigFilter('magic_call_string', 'Twig\Tests\TwigTestExtension::magicStaticCall'), + new TwigFilter('magic_call_array', ['Twig\Tests\TwigTestExtension', 'magicStaticCall']), + new TwigFilter('*_path', [$this, 'dynamic_path']), + new TwigFilter('*_foo_*_bar', [$this, 'dynamic_foo']), + ]; } public function getFunctions() { - return array( - new Twig_SimpleFunction('§', array($this, '§Function')), - new Twig_SimpleFunction('safe_br', array($this, 'br'), array('is_safe' => array('html'))), - new Twig_SimpleFunction('unsafe_br', array($this, 'br')), - new Twig_SimpleFunction('static_call_string', 'TwigTestExtension::staticCall'), - new Twig_SimpleFunction('static_call_array', array('TwigTestExtension', 'staticCall')), - new Twig_SimpleFunction('*_path', array($this, 'dynamic_path')), - new Twig_SimpleFunction('*_foo_*_bar', array($this, 'dynamic_foo')), - ); + return [ + new TwigFunction('§', [$this, '§Function']), + new TwigFunction('safe_br', [$this, 'br'], ['is_safe' => ['html']]), + new TwigFunction('unsafe_br', [$this, 'br']), + new TwigFunction('static_call_string', 'Twig\Tests\TwigTestExtension::staticCall'), + new TwigFunction('static_call_array', ['Twig\Tests\TwigTestExtension', 'staticCall']), + new TwigFunction('*_path', [$this, 'dynamic_path']), + new TwigFunction('*_foo_*_bar', [$this, 'dynamic_foo']), + ]; } public function getTests() { - return array( - new Twig_SimpleTest('multi word', array($this, 'is_multi_word')), - ); + return [ + new TwigTest('multi word', [$this, 'is_multi_word']), + new TwigTest('test_*', [$this, 'dynamic_test']), + ]; } public function §Filter($value) @@ -209,6 +226,11 @@ class TwigTestExtension extends Twig_Extension return $foo.'/'.$bar.'/'.$item; } + public function dynamic_test($element, $item) + { + return $element === $item; + } + public function escape_something($value) { return strtoupper($value); @@ -237,7 +259,7 @@ class TwigTestExtension extends Twig_Extension public function __call($method, $arguments) { if ('magicCall' !== $method) { - throw new BadMethodCallException('Unexpected call to __call'); + throw new \BadMethodCallException('Unexpected call to __call'); } return 'magic_'.$arguments[0]; @@ -246,7 +268,7 @@ class TwigTestExtension extends Twig_Extension public static function __callStatic($method, $arguments) { if ('magicStaticCall' !== $method) { - throw new BadMethodCallException('Unexpected call to __callStatic'); + throw new \BadMethodCallException('Unexpected call to __callStatic'); } return 'static_magic_'.$arguments[0]; @@ -261,7 +283,7 @@ class MagicCallStub { public function __call($name, $args) { - throw new Exception('__call shall not be called'); + throw new \Exception('__call shall not be called'); } } @@ -304,6 +326,61 @@ class CountableStub implements \Countable public function __toString() { - throw new Exception('__toString shall not be called on \Countables'); + throw new \Exception('__toString shall not be called on \Countables'); + } +} + +/** + * This class is used in tests for the length filter. + */ +class IteratorAggregateStub implements \IteratorAggregate +{ + private $data; + + public function __construct(array $data) + { + $this->data = $data; + } + + public function getIterator() + { + return new \ArrayIterator($this->data); + } +} + +class SimpleIteratorForTesting implements \Iterator +{ + private $data = [1, 2, 3, 4, 5, 6, 7]; + private $key = 0; + + public function current() + { + return $this->key; + } + + public function next() + { + ++$this->key; + } + + public function key() + { + return $this->key; + } + + public function valid() + { + return isset($this->data[$this->key]); + } + + public function rewind() + { + $this->key = 0; + } + + public function __toString() + { + // for testing, make sure string length returned is not the same as the `iterator_count` + return str_repeat('X', iterator_count($this) + 10); } } diff --git a/vendor/twig/twig/test/Twig/Tests/LegacyFixtures/autoescape/filename.legacy.test b/vendor/twig/twig/tests/LegacyFixtures/autoescape/filename.legacy.test similarity index 79% rename from vendor/twig/twig/test/Twig/Tests/LegacyFixtures/autoescape/filename.legacy.test rename to vendor/twig/twig/tests/LegacyFixtures/autoescape/filename.legacy.test index b091ad34d3173b2a973961b8739a526217a1dbd1..d25f75e8ee0ae0242b28fe86804867013cbf058f 100644 --- a/vendor/twig/twig/test/Twig/Tests/LegacyFixtures/autoescape/filename.legacy.test +++ b/vendor/twig/twig/tests/LegacyFixtures/autoescape/filename.legacy.test @@ -9,9 +9,9 @@ --TEMPLATE(index.txt.twig)-- {{ br -}} --DATA-- -return array('br' => '<br />') +return ['br' => '<br />'] --CONFIG-- -return array('autoescape' => 'filename') +return ['autoescape' => 'filename'] --EXPECT-- <br /> <br /> diff --git a/vendor/twig/twig/test/Twig/Tests/LegacyFixtures/functions/undefined_block.legacy.test b/vendor/twig/twig/tests/LegacyFixtures/functions/undefined_block.legacy.test similarity index 95% rename from vendor/twig/twig/test/Twig/Tests/LegacyFixtures/functions/undefined_block.legacy.test rename to vendor/twig/twig/tests/LegacyFixtures/functions/undefined_block.legacy.test index 62e24f0f468936846597d9f37483f8784e86b5d9..e52c3b259239b7478720f5d7169c3a5b38977415 100644 --- a/vendor/twig/twig/test/Twig/Tests/LegacyFixtures/functions/undefined_block.legacy.test +++ b/vendor/twig/twig/tests/LegacyFixtures/functions/undefined_block.legacy.test @@ -7,6 +7,6 @@ {% block foo %}Foo{% endblock %} {% block bar %}Bar{% endblock %} --DATA-- -return array() +return [] --EXPECT-- FooBarBar diff --git a/vendor/twig/twig/test/Twig/Tests/LegacyFixtures/test.legacy.test b/vendor/twig/twig/tests/LegacyFixtures/test.legacy.test similarity index 87% rename from vendor/twig/twig/test/Twig/Tests/LegacyFixtures/test.legacy.test rename to vendor/twig/twig/tests/LegacyFixtures/test.legacy.test index d9c1d5085169e2b59b9db1716341b1434b58acea..4bd1f6ac0a5e288dd050ba1e95e829e3c69093fc 100644 --- a/vendor/twig/twig/test/Twig/Tests/LegacyFixtures/test.legacy.test +++ b/vendor/twig/twig/tests/LegacyFixtures/test.legacy.test @@ -3,6 +3,6 @@ Old test classes usage --TEMPLATE-- {{ 'foo' is multi word ? 'yes' : 'no' }} --DATA-- -return array() +return [] --EXPECT-- no diff --git a/vendor/twig/twig/test/Twig/Tests/LegacyIntegrationTest.php b/vendor/twig/twig/tests/LegacyIntegrationTest.php similarity index 63% rename from vendor/twig/twig/test/Twig/Tests/LegacyIntegrationTest.php rename to vendor/twig/twig/tests/LegacyIntegrationTest.php index 2ed75803843bba32063308d5fa41f0024885a0dd..db556f31bf7e124264a30306823a7098e1469bdc 100644 --- a/vendor/twig/twig/test/Twig/Tests/LegacyIntegrationTest.php +++ b/vendor/twig/twig/tests/LegacyIntegrationTest.php @@ -1,5 +1,7 @@ <?php +namespace Twig\Tests; + /* * This file is part of Twig. * @@ -9,37 +11,40 @@ * file that was distributed with this source code. */ -class Twig_Tests_LegacyIntegrationTest extends Twig_Test_IntegrationTestCase +use Twig\Extension\AbstractExtension; +use Twig\Test\IntegrationTestCase; + +class LegacyIntegrationTest extends IntegrationTestCase { public function getExtensions() { - return array( + return [ new LegacyTwigTestExtension(), - ); + ]; } public function getFixturesDir() { - return dirname(__FILE__).'/LegacyFixtures/'; + return __DIR__.'/LegacyFixtures/'; } public function getTests($name, $legacyTests = false) { if (!$legacyTests) { - return array(array('', '', '', array(), '', array())); + return [['', '', '', [], '', []]]; } return parent::getTests($name, true); } } -class LegacyTwigTestExtension extends Twig_Extension +class LegacyTwigTestExtension extends AbstractExtension { public function getTests() { - return array( - 'multi word' => new Twig_Test_Method($this, 'is_multi_word'), - ); + return [ + 'multi word' => new \Twig_Test_Method($this, 'is_multi_word'), + ]; } public function is_multi_word($value) diff --git a/vendor/twig/twig/tests/LexerTest.php b/vendor/twig/twig/tests/LexerTest.php new file mode 100644 index 0000000000000000000000000000000000000000..8bd2de5cf9b1de1f4816934790aa5d83f495d0cf --- /dev/null +++ b/vendor/twig/twig/tests/LexerTest.php @@ -0,0 +1,378 @@ +<?php + +namespace Twig\Tests; + +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use Twig\Environment; +use Twig\Lexer; +use Twig\Source; +use Twig\Token; + +class LexerTest extends \PHPUnit\Framework\TestCase +{ + /** + * @group legacy + */ + public function testLegacyConstructorSignature() + { + $lexer = new Lexer(new Environment($this->createMock('\Twig\Loader\LoaderInterface'))); + $stream = $lexer->tokenize('{{ foo }}', 'foo'); + $this->assertEquals('foo', $stream->getFilename()); + $this->assertEquals('{{ foo }}', $stream->getSource()); + } + + public function testNameLabelForTag() + { + $template = '{% § %}'; + + $lexer = new Lexer(new Environment($this->createMock('\Twig\Loader\LoaderInterface'))); + $stream = $lexer->tokenize(new Source($template, 'index')); + + $stream->expect(Token::BLOCK_START_TYPE); + $this->assertSame('§', $stream->expect(Token::NAME_TYPE)->getValue()); + } + + public function testNameLabelForFunction() + { + $template = '{{ §() }}'; + + $lexer = new Lexer(new Environment($this->createMock('\Twig\Loader\LoaderInterface'))); + $stream = $lexer->tokenize(new Source($template, 'index')); + + $stream->expect(Token::VAR_START_TYPE); + $this->assertSame('§', $stream->expect(Token::NAME_TYPE)->getValue()); + } + + public function testBracketsNesting() + { + $template = '{{ {"a":{"b":"c"}} }}'; + + $this->assertEquals(2, $this->countToken($template, Token::PUNCTUATION_TYPE, '{')); + $this->assertEquals(2, $this->countToken($template, Token::PUNCTUATION_TYPE, '}')); + } + + protected function countToken($template, $type, $value = null) + { + $lexer = new Lexer(new Environment($this->createMock('\Twig\Loader\LoaderInterface'))); + $stream = $lexer->tokenize(new Source($template, 'index')); + + $count = 0; + while (!$stream->isEOF()) { + $token = $stream->next(); + if ($type === $token->getType()) { + if (null === $value || $value === $token->getValue()) { + ++$count; + } + } + } + + return $count; + } + + public function testLineDirective() + { + $template = "foo\n" + ."bar\n" + ."{% line 10 %}\n" + ."{{\n" + ."baz\n" + ."}}\n"; + + $lexer = new Lexer(new Environment($this->createMock('\Twig\Loader\LoaderInterface'))); + $stream = $lexer->tokenize(new Source($template, 'index')); + + // foo\nbar\n + $this->assertSame(1, $stream->expect(Token::TEXT_TYPE)->getLine()); + // \n (after {% line %}) + $this->assertSame(10, $stream->expect(Token::TEXT_TYPE)->getLine()); + // {{ + $this->assertSame(11, $stream->expect(Token::VAR_START_TYPE)->getLine()); + // baz + $this->assertSame(12, $stream->expect(Token::NAME_TYPE)->getLine()); + } + + public function testLineDirectiveInline() + { + $template = "foo\n" + ."bar{% line 10 %}{{\n" + ."baz\n" + ."}}\n"; + + $lexer = new Lexer(new Environment($this->createMock('\Twig\Loader\LoaderInterface'))); + $stream = $lexer->tokenize(new Source($template, 'index')); + + // foo\nbar + $this->assertSame(1, $stream->expect(Token::TEXT_TYPE)->getLine()); + // {{ + $this->assertSame(10, $stream->expect(Token::VAR_START_TYPE)->getLine()); + // baz + $this->assertSame(11, $stream->expect(Token::NAME_TYPE)->getLine()); + } + + public function testLongComments() + { + $template = '{# '.str_repeat('*', 100000).' #}'; + + $lexer = new Lexer(new Environment($this->createMock('\Twig\Loader\LoaderInterface'))); + $lexer->tokenize(new Source($template, 'index')); + + // add a dummy assertion here to satisfy PHPUnit, the only thing we want to test is that the code above + // can be executed without throwing any exceptions + $this->addToAssertionCount(1); + } + + public function testLongVerbatim() + { + $template = '{% verbatim %}'.str_repeat('*', 100000).'{% endverbatim %}'; + + $lexer = new Lexer(new Environment($this->createMock('\Twig\Loader\LoaderInterface'))); + $lexer->tokenize(new Source($template, 'index')); + + // add a dummy assertion here to satisfy PHPUnit, the only thing we want to test is that the code above + // can be executed without throwing any exceptions + $this->addToAssertionCount(1); + } + + public function testLongVar() + { + $template = '{{ '.str_repeat('x', 100000).' }}'; + + $lexer = new Lexer(new Environment($this->createMock('\Twig\Loader\LoaderInterface'))); + $lexer->tokenize(new Source($template, 'index')); + + // add a dummy assertion here to satisfy PHPUnit, the only thing we want to test is that the code above + // can be executed without throwing any exceptions + $this->addToAssertionCount(1); + } + + public function testLongBlock() + { + $template = '{% '.str_repeat('x', 100000).' %}'; + + $lexer = new Lexer(new Environment($this->createMock('\Twig\Loader\LoaderInterface'))); + $lexer->tokenize(new Source($template, 'index')); + + // add a dummy assertion here to satisfy PHPUnit, the only thing we want to test is that the code above + // can be executed without throwing any exceptions + $this->addToAssertionCount(1); + } + + public function testBigNumbers() + { + $template = '{{ 922337203685477580700 }}'; + + $lexer = new Lexer(new Environment($this->createMock('\Twig\Loader\LoaderInterface'))); + $stream = $lexer->tokenize(new Source($template, 'index')); + $stream->next(); + $node = $stream->next(); + $this->assertEquals('922337203685477580700', $node->getValue()); + } + + public function testStringWithEscapedDelimiter() + { + $tests = [ + "{{ 'foo \' bar' }}" => 'foo \' bar', + '{{ "foo \" bar" }}' => 'foo " bar', + ]; + $lexer = new Lexer(new Environment($this->createMock('\Twig\Loader\LoaderInterface'))); + foreach ($tests as $template => $expected) { + $stream = $lexer->tokenize(new Source($template, 'index')); + $stream->expect(Token::VAR_START_TYPE); + $stream->expect(Token::STRING_TYPE, $expected); + + // add a dummy assertion here to satisfy PHPUnit, the only thing we want to test is that the code above + // can be executed without throwing any exceptions + $this->addToAssertionCount(1); + } + } + + public function testStringWithInterpolation() + { + $template = 'foo {{ "bar #{ baz + 1 }" }}'; + + $lexer = new Lexer(new Environment($this->createMock('\Twig\Loader\LoaderInterface'))); + $stream = $lexer->tokenize(new Source($template, 'index')); + $stream->expect(Token::TEXT_TYPE, 'foo '); + $stream->expect(Token::VAR_START_TYPE); + $stream->expect(Token::STRING_TYPE, 'bar '); + $stream->expect(Token::INTERPOLATION_START_TYPE); + $stream->expect(Token::NAME_TYPE, 'baz'); + $stream->expect(Token::OPERATOR_TYPE, '+'); + $stream->expect(Token::NUMBER_TYPE, '1'); + $stream->expect(Token::INTERPOLATION_END_TYPE); + $stream->expect(Token::VAR_END_TYPE); + + // add a dummy assertion here to satisfy PHPUnit, the only thing we want to test is that the code above + // can be executed without throwing any exceptions + $this->addToAssertionCount(1); + } + + public function testStringWithEscapedInterpolation() + { + $template = '{{ "bar \#{baz+1}" }}'; + + $lexer = new Lexer(new Environment($this->createMock('\Twig\Loader\LoaderInterface'))); + $stream = $lexer->tokenize(new Source($template, 'index')); + $stream->expect(Token::VAR_START_TYPE); + $stream->expect(Token::STRING_TYPE, 'bar #{baz+1}'); + $stream->expect(Token::VAR_END_TYPE); + + // add a dummy assertion here to satisfy PHPUnit, the only thing we want to test is that the code above + // can be executed without throwing any exceptions + $this->addToAssertionCount(1); + } + + public function testStringWithHash() + { + $template = '{{ "bar # baz" }}'; + + $lexer = new Lexer(new Environment($this->createMock('\Twig\Loader\LoaderInterface'))); + $stream = $lexer->tokenize(new Source($template, 'index')); + $stream->expect(Token::VAR_START_TYPE); + $stream->expect(Token::STRING_TYPE, 'bar # baz'); + $stream->expect(Token::VAR_END_TYPE); + + // add a dummy assertion here to satisfy PHPUnit, the only thing we want to test is that the code above + // can be executed without throwing any exceptions + $this->addToAssertionCount(1); + } + + public function testStringWithUnterminatedInterpolation() + { + $this->expectException('\Twig\Error\SyntaxError'); + $this->expectExceptionMessage('Unclosed """'); + + $template = '{{ "bar #{x" }}'; + + $lexer = new Lexer(new Environment($this->createMock('\Twig\Loader\LoaderInterface'))); + $lexer->tokenize(new Source($template, 'index')); + } + + public function testStringWithNestedInterpolations() + { + $template = '{{ "bar #{ "foo#{bar}" }" }}'; + + $lexer = new Lexer(new Environment($this->createMock('\Twig\Loader\LoaderInterface'))); + $stream = $lexer->tokenize(new Source($template, 'index')); + $stream->expect(Token::VAR_START_TYPE); + $stream->expect(Token::STRING_TYPE, 'bar '); + $stream->expect(Token::INTERPOLATION_START_TYPE); + $stream->expect(Token::STRING_TYPE, 'foo'); + $stream->expect(Token::INTERPOLATION_START_TYPE); + $stream->expect(Token::NAME_TYPE, 'bar'); + $stream->expect(Token::INTERPOLATION_END_TYPE); + $stream->expect(Token::INTERPOLATION_END_TYPE); + $stream->expect(Token::VAR_END_TYPE); + + // add a dummy assertion here to satisfy PHPUnit, the only thing we want to test is that the code above + // can be executed without throwing any exceptions + $this->addToAssertionCount(1); + } + + public function testStringWithNestedInterpolationsInBlock() + { + $template = '{% foo "bar #{ "foo#{bar}" }" %}'; + + $lexer = new Lexer(new Environment($this->createMock('\Twig\Loader\LoaderInterface'))); + $stream = $lexer->tokenize(new Source($template, 'index')); + $stream->expect(Token::BLOCK_START_TYPE); + $stream->expect(Token::NAME_TYPE, 'foo'); + $stream->expect(Token::STRING_TYPE, 'bar '); + $stream->expect(Token::INTERPOLATION_START_TYPE); + $stream->expect(Token::STRING_TYPE, 'foo'); + $stream->expect(Token::INTERPOLATION_START_TYPE); + $stream->expect(Token::NAME_TYPE, 'bar'); + $stream->expect(Token::INTERPOLATION_END_TYPE); + $stream->expect(Token::INTERPOLATION_END_TYPE); + $stream->expect(Token::BLOCK_END_TYPE); + + // add a dummy assertion here to satisfy PHPUnit, the only thing we want to test is that the code above + // can be executed without throwing any exceptions + $this->addToAssertionCount(1); + } + + public function testOperatorEndingWithALetterAtTheEndOfALine() + { + $template = "{{ 1 and\n0}}"; + + $lexer = new Lexer(new Environment($this->createMock('\Twig\Loader\LoaderInterface'))); + $stream = $lexer->tokenize(new Source($template, 'index')); + $stream->expect(Token::VAR_START_TYPE); + $stream->expect(Token::NUMBER_TYPE, 1); + $stream->expect(Token::OPERATOR_TYPE, 'and'); + + // add a dummy assertion here to satisfy PHPUnit, the only thing we want to test is that the code above + // can be executed without throwing any exceptions + $this->addToAssertionCount(1); + } + + public function testUnterminatedVariable() + { + $this->expectException('\Twig\Error\SyntaxError'); + $this->expectExceptionMessage('Unclosed "variable" in "index" at line 3'); + + $template = ' + +{{ + +bar + + +'; + + $lexer = new Lexer(new Environment($this->createMock('\Twig\Loader\LoaderInterface'))); + $lexer->tokenize(new Source($template, 'index')); + } + + public function testUnterminatedBlock() + { + $this->expectException('\Twig\Error\SyntaxError'); + $this->expectExceptionMessage('Unclosed "block" in "index" at line 3'); + + $template = ' + +{% + +bar + + +'; + + $lexer = new Lexer(new Environment($this->createMock('\Twig\Loader\LoaderInterface'))); + $lexer->tokenize(new Source($template, 'index')); + } + + public function testOverridingSyntax() + { + $template = '[# comment #]{# variable #}/# if true #/true/# endif #/'; + $lexer = new Lexer(new Environment($this->createMock('\Twig\Loader\LoaderInterface')), [ + 'tag_comment' => ['[#', '#]'], + 'tag_block' => ['/#', '#/'], + 'tag_variable' => ['{#', '#}'], + ]); + $stream = $lexer->tokenize(new Source($template, 'index')); + $stream->expect(Token::VAR_START_TYPE); + $stream->expect(Token::NAME_TYPE, 'variable'); + $stream->expect(Token::VAR_END_TYPE); + $stream->expect(Token::BLOCK_START_TYPE); + $stream->expect(Token::NAME_TYPE, 'if'); + $stream->expect(Token::NAME_TYPE, 'true'); + $stream->expect(Token::BLOCK_END_TYPE); + $stream->expect(Token::TEXT_TYPE, 'true'); + $stream->expect(Token::BLOCK_START_TYPE); + $stream->expect(Token::NAME_TYPE, 'endif'); + $stream->expect(Token::BLOCK_END_TYPE); + + // add a dummy assertion here to satisfy PHPUnit, the only thing we want to test is that the code above + // can be executed without throwing any exceptions + $this->addToAssertionCount(1); + } +} diff --git a/vendor/twig/twig/test/Twig/Tests/Loader/ArrayTest.php b/vendor/twig/twig/tests/Loader/ArrayTest.php similarity index 73% rename from vendor/twig/twig/test/Twig/Tests/Loader/ArrayTest.php rename to vendor/twig/twig/tests/Loader/ArrayTest.php index 593063933e52e5026c30247f416e9ff7972f7b93..ab670b58aa21962c9c52a5e5f9a5881064f26ce0 100644 --- a/vendor/twig/twig/test/Twig/Tests/Loader/ArrayTest.php +++ b/vendor/twig/twig/tests/Loader/ArrayTest.php @@ -1,5 +1,7 @@ <?php +namespace Twig\Tests\Loader; + /* * This file is part of Twig. * @@ -9,52 +11,54 @@ * file that was distributed with this source code. */ -class Twig_Tests_Loader_ArrayTest extends \PHPUnit\Framework\TestCase +use Twig\Loader\ArrayLoader; + +class ArrayTest extends \PHPUnit\Framework\TestCase { /** * @group legacy */ public function testGetSource() { - $loader = new Twig_Loader_Array(array('foo' => 'bar')); + $loader = new ArrayLoader(['foo' => 'bar']); $this->assertEquals('bar', $loader->getSource('foo')); } /** * @group legacy - * @expectedException Twig_Error_Loader */ public function testGetSourceWhenTemplateDoesNotExist() { - $loader = new Twig_Loader_Array(array()); + $this->expectException('\Twig\Error\LoaderError'); + + $loader = new ArrayLoader([]); $loader->getSource('foo'); } - /** - * @expectedException Twig_Error_Loader - */ public function testGetSourceContextWhenTemplateDoesNotExist() { - $loader = new Twig_Loader_Array(array()); + $this->expectException('\Twig\Error\LoaderError'); + + $loader = new ArrayLoader([]); $loader->getSourceContext('foo'); } public function testGetCacheKey() { - $loader = new Twig_Loader_Array(array('foo' => 'bar')); + $loader = new ArrayLoader(['foo' => 'bar']); $this->assertEquals('foo:bar', $loader->getCacheKey('foo')); } public function testGetCacheKeyWhenTemplateHasDuplicateContent() { - $loader = new Twig_Loader_Array(array( + $loader = new ArrayLoader([ 'foo' => 'bar', 'baz' => 'bar', - )); + ]); $this->assertEquals('foo:bar', $loader->getCacheKey('foo')); $this->assertEquals('baz:bar', $loader->getCacheKey('baz')); @@ -62,28 +66,27 @@ class Twig_Tests_Loader_ArrayTest extends \PHPUnit\Framework\TestCase public function testGetCacheKeyIsProtectedFromEdgeCollisions() { - $loader = new Twig_Loader_Array(array( + $loader = new ArrayLoader([ 'foo__' => 'bar', 'foo' => '__bar', - )); + ]); $this->assertEquals('foo__:bar', $loader->getCacheKey('foo__')); $this->assertEquals('foo:__bar', $loader->getCacheKey('foo')); } - /** - * @expectedException Twig_Error_Loader - */ public function testGetCacheKeyWhenTemplateDoesNotExist() { - $loader = new Twig_Loader_Array(array()); + $this->expectException('\Twig\Error\LoaderError'); + + $loader = new ArrayLoader([]); $loader->getCacheKey('foo'); } public function testSetTemplate() { - $loader = new Twig_Loader_Array(array()); + $loader = new ArrayLoader([]); $loader->setTemplate('foo', 'bar'); $this->assertEquals('bar', $loader->getSourceContext('foo')->getCode()); @@ -91,16 +94,15 @@ class Twig_Tests_Loader_ArrayTest extends \PHPUnit\Framework\TestCase public function testIsFresh() { - $loader = new Twig_Loader_Array(array('foo' => 'bar')); + $loader = new ArrayLoader(['foo' => 'bar']); $this->assertTrue($loader->isFresh('foo', time())); } - /** - * @expectedException Twig_Error_Loader - */ public function testIsFreshWhenTemplateDoesNotExist() { - $loader = new Twig_Loader_Array(array()); + $this->expectException('\Twig\Error\LoaderError'); + + $loader = new ArrayLoader([]); $loader->isFresh('foo', time()); } @@ -108,7 +110,7 @@ class Twig_Tests_Loader_ArrayTest extends \PHPUnit\Framework\TestCase public function testTemplateReference() { $name = new Twig_Test_Loader_TemplateReference('foo'); - $loader = new Twig_Loader_Array(array('foo' => 'bar')); + $loader = new ArrayLoader(['foo' => 'bar']); $loader->getCacheKey($name); $loader->getSourceContext($name); diff --git a/vendor/twig/twig/test/Twig/Tests/Loader/ChainTest.php b/vendor/twig/twig/tests/Loader/ChainTest.php similarity index 55% rename from vendor/twig/twig/test/Twig/Tests/Loader/ChainTest.php rename to vendor/twig/twig/tests/Loader/ChainTest.php index 8a8a84a5a03101c3440de405ae78513c801ed8d1..d89e2cc23f99bdec75eb8873508e17eecc3100f1 100644 --- a/vendor/twig/twig/test/Twig/Tests/Loader/ChainTest.php +++ b/vendor/twig/twig/tests/Loader/ChainTest.php @@ -1,5 +1,7 @@ <?php +namespace Twig\Tests\Loader; + /* * This file is part of Twig. * @@ -9,17 +11,25 @@ * file that was distributed with this source code. */ -class Twig_Tests_Loader_ChainTest extends \PHPUnit\Framework\TestCase +use Twig\Loader\ArrayLoader; +use Twig\Loader\ChainLoader; +use Twig\Loader\ExistsLoaderInterface; +use Twig\Loader\FilesystemLoader; +use Twig\Loader\LoaderInterface; +use Twig\Loader\SourceContextLoaderInterface; +use Twig\Source; + +class ChainTest extends \PHPUnit\Framework\TestCase { /** * @group legacy */ public function testGetSource() { - $loader = new Twig_Loader_Chain(array( - new Twig_Loader_Array(array('foo' => 'bar')), - new Twig_Loader_Array(array('foo' => 'foobar', 'bar' => 'foo')), - )); + $loader = new ChainLoader([ + new ArrayLoader(['foo' => 'bar']), + new ArrayLoader(['foo' => 'foobar', 'bar' => 'foo']), + ]); $this->assertEquals('bar', $loader->getSource('foo')); $this->assertEquals('foo', $loader->getSource('bar')); @@ -27,12 +37,12 @@ class Twig_Tests_Loader_ChainTest extends \PHPUnit\Framework\TestCase public function testGetSourceContext() { - $path = dirname(__FILE__).'/../Fixtures'; - $loader = new Twig_Loader_Chain(array( - new Twig_Loader_Array(array('foo' => 'bar')), - new Twig_Loader_Array(array('errors/index.html' => 'baz')), - new Twig_Loader_Filesystem(array($path)), - )); + $path = __DIR__.'/../Fixtures'; + $loader = new ChainLoader([ + new ArrayLoader(['foo' => 'bar']), + new ArrayLoader(['errors/index.html' => 'baz']), + new FilesystemLoader([$path]), + ]); $this->assertEquals('foo', $loader->getSourceContext('foo')->getName()); $this->assertSame('', $loader->getSourceContext('foo')->getPath()); @@ -46,68 +56,67 @@ class Twig_Tests_Loader_ChainTest extends \PHPUnit\Framework\TestCase $this->assertNotEquals('baz', $loader->getSourceContext('errors/base.html')->getCode()); } - /** - * @expectedException Twig_Error_Loader - */ public function testGetSourceContextWhenTemplateDoesNotExist() { - $loader = new Twig_Loader_Chain(array()); + $this->expectException('\Twig\Error\LoaderError'); + + $loader = new ChainLoader([]); $loader->getSourceContext('foo'); } /** * @group legacy - * @expectedException Twig_Error_Loader */ public function testGetSourceWhenTemplateDoesNotExist() { - $loader = new Twig_Loader_Chain(array()); + $this->expectException('\Twig\Error\LoaderError'); + + $loader = new ChainLoader([]); $loader->getSource('foo'); } public function testGetCacheKey() { - $loader = new Twig_Loader_Chain(array( - new Twig_Loader_Array(array('foo' => 'bar')), - new Twig_Loader_Array(array('foo' => 'foobar', 'bar' => 'foo')), - )); + $loader = new ChainLoader([ + new ArrayLoader(['foo' => 'bar']), + new ArrayLoader(['foo' => 'foobar', 'bar' => 'foo']), + ]); $this->assertEquals('foo:bar', $loader->getCacheKey('foo')); $this->assertEquals('bar:foo', $loader->getCacheKey('bar')); } - /** - * @expectedException Twig_Error_Loader - */ public function testGetCacheKeyWhenTemplateDoesNotExist() { - $loader = new Twig_Loader_Chain(array()); + $this->expectException('\Twig\Error\LoaderError'); + + $loader = new ChainLoader([]); $loader->getCacheKey('foo'); } public function testAddLoader() { - $loader = new Twig_Loader_Chain(); - $loader->addLoader(new Twig_Loader_Array(array('foo' => 'bar'))); + $loader = new ChainLoader(); + $loader->addLoader(new ArrayLoader(['foo' => 'bar'])); $this->assertEquals('bar', $loader->getSourceContext('foo')->getCode()); } public function testExists() { - $loader1 = $this->getMockBuilder('Twig_ChainTestLoaderWithExistsInterface')->getMock(); - $loader1->expects($this->once())->method('exists')->will($this->returnValue(false)); + $loader1 = $this->createMock('Twig\Tests\Loader\ChainTestLoaderWithExistsInterface'); + $loader1->expects($this->once())->method('exists')->willReturn(false); $loader1->expects($this->never())->method('getSourceContext'); // can be removed in 2.0 - $loader2 = $this->getMockBuilder('Twig_ChainTestLoaderInterface')->getMock(); - //$loader2 = $this->getMockBuilder(array('Twig_LoaderInterface', 'Twig_SourceContextLoaderInterface'))->getMock(); - $loader2->expects($this->once())->method('getSourceContext')->will($this->returnValue(new Twig_Source('content', 'index'))); + $loader2 = $this->createMock('Twig\Tests\Loader\ChainTestLoaderInterface'); + //$loader2 = $this->createMock(['\Twig\Loader\LoaderInterface', '\Twig\Loader\SourceContextLoaderInterface']); + $loader2->expects($this->once())->method('getSourceContext')->willReturn(new Source('content', 'index')); - $loader = new Twig_Loader_Chain(); + $loader = new ChainLoader(); $loader->addLoader($loader1); $loader->addLoader($loader2); @@ -115,10 +124,10 @@ class Twig_Tests_Loader_ChainTest extends \PHPUnit\Framework\TestCase } } -interface Twig_ChainTestLoaderInterface extends Twig_LoaderInterface, Twig_SourceContextLoaderInterface +interface ChainTestLoaderInterface extends LoaderInterface, SourceContextLoaderInterface { } -interface Twig_ChainTestLoaderWithExistsInterface extends Twig_LoaderInterface, Twig_ExistsLoaderInterface, Twig_SourceContextLoaderInterface +interface ChainTestLoaderWithExistsInterface extends LoaderInterface, ExistsLoaderInterface, SourceContextLoaderInterface { } diff --git a/vendor/twig/twig/tests/Loader/FilesystemTest.php b/vendor/twig/twig/tests/Loader/FilesystemTest.php new file mode 100644 index 0000000000000000000000000000000000000000..3307a9b7e932d73862ec977d80b7d2a3597c3ad5 --- /dev/null +++ b/vendor/twig/twig/tests/Loader/FilesystemTest.php @@ -0,0 +1,247 @@ +<?php + +namespace Twig\Tests\Loader; + +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use Twig\Environment; +use Twig\Error\LoaderError; +use Twig\Loader\FilesystemLoader; + +class FilesystemTest extends \PHPUnit\Framework\TestCase +{ + public function testGetSourceContext() + { + $path = __DIR__.'/../Fixtures'; + $loader = new FilesystemLoader([$path]); + $this->assertEquals('errors/index.html', $loader->getSourceContext('errors/index.html')->getName()); + $this->assertEquals(realpath($path.'/errors/index.html'), realpath($loader->getSourceContext('errors/index.html')->getPath())); + } + + /** + * @dataProvider getSecurityTests + */ + public function testSecurity($template) + { + $loader = new FilesystemLoader([__DIR__.'/../Fixtures']); + + try { + $loader->getCacheKey($template); + $this->fail(); + } catch (LoaderError $e) { + $this->assertStringNotContainsString('Unable to find template', $e->getMessage()); + } + } + + public function getSecurityTests() + { + return [ + ["AutoloaderTest\0.php"], + ['..\\AutoloaderTest.php'], + ['..\\\\\\AutoloaderTest.php'], + ['../AutoloaderTest.php'], + ['..////AutoloaderTest.php'], + ['./../AutoloaderTest.php'], + ['.\\..\\AutoloaderTest.php'], + ['././././././../AutoloaderTest.php'], + ['.\\./.\\./.\\./../AutoloaderTest.php'], + ['foo/../../AutoloaderTest.php'], + ['foo\\..\\..\\AutoloaderTest.php'], + ['foo/../bar/../../AutoloaderTest.php'], + ['foo/bar/../../../AutoloaderTest.php'], + ['filters/../../AutoloaderTest.php'], + ['filters//..//..//AutoloaderTest.php'], + ['filters\\..\\..\\AutoloaderTest.php'], + ['filters\\\\..\\\\..\\\\AutoloaderTest.php'], + ['filters\\//../\\/\\..\\AutoloaderTest.php'], + ['/../AutoloaderTest.php'], + ]; + } + + /** + * @dataProvider getBasePaths + */ + public function testPaths($basePath, $cacheKey, $rootPath) + { + $loader = new FilesystemLoader([$basePath.'/normal', $basePath.'/normal_bis'], $rootPath); + $loader->setPaths([$basePath.'/named', $basePath.'/named_bis'], 'named'); + $loader->addPath($basePath.'/named_ter', 'named'); + $loader->addPath($basePath.'/normal_ter'); + $loader->prependPath($basePath.'/normal_final'); + $loader->prependPath($basePath.'/named/../named_quater', 'named'); + $loader->prependPath($basePath.'/named_final', 'named'); + + $this->assertEquals([ + $basePath.'/normal_final', + $basePath.'/normal', + $basePath.'/normal_bis', + $basePath.'/normal_ter', + ], $loader->getPaths()); + $this->assertEquals([ + $basePath.'/named_final', + $basePath.'/named/../named_quater', + $basePath.'/named', + $basePath.'/named_bis', + $basePath.'/named_ter', + ], $loader->getPaths('named')); + + // do not use realpath here as it would make the test unuseful + $this->assertEquals($cacheKey, str_replace('\\', '/', $loader->getCacheKey('@named/named_absolute.html'))); + $this->assertEquals("path (final)\n", $loader->getSourceContext('index.html')->getCode()); + $this->assertEquals("path (final)\n", $loader->getSourceContext('@__main__/index.html')->getCode()); + $this->assertEquals("named path (final)\n", $loader->getSourceContext('@named/index.html')->getCode()); + } + + public function getBasePaths() + { + return [ + [ + __DIR__.'/Fixtures', + 'tests/Loader/Fixtures/named_quater/named_absolute.html', + null, + ], + [ + __DIR__.'/Fixtures/../Fixtures', + 'tests/Loader/Fixtures/named_quater/named_absolute.html', + null, + ], + [ + 'tests/Loader/Fixtures', + 'tests/Loader/Fixtures/named_quater/named_absolute.html', + getcwd(), + ], + [ + 'Fixtures', + 'Fixtures/named_quater/named_absolute.html', + getcwd().'/tests/Loader', + ], + [ + 'Fixtures', + 'Fixtures/named_quater/named_absolute.html', + getcwd().'/tests/../tests/Loader', + ], + ]; + } + + public function testEmptyConstructor() + { + $loader = new FilesystemLoader(); + $this->assertEquals([], $loader->getPaths()); + } + + public function testGetNamespaces() + { + $loader = new FilesystemLoader(sys_get_temp_dir()); + $this->assertEquals([FilesystemLoader::MAIN_NAMESPACE], $loader->getNamespaces()); + + $loader->addPath(sys_get_temp_dir(), 'named'); + $this->assertEquals([FilesystemLoader::MAIN_NAMESPACE, 'named'], $loader->getNamespaces()); + } + + public function testFindTemplateExceptionNamespace() + { + $basePath = __DIR__.'/Fixtures'; + + $loader = new FilesystemLoader([$basePath.'/normal']); + $loader->addPath($basePath.'/named', 'named'); + + try { + $loader->getSourceContext('@named/nowhere.html'); + } catch (\Exception $e) { + $this->assertInstanceOf('\Twig\Error\LoaderError', $e); + $this->assertStringContainsString('Unable to find template "@named/nowhere.html"', $e->getMessage()); + } + } + + public function testFindTemplateWithCache() + { + $basePath = __DIR__.'/Fixtures'; + + $loader = new FilesystemLoader([$basePath.'/normal']); + $loader->addPath($basePath.'/named', 'named'); + + // prime the cache for index.html in the named namespace + $namedSource = $loader->getSourceContext('@named/index.html')->getCode(); + $this->assertEquals("named path\n", $namedSource); + + // get index.html from the main namespace + $this->assertEquals("path\n", $loader->getSourceContext('index.html')->getCode()); + } + + public function testLoadTemplateAndRenderBlockWithCache() + { + $loader = new FilesystemLoader([]); + $loader->addPath(__DIR__.'/Fixtures/themes/theme2'); + $loader->addPath(__DIR__.'/Fixtures/themes/theme1'); + $loader->addPath(__DIR__.'/Fixtures/themes/theme1', 'default_theme'); + + $twig = new Environment($loader); + + $template = $twig->load('blocks.html.twig'); + $this->assertSame('block from theme 1', $template->renderBlock('b1', [])); + + $template = $twig->load('blocks.html.twig'); + $this->assertSame('block from theme 2', $template->renderBlock('b2', [])); + } + + public function getArrayInheritanceTests() + { + return [ + 'valid array inheritance' => ['array_inheritance_valid_parent.html.twig'], + 'array inheritance with null first template' => ['array_inheritance_null_parent.html.twig'], + 'array inheritance with empty first template' => ['array_inheritance_empty_parent.html.twig'], + 'array inheritance with non-existent first template' => ['array_inheritance_nonexistent_parent.html.twig'], + ]; + } + + /** + * @dataProvider getArrayInheritanceTests + * + * @param $templateName string Template name with array inheritance + */ + public function testArrayInheritance($templateName) + { + $loader = new FilesystemLoader([]); + $loader->addPath(__DIR__.'/Fixtures/inheritance'); + + $twig = new Environment($loader); + + $template = $twig->load($templateName); + $this->assertSame('VALID Child', $template->renderBlock('body', [])); + } + + /** + * @requires PHP 5.3 + */ + public function testLoadTemplateFromPhar() + { + $loader = new FilesystemLoader([]); + // phar-sample.phar was created with the following script: + // $f = new Phar('phar-test.phar'); + // $f->addFromString('hello.twig', 'hello from phar'); + $loader->addPath('phar://'.__DIR__.'/Fixtures/phar/phar-sample.phar'); + $this->assertSame('hello from phar', $loader->getSourceContext('hello.twig')->getCode()); + } + + public function testTemplateExistsAlwaysReturnsBool() + { + $loader = new FilesystemLoader([]); + $this->assertFalse($loader->exists("foo\0.twig")); + $this->assertFalse($loader->exists('../foo.twig')); + $this->assertFalse($loader->exists('@foo')); + $this->assertFalse($loader->exists('foo')); + $this->assertFalse($loader->exists('@foo/bar.twig')); + + $loader->addPath(__DIR__.'/Fixtures/normal'); + $this->assertTrue($loader->exists('index.html')); + $loader->addPath(__DIR__.'/Fixtures/normal', 'foo'); + $this->assertTrue($loader->exists('@foo/index.html')); + } +} diff --git a/vendor/twig/twig/test/Twig/Tests/Loader/Fixtures/inheritance/array_inheritance_empty_parent.html.twig b/vendor/twig/twig/tests/Loader/Fixtures/inheritance/array_inheritance_empty_parent.html.twig similarity index 100% rename from vendor/twig/twig/test/Twig/Tests/Loader/Fixtures/inheritance/array_inheritance_empty_parent.html.twig rename to vendor/twig/twig/tests/Loader/Fixtures/inheritance/array_inheritance_empty_parent.html.twig diff --git a/vendor/twig/twig/test/Twig/Tests/Loader/Fixtures/inheritance/array_inheritance_nonexistent_parent.html.twig b/vendor/twig/twig/tests/Loader/Fixtures/inheritance/array_inheritance_nonexistent_parent.html.twig similarity index 100% rename from vendor/twig/twig/test/Twig/Tests/Loader/Fixtures/inheritance/array_inheritance_nonexistent_parent.html.twig rename to vendor/twig/twig/tests/Loader/Fixtures/inheritance/array_inheritance_nonexistent_parent.html.twig diff --git a/vendor/twig/twig/test/Twig/Tests/Loader/Fixtures/inheritance/array_inheritance_null_parent.html.twig b/vendor/twig/twig/tests/Loader/Fixtures/inheritance/array_inheritance_null_parent.html.twig similarity index 100% rename from vendor/twig/twig/test/Twig/Tests/Loader/Fixtures/inheritance/array_inheritance_null_parent.html.twig rename to vendor/twig/twig/tests/Loader/Fixtures/inheritance/array_inheritance_null_parent.html.twig diff --git a/vendor/twig/twig/test/Twig/Tests/Loader/Fixtures/inheritance/array_inheritance_valid_parent.html.twig b/vendor/twig/twig/tests/Loader/Fixtures/inheritance/array_inheritance_valid_parent.html.twig similarity index 100% rename from vendor/twig/twig/test/Twig/Tests/Loader/Fixtures/inheritance/array_inheritance_valid_parent.html.twig rename to vendor/twig/twig/tests/Loader/Fixtures/inheritance/array_inheritance_valid_parent.html.twig diff --git a/vendor/twig/twig/test/Twig/Tests/Loader/Fixtures/inheritance/parent.html.twig b/vendor/twig/twig/tests/Loader/Fixtures/inheritance/parent.html.twig similarity index 100% rename from vendor/twig/twig/test/Twig/Tests/Loader/Fixtures/inheritance/parent.html.twig rename to vendor/twig/twig/tests/Loader/Fixtures/inheritance/parent.html.twig diff --git a/vendor/twig/twig/test/Twig/Tests/Loader/Fixtures/inheritance/spare_parent.html.twig b/vendor/twig/twig/tests/Loader/Fixtures/inheritance/spare_parent.html.twig similarity index 100% rename from vendor/twig/twig/test/Twig/Tests/Loader/Fixtures/inheritance/spare_parent.html.twig rename to vendor/twig/twig/tests/Loader/Fixtures/inheritance/spare_parent.html.twig diff --git a/vendor/twig/twig/test/Twig/Tests/Loader/Fixtures/named/index.html b/vendor/twig/twig/tests/Loader/Fixtures/named/index.html similarity index 100% rename from vendor/twig/twig/test/Twig/Tests/Loader/Fixtures/named/index.html rename to vendor/twig/twig/tests/Loader/Fixtures/named/index.html diff --git a/vendor/twig/twig/test/Twig/Tests/Loader/Fixtures/named_bis/index.html b/vendor/twig/twig/tests/Loader/Fixtures/named_bis/index.html similarity index 100% rename from vendor/twig/twig/test/Twig/Tests/Loader/Fixtures/named_bis/index.html rename to vendor/twig/twig/tests/Loader/Fixtures/named_bis/index.html diff --git a/vendor/twig/twig/test/Twig/Tests/Loader/Fixtures/named_final/index.html b/vendor/twig/twig/tests/Loader/Fixtures/named_final/index.html similarity index 100% rename from vendor/twig/twig/test/Twig/Tests/Loader/Fixtures/named_final/index.html rename to vendor/twig/twig/tests/Loader/Fixtures/named_final/index.html diff --git a/vendor/twig/twig/test/Twig/Tests/Loader/Fixtures/named_quater/named_absolute.html b/vendor/twig/twig/tests/Loader/Fixtures/named_quater/named_absolute.html similarity index 100% rename from vendor/twig/twig/test/Twig/Tests/Loader/Fixtures/named_quater/named_absolute.html rename to vendor/twig/twig/tests/Loader/Fixtures/named_quater/named_absolute.html diff --git a/vendor/twig/twig/test/Twig/Tests/Loader/Fixtures/named_ter/index.html b/vendor/twig/twig/tests/Loader/Fixtures/named_ter/index.html similarity index 100% rename from vendor/twig/twig/test/Twig/Tests/Loader/Fixtures/named_ter/index.html rename to vendor/twig/twig/tests/Loader/Fixtures/named_ter/index.html diff --git a/vendor/twig/twig/test/Twig/Tests/Loader/Fixtures/normal/index.html b/vendor/twig/twig/tests/Loader/Fixtures/normal/index.html similarity index 100% rename from vendor/twig/twig/test/Twig/Tests/Loader/Fixtures/normal/index.html rename to vendor/twig/twig/tests/Loader/Fixtures/normal/index.html diff --git a/vendor/twig/twig/test/Twig/Tests/Loader/Fixtures/normal_bis/index.html b/vendor/twig/twig/tests/Loader/Fixtures/normal_bis/index.html similarity index 100% rename from vendor/twig/twig/test/Twig/Tests/Loader/Fixtures/normal_bis/index.html rename to vendor/twig/twig/tests/Loader/Fixtures/normal_bis/index.html diff --git a/vendor/twig/twig/test/Twig/Tests/Loader/Fixtures/normal_final/index.html b/vendor/twig/twig/tests/Loader/Fixtures/normal_final/index.html similarity index 100% rename from vendor/twig/twig/test/Twig/Tests/Loader/Fixtures/normal_final/index.html rename to vendor/twig/twig/tests/Loader/Fixtures/normal_final/index.html diff --git a/vendor/twig/twig/test/Twig/Tests/Loader/Fixtures/normal_ter/index.html b/vendor/twig/twig/tests/Loader/Fixtures/normal_ter/index.html similarity index 100% rename from vendor/twig/twig/test/Twig/Tests/Loader/Fixtures/normal_ter/index.html rename to vendor/twig/twig/tests/Loader/Fixtures/normal_ter/index.html diff --git a/vendor/twig/twig/test/Twig/Tests/Loader/Fixtures/phar/phar-sample.phar b/vendor/twig/twig/tests/Loader/Fixtures/phar/phar-sample.phar similarity index 100% rename from vendor/twig/twig/test/Twig/Tests/Loader/Fixtures/phar/phar-sample.phar rename to vendor/twig/twig/tests/Loader/Fixtures/phar/phar-sample.phar diff --git a/vendor/twig/twig/test/Twig/Tests/Loader/Fixtures/themes/theme1/blocks.html.twig b/vendor/twig/twig/tests/Loader/Fixtures/themes/theme1/blocks.html.twig similarity index 100% rename from vendor/twig/twig/test/Twig/Tests/Loader/Fixtures/themes/theme1/blocks.html.twig rename to vendor/twig/twig/tests/Loader/Fixtures/themes/theme1/blocks.html.twig diff --git a/vendor/twig/twig/test/Twig/Tests/Loader/Fixtures/themes/theme2/blocks.html.twig b/vendor/twig/twig/tests/Loader/Fixtures/themes/theme2/blocks.html.twig similarity index 100% rename from vendor/twig/twig/test/Twig/Tests/Loader/Fixtures/themes/theme2/blocks.html.twig rename to vendor/twig/twig/tests/Loader/Fixtures/themes/theme2/blocks.html.twig diff --git a/vendor/twig/twig/test/Twig/Tests/NativeExtensionTest.php b/vendor/twig/twig/tests/NativeExtensionTest.php similarity index 55% rename from vendor/twig/twig/test/Twig/Tests/NativeExtensionTest.php rename to vendor/twig/twig/tests/NativeExtensionTest.php index 50736dc22df78a45298c0b21ffa2b321ccab079f..3399292e386402927b47d7d3633765bf8926d19c 100644 --- a/vendor/twig/twig/test/Twig/Tests/NativeExtensionTest.php +++ b/vendor/twig/twig/tests/NativeExtensionTest.php @@ -1,5 +1,9 @@ <?php +namespace Twig\Tests; + +namespace Twig\Tests; + /* * This file is part of Twig. * @@ -9,21 +13,28 @@ * file that was distributed with this source code. */ -class Twig_Tests_NativeExtensionTest extends \PHPUnit\Framework\TestCase +use Twig\Environment; +use Twig\Loader\ArrayLoader; + +class NativeExtensionTest extends \PHPUnit\Framework\TestCase { /** * @requires PHP 5.3 */ public function testGetProperties() { - $twig = new Twig_Environment(new Twig_Loader_Array(array('index' => '{{ d1.date }}{{ d2.date }}')), array( + if (\PHP_VERSION_ID >= 70000) { + $this->markTestSkipped('Extension is not available on PHP 7+'); + } + + $twig = new Environment(new ArrayLoader(['index' => '{{ d1.date }}{{ d2.date }}']), [ 'debug' => true, 'cache' => false, 'autoescape' => false, - )); + ]); - $d1 = new DateTime(); - $d2 = new DateTime(); + $d1 = new \DateTime(); + $d2 = new \DateTime(); $output = $twig->render('index', compact('d1', 'd2')); // If it fails, PHP will crash. diff --git a/vendor/twig/twig/tests/Node/AutoEscapeTest.php b/vendor/twig/twig/tests/Node/AutoEscapeTest.php new file mode 100644 index 0000000000000000000000000000000000000000..d0f641c083c0b36ee1247c9d738fa2a6e756cd65 --- /dev/null +++ b/vendor/twig/twig/tests/Node/AutoEscapeTest.php @@ -0,0 +1,39 @@ +<?php + +namespace Twig\Tests\Node; + +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use Twig\Node\AutoEscapeNode; +use Twig\Node\Node; +use Twig\Node\TextNode; +use Twig\Test\NodeTestCase; + +class AutoEscapeTest extends NodeTestCase +{ + public function testConstructor() + { + $body = new Node([new TextNode('foo', 1)]); + $node = new AutoEscapeNode(true, $body, 1); + + $this->assertEquals($body, $node->getNode('body')); + $this->assertTrue($node->getAttribute('value')); + } + + public function getTests() + { + $body = new Node([new TextNode('foo', 1)]); + $node = new AutoEscapeNode(true, $body, 1); + + return [ + [$node, "// line 1\necho \"foo\";"], + ]; + } +} diff --git a/vendor/twig/twig/test/Twig/Tests/Node/BlockReferenceTest.php b/vendor/twig/twig/tests/Node/BlockReferenceTest.php similarity index 60% rename from vendor/twig/twig/test/Twig/Tests/Node/BlockReferenceTest.php rename to vendor/twig/twig/tests/Node/BlockReferenceTest.php index 84dac9bfa8326df8f1f1dab1050a92cc085add3a..63dc0707c78bf5673060d03bfd1bc0fd4756554e 100644 --- a/vendor/twig/twig/test/Twig/Tests/Node/BlockReferenceTest.php +++ b/vendor/twig/twig/tests/Node/BlockReferenceTest.php @@ -1,5 +1,7 @@ <?php +namespace Twig\Tests\Node; + /* * This file is part of Twig. * @@ -9,23 +11,26 @@ * file that was distributed with this source code. */ -class Twig_Tests_Node_BlockReferenceTest extends Twig_Test_NodeTestCase +use Twig\Node\BlockReferenceNode; +use Twig\Test\NodeTestCase; + +class BlockReferenceTest extends NodeTestCase { public function testConstructor() { - $node = new Twig_Node_BlockReference('foo', 1); + $node = new BlockReferenceNode('foo', 1); $this->assertEquals('foo', $node->getAttribute('name')); } public function getTests() { - return array( - array(new Twig_Node_BlockReference('foo', 1), <<<EOF + return [ + [new BlockReferenceNode('foo', 1), <<<EOF // line 1 \$this->displayBlock('foo', \$context, \$blocks); EOF - ), - ); + ], + ]; } } diff --git a/vendor/twig/twig/test/Twig/Tests/Node/BlockTest.php b/vendor/twig/twig/tests/Node/BlockTest.php similarity index 50% rename from vendor/twig/twig/test/Twig/Tests/Node/BlockTest.php rename to vendor/twig/twig/tests/Node/BlockTest.php index e7246dcc360d86357dbb56b8b8cd87529368a31d..235cbaf84fd4f830a61b02e8ebf3ce823a97e060 100644 --- a/vendor/twig/twig/test/Twig/Tests/Node/BlockTest.php +++ b/vendor/twig/twig/tests/Node/BlockTest.php @@ -1,5 +1,7 @@ <?php +namespace Twig\Tests\Node; + /* * This file is part of Twig. * @@ -9,12 +11,16 @@ * file that was distributed with this source code. */ -class Twig_Tests_Node_BlockTest extends Twig_Test_NodeTestCase +use Twig\Node\BlockNode; +use Twig\Node\TextNode; +use Twig\Test\NodeTestCase; + +class BlockTest extends NodeTestCase { public function testConstructor() { - $body = new Twig_Node_Text('foo', 1); - $node = new Twig_Node_Block('foo', $body, 1); + $body = new TextNode('foo', 1); + $node = new BlockNode('foo', $body, 1); $this->assertEquals($body, $node->getNode('body')); $this->assertEquals('foo', $node->getAttribute('name')); @@ -22,18 +28,18 @@ class Twig_Tests_Node_BlockTest extends Twig_Test_NodeTestCase public function getTests() { - $body = new Twig_Node_Text('foo', 1); - $node = new Twig_Node_Block('foo', $body, 1); + $body = new TextNode('foo', 1); + $node = new BlockNode('foo', $body, 1); - return array( - array($node, <<<EOF + return [ + [$node, <<<EOF // line 1 -public function block_foo(\$context, array \$blocks = array()) +public function block_foo(\$context, array \$blocks = []) { echo "foo"; } EOF - ), - ); + ], + ]; } } diff --git a/vendor/twig/twig/tests/Node/DeprecatedTest.php b/vendor/twig/twig/tests/Node/DeprecatedTest.php new file mode 100644 index 0000000000000000000000000000000000000000..f4d1cb3b4dafd65d4c069d3cbfadbb6d2c6ba0ae --- /dev/null +++ b/vendor/twig/twig/tests/Node/DeprecatedTest.php @@ -0,0 +1,82 @@ +<?php + +namespace Twig\Tests\Node; + +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use Twig\Environment; +use Twig\Node\DeprecatedNode; +use Twig\Node\Expression\ConstantExpression; +use Twig\Node\Expression\FunctionExpression; +use Twig\Node\IfNode; +use Twig\Node\Node; +use Twig\Test\NodeTestCase; +use Twig\TwigFunction; + +class DeprecatedTest extends NodeTestCase +{ + public function testConstructor() + { + $expr = new ConstantExpression('foo', 1); + $node = new DeprecatedNode($expr, 1); + + $this->assertEquals($expr, $node->getNode('expr')); + } + + public function getTests() + { + $tests = []; + + $expr = new ConstantExpression('This section is deprecated', 1); + $node = new DeprecatedNode($expr, 1, 'deprecated'); + $node->setTemplateName('foo.twig'); + + $tests[] = [$node, <<<EOF +// line 1 +@trigger_error("This section is deprecated"." (\"foo.twig\" at line 1).", E_USER_DEPRECATED); +EOF + ]; + + $t = new Node([ + new ConstantExpression(true, 1), + new DeprecatedNode($expr, 2, 'deprecated'), + ], [], 1); + $node = new IfNode($t, null, 1); + $node->setTemplateName('foo.twig'); + + $tests[] = [$node, <<<EOF +// line 1 +if (true) { + // line 2 + @trigger_error("This section is deprecated"." (\"foo.twig\" at line 2).", E_USER_DEPRECATED); +} +EOF + ]; + + $environment = new Environment($this->createMock('\Twig\Loader\LoaderInterface')); + $environment->addFunction(new TwigFunction('foo', 'foo', [])); + + $expr = new FunctionExpression('foo', new Node(), 1); + $node = new DeprecatedNode($expr, 1, 'deprecated'); + $node->setTemplateName('foo.twig'); + + $compiler = $this->getCompiler($environment); + $varName = $compiler->getVarName(); + + $tests[] = [$node, <<<EOF +// line 1 +\$$varName = foo(); +@trigger_error(\$$varName." (\"foo.twig\" at line 1).", E_USER_DEPRECATED); +EOF + , $environment]; + + return $tests; + } +} diff --git a/vendor/twig/twig/tests/Node/DoTest.php b/vendor/twig/twig/tests/Node/DoTest.php new file mode 100644 index 0000000000000000000000000000000000000000..aaebba5f7952418c486b4b7d163f7fef32483753 --- /dev/null +++ b/vendor/twig/twig/tests/Node/DoTest.php @@ -0,0 +1,38 @@ +<?php + +namespace Twig\Tests\Node; + +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use Twig\Node\DoNode; +use Twig\Node\Expression\ConstantExpression; +use Twig\Test\NodeTestCase; + +class DoTest extends NodeTestCase +{ + public function testConstructor() + { + $expr = new ConstantExpression('foo', 1); + $node = new DoNode($expr, 1); + + $this->assertEquals($expr, $node->getNode('expr')); + } + + public function getTests() + { + $tests = []; + + $expr = new ConstantExpression('foo', 1); + $node = new DoNode($expr, 1); + $tests[] = [$node, "// line 1\n\"foo\";"]; + + return $tests; + } +} diff --git a/vendor/twig/twig/tests/Node/Expression/ArrayTest.php b/vendor/twig/twig/tests/Node/Expression/ArrayTest.php new file mode 100644 index 0000000000000000000000000000000000000000..cfd9c67f3cbd70143b07af929c3565c84cfa2de7 --- /dev/null +++ b/vendor/twig/twig/tests/Node/Expression/ArrayTest.php @@ -0,0 +1,43 @@ +<?php + +namespace Twig\Tests\Node\Expression; + +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use Twig\Node\Expression\ArrayExpression; +use Twig\Node\Expression\ConstantExpression; +use Twig\Test\NodeTestCase; + +class ArrayTest extends NodeTestCase +{ + public function testConstructor() + { + $elements = [new ConstantExpression('foo', 1), $foo = new ConstantExpression('bar', 1)]; + $node = new ArrayExpression($elements, 1); + + $this->assertEquals($foo, $node->getNode(1)); + } + + public function getTests() + { + $elements = [ + new ConstantExpression('foo', 1), + new ConstantExpression('bar', 1), + + new ConstantExpression('bar', 1), + new ConstantExpression('foo', 1), + ]; + $node = new ArrayExpression($elements, 1); + + return [ + [$node, '["foo" => "bar", "bar" => "foo"]'], + ]; + } +} diff --git a/vendor/twig/twig/test/Twig/Tests/Node/Expression/AssignNameTest.php b/vendor/twig/twig/tests/Node/Expression/AssignNameTest.php similarity index 52% rename from vendor/twig/twig/test/Twig/Tests/Node/Expression/AssignNameTest.php rename to vendor/twig/twig/tests/Node/Expression/AssignNameTest.php index bf365de497f483713c74a256531740d143a079d6..80dbe94c6c0b613bf2e48ca8032ffa7526acf572 100644 --- a/vendor/twig/twig/test/Twig/Tests/Node/Expression/AssignNameTest.php +++ b/vendor/twig/twig/tests/Node/Expression/AssignNameTest.php @@ -1,5 +1,7 @@ <?php +namespace Twig\Tests\Node\Expression; + /* * This file is part of Twig. * @@ -9,21 +11,24 @@ * file that was distributed with this source code. */ -class Twig_Tests_Node_Expression_AssignNameTest extends Twig_Test_NodeTestCase +use Twig\Node\Expression\AssignNameExpression; +use Twig\Test\NodeTestCase; + +class AssignNameTest extends NodeTestCase { public function testConstructor() { - $node = new Twig_Node_Expression_AssignName('foo', 1); + $node = new AssignNameExpression('foo', 1); $this->assertEquals('foo', $node->getAttribute('name')); } public function getTests() { - $node = new Twig_Node_Expression_AssignName('foo', 1); + $node = new AssignNameExpression('foo', 1); - return array( - array($node, '$context["foo"]'), - ); + return [ + [$node, '$context["foo"]'], + ]; } } diff --git a/vendor/twig/twig/tests/Node/Expression/Binary/AddTest.php b/vendor/twig/twig/tests/Node/Expression/Binary/AddTest.php new file mode 100644 index 0000000000000000000000000000000000000000..5cff2bcff1de1599964c151722f360f81ac39bd3 --- /dev/null +++ b/vendor/twig/twig/tests/Node/Expression/Binary/AddTest.php @@ -0,0 +1,40 @@ +<?php + +namespace Twig\Tests\Node\Expression\Binary; + +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use Twig\Node\Expression\Binary\AddBinary; +use Twig\Node\Expression\ConstantExpression; +use Twig\Test\NodeTestCase; + +class AddTest extends NodeTestCase +{ + public function testConstructor() + { + $left = new ConstantExpression(1, 1); + $right = new ConstantExpression(2, 1); + $node = new AddBinary($left, $right, 1); + + $this->assertEquals($left, $node->getNode('left')); + $this->assertEquals($right, $node->getNode('right')); + } + + public function getTests() + { + $left = new ConstantExpression(1, 1); + $right = new ConstantExpression(2, 1); + $node = new AddBinary($left, $right, 1); + + return [ + [$node, '(1 + 2)'], + ]; + } +} diff --git a/vendor/twig/twig/tests/Node/Expression/Binary/AndTest.php b/vendor/twig/twig/tests/Node/Expression/Binary/AndTest.php new file mode 100644 index 0000000000000000000000000000000000000000..d83aed04d964c73aed57cdbbf379c35471b26f4d --- /dev/null +++ b/vendor/twig/twig/tests/Node/Expression/Binary/AndTest.php @@ -0,0 +1,40 @@ +<?php + +namespace Twig\Tests\Node\Expression\Binary; + +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use Twig\Node\Expression\Binary\AndBinary; +use Twig\Node\Expression\ConstantExpression; +use Twig\Test\NodeTestCase; + +class AndTest extends NodeTestCase +{ + public function testConstructor() + { + $left = new ConstantExpression(1, 1); + $right = new ConstantExpression(2, 1); + $node = new AndBinary($left, $right, 1); + + $this->assertEquals($left, $node->getNode('left')); + $this->assertEquals($right, $node->getNode('right')); + } + + public function getTests() + { + $left = new ConstantExpression(1, 1); + $right = new ConstantExpression(2, 1); + $node = new AndBinary($left, $right, 1); + + return [ + [$node, '(1 && 2)'], + ]; + } +} diff --git a/vendor/twig/twig/tests/Node/Expression/Binary/ConcatTest.php b/vendor/twig/twig/tests/Node/Expression/Binary/ConcatTest.php new file mode 100644 index 0000000000000000000000000000000000000000..0eff603ba282a8bcf23d18435c6095c4a9f99fb5 --- /dev/null +++ b/vendor/twig/twig/tests/Node/Expression/Binary/ConcatTest.php @@ -0,0 +1,40 @@ +<?php + +namespace Twig\Tests\Node\Expression\Binary; + +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use Twig\Node\Expression\Binary\ConcatBinary; +use Twig\Node\Expression\ConstantExpression; +use Twig\Test\NodeTestCase; + +class ConcatTest extends NodeTestCase +{ + public function testConstructor() + { + $left = new ConstantExpression(1, 1); + $right = new ConstantExpression(2, 1); + $node = new ConcatBinary($left, $right, 1); + + $this->assertEquals($left, $node->getNode('left')); + $this->assertEquals($right, $node->getNode('right')); + } + + public function getTests() + { + $left = new ConstantExpression(1, 1); + $right = new ConstantExpression(2, 1); + $node = new ConcatBinary($left, $right, 1); + + return [ + [$node, '(1 . 2)'], + ]; + } +} diff --git a/vendor/twig/twig/tests/Node/Expression/Binary/DivTest.php b/vendor/twig/twig/tests/Node/Expression/Binary/DivTest.php new file mode 100644 index 0000000000000000000000000000000000000000..20cf4646f850e1f922d4aa9bf48627805f5fe623 --- /dev/null +++ b/vendor/twig/twig/tests/Node/Expression/Binary/DivTest.php @@ -0,0 +1,40 @@ +<?php + +namespace Twig\Tests\Node\Expression\Binary; + +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use Twig\Node\Expression\Binary\DivBinary; +use Twig\Node\Expression\ConstantExpression; +use Twig\Test\NodeTestCase; + +class DivTest extends NodeTestCase +{ + public function testConstructor() + { + $left = new ConstantExpression(1, 1); + $right = new ConstantExpression(2, 1); + $node = new DivBinary($left, $right, 1); + + $this->assertEquals($left, $node->getNode('left')); + $this->assertEquals($right, $node->getNode('right')); + } + + public function getTests() + { + $left = new ConstantExpression(1, 1); + $right = new ConstantExpression(2, 1); + $node = new DivBinary($left, $right, 1); + + return [ + [$node, '(1 / 2)'], + ]; + } +} diff --git a/vendor/twig/twig/tests/Node/Expression/Binary/FloorDivTest.php b/vendor/twig/twig/tests/Node/Expression/Binary/FloorDivTest.php new file mode 100644 index 0000000000000000000000000000000000000000..826859851bbb97b4e285bf3c7560a434e7e65ae0 --- /dev/null +++ b/vendor/twig/twig/tests/Node/Expression/Binary/FloorDivTest.php @@ -0,0 +1,40 @@ +<?php + +namespace Twig\Tests\Node\Expression\Binary; + +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use Twig\Node\Expression\Binary\FloorDivBinary; +use Twig\Node\Expression\ConstantExpression; +use Twig\Test\NodeTestCase; + +class FloorDivTest extends NodeTestCase +{ + public function testConstructor() + { + $left = new ConstantExpression(1, 1); + $right = new ConstantExpression(2, 1); + $node = new FloorDivBinary($left, $right, 1); + + $this->assertEquals($left, $node->getNode('left')); + $this->assertEquals($right, $node->getNode('right')); + } + + public function getTests() + { + $left = new ConstantExpression(1, 1); + $right = new ConstantExpression(2, 1); + $node = new FloorDivBinary($left, $right, 1); + + return [ + [$node, '(int) floor((1 / 2))'], + ]; + } +} diff --git a/vendor/twig/twig/tests/Node/Expression/Binary/ModTest.php b/vendor/twig/twig/tests/Node/Expression/Binary/ModTest.php new file mode 100644 index 0000000000000000000000000000000000000000..2069ef08950d31b313e09d4710f2ca3094bd7cc1 --- /dev/null +++ b/vendor/twig/twig/tests/Node/Expression/Binary/ModTest.php @@ -0,0 +1,40 @@ +<?php + +namespace Twig\Tests\Node\Expression\Binary; + +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use Twig\Node\Expression\Binary\ModBinary; +use Twig\Node\Expression\ConstantExpression; +use Twig\Test\NodeTestCase; + +class ModTest extends NodeTestCase +{ + public function testConstructor() + { + $left = new ConstantExpression(1, 1); + $right = new ConstantExpression(2, 1); + $node = new ModBinary($left, $right, 1); + + $this->assertEquals($left, $node->getNode('left')); + $this->assertEquals($right, $node->getNode('right')); + } + + public function getTests() + { + $left = new ConstantExpression(1, 1); + $right = new ConstantExpression(2, 1); + $node = new ModBinary($left, $right, 1); + + return [ + [$node, '(1 % 2)'], + ]; + } +} diff --git a/vendor/twig/twig/tests/Node/Expression/Binary/MulTest.php b/vendor/twig/twig/tests/Node/Expression/Binary/MulTest.php new file mode 100644 index 0000000000000000000000000000000000000000..c50dfc12b1bb35e04b78dfdedb9513b266c0934d --- /dev/null +++ b/vendor/twig/twig/tests/Node/Expression/Binary/MulTest.php @@ -0,0 +1,40 @@ +<?php + +namespace Twig\Tests\Node\Expression\Binary; + +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use Twig\Node\Expression\Binary\MulBinary; +use Twig\Node\Expression\ConstantExpression; +use Twig\Test\NodeTestCase; + +class MulTest extends NodeTestCase +{ + public function testConstructor() + { + $left = new ConstantExpression(1, 1); + $right = new ConstantExpression(2, 1); + $node = new MulBinary($left, $right, 1); + + $this->assertEquals($left, $node->getNode('left')); + $this->assertEquals($right, $node->getNode('right')); + } + + public function getTests() + { + $left = new ConstantExpression(1, 1); + $right = new ConstantExpression(2, 1); + $node = new MulBinary($left, $right, 1); + + return [ + [$node, '(1 * 2)'], + ]; + } +} diff --git a/vendor/twig/twig/tests/Node/Expression/Binary/OrTest.php b/vendor/twig/twig/tests/Node/Expression/Binary/OrTest.php new file mode 100644 index 0000000000000000000000000000000000000000..94df7c0b165fa2e1451117c1d25301a77a77fe1c --- /dev/null +++ b/vendor/twig/twig/tests/Node/Expression/Binary/OrTest.php @@ -0,0 +1,40 @@ +<?php + +namespace Twig\Tests\Node\Expression\Binary; + +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use Twig\Node\Expression\Binary\OrBinary; +use Twig\Node\Expression\ConstantExpression; +use Twig\Test\NodeTestCase; + +class OrTest extends NodeTestCase +{ + public function testConstructor() + { + $left = new ConstantExpression(1, 1); + $right = new ConstantExpression(2, 1); + $node = new OrBinary($left, $right, 1); + + $this->assertEquals($left, $node->getNode('left')); + $this->assertEquals($right, $node->getNode('right')); + } + + public function getTests() + { + $left = new ConstantExpression(1, 1); + $right = new ConstantExpression(2, 1); + $node = new OrBinary($left, $right, 1); + + return [ + [$node, '(1 || 2)'], + ]; + } +} diff --git a/vendor/twig/twig/tests/Node/Expression/Binary/SubTest.php b/vendor/twig/twig/tests/Node/Expression/Binary/SubTest.php new file mode 100644 index 0000000000000000000000000000000000000000..04eebe290d601466b1d73cc5de3ab870cbd472ae --- /dev/null +++ b/vendor/twig/twig/tests/Node/Expression/Binary/SubTest.php @@ -0,0 +1,40 @@ +<?php + +namespace Twig\Tests\Node\Expression\Binary; + +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use Twig\Node\Expression\Binary\SubBinary; +use Twig\Node\Expression\ConstantExpression; +use Twig\Test\NodeTestCase; + +class SubTest extends NodeTestCase +{ + public function testConstructor() + { + $left = new ConstantExpression(1, 1); + $right = new ConstantExpression(2, 1); + $node = new SubBinary($left, $right, 1); + + $this->assertEquals($left, $node->getNode('left')); + $this->assertEquals($right, $node->getNode('right')); + } + + public function getTests() + { + $left = new ConstantExpression(1, 1); + $right = new ConstantExpression(2, 1); + $node = new SubBinary($left, $right, 1); + + return [ + [$node, '(1 - 2)'], + ]; + } +} diff --git a/vendor/twig/twig/tests/Node/Expression/CallTest.php b/vendor/twig/twig/tests/Node/Expression/CallTest.php new file mode 100644 index 0000000000000000000000000000000000000000..1ffb4c7b6f46e4bf9cf375e2a96a4a5a5830c143 --- /dev/null +++ b/vendor/twig/twig/tests/Node/Expression/CallTest.php @@ -0,0 +1,139 @@ +<?php + +namespace Twig\Tests\Node\Expression; + +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use Twig\Node\Expression\CallExpression; + +class CallTest extends \PHPUnit\Framework\TestCase +{ + public function testGetArguments() + { + $node = new Node_Expression_Call([], ['type' => 'function', 'name' => 'date']); + $this->assertEquals(['U', null], $node->getArguments('date', ['format' => 'U', 'timestamp' => null])); + } + + public function testGetArgumentsWhenPositionalArgumentsAfterNamedArguments() + { + $this->expectException('\Twig\Error\SyntaxError'); + $this->expectExceptionMessage('Positional arguments cannot be used after named arguments for function "date".'); + + $node = new Node_Expression_Call([], ['type' => 'function', 'name' => 'date']); + $node->getArguments('date', ['timestamp' => 123456, 'Y-m-d']); + } + + public function testGetArgumentsWhenArgumentIsDefinedTwice() + { + $this->expectException('\Twig\Error\SyntaxError'); + $this->expectExceptionMessage('Argument "format" is defined twice for function "date".'); + + $node = new Node_Expression_Call([], ['type' => 'function', 'name' => 'date']); + $node->getArguments('date', ['Y-m-d', 'format' => 'U']); + } + + public function testGetArgumentsWithWrongNamedArgumentName() + { + $this->expectException('\Twig\Error\SyntaxError'); + $this->expectExceptionMessage('Unknown argument "unknown" for function "date(format, timestamp)".'); + + $node = new Node_Expression_Call([], ['type' => 'function', 'name' => 'date']); + $node->getArguments('date', ['Y-m-d', 'timestamp' => null, 'unknown' => '']); + } + + public function testGetArgumentsWithWrongNamedArgumentNames() + { + $this->expectException('\Twig\Error\SyntaxError'); + $this->expectExceptionMessage('Unknown arguments "unknown1", "unknown2" for function "date(format, timestamp)".'); + + $node = new Node_Expression_Call([], ['type' => 'function', 'name' => 'date']); + $node->getArguments('date', ['Y-m-d', 'timestamp' => null, 'unknown1' => '', 'unknown2' => '']); + } + + public function testResolveArgumentsWithMissingValueForOptionalArgument() + { + $this->expectException('\Twig\Error\SyntaxError'); + $this->expectExceptionMessage('Argument "case_sensitivity" could not be assigned for function "substr_compare(main_str, str, offset, length, case_sensitivity)" because it is mapped to an internal PHP function which cannot determine default value for optional argument "length".'); + + $node = new Node_Expression_Call([], ['type' => 'function', 'name' => 'substr_compare']); + $node->getArguments('substr_compare', ['abcd', 'bc', 'offset' => 1, 'case_sensitivity' => true]); + } + + public function testResolveArgumentsOnlyNecessaryArgumentsForCustomFunction() + { + $node = new Node_Expression_Call([], ['type' => 'function', 'name' => 'custom_function']); + + $this->assertEquals(['arg1'], $node->getArguments([$this, 'customFunction'], ['arg1' => 'arg1'])); + } + + public function testGetArgumentsForStaticMethod() + { + $node = new Node_Expression_Call([], ['type' => 'function', 'name' => 'custom_static_function']); + $this->assertEquals(['arg1'], $node->getArguments(__CLASS__.'::customStaticFunction', ['arg1' => 'arg1'])); + } + + public function testResolveArgumentsWithMissingParameterForArbitraryArguments() + { + $this->expectException('\LogicException'); + $this->expectExceptionMessage('The last parameter of "Twig\\Tests\\Node\\Expression\\CallTest::customFunctionWithArbitraryArguments" for function "foo" must be an array with default value, eg. "array $arg = []".'); + + $node = new Node_Expression_Call([], ['type' => 'function', 'name' => 'foo', 'is_variadic' => true]); + $node->getArguments([$this, 'customFunctionWithArbitraryArguments'], []); + } + + public static function customStaticFunction($arg1, $arg2 = 'default', $arg3 = []) + { + } + + public function customFunction($arg1, $arg2 = 'default', $arg3 = []) + { + } + + public function customFunctionWithArbitraryArguments() + { + } + + public function testResolveArgumentsWithMissingParameterForArbitraryArgumentsOnFunction() + { + $this->expectException('\LogicException'); + $this->expectExceptionMessageRegExp('#^The last parameter of "Twig\\\\Tests\\\\Node\\\\Expression\\\\custom_Twig_Tests_Node_Expression_CallTest_function" for function "foo" must be an array with default value, eg\\. "array \\$arg \\= \\[\\]"\\.$#'); + + $node = new Node_Expression_Call([], ['type' => 'function', 'name' => 'foo', 'is_variadic' => true]); + $node->getArguments('Twig\Tests\Node\Expression\custom_Twig_Tests_Node_Expression_CallTest_function', []); + } + + public function testResolveArgumentsWithMissingParameterForArbitraryArgumentsOnObject() + { + $this->expectException('\LogicException'); + $this->expectExceptionMessageRegExp('#^The last parameter of "Twig\\\\Tests\\\\Node\\\\Expression\\\\CallableTestClass\\:\\:__invoke" for function "foo" must be an array with default value, eg\\. "array \\$arg \\= \\[\\]"\\.$#'); + + $node = new Node_Expression_Call([], ['type' => 'function', 'name' => 'foo', 'is_variadic' => true]); + $node->getArguments(new CallableTestClass(), []); + } +} + +class Node_Expression_Call extends CallExpression +{ + public function getArguments($callable, $arguments) + { + return parent::getArguments($callable, $arguments); + } +} + +class CallableTestClass +{ + public function __invoke($required) + { + } +} + +function custom_Twig_Tests_Node_Expression_CallTest_function($required) +{ +} diff --git a/vendor/twig/twig/tests/Node/Expression/ConditionalTest.php b/vendor/twig/twig/tests/Node/Expression/ConditionalTest.php new file mode 100644 index 0000000000000000000000000000000000000000..004e9c9513e894d4a730f2ebaa822b47b3a75249 --- /dev/null +++ b/vendor/twig/twig/tests/Node/Expression/ConditionalTest.php @@ -0,0 +1,44 @@ +<?php + +namespace Twig\Tests\Node\Expression; + +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use Twig\Node\Expression\ConditionalExpression; +use Twig\Node\Expression\ConstantExpression; +use Twig\Test\NodeTestCase; + +class ConditionalTest extends NodeTestCase +{ + public function testConstructor() + { + $expr1 = new ConstantExpression(1, 1); + $expr2 = new ConstantExpression(2, 1); + $expr3 = new ConstantExpression(3, 1); + $node = new ConditionalExpression($expr1, $expr2, $expr3, 1); + + $this->assertEquals($expr1, $node->getNode('expr1')); + $this->assertEquals($expr2, $node->getNode('expr2')); + $this->assertEquals($expr3, $node->getNode('expr3')); + } + + public function getTests() + { + $tests = []; + + $expr1 = new ConstantExpression(1, 1); + $expr2 = new ConstantExpression(2, 1); + $expr3 = new ConstantExpression(3, 1); + $node = new ConditionalExpression($expr1, $expr2, $expr3, 1); + $tests[] = [$node, '((1) ? (2) : (3))']; + + return $tests; + } +} diff --git a/vendor/twig/twig/test/Twig/Tests/Node/Expression/ConstantTest.php b/vendor/twig/twig/tests/Node/Expression/ConstantTest.php similarity index 55% rename from vendor/twig/twig/test/Twig/Tests/Node/Expression/ConstantTest.php rename to vendor/twig/twig/tests/Node/Expression/ConstantTest.php index 2ff9318229e6f8c8f3721e744d0675278fe9caca..920892e942d5f58bcbe7528bee50db5496c9c467 100644 --- a/vendor/twig/twig/test/Twig/Tests/Node/Expression/ConstantTest.php +++ b/vendor/twig/twig/tests/Node/Expression/ConstantTest.php @@ -1,5 +1,7 @@ <?php +namespace Twig\Tests\Node\Expression; + /* * This file is part of Twig. * @@ -9,21 +11,24 @@ * file that was distributed with this source code. */ -class Twig_Tests_Node_Expression_ConstantTest extends Twig_Test_NodeTestCase +use Twig\Node\Expression\ConstantExpression; +use Twig\Test\NodeTestCase; + +class ConstantTest extends NodeTestCase { public function testConstructor() { - $node = new Twig_Node_Expression_Constant('foo', 1); + $node = new ConstantExpression('foo', 1); $this->assertEquals('foo', $node->getAttribute('value')); } public function getTests() { - $tests = array(); + $tests = []; - $node = new Twig_Node_Expression_Constant('foo', 1); - $tests[] = array($node, '"foo"'); + $node = new ConstantExpression('foo', 1); + $tests[] = [$node, '"foo"']; return $tests; } diff --git a/vendor/twig/twig/tests/Node/Expression/FilterTest.php b/vendor/twig/twig/tests/Node/Expression/FilterTest.php new file mode 100644 index 0000000000000000000000000000000000000000..d7e38f3171d2d03047591160d3e767c51edc1906 --- /dev/null +++ b/vendor/twig/twig/tests/Node/Expression/FilterTest.php @@ -0,0 +1,161 @@ +<?php + +namespace Twig\Tests\Node\Expression; + +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use Twig\Environment; +use Twig\Node\Expression\ConstantExpression; +use Twig\Node\Expression\FilterExpression; +use Twig\Node\Node; +use Twig\Test\NodeTestCase; +use Twig\TwigFilter; + +class FilterTest extends NodeTestCase +{ + public function testConstructor() + { + $expr = new ConstantExpression('foo', 1); + $name = new ConstantExpression('upper', 1); + $args = new Node(); + $node = new FilterExpression($expr, $name, $args, 1); + + $this->assertEquals($expr, $node->getNode('node')); + $this->assertEquals($name, $node->getNode('filter')); + $this->assertEquals($args, $node->getNode('arguments')); + } + + public function getTests() + { + $environment = new Environment($this->createMock('\Twig\Loader\LoaderInterface')); + $environment->addFilter(new TwigFilter('bar', 'bar', ['needs_environment' => true])); + $environment->addFilter(new TwigFilter('barbar', 'Twig\Tests\Node\Expression\twig_tests_filter_barbar', ['needs_context' => true, 'is_variadic' => true])); + + $tests = []; + + $expr = new ConstantExpression('foo', 1); + $node = $this->createFilter($expr, 'upper'); + $node = $this->createFilter($node, 'number_format', [new ConstantExpression(2, 1), new ConstantExpression('.', 1), new ConstantExpression(',', 1)]); + + if (\function_exists('mb_get_info')) { + $tests[] = [$node, 'twig_number_format_filter($this->env, twig_upper_filter($this->env, "foo"), 2, ".", ",")']; + } else { + $tests[] = [$node, 'twig_number_format_filter($this->env, strtoupper("foo"), 2, ".", ",")']; + } + + // named arguments + $date = new ConstantExpression(0, 1); + $node = $this->createFilter($date, 'date', [ + 'timezone' => new ConstantExpression('America/Chicago', 1), + 'format' => new ConstantExpression('d/m/Y H:i:s P', 1), + ]); + $tests[] = [$node, 'twig_date_format_filter($this->env, 0, "d/m/Y H:i:s P", "America/Chicago")']; + + // skip an optional argument + $date = new ConstantExpression(0, 1); + $node = $this->createFilter($date, 'date', [ + 'timezone' => new ConstantExpression('America/Chicago', 1), + ]); + $tests[] = [$node, 'twig_date_format_filter($this->env, 0, null, "America/Chicago")']; + + // underscores vs camelCase for named arguments + $string = new ConstantExpression('abc', 1); + $node = $this->createFilter($string, 'reverse', [ + 'preserve_keys' => new ConstantExpression(true, 1), + ]); + $tests[] = [$node, 'twig_reverse_filter($this->env, "abc", true)']; + $node = $this->createFilter($string, 'reverse', [ + 'preserveKeys' => new ConstantExpression(true, 1), + ]); + $tests[] = [$node, 'twig_reverse_filter($this->env, "abc", true)']; + + // filter as an anonymous function + if (\PHP_VERSION_ID >= 50300) { + $node = $this->createFilter(new ConstantExpression('foo', 1), 'anonymous'); + $tests[] = [$node, 'call_user_func_array($this->env->getFilter(\'anonymous\')->getCallable(), ["foo"])']; + } + + // needs environment + $node = $this->createFilter($string, 'bar'); + $tests[] = [$node, 'bar($this->env, "abc")', $environment]; + + $node = $this->createFilter($string, 'bar', [new ConstantExpression('bar', 1)]); + $tests[] = [$node, 'bar($this->env, "abc", "bar")', $environment]; + + // arbitrary named arguments + $node = $this->createFilter($string, 'barbar'); + $tests[] = [$node, 'Twig\Tests\Node\Expression\twig_tests_filter_barbar($context, "abc")', $environment]; + + $node = $this->createFilter($string, 'barbar', ['foo' => new ConstantExpression('bar', 1)]); + $tests[] = [$node, 'Twig\Tests\Node\Expression\twig_tests_filter_barbar($context, "abc", null, null, ["foo" => "bar"])', $environment]; + + $node = $this->createFilter($string, 'barbar', ['arg2' => new ConstantExpression('bar', 1)]); + $tests[] = [$node, 'Twig\Tests\Node\Expression\twig_tests_filter_barbar($context, "abc", null, "bar")', $environment]; + + $node = $this->createFilter($string, 'barbar', [ + new ConstantExpression('1', 1), + new ConstantExpression('2', 1), + new ConstantExpression('3', 1), + 'foo' => new ConstantExpression('bar', 1), + ]); + $tests[] = [$node, 'Twig\Tests\Node\Expression\twig_tests_filter_barbar($context, "abc", "1", "2", [0 => "3", "foo" => "bar"])', $environment]; + + return $tests; + } + + public function testCompileWithWrongNamedArgumentName() + { + $this->expectException('\Twig\Error\SyntaxError'); + $this->expectExceptionMessage('Unknown argument "foobar" for filter "date(format, timezone)" at line 1.'); + + $date = new ConstantExpression(0, 1); + $node = $this->createFilter($date, 'date', [ + 'foobar' => new ConstantExpression('America/Chicago', 1), + ]); + + $compiler = $this->getCompiler(); + $compiler->compile($node); + } + + public function testCompileWithMissingNamedArgument() + { + $this->expectException('\Twig\Error\SyntaxError'); + $this->expectExceptionMessage('Value for argument "from" is required for filter "replace" at line 1.'); + + $value = new ConstantExpression(0, 1); + $node = $this->createFilter($value, 'replace', [ + 'to' => new ConstantExpression('foo', 1), + ]); + + $compiler = $this->getCompiler(); + $compiler->compile($node); + } + + protected function createFilter($node, $name, array $arguments = []) + { + $name = new ConstantExpression($name, 1); + $arguments = new Node($arguments); + + return new FilterExpression($node, $name, $arguments, 1); + } + + protected function getEnvironment() + { + if (\PHP_VERSION_ID >= 50300) { + return include 'PHP53/FilterInclude.php'; + } + + return parent::getEnvironment(); + } +} + +function twig_tests_filter_barbar($context, $string, $arg1 = null, $arg2 = null, array $args = []) +{ +} diff --git a/vendor/twig/twig/tests/Node/Expression/FunctionTest.php b/vendor/twig/twig/tests/Node/Expression/FunctionTest.php new file mode 100644 index 0000000000000000000000000000000000000000..489f17ab41d5d77de305f3026062f45cd871353d --- /dev/null +++ b/vendor/twig/twig/tests/Node/Expression/FunctionTest.php @@ -0,0 +1,119 @@ +<?php + +namespace Twig\Tests\Node\Expression; + +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use Twig\Environment; +use Twig\Node\Expression\ConstantExpression; +use Twig\Node\Expression\FunctionExpression; +use Twig\Node\Node; +use Twig\Test\NodeTestCase; +use Twig\TwigFunction; + +class FunctionTest extends NodeTestCase +{ + public function testConstructor() + { + $name = 'function'; + $args = new Node(); + $node = new FunctionExpression($name, $args, 1); + + $this->assertEquals($name, $node->getAttribute('name')); + $this->assertEquals($args, $node->getNode('arguments')); + } + + public function getTests() + { + $environment = new Environment($this->createMock('\Twig\Loader\LoaderInterface')); + $environment->addFunction(new TwigFunction('foo', 'foo', [])); + $environment->addFunction(new TwigFunction('bar', 'bar', ['needs_environment' => true])); + $environment->addFunction(new TwigFunction('foofoo', 'foofoo', ['needs_context' => true])); + $environment->addFunction(new TwigFunction('foobar', 'foobar', ['needs_environment' => true, 'needs_context' => true])); + $environment->addFunction(new TwigFunction('barbar', 'Twig\Tests\Node\Expression\twig_tests_function_barbar', ['is_variadic' => true])); + + $tests = []; + + $node = $this->createFunction('foo'); + $tests[] = [$node, 'foo()', $environment]; + + $node = $this->createFunction('foo', [new ConstantExpression('bar', 1), new ConstantExpression('foobar', 1)]); + $tests[] = [$node, 'foo("bar", "foobar")', $environment]; + + $node = $this->createFunction('bar'); + $tests[] = [$node, 'bar($this->env)', $environment]; + + $node = $this->createFunction('bar', [new ConstantExpression('bar', 1)]); + $tests[] = [$node, 'bar($this->env, "bar")', $environment]; + + $node = $this->createFunction('foofoo'); + $tests[] = [$node, 'foofoo($context)', $environment]; + + $node = $this->createFunction('foofoo', [new ConstantExpression('bar', 1)]); + $tests[] = [$node, 'foofoo($context, "bar")', $environment]; + + $node = $this->createFunction('foobar'); + $tests[] = [$node, 'foobar($this->env, $context)', $environment]; + + $node = $this->createFunction('foobar', [new ConstantExpression('bar', 1)]); + $tests[] = [$node, 'foobar($this->env, $context, "bar")', $environment]; + + // named arguments + $node = $this->createFunction('date', [ + 'timezone' => new ConstantExpression('America/Chicago', 1), + 'date' => new ConstantExpression(0, 1), + ]); + $tests[] = [$node, 'twig_date_converter($this->env, 0, "America/Chicago")']; + + // arbitrary named arguments + $node = $this->createFunction('barbar'); + $tests[] = [$node, 'Twig\Tests\Node\Expression\twig_tests_function_barbar()', $environment]; + + $node = $this->createFunction('barbar', ['foo' => new ConstantExpression('bar', 1)]); + $tests[] = [$node, 'Twig\Tests\Node\Expression\twig_tests_function_barbar(null, null, ["foo" => "bar"])', $environment]; + + $node = $this->createFunction('barbar', ['arg2' => new ConstantExpression('bar', 1)]); + $tests[] = [$node, 'Twig\Tests\Node\Expression\twig_tests_function_barbar(null, "bar")', $environment]; + + $node = $this->createFunction('barbar', [ + new ConstantExpression('1', 1), + new ConstantExpression('2', 1), + new ConstantExpression('3', 1), + 'foo' => new ConstantExpression('bar', 1), + ]); + $tests[] = [$node, 'Twig\Tests\Node\Expression\twig_tests_function_barbar("1", "2", [0 => "3", "foo" => "bar"])', $environment]; + + // function as an anonymous function + if (\PHP_VERSION_ID >= 50300) { + $node = $this->createFunction('anonymous', [new ConstantExpression('foo', 1)]); + $tests[] = [$node, 'call_user_func_array($this->env->getFunction(\'anonymous\')->getCallable(), ["foo"])']; + } + + return $tests; + } + + protected function createFunction($name, array $arguments = []) + { + return new FunctionExpression($name, new Node($arguments), 1); + } + + protected function getEnvironment() + { + if (\PHP_VERSION_ID >= 50300) { + return include 'PHP53/FunctionInclude.php'; + } + + return parent::getEnvironment(); + } +} + +function twig_tests_function_barbar($arg1 = null, $arg2 = null, array $args = []) +{ +} diff --git a/vendor/twig/twig/tests/Node/Expression/GetAttrTest.php b/vendor/twig/twig/tests/Node/Expression/GetAttrTest.php new file mode 100644 index 0000000000000000000000000000000000000000..5f9a0a79d86f2f2d42d082ec257d4388ba3c6185 --- /dev/null +++ b/vendor/twig/twig/tests/Node/Expression/GetAttrTest.php @@ -0,0 +1,59 @@ +<?php + +namespace Twig\Tests\Node\Expression; + +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use Twig\Node\Expression\ArrayExpression; +use Twig\Node\Expression\ConstantExpression; +use Twig\Node\Expression\GetAttrExpression; +use Twig\Node\Expression\NameExpression; +use Twig\Template; +use Twig\Test\NodeTestCase; + +class GetAttrTest extends NodeTestCase +{ + public function testConstructor() + { + $expr = new NameExpression('foo', 1); + $attr = new ConstantExpression('bar', 1); + $args = new ArrayExpression([], 1); + $args->addElement(new NameExpression('foo', 1)); + $args->addElement(new ConstantExpression('bar', 1)); + $node = new GetAttrExpression($expr, $attr, $args, Template::ARRAY_CALL, 1); + + $this->assertEquals($expr, $node->getNode('node')); + $this->assertEquals($attr, $node->getNode('attribute')); + $this->assertEquals($args, $node->getNode('arguments')); + $this->assertEquals(Template::ARRAY_CALL, $node->getAttribute('type')); + } + + public function getTests() + { + $tests = []; + + $expr = new NameExpression('foo', 1); + $attr = new ConstantExpression('bar', 1); + $args = new ArrayExpression([], 1); + $node = new GetAttrExpression($expr, $attr, $args, Template::ANY_CALL, 1); + $tests[] = [$node, sprintf('%s%s, "bar", [])', $this->getAttributeGetter(), $this->getVariableGetter('foo', 1))]; + + $node = new GetAttrExpression($expr, $attr, $args, Template::ARRAY_CALL, 1); + $tests[] = [$node, sprintf('%s%s, "bar", [], "array")', $this->getAttributeGetter(), $this->getVariableGetter('foo', 1))]; + + $args = new ArrayExpression([], 1); + $args->addElement(new NameExpression('foo', 1)); + $args->addElement(new ConstantExpression('bar', 1)); + $node = new GetAttrExpression($expr, $attr, $args, Template::METHOD_CALL, 1); + $tests[] = [$node, sprintf('%s%s, "bar", [0 => %s, 1 => "bar"], "method")', $this->getAttributeGetter(), $this->getVariableGetter('foo', 1), $this->getVariableGetter('foo'))]; + + return $tests; + } +} diff --git a/vendor/twig/twig/tests/Node/Expression/NameTest.php b/vendor/twig/twig/tests/Node/Expression/NameTest.php new file mode 100644 index 0000000000000000000000000000000000000000..738f28ae04941e4173f2b59b1cb8383292196060 --- /dev/null +++ b/vendor/twig/twig/tests/Node/Expression/NameTest.php @@ -0,0 +1,49 @@ +<?php + +namespace Twig\Tests\Node\Expression; + +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use Twig\Environment; +use Twig\Node\Expression\NameExpression; +use Twig\Test\NodeTestCase; + +class NameTest extends NodeTestCase +{ + public function testConstructor() + { + $node = new NameExpression('foo', 1); + + $this->assertEquals('foo', $node->getAttribute('name')); + } + + public function getTests() + { + $node = new NameExpression('foo', 1); + $context = new NameExpression('_context', 1); + + $env = new Environment($this->createMock('\Twig\Loader\LoaderInterface'), ['strict_variables' => true]); + $env1 = new Environment($this->createMock('\Twig\Loader\LoaderInterface'), ['strict_variables' => false]); + + if (\PHP_VERSION_ID >= 70000) { + $output = '($context["foo"] ?? $this->getContext($context, "foo"))'; + } elseif (\PHP_VERSION_ID >= 50400) { + $output = '(isset($context["foo"]) ? $context["foo"] : $this->getContext($context, "foo"))'; + } else { + $output = '$this->getContext($context, "foo")'; + } + + return [ + [$node, "// line 1\n".$output, $env], + [$node, $this->getVariableGetter('foo', 1), $env1], + [$context, "// line 1\n\$context"], + ]; + } +} diff --git a/vendor/twig/twig/tests/Node/Expression/NullCoalesceTest.php b/vendor/twig/twig/tests/Node/Expression/NullCoalesceTest.php new file mode 100644 index 0000000000000000000000000000000000000000..bbfff5763baa11755a1fb22a0e74b6fa4cf61ab8 --- /dev/null +++ b/vendor/twig/twig/tests/Node/Expression/NullCoalesceTest.php @@ -0,0 +1,38 @@ +<?php + +namespace Twig\Tests\Node\Expression; + +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use Twig\Node\Expression\ConstantExpression; +use Twig\Node\Expression\NameExpression; +use Twig\Node\Expression\NullCoalesceExpression; +use Twig\Test\NodeTestCase; + +class NullCoalesceTest extends NodeTestCase +{ + public function getTests() + { + $tests = []; + + $left = new NameExpression('foo', 1); + $right = new ConstantExpression(2, 1); + $node = new NullCoalesceExpression($left, $right, 1); + if (\PHP_VERSION_ID >= 70000) { + $tests[] = [$node, "((// line 1\n\$context[\"foo\"]) ?? (2))"]; + } elseif (\PHP_VERSION_ID >= 50400) { + $tests[] = [$node, "(((// line 1\n(isset(\$context[\"foo\"]) || array_key_exists(\"foo\", \$context)) && !(null === (isset(\$context[\"foo\"]) ? \$context[\"foo\"] : null)))) ? ((isset(\$context[\"foo\"]) ? \$context[\"foo\"] : null)) : (2))"]; + } else { + $tests[] = [$node, "(((// line 1\n(isset(\$context[\"foo\"]) || array_key_exists(\"foo\", \$context)) && !(null === \$this->getContext(\$context, \"foo\")))) ? (\$this->getContext(\$context, \"foo\")) : (2))"]; + } + + return $tests; + } +} diff --git a/vendor/twig/twig/tests/Node/Expression/PHP53/FilterInclude.php b/vendor/twig/twig/tests/Node/Expression/PHP53/FilterInclude.php new file mode 100644 index 0000000000000000000000000000000000000000..fc8f51776106e39a06f097bf17c10b54b0671ac3 --- /dev/null +++ b/vendor/twig/twig/tests/Node/Expression/PHP53/FilterInclude.php @@ -0,0 +1,8 @@ +<?php + +namespace Twig\Tests\Node\Expression\PHP53; + +$env = new \Twig\Environment(new \Twig\Loader\ArrayLoader([])); +$env->addFilter(new \Twig\TwigFilter('anonymous', function () {})); + +return $env; diff --git a/vendor/twig/twig/tests/Node/Expression/PHP53/FunctionInclude.php b/vendor/twig/twig/tests/Node/Expression/PHP53/FunctionInclude.php new file mode 100644 index 0000000000000000000000000000000000000000..b364001cdeec1f66dc0add427f5f4e214a99b431 --- /dev/null +++ b/vendor/twig/twig/tests/Node/Expression/PHP53/FunctionInclude.php @@ -0,0 +1,8 @@ +<?php + +namespace Twig\Tests\Node\Expression\PHP53; + +$env = new \Twig\Environment(new \Twig\Loader\ArrayLoader([])); +$env->addFunction(new \Twig\TwigFunction('anonymous', function () {})); + +return $env; diff --git a/vendor/twig/twig/tests/Node/Expression/PHP53/TestInclude.php b/vendor/twig/twig/tests/Node/Expression/PHP53/TestInclude.php new file mode 100644 index 0000000000000000000000000000000000000000..b2bf2cede50398e62e346a0772aa0f089cd5037e --- /dev/null +++ b/vendor/twig/twig/tests/Node/Expression/PHP53/TestInclude.php @@ -0,0 +1,8 @@ +<?php + +namespace Twig\Tests\Node\Expression\PHP53; + +$env = new \Twig\Environment(new \Twig\Loader\ArrayLoader([])); +$env->addTest(new \Twig\TwigTest('anonymous', function () {})); + +return $env; diff --git a/vendor/twig/twig/test/Twig/Tests/Node/Expression/ParentTest.php b/vendor/twig/twig/tests/Node/Expression/ParentTest.php similarity index 54% rename from vendor/twig/twig/test/Twig/Tests/Node/Expression/ParentTest.php rename to vendor/twig/twig/tests/Node/Expression/ParentTest.php index ab2bbe07485775f51bcc6aecc109ecf70f967648..1a67b77fe40bf5bd0d7e7386656e13ffb0ac703d 100644 --- a/vendor/twig/twig/test/Twig/Tests/Node/Expression/ParentTest.php +++ b/vendor/twig/twig/tests/Node/Expression/ParentTest.php @@ -1,5 +1,7 @@ <?php +namespace Twig\Tests\Node\Expression; + /* * This file is part of Twig. * @@ -9,19 +11,22 @@ * file that was distributed with this source code. */ -class Twig_Tests_Node_Expression_ParentTest extends Twig_Test_NodeTestCase +use Twig\Node\Expression\ParentExpression; +use Twig\Test\NodeTestCase; + +class ParentTest extends NodeTestCase { public function testConstructor() { - $node = new Twig_Node_Expression_Parent('foo', 1); + $node = new ParentExpression('foo', 1); $this->assertEquals('foo', $node->getAttribute('name')); } public function getTests() { - $tests = array(); - $tests[] = array(new Twig_Node_Expression_Parent('foo', 1), '$this->renderParentBlock("foo", $context, $blocks)'); + $tests = []; + $tests[] = [new ParentExpression('foo', 1), '$this->renderParentBlock("foo", $context, $blocks)']; return $tests; } diff --git a/vendor/twig/twig/tests/Node/Expression/TestTest.php b/vendor/twig/twig/tests/Node/Expression/TestTest.php new file mode 100644 index 0000000000000000000000000000000000000000..11e1596ca401d10dbcf6b6145e00d1e045e92569 --- /dev/null +++ b/vendor/twig/twig/tests/Node/Expression/TestTest.php @@ -0,0 +1,92 @@ +<?php + +namespace Twig\Tests\Node\Expression; + +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use Twig\Environment; +use Twig\Node\Expression\ConstantExpression; +use Twig\Node\Expression\Test\NullTest; +use Twig\Node\Expression\TestExpression; +use Twig\Node\Node; +use Twig\Test\NodeTestCase; +use Twig\TwigTest; + +class TestTest extends NodeTestCase +{ + public function testConstructor() + { + $expr = new ConstantExpression('foo', 1); + $name = new ConstantExpression('null', 1); + $args = new Node(); + $node = new TestExpression($expr, $name, $args, 1); + + $this->assertEquals($expr, $node->getNode('node')); + $this->assertEquals($args, $node->getNode('arguments')); + $this->assertEquals($name, $node->getAttribute('name')); + } + + public function getTests() + { + $environment = new Environment($this->createMock('\Twig\Loader\LoaderInterface')); + $environment->addTest(new TwigTest('barbar', 'Twig\Tests\Node\Expression\twig_tests_test_barbar', ['is_variadic' => true, 'need_context' => true])); + + $tests = []; + + $expr = new ConstantExpression('foo', 1); + $node = new NullTest($expr, 'null', new Node([]), 1); + $tests[] = [$node, '(null === "foo")']; + + // test as an anonymous function + if (\PHP_VERSION_ID >= 50300) { + $node = $this->createTest(new ConstantExpression('foo', 1), 'anonymous', [new ConstantExpression('foo', 1)]); + $tests[] = [$node, 'call_user_func_array($this->env->getTest(\'anonymous\')->getCallable(), ["foo", "foo"])']; + } + + // arbitrary named arguments + $string = new ConstantExpression('abc', 1); + $node = $this->createTest($string, 'barbar'); + $tests[] = [$node, 'Twig\Tests\Node\Expression\twig_tests_test_barbar("abc")', $environment]; + + $node = $this->createTest($string, 'barbar', ['foo' => new ConstantExpression('bar', 1)]); + $tests[] = [$node, 'Twig\Tests\Node\Expression\twig_tests_test_barbar("abc", null, null, ["foo" => "bar"])', $environment]; + + $node = $this->createTest($string, 'barbar', ['arg2' => new ConstantExpression('bar', 1)]); + $tests[] = [$node, 'Twig\Tests\Node\Expression\twig_tests_test_barbar("abc", null, "bar")', $environment]; + + $node = $this->createTest($string, 'barbar', [ + new ConstantExpression('1', 1), + new ConstantExpression('2', 1), + new ConstantExpression('3', 1), + 'foo' => new ConstantExpression('bar', 1), + ]); + $tests[] = [$node, 'Twig\Tests\Node\Expression\twig_tests_test_barbar("abc", "1", "2", [0 => "3", "foo" => "bar"])', $environment]; + + return $tests; + } + + protected function createTest($node, $name, array $arguments = []) + { + return new TestExpression($node, $name, new Node($arguments), 1); + } + + protected function getEnvironment() + { + if (\PHP_VERSION_ID >= 50300) { + return include 'PHP53/TestInclude.php'; + } + + return parent::getEnvironment(); + } +} + +function twig_tests_test_barbar($string, $arg1 = null, $arg2 = null, array $args = []) +{ +} diff --git a/vendor/twig/twig/tests/Node/Expression/Unary/NegTest.php b/vendor/twig/twig/tests/Node/Expression/Unary/NegTest.php new file mode 100644 index 0000000000000000000000000000000000000000..fcbf66ece8fdd7b7fa8554406d6a7ac204cc3ca2 --- /dev/null +++ b/vendor/twig/twig/tests/Node/Expression/Unary/NegTest.php @@ -0,0 +1,38 @@ +<?php + +namespace Twig\Tests\Node\Expression\Unary; + +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use Twig\Node\Expression\ConstantExpression; +use Twig\Node\Expression\Unary\NegUnary; +use Twig\Test\NodeTestCase; + +class NegTest extends NodeTestCase +{ + public function testConstructor() + { + $expr = new ConstantExpression(1, 1); + $node = new NegUnary($expr, 1); + + $this->assertEquals($expr, $node->getNode('node')); + } + + public function getTests() + { + $node = new ConstantExpression(1, 1); + $node = new NegUnary($node, 1); + + return [ + [$node, '-1'], + [new NegUnary($node, 1), '- -1'], + ]; + } +} diff --git a/vendor/twig/twig/tests/Node/Expression/Unary/NotTest.php b/vendor/twig/twig/tests/Node/Expression/Unary/NotTest.php new file mode 100644 index 0000000000000000000000000000000000000000..8197111e17a4d22a6df6045b09e6375d117a3cec --- /dev/null +++ b/vendor/twig/twig/tests/Node/Expression/Unary/NotTest.php @@ -0,0 +1,37 @@ +<?php + +namespace Twig\Tests\Node\Expression\Unary; + +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use Twig\Node\Expression\ConstantExpression; +use Twig\Node\Expression\Unary\NotUnary; +use Twig\Test\NodeTestCase; + +class NotTest extends NodeTestCase +{ + public function testConstructor() + { + $expr = new ConstantExpression(1, 1); + $node = new NotUnary($expr, 1); + + $this->assertEquals($expr, $node->getNode('node')); + } + + public function getTests() + { + $node = new ConstantExpression(1, 1); + $node = new NotUnary($node, 1); + + return [ + [$node, '!1'], + ]; + } +} diff --git a/vendor/twig/twig/tests/Node/Expression/Unary/PosTest.php b/vendor/twig/twig/tests/Node/Expression/Unary/PosTest.php new file mode 100644 index 0000000000000000000000000000000000000000..780e339e0cfdbd043c17ae79ba0fb94661248dd4 --- /dev/null +++ b/vendor/twig/twig/tests/Node/Expression/Unary/PosTest.php @@ -0,0 +1,37 @@ +<?php + +namespace Twig\Tests\Node\Expression\Unary; + +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use Twig\Node\Expression\ConstantExpression; +use Twig\Node\Expression\Unary\PosUnary; +use Twig\Test\NodeTestCase; + +class PosTest extends NodeTestCase +{ + public function testConstructor() + { + $expr = new ConstantExpression(1, 1); + $node = new PosUnary($expr, 1); + + $this->assertEquals($expr, $node->getNode('node')); + } + + public function getTests() + { + $node = new ConstantExpression(1, 1); + $node = new PosUnary($node, 1); + + return [ + [$node, '+1'], + ]; + } +} diff --git a/vendor/twig/twig/test/Twig/Tests/Node/ForTest.php b/vendor/twig/twig/tests/Node/ForTest.php similarity index 62% rename from vendor/twig/twig/test/Twig/Tests/Node/ForTest.php rename to vendor/twig/twig/tests/Node/ForTest.php index 2bf4c7b436d5a0ccdfcd0e9c8d008157b12046ce..d960ed6196bfcd94dde8d2b7597b812b508db3d4 100644 --- a/vendor/twig/twig/test/Twig/Tests/Node/ForTest.php +++ b/vendor/twig/twig/tests/Node/ForTest.php @@ -1,5 +1,7 @@ <?php +namespace Twig\Tests\Node; + /* * This file is part of Twig. * @@ -9,47 +11,55 @@ * file that was distributed with this source code. */ -class Twig_Tests_Node_ForTest extends Twig_Test_NodeTestCase +use Twig\Node\Expression\AssignNameExpression; +use Twig\Node\Expression\ConstantExpression; +use Twig\Node\Expression\NameExpression; +use Twig\Node\ForNode; +use Twig\Node\Node; +use Twig\Node\PrintNode; +use Twig\Test\NodeTestCase; + +class ForTest extends NodeTestCase { public function testConstructor() { - $keyTarget = new Twig_Node_Expression_AssignName('key', 1); - $valueTarget = new Twig_Node_Expression_AssignName('item', 1); - $seq = new Twig_Node_Expression_Name('items', 1); - $ifexpr = new Twig_Node_Expression_Constant(true, 1); - $body = new Twig_Node(array(new Twig_Node_Print(new Twig_Node_Expression_Name('foo', 1), 1)), array(), 1); + $keyTarget = new AssignNameExpression('key', 1); + $valueTarget = new AssignNameExpression('item', 1); + $seq = new NameExpression('items', 1); + $ifexpr = new ConstantExpression(true, 1); + $body = new Node([new PrintNode(new NameExpression('foo', 1), 1)], [], 1); $else = null; - $node = new Twig_Node_For($keyTarget, $valueTarget, $seq, $ifexpr, $body, $else, 1); + $node = new ForNode($keyTarget, $valueTarget, $seq, $ifexpr, $body, $else, 1); $node->setAttribute('with_loop', false); $this->assertEquals($keyTarget, $node->getNode('key_target')); $this->assertEquals($valueTarget, $node->getNode('value_target')); $this->assertEquals($seq, $node->getNode('seq')); $this->assertTrue($node->getAttribute('ifexpr')); - $this->assertEquals('Twig_Node_If', get_class($node->getNode('body'))); + $this->assertInstanceOf('\Twig\Node\IfNode', $node->getNode('body')); $this->assertEquals($body, $node->getNode('body')->getNode('tests')->getNode(1)->getNode(0)); $this->assertFalse($node->hasNode('else')); - $else = new Twig_Node_Print(new Twig_Node_Expression_Name('foo', 1), 1); - $node = new Twig_Node_For($keyTarget, $valueTarget, $seq, $ifexpr, $body, $else, 1); + $else = new PrintNode(new NameExpression('foo', 1), 1); + $node = new ForNode($keyTarget, $valueTarget, $seq, $ifexpr, $body, $else, 1); $node->setAttribute('with_loop', false); $this->assertEquals($else, $node->getNode('else')); } public function getTests() { - $tests = array(); + $tests = []; - $keyTarget = new Twig_Node_Expression_AssignName('key', 1); - $valueTarget = new Twig_Node_Expression_AssignName('item', 1); - $seq = new Twig_Node_Expression_Name('items', 1); + $keyTarget = new AssignNameExpression('key', 1); + $valueTarget = new AssignNameExpression('item', 1); + $seq = new NameExpression('items', 1); $ifexpr = null; - $body = new Twig_Node(array(new Twig_Node_Print(new Twig_Node_Expression_Name('foo', 1), 1)), array(), 1); + $body = new Node([new PrintNode(new NameExpression('foo', 1), 1)], [], 1); $else = null; - $node = new Twig_Node_For($keyTarget, $valueTarget, $seq, $ifexpr, $body, $else, 1); + $node = new ForNode($keyTarget, $valueTarget, $seq, $ifexpr, $body, $else, 1); $node->setAttribute('with_loop', false); - $tests[] = array($node, <<<EOF + $tests[] = [$node, <<<EOF // line 1 \$context['_parent'] = \$context; \$context['_seq'] = twig_ensure_traversable({$this->getVariableGetter('items')}); @@ -60,28 +70,28 @@ foreach (\$context['_seq'] as \$context["key"] => \$context["item"]) { unset(\$context['_seq'], \$context['_iterated'], \$context['key'], \$context['item'], \$context['_parent'], \$context['loop']); \$context = array_intersect_key(\$context, \$_parent) + \$_parent; EOF - ); + ]; - $keyTarget = new Twig_Node_Expression_AssignName('k', 1); - $valueTarget = new Twig_Node_Expression_AssignName('v', 1); - $seq = new Twig_Node_Expression_Name('values', 1); + $keyTarget = new AssignNameExpression('k', 1); + $valueTarget = new AssignNameExpression('v', 1); + $seq = new NameExpression('values', 1); $ifexpr = null; - $body = new Twig_Node(array(new Twig_Node_Print(new Twig_Node_Expression_Name('foo', 1), 1)), array(), 1); + $body = new Node([new PrintNode(new NameExpression('foo', 1), 1)], [], 1); $else = null; - $node = new Twig_Node_For($keyTarget, $valueTarget, $seq, $ifexpr, $body, $else, 1); + $node = new ForNode($keyTarget, $valueTarget, $seq, $ifexpr, $body, $else, 1); $node->setAttribute('with_loop', true); - $tests[] = array($node, <<<EOF + $tests[] = [$node, <<<EOF // line 1 \$context['_parent'] = \$context; \$context['_seq'] = twig_ensure_traversable({$this->getVariableGetter('values')}); -\$context['loop'] = array( +\$context['loop'] = [ 'parent' => \$context['_parent'], 'index0' => 0, 'index' => 1, 'first' => true, -); -if (is_array(\$context['_seq']) || (is_object(\$context['_seq']) && \$context['_seq'] instanceof Countable)) { +]; +if (is_array(\$context['_seq']) || (is_object(\$context['_seq']) && \$context['_seq'] instanceof \Countable)) { \$length = count(\$context['_seq']); \$context['loop']['revindex0'] = \$length - 1; \$context['loop']['revindex'] = \$length; @@ -103,27 +113,27 @@ foreach (\$context['_seq'] as \$context["k"] => \$context["v"]) { unset(\$context['_seq'], \$context['_iterated'], \$context['k'], \$context['v'], \$context['_parent'], \$context['loop']); \$context = array_intersect_key(\$context, \$_parent) + \$_parent; EOF - ); + ]; - $keyTarget = new Twig_Node_Expression_AssignName('k', 1); - $valueTarget = new Twig_Node_Expression_AssignName('v', 1); - $seq = new Twig_Node_Expression_Name('values', 1); - $ifexpr = new Twig_Node_Expression_Constant(true, 1); - $body = new Twig_Node(array(new Twig_Node_Print(new Twig_Node_Expression_Name('foo', 1), 1)), array(), 1); + $keyTarget = new AssignNameExpression('k', 1); + $valueTarget = new AssignNameExpression('v', 1); + $seq = new NameExpression('values', 1); + $ifexpr = new ConstantExpression(true, 1); + $body = new Node([new PrintNode(new NameExpression('foo', 1), 1)], [], 1); $else = null; - $node = new Twig_Node_For($keyTarget, $valueTarget, $seq, $ifexpr, $body, $else, 1); + $node = new ForNode($keyTarget, $valueTarget, $seq, $ifexpr, $body, $else, 1); $node->setAttribute('with_loop', true); - $tests[] = array($node, <<<EOF + $tests[] = [$node, <<<EOF // line 1 \$context['_parent'] = \$context; \$context['_seq'] = twig_ensure_traversable({$this->getVariableGetter('values')}); -\$context['loop'] = array( +\$context['loop'] = [ 'parent' => \$context['_parent'], 'index0' => 0, 'index' => 1, 'first' => true, -); +]; foreach (\$context['_seq'] as \$context["k"] => \$context["v"]) { if (true) { echo {$this->getVariableGetter('foo')}; @@ -136,29 +146,29 @@ foreach (\$context['_seq'] as \$context["k"] => \$context["v"]) { unset(\$context['_seq'], \$context['_iterated'], \$context['k'], \$context['v'], \$context['_parent'], \$context['loop']); \$context = array_intersect_key(\$context, \$_parent) + \$_parent; EOF - ); + ]; - $keyTarget = new Twig_Node_Expression_AssignName('k', 1); - $valueTarget = new Twig_Node_Expression_AssignName('v', 1); - $seq = new Twig_Node_Expression_Name('values', 1); + $keyTarget = new AssignNameExpression('k', 1); + $valueTarget = new AssignNameExpression('v', 1); + $seq = new NameExpression('values', 1); $ifexpr = null; - $body = new Twig_Node(array(new Twig_Node_Print(new Twig_Node_Expression_Name('foo', 1), 1)), array(), 1); - $else = new Twig_Node_Print(new Twig_Node_Expression_Name('foo', 1), 1); - $node = new Twig_Node_For($keyTarget, $valueTarget, $seq, $ifexpr, $body, $else, 1); + $body = new Node([new PrintNode(new NameExpression('foo', 1), 1)], [], 1); + $else = new PrintNode(new NameExpression('foo', 1), 1); + $node = new ForNode($keyTarget, $valueTarget, $seq, $ifexpr, $body, $else, 1); $node->setAttribute('with_loop', true); - $tests[] = array($node, <<<EOF + $tests[] = [$node, <<<EOF // line 1 \$context['_parent'] = \$context; \$context['_seq'] = twig_ensure_traversable({$this->getVariableGetter('values')}); \$context['_iterated'] = false; -\$context['loop'] = array( +\$context['loop'] = [ 'parent' => \$context['_parent'], 'index0' => 0, 'index' => 1, 'first' => true, -); -if (is_array(\$context['_seq']) || (is_object(\$context['_seq']) && \$context['_seq'] instanceof Countable)) { +]; +if (is_array(\$context['_seq']) || (is_object(\$context['_seq']) && \$context['_seq'] instanceof \Countable)) { \$length = count(\$context['_seq']); \$context['loop']['revindex0'] = \$length - 1; \$context['loop']['revindex'] = \$length; @@ -184,7 +194,7 @@ if (!\$context['_iterated']) { unset(\$context['_seq'], \$context['_iterated'], \$context['k'], \$context['v'], \$context['_parent'], \$context['loop']); \$context = array_intersect_key(\$context, \$_parent) + \$_parent; EOF - ); + ]; return $tests; } diff --git a/vendor/twig/twig/tests/Node/IfTest.php b/vendor/twig/twig/tests/Node/IfTest.php new file mode 100644 index 0000000000000000000000000000000000000000..d5a6eac8ab499ce67774ee62e786756e193ef5f3 --- /dev/null +++ b/vendor/twig/twig/tests/Node/IfTest.php @@ -0,0 +1,97 @@ +<?php + +namespace Twig\Tests\Node; + +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use Twig\Node\Expression\ConstantExpression; +use Twig\Node\Expression\NameExpression; +use Twig\Node\IfNode; +use Twig\Node\Node; +use Twig\Node\PrintNode; +use Twig\Test\NodeTestCase; + +class IfTest extends NodeTestCase +{ + public function testConstructor() + { + $t = new Node([ + new ConstantExpression(true, 1), + new PrintNode(new NameExpression('foo', 1), 1), + ], [], 1); + $else = null; + $node = new IfNode($t, $else, 1); + + $this->assertEquals($t, $node->getNode('tests')); + $this->assertFalse($node->hasNode('else')); + + $else = new PrintNode(new NameExpression('bar', 1), 1); + $node = new IfNode($t, $else, 1); + $this->assertEquals($else, $node->getNode('else')); + } + + public function getTests() + { + $tests = []; + + $t = new Node([ + new ConstantExpression(true, 1), + new PrintNode(new NameExpression('foo', 1), 1), + ], [], 1); + $else = null; + $node = new IfNode($t, $else, 1); + + $tests[] = [$node, <<<EOF +// line 1 +if (true) { + echo {$this->getVariableGetter('foo')}; +} +EOF + ]; + + $t = new Node([ + new ConstantExpression(true, 1), + new PrintNode(new NameExpression('foo', 1), 1), + new ConstantExpression(false, 1), + new PrintNode(new NameExpression('bar', 1), 1), + ], [], 1); + $else = null; + $node = new IfNode($t, $else, 1); + + $tests[] = [$node, <<<EOF +// line 1 +if (true) { + echo {$this->getVariableGetter('foo')}; +} elseif (false) { + echo {$this->getVariableGetter('bar')}; +} +EOF + ]; + + $t = new Node([ + new ConstantExpression(true, 1), + new PrintNode(new NameExpression('foo', 1), 1), + ], [], 1); + $else = new PrintNode(new NameExpression('bar', 1), 1); + $node = new IfNode($t, $else, 1); + + $tests[] = [$node, <<<EOF +// line 1 +if (true) { + echo {$this->getVariableGetter('foo')}; +} else { + echo {$this->getVariableGetter('bar')}; +} +EOF + ]; + + return $tests; + } +} diff --git a/vendor/twig/twig/tests/Node/ImportTest.php b/vendor/twig/twig/tests/Node/ImportTest.php new file mode 100644 index 0000000000000000000000000000000000000000..dbb49ab92ad325968329e91f00f7703fbf4a5e09 --- /dev/null +++ b/vendor/twig/twig/tests/Node/ImportTest.php @@ -0,0 +1,47 @@ +<?php + +namespace Twig\Tests\Node; + +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use Twig\Node\Expression\AssignNameExpression; +use Twig\Node\Expression\ConstantExpression; +use Twig\Node\ImportNode; +use Twig\Test\NodeTestCase; + +class ImportTest extends NodeTestCase +{ + public function testConstructor() + { + $macro = new ConstantExpression('foo.twig', 1); + $var = new AssignNameExpression('macro', 1); + $node = new ImportNode($macro, $var, 1); + + $this->assertEquals($macro, $node->getNode('expr')); + $this->assertEquals($var, $node->getNode('var')); + } + + public function getTests() + { + $tests = []; + + $macro = new ConstantExpression('foo.twig', 1); + $var = new AssignNameExpression('macro', 1); + $node = new ImportNode($macro, $var, 1); + + $tests[] = [$node, <<<EOF +// line 1 +\$context["macro"] = \$this->loadTemplate("foo.twig", null, 1)->unwrap(); +EOF + ]; + + return $tests; + } +} diff --git a/vendor/twig/twig/tests/Node/IncludeTest.php b/vendor/twig/twig/tests/Node/IncludeTest.php new file mode 100644 index 0000000000000000000000000000000000000000..ab1fdf0bfe018fc132448f9f0aa2d9cbf9080bd9 --- /dev/null +++ b/vendor/twig/twig/tests/Node/IncludeTest.php @@ -0,0 +1,95 @@ +<?php + +namespace Twig\Tests\Node; + +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use Twig\Node\Expression\ArrayExpression; +use Twig\Node\Expression\ConditionalExpression; +use Twig\Node\Expression\ConstantExpression; +use Twig\Node\IncludeNode; +use Twig\Test\NodeTestCase; + +class IncludeTest extends NodeTestCase +{ + public function testConstructor() + { + $expr = new ConstantExpression('foo.twig', 1); + $node = new IncludeNode($expr, null, false, false, 1); + + $this->assertFalse($node->hasNode('variables')); + $this->assertEquals($expr, $node->getNode('expr')); + $this->assertFalse($node->getAttribute('only')); + + $vars = new ArrayExpression([new ConstantExpression('foo', 1), new ConstantExpression(true, 1)], 1); + $node = new IncludeNode($expr, $vars, true, false, 1); + $this->assertEquals($vars, $node->getNode('variables')); + $this->assertTrue($node->getAttribute('only')); + } + + public function getTests() + { + $tests = []; + + $expr = new ConstantExpression('foo.twig', 1); + $node = new IncludeNode($expr, null, false, false, 1); + $tests[] = [$node, <<<EOF +// line 1 +\$this->loadTemplate("foo.twig", null, 1)->display(\$context); +EOF + ]; + + $expr = new ConditionalExpression( + new ConstantExpression(true, 1), + new ConstantExpression('foo', 1), + new ConstantExpression('foo', 1), + 0 + ); + $node = new IncludeNode($expr, null, false, false, 1); + $tests[] = [$node, <<<EOF +// line 1 +\$this->loadTemplate(((true) ? ("foo") : ("foo")), null, 1)->display(\$context); +EOF + ]; + + $expr = new ConstantExpression('foo.twig', 1); + $vars = new ArrayExpression([new ConstantExpression('foo', 1), new ConstantExpression(true, 1)], 1); + $node = new IncludeNode($expr, $vars, false, false, 1); + $tests[] = [$node, <<<EOF +// line 1 +\$this->loadTemplate("foo.twig", null, 1)->display(twig_array_merge(\$context, ["foo" => true])); +EOF + ]; + + $node = new IncludeNode($expr, $vars, true, false, 1); + $tests[] = [$node, <<<EOF +// line 1 +\$this->loadTemplate("foo.twig", null, 1)->display(twig_to_array(["foo" => true])); +EOF + ]; + + $node = new IncludeNode($expr, $vars, true, true, 1); + $tests[] = [$node, <<<EOF +// line 1 +\$__internal_%s = null; +try { + \$__internal_%s = \$this->loadTemplate("foo.twig", null, 1); +} catch (LoaderError \$e) { + // ignore missing template +} +if (\$__internal_%s) { + \$__internal_%s->display(twig_to_array(["foo" => true])); +} +EOF + , null, true]; + + return $tests; + } +} diff --git a/vendor/twig/twig/tests/Node/MacroTest.php b/vendor/twig/twig/tests/Node/MacroTest.php new file mode 100644 index 0000000000000000000000000000000000000000..82fc9999da24647dd24f4ccd9365be926cecefcb --- /dev/null +++ b/vendor/twig/twig/tests/Node/MacroTest.php @@ -0,0 +1,83 @@ +<?php + +namespace Twig\Tests\Node; + +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use Twig\Node\Expression\ConstantExpression; +use Twig\Node\Expression\NameExpression; +use Twig\Node\MacroNode; +use Twig\Node\Node; +use Twig\Node\TextNode; +use Twig\Test\NodeTestCase; + +class MacroTest extends NodeTestCase +{ + public function testConstructor() + { + $body = new TextNode('foo', 1); + $arguments = new Node([new NameExpression('foo', 1)], [], 1); + $node = new MacroNode('foo', $body, $arguments, 1); + + $this->assertEquals($body, $node->getNode('body')); + $this->assertEquals($arguments, $node->getNode('arguments')); + $this->assertEquals('foo', $node->getAttribute('name')); + } + + public function getTests() + { + $body = new TextNode('foo', 1); + $arguments = new Node([ + 'foo' => new ConstantExpression(null, 1), + 'bar' => new ConstantExpression('Foo', 1), + ], [], 1); + $node = new MacroNode('foo', $body, $arguments, 1); + + if (\PHP_VERSION_ID >= 50600) { + $declaration = ', ...$__varargs__'; + $varargs = '$__varargs__'; + } else { + $declaration = ''; + $varargs = 'func_num_args() > 2 ? array_slice(func_get_args(), 2) : []'; + } + + return [ + [$node, <<<EOF +// line 1 +public function getfoo(\$__foo__ = null, \$__bar__ = "Foo"$declaration) +{ + \$context = \$this->env->mergeGlobals([ + "foo" => \$__foo__, + "bar" => \$__bar__, + "varargs" => $varargs, + ]); + + \$blocks = []; + + ob_start(function () { return ''; }); + try { + echo "foo"; + } catch (\Exception \$e) { + ob_end_clean(); + + throw \$e; + } catch (\Throwable \$e) { + ob_end_clean(); + + throw \$e; + } + + return ('' === \$tmp = ob_get_clean()) ? '' : new Markup(\$tmp, \$this->env->getCharset()); +} +EOF + ], + ]; + } +} diff --git a/vendor/twig/twig/tests/Node/ModuleTest.php b/vendor/twig/twig/tests/Node/ModuleTest.php new file mode 100644 index 0000000000000000000000000000000000000000..aa000d39b2de7b4d90d83a6c8a27bba16451994e --- /dev/null +++ b/vendor/twig/twig/tests/Node/ModuleTest.php @@ -0,0 +1,270 @@ +<?php + +namespace Twig\Tests\Node; + +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use Twig\Environment; +use Twig\Node\Expression\AssignNameExpression; +use Twig\Node\Expression\ConditionalExpression; +use Twig\Node\Expression\ConstantExpression; +use Twig\Node\ImportNode; +use Twig\Node\ModuleNode; +use Twig\Node\Node; +use Twig\Node\SetNode; +use Twig\Node\TextNode; +use Twig\Source; +use Twig\Test\NodeTestCase; + +class ModuleTest extends NodeTestCase +{ + public function testConstructor() + { + $body = new TextNode('foo', 1); + $parent = new ConstantExpression('layout.twig', 1); + $blocks = new Node(); + $macros = new Node(); + $traits = new Node(); + $source = new Source('{{ foo }}', 'foo.twig'); + $node = new ModuleNode($body, $parent, $blocks, $macros, $traits, new Node([]), $source); + + $this->assertEquals($body, $node->getNode('body')); + $this->assertEquals($blocks, $node->getNode('blocks')); + $this->assertEquals($macros, $node->getNode('macros')); + $this->assertEquals($parent, $node->getNode('parent')); + $this->assertEquals($source->getName(), $node->getTemplateName()); + } + + public function getTests() + { + $twig = new Environment($this->createMock('\Twig\Loader\LoaderInterface')); + + $tests = []; + + $body = new TextNode('foo', 1); + $extends = null; + $blocks = new Node(); + $macros = new Node(); + $traits = new Node(); + $source = new Source('{{ foo }}', 'foo.twig'); + + $node = new ModuleNode($body, $extends, $blocks, $macros, $traits, new Node([]), $source); + $tests[] = [$node, <<<EOF +<?php + +use Twig\Environment; +use Twig\Error\LoaderError; +use Twig\Error\RuntimeError; +use Twig\Markup; +use Twig\Sandbox\SecurityError; +use Twig\Sandbox\SecurityNotAllowedTagError; +use Twig\Sandbox\SecurityNotAllowedFilterError; +use Twig\Sandbox\SecurityNotAllowedFunctionError; +use Twig\Source; +use Twig\Template; + +/* foo.twig */ +class __TwigTemplate_%x extends \Twig\Template +{ + public function __construct(Environment \$env) + { + parent::__construct(\$env); + + \$this->parent = false; + + \$this->blocks = [ + ]; + } + + protected function doDisplay(array \$context, array \$blocks = []) + { + // line 1 + echo "foo"; + } + + public function getTemplateName() + { + return "foo.twig"; + } + + public function getDebugInfo() + { + return array ( 30 => 1,); + } + + /** @deprecated since 1.27 (to be removed in 2.0). Use getSourceContext() instead */ + public function getSource() + { + @trigger_error('The '.__METHOD__.' method is deprecated since version 1.27 and will be removed in 2.0. Use getSourceContext() instead.', E_USER_DEPRECATED); + + return \$this->getSourceContext()->getCode(); + } + + public function getSourceContext() + { + return new Source("", "foo.twig", ""); + } +} +EOF + , $twig, true]; + + $import = new ImportNode(new ConstantExpression('foo.twig', 1), new AssignNameExpression('macro', 1), 2); + + $body = new Node([$import]); + $extends = new ConstantExpression('layout.twig', 1); + + $node = new ModuleNode($body, $extends, $blocks, $macros, $traits, new Node([]), $source); + $tests[] = [$node, <<<EOF +<?php + +use Twig\Environment; +use Twig\Error\LoaderError; +use Twig\Error\RuntimeError; +use Twig\Markup; +use Twig\Sandbox\SecurityError; +use Twig\Sandbox\SecurityNotAllowedTagError; +use Twig\Sandbox\SecurityNotAllowedFilterError; +use Twig\Sandbox\SecurityNotAllowedFunctionError; +use Twig\Source; +use Twig\Template; + +/* foo.twig */ +class __TwigTemplate_%x extends \Twig\Template +{ + public function __construct(Environment \$env) + { + parent::__construct(\$env); + + \$this->blocks = [ + ]; + } + + protected function doGetParent(array \$context) + { + // line 1 + return "layout.twig"; + } + + protected function doDisplay(array \$context, array \$blocks = []) + { + // line 2 + \$context["macro"] = \$this->loadTemplate("foo.twig", "foo.twig", 2)->unwrap(); + // line 1 + \$this->parent = \$this->loadTemplate("layout.twig", "foo.twig", 1); + \$this->parent->display(\$context, array_merge(\$this->blocks, \$blocks)); + } + + public function getTemplateName() + { + return "foo.twig"; + } + + public function isTraitable() + { + return false; + } + + public function getDebugInfo() + { + return array ( 36 => 1, 34 => 2, 28 => 1,); + } + + /** @deprecated since 1.27 (to be removed in 2.0). Use getSourceContext() instead */ + public function getSource() + { + @trigger_error('The '.__METHOD__.' method is deprecated since version 1.27 and will be removed in 2.0. Use getSourceContext() instead.', E_USER_DEPRECATED); + + return \$this->getSourceContext()->getCode(); + } + + public function getSourceContext() + { + return new Source("", "foo.twig", ""); + } +} +EOF + , $twig, true]; + + $set = new SetNode(false, new Node([new AssignNameExpression('foo', 4)]), new Node([new ConstantExpression('foo', 4)]), 4); + $body = new Node([$set]); + $extends = new ConditionalExpression( + new ConstantExpression(true, 2), + new ConstantExpression('foo', 2), + new ConstantExpression('foo', 2), + 2 + ); + + $twig = new Environment($this->createMock('\Twig\Loader\LoaderInterface'), ['debug' => true]); + $node = new ModuleNode($body, $extends, $blocks, $macros, $traits, new Node([]), $source); + $tests[] = [$node, <<<EOF +<?php + +use Twig\Environment; +use Twig\Error\LoaderError; +use Twig\Error\RuntimeError; +use Twig\Markup; +use Twig\Sandbox\SecurityError; +use Twig\Sandbox\SecurityNotAllowedTagError; +use Twig\Sandbox\SecurityNotAllowedFilterError; +use Twig\Sandbox\SecurityNotAllowedFunctionError; +use Twig\Source; +use Twig\Template; + +/* foo.twig */ +class __TwigTemplate_%x extends \Twig\Template +{ + protected function doGetParent(array \$context) + { + // line 2 + return \$this->loadTemplate(((true) ? ("foo") : ("foo")), "foo.twig", 2); + } + + protected function doDisplay(array \$context, array \$blocks = []) + { + // line 4 + \$context["foo"] = "foo"; + // line 2 + \$this->getParent(\$context)->display(\$context, array_merge(\$this->blocks, \$blocks)); + } + + public function getTemplateName() + { + return "foo.twig"; + } + + public function isTraitable() + { + return false; + } + + public function getDebugInfo() + { + return array ( 28 => 2, 26 => 4, 20 => 2,); + } + + /** @deprecated since 1.27 (to be removed in 2.0). Use getSourceContext() instead */ + public function getSource() + { + @trigger_error('The '.__METHOD__.' method is deprecated since version 1.27 and will be removed in 2.0. Use getSourceContext() instead.', E_USER_DEPRECATED); + + return \$this->getSourceContext()->getCode(); + } + + public function getSourceContext() + { + return new Source("{{ foo }}", "foo.twig", ""); + } +} +EOF + , $twig, true]; + + return $tests; + } +} diff --git a/vendor/twig/twig/test/Twig/Tests/Node/DoTest.php b/vendor/twig/twig/tests/Node/PrintTest.php similarity index 50% rename from vendor/twig/twig/test/Twig/Tests/Node/DoTest.php rename to vendor/twig/twig/tests/Node/PrintTest.php index aa33d1a2dc7d99285422bfc695a82ca6b4d45f67..49f8eb49840262aba3deb971792e01669dd771ad 100644 --- a/vendor/twig/twig/test/Twig/Tests/Node/DoTest.php +++ b/vendor/twig/twig/tests/Node/PrintTest.php @@ -1,5 +1,7 @@ <?php +namespace Twig\Tests\Node; + /* * This file is part of Twig. * @@ -9,23 +11,24 @@ * file that was distributed with this source code. */ -class Twig_Tests_Node_DoTest extends Twig_Test_NodeTestCase +use Twig\Node\Expression\ConstantExpression; +use Twig\Node\PrintNode; +use Twig\Test\NodeTestCase; + +class PrintTest extends NodeTestCase { public function testConstructor() { - $expr = new Twig_Node_Expression_Constant('foo', 1); - $node = new Twig_Node_Do($expr, 1); + $expr = new ConstantExpression('foo', 1); + $node = new PrintNode($expr, 1); $this->assertEquals($expr, $node->getNode('expr')); } public function getTests() { - $tests = array(); - - $expr = new Twig_Node_Expression_Constant('foo', 1); - $node = new Twig_Node_Do($expr, 1); - $tests[] = array($node, "// line 1\n\"foo\";"); + $tests = []; + $tests[] = [new PrintNode(new ConstantExpression('foo', 1), 1), "// line 1\necho \"foo\";"]; return $tests; } diff --git a/vendor/twig/twig/tests/Node/SandboxTest.php b/vendor/twig/twig/tests/Node/SandboxTest.php new file mode 100644 index 0000000000000000000000000000000000000000..b81781e8b45c7e03043cbeac66a3670a037cabed --- /dev/null +++ b/vendor/twig/twig/tests/Node/SandboxTest.php @@ -0,0 +1,49 @@ +<?php + +namespace Twig\Tests\Node; + +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use Twig\Node\SandboxNode; +use Twig\Node\TextNode; +use Twig\Test\NodeTestCase; + +class SandboxTest extends NodeTestCase +{ + public function testConstructor() + { + $body = new TextNode('foo', 1); + $node = new SandboxNode($body, 1); + + $this->assertEquals($body, $node->getNode('body')); + } + + public function getTests() + { + $tests = []; + + $body = new TextNode('foo', 1); + $node = new SandboxNode($body, 1); + + $tests[] = [$node, <<<EOF +// line 1 +if (!\$alreadySandboxed = \$this->sandbox->isSandboxed()) { + \$this->sandbox->enableSandbox(); +} +echo "foo"; +if (!\$alreadySandboxed) { + \$this->sandbox->disableSandbox(); +} +EOF + ]; + + return $tests; + } +} diff --git a/vendor/twig/twig/tests/Node/SetTest.php b/vendor/twig/twig/tests/Node/SetTest.php new file mode 100644 index 0000000000000000000000000000000000000000..370af95f2cdaf204e53ac2ccc2bc19095ea14eea --- /dev/null +++ b/vendor/twig/twig/tests/Node/SetTest.php @@ -0,0 +1,80 @@ +<?php + +namespace Twig\Tests\Node; + +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use Twig\Node\Expression\AssignNameExpression; +use Twig\Node\Expression\ConstantExpression; +use Twig\Node\Expression\NameExpression; +use Twig\Node\Node; +use Twig\Node\PrintNode; +use Twig\Node\SetNode; +use Twig\Node\TextNode; +use Twig\Test\NodeTestCase; + +class SetTest extends NodeTestCase +{ + public function testConstructor() + { + $names = new Node([new AssignNameExpression('foo', 1)], [], 1); + $values = new Node([new ConstantExpression('foo', 1)], [], 1); + $node = new SetNode(false, $names, $values, 1); + + $this->assertEquals($names, $node->getNode('names')); + $this->assertEquals($values, $node->getNode('values')); + $this->assertFalse($node->getAttribute('capture')); + } + + public function getTests() + { + $tests = []; + + $names = new Node([new AssignNameExpression('foo', 1)], [], 1); + $values = new Node([new ConstantExpression('foo', 1)], [], 1); + $node = new SetNode(false, $names, $values, 1); + $tests[] = [$node, <<<EOF +// line 1 +\$context["foo"] = "foo"; +EOF + ]; + + $names = new Node([new AssignNameExpression('foo', 1)], [], 1); + $values = new Node([new PrintNode(new ConstantExpression('foo', 1), 1)], [], 1); + $node = new SetNode(true, $names, $values, 1); + $tests[] = [$node, <<<EOF +// line 1 +ob_start(function () { return ''; }); +echo "foo"; +\$context["foo"] = ('' === \$tmp = ob_get_clean()) ? '' : new Markup(\$tmp, \$this->env->getCharset()); +EOF + ]; + + $names = new Node([new AssignNameExpression('foo', 1)], [], 1); + $values = new TextNode('foo', 1); + $node = new SetNode(true, $names, $values, 1); + $tests[] = [$node, <<<EOF +// line 1 +\$context["foo"] = ('' === \$tmp = "foo") ? '' : new Markup(\$tmp, \$this->env->getCharset()); +EOF + ]; + + $names = new Node([new AssignNameExpression('foo', 1), new AssignNameExpression('bar', 1)], [], 1); + $values = new Node([new ConstantExpression('foo', 1), new NameExpression('bar', 1)], [], 1); + $node = new SetNode(false, $names, $values, 1); + $tests[] = [$node, <<<EOF +// line 1 +list(\$context["foo"], \$context["bar"]) = ["foo", {$this->getVariableGetter('bar')}]; +EOF + ]; + + return $tests; + } +} diff --git a/vendor/twig/twig/tests/Node/SpacelessTest.php b/vendor/twig/twig/tests/Node/SpacelessTest.php new file mode 100644 index 0000000000000000000000000000000000000000..5f3c81442ed29840d82710a8059e6446b5c3eb8a --- /dev/null +++ b/vendor/twig/twig/tests/Node/SpacelessTest.php @@ -0,0 +1,44 @@ +<?php + +namespace Twig\Tests\Node; + +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use Twig\Node\Node; +use Twig\Node\SpacelessNode; +use Twig\Node\TextNode; +use Twig\Test\NodeTestCase; + +class SpacelessTest extends NodeTestCase +{ + public function testConstructor() + { + $body = new Node([new TextNode('<div> <div> foo </div> </div>', 1)]); + $node = new SpacelessNode($body, 1); + + $this->assertEquals($body, $node->getNode('body')); + } + + public function getTests() + { + $body = new Node([new TextNode('<div> <div> foo </div> </div>', 1)]); + $node = new SpacelessNode($body, 1); + + return [ + [$node, <<<EOF +// line 1 +ob_start(function () { return ''; }); +echo "<div> <div> foo </div> </div>"; +echo trim(preg_replace('/>\s+</', '><', ob_get_clean())); +EOF + ], + ]; + } +} diff --git a/vendor/twig/twig/test/Twig/Tests/Node/TextTest.php b/vendor/twig/twig/tests/Node/TextTest.php similarity index 60% rename from vendor/twig/twig/test/Twig/Tests/Node/TextTest.php rename to vendor/twig/twig/tests/Node/TextTest.php index ceaf67f4c5bda237db26bd62ace65dc85f5dbf0e..ace191213d8e0ea8671a5059c9be60b0eff07118 100644 --- a/vendor/twig/twig/test/Twig/Tests/Node/TextTest.php +++ b/vendor/twig/twig/tests/Node/TextTest.php @@ -1,5 +1,7 @@ <?php +namespace Twig\Tests\Node; + /* * This file is part of Twig. * @@ -9,19 +11,22 @@ * file that was distributed with this source code. */ -class Twig_Tests_Node_TextTest extends Twig_Test_NodeTestCase +use Twig\Node\TextNode; +use Twig\Test\NodeTestCase; + +class TextTest extends NodeTestCase { public function testConstructor() { - $node = new Twig_Node_Text('foo', 1); + $node = new TextNode('foo', 1); $this->assertEquals('foo', $node->getAttribute('data')); } public function getTests() { - $tests = array(); - $tests[] = array(new Twig_Node_Text('foo', 1), "// line 1\necho \"foo\";"); + $tests = []; + $tests[] = [new TextNode('foo', 1), "// line 1\necho \"foo\";"]; return $tests; } diff --git a/vendor/twig/twig/tests/NodeTraverserTest.php b/vendor/twig/twig/tests/NodeTraverserTest.php new file mode 100644 index 0000000000000000000000000000000000000000..7136ae7f6cc32e1c8993c17e63f49cfce4ed1f14 --- /dev/null +++ b/vendor/twig/twig/tests/NodeTraverserTest.php @@ -0,0 +1,49 @@ +<?php + +namespace Twig\Tests; + +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use Twig\Environment; +use Twig\Node\Node; +use Twig\NodeTraverser; +use Twig\NodeVisitor\NodeVisitorInterface; + +class NodeTraverserTest extends \PHPUnit\Framework\TestCase +{ + /** + * @group legacy + */ + public function testNodeIsNullWhenTraversing() + { + $env = new Environment($this->createMock('\Twig\Loader\LoaderInterface')); + $traverser = new NodeTraverser($env, [new IdentityVisitor()]); + $n = new Node([new Node([]), null, new Node([])]); + $this->assertCount(3, $traverser->traverse($n)); + } +} + +class IdentityVisitor implements NodeVisitorInterface +{ + public function enterNode(\Twig_NodeInterface $node, Environment $env) + { + return $node; + } + + public function leaveNode(\Twig_NodeInterface $node, Environment $env) + { + return $node; + } + + public function getPriority() + { + return 0; + } +} diff --git a/vendor/twig/twig/tests/NodeVisitor/OptimizerTest.php b/vendor/twig/twig/tests/NodeVisitor/OptimizerTest.php new file mode 100644 index 0000000000000000000000000000000000000000..6bcc828264c99c2923c9a8defe09c49516e6230d --- /dev/null +++ b/vendor/twig/twig/tests/NodeVisitor/OptimizerTest.php @@ -0,0 +1,116 @@ +<?php + +namespace Twig\Tests\NodeVisitor; + +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use Twig\Environment; +use Twig\Node\ForNode; +use Twig\Source; + +class OptimizerTest extends \PHPUnit\Framework\TestCase +{ + public function testRenderBlockOptimizer() + { + $env = new Environment($this->createMock('\Twig\Loader\LoaderInterface'), ['cache' => false, 'autoescape' => false]); + + $stream = $env->parse($env->tokenize(new Source('{{ block("foo") }}', 'index'))); + + $node = $stream->getNode('body')->getNode(0); + + $this->assertInstanceOf('\Twig\Node\Expression\BlockReferenceExpression', $node); + $this->assertTrue($node->getAttribute('output')); + } + + public function testRenderParentBlockOptimizer() + { + $env = new Environment($this->createMock('\Twig\Loader\LoaderInterface'), ['cache' => false, 'autoescape' => false]); + + $stream = $env->parse($env->tokenize(new Source('{% extends "foo" %}{% block content %}{{ parent() }}{% endblock %}', 'index'))); + + $node = $stream->getNode('blocks')->getNode('content')->getNode(0)->getNode('body'); + + $this->assertInstanceOf('\Twig\Node\Expression\ParentExpression', $node); + $this->assertTrue($node->getAttribute('output')); + } + + /** + * @dataProvider getTestsForForOptimizer + */ + public function testForOptimizer($template, $expected) + { + $env = new Environment($this->createMock('\Twig\Loader\LoaderInterface'), ['cache' => false]); + + $stream = $env->parse($env->tokenize(new Source($template, 'index'))); + + foreach ($expected as $target => $withLoop) { + $this->assertTrue($this->checkForConfiguration($stream, $target, $withLoop), sprintf('variable %s is %soptimized', $target, $withLoop ? 'not ' : '')); + } + } + + public function getTestsForForOptimizer() + { + return [ + ['{% for i in foo %}{% endfor %}', ['i' => false]], + + ['{% for i in foo %}{{ loop.index }}{% endfor %}', ['i' => true]], + + ['{% for i in foo %}{% for j in foo %}{% endfor %}{% endfor %}', ['i' => false, 'j' => false]], + + ['{% for i in foo %}{% include "foo" %}{% endfor %}', ['i' => true]], + + ['{% for i in foo %}{% include "foo" only %}{% endfor %}', ['i' => false]], + + ['{% for i in foo %}{% include "foo" with { "foo": "bar" } only %}{% endfor %}', ['i' => false]], + + ['{% for i in foo %}{% include "foo" with { "foo": loop.index } only %}{% endfor %}', ['i' => true]], + + ['{% for i in foo %}{% for j in foo %}{{ loop.index }}{% endfor %}{% endfor %}', ['i' => false, 'j' => true]], + + ['{% for i in foo %}{% for j in foo %}{{ loop.parent.loop.index }}{% endfor %}{% endfor %}', ['i' => true, 'j' => true]], + + ['{% for i in foo %}{% set l = loop %}{% for j in foo %}{{ l.index }}{% endfor %}{% endfor %}', ['i' => true, 'j' => false]], + + ['{% for i in foo %}{% for j in foo %}{{ foo.parent.loop.index }}{% endfor %}{% endfor %}', ['i' => false, 'j' => false]], + + ['{% for i in foo %}{% for j in foo %}{{ loop["parent"].loop.index }}{% endfor %}{% endfor %}', ['i' => true, 'j' => true]], + + ['{% for i in foo %}{{ include("foo") }}{% endfor %}', ['i' => true]], + + ['{% for i in foo %}{{ include("foo", with_context = false) }}{% endfor %}', ['i' => false]], + + ['{% for i in foo %}{{ include("foo", with_context = true) }}{% endfor %}', ['i' => true]], + + ['{% for i in foo %}{{ include("foo", { "foo": "bar" }, with_context = false) }}{% endfor %}', ['i' => false]], + + ['{% for i in foo %}{{ include("foo", { "foo": loop.index }, with_context = false) }}{% endfor %}', ['i' => true]], + ]; + } + + public function checkForConfiguration(\Twig_NodeInterface $node = null, $target, $withLoop) + { + if (null === $node) { + return; + } + + foreach ($node as $n) { + if ($n instanceof ForNode) { + if ($target === $n->getNode('value_target')->getAttribute('name')) { + return $withLoop == $n->getAttribute('with_loop'); + } + } + + $ret = $this->checkForConfiguration($n, $target, $withLoop); + if (null !== $ret) { + return $ret; + } + } + } +} diff --git a/vendor/twig/twig/tests/ParserTest.php b/vendor/twig/twig/tests/ParserTest.php new file mode 100644 index 0000000000000000000000000000000000000000..917d5deaa7d065f096dbe3c6df2cfd9024bf1a86 --- /dev/null +++ b/vendor/twig/twig/tests/ParserTest.php @@ -0,0 +1,218 @@ +<?php + +namespace Twig\Tests; + +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use Twig\Environment; +use Twig\Node\MacroNode; +use Twig\Node\Node; +use Twig\Node\SetNode; +use Twig\Node\TextNode; +use Twig\Parser; +use Twig\Source; +use Twig\Token; +use Twig\TokenParser\AbstractTokenParser; +use Twig\TokenStream; + +class ParserTest extends \PHPUnit\Framework\TestCase +{ + public function testSetMacroThrowsExceptionOnReservedMethods() + { + $this->expectException('\Twig\Error\SyntaxError'); + + $parser = $this->getParser(); + $parser->setMacro('parent', new MacroNode('foo', new Node(), new Node(), 1)); + } + + public function testUnknownTag() + { + $this->expectException('\Twig\Error\SyntaxError'); + $this->expectExceptionMessage('Unknown "foo" tag. Did you mean "for" at line 1?'); + + $stream = new TokenStream([ + new Token(Token::BLOCK_START_TYPE, '', 1), + new Token(Token::NAME_TYPE, 'foo', 1), + new Token(Token::BLOCK_END_TYPE, '', 1), + new Token(Token::EOF_TYPE, '', 1), + ]); + $parser = new Parser(new Environment($this->createMock('\Twig\Loader\LoaderInterface'))); + $parser->parse($stream); + } + + public function testUnknownTagWithoutSuggestions() + { + $this->expectException('\Twig\Error\SyntaxError'); + $this->expectExceptionMessage('Unknown "foobar" tag at line 1.'); + + $stream = new TokenStream([ + new Token(Token::BLOCK_START_TYPE, '', 1), + new Token(Token::NAME_TYPE, 'foobar', 1), + new Token(Token::BLOCK_END_TYPE, '', 1), + new Token(Token::EOF_TYPE, '', 1), + ]); + $parser = new Parser(new Environment($this->createMock('\Twig\Loader\LoaderInterface'))); + $parser->parse($stream); + } + + /** + * @dataProvider getFilterBodyNodesData + */ + public function testFilterBodyNodes($input, $expected) + { + $parser = $this->getParser(); + + $this->assertEquals($expected, $parser->filterBodyNodes($input)); + } + + public function getFilterBodyNodesData() + { + return [ + [ + new Node([new TextNode(' ', 1)]), + new Node([]), + ], + [ + $input = new Node([new SetNode(false, new Node(), new Node(), 1)]), + $input, + ], + [ + $input = new Node([new SetNode(true, new Node(), new Node([new Node([new TextNode('foo', 1)])]), 1)]), + $input, + ], + ]; + } + + /** + * @dataProvider getFilterBodyNodesDataThrowsException + */ + public function testFilterBodyNodesThrowsException($input) + { + $this->expectException('\Twig\Error\SyntaxError'); + + $parser = $this->getParser(); + + $parser->filterBodyNodes($input); + } + + public function getFilterBodyNodesDataThrowsException() + { + return [ + [new TextNode('foo', 1)], + [new Node([new Node([new TextNode('foo', 1)])])], + ]; + } + + /** + * @dataProvider getFilterBodyNodesWithBOMData + */ + public function testFilterBodyNodesWithBOM($emptyNode) + { + $this->assertNull($this->getParser()->filterBodyNodes(new TextNode(\chr(0xEF).\chr(0xBB).\chr(0xBF).$emptyNode, 1))); + } + + public function getFilterBodyNodesWithBOMData() + { + return [ + [' '], + ["\t"], + ["\n"], + ["\n\t\n "], + ]; + } + + public function testParseIsReentrant() + { + $twig = new Environment($this->createMock('\Twig\Loader\LoaderInterface'), [ + 'autoescape' => false, + 'optimizations' => 0, + ]); + $twig->addTokenParser(new TestTokenParser()); + + $parser = new Parser($twig); + + $parser->parse(new TokenStream([ + new Token(Token::BLOCK_START_TYPE, '', 1), + new Token(Token::NAME_TYPE, 'test', 1), + new Token(Token::BLOCK_END_TYPE, '', 1), + new Token(Token::VAR_START_TYPE, '', 1), + new Token(Token::NAME_TYPE, 'foo', 1), + new Token(Token::VAR_END_TYPE, '', 1), + new Token(Token::EOF_TYPE, '', 1), + ])); + + $this->assertNull($parser->getParent()); + } + + public function testGetVarName() + { + $twig = new Environment($this->createMock('\Twig\Loader\LoaderInterface'), [ + 'autoescape' => false, + 'optimizations' => 0, + ]); + + $twig->parse($twig->tokenize(new Source(<<<EOF +{% from _self import foo %} + +{% macro foo() %} + {{ foo }} +{% endmacro %} +EOF + , 'index'))); + + // The getVarName() must not depend on the template loaders, + // If this test does not throw any exception, that's good. + // see https://github.com/symfony/symfony/issues/4218 + $this->addToAssertionCount(1); + } + + protected function getParser() + { + $parser = new TestParser(new Environment($this->createMock('\Twig\Loader\LoaderInterface'))); + $parser->setParent(new Node()); + $parser->stream = new TokenStream([]); + + return $parser; + } +} + +class TestParser extends Parser +{ + public $stream; + + public function filterBodyNodes(\Twig_NodeInterface $node) + { + return parent::filterBodyNodes($node); + } +} + +class TestTokenParser extends AbstractTokenParser +{ + public function parse(Token $token) + { + // simulate the parsing of another template right in the middle of the parsing of the current template + $this->parser->parse(new TokenStream([ + new Token(Token::BLOCK_START_TYPE, '', 1), + new Token(Token::NAME_TYPE, 'extends', 1), + new Token(Token::STRING_TYPE, 'base', 1), + new Token(Token::BLOCK_END_TYPE, '', 1), + new Token(Token::EOF_TYPE, '', 1), + ])); + + $this->parser->getStream()->expect(Token::BLOCK_END_TYPE); + + return new Node([]); + } + + public function getTag() + { + return 'test'; + } +} diff --git a/vendor/twig/twig/tests/Profiler/Dumper/AbstractTest.php b/vendor/twig/twig/tests/Profiler/Dumper/AbstractTest.php new file mode 100644 index 0000000000000000000000000000000000000000..a55bfa0d38b7cffe938210c6c05d423c4588f524 --- /dev/null +++ b/vendor/twig/twig/tests/Profiler/Dumper/AbstractTest.php @@ -0,0 +1,107 @@ +<?php + +namespace Twig\Tests\Profiler\Dumper; + +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use Twig\Profiler\Profile; + +abstract class AbstractTest extends \PHPUnit\Framework\TestCase +{ + protected function getProfile() + { + $profile = new Profile('main'); + $subProfiles = [ + $this->getIndexProfile( + [ + $this->getEmbeddedBlockProfile(), + $this->getEmbeddedTemplateProfile( + [ + $this->getIncludedTemplateProfile(), + ] + ), + $this->getMacroProfile(), + $this->getEmbeddedTemplateProfile( + [ + $this->getIncludedTemplateProfile(), + ] + ), + ] + ), + ]; + + $p = new \ReflectionProperty($profile, 'profiles'); + $p->setAccessible(true); + $p->setValue($profile, $subProfiles); + + return $profile; + } + + private function getIndexProfile(array $subProfiles = []) + { + return $this->generateProfile('main', 1, 'template', 'index.twig', $subProfiles); + } + + private function getEmbeddedBlockProfile(array $subProfiles = []) + { + return $this->generateProfile('body', 0.0001, 'block', 'embedded.twig', $subProfiles); + } + + private function getEmbeddedTemplateProfile(array $subProfiles = []) + { + return $this->generateProfile('main', 0.0001, 'template', 'embedded.twig', $subProfiles); + } + + private function getIncludedTemplateProfile(array $subProfiles = []) + { + return $this->generateProfile('main', 0.0001, 'template', 'included.twig', $subProfiles); + } + + private function getMacroProfile(array $subProfiles = []) + { + return $this->generateProfile('foo', 0.0001, 'macro', 'index.twig', $subProfiles); + } + + /** + * @param string $name + * @param float $duration + * @param bool $isTemplate + * @param string $type + * @param string $templateName + * @param array $subProfiles + * + * @return Profile + */ + private function generateProfile($name, $duration, $type, $templateName, array $subProfiles = []) + { + $profile = new Profile($templateName, $type, $name); + + $p = new \ReflectionProperty($profile, 'profiles'); + $p->setAccessible(true); + $p->setValue($profile, $subProfiles); + + $starts = new \ReflectionProperty($profile, 'starts'); + $starts->setAccessible(true); + $starts->setValue($profile, [ + 'wt' => 0, + 'mu' => 0, + 'pmu' => 0, + ]); + $ends = new \ReflectionProperty($profile, 'ends'); + $ends->setAccessible(true); + $ends->setValue($profile, [ + 'wt' => $duration, + 'mu' => 0, + 'pmu' => 0, + ]); + + return $profile; + } +} diff --git a/vendor/twig/twig/test/Twig/Tests/Profiler/Dumper/BlackfireTest.php b/vendor/twig/twig/tests/Profiler/Dumper/BlackfireTest.php similarity index 80% rename from vendor/twig/twig/test/Twig/Tests/Profiler/Dumper/BlackfireTest.php rename to vendor/twig/twig/tests/Profiler/Dumper/BlackfireTest.php index 1a1b9d299b43786d9f1432639cbc534341211f4f..b1c2cd7d1f008c3646bd21f4c3e7c123cc69e534 100644 --- a/vendor/twig/twig/test/Twig/Tests/Profiler/Dumper/BlackfireTest.php +++ b/vendor/twig/twig/tests/Profiler/Dumper/BlackfireTest.php @@ -1,5 +1,7 @@ <?php +namespace Twig\Tests\Profiler\Dumper; + /* * This file is part of Twig. * @@ -9,11 +11,13 @@ * file that was distributed with this source code. */ -class Twig_Tests_Profiler_Dumper_BlackfireTest extends Twig_Tests_Profiler_Dumper_AbstractTest +use Twig\Profiler\Dumper\BlackfireDumper; + +class BlackfireTest extends AbstractTest { public function testDump() { - $dumper = new Twig_Profiler_Dumper_Blackfire(); + $dumper = new BlackfireDumper(); $this->assertStringMatchesFormat(<<<EOF file-format: BlackfireProbe diff --git a/vendor/twig/twig/test/Twig/Tests/Profiler/Dumper/HtmlTest.php b/vendor/twig/twig/tests/Profiler/Dumper/HtmlTest.php similarity index 86% rename from vendor/twig/twig/test/Twig/Tests/Profiler/Dumper/HtmlTest.php rename to vendor/twig/twig/tests/Profiler/Dumper/HtmlTest.php index 66a68c4beae924478c843ec85dbe30eaae1e4806..20a1ab439c56ebc36c6a7f38abf09fc75e5a61f1 100644 --- a/vendor/twig/twig/test/Twig/Tests/Profiler/Dumper/HtmlTest.php +++ b/vendor/twig/twig/tests/Profiler/Dumper/HtmlTest.php @@ -1,5 +1,7 @@ <?php +namespace Twig\Tests\Profiler\Dumper; + /* * This file is part of Twig. * @@ -9,11 +11,13 @@ * file that was distributed with this source code. */ -class Twig_Tests_Profiler_Dumper_HtmlTest extends Twig_Tests_Profiler_Dumper_AbstractTest +use Twig\Profiler\Dumper\HtmlDumper; + +class HtmlTest extends AbstractTest { public function testDump() { - $dumper = new Twig_Profiler_Dumper_Html(); + $dumper = new HtmlDumper(); $this->assertStringMatchesFormat(<<<EOF <pre>main <span style="color: #d44">%d.%dms/%d%</span> â”” <span style="background-color: #ffd">index.twig</span> <span style="color: #d44">%d.%dms/%d%</span> diff --git a/vendor/twig/twig/test/Twig/Tests/Profiler/Dumper/TextTest.php b/vendor/twig/twig/tests/Profiler/Dumper/TextTest.php similarity index 78% rename from vendor/twig/twig/test/Twig/Tests/Profiler/Dumper/TextTest.php rename to vendor/twig/twig/tests/Profiler/Dumper/TextTest.php index e2ea165ace4816987188958f1515d245e4e72e61..8240e356bd26a74224e0cb72bffdb89db28c1b7f 100644 --- a/vendor/twig/twig/test/Twig/Tests/Profiler/Dumper/TextTest.php +++ b/vendor/twig/twig/tests/Profiler/Dumper/TextTest.php @@ -1,5 +1,7 @@ <?php +namespace Twig\Tests\Profiler\Dumper; + /* * This file is part of Twig. * @@ -9,11 +11,13 @@ * file that was distributed with this source code. */ -class Twig_Tests_Profiler_Dumper_TextTest extends Twig_Tests_Profiler_Dumper_AbstractTest +use Twig\Profiler\Dumper\TextDumper; + +class TextTest extends AbstractTest { public function testDump() { - $dumper = new Twig_Profiler_Dumper_Text(); + $dumper = new TextDumper(); $this->assertStringMatchesFormat(<<<EOF main %d.%dms/%d% â”” index.twig %d.%dms/%d% diff --git a/vendor/twig/twig/test/Twig/Tests/Profiler/ProfileTest.php b/vendor/twig/twig/tests/Profiler/ProfileTest.php similarity index 62% rename from vendor/twig/twig/test/Twig/Tests/Profiler/ProfileTest.php rename to vendor/twig/twig/tests/Profiler/ProfileTest.php index 08db96a90ce538d157f08be8f03f4322c3c837ef..0b7fd272f2a1a4bc57c321e3033830585d18c082 100644 --- a/vendor/twig/twig/test/Twig/Tests/Profiler/ProfileTest.php +++ b/vendor/twig/twig/tests/Profiler/ProfileTest.php @@ -1,5 +1,7 @@ <?php +namespace Twig\Tests\Profiler; + /* * This file is part of Twig. * @@ -9,11 +11,13 @@ * file that was distributed with this source code. */ -class Twig_Tests_Profiler_ProfileTest extends \PHPUnit\Framework\TestCase +use Twig\Profiler\Profile; + +class ProfileTest extends \PHPUnit\Framework\TestCase { public function testConstructor() { - $profile = new Twig_Profiler_Profile('template', 'type', 'name'); + $profile = new Profile('template', 'type', 'name'); $this->assertEquals('template', $profile->getTemplate()); $this->assertEquals('type', $profile->getType()); @@ -22,53 +26,53 @@ class Twig_Tests_Profiler_ProfileTest extends \PHPUnit\Framework\TestCase public function testIsRoot() { - $profile = new Twig_Profiler_Profile('template', Twig_Profiler_Profile::ROOT); + $profile = new Profile('template', Profile::ROOT); $this->assertTrue($profile->isRoot()); - $profile = new Twig_Profiler_Profile('template', Twig_Profiler_Profile::TEMPLATE); + $profile = new Profile('template', Profile::TEMPLATE); $this->assertFalse($profile->isRoot()); } public function testIsTemplate() { - $profile = new Twig_Profiler_Profile('template', Twig_Profiler_Profile::TEMPLATE); + $profile = new Profile('template', Profile::TEMPLATE); $this->assertTrue($profile->isTemplate()); - $profile = new Twig_Profiler_Profile('template', Twig_Profiler_Profile::ROOT); + $profile = new Profile('template', Profile::ROOT); $this->assertFalse($profile->isTemplate()); } public function testIsBlock() { - $profile = new Twig_Profiler_Profile('template', Twig_Profiler_Profile::BLOCK); + $profile = new Profile('template', Profile::BLOCK); $this->assertTrue($profile->isBlock()); - $profile = new Twig_Profiler_Profile('template', Twig_Profiler_Profile::ROOT); + $profile = new Profile('template', Profile::ROOT); $this->assertFalse($profile->isBlock()); } public function testIsMacro() { - $profile = new Twig_Profiler_Profile('template', Twig_Profiler_Profile::MACRO); + $profile = new Profile('template', Profile::MACRO); $this->assertTrue($profile->isMacro()); - $profile = new Twig_Profiler_Profile('template', Twig_Profiler_Profile::ROOT); + $profile = new Profile('template', Profile::ROOT); $this->assertFalse($profile->isMacro()); } public function testGetAddProfile() { - $profile = new Twig_Profiler_Profile(); - $profile->addProfile($a = new Twig_Profiler_Profile()); - $profile->addProfile($b = new Twig_Profiler_Profile()); + $profile = new Profile(); + $profile->addProfile($a = new Profile()); + $profile->addProfile($b = new Profile()); - $this->assertSame(array($a, $b), $profile->getProfiles()); - $this->assertSame(array($a, $b), iterator_to_array($profile)); + $this->assertSame([$a, $b], $profile->getProfiles()); + $this->assertSame([$a, $b], iterator_to_array($profile)); } public function testGetDuration() { - $profile = new Twig_Profiler_Profile(); + $profile = new Profile(); usleep(1); $profile->leave(); @@ -77,8 +81,8 @@ class Twig_Tests_Profiler_ProfileTest extends \PHPUnit\Framework\TestCase public function testSerialize() { - $profile = new Twig_Profiler_Profile('template', 'type', 'name'); - $profile1 = new Twig_Profiler_Profile('template1', 'type1', 'name1'); + $profile = new Profile('template', 'type', 'name'); + $profile1 = new Profile('template1', 'type1', 'name1'); $profile->addProfile($profile1); $profile->leave(); $profile1->leave(); @@ -100,7 +104,7 @@ class Twig_Tests_Profiler_ProfileTest extends \PHPUnit\Framework\TestCase public function testReset() { - $profile = new Twig_Profiler_Profile(); + $profile = new Profile(); usleep(1); $profile->leave(); $profile->reset(); diff --git a/vendor/twig/twig/test/Twig/Tests/TemplateTest.php b/vendor/twig/twig/tests/TemplateTest.php similarity index 50% rename from vendor/twig/twig/test/Twig/Tests/TemplateTest.php rename to vendor/twig/twig/tests/TemplateTest.php index c22a433361e3d858c1ca9d0d398a01c64cc47ad4..41f8d1b043399efe3617d5874964e813463d5d50 100644 --- a/vendor/twig/twig/test/Twig/Tests/TemplateTest.php +++ b/vendor/twig/twig/tests/TemplateTest.php @@ -1,5 +1,7 @@ <?php +namespace Twig\Tests; + /* * This file is part of Twig. * @@ -8,15 +10,28 @@ * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ -class Twig_Tests_TemplateTest extends \PHPUnit\Framework\TestCase + +use Twig\Environment; +use Twig\Error\RuntimeError; +use Twig\Extension\SandboxExtension; +use Twig\Loader\ArrayLoader; +use Twig\Loader\LoaderInterface; +use Twig\Loader\SourceContextLoaderInterface; +use Twig\Node\Expression\GetAttrExpression; +use Twig\NodeVisitor\NodeVisitorInterface; +use Twig\Sandbox\SecurityError; +use Twig\Sandbox\SecurityPolicy; +use Twig\Template; + +class TemplateTest extends \PHPUnit\Framework\TestCase { - /** - * @expectedException LogicException - */ public function testDisplayBlocksAcceptTemplateOnlyAsBlocks() { - $template = $this->getMockForAbstractClass('Twig_Template', array(), '', false); - $template->displayBlock('foo', array(), array('foo' => array(new stdClass(), 'foo'))); + $this->expectException('\LogicException'); + + $twig = new Environment($this->createMock('\Twig\Loader\LoaderInterface')); + $template = new TemplateForTest($twig); + $template->displayBlock('foo', [], ['foo' => [new \stdClass(), 'foo']]); } /** @@ -24,48 +39,49 @@ class Twig_Tests_TemplateTest extends \PHPUnit\Framework\TestCase */ public function testGetAttributeExceptions($template, $message) { - $templates = array('index' => $template); - $env = new Twig_Environment(new Twig_Loader_Array($templates), array('strict_variables' => true)); - $template = $env->loadTemplate('index'); + $templates = ['index' => $template]; + $env = new Environment(new ArrayLoader($templates), ['strict_variables' => true]); + $template = $env->load('index'); - $context = array( + $context = [ 'string' => 'foo', 'null' => null, - 'empty_array' => array(), - 'array' => array('foo' => 'foo'), - 'array_access' => new Twig_TemplateArrayAccessObject(), - 'magic_exception' => new Twig_TemplateMagicPropertyObjectWithException(), - 'object' => new stdClass(), - ); + 'empty_array' => [], + 'array' => ['foo' => 'foo'], + 'array_access' => new TemplateArrayAccessObject(), + 'magic_exception' => new TemplateMagicPropertyObjectWithException(), + 'object' => new \stdClass(), + ]; try { $template->render($context); $this->fail('Accessing an invalid attribute should throw an exception.'); - } catch (Twig_Error_Runtime $e) { + } catch (RuntimeError $e) { $this->assertSame(sprintf($message, 'index'), $e->getMessage()); } } public function getAttributeExceptions() { - return array( - array('{{ string["a"] }}', 'Impossible to access a key ("a") on a string variable ("foo") in "%s" at line 1.'), - array('{{ null["a"] }}', 'Impossible to access a key ("a") on a null variable in "%s" at line 1.'), - array('{{ empty_array["a"] }}', 'Key "a" does not exist as the array is empty in "%s" at line 1.'), - array('{{ array["a"] }}', 'Key "a" for array with keys "foo" does not exist in "%s" at line 1.'), - array('{{ array_access["a"] }}', 'Key "a" in object with ArrayAccess of class "Twig_TemplateArrayAccessObject" does not exist in "%s" at line 1.'), - array('{{ string.a }}', 'Impossible to access an attribute ("a") on a string variable ("foo") in "%s" at line 1.'), - array('{{ string.a() }}', 'Impossible to invoke a method ("a") on a string variable ("foo") in "%s" at line 1.'), - array('{{ null.a }}', 'Impossible to access an attribute ("a") on a null variable in "%s" at line 1.'), - array('{{ null.a() }}', 'Impossible to invoke a method ("a") on a null variable in "%s" at line 1.'), - array('{{ empty_array.a }}', 'Key "a" does not exist as the array is empty in "%s" at line 1.'), - array('{{ array.a }}', 'Key "a" for array with keys "foo" does not exist in "%s" at line 1.'), - array('{{ attribute(array, -10) }}', 'Key "-10" for array with keys "foo" does not exist in "%s" at line 1.'), - array('{{ array_access.a }}', 'Neither the property "a" nor one of the methods "a()", "geta()"/"isa()" or "__call()" exist and have public access in class "Twig_TemplateArrayAccessObject" in "%s" at line 1.'), - array('{% from _self import foo %}{% macro foo(obj) %}{{ obj.missing_method() }}{% endmacro %}{{ foo(array_access) }}', 'Neither the property "missing_method" nor one of the methods "missing_method()", "getmissing_method()"/"ismissing_method()" or "__call()" exist and have public access in class "Twig_TemplateArrayAccessObject" in "%s" at line 1.'), - array('{{ magic_exception.test }}', 'An exception has been thrown during the rendering of a template ("Hey! Don\'t try to isset me!") in "%s" at line 1.'), - array('{{ object["a"] }}', 'Impossible to access a key "a" on an object of class "stdClass" that does not implement ArrayAccess interface in "%s" at line 1.'), - ); + return [ + ['{{ string["a"] }}', 'Impossible to access a key ("a") on a string variable ("foo") in "%s" at line 1.'], + ['{{ null["a"] }}', 'Impossible to access a key ("a") on a null variable in "%s" at line 1.'], + ['{{ empty_array["a"] }}', 'Key "a" does not exist as the array is empty in "%s" at line 1.'], + ['{{ array["a"] }}', 'Key "a" for array with keys "foo" does not exist in "%s" at line 1.'], + ['{{ array_access["a"] }}', 'Key "a" in object with ArrayAccess of class "Twig\Tests\TemplateArrayAccessObject" does not exist in "%s" at line 1.'], + ['{{ string.a }}', 'Impossible to access an attribute ("a") on a string variable ("foo") in "%s" at line 1.'], + ['{{ string.a() }}', 'Impossible to invoke a method ("a") on a string variable ("foo") in "%s" at line 1.'], + ['{{ null.a }}', 'Impossible to access an attribute ("a") on a null variable in "%s" at line 1.'], + ['{{ null.a() }}', 'Impossible to invoke a method ("a") on a null variable in "%s" at line 1.'], + ['{{ array.a() }}', 'Impossible to invoke a method ("a") on an array in "%s" at line 1.'], + ['{{ empty_array.a }}', 'Key "a" does not exist as the array is empty in "%s" at line 1.'], + ['{{ array.a }}', 'Key "a" for array with keys "foo" does not exist in "%s" at line 1.'], + ['{{ attribute(array, -10) }}', 'Key "-10" for array with keys "foo" does not exist in "%s" at line 1.'], + ['{{ array_access.a }}', 'Neither the property "a" nor one of the methods "a()", "geta()"/"isa()" or "__call()" exist and have public access in class "Twig\Tests\TemplateArrayAccessObject" in "%s" at line 1.'], + ['{% from _self import foo %}{% macro foo(obj) %}{{ obj.missing_method() }}{% endmacro %}{{ foo(array_access) }}', 'Neither the property "missing_method" nor one of the methods "missing_method()", "getmissing_method()"/"ismissing_method()" or "__call()" exist and have public access in class "Twig\Tests\TemplateArrayAccessObject" in "%s" at line 1.'], + ['{{ magic_exception.test }}', 'An exception has been thrown during the rendering of a template ("Hey! Don\'t try to isset me!") in "%s" at line 1.'], + ['{{ object["a"] }}', 'Impossible to access a key "a" on an object of class "stdClass" that does not implement ArrayAccess interface in "%s" at line 1.'], + ]; } /** @@ -73,38 +89,38 @@ class Twig_Tests_TemplateTest extends \PHPUnit\Framework\TestCase */ public function testGetAttributeWithSandbox($object, $item, $allowed) { - $twig = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock()); - $policy = new Twig_Sandbox_SecurityPolicy(array(), array(), array(/*method*/), array(/*prop*/), array()); - $twig->addExtension(new Twig_Extension_Sandbox($policy, !$allowed)); - $template = new Twig_TemplateTest($twig); + $twig = new Environment($this->createMock('\Twig\Loader\LoaderInterface')); + $policy = new SecurityPolicy([], [], [/*method*/], [/*prop*/], []); + $twig->addExtension(new SandboxExtension($policy, !$allowed)); + $template = new TemplateForTest($twig); try { - $template->getAttribute($object, $item, array(), 'any'); + $template->getAttribute($object, $item, [], 'any'); if (!$allowed) { $this->fail(); } else { $this->addToAssertionCount(1); } - } catch (Twig_Sandbox_SecurityError $e) { + } catch (SecurityError $e) { if ($allowed) { $this->fail(); } else { $this->addToAssertionCount(1); } - $this->assertContains('is not allowed', $e->getMessage()); + $this->assertStringContainsString('is not allowed', $e->getMessage()); } } public function getGetAttributeWithSandbox() { - return array( - array(new Twig_TemplatePropertyObject(), 'defined', false), - array(new Twig_TemplatePropertyObject(), 'defined', true), - array(new Twig_TemplateMethodObject(), 'defined', false), - array(new Twig_TemplateMethodObject(), 'defined', true), - ); + return [ + [new TemplatePropertyObject(), 'defined', false], + [new TemplatePropertyObject(), 'defined', true], + [new TemplateMethodObject(), 'defined', false], + [new TemplateMethodObject(), 'defined', true], + ]; } /** @@ -113,28 +129,28 @@ class Twig_Tests_TemplateTest extends \PHPUnit\Framework\TestCase public function testGetAttributeWithTemplateAsObject() { // to be removed in 2.0 - $twig = new Twig_Environment($this->getMockBuilder('Twig_TemplateTestLoaderInterface')->getMock()); - //$twig = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface', 'Twig_SourceContextLoaderInterface')->getMock()); + $twig = new Environment($this->createMock('Twig\Tests\TemplateTestLoaderInterface')); + //$twig = new Environment($this->createMock('\Twig\Loader\LoaderInterface', '\Twig\Loader\SourceContextLoaderInterface')); - $template = new Twig_TemplateTest($twig, 'index.twig'); - $template1 = new Twig_TemplateTest($twig, 'index1.twig'); + $template = new TemplateForTest($twig, 'index.twig'); + $template1 = new TemplateForTest($twig, 'index1.twig'); - $this->assertInstanceof('Twig_Markup', $template->getAttribute($template1, 'string')); + $this->assertInstanceOf('\Twig\Markup', $template->getAttribute($template1, 'string')); $this->assertEquals('some_string', $template->getAttribute($template1, 'string')); - $this->assertInstanceof('Twig_Markup', $template->getAttribute($template1, 'true')); + $this->assertInstanceOf('\Twig\Markup', $template->getAttribute($template1, 'true')); $this->assertEquals('1', $template->getAttribute($template1, 'true')); - $this->assertInstanceof('Twig_Markup', $template->getAttribute($template1, 'zero')); + $this->assertInstanceOf('\Twig\Markup', $template->getAttribute($template1, 'zero')); $this->assertEquals('0', $template->getAttribute($template1, 'zero')); - $this->assertNotInstanceof('Twig_Markup', $template->getAttribute($template1, 'empty')); + $this->assertNotInstanceof('\Twig\Markup', $template->getAttribute($template1, 'empty')); $this->assertSame('', $template->getAttribute($template1, 'empty')); - $this->assertFalse($template->getAttribute($template1, 'env', array(), Twig_Template::ANY_CALL, true)); - $this->assertFalse($template->getAttribute($template1, 'environment', array(), Twig_Template::ANY_CALL, true)); - $this->assertFalse($template->getAttribute($template1, 'getEnvironment', array(), Twig_Template::METHOD_CALL, true)); - $this->assertFalse($template->getAttribute($template1, 'displayWithErrorHandling', array(), Twig_Template::METHOD_CALL, true)); + $this->assertFalse($template->getAttribute($template1, 'env', [], Template::ANY_CALL, true)); + $this->assertFalse($template->getAttribute($template1, 'environment', [], Template::ANY_CALL, true)); + $this->assertFalse($template->getAttribute($template1, 'getEnvironment', [], Template::METHOD_CALL, true)); + $this->assertFalse($template->getAttribute($template1, 'displayWithErrorHandling', [], Template::METHOD_CALL, true)); } /** @@ -161,43 +177,43 @@ class Twig_Tests_TemplateTest extends \PHPUnit\Framework\TestCase public function testGetAttributeWithTemplateAsObjectForDeprecations() { // to be removed in 2.0 - $twig = new Twig_Environment($this->getMockBuilder('Twig_TemplateTestLoaderInterface')->getMock()); - //$twig = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface', 'Twig_SourceContextLoaderInterface')->getMock()); + $twig = new Environment($this->createMock('Twig\Tests\TemplateTestLoaderInterface')); + //$twig = new Environment($this->createMock('\Twig\Loader\LoaderInterface', '\Twig\Loader\SourceContextLoaderInterface')); - $template = new Twig_TemplateTest($twig, 'index.twig'); - $template1 = new Twig_TemplateTest($twig, 'index1.twig'); + $template = new TemplateForTest($twig, 'index.twig'); + $template1 = new TemplateForTest($twig, 'index1.twig'); - $this->assertInstanceof('Twig_Markup', $template->getAttribute($template1, 'string')); + $this->assertInstanceOf('\Twig\Markup', $template->getAttribute($template1, 'string')); $this->assertEquals('some_string', $template->getAttribute($template1, 'string')); - $this->assertInstanceof('Twig_Markup', $template->getAttribute($template1, 'true')); + $this->assertInstanceOf('\Twig\Markup', $template->getAttribute($template1, 'true')); $this->assertEquals('1', $template->getAttribute($template1, 'true')); - $this->assertInstanceof('Twig_Markup', $template->getAttribute($template1, 'zero')); + $this->assertInstanceOf('\Twig\Markup', $template->getAttribute($template1, 'zero')); $this->assertEquals('0', $template->getAttribute($template1, 'zero')); - $this->assertNotInstanceof('Twig_Markup', $template->getAttribute($template1, 'empty')); + $this->assertNotInstanceof('\Twig\Markup', $template->getAttribute($template1, 'empty')); $this->assertSame('', $template->getAttribute($template1, 'empty')); - $blocks = array('name' => array($template1, 'block_name')); + $blocks = ['name' => [$template1, 'block_name']]; // trigger some deprecation notice messages to check them with @expectedDeprecation - $template->getAttribute($template, 'renderBlock', array('name', array(), $blocks)); - $template->getAttribute($template, 'displayBlock', array('name', array(), $blocks)); - $template->getAttribute($template, 'hasBlock', array('name', array())); - $template->getAttribute($template, 'render', array(array())); - $template->getAttribute($template, 'display', array(array())); + $template->getAttribute($template, 'renderBlock', ['name', [], $blocks]); + $template->getAttribute($template, 'displayBlock', ['name', [], $blocks]); + $template->getAttribute($template, 'hasBlock', ['name', []]); + $template->getAttribute($template, 'render', [[]]); + $template->getAttribute($template, 'display', [[]]); - $template->getAttribute($template1, 'renderBlock', array('name', array(), $blocks)); - $template->getAttribute($template1, 'displayBlock', array('name', array(), $blocks)); - $template->getAttribute($template1, 'hasBlock', array('name', array())); - $template->getAttribute($template1, 'render', array(array())); - $template->getAttribute($template1, 'display', array(array())); + $template->getAttribute($template1, 'renderBlock', ['name', [], $blocks]); + $template->getAttribute($template1, 'displayBlock', ['name', [], $blocks]); + $template->getAttribute($template1, 'hasBlock', ['name', []]); + $template->getAttribute($template1, 'render', [[]]); + $template->getAttribute($template1, 'display', [[]]); - $this->assertFalse($template->getAttribute($template1, 'env', array(), Twig_Template::ANY_CALL, true)); - $this->assertFalse($template->getAttribute($template1, 'environment', array(), Twig_Template::ANY_CALL, true)); - $this->assertFalse($template->getAttribute($template1, 'getEnvironment', array(), Twig_Template::METHOD_CALL, true)); - $this->assertFalse($template->getAttribute($template1, 'displayWithErrorHandling', array(), Twig_Template::METHOD_CALL, true)); + $this->assertFalse($template->getAttribute($template1, 'env', [], Template::ANY_CALL, true)); + $this->assertFalse($template->getAttribute($template1, 'environment', [], Template::ANY_CALL, true)); + $this->assertFalse($template->getAttribute($template1, 'getEnvironment', [], Template::METHOD_CALL, true)); + $this->assertFalse($template->getAttribute($template1, 'displayWithErrorHandling', [], Template::METHOD_CALL, true)); } /** @@ -207,18 +223,18 @@ class Twig_Tests_TemplateTest extends \PHPUnit\Framework\TestCase */ public function testRenderBlockWithUndefinedBlock() { - $twig = new Twig_Environment($this->getMockBuilder('Twig_TemplateTestLoaderInterface')->getMock()); + $twig = new Environment($this->createMock('Twig\Tests\TemplateTestLoaderInterface')); - $template = new Twig_TemplateTest($twig, 'index.twig'); - $template->renderBlock('unknown', array()); - $template->displayBlock('unknown', array()); + $template = new TemplateForTest($twig, 'index.twig'); + $template->renderBlock('unknown', []); + $template->displayBlock('unknown', []); } public function testGetAttributeOnArrayWithConfusableKey() { - $template = new Twig_TemplateTest(new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock())); + $template = new TemplateForTest(new Environment($this->createMock('\Twig\Loader\LoaderInterface'))); - $array = array('Zero', 'One', -1 => 'MinusOne', '' => 'EmptyString', '1.5' => 'FloatButString', '01' => 'IntegerButStringWithLeadingZeros'); + $array = ['Zero', 'One', -1 => 'MinusOne', '' => 'EmptyString', '1.5' => 'FloatButString', '01' => 'IntegerButStringWithLeadingZeros']; $this->assertSame('Zero', $array[false]); $this->assertSame('One', $array[true]); @@ -244,7 +260,7 @@ class Twig_Tests_TemplateTest extends \PHPUnit\Framework\TestCase */ public function testGetAttribute($defined, $value, $object, $item, $arguments, $type) { - $template = new Twig_TemplateTest(new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock())); + $template = new TemplateForTest(new Environment($this->createMock('\Twig\Loader\LoaderInterface'))); $this->assertEquals($value, $template->getAttribute($object, $item, $arguments, $type)); } @@ -254,18 +270,14 @@ class Twig_Tests_TemplateTest extends \PHPUnit\Framework\TestCase */ public function testGetAttributeStrict($defined, $value, $object, $item, $arguments, $type, $exceptionMessage = null) { - $template = new Twig_TemplateTest(new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock(), array('strict_variables' => true))); + $template = new TemplateForTest(new Environment($this->createMock('\Twig\Loader\LoaderInterface'), ['strict_variables' => true])); if ($defined) { $this->assertEquals($value, $template->getAttribute($object, $item, $arguments, $type)); } else { - if (method_exists($this, 'expectException')) { - $this->expectException('Twig_Error_Runtime'); - if (null !== $exceptionMessage) { - $this->expectExceptionMessage($exceptionMessage); - } - } else { - $this->setExpectedException('Twig_Error_Runtime', $exceptionMessage); + $this->expectException('\Twig\Error\RuntimeError'); + if (null !== $exceptionMessage) { + $this->expectExceptionMessage($exceptionMessage); } $this->assertEquals($value, $template->getAttribute($object, $item, $arguments, $type)); } @@ -276,7 +288,7 @@ class Twig_Tests_TemplateTest extends \PHPUnit\Framework\TestCase */ public function testGetAttributeDefined($defined, $value, $object, $item, $arguments, $type) { - $template = new Twig_TemplateTest(new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock())); + $template = new TemplateForTest(new Environment($this->createMock('\Twig\Loader\LoaderInterface'))); $this->assertEquals($defined, $template->getAttribute($object, $item, $arguments, $type, true)); } @@ -286,23 +298,23 @@ class Twig_Tests_TemplateTest extends \PHPUnit\Framework\TestCase */ public function testGetAttributeDefinedStrict($defined, $value, $object, $item, $arguments, $type) { - $template = new Twig_TemplateTest(new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock(), array('strict_variables' => true))); + $template = new TemplateForTest(new Environment($this->createMock('\Twig\Loader\LoaderInterface'), ['strict_variables' => true])); $this->assertEquals($defined, $template->getAttribute($object, $item, $arguments, $type, true)); } public function testGetAttributeCallExceptions() { - $template = new Twig_TemplateTest(new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock())); + $template = new TemplateForTest(new Environment($this->createMock('\Twig\Loader\LoaderInterface'))); - $object = new Twig_TemplateMagicMethodExceptionObject(); + $object = new TemplateMagicMethodExceptionObject(); $this->assertNull($template->getAttribute($object, 'foo')); } public function getGetAttributeTests() { - $array = array( + $array = [ 'defined' => 'defined', 'zero' => 0, 'null' => null, @@ -311,54 +323,56 @@ class Twig_Tests_TemplateTest extends \PHPUnit\Framework\TestCase 'baz' => 'baz', '09' => '09', '+4' => '+4', - ); + ]; - $objectArray = new Twig_TemplateArrayAccessObject(); + $objectArray = new TemplateArrayAccessObject(); + $arrayObject = new \ArrayObject($array); $stdObject = (object) $array; - $magicPropertyObject = new Twig_TemplateMagicPropertyObject(); - $propertyObject = new Twig_TemplatePropertyObject(); - $propertyObject1 = new Twig_TemplatePropertyObjectAndIterator(); - $propertyObject2 = new Twig_TemplatePropertyObjectAndArrayAccess(); - $propertyObject3 = new Twig_TemplatePropertyObjectDefinedWithUndefinedValue(); - $methodObject = new Twig_TemplateMethodObject(); - $magicMethodObject = new Twig_TemplateMagicMethodObject(); - - $anyType = Twig_Template::ANY_CALL; - $methodType = Twig_Template::METHOD_CALL; - $arrayType = Twig_Template::ARRAY_CALL; - - $basicTests = array( + $magicPropertyObject = new TemplateMagicPropertyObject(); + $propertyObject = new TemplatePropertyObject(); + $propertyObject1 = new TemplatePropertyObjectAndIterator(); + $propertyObject2 = new TemplatePropertyObjectAndArrayAccess(); + $propertyObject3 = new TemplatePropertyObjectDefinedWithUndefinedValue(); + $methodObject = new TemplateMethodObject(); + $magicMethodObject = new TemplateMagicMethodObject(); + + $anyType = Template::ANY_CALL; + $methodType = Template::METHOD_CALL; + $arrayType = Template::ARRAY_CALL; + + $basicTests = [ // array(defined, value, property to fetch) - array(true, 'defined', 'defined'), - array(false, null, 'undefined'), - array(false, null, 'protected'), - array(true, 0, 'zero'), - array(true, 1, 1), - array(true, 1, 1.0), - array(true, null, 'null'), - array(true, true, 'bar'), - array(true, 'baz', 'baz'), - array(true, '09', '09'), - array(true, '+4', '+4'), - ); - $testObjects = array( + [true, 'defined', 'defined'], + [false, null, 'undefined'], + [false, null, 'protected'], + [true, 0, 'zero'], + [true, 1, 1], + [true, 1, 1.0], + [true, null, 'null'], + [true, true, 'bar'], + [true, 'baz', 'baz'], + [true, '09', '09'], + [true, '+4', '+4'], + ]; + $testObjects = [ // array(object, type of fetch) - array($array, $arrayType), - array($objectArray, $arrayType), - array($stdObject, $anyType), - array($magicPropertyObject, $anyType), - array($methodObject, $methodType), - array($methodObject, $anyType), - array($propertyObject, $anyType), - array($propertyObject1, $anyType), - array($propertyObject2, $anyType), - ); - - $tests = array(); + [$array, $arrayType], + [$objectArray, $arrayType], + [$arrayObject, $anyType], + [$stdObject, $anyType], + [$magicPropertyObject, $anyType], + [$methodObject, $methodType], + [$methodObject, $anyType], + [$propertyObject, $anyType], + [$propertyObject1, $anyType], + [$propertyObject2, $anyType], + ]; + + $tests = []; foreach ($testObjects as $testObject) { foreach ($basicTests as $test) { // properties cannot be numbers - if (($testObject[0] instanceof stdClass || $testObject[0] instanceof Twig_TemplatePropertyObject) && is_numeric($test[2])) { + if (($testObject[0] instanceof \stdClass || $testObject[0] instanceof TemplatePropertyObject) && is_numeric($test[2])) { continue; } @@ -366,27 +380,27 @@ class Twig_Tests_TemplateTest extends \PHPUnit\Framework\TestCase continue; } - $tests[] = array($test[0], $test[1], $testObject[0], $test[2], array(), $testObject[1]); + $tests[] = [$test[0], $test[1], $testObject[0], $test[2], [], $testObject[1]]; } } // additional properties tests - $tests = array_merge($tests, array( - array(true, null, $propertyObject3, 'foo', array(), $anyType), - )); + $tests = array_merge($tests, [ + [true, null, $propertyObject3, 'foo', [], $anyType], + ]); // additional method tests - $tests = array_merge($tests, array( - array(true, 'defined', $methodObject, 'defined', array(), $methodType), - array(true, 'defined', $methodObject, 'DEFINED', array(), $methodType), - array(true, 'defined', $methodObject, 'getDefined', array(), $methodType), - array(true, 'defined', $methodObject, 'GETDEFINED', array(), $methodType), - array(true, 'static', $methodObject, 'static', array(), $methodType), - array(true, 'static', $methodObject, 'getStatic', array(), $methodType), - - array(true, '__call_undefined', $magicMethodObject, 'undefined', array(), $methodType), - array(true, '__call_UNDEFINED', $magicMethodObject, 'UNDEFINED', array(), $methodType), - )); + $tests = array_merge($tests, [ + [true, 'defined', $methodObject, 'defined', [], $methodType], + [true, 'defined', $methodObject, 'DEFINED', [], $methodType], + [true, 'defined', $methodObject, 'getDefined', [], $methodType], + [true, 'defined', $methodObject, 'GETDEFINED', [], $methodType], + [true, 'static', $methodObject, 'static', [], $methodType], + [true, 'static', $methodObject, 'getStatic', [], $methodType], + + [true, '__call_undefined', $magicMethodObject, 'undefined', [], $methodType], + [true, '__call_UNDEFINED', $magicMethodObject, 'UNDEFINED', [], $methodType], + ]); // add the same tests for the any type foreach ($tests as $test) { @@ -396,42 +410,46 @@ class Twig_Tests_TemplateTest extends \PHPUnit\Framework\TestCase } } - $methodAndPropObject = new Twig_TemplateMethodAndPropObject(); + $methodAndPropObject = new TemplateMethodAndPropObject(); // additional method tests - $tests = array_merge($tests, array( - array(true, 'a', $methodAndPropObject, 'a', array(), $anyType), - array(true, 'a', $methodAndPropObject, 'a', array(), $methodType), - array(false, null, $methodAndPropObject, 'a', array(), $arrayType), - - array(true, 'b_prop', $methodAndPropObject, 'b', array(), $anyType), - array(true, 'b', $methodAndPropObject, 'B', array(), $anyType), - array(true, 'b', $methodAndPropObject, 'b', array(), $methodType), - array(true, 'b', $methodAndPropObject, 'B', array(), $methodType), - array(false, null, $methodAndPropObject, 'b', array(), $arrayType), - - array(false, null, $methodAndPropObject, 'c', array(), $anyType), - array(false, null, $methodAndPropObject, 'c', array(), $methodType), - array(false, null, $methodAndPropObject, 'c', array(), $arrayType), - )); + $tests = array_merge($tests, [ + [true, 'a', $methodAndPropObject, 'a', [], $anyType], + [true, 'a', $methodAndPropObject, 'a', [], $methodType], + [false, null, $methodAndPropObject, 'a', [], $arrayType], + + [true, 'b_prop', $methodAndPropObject, 'b', [], $anyType], + [true, 'b', $methodAndPropObject, 'B', [], $anyType], + [true, 'b', $methodAndPropObject, 'b', [], $methodType], + [true, 'b', $methodAndPropObject, 'B', [], $methodType], + [false, null, $methodAndPropObject, 'b', [], $arrayType], + + [false, null, $methodAndPropObject, 'c', [], $anyType], + [false, null, $methodAndPropObject, 'c', [], $methodType], + [false, null, $methodAndPropObject, 'c', [], $arrayType], + ]); + + $arrayAccess = new TemplateArrayAccess(); + $tests = array_merge($tests, [ + [true, ['foo' => 'bar'], $arrayAccess, 'vars', [], $anyType], + ]); // tests when input is not an array or object - $tests = array_merge($tests, array( - array(false, null, 42, 'a', array(), $anyType, 'Impossible to access an attribute ("a") on a integer variable ("42") in "index.twig".'), - array(false, null, 'string', 'a', array(), $anyType, 'Impossible to access an attribute ("a") on a string variable ("string") in "index.twig".'), - array(false, null, array(), 'a', array(), $anyType, 'Key "a" does not exist as the array is empty in "index.twig".'), - )); + $tests = array_merge($tests, [ + [false, null, 42, 'a', [], $anyType, 'Impossible to access an attribute ("a") on a integer variable ("42") in "index.twig".'], + [false, null, 'string', 'a', [], $anyType, 'Impossible to access an attribute ("a") on a string variable ("string") in "index.twig".'], + [false, null, [], 'a', [], $anyType, 'Key "a" does not exist as the array is empty in "index.twig".'], + ]); return $tests; } - /** - * @expectedException Twig_Error_Runtime - */ public function testGetIsMethods() { - $getIsObject = new Twig_TemplateGetIsMethods(); - $template = new Twig_TemplateTest(new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock(), array('strict_variables' => true))); + $this->expectException('\Twig\Error\RuntimeError'); + + $getIsObject = new TemplateGetIsMethods(); + $template = new TemplateForTest(new Environment($this->createMock('\Twig\Loader\LoaderInterface'), ['strict_variables' => true])); // first time should not create a cache for "get" $this->assertNull($template->getAttribute($getIsObject, 'get')); // 0 should be in the method cache now, so this should fail @@ -439,14 +457,14 @@ class Twig_Tests_TemplateTest extends \PHPUnit\Framework\TestCase } } -class Twig_TemplateTest extends Twig_Template +class TemplateForTest extends Template { private $name; - public function __construct(Twig_Environment $env, $name = 'index.twig') + public function __construct(Environment $env, $name = 'index.twig') { parent::__construct($env); - self::$cache = array(); + self::$cache = []; $this->name = $name; } @@ -477,7 +495,7 @@ class Twig_TemplateTest extends Twig_Template public function getDebugInfo() { - return array(); + return []; } protected function doGetParent(array $context) @@ -485,29 +503,29 @@ class Twig_TemplateTest extends Twig_Template return false; } - protected function doDisplay(array $context, array $blocks = array()) + protected function doDisplay(array $context, array $blocks = []) { } - public function getAttribute($object, $item, array $arguments = array(), $type = Twig_Template::ANY_CALL, $isDefinedTest = false, $ignoreStrictCheck = false) + public function getAttribute($object, $item, array $arguments = [], $type = Template::ANY_CALL, $isDefinedTest = false, $ignoreStrictCheck = false) { - if (function_exists('twig_template_get_attributes')) { + if (\function_exists('twig_template_get_attributes')) { return twig_template_get_attributes($this, $object, $item, $arguments, $type, $isDefinedTest, $ignoreStrictCheck); } else { return parent::getAttribute($object, $item, $arguments, $type, $isDefinedTest, $ignoreStrictCheck); } } - public function block_name($context, array $blocks = array()) + public function block_name($context, array $blocks = []) { } } -class Twig_TemplateArrayAccessObject implements ArrayAccess +class TemplateArrayAccessObject implements \ArrayAccess { protected $protected = 'protected'; - public $attributes = array( + public $attributes = [ 'defined' => 'defined', 'zero' => 0, 'null' => null, @@ -516,16 +534,16 @@ class Twig_TemplateArrayAccessObject implements ArrayAccess 'baz' => 'baz', '09' => '09', '+4' => '+4', - ); + ]; public function offsetExists($name) { - return array_key_exists($name, $this->attributes); + return \array_key_exists($name, $this->attributes); } public function offsetGet($name) { - return array_key_exists($name, $this->attributes) ? $this->attributes[$name] : null; + return \array_key_exists($name, $this->attributes) ? $this->attributes[$name] : null; } public function offsetSet($name, $value) @@ -537,11 +555,11 @@ class Twig_TemplateArrayAccessObject implements ArrayAccess } } -class Twig_TemplateMagicPropertyObject +class TemplateMagicPropertyObject { public $defined = 'defined'; - public $attributes = array( + public $attributes = [ 'zero' => 0, 'null' => null, '1' => 1, @@ -549,30 +567,30 @@ class Twig_TemplateMagicPropertyObject 'baz' => 'baz', '09' => '09', '+4' => '+4', - ); + ]; protected $protected = 'protected'; public function __isset($name) { - return array_key_exists($name, $this->attributes); + return \array_key_exists($name, $this->attributes); } public function __get($name) { - return array_key_exists($name, $this->attributes) ? $this->attributes[$name] : null; + return \array_key_exists($name, $this->attributes) ? $this->attributes[$name] : null; } } -class Twig_TemplateMagicPropertyObjectWithException +class TemplateMagicPropertyObjectWithException { public function __isset($key) { - throw new Exception('Hey! Don\'t try to isset me!'); + throw new \Exception('Hey! Don\'t try to isset me!'); } } -class Twig_TemplatePropertyObject +class TemplatePropertyObject { public $defined = 'defined'; public $zero = 0; @@ -583,27 +601,29 @@ class Twig_TemplatePropertyObject protected $protected = 'protected'; } -class Twig_TemplatePropertyObjectAndIterator extends Twig_TemplatePropertyObject implements IteratorAggregate +class TemplatePropertyObjectAndIterator extends TemplatePropertyObject implements \IteratorAggregate { public function getIterator() { - return new ArrayIterator(array('foo', 'bar')); + return new \ArrayIterator(['foo', 'bar']); } } -class Twig_TemplatePropertyObjectAndArrayAccess extends Twig_TemplatePropertyObject implements ArrayAccess +class TemplatePropertyObjectAndArrayAccess extends TemplatePropertyObject implements \ArrayAccess { - private $data = array( + private $data = [ 'defined' => 'defined', 'zero' => 0, 'null' => null, 'bar' => true, + 'foo' => true, 'baz' => 'baz', - ); + 'baf' => 'baf', + ]; public function offsetExists($offset) { - return array_key_exists($offset, $this->data); + return \array_key_exists($offset, $this->data); } public function offsetGet($offset) @@ -620,7 +640,7 @@ class Twig_TemplatePropertyObjectAndArrayAccess extends Twig_TemplatePropertyObj } } -class Twig_TemplatePropertyObjectDefinedWithUndefinedValue +class TemplatePropertyObjectDefinedWithUndefinedValue { public $foo; @@ -630,7 +650,7 @@ class Twig_TemplatePropertyObjectDefinedWithUndefinedValue } } -class Twig_TemplateMethodObject +class TemplateMethodObject { public function getDefined() { @@ -682,7 +702,7 @@ class Twig_TemplateMethodObject } } -class Twig_TemplateGetIsMethods +class TemplateGetIsMethods { public function get() { @@ -693,7 +713,7 @@ class Twig_TemplateGetIsMethods } } -class Twig_TemplateMethodAndPropObject +class TemplateMethodAndPropObject { private $a = 'a_prop'; @@ -717,7 +737,35 @@ class Twig_TemplateMethodAndPropObject } } -class Twig_TemplateMagicMethodObject +class TemplateArrayAccess implements \ArrayAccess +{ + public $vars = [ + 'foo' => 'bar', + ]; + private $children = []; + + public function offsetExists($offset) + { + return \array_key_exists($offset, $this->children); + } + + public function offsetGet($offset) + { + return $this->children[$offset]; + } + + public function offsetSet($offset, $value) + { + $this->children[$offset] = $value; + } + + public function offsetUnset($offset) + { + unset($this->children[$offset]); + } +} + +class TemplateMagicMethodObject { public function __call($method, $arguments) { @@ -725,26 +773,26 @@ class Twig_TemplateMagicMethodObject } } -class Twig_TemplateMagicMethodExceptionObject +class TemplateMagicMethodExceptionObject { public function __call($method, $arguments) { - throw new BadMethodCallException(sprintf('Unknown method "%s".', $method)); + throw new \BadMethodCallException(sprintf('Unknown method "%s".', $method)); } } -class CExtDisablingNodeVisitor implements Twig_NodeVisitorInterface +class CExtDisablingNodeVisitor implements NodeVisitorInterface { - public function enterNode(Twig_NodeInterface $node, Twig_Environment $env) + public function enterNode(\Twig_NodeInterface $node, Environment $env) { - if ($node instanceof Twig_Node_Expression_GetAttr) { + if ($node instanceof GetAttrExpression) { $node->setAttribute('disable_c_ext', true); } return $node; } - public function leaveNode(Twig_NodeInterface $node, Twig_Environment $env) + public function leaveNode(\Twig_NodeInterface $node, Environment $env) { return $node; } @@ -756,6 +804,6 @@ class CExtDisablingNodeVisitor implements Twig_NodeVisitorInterface } // to be removed in 2.0 -interface Twig_TemplateTestLoaderInterface extends Twig_LoaderInterface, Twig_SourceContextLoaderInterface +interface TemplateTestLoaderInterface extends LoaderInterface, SourceContextLoaderInterface { } diff --git a/vendor/twig/twig/test/Twig/Tests/TemplateWrapperTest.php b/vendor/twig/twig/tests/TemplateWrapperTest.php similarity index 57% rename from vendor/twig/twig/test/Twig/Tests/TemplateWrapperTest.php rename to vendor/twig/twig/tests/TemplateWrapperTest.php index cc71052c412604352cbb7ba6115c85a153baa765..b4a0958b501c126ee7fe1728bb40c652439a7764 100644 --- a/vendor/twig/twig/test/Twig/Tests/TemplateWrapperTest.php +++ b/vendor/twig/twig/tests/TemplateWrapperTest.php @@ -1,5 +1,7 @@ <?php +namespace Twig\Tests; + /* * This file is part of Twig. * @@ -8,56 +10,60 @@ * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ -class Twig_Tests_TemplateWrapperTest extends \PHPUnit\Framework\TestCase + +use Twig\Environment; +use Twig\Loader\ArrayLoader; + +class TemplateWrapperTest extends \PHPUnit\Framework\TestCase { public function testHasGetBlocks() { - $twig = new Twig_Environment(new Twig_Loader_Array(array( + $twig = new Environment(new ArrayLoader([ 'index' => '{% block foo %}{% endblock %}', 'index_with_use' => '{% use "imported" %}{% block foo %}{% endblock %}', 'index_with_extends' => '{% extends "extended" %}{% block foo %}{% endblock %}', 'imported' => '{% block imported %}{% endblock %}', 'extended' => '{% block extended %}{% endblock %}', - ))); + ])); - $wrapper = new Twig_TemplateWrapper($twig, $twig->loadTemplate('index')); + $wrapper = $twig->load('index'); $this->assertTrue($wrapper->hasBlock('foo')); $this->assertFalse($wrapper->hasBlock('bar')); - $this->assertEquals(array('foo'), $wrapper->getBlockNames()); + $this->assertEquals(['foo'], $wrapper->getBlockNames()); - $wrapper = new Twig_TemplateWrapper($twig, $twig->loadTemplate('index_with_use')); + $wrapper = $twig->load('index_with_use'); $this->assertTrue($wrapper->hasBlock('foo')); $this->assertTrue($wrapper->hasBlock('imported')); - $this->assertEquals(array('imported', 'foo'), $wrapper->getBlockNames()); + $this->assertEquals(['imported', 'foo'], $wrapper->getBlockNames()); - $wrapper = new Twig_TemplateWrapper($twig, $twig->loadTemplate('index_with_extends')); + $wrapper = $twig->load('index_with_extends'); $this->assertTrue($wrapper->hasBlock('foo')); $this->assertTrue($wrapper->hasBlock('extended')); - $this->assertEquals(array('foo', 'extended'), $wrapper->getBlockNames()); + $this->assertEquals(['foo', 'extended'], $wrapper->getBlockNames()); } public function testRenderBlock() { - $twig = new Twig_Environment(new Twig_Loader_Array(array( + $twig = new Environment(new ArrayLoader([ 'index' => '{% block foo %}{{ foo }}{{ bar }}{% endblock %}', - ))); + ])); $twig->addGlobal('bar', 'BAR'); - $wrapper = new Twig_TemplateWrapper($twig, $twig->loadTemplate('index')); - $this->assertEquals('FOOBAR', $wrapper->renderBlock('foo', array('foo' => 'FOO'))); + $wrapper = $twig->load('index'); + $this->assertEquals('FOOBAR', $wrapper->renderBlock('foo', ['foo' => 'FOO'])); } public function testDisplayBlock() { - $twig = new Twig_Environment(new Twig_Loader_Array(array( + $twig = new Environment(new ArrayLoader([ 'index' => '{% block foo %}{{ foo }}{{ bar }}{% endblock %}', - ))); + ])); $twig->addGlobal('bar', 'BAR'); - $wrapper = new Twig_TemplateWrapper($twig, $twig->loadTemplate('index')); + $wrapper = $twig->load('index'); ob_start(); - $wrapper->displayBlock('foo', array('foo' => 'FOO')); + $wrapper->displayBlock('foo', ['foo' => 'FOO']); $this->assertEquals('FOOBAR', ob_get_clean()); } diff --git a/vendor/twig/twig/test/Twig/Tests/TokenStreamTest.php b/vendor/twig/twig/tests/TokenStreamTest.php similarity index 51% rename from vendor/twig/twig/test/Twig/Tests/TokenStreamTest.php rename to vendor/twig/twig/tests/TokenStreamTest.php index f219c9554b280d510c22c06d9d67af4f35fa9c71..c98e0f0720d256a7465b1b17345344b7bb7bdccf 100644 --- a/vendor/twig/twig/test/Twig/Tests/TokenStreamTest.php +++ b/vendor/twig/twig/tests/TokenStreamTest.php @@ -1,5 +1,7 @@ <?php +namespace Twig\Tests; + /* * This file is part of Twig. * @@ -9,22 +11,25 @@ * file that was distributed with this source code. */ -class Twig_Tests_TokenStreamTest extends \PHPUnit\Framework\TestCase +use Twig\Token; +use Twig\TokenStream; + +class TokenStreamTest extends \PHPUnit\Framework\TestCase { protected static $tokens; protected function setUp() { - self::$tokens = array( - new Twig_Token(Twig_Token::TEXT_TYPE, 1, 1), - new Twig_Token(Twig_Token::TEXT_TYPE, 2, 1), - new Twig_Token(Twig_Token::TEXT_TYPE, 3, 1), - new Twig_Token(Twig_Token::TEXT_TYPE, 4, 1), - new Twig_Token(Twig_Token::TEXT_TYPE, 5, 1), - new Twig_Token(Twig_Token::TEXT_TYPE, 6, 1), - new Twig_Token(Twig_Token::TEXT_TYPE, 7, 1), - new Twig_Token(Twig_Token::EOF_TYPE, 0, 1), - ); + self::$tokens = [ + new Token(Token::TEXT_TYPE, 1, 1), + new Token(Token::TEXT_TYPE, 2, 1), + new Token(Token::TEXT_TYPE, 3, 1), + new Token(Token::TEXT_TYPE, 4, 1), + new Token(Token::TEXT_TYPE, 5, 1), + new Token(Token::TEXT_TYPE, 6, 1), + new Token(Token::TEXT_TYPE, 7, 1), + new Token(Token::EOF_TYPE, 0, 1), + ]; } /** @@ -32,7 +37,7 @@ class Twig_Tests_TokenStreamTest extends \PHPUnit\Framework\TestCase */ public function testLegacyConstructorSignature() { - $stream = new Twig_TokenStream(array(), 'foo', '{{ foo }}'); + $stream = new TokenStream([], 'foo', '{{ foo }}'); $this->assertEquals('foo', $stream->getFilename()); $this->assertEquals('{{ foo }}', $stream->getSource()); $this->assertEquals('foo', $stream->getSourceContext()->getName()); @@ -41,8 +46,8 @@ class Twig_Tests_TokenStreamTest extends \PHPUnit\Framework\TestCase public function testNext() { - $stream = new Twig_TokenStream(self::$tokens); - $repr = array(); + $stream = new TokenStream(self::$tokens); + $repr = []; while (!$stream->isEOF()) { $token = $stream->next(); @@ -51,29 +56,27 @@ class Twig_Tests_TokenStreamTest extends \PHPUnit\Framework\TestCase $this->assertEquals('1, 2, 3, 4, 5, 6, 7', implode(', ', $repr), '->next() advances the pointer and returns the current token'); } - /** - * @expectedException Twig_Error_Syntax - * @expectedExceptionMessage Unexpected end of template - */ public function testEndOfTemplateNext() { - $stream = new Twig_TokenStream(array( - new Twig_Token(Twig_Token::BLOCK_START_TYPE, 1, 1), - )); + $this->expectException('\Twig\Error\SyntaxError'); + $this->expectExceptionMessage('Unexpected end of template'); + + $stream = new TokenStream([ + new Token(Token::BLOCK_START_TYPE, 1, 1), + ]); while (!$stream->isEOF()) { $stream->next(); } } - /** - * @expectedException Twig_Error_Syntax - * @expectedExceptionMessage Unexpected end of template - */ public function testEndOfTemplateLook() { - $stream = new Twig_TokenStream(array( - new Twig_Token(Twig_Token::BLOCK_START_TYPE, 1, 1), - )); + $this->expectException('\Twig\Error\SyntaxError'); + $this->expectExceptionMessage('Unexpected end of template'); + + $stream = new TokenStream([ + new Token(Token::BLOCK_START_TYPE, 1, 1), + ]); while (!$stream->isEOF()) { $stream->look(); $stream->next(); diff --git a/vendor/twig/twig/tests/Util/DeprecationCollectorTest.php b/vendor/twig/twig/tests/Util/DeprecationCollectorTest.php new file mode 100644 index 0000000000000000000000000000000000000000..e360dbb141a47186d0454109162ae3a19de5aebc --- /dev/null +++ b/vendor/twig/twig/tests/Util/DeprecationCollectorTest.php @@ -0,0 +1,48 @@ +<?php + +namespace Twig\Tests\Util; + +/* + * This file is part of Twig. + * + * (c) Fabien Potencier + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use Twig\Environment; +use Twig\TwigFunction; +use Twig\Util\DeprecationCollector; + +class DeprecationCollectorTest extends \PHPUnit\Framework\TestCase +{ + /** + * @requires PHP 5.3 + */ + public function testCollect() + { + $twig = new Environment($this->createMock('\Twig\Loader\LoaderInterface')); + $twig->addFunction(new TwigFunction('deprec', [$this, 'deprec'], ['deprecated' => true])); + + $collector = new DeprecationCollector($twig); + $deprecations = $collector->collect(new Twig_Tests_Util_Iterator()); + + $this->assertEquals(['Twig Function "deprec" is deprecated in deprec.twig at line 1.'], $deprecations); + } + + public function deprec() + { + } +} + +class Twig_Tests_Util_Iterator implements \IteratorAggregate +{ + public function getIterator() + { + return new \ArrayIterator([ + 'ok.twig' => '{{ foo }}', + 'deprec.twig' => '{{ deprec("foo") }}', + ]); + } +} diff --git a/vendor/twig/twig/test/Twig/Tests/escapingTest.php b/vendor/twig/twig/tests/escapingTest.php similarity index 84% rename from vendor/twig/twig/test/Twig/Tests/escapingTest.php rename to vendor/twig/twig/tests/escapingTest.php index 9b98dddcf132379501969c06079524207e83059a..84759ebb48436ce9038cd9691112f4e49d005dd6 100644 --- a/vendor/twig/twig/test/Twig/Tests/escapingTest.php +++ b/vendor/twig/twig/tests/escapingTest.php @@ -1,28 +1,31 @@ <?php +namespace Twig\Tests; + /** * This class is adapted from code coming from Zend Framework. * - * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (http://www.zend.com) - * @license http://framework.zend.com/license/new-bsd New BSD License + * @copyright Copyright (c) 2005-2012 Zend Technologies USA Inc. (https://www.zend.com) + * @license https://framework.zend.com/license/new-bsd New BSD License */ class Twig_Test_EscapingTest extends \PHPUnit\Framework\TestCase { /** * All character encodings supported by htmlspecialchars(). */ - protected $htmlSpecialChars = array( + protected $htmlSpecialChars = [ '\'' => ''', '"' => '"', '<' => '<', '>' => '>', '&' => '&', - ); + ]; - protected $htmlAttrSpecialChars = array( + protected $htmlAttrSpecialChars = [ '\'' => ''', /* Characters beyond ASCII value 255 to unicode escape */ 'Ä€' => 'Ā', + '😀' => '😀', /* Immune chars excluded */ ',' => ',', '.' => '.', @@ -47,17 +50,19 @@ class Twig_Test_EscapingTest extends \PHPUnit\Framework\TestCase '"' => '"', /* Encode spaces for quoteless attribute protection */ ' ' => ' ', - ); + ]; - protected $jsSpecialChars = array( + protected $jsSpecialChars = [ /* HTML special chars - escape without exception to hex */ - '<' => '\\x3C', - '>' => '\\x3E', - '\'' => '\\x27', - '"' => '\\x22', - '&' => '\\x26', + '<' => '\\u003C', + '>' => '\\u003E', + '\'' => '\\u0027', + '"' => '\\u0022', + '&' => '\\u0026', + '/' => '\\/', /* Characters beyond ASCII value 255 to unicode escape */ 'Ä€' => '\\u0100', + '😀' => '\\uD83D\\uDE00', /* Immune chars excluded */ ',' => ',', '.' => '.', @@ -70,15 +75,17 @@ class Twig_Test_EscapingTest extends \PHPUnit\Framework\TestCase '0' => '0', '9' => '9', /* Basic control characters and null */ - "\r" => '\\x0D', - "\n" => '\\x0A', - "\t" => '\\x09', - "\0" => '\\x00', + "\r" => '\r', + "\n" => '\n', + "\x08" => '\b', + "\t" => '\t', + "\x0C" => '\f', + "\0" => '\\u0000', /* Encode spaces for quoteless attribute protection */ - ' ' => '\\x20', - ); + ' ' => '\\u0020', + ]; - protected $urlSpecialChars = array( + protected $urlSpecialChars = [ /* HTML special chars - escape without exception to percent encoding */ '<' => '%3C', '>' => '%3E', @@ -111,9 +118,9 @@ class Twig_Test_EscapingTest extends \PHPUnit\Framework\TestCase ' ' => '%20', '~' => '~', '+' => '%2B', - ); + ]; - protected $cssSpecialChars = array( + protected $cssSpecialChars = [ /* HTML special chars - escape without exception to hex */ '<' => '\\3C ', '>' => '\\3E ', @@ -140,13 +147,13 @@ class Twig_Test_EscapingTest extends \PHPUnit\Framework\TestCase "\0" => '\\0 ', /* Encode spaces for quoteless attribute protection */ ' ' => '\\20 ', - ); + ]; protected $env; protected function setUp() { - $this->env = new Twig_Environment($this->getMockBuilder('Twig_LoaderInterface')->getMock()); + $this->env = new \Twig\Environment($this->createMock('\Twig\Loader\LoaderInterface')); } public function testHtmlEscapingConvertsSpecialChars() @@ -215,7 +222,7 @@ class Twig_Test_EscapingTest extends \PHPUnit\Framework\TestCase public function testUnicodeCodepointConversionToUtf8() { $expected = ' ~Þ™'; - $codepoints = array(0x20, 0x7e, 0x799); + $codepoints = [0x20, 0x7e, 0x799]; $result = ''; foreach ($codepoints as $value) { $result .= $this->codepointToUtf8($value); @@ -233,29 +240,29 @@ class Twig_Test_EscapingTest extends \PHPUnit\Framework\TestCase protected function codepointToUtf8($codepoint) { if ($codepoint < 0x80) { - return chr($codepoint); + return \chr($codepoint); } if ($codepoint < 0x800) { - return chr($codepoint >> 6 & 0x3f | 0xc0) - .chr($codepoint & 0x3f | 0x80); + return \chr($codepoint >> 6 & 0x3f | 0xc0) + .\chr($codepoint & 0x3f | 0x80); } if ($codepoint < 0x10000) { - return chr($codepoint >> 12 & 0x0f | 0xe0) - .chr($codepoint >> 6 & 0x3f | 0x80) - .chr($codepoint & 0x3f | 0x80); + return \chr($codepoint >> 12 & 0x0f | 0xe0) + .\chr($codepoint >> 6 & 0x3f | 0x80) + .\chr($codepoint & 0x3f | 0x80); } if ($codepoint < 0x110000) { - return chr($codepoint >> 18 & 0x07 | 0xf0) - .chr($codepoint >> 12 & 0x3f | 0x80) - .chr($codepoint >> 6 & 0x3f | 0x80) - .chr($codepoint & 0x3f | 0x80); + return \chr($codepoint >> 18 & 0x07 | 0xf0) + .\chr($codepoint >> 12 & 0x3f | 0x80) + .\chr($codepoint >> 6 & 0x3f | 0x80) + .\chr($codepoint & 0x3f | 0x80); } - throw new Exception('Codepoint requested outside of Unicode range.'); + throw new \Exception('Codepoint requested outside of Unicode range.'); } public function testJavascriptEscapingEscapesOwaspRecommendedRanges() { - $immune = array(',', '.', '_'); // Exceptions to escaping ranges + $immune = [',', '.', '_']; // Exceptions to escaping ranges for ($chr = 0; $chr < 0xFF; ++$chr) { if ($chr >= 0x30 && $chr <= 0x39 || $chr >= 0x41 && $chr <= 0x5A @@ -264,7 +271,7 @@ class Twig_Test_EscapingTest extends \PHPUnit\Framework\TestCase $this->assertEquals($literal, twig_escape_filter($this->env, $literal, 'js')); } else { $literal = $this->codepointToUtf8($chr); - if (in_array($literal, $immune)) { + if (\in_array($literal, $immune)) { $this->assertEquals($literal, twig_escape_filter($this->env, $literal, 'js')); } else { $this->assertNotEquals( @@ -278,7 +285,7 @@ class Twig_Test_EscapingTest extends \PHPUnit\Framework\TestCase public function testHtmlAttributeEscapingEscapesOwaspRecommendedRanges() { - $immune = array(',', '.', '-', '_'); // Exceptions to escaping ranges + $immune = [',', '.', '-', '_']; // Exceptions to escaping ranges for ($chr = 0; $chr < 0xFF; ++$chr) { if ($chr >= 0x30 && $chr <= 0x39 || $chr >= 0x41 && $chr <= 0x5A @@ -287,7 +294,7 @@ class Twig_Test_EscapingTest extends \PHPUnit\Framework\TestCase $this->assertEquals($literal, twig_escape_filter($this->env, $literal, 'html_attr')); } else { $literal = $this->codepointToUtf8($chr); - if (in_array($literal, $immune)) { + if (\in_array($literal, $immune)) { $this->assertEquals($literal, twig_escape_filter($this->env, $literal, 'html_attr')); } else { $this->assertNotEquals(