summaryrefslogtreecommitdiff
path: root/vendor/symfony/http-kernel
diff options
context:
space:
mode:
authorGreg Roach <fisharebest@gmail.com>2018-01-19 15:40:08 +0000
committerGreg Roach <fisharebest@gmail.com>2018-01-19 22:39:48 +0000
commit9499ed38534b88c310649782326f430b724fbe3a (patch)
tree3b10195a8e8e56024f75403869d5a56074314181 /vendor/symfony/http-kernel
parentc9b4efa1714b4374cc3446e0d3a1935da0cb3a59 (diff)
downloadwebtrees-9499ed38534b88c310649782326f430b724fbe3a.tar.gz
webtrees-9499ed38534b88c310649782326f430b724fbe3a.tar.bz2
webtrees-9499ed38534b88c310649782326f430b724fbe3a.zip
Add symfony/http-kernel
Diffstat (limited to 'vendor/symfony/http-kernel')
-rw-r--r--vendor/symfony/http-kernel/.gitignore5
-rw-r--r--vendor/symfony/http-kernel/Bundle/Bundle.php231
-rw-r--r--vendor/symfony/http-kernel/Bundle/BundleInterface.php84
-rw-r--r--vendor/symfony/http-kernel/CHANGELOG.md134
-rw-r--r--vendor/symfony/http-kernel/CacheClearer/CacheClearerInterface.php27
-rw-r--r--vendor/symfony/http-kernel/CacheClearer/ChainCacheClearer.php55
-rw-r--r--vendor/symfony/http-kernel/CacheClearer/Psr6CacheClearer.php58
-rw-r--r--vendor/symfony/http-kernel/CacheWarmer/CacheWarmer.php32
-rw-r--r--vendor/symfony/http-kernel/CacheWarmer/CacheWarmerAggregate.php74
-rw-r--r--vendor/symfony/http-kernel/CacheWarmer/CacheWarmerInterface.php32
-rw-r--r--vendor/symfony/http-kernel/CacheWarmer/WarmableInterface.php27
-rw-r--r--vendor/symfony/http-kernel/Client.php206
-rw-r--r--vendor/symfony/http-kernel/Config/EnvParametersResource.php99
-rw-r--r--vendor/symfony/http-kernel/Config/FileLocator.php56
-rw-r--r--vendor/symfony/http-kernel/Controller/ArgumentResolver.php94
-rw-r--r--vendor/symfony/http-kernel/Controller/ArgumentResolver/DefaultValueResolver.php40
-rw-r--r--vendor/symfony/http-kernel/Controller/ArgumentResolver/RequestAttributeValueResolver.php40
-rw-r--r--vendor/symfony/http-kernel/Controller/ArgumentResolver/RequestValueResolver.php40
-rw-r--r--vendor/symfony/http-kernel/Controller/ArgumentResolver/ServiceValueResolver.php48
-rw-r--r--vendor/symfony/http-kernel/Controller/ArgumentResolver/SessionValueResolver.php46
-rw-r--r--vendor/symfony/http-kernel/Controller/ArgumentResolver/VariadicValueResolver.php48
-rw-r--r--vendor/symfony/http-kernel/Controller/ArgumentResolverInterface.php35
-rw-r--r--vendor/symfony/http-kernel/Controller/ArgumentValueResolverInterface.php43
-rw-r--r--vendor/symfony/http-kernel/Controller/ContainerControllerResolver.php76
-rw-r--r--vendor/symfony/http-kernel/Controller/ControllerReference.php46
-rw-r--r--vendor/symfony/http-kernel/Controller/ControllerResolver.php265
-rw-r--r--vendor/symfony/http-kernel/Controller/ControllerResolverInterface.php59
-rw-r--r--vendor/symfony/http-kernel/Controller/TraceableArgumentResolver.php44
-rw-r--r--vendor/symfony/http-kernel/Controller/TraceableControllerResolver.php78
-rw-r--r--vendor/symfony/http-kernel/ControllerMetadata/ArgumentMetadata.php115
-rw-r--r--vendor/symfony/http-kernel/ControllerMetadata/ArgumentMetadataFactory.php129
-rw-r--r--vendor/symfony/http-kernel/ControllerMetadata/ArgumentMetadataFactoryInterface.php27
-rw-r--r--vendor/symfony/http-kernel/DataCollector/AjaxDataCollector.php33
-rw-r--r--vendor/symfony/http-kernel/DataCollector/ConfigDataCollector.php330
-rw-r--r--vendor/symfony/http-kernel/DataCollector/DataCollector.php128
-rw-r--r--vendor/symfony/http-kernel/DataCollector/DataCollectorInterface.php39
-rw-r--r--vendor/symfony/http-kernel/DataCollector/DumpDataCollector.php303
-rw-r--r--vendor/symfony/http-kernel/DataCollector/EventDataCollector.php108
-rw-r--r--vendor/symfony/http-kernel/DataCollector/ExceptionDataCollector.php104
-rw-r--r--vendor/symfony/http-kernel/DataCollector/LateDataCollectorInterface.php25
-rw-r--r--vendor/symfony/http-kernel/DataCollector/LoggerDataCollector.php262
-rw-r--r--vendor/symfony/http-kernel/DataCollector/MemoryDataCollector.php109
-rw-r--r--vendor/symfony/http-kernel/DataCollector/RequestDataCollector.php397
-rw-r--r--vendor/symfony/http-kernel/DataCollector/RouterDataCollector.php102
-rw-r--r--vendor/symfony/http-kernel/DataCollector/TimeDataCollector.php136
-rw-r--r--vendor/symfony/http-kernel/DataCollector/Util/ValueExporter.php99
-rw-r--r--vendor/symfony/http-kernel/Debug/FileLinkFormatter.php88
-rw-r--r--vendor/symfony/http-kernel/Debug/TraceableEventDispatcher.php82
-rw-r--r--vendor/symfony/http-kernel/DependencyInjection/AddAnnotatedClassesToCachePass.php153
-rw-r--r--vendor/symfony/http-kernel/DependencyInjection/AddClassesToCachePass.php25
-rw-r--r--vendor/symfony/http-kernel/DependencyInjection/ConfigurableExtension.php45
-rw-r--r--vendor/symfony/http-kernel/DependencyInjection/ControllerArgumentValueResolverPass.php48
-rw-r--r--vendor/symfony/http-kernel/DependencyInjection/Extension.php77
-rw-r--r--vendor/symfony/http-kernel/DependencyInjection/FragmentRendererPass.php67
-rw-r--r--vendor/symfony/http-kernel/DependencyInjection/LazyLoadingFragmentHandler.php81
-rw-r--r--vendor/symfony/http-kernel/DependencyInjection/MergeExtensionConfigurationPass.php41
-rw-r--r--vendor/symfony/http-kernel/DependencyInjection/RegisterControllerArgumentLocatorsPass.php158
-rw-r--r--vendor/symfony/http-kernel/DependencyInjection/RemoveEmptyControllerArgumentLocatorsPass.php76
-rw-r--r--vendor/symfony/http-kernel/Event/FilterControllerArgumentsEvent.php55
-rw-r--r--vendor/symfony/http-kernel/Event/FilterControllerEvent.php61
-rw-r--r--vendor/symfony/http-kernel/Event/FilterResponseEvent.php62
-rw-r--r--vendor/symfony/http-kernel/Event/FinishRequestEvent.php21
-rw-r--r--vendor/symfony/http-kernel/Event/GetResponseEvent.php65
-rw-r--r--vendor/symfony/http-kernel/Event/GetResponseForControllerResultEvent.php61
-rw-r--r--vendor/symfony/http-kernel/Event/GetResponseForExceptionEvent.php90
-rw-r--r--vendor/symfony/http-kernel/Event/KernelEvent.php94
-rw-r--r--vendor/symfony/http-kernel/Event/PostResponseEvent.php46
-rw-r--r--vendor/symfony/http-kernel/EventListener/AbstractSessionListener.php54
-rw-r--r--vendor/symfony/http-kernel/EventListener/AbstractTestSessionListener.php84
-rw-r--r--vendor/symfony/http-kernel/EventListener/AddRequestFormatsListener.php57
-rw-r--r--vendor/symfony/http-kernel/EventListener/DebugHandlersListener.php146
-rw-r--r--vendor/symfony/http-kernel/EventListener/DumpListener.php59
-rw-r--r--vendor/symfony/http-kernel/EventListener/ExceptionListener.php116
-rw-r--r--vendor/symfony/http-kernel/EventListener/FragmentListener.php103
-rw-r--r--vendor/symfony/http-kernel/EventListener/LocaleListener.php85
-rw-r--r--vendor/symfony/http-kernel/EventListener/ProfilerListener.php135
-rw-r--r--vendor/symfony/http-kernel/EventListener/ResponseListener.php58
-rw-r--r--vendor/symfony/http-kernel/EventListener/RouterListener.php140
-rw-r--r--vendor/symfony/http-kernel/EventListener/SaveSessionListener.php66
-rw-r--r--vendor/symfony/http-kernel/EventListener/SessionListener.php40
-rw-r--r--vendor/symfony/http-kernel/EventListener/StreamedResponseListener.php51
-rw-r--r--vendor/symfony/http-kernel/EventListener/SurrogateListener.php72
-rw-r--r--vendor/symfony/http-kernel/EventListener/TestSessionListener.php40
-rw-r--r--vendor/symfony/http-kernel/EventListener/TranslatorListener.php69
-rw-r--r--vendor/symfony/http-kernel/EventListener/ValidateRequestListener.php55
-rw-r--r--vendor/symfony/http-kernel/Exception/AccessDeniedHttpException.php33
-rw-r--r--vendor/symfony/http-kernel/Exception/BadRequestHttpException.php32
-rw-r--r--vendor/symfony/http-kernel/Exception/ConflictHttpException.php32
-rw-r--r--vendor/symfony/http-kernel/Exception/GoneHttpException.php32
-rw-r--r--vendor/symfony/http-kernel/Exception/HttpException.php51
-rw-r--r--vendor/symfony/http-kernel/Exception/HttpExceptionInterface.php34
-rw-r--r--vendor/symfony/http-kernel/Exception/LengthRequiredHttpException.php32
-rw-r--r--vendor/symfony/http-kernel/Exception/MethodNotAllowedHttpException.php35
-rw-r--r--vendor/symfony/http-kernel/Exception/NotAcceptableHttpException.php32
-rw-r--r--vendor/symfony/http-kernel/Exception/NotFoundHttpException.php32
-rw-r--r--vendor/symfony/http-kernel/Exception/PreconditionFailedHttpException.php32
-rw-r--r--vendor/symfony/http-kernel/Exception/PreconditionRequiredHttpException.php34
-rw-r--r--vendor/symfony/http-kernel/Exception/ServiceUnavailableHttpException.php38
-rw-r--r--vendor/symfony/http-kernel/Exception/TooManyRequestsHttpException.php40
-rw-r--r--vendor/symfony/http-kernel/Exception/UnauthorizedHttpException.php35
-rw-r--r--vendor/symfony/http-kernel/Exception/UnprocessableEntityHttpException.php32
-rw-r--r--vendor/symfony/http-kernel/Exception/UnsupportedMediaTypeHttpException.php32
-rw-r--r--vendor/symfony/http-kernel/Fragment/AbstractSurrogateFragmentRenderer.php112
-rw-r--r--vendor/symfony/http-kernel/Fragment/EsiFragmentRenderer.php28
-rw-r--r--vendor/symfony/http-kernel/Fragment/FragmentHandler.php118
-rw-r--r--vendor/symfony/http-kernel/Fragment/FragmentRendererInterface.php42
-rw-r--r--vendor/symfony/http-kernel/Fragment/HIncludeFragmentRenderer.php167
-rw-r--r--vendor/symfony/http-kernel/Fragment/InlineFragmentRenderer.php158
-rw-r--r--vendor/symfony/http-kernel/Fragment/RoutableFragmentRenderer.php90
-rw-r--r--vendor/symfony/http-kernel/Fragment/SsiFragmentRenderer.php28
-rw-r--r--vendor/symfony/http-kernel/HttpCache/AbstractSurrogate.php138
-rw-r--r--vendor/symfony/http-kernel/HttpCache/Esi.php115
-rw-r--r--vendor/symfony/http-kernel/HttpCache/HttpCache.php737
-rw-r--r--vendor/symfony/http-kernel/HttpCache/ResponseCacheStrategy.php96
-rw-r--r--vendor/symfony/http-kernel/HttpCache/ResponseCacheStrategyInterface.php41
-rw-r--r--vendor/symfony/http-kernel/HttpCache/Ssi.php98
-rw-r--r--vendor/symfony/http-kernel/HttpCache/Store.php508
-rw-r--r--vendor/symfony/http-kernel/HttpCache/StoreInterface.php96
-rw-r--r--vendor/symfony/http-kernel/HttpCache/SurrogateInterface.php103
-rw-r--r--vendor/symfony/http-kernel/HttpKernel.php301
-rw-r--r--vendor/symfony/http-kernel/HttpKernelInterface.php43
-rw-r--r--vendor/symfony/http-kernel/Kernel.php866
-rw-r--r--vendor/symfony/http-kernel/KernelEvents.php119
-rw-r--r--vendor/symfony/http-kernel/KernelInterface.php164
-rw-r--r--vendor/symfony/http-kernel/LICENSE19
-rw-r--r--vendor/symfony/http-kernel/Log/DebugLoggerInterface.php38
-rw-r--r--vendor/symfony/http-kernel/Profiler/FileProfilerStorage.php284
-rw-r--r--vendor/symfony/http-kernel/Profiler/Profile.php295
-rw-r--r--vendor/symfony/http-kernel/Profiler/Profiler.php270
-rw-r--r--vendor/symfony/http-kernel/Profiler/ProfilerStorageInterface.php59
-rw-r--r--vendor/symfony/http-kernel/README.md16
-rw-r--r--vendor/symfony/http-kernel/TerminableInterface.php35
-rw-r--r--vendor/symfony/http-kernel/Tests/Bundle/BundleTest.php100
-rw-r--r--vendor/symfony/http-kernel/Tests/CacheClearer/ChainCacheClearerTest.php58
-rw-r--r--vendor/symfony/http-kernel/Tests/CacheClearer/Psr6CacheClearerTest.php69
-rw-r--r--vendor/symfony/http-kernel/Tests/CacheWarmer/CacheWarmerAggregateTest.php101
-rw-r--r--vendor/symfony/http-kernel/Tests/CacheWarmer/CacheWarmerTest.php68
-rw-r--r--vendor/symfony/http-kernel/Tests/ClientTest.php183
-rw-r--r--vendor/symfony/http-kernel/Tests/Config/EnvParametersResourceTest.php107
-rw-r--r--vendor/symfony/http-kernel/Tests/Config/FileLocatorTest.php48
-rw-r--r--vendor/symfony/http-kernel/Tests/Controller/ArgumentResolverTest.php349
-rw-r--r--vendor/symfony/http-kernel/Tests/Controller/ContainerControllerResolverTest.php148
-rw-r--r--vendor/symfony/http-kernel/Tests/Controller/ControllerResolverTest.php331
-rw-r--r--vendor/symfony/http-kernel/Tests/ControllerMetadata/ArgumentMetadataFactoryTest.php148
-rw-r--r--vendor/symfony/http-kernel/Tests/ControllerMetadata/ArgumentMetadataTest.php46
-rw-r--r--vendor/symfony/http-kernel/Tests/DataCollector/Compiler.log4
-rw-r--r--vendor/symfony/http-kernel/Tests/DataCollector/ConfigDataCollectorTest.php66
-rw-r--r--vendor/symfony/http-kernel/Tests/DataCollector/DataCollectorTest.php38
-rw-r--r--vendor/symfony/http-kernel/Tests/DataCollector/DumpDataCollectorTest.php115
-rw-r--r--vendor/symfony/http-kernel/Tests/DataCollector/ExceptionDataCollectorTest.php40
-rw-r--r--vendor/symfony/http-kernel/Tests/DataCollector/LoggerDataCollectorTest.php126
-rw-r--r--vendor/symfony/http-kernel/Tests/DataCollector/MemoryDataCollectorTest.php59
-rw-r--r--vendor/symfony/http-kernel/Tests/DataCollector/RequestDataCollectorTest.php287
-rw-r--r--vendor/symfony/http-kernel/Tests/DataCollector/TimeDataCollectorTest.php55
-rw-r--r--vendor/symfony/http-kernel/Tests/DataCollector/Util/ValueExporterTest.php51
-rw-r--r--vendor/symfony/http-kernel/Tests/Debug/FileLinkFormatterTest.php67
-rw-r--r--vendor/symfony/http-kernel/Tests/Debug/TraceableEventDispatcherTest.php121
-rw-r--r--vendor/symfony/http-kernel/Tests/DependencyInjection/AddAnnotatedClassesToCachePassTest.php99
-rw-r--r--vendor/symfony/http-kernel/Tests/DependencyInjection/ControllerArgumentValueResolverPassTest.php67
-rw-r--r--vendor/symfony/http-kernel/Tests/DependencyInjection/FragmentRendererPassTest.php105
-rw-r--r--vendor/symfony/http-kernel/Tests/DependencyInjection/LazyLoadingFragmentHandlerTest.php66
-rw-r--r--vendor/symfony/http-kernel/Tests/DependencyInjection/MergeExtensionConfigurationPassTest.php55
-rw-r--r--vendor/symfony/http-kernel/Tests/DependencyInjection/RegisterControllerArgumentLocatorsPassTest.php329
-rw-r--r--vendor/symfony/http-kernel/Tests/DependencyInjection/RemoveEmptyControllerArgumentLocatorsPassTest.php148
-rw-r--r--vendor/symfony/http-kernel/Tests/Event/GetResponseForExceptionEventTest.php27
-rw-r--r--vendor/symfony/http-kernel/Tests/EventListener/AddRequestFormatsListenerTest.php84
-rw-r--r--vendor/symfony/http-kernel/Tests/EventListener/DebugHandlersListenerTest.php135
-rw-r--r--vendor/symfony/http-kernel/Tests/EventListener/DumpListenerTest.php81
-rw-r--r--vendor/symfony/http-kernel/Tests/EventListener/ExceptionListenerTest.php149
-rw-r--r--vendor/symfony/http-kernel/Tests/EventListener/FragmentListenerTest.php122
-rw-r--r--vendor/symfony/http-kernel/Tests/EventListener/LocaleListenerTest.php103
-rw-r--r--vendor/symfony/http-kernel/Tests/EventListener/ProfilerListenerTest.php71
-rw-r--r--vendor/symfony/http-kernel/Tests/EventListener/ResponseListenerTest.php95
-rw-r--r--vendor/symfony/http-kernel/Tests/EventListener/RouterListenerTest.php188
-rw-r--r--vendor/symfony/http-kernel/Tests/EventListener/SurrogateListenerTest.php67
-rw-r--r--vendor/symfony/http-kernel/Tests/EventListener/TestSessionListenerTest.php145
-rw-r--r--vendor/symfony/http-kernel/Tests/EventListener/TranslatorListenerTest.php118
-rw-r--r--vendor/symfony/http-kernel/Tests/EventListener/ValidateRequestListenerTest.php43
-rw-r--r--vendor/symfony/http-kernel/Tests/Exception/AccessDeniedHttpExceptionTest.php13
-rw-r--r--vendor/symfony/http-kernel/Tests/Exception/BadRequestHttpExceptionTest.php13
-rw-r--r--vendor/symfony/http-kernel/Tests/Exception/ConflictHttpExceptionTest.php13
-rw-r--r--vendor/symfony/http-kernel/Tests/Exception/GoneHttpExceptionTest.php13
-rw-r--r--vendor/symfony/http-kernel/Tests/Exception/HttpExceptionTest.php53
-rw-r--r--vendor/symfony/http-kernel/Tests/Exception/LengthRequiredHttpExceptionTest.php13
-rw-r--r--vendor/symfony/http-kernel/Tests/Exception/MethodNotAllowedHttpExceptionTest.php24
-rw-r--r--vendor/symfony/http-kernel/Tests/Exception/NotAcceptableHttpExceptionTest.php13
-rw-r--r--vendor/symfony/http-kernel/Tests/Exception/NotFoundHttpExceptionTest.php13
-rw-r--r--vendor/symfony/http-kernel/Tests/Exception/PreconditionFailedHttpExceptionTest.php13
-rw-r--r--vendor/symfony/http-kernel/Tests/Exception/PreconditionRequiredHttpExceptionTest.php13
-rw-r--r--vendor/symfony/http-kernel/Tests/Exception/ServiceUnavailableHttpExceptionTest.php29
-rw-r--r--vendor/symfony/http-kernel/Tests/Exception/TooManyRequestsHttpExceptionTest.php29
-rw-r--r--vendor/symfony/http-kernel/Tests/Exception/UnauthorizedHttpExceptionTest.php24
-rw-r--r--vendor/symfony/http-kernel/Tests/Exception/UnprocessableEntityHttpExceptionTest.php28
-rw-r--r--vendor/symfony/http-kernel/Tests/Exception/UnsupportedMediaTypeHttpExceptionTest.php23
-rw-r--r--vendor/symfony/http-kernel/Tests/Fixtures/123/Kernel123.php37
-rw-r--r--vendor/symfony/http-kernel/Tests/Fixtures/BaseBundle/Resources/foo.txt0
-rw-r--r--vendor/symfony/http-kernel/Tests/Fixtures/BaseBundle/Resources/hide.txt0
-rw-r--r--vendor/symfony/http-kernel/Tests/Fixtures/Bundle1Bundle/Resources/foo.txt0
-rw-r--r--vendor/symfony/http-kernel/Tests/Fixtures/Bundle1Bundle/bar.txt0
-rw-r--r--vendor/symfony/http-kernel/Tests/Fixtures/Bundle1Bundle/foo.txt0
-rw-r--r--vendor/symfony/http-kernel/Tests/Fixtures/Bundle2Bundle/foo.txt0
-rw-r--r--vendor/symfony/http-kernel/Tests/Fixtures/ChildBundle/Resources/foo.txt0
-rw-r--r--vendor/symfony/http-kernel/Tests/Fixtures/ChildBundle/Resources/hide.txt0
-rw-r--r--vendor/symfony/http-kernel/Tests/Fixtures/Controller/BasicTypesController.php19
-rw-r--r--vendor/symfony/http-kernel/Tests/Fixtures/Controller/ExtendingRequest.php18
-rw-r--r--vendor/symfony/http-kernel/Tests/Fixtures/Controller/ExtendingSession.php18
-rw-r--r--vendor/symfony/http-kernel/Tests/Fixtures/Controller/NullableController.php19
-rw-r--r--vendor/symfony/http-kernel/Tests/Fixtures/Controller/VariadicController.php19
-rw-r--r--vendor/symfony/http-kernel/Tests/Fixtures/DataCollector/CloneVarDataCollector.php41
-rw-r--r--vendor/symfony/http-kernel/Tests/Fixtures/ExtensionAbsentBundle/ExtensionAbsentBundle.php18
-rw-r--r--vendor/symfony/http-kernel/Tests/Fixtures/ExtensionLoadedBundle/DependencyInjection/ExtensionLoadedExtension.php22
-rw-r--r--vendor/symfony/http-kernel/Tests/Fixtures/ExtensionLoadedBundle/ExtensionLoadedBundle.php18
-rw-r--r--vendor/symfony/http-kernel/Tests/Fixtures/ExtensionNotValidBundle/DependencyInjection/ExtensionNotValidExtension.php20
-rw-r--r--vendor/symfony/http-kernel/Tests/Fixtures/ExtensionNotValidBundle/ExtensionNotValidBundle.php18
-rw-r--r--vendor/symfony/http-kernel/Tests/Fixtures/ExtensionPresentBundle/Command/BarCommand.php17
-rw-r--r--vendor/symfony/http-kernel/Tests/Fixtures/ExtensionPresentBundle/Command/FooCommand.php22
-rw-r--r--vendor/symfony/http-kernel/Tests/Fixtures/ExtensionPresentBundle/DependencyInjection/ExtensionPresentExtension.php22
-rw-r--r--vendor/symfony/http-kernel/Tests/Fixtures/ExtensionPresentBundle/ExtensionPresentBundle.php18
-rw-r--r--vendor/symfony/http-kernel/Tests/Fixtures/KernelForOverrideName.php28
-rw-r--r--vendor/symfony/http-kernel/Tests/Fixtures/KernelForTest.php37
-rw-r--r--vendor/symfony/http-kernel/Tests/Fixtures/KernelWithoutBundles.php33
-rw-r--r--vendor/symfony/http-kernel/Tests/Fixtures/Resources/BaseBundle/hide.txt0
-rw-r--r--vendor/symfony/http-kernel/Tests/Fixtures/Resources/Bundle1Bundle/foo.txt0
-rw-r--r--vendor/symfony/http-kernel/Tests/Fixtures/Resources/ChildBundle/foo.txt0
-rw-r--r--vendor/symfony/http-kernel/Tests/Fixtures/Resources/FooBundle/foo.txt0
-rw-r--r--vendor/symfony/http-kernel/Tests/Fixtures/TestClient.php31
-rw-r--r--vendor/symfony/http-kernel/Tests/Fixtures/TestEventDispatcher.php28
-rw-r--r--vendor/symfony/http-kernel/Tests/Fragment/EsiFragmentRendererTest.php110
-rw-r--r--vendor/symfony/http-kernel/Tests/Fragment/FragmentHandlerTest.php99
-rw-r--r--vendor/symfony/http-kernel/Tests/Fragment/HIncludeFragmentRendererTest.php89
-rw-r--r--vendor/symfony/http-kernel/Tests/Fragment/InlineFragmentRendererTest.php250
-rw-r--r--vendor/symfony/http-kernel/Tests/Fragment/RoutableFragmentRendererTest.php94
-rw-r--r--vendor/symfony/http-kernel/Tests/Fragment/SsiFragmentRendererTest.php97
-rw-r--r--vendor/symfony/http-kernel/Tests/HttpCache/EsiTest.php248
-rw-r--r--vendor/symfony/http-kernel/Tests/HttpCache/HttpCacheTest.php1367
-rw-r--r--vendor/symfony/http-kernel/Tests/HttpCache/HttpCacheTestCase.php185
-rw-r--r--vendor/symfony/http-kernel/Tests/HttpCache/ResponseCacheStrategyTest.php222
-rw-r--r--vendor/symfony/http-kernel/Tests/HttpCache/SsiTest.php215
-rw-r--r--vendor/symfony/http-kernel/Tests/HttpCache/StoreTest.php301
-rw-r--r--vendor/symfony/http-kernel/Tests/HttpCache/TestHttpKernel.php92
-rw-r--r--vendor/symfony/http-kernel/Tests/HttpCache/TestMultipleHttpKernel.php81
-rw-r--r--vendor/symfony/http-kernel/Tests/HttpKernelTest.php403
-rw-r--r--vendor/symfony/http-kernel/Tests/KernelTest.php900
-rw-r--r--vendor/symfony/http-kernel/Tests/Logger.php88
-rw-r--r--vendor/symfony/http-kernel/Tests/Profiler/FileProfilerStorageTest.php350
-rw-r--r--vendor/symfony/http-kernel/Tests/Profiler/ProfilerTest.php91
-rw-r--r--vendor/symfony/http-kernel/Tests/TestHttpKernel.php42
-rw-r--r--vendor/symfony/http-kernel/Tests/UriSignerTest.php64
-rw-r--r--vendor/symfony/http-kernel/UriSigner.php112
-rw-r--r--vendor/symfony/http-kernel/composer.json70
-rw-r--r--vendor/symfony/http-kernel/phpunit.xml.dist40
251 files changed, 24788 insertions, 0 deletions
diff --git a/vendor/symfony/http-kernel/.gitignore b/vendor/symfony/http-kernel/.gitignore
new file mode 100644
index 0000000000..94a6a25288
--- /dev/null
+++ b/vendor/symfony/http-kernel/.gitignore
@@ -0,0 +1,5 @@
+vendor/
+composer.lock
+phpunit.xml
+Tests/Fixtures/cache/
+Tests/Fixtures/logs/
diff --git a/vendor/symfony/http-kernel/Bundle/Bundle.php b/vendor/symfony/http-kernel/Bundle/Bundle.php
new file mode 100644
index 0000000000..0b0ea088dc
--- /dev/null
+++ b/vendor/symfony/http-kernel/Bundle/Bundle.php
@@ -0,0 +1,231 @@
+<?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\Bundle;
+
+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.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+abstract class Bundle implements BundleInterface
+{
+ use ContainerAwareTrait;
+
+ protected $name;
+ protected $extension;
+ protected $path;
+ private $namespace;
+
+ /**
+ * Boots the Bundle.
+ */
+ public function boot()
+ {
+ }
+
+ /**
+ * Shutdowns the Bundle.
+ */
+ public function shutdown()
+ {
+ }
+
+ /**
+ * Builds the bundle.
+ *
+ * It is only ever called once when the cache is empty.
+ *
+ * This method can be overridden to register compilation passes,
+ * other extensions, ...
+ *
+ * @param ContainerBuilder $container A ContainerBuilder instance
+ */
+ public function build(ContainerBuilder $container)
+ {
+ }
+
+ /**
+ * Returns the bundle's container extension.
+ *
+ * @return ExtensionInterface|null The container extension
+ *
+ * @throws \LogicException
+ */
+ public function getContainerExtension()
+ {
+ if (null === $this->extension) {
+ $extension = $this->createContainerExtension();
+
+ if (null !== $extension) {
+ if (!$extension instanceof ExtensionInterface) {
+ throw new \LogicException(sprintf('Extension %s must implement Symfony\Component\DependencyInjection\Extension\ExtensionInterface.', get_class($extension)));
+ }
+
+ // check naming convention
+ $basename = preg_replace('/Bundle$/', '', $this->getName());
+ $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()
+ ));
+ }
+
+ $this->extension = $extension;
+ } else {
+ $this->extension = false;
+ }
+ }
+
+ if ($this->extension) {
+ return $this->extension;
+ }
+ }
+
+ /**
+ * Gets the Bundle namespace.
+ *
+ * @return string The Bundle namespace
+ */
+ public function getNamespace()
+ {
+ if (null === $this->namespace) {
+ $this->parseClassName();
+ }
+
+ return $this->namespace;
+ }
+
+ /**
+ * Gets the Bundle directory path.
+ *
+ * @return string The Bundle absolute path
+ */
+ public function getPath()
+ {
+ if (null === $this->path) {
+ $reflected = new \ReflectionObject($this);
+ $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).
+ *
+ * @return string The Bundle name
+ */
+ final public function getName()
+ {
+ if (null === $this->name) {
+ $this->parseClassName();
+ }
+
+ 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
+ *
+ * @param Application $application An Application instance
+ */
+ 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()) {
+ $application->add($r->newInstance());
+ }
+ }
+ }
+
+ /**
+ * Returns the bundle's container extension class.
+ *
+ * @return string
+ */
+ protected function getContainerExtensionClass()
+ {
+ $basename = preg_replace('/Bundle$/', '', $this->getName());
+
+ return $this->getNamespace().'\\DependencyInjection\\'.$basename.'Extension';
+ }
+
+ /**
+ * Creates the bundle's container extension.
+ *
+ * @return ExtensionInterface|null
+ */
+ protected function createContainerExtension()
+ {
+ if (class_exists($class = $this->getContainerExtensionClass())) {
+ return new $class();
+ }
+ }
+
+ private function parseClassName()
+ {
+ $pos = strrpos(static::class, '\\');
+ $this->namespace = false === $pos ? '' : substr(static::class, 0, $pos);
+ if (null === $this->name) {
+ $this->name = false === $pos ? static::class : substr(static::class, $pos + 1);
+ }
+ }
+}
diff --git a/vendor/symfony/http-kernel/Bundle/BundleInterface.php b/vendor/symfony/http-kernel/Bundle/BundleInterface.php
new file mode 100644
index 0000000000..25eea1d76d
--- /dev/null
+++ b/vendor/symfony/http-kernel/Bundle/BundleInterface.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\Bundle;
+
+use Symfony\Component\DependencyInjection\ContainerAwareInterface;
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\DependencyInjection\Extension\ExtensionInterface;
+
+/**
+ * BundleInterface.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+interface BundleInterface extends ContainerAwareInterface
+{
+ /**
+ * Boots the Bundle.
+ */
+ public function boot();
+
+ /**
+ * Shutdowns the Bundle.
+ */
+ public function shutdown();
+
+ /**
+ * Builds the bundle.
+ *
+ * It is only ever called once when the cache is empty.
+ *
+ * @param ContainerBuilder $container A ContainerBuilder instance
+ */
+ public function build(ContainerBuilder $container);
+
+ /**
+ * Returns the container extension that should be implicitly loaded.
+ *
+ * @return ExtensionInterface|null The default extension or null if there is none
+ */
+ 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
+ */
+ public function getParent();
+
+ /**
+ * Returns the bundle name (the class short name).
+ *
+ * @return string The Bundle name
+ */
+ public function getName();
+
+ /**
+ * Gets the Bundle namespace.
+ *
+ * @return string The Bundle namespace
+ */
+ public function getNamespace();
+
+ /**
+ * Gets the Bundle directory path.
+ *
+ * The path should always be returned as a Unix path (with /).
+ *
+ * @return string The Bundle absolute path
+ */
+ public function getPath();
+}
diff --git a/vendor/symfony/http-kernel/CHANGELOG.md b/vendor/symfony/http-kernel/CHANGELOG.md
new file mode 100644
index 0000000000..061f61d172
--- /dev/null
+++ b/vendor/symfony/http-kernel/CHANGELOG.md
@@ -0,0 +1,134 @@
+CHANGELOG
+=========
+
+3.3.0
+-----
+
+ * added `kernel.project_dir` and `Kernel::getProjectDir()`
+ * deprecated `kernel.root_dir` and `Kernel::getRootDir()`
+ * deprecated `Kernel::getEnvParameters()`
+ * deprecated the special `SYMFONY__` environment variables
+ * added the possibility to change the query string parameter used by `UriSigner`
+ * deprecated `LazyLoadingFragmentHandler::addRendererService()`
+ * deprecated `Extension::addClassesToCompile()` and `Extension::getClassesToCompile()`
+ * deprecated `Psr6CacheClearer::addPool()`
+
+3.2.0
+-----
+
+ * deprecated `DataCollector::varToString()`, use `cloneVar()` instead
+ * changed surrogate capability name in `AbstractSurrogate::addSurrogateCapability` to 'symfony'
+ * Added `ControllerArgumentValueResolverPass`
+
+3.1.0
+-----
+ * deprecated passing objects as URI attributes to the ESI and SSI renderers
+ * deprecated `ControllerResolver::getArguments()`
+ * added `Symfony\Component\HttpKernel\Controller\ArgumentResolverInterface`
+ * added `Symfony\Component\HttpKernel\Controller\ArgumentResolverInterface` as argument to `HttpKernel`
+ * added `Symfony\Component\HttpKernel\Controller\ArgumentResolver`
+ * added `Symfony\Component\HttpKernel\DataCollector\RequestDataCollector::getMethod()`
+ * added `Symfony\Component\HttpKernel\DataCollector\RequestDataCollector::getRedirect()`
+ * added the `kernel.controller_arguments` event, triggered after controller arguments have been resolved
+
+3.0.0
+-----
+
+ * removed `Symfony\Component\HttpKernel\Kernel::init()`
+ * removed `Symfony\Component\HttpKernel\Kernel::isClassInActiveBundle()` and `Symfony\Component\HttpKernel\KernelInterface::isClassInActiveBundle()`
+ * removed `Symfony\Component\HttpKernel\Debug\TraceableEventDispatcher::setProfiler()`
+ * removed `Symfony\Component\HttpKernel\EventListener\FragmentListener::getLocalIpAddresses()`
+ * removed `Symfony\Component\HttpKernel\EventListener\LocaleListener::setRequest()`
+ * removed `Symfony\Component\HttpKernel\EventListener\RouterListener::setRequest()`
+ * removed `Symfony\Component\HttpKernel\EventListener\ProfilerListener::onKernelRequest()`
+ * removed `Symfony\Component\HttpKernel\Fragment\FragmentHandler::setRequest()`
+ * removed `Symfony\Component\HttpKernel\HttpCache\Esi::hasSurrogateEsiCapability()`
+ * removed `Symfony\Component\HttpKernel\HttpCache\Esi::addSurrogateEsiCapability()`
+ * removed `Symfony\Component\HttpKernel\HttpCache\Esi::needsEsiParsing()`
+ * removed `Symfony\Component\HttpKernel\HttpCache\HttpCache::getEsi()`
+ * removed `Symfony\Component\HttpKernel\DependencyInjection\ContainerAwareHttpKernel`
+ * removed `Symfony\Component\HttpKernel\DependencyInjection\RegisterListenersPass`
+ * removed `Symfony\Component\HttpKernel\EventListener\ErrorsLoggerListener`
+ * removed `Symfony\Component\HttpKernel\EventListener\EsiListener`
+ * removed `Symfony\Component\HttpKernel\HttpCache\EsiResponseCacheStrategy`
+ * removed `Symfony\Component\HttpKernel\HttpCache\EsiResponseCacheStrategyInterface`
+ * removed `Symfony\Component\HttpKernel\Log\LoggerInterface`
+ * removed `Symfony\Component\HttpKernel\Log\NullLogger`
+ * removed `Symfony\Component\HttpKernel\Profiler::import()`
+ * removed `Symfony\Component\HttpKernel\Profiler::export()`
+
+2.8.0
+-----
+
+ * deprecated `Profiler::import` and `Profiler::export`
+
+2.7.0
+-----
+
+ * added the HTTP status code to profiles
+
+2.6.0
+-----
+
+ * deprecated `Symfony\Component\HttpKernel\EventListener\ErrorsLoggerListener`, use `Symfony\Component\HttpKernel\EventListener\DebugHandlersListener` instead
+ * deprecated unused method `Symfony\Component\HttpKernel\Kernel::isClassInActiveBundle` and `Symfony\Component\HttpKernel\KernelInterface::isClassInActiveBundle`
+
+2.5.0
+-----
+
+ * deprecated `Symfony\Component\HttpKernel\DependencyInjection\RegisterListenersPass`, use `Symfony\Component\EventDispatcher\DependencyInjection\RegisterListenersPass` instead
+
+2.4.0
+-----
+
+ * added event listeners for the session
+ * added the KernelEvents::FINISH_REQUEST event
+
+2.3.0
+-----
+
+ * [BC BREAK] renamed `Symfony\Component\HttpKernel\EventListener\DeprecationLoggerListener` to `Symfony\Component\HttpKernel\EventListener\ErrorsLoggerListener` and changed its constructor
+ * deprecated `Symfony\Component\HttpKernel\Debug\ErrorHandler`, `Symfony\Component\HttpKernel\Debug\ExceptionHandler`,
+ `Symfony\Component\HttpKernel\Exception\FatalErrorException` and `Symfony\Component\HttpKernel\Exception\FlattenException`
+ * deprecated `Symfony\Component\HttpKernel\Kernel::init()`
+ * added the possibility to specify an id an extra attributes to hinclude tags
+ * added the collect of data if a controller is a Closure in the Request collector
+ * pass exceptions from the ExceptionListener to the logger using the logging context to allow for more
+ detailed messages
+
+2.2.0
+-----
+
+ * [BC BREAK] the path info for sub-request is now always _fragment (or whatever you configured instead of the default)
+ * added Symfony\Component\HttpKernel\EventListener\FragmentListener
+ * added Symfony\Component\HttpKernel\UriSigner
+ * added Symfony\Component\HttpKernel\FragmentRenderer and rendering strategies (in Symfony\Component\HttpKernel\Fragment\FragmentRendererInterface)
+ * added Symfony\Component\HttpKernel\DependencyInjection\ContainerAwareHttpKernel
+ * added ControllerReference to create reference of Controllers (used in the FragmentRenderer class)
+ * [BC BREAK] renamed TimeDataCollector::getTotalTime() to
+ TimeDataCollector::getDuration()
+ * updated the MemoryDataCollector to include the memory used in the
+ kernel.terminate event listeners
+ * moved the Stopwatch classes to a new component
+ * added TraceableControllerResolver
+ * added TraceableEventDispatcher (removed ContainerAwareTraceableEventDispatcher)
+ * added support for WinCache opcode cache in ConfigDataCollector
+
+2.1.0
+-----
+
+ * [BC BREAK] the charset is now configured via the Kernel::getCharset() method
+ * [BC BREAK] the current locale for the user is not stored anymore in the session
+ * added the HTTP method to the profiler storage
+ * updated all listeners to implement EventSubscriberInterface
+ * added TimeDataCollector
+ * added ContainerAwareTraceableEventDispatcher
+ * moved TraceableEventDispatcherInterface to the EventDispatcher component
+ * added RouterListener, LocaleListener, and StreamedResponseListener
+ * added CacheClearerInterface (and ChainCacheClearer)
+ * added a kernel.terminate event (via TerminableInterface and PostResponseEvent)
+ * added a Stopwatch class
+ * added WarmableInterface
+ * improved extensibility between bundles
+ * added profiler storages for Memcache(d), File-based, MongoDB, Redis
+ * moved Filesystem class to its own component
diff --git a/vendor/symfony/http-kernel/CacheClearer/CacheClearerInterface.php b/vendor/symfony/http-kernel/CacheClearer/CacheClearerInterface.php
new file mode 100644
index 0000000000..675c584234
--- /dev/null
+++ b/vendor/symfony/http-kernel/CacheClearer/CacheClearerInterface.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\CacheClearer;
+
+/**
+ * CacheClearerInterface.
+ *
+ * @author Dustin Dobervich <ddobervich@gmail.com>
+ */
+interface CacheClearerInterface
+{
+ /**
+ * Clears any caches necessary.
+ *
+ * @param string $cacheDir The cache directory
+ */
+ public function clear($cacheDir);
+}
diff --git a/vendor/symfony/http-kernel/CacheClearer/ChainCacheClearer.php b/vendor/symfony/http-kernel/CacheClearer/ChainCacheClearer.php
new file mode 100644
index 0000000000..c749c7c0a4
--- /dev/null
+++ b/vendor/symfony/http-kernel/CacheClearer/ChainCacheClearer.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\HttpKernel\CacheClearer;
+
+/**
+ * ChainCacheClearer.
+ *
+ * @author Dustin Dobervich <ddobervich@gmail.com>
+ */
+class ChainCacheClearer implements CacheClearerInterface
+{
+ /**
+ * @var array
+ */
+ protected $clearers;
+
+ /**
+ * Constructs a new instance of ChainCacheClearer.
+ *
+ * @param array $clearers The initial clearers
+ */
+ public function __construct(array $clearers = array())
+ {
+ $this->clearers = $clearers;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function clear($cacheDir)
+ {
+ foreach ($this->clearers as $clearer) {
+ $clearer->clear($cacheDir);
+ }
+ }
+
+ /**
+ * Adds a cache clearer to the aggregate.
+ *
+ * @param CacheClearerInterface $clearer
+ */
+ public function add(CacheClearerInterface $clearer)
+ {
+ $this->clearers[] = $clearer;
+ }
+}
diff --git a/vendor/symfony/http-kernel/CacheClearer/Psr6CacheClearer.php b/vendor/symfony/http-kernel/CacheClearer/Psr6CacheClearer.php
new file mode 100644
index 0000000000..2336b18a29
--- /dev/null
+++ b/vendor/symfony/http-kernel/CacheClearer/Psr6CacheClearer.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\CacheClearer;
+
+use Psr\Cache\CacheItemPoolInterface;
+
+/**
+ * @author Nicolas Grekas <p@tchwork.com>
+ */
+class Psr6CacheClearer implements CacheClearerInterface
+{
+ private $pools = array();
+
+ public function __construct(array $pools = array())
+ {
+ $this->pools = $pools;
+ }
+
+ public function addPool(CacheItemPoolInterface $pool)
+ {
+ @trigger_error(sprintf('The %s() method is deprecated since version 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;
+ }
+
+ public function hasPool($name)
+ {
+ return isset($this->pools[$name]);
+ }
+
+ public function clearPool($name)
+ {
+ if (!isset($this->pools[$name])) {
+ throw new \InvalidArgumentException(sprintf('Cache pool not found: %s.', $name));
+ }
+
+ return $this->pools[$name]->clear();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function clear($cacheDir)
+ {
+ foreach ($this->pools as $pool) {
+ $pool->clear();
+ }
+ }
+}
diff --git a/vendor/symfony/http-kernel/CacheWarmer/CacheWarmer.php b/vendor/symfony/http-kernel/CacheWarmer/CacheWarmer.php
new file mode 100644
index 0000000000..dba35a639a
--- /dev/null
+++ b/vendor/symfony/http-kernel/CacheWarmer/CacheWarmer.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\HttpKernel\CacheWarmer;
+
+/**
+ * Abstract cache warmer that knows how to write a file to the cache.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+abstract class CacheWarmer implements CacheWarmerInterface
+{
+ protected function writeCacheFile($file, $content)
+ {
+ $tmpFile = @tempnam(dirname($file), basename($file));
+ if (false !== @file_put_contents($tmpFile, $content) && @rename($tmpFile, $file)) {
+ @chmod($file, 0666 & ~umask());
+
+ return;
+ }
+
+ throw new \RuntimeException(sprintf('Failed to write cache file "%s".', $file));
+ }
+}
diff --git a/vendor/symfony/http-kernel/CacheWarmer/CacheWarmerAggregate.php b/vendor/symfony/http-kernel/CacheWarmer/CacheWarmerAggregate.php
new file mode 100644
index 0000000000..e5f4e4fa4a
--- /dev/null
+++ b/vendor/symfony/http-kernel/CacheWarmer/CacheWarmerAggregate.php
@@ -0,0 +1,74 @@
+<?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\CacheWarmer;
+
+/**
+ * Aggregates several cache warmers into a single one.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+class CacheWarmerAggregate implements CacheWarmerInterface
+{
+ protected $warmers = array();
+ protected $optionalsEnabled = false;
+
+ public function __construct(array $warmers = array())
+ {
+ foreach ($warmers as $warmer) {
+ $this->add($warmer);
+ }
+ }
+
+ public function enableOptionalWarmers()
+ {
+ $this->optionalsEnabled = true;
+ }
+
+ /**
+ * Warms up the cache.
+ *
+ * @param string $cacheDir The cache directory
+ */
+ public function warmUp($cacheDir)
+ {
+ foreach ($this->warmers as $warmer) {
+ if (!$this->optionalsEnabled && $warmer->isOptional()) {
+ continue;
+ }
+
+ $warmer->warmUp($cacheDir);
+ }
+ }
+
+ /**
+ * Checks whether this warmer is optional or not.
+ *
+ * @return bool always false
+ */
+ public function isOptional()
+ {
+ return false;
+ }
+
+ public function setWarmers(array $warmers)
+ {
+ $this->warmers = array();
+ foreach ($warmers as $warmer) {
+ $this->add($warmer);
+ }
+ }
+
+ public function add(CacheWarmerInterface $warmer)
+ {
+ $this->warmers[] = $warmer;
+ }
+}
diff --git a/vendor/symfony/http-kernel/CacheWarmer/CacheWarmerInterface.php b/vendor/symfony/http-kernel/CacheWarmer/CacheWarmerInterface.php
new file mode 100644
index 0000000000..8fece5e954
--- /dev/null
+++ b/vendor/symfony/http-kernel/CacheWarmer/CacheWarmerInterface.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\HttpKernel\CacheWarmer;
+
+/**
+ * Interface for classes able to warm up the cache.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+interface CacheWarmerInterface extends WarmableInterface
+{
+ /**
+ * Checks whether this warmer is optional or not.
+ *
+ * Optional warmers can be ignored on certain conditions.
+ *
+ * A warmer should return true if the cache can be
+ * generated incrementally and on-demand.
+ *
+ * @return bool true if the warmer is optional, false otherwise
+ */
+ public function isOptional();
+}
diff --git a/vendor/symfony/http-kernel/CacheWarmer/WarmableInterface.php b/vendor/symfony/http-kernel/CacheWarmer/WarmableInterface.php
new file mode 100644
index 0000000000..25d8ee8f61
--- /dev/null
+++ b/vendor/symfony/http-kernel/CacheWarmer/WarmableInterface.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\CacheWarmer;
+
+/**
+ * Interface for classes that support warming their cache.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+interface WarmableInterface
+{
+ /**
+ * Warms up the cache.
+ *
+ * @param string $cacheDir The cache directory
+ */
+ public function warmUp($cacheDir);
+}
diff --git a/vendor/symfony/http-kernel/Client.php b/vendor/symfony/http-kernel/Client.php
new file mode 100644
index 0000000000..94f70cd6f7
--- /dev/null
+++ b/vendor/symfony/http-kernel/Client.php
@@ -0,0 +1,206 @@
+<?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\BrowserKit\Client as BaseClient;
+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.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ *
+ * @method Request|null getRequest() A Request instance
+ * @method Response|null getResponse() A Response instance
+ */
+class Client extends BaseClient
+{
+ protected $kernel;
+
+ /**
+ * Constructor.
+ *
+ * @param HttpKernelInterface $kernel An HttpKernel instance
+ * @param array $server The server parameters (equivalent of $_SERVER)
+ * @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)
+ {
+ // These class properties must be set before calling the parent constructor, as it may depend on it.
+ $this->kernel = $kernel;
+ $this->followRedirects = false;
+
+ parent::__construct($server, $history, $cookieJar);
+ }
+
+ /**
+ * Makes a request.
+ *
+ * @param Request $request A Request instance
+ *
+ * @return Response A Response instance
+ */
+ protected function doRequest($request)
+ {
+ $response = $this->kernel->handle($request);
+
+ if ($this->kernel instanceof TerminableInterface) {
+ $this->kernel->terminate($request, $response);
+ }
+
+ return $response;
+ }
+
+ /**
+ * Returns the script to execute when the request must be insulated.
+ *
+ * @param Request $request A Request instance
+ *
+ * @return string
+ */
+ protected function getScript($request)
+ {
+ $kernel = str_replace("'", "\\'", serialize($this->kernel));
+ $request = str_replace("'", "\\'", serialize($request));
+ $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';
+ if (file_exists($file)) {
+ $requires .= "require_once '".str_replace("'", "\\'", $file)."';\n";
+ }
+ }
+ }
+
+ if (!$requires) {
+ throw new \RuntimeException('Composer autoloader not found.');
+ }
+
+ $code = <<<EOF
+<?php
+
+error_reporting($errorReporting);
+
+$requires
+
+\$kernel = unserialize('$kernel');
+\$request = unserialize('$request');
+EOF;
+
+ return $code.$this->getHandleScript();
+ }
+
+ protected function getHandleScript()
+ {
+ return <<<'EOF'
+$response = $kernel->handle($request);
+
+if ($kernel instanceof Symfony\Component\HttpKernel\TerminableInterface) {
+ $kernel->terminate($request, $response);
+}
+
+echo serialize($response);
+EOF;
+ }
+
+ /**
+ * Converts the BrowserKit request to a HttpKernel request.
+ *
+ * @param DomRequest $request A DomRequest instance
+ *
+ * @return Request A Request instance
+ */
+ protected function filterRequest(DomRequest $request)
+ {
+ $httpRequest = Request::create($request->getUri(), $request->getMethod(), $request->getParameters(), $request->getCookies(), $request->getFiles(), $request->getServer(), $request->getContent());
+
+ foreach ($this->filterFiles($httpRequest->files->all()) as $key => $value) {
+ $httpRequest->files->set($key, $value);
+ }
+
+ return $httpRequest;
+ }
+
+ /**
+ * Filters an array of files.
+ *
+ * This method created test instances of UploadedFile so that the move()
+ * method can be called on those instances.
+ *
+ * If the size of a file is greater than the allowed size (from php.ini) then
+ * an invalid UploadedFile is returned with an error set to UPLOAD_ERR_INI_SIZE.
+ *
+ * @see UploadedFile
+ *
+ * @param array $files An array of files
+ *
+ * @return array An array with all uploaded files marked as already moved
+ */
+ protected function filterFiles(array $files)
+ {
+ $filtered = array();
+ foreach ($files as $key => $value) {
+ if (is_array($value)) {
+ $filtered[$key] = $this->filterFiles($value);
+ } elseif ($value instanceof UploadedFile) {
+ if ($value->isValid() && $value->getSize() > UploadedFile::getMaxFilesize()) {
+ $filtered[$key] = new UploadedFile(
+ '',
+ $value->getClientOriginalName(),
+ $value->getClientMimeType(),
+ 0,
+ UPLOAD_ERR_INI_SIZE,
+ true
+ );
+ } else {
+ $filtered[$key] = new UploadedFile(
+ $value->getPathname(),
+ $value->getClientOriginalName(),
+ $value->getClientMimeType(),
+ $value->getClientSize(),
+ $value->getError(),
+ true
+ );
+ }
+ }
+ }
+
+ return $filtered;
+ }
+
+ /**
+ * Converts the HttpKernel response to a BrowserKit response.
+ *
+ * @param Response $response A Response instance
+ *
+ * @return DomResponse A DomResponse instance
+ */
+ protected function filterResponse($response)
+ {
+ // this is needed to support StreamedResponse
+ ob_start();
+ $response->sendContent();
+ $content = ob_get_clean();
+
+ return new DomResponse($content, $response->getStatusCode(), $response->headers->all());
+ }
+}
diff --git a/vendor/symfony/http-kernel/Config/EnvParametersResource.php b/vendor/symfony/http-kernel/Config/EnvParametersResource.php
new file mode 100644
index 0000000000..0fe6aca8c1
--- /dev/null
+++ b/vendor/symfony/http-kernel/Config/EnvParametersResource.php
@@ -0,0 +1,99 @@
+<?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>
+ */
+class EnvParametersResource implements SelfCheckingResourceInterface, \Serializable
+{
+ /**
+ * @var string
+ */
+ private $prefix;
+
+ /**
+ * @var string
+ */
+ private $variables;
+
+ /**
+ * Constructor.
+ *
+ * @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
new file mode 100644
index 0000000000..169c9ad6e5
--- /dev/null
+++ b/vendor/symfony/http-kernel/Config/FileLocator.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\HttpKernel\Config;
+
+use Symfony\Component\Config\FileLocator as BaseFileLocator;
+use Symfony\Component\HttpKernel\KernelInterface;
+
+/**
+ * FileLocator uses the KernelInterface to locate resources in bundles.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+class FileLocator extends BaseFileLocator
+{
+ private $kernel;
+ private $path;
+
+ /**
+ * Constructor.
+ *
+ * @param KernelInterface $kernel A KernelInterface instance
+ * @param null|string $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())
+ {
+ $this->kernel = $kernel;
+ if (null !== $path) {
+ $this->path = $path;
+ $paths[] = $path;
+ }
+
+ parent::__construct($paths);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function locate($file, $currentPath = null, $first = true)
+ {
+ if (isset($file[0]) && '@' === $file[0]) {
+ return $this->kernel->locateResource($file, $this->path, $first);
+ }
+
+ return parent::locate($file, $currentPath, $first);
+ }
+}
diff --git a/vendor/symfony/http-kernel/Controller/ArgumentResolver.php b/vendor/symfony/http-kernel/Controller/ArgumentResolver.php
new file mode 100644
index 0000000000..2c17125c5a
--- /dev/null
+++ b/vendor/symfony/http-kernel/Controller/ArgumentResolver.php
@@ -0,0 +1,94 @@
+<?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;
+
+use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\HttpKernel\Controller\ArgumentResolver\DefaultValueResolver;
+use Symfony\Component\HttpKernel\Controller\ArgumentResolver\RequestAttributeValueResolver;
+use Symfony\Component\HttpKernel\Controller\ArgumentResolver\RequestValueResolver;
+use Symfony\Component\HttpKernel\Controller\ArgumentResolver\SessionValueResolver;
+use Symfony\Component\HttpKernel\Controller\ArgumentResolver\VariadicValueResolver;
+use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadataFactory;
+use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadataFactoryInterface;
+
+/**
+ * Responsible for resolving the arguments passed to an action.
+ *
+ * @author Iltar van der Berg <kjarli@gmail.com>
+ */
+final class ArgumentResolver implements ArgumentResolverInterface
+{
+ private $argumentMetadataFactory;
+
+ /**
+ * @var iterable|ArgumentValueResolverInterface[]
+ */
+ private $argumentValueResolvers;
+
+ public function __construct(ArgumentMetadataFactoryInterface $argumentMetadataFactory = null, $argumentValueResolvers = array())
+ {
+ $this->argumentMetadataFactory = $argumentMetadataFactory ?: new ArgumentMetadataFactory();
+ $this->argumentValueResolvers = $argumentValueResolvers ?: self::getDefaultArgumentValueResolvers();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getArguments(Request $request, $controller)
+ {
+ $arguments = array();
+
+ foreach ($this->argumentMetadataFactory->createArgumentMetadata($controller) as $metadata) {
+ foreach ($this->argumentValueResolvers as $resolver) {
+ if (!$resolver->supports($request, $metadata)) {
+ continue;
+ }
+
+ $resolved = $resolver->resolve($request, $metadata);
+
+ if (!$resolved instanceof \Generator) {
+ throw new \InvalidArgumentException(sprintf('%s::resolve() must yield at least one value.', get_class($resolver)));
+ }
+
+ foreach ($resolved as $append) {
+ $arguments[] = $append;
+ }
+
+ // continue to the next controller argument
+ continue 2;
+ }
+
+ $representative = $controller;
+
+ 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()));
+ }
+
+ return $arguments;
+ }
+
+ public static function getDefaultArgumentValueResolvers()
+ {
+ return array(
+ new RequestAttributeValueResolver(),
+ new RequestValueResolver(),
+ new SessionValueResolver(),
+ new DefaultValueResolver(),
+ new VariadicValueResolver(),
+ );
+ }
+}
diff --git a/vendor/symfony/http-kernel/Controller/ArgumentResolver/DefaultValueResolver.php b/vendor/symfony/http-kernel/Controller/ArgumentResolver/DefaultValueResolver.php
new file mode 100644
index 0000000000..e58fd3ab2b
--- /dev/null
+++ b/vendor/symfony/http-kernel/Controller/ArgumentResolver/DefaultValueResolver.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\HttpKernel\Controller\ArgumentResolver;
+
+use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface;
+use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata;
+
+/**
+ * Yields the default value defined in the action signature when no value has been given.
+ *
+ * @author Iltar van der Berg <kjarli@gmail.com>
+ */
+final class DefaultValueResolver implements ArgumentValueResolverInterface
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function supports(Request $request, ArgumentMetadata $argument)
+ {
+ return $argument->hasDefaultValue() || (null !== $argument->getType() && $argument->isNullable() && !$argument->isVariadic());
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function resolve(Request $request, ArgumentMetadata $argument)
+ {
+ yield $argument->hasDefaultValue() ? $argument->getDefaultValue() : null;
+ }
+}
diff --git a/vendor/symfony/http-kernel/Controller/ArgumentResolver/RequestAttributeValueResolver.php b/vendor/symfony/http-kernel/Controller/ArgumentResolver/RequestAttributeValueResolver.php
new file mode 100644
index 0000000000..05be372d84
--- /dev/null
+++ b/vendor/symfony/http-kernel/Controller/ArgumentResolver/RequestAttributeValueResolver.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\HttpKernel\Controller\ArgumentResolver;
+
+use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface;
+use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata;
+
+/**
+ * Yields a non-variadic argument's value from the request attributes.
+ *
+ * @author Iltar van der Berg <kjarli@gmail.com>
+ */
+final class RequestAttributeValueResolver implements ArgumentValueResolverInterface
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function supports(Request $request, ArgumentMetadata $argument)
+ {
+ return !$argument->isVariadic() && $request->attributes->has($argument->getName());
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function resolve(Request $request, ArgumentMetadata $argument)
+ {
+ yield $request->attributes->get($argument->getName());
+ }
+}
diff --git a/vendor/symfony/http-kernel/Controller/ArgumentResolver/RequestValueResolver.php b/vendor/symfony/http-kernel/Controller/ArgumentResolver/RequestValueResolver.php
new file mode 100644
index 0000000000..2a5060a612
--- /dev/null
+++ b/vendor/symfony/http-kernel/Controller/ArgumentResolver/RequestValueResolver.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\HttpKernel\Controller\ArgumentResolver;
+
+use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface;
+use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata;
+
+/**
+ * Yields the same instance as the request object passed along.
+ *
+ * @author Iltar van der Berg <kjarli@gmail.com>
+ */
+final class RequestValueResolver implements ArgumentValueResolverInterface
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function supports(Request $request, ArgumentMetadata $argument)
+ {
+ return Request::class === $argument->getType() || is_subclass_of($argument->getType(), Request::class);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function resolve(Request $request, ArgumentMetadata $argument)
+ {
+ yield $request;
+ }
+}
diff --git a/vendor/symfony/http-kernel/Controller/ArgumentResolver/ServiceValueResolver.php b/vendor/symfony/http-kernel/Controller/ArgumentResolver/ServiceValueResolver.php
new file mode 100644
index 0000000000..b1da6a9a75
--- /dev/null
+++ b/vendor/symfony/http-kernel/Controller/ArgumentResolver/ServiceValueResolver.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\HttpKernel\Controller\ArgumentResolver;
+
+use Psr\Container\ContainerInterface;
+use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface;
+use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata;
+
+/**
+ * Yields a service keyed by _controller and argument name.
+ *
+ * @author Nicolas Grekas <p@tchwork.com>
+ */
+final class ServiceValueResolver implements ArgumentValueResolverInterface
+{
+ private $container;
+
+ public function __construct(ContainerInterface $container)
+ {
+ $this->container = $container;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function supports(Request $request, ArgumentMetadata $argument)
+ {
+ return is_string($controller = $request->attributes->get('_controller')) && $this->container->has($controller) && $this->container->get($controller)->has($argument->getName());
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function resolve(Request $request, ArgumentMetadata $argument)
+ {
+ yield $this->container->get($request->attributes->get('_controller'))->get($argument->getName());
+ }
+}
diff --git a/vendor/symfony/http-kernel/Controller/ArgumentResolver/SessionValueResolver.php b/vendor/symfony/http-kernel/Controller/ArgumentResolver/SessionValueResolver.php
new file mode 100644
index 0000000000..9e656d281b
--- /dev/null
+++ b/vendor/symfony/http-kernel/Controller/ArgumentResolver/SessionValueResolver.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\HttpKernel\Controller\ArgumentResolver;
+
+use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\HttpFoundation\Session\SessionInterface;
+use Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface;
+use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata;
+
+/**
+ * Yields the Session.
+ *
+ * @author Iltar van der Berg <kjarli@gmail.com>
+ */
+final class SessionValueResolver implements ArgumentValueResolverInterface
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function supports(Request $request, ArgumentMetadata $argument)
+ {
+ $type = $argument->getType();
+ if (SessionInterface::class !== $type && !is_subclass_of($type, SessionInterface::class)) {
+ return false;
+ }
+
+ return $request->getSession() instanceof $type;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function resolve(Request $request, ArgumentMetadata $argument)
+ {
+ yield $request->getSession();
+ }
+}
diff --git a/vendor/symfony/http-kernel/Controller/ArgumentResolver/VariadicValueResolver.php b/vendor/symfony/http-kernel/Controller/ArgumentResolver/VariadicValueResolver.php
new file mode 100644
index 0000000000..56ae5f191c
--- /dev/null
+++ b/vendor/symfony/http-kernel/Controller/ArgumentResolver/VariadicValueResolver.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\HttpKernel\Controller\ArgumentResolver;
+
+use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface;
+use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata;
+
+/**
+ * Yields a variadic argument's values from the request attributes.
+ *
+ * @author Iltar van der Berg <kjarli@gmail.com>
+ */
+final class VariadicValueResolver implements ArgumentValueResolverInterface
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function supports(Request $request, ArgumentMetadata $argument)
+ {
+ return $argument->isVariadic() && $request->attributes->has($argument->getName());
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function resolve(Request $request, ArgumentMetadata $argument)
+ {
+ $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)));
+ }
+
+ foreach ($values as $value) {
+ yield $value;
+ }
+ }
+}
diff --git a/vendor/symfony/http-kernel/Controller/ArgumentResolverInterface.php b/vendor/symfony/http-kernel/Controller/ArgumentResolverInterface.php
new file mode 100644
index 0000000000..5c51230966
--- /dev/null
+++ b/vendor/symfony/http-kernel/Controller/ArgumentResolverInterface.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\HttpKernel\Controller;
+
+use Symfony\Component\HttpFoundation\Request;
+
+/**
+ * An ArgumentResolverInterface instance knows how to determine the
+ * arguments for a specific action.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+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
+ *
+ * @throws \RuntimeException When no value could be provided for a required argument
+ */
+ public function getArguments(Request $request, $controller);
+}
diff --git a/vendor/symfony/http-kernel/Controller/ArgumentValueResolverInterface.php b/vendor/symfony/http-kernel/Controller/ArgumentValueResolverInterface.php
new file mode 100644
index 0000000000..fd7b09ecf2
--- /dev/null
+++ b/vendor/symfony/http-kernel/Controller/ArgumentValueResolverInterface.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\Controller;
+
+use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata;
+
+/**
+ * Responsible for resolving the value of an argument based on its metadata.
+ *
+ * @author Iltar van der Berg <kjarli@gmail.com>
+ */
+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);
+
+ /**
+ * 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
new file mode 100644
index 0000000000..1a107c62f6
--- /dev/null
+++ b/vendor/symfony/http-kernel/Controller/ContainerControllerResolver.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\Controller;
+
+use Psr\Container\ContainerInterface;
+use Psr\Log\LoggerInterface;
+
+/**
+ * A controller resolver searching for a controller in a psr-11 container when using the "service:method" notation.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ * @author Maxime Steinhausser <maxime.steinhausser@gmail.com>
+ */
+class ContainerControllerResolver extends ControllerResolver
+{
+ protected $container;
+
+ public function __construct(ContainerInterface $container, LoggerInterface $logger = null)
+ {
+ $this->container = $container;
+
+ parent::__construct($logger);
+ }
+
+ /**
+ * 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);
+ }
+
+ if (1 == substr_count($controller, ':')) {
+ // controller in the "service:method" notation
+ list($service, $method) = explode(':', $controller, 2);
+
+ return array($this->container->get($service), $method);
+ }
+
+ if ($this->container->has($controller) && method_exists($service = $this->container->get($controller), '__invoke')) {
+ // invokable controller in the "service" notation
+ return $service;
+ }
+
+ throw new \LogicException(sprintf('Unable to parse the controller name "%s".', $controller));
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function instantiateController($class)
+ {
+ if ($this->container->has($class)) {
+ return $this->container->get($class);
+ }
+
+ return parent::instantiateController($class);
+ }
+}
diff --git a/vendor/symfony/http-kernel/Controller/ControllerReference.php b/vendor/symfony/http-kernel/Controller/ControllerReference.php
new file mode 100644
index 0000000000..3d1592e83a
--- /dev/null
+++ b/vendor/symfony/http-kernel/Controller/ControllerReference.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\HttpKernel\Controller;
+
+use Symfony\Component\HttpKernel\Fragment\FragmentRendererInterface;
+
+/**
+ * Acts as a marker and a data holder for a Controller.
+ *
+ * Some methods in Symfony accept both a URI (as a string) or a controller as
+ * an argument. In the latter case, instead of passing an array representing
+ * the controller, you can use an instance of this class.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ *
+ * @see FragmentRendererInterface
+ */
+class ControllerReference
+{
+ public $controller;
+ public $attributes = array();
+ public $query = array();
+
+ /**
+ * Constructor.
+ *
+ * @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())
+ {
+ $this->controller = $controller;
+ $this->attributes = $attributes;
+ $this->query = $query;
+ }
+}
diff --git a/vendor/symfony/http-kernel/Controller/ControllerResolver.php b/vendor/symfony/http-kernel/Controller/ControllerResolver.php
new file mode 100644
index 0000000000..f51a5a8efb
--- /dev/null
+++ b/vendor/symfony/http-kernel/Controller/ControllerResolver.php
@@ -0,0 +1,265 @@
+<?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;
+
+use Psr\Log\LoggerInterface;
+use Symfony\Component\HttpFoundation\Request;
+
+/**
+ * ControllerResolver.
+ *
+ * This implementation uses the '_controller' request attribute to determine
+ * the controller to execute and uses the request attributes to determine
+ * the controller method arguments.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+class ControllerResolver implements ArgumentResolverInterface, 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;
+
+ /**
+ * Constructor.
+ *
+ * @param LoggerInterface $logger A LoggerInterface instance
+ */
+ 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)
+ {
+ if (!$controller = $request->attributes->get('_controller')) {
+ if (null !== $this->logger) {
+ $this->logger->warning('Unable to look for the controller as the "_controller" parameter is missing.');
+ }
+
+ return false;
+ }
+
+ if (is_array($controller)) {
+ return $controller;
+ }
+
+ if (is_object($controller)) {
+ if (method_exists($controller, '__invoke')) {
+ return $controller;
+ }
+
+ throw new \InvalidArgumentException(sprintf('Controller "%s" for URI "%s" is not callable.', get_class($controller), $request->getPathInfo()));
+ }
+
+ if (false === strpos($controller, ':')) {
+ if (method_exists($controller, '__invoke')) {
+ return $this->instantiateController($controller);
+ } elseif (function_exists($controller)) {
+ return $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 $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);
+ }
+
+ 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;
+ }
+
+ 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));
+ }
+ }
+
+ return $arguments;
+ }
+
+ /**
+ * Returns a callable for the given controller.
+ *
+ * @param string $controller A Controller string
+ *
+ * @return callable A PHP callable
+ *
+ * @throws \InvalidArgumentException
+ */
+ protected function createController($controller)
+ {
+ if (false === strpos($controller, '::')) {
+ throw new \InvalidArgumentException(sprintf('Unable to find controller "%s".', $controller));
+ }
+
+ list($class, $method) = explode('::', $controller, 2);
+
+ if (!class_exists($class)) {
+ throw new \InvalidArgumentException(sprintf('Class "%s" does not exist.', $class));
+ }
+
+ return array($this->instantiateController($class), $method);
+ }
+
+ /**
+ * Returns an instantiated controller.
+ *
+ * @param string $class A class name
+ *
+ * @return object
+ */
+ protected function instantiateController($class)
+ {
+ return new $class();
+ }
+
+ private function getControllerError($callable)
+ {
+ if (is_string($callable)) {
+ if (false !== strpos($callable, '::')) {
+ $callable = explode('::', $callable);
+ }
+
+ if (class_exists($callable) && !method_exists($callable, '__invoke')) {
+ return sprintf('Class "%s" does not have a method "__invoke".', $callable);
+ }
+
+ if (!function_exists($callable)) {
+ return sprintf('Function "%s" does not exist.', $callable);
+ }
+ }
+
+ if (!is_array($callable)) {
+ return sprintf('Invalid type for controller given, expected string or array, got "%s".', gettype($callable));
+ }
+
+ if (2 !== count($callable)) {
+ return sprintf('Invalid format for controller, expected array(controller, method) or controller::method.');
+ }
+
+ list($controller, $method) = $callable;
+
+ if (is_string($controller) && !class_exists($controller)) {
+ return sprintf('Class "%s" does not exist.', $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);
+
+ $alternatives = array();
+
+ foreach ($collection as $item) {
+ $lev = levenshtein($method, $item);
+
+ if ($lev <= strlen($method) / 3 || false !== strpos($item, $method)) {
+ $alternatives[] = $item;
+ }
+ }
+
+ asort($alternatives);
+
+ $message = sprintf('Expected method "%s" on class "%s"', $method, $className);
+
+ if (count($alternatives) > 0) {
+ $message .= sprintf(', did you mean "%s"?', implode('", "', $alternatives));
+ } else {
+ $message .= sprintf('. Available methods: "%s".', implode('", "', $collection));
+ }
+
+ return $message;
+ }
+}
diff --git a/vendor/symfony/http-kernel/Controller/ControllerResolverInterface.php b/vendor/symfony/http-kernel/Controller/ControllerResolverInterface.php
new file mode 100644
index 0000000000..0dd7cce96d
--- /dev/null
+++ b/vendor/symfony/http-kernel/Controller/ControllerResolverInterface.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\HttpKernel\Controller;
+
+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>
+ */
+interface ControllerResolverInterface
+{
+ /**
+ * Returns the Controller instance associated with a Request.
+ *
+ * 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
+ * controller but cannot because of some errors made by the developer.
+ *
+ * @param Request $request A Request instance
+ *
+ * @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
+ */
+ 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
new file mode 100644
index 0000000000..6fb0fa66ac
--- /dev/null
+++ b/vendor/symfony/http-kernel/Controller/TraceableArgumentResolver.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\HttpKernel\Controller;
+
+use Symfony\Component\Stopwatch\Stopwatch;
+use Symfony\Component\HttpFoundation\Request;
+
+/**
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+class TraceableArgumentResolver implements ArgumentResolverInterface
+{
+ private $resolver;
+ private $stopwatch;
+
+ public function __construct(ArgumentResolverInterface $resolver, Stopwatch $stopwatch)
+ {
+ $this->resolver = $resolver;
+ $this->stopwatch = $stopwatch;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getArguments(Request $request, $controller)
+ {
+ $e = $this->stopwatch->start('controller.get_arguments');
+
+ $ret = $this->resolver->getArguments($request, $controller);
+
+ $e->stop();
+
+ return $ret;
+ }
+}
diff --git a/vendor/symfony/http-kernel/Controller/TraceableControllerResolver.php b/vendor/symfony/http-kernel/Controller/TraceableControllerResolver.php
new file mode 100644
index 0000000000..ce291b1e3e
--- /dev/null
+++ b/vendor/symfony/http-kernel/Controller/TraceableControllerResolver.php
@@ -0,0 +1,78 @@
+<?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;
+
+use Symfony\Component\Stopwatch\Stopwatch;
+use Symfony\Component\HttpFoundation\Request;
+
+/**
+ * TraceableControllerResolver.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+class TraceableControllerResolver implements ControllerResolverInterface, ArgumentResolverInterface
+{
+ private $resolver;
+ private $stopwatch;
+ private $argumentResolver;
+
+ /**
+ * Constructor.
+ *
+ * @param ControllerResolverInterface $resolver A ControllerResolverInterface instance
+ * @param Stopwatch $stopwatch A Stopwatch instance
+ * @param ArgumentResolverInterface $argumentResolver Only required for BC
+ */
+ public function __construct(ControllerResolverInterface $resolver, Stopwatch $stopwatch, ArgumentResolverInterface $argumentResolver = null)
+ {
+ $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);
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getController(Request $request)
+ {
+ $e = $this->stopwatch->start('controller.get_callable');
+
+ $ret = $this->resolver->getController($request);
+
+ $e->stop();
+
+ 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
new file mode 100644
index 0000000000..32316a8d51
--- /dev/null
+++ b/vendor/symfony/http-kernel/ControllerMetadata/ArgumentMetadata.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\HttpKernel\ControllerMetadata;
+
+/**
+ * Responsible for storing metadata of an argument.
+ *
+ * @author Iltar van der Berg <kjarli@gmail.com>
+ */
+class ArgumentMetadata
+{
+ private $name;
+ private $type;
+ private $isVariadic;
+ private $hasDefaultValue;
+ 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)
+ {
+ $this->name = $name;
+ $this->type = $type;
+ $this->isVariadic = $isVariadic;
+ $this->hasDefaultValue = $hasDefaultValue;
+ $this->defaultValue = $defaultValue;
+ $this->isNullable = $isNullable || null === $type || ($hasDefaultValue && null === $defaultValue);
+ }
+
+ /**
+ * Returns the name as given in PHP, $foo would yield "foo".
+ *
+ * @return string
+ */
+ public function getName()
+ {
+ return $this->name;
+ }
+
+ /**
+ * Returns the type of the argument.
+ *
+ * The type is the PHP class in 5.5+ and additionally the basic type in PHP 7.0+.
+ *
+ * @return string
+ */
+ public function getType()
+ {
+ return $this->type;
+ }
+
+ /**
+ * Returns whether the argument is defined as "...$variadic".
+ *
+ * @return bool
+ */
+ public function isVariadic()
+ {
+ return $this->isVariadic;
+ }
+
+ /**
+ * Returns whether the argument has a default value.
+ *
+ * Implies whether an argument is optional.
+ *
+ * @return bool
+ */
+ public function hasDefaultValue()
+ {
+ return $this->hasDefaultValue;
+ }
+
+ /**
+ * Returns whether the argument accepts null values.
+ *
+ * @return bool
+ */
+ public function isNullable()
+ {
+ return $this->isNullable;
+ }
+
+ /**
+ * Returns the default value of the argument.
+ *
+ * @throws \LogicException if no default value is present; {@see self::hasDefaultValue()}
+ *
+ * @return mixed
+ */
+ public function getDefaultValue()
+ {
+ if (!$this->hasDefaultValue) {
+ throw new \LogicException(sprintf('Argument $%s does not have a default value. Use %s::hasDefaultValue() to avoid this exception.', $this->name, __CLASS__));
+ }
+
+ return $this->defaultValue;
+ }
+}
diff --git a/vendor/symfony/http-kernel/ControllerMetadata/ArgumentMetadataFactory.php b/vendor/symfony/http-kernel/ControllerMetadata/ArgumentMetadataFactory.php
new file mode 100644
index 0000000000..d1e7af2068
--- /dev/null
+++ b/vendor/symfony/http-kernel/ControllerMetadata/ArgumentMetadataFactory.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\HttpKernel\ControllerMetadata;
+
+/**
+ * Builds {@see ArgumentMetadata} objects based on the given Controller.
+ *
+ * @author Iltar van der Berg <kjarli@gmail.com>
+ */
+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();
+
+ if (is_array($controller)) {
+ $reflection = new \ReflectionMethod($controller[0], $controller[1]);
+ } 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());
+ }
+
+ 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)
+ {
+ 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 (preg_match('/^(?:[^ ]++ ){4}([a-zA-Z_\x7F-\xFF][^ ]++)/', $parameter, $info)) {
+ return $info[1];
+ }
+ }
+}
diff --git a/vendor/symfony/http-kernel/ControllerMetadata/ArgumentMetadataFactoryInterface.php b/vendor/symfony/http-kernel/ControllerMetadata/ArgumentMetadataFactoryInterface.php
new file mode 100644
index 0000000000..6ea179d783
--- /dev/null
+++ b/vendor/symfony/http-kernel/ControllerMetadata/ArgumentMetadataFactoryInterface.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\ControllerMetadata;
+
+/**
+ * Builds method argument data.
+ *
+ * @author Iltar van der Berg <kjarli@gmail.com>
+ */
+interface ArgumentMetadataFactoryInterface
+{
+ /**
+ * @param mixed $controller The controller to resolve the arguments for
+ *
+ * @return ArgumentMetadata[]
+ */
+ public function createArgumentMetadata($controller);
+}
diff --git a/vendor/symfony/http-kernel/DataCollector/AjaxDataCollector.php b/vendor/symfony/http-kernel/DataCollector/AjaxDataCollector.php
new file mode 100644
index 0000000000..b8405d5945
--- /dev/null
+++ b/vendor/symfony/http-kernel/DataCollector/AjaxDataCollector.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\HttpKernel\DataCollector;
+
+use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\HttpFoundation\Response;
+
+/**
+ * AjaxDataCollector.
+ *
+ * @author Bart van den Burg <bart@burgov.nl>
+ */
+class AjaxDataCollector extends DataCollector
+{
+ public function collect(Request $request, Response $response, \Exception $exception = null)
+ {
+ // all collecting is done client side
+ }
+
+ public function getName()
+ {
+ return 'ajax';
+ }
+}
diff --git a/vendor/symfony/http-kernel/DataCollector/ConfigDataCollector.php b/vendor/symfony/http-kernel/DataCollector/ConfigDataCollector.php
new file mode 100644
index 0000000000..87c4c08e69
--- /dev/null
+++ b/vendor/symfony/http-kernel/DataCollector/ConfigDataCollector.php
@@ -0,0 +1,330 @@
+<?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;
+
+use Symfony\Component\HttpKernel\KernelInterface;
+use Symfony\Component\HttpKernel\Kernel;
+use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\HttpFoundation\Response;
+use Symfony\Component\VarDumper\Caster\LinkStub;
+
+/**
+ * ConfigDataCollector.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+class ConfigDataCollector extends DataCollector implements LateDataCollectorInterface
+{
+ /**
+ * @var KernelInterface
+ */
+ private $kernel;
+ private $name;
+ private $version;
+ private $hasVarDumper;
+
+ /**
+ * Constructor.
+ *
+ * @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)
+ {
+ $this->name = $name;
+ $this->version = $version;
+ $this->hasVarDumper = class_exists(LinkStub::class);
+ }
+
+ /**
+ * Sets the Kernel associated with this Request.
+ *
+ * @param KernelInterface $kernel A KernelInterface instance
+ */
+ public function setKernel(KernelInterface $kernel = null)
+ {
+ $this->kernel = $kernel;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function collect(Request $request, Response $response, \Exception $exception = null)
+ {
+ $this->data = array(
+ '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,
+ );
+
+ if (isset($this->kernel)) {
+ foreach ($this->kernel->getBundles() as $name => $bundle) {
+ $this->data['bundles'][$name] = $this->hasVarDumper ? new LinkStub($bundle->getPath()) : $bundle->getPath();
+ }
+
+ $this->data['symfony_state'] = $this->determineSymfonyState();
+ $this->data['symfony_minor_version'] = sprintf('%s.%s', Kernel::MAJOR_VERSION, Kernel::MINOR_VERSION);
+ $eom = \DateTime::createFromFormat('m/Y', Kernel::END_OF_MAINTENANCE);
+ $eol = \DateTime::createFromFormat('m/Y', Kernel::END_OF_LIFE);
+ $this->data['symfony_eom'] = $eom->format('F Y');
+ $this->data['symfony_eol'] = $eol->format('F Y');
+ }
+
+ if (preg_match('~^(\d+(?:\.\d+)*)(.+)?$~', $this->data['php_version'], $matches) && isset($matches[2])) {
+ $this->data['php_version'] = $matches[1];
+ $this->data['php_version_extra'] = $matches[2];
+ }
+ }
+
+ public function lateCollect()
+ {
+ $this->data = $this->cloneVar($this->data);
+ }
+
+ public function getApplicationName()
+ {
+ return $this->data['app_name'];
+ }
+
+ public function getApplicationVersion()
+ {
+ return $this->data['app_version'];
+ }
+
+ /**
+ * Gets the token.
+ *
+ * @return string The token
+ */
+ public function getToken()
+ {
+ return $this->data['token'];
+ }
+
+ /**
+ * Gets the Symfony version.
+ *
+ * @return string The Symfony version
+ */
+ public function getSymfonyVersion()
+ {
+ return $this->data['symfony_version'];
+ }
+
+ /**
+ * Returns the state of the current Symfony release.
+ *
+ * @return string One of: unknown, dev, stable, eom, eol
+ */
+ public function getSymfonyState()
+ {
+ return $this->data['symfony_state'];
+ }
+
+ /**
+ * Returns the minor Symfony version used (without patch numbers of extra
+ * suffix like "RC", "beta", etc.).
+ *
+ * @return string
+ */
+ public function getSymfonyMinorVersion()
+ {
+ return $this->data['symfony_minor_version'];
+ }
+
+ /**
+ * Returns the human redable date when this Symfony version ends its
+ * maintenance period.
+ *
+ * @return string
+ */
+ public function getSymfonyEom()
+ {
+ return $this->data['symfony_eom'];
+ }
+
+ /**
+ * Returns the human redable date when this Symfony version reaches its
+ * "end of life" and won't receive bugs or security fixes.
+ *
+ * @return string
+ */
+ public function getSymfonyEol()
+ {
+ return $this->data['symfony_eol'];
+ }
+
+ /**
+ * Gets the PHP version.
+ *
+ * @return string The PHP version
+ */
+ public function getPhpVersion()
+ {
+ return $this->data['php_version'];
+ }
+
+ /**
+ * Gets the PHP version extra part.
+ *
+ * @return string|null The extra part
+ */
+ public function getPhpVersionExtra()
+ {
+ return isset($this->data['php_version_extra']) ? $this->data['php_version_extra'] : null;
+ }
+
+ /**
+ * @return int The PHP architecture as number of bits (e.g. 32 or 64)
+ */
+ public function getPhpArchitecture()
+ {
+ return $this->data['php_architecture'];
+ }
+
+ /**
+ * @return string
+ */
+ public function getPhpIntlLocale()
+ {
+ return $this->data['php_intl_locale'];
+ }
+
+ /**
+ * @return string
+ */
+ public function getPhpTimezone()
+ {
+ return $this->data['php_timezone'];
+ }
+
+ /**
+ * Gets the application name.
+ *
+ * @return string The application name
+ */
+ public function getAppName()
+ {
+ return $this->data['name'];
+ }
+
+ /**
+ * Gets the environment.
+ *
+ * @return string The environment
+ */
+ public function getEnv()
+ {
+ return $this->data['env'];
+ }
+
+ /**
+ * Returns true if the debug is enabled.
+ *
+ * @return bool true if debug is enabled, false otherwise
+ */
+ public function isDebug()
+ {
+ return $this->data['debug'];
+ }
+
+ /**
+ * Returns true if the XDebug is enabled.
+ *
+ * @return bool true if XDebug is enabled, false otherwise
+ */
+ public function hasXDebug()
+ {
+ return $this->data['xdebug_enabled'];
+ }
+
+ /**
+ * Returns true if APCu is enabled.
+ *
+ * @return bool true if APCu is enabled, false otherwise
+ */
+ public function hasApcu()
+ {
+ return $this->data['apcu_enabled'];
+ }
+
+ /**
+ * Returns true if Zend OPcache is enabled.
+ *
+ * @return bool true if Zend OPcache is enabled, false otherwise
+ */
+ public function hasZendOpcache()
+ {
+ return $this->data['zend_opcache_enabled'];
+ }
+
+ public function getBundles()
+ {
+ return $this->data['bundles'];
+ }
+
+ /**
+ * Gets the PHP SAPI name.
+ *
+ * @return string The environment
+ */
+ public function getSapiName()
+ {
+ return $this->data['sapi_name'];
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getName()
+ {
+ return 'config';
+ }
+
+ /**
+ * Tries to retrieve information about the current Symfony version.
+ *
+ * @return string One of: dev, stable, eom, eol
+ */
+ private function determineSymfonyState()
+ {
+ $now = new \DateTime();
+ $eom = \DateTime::createFromFormat('m/Y', Kernel::END_OF_MAINTENANCE)->modify('last day of this month');
+ $eol = \DateTime::createFromFormat('m/Y', Kernel::END_OF_LIFE)->modify('last day of this month');
+
+ if ($now > $eol) {
+ $versionState = 'eol';
+ } elseif ($now > $eom) {
+ $versionState = 'eom';
+ } elseif ('' !== Kernel::EXTRA_VERSION) {
+ $versionState = 'dev';
+ } else {
+ $versionState = 'stable';
+ }
+
+ return $versionState;
+ }
+}
diff --git a/vendor/symfony/http-kernel/DataCollector/DataCollector.php b/vendor/symfony/http-kernel/DataCollector/DataCollector.php
new file mode 100644
index 0000000000..845c2c1380
--- /dev/null
+++ b/vendor/symfony/http-kernel/DataCollector/DataCollector.php
@@ -0,0 +1,128 @@
+<?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;
+
+use Symfony\Component\HttpKernel\DataCollector\Util\ValueExporter;
+use Symfony\Component\VarDumper\Caster\CutStub;
+use Symfony\Component\VarDumper\Cloner\ClonerInterface;
+use Symfony\Component\VarDumper\Cloner\Data;
+use Symfony\Component\VarDumper\Cloner\Stub;
+use Symfony\Component\VarDumper\Cloner\VarCloner;
+
+/**
+ * DataCollector.
+ *
+ * Children of this class must store the collected data in the data property.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ * @author Bernhard Schussek <bschussek@symfony.com>
+ */
+abstract class DataCollector implements DataCollectorInterface, \Serializable
+{
+ protected $data = array();
+
+ /**
+ * @var ValueExporter
+ */
+ private $valueExporter;
+
+ /**
+ * @var ClonerInterface
+ */
+ private $cloner;
+
+ public function serialize()
+ {
+ return serialize($this->data);
+ }
+
+ public function unserialize($data)
+ {
+ $this->data = unserialize($data);
+ }
+
+ /**
+ * Converts the variable into a serializable Data instance.
+ *
+ * This array can be displayed in the template using
+ * the VarDumper component.
+ *
+ * @param mixed $var
+ *
+ * @return Data
+ */
+ protected function cloneVar($var)
+ {
+ if ($var instanceof Data) {
+ 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 version 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 (false === $this->cloner) {
+ if (null === $this->valueExporter) {
+ $this->valueExporter = new ValueExporter();
+ }
+
+ return $this->valueExporter->exportValue($var);
+ }
+
+ 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 version 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(
+ '*' => 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) {
+ $a[$k] = new CutStub($v);
+ }
+ }
+ }
+
+ return $a;
+ },
+ );
+ }
+}
diff --git a/vendor/symfony/http-kernel/DataCollector/DataCollectorInterface.php b/vendor/symfony/http-kernel/DataCollector/DataCollectorInterface.php
new file mode 100644
index 0000000000..2820ad5b28
--- /dev/null
+++ b/vendor/symfony/http-kernel/DataCollector/DataCollectorInterface.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\HttpKernel\DataCollector;
+
+use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\HttpFoundation\Response;
+
+/**
+ * DataCollectorInterface.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+interface DataCollectorInterface
+{
+ /**
+ * Collects data for the given Request and Response.
+ *
+ * @param Request $request A Request instance
+ * @param Response $response A Response instance
+ * @param \Exception $exception An Exception instance
+ */
+ public function collect(Request $request, Response $response, \Exception $exception = null);
+
+ /**
+ * Returns the name of the collector.
+ *
+ * @return string The collector name
+ */
+ public function getName();
+}
diff --git a/vendor/symfony/http-kernel/DataCollector/DumpDataCollector.php b/vendor/symfony/http-kernel/DataCollector/DumpDataCollector.php
new file mode 100644
index 0000000000..b50386cb96
--- /dev/null
+++ b/vendor/symfony/http-kernel/DataCollector/DumpDataCollector.php
@@ -0,0 +1,303 @@
+<?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;
+
+use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\HttpFoundation\RequestStack;
+use Symfony\Component\HttpFoundation\Response;
+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\DataDumperInterface;
+use Twig\Template;
+
+/**
+ * @author Nicolas Grekas <p@tchwork.com>
+ */
+class DumpDataCollector extends DataCollector implements DataDumperInterface
+{
+ private $stopwatch;
+ private $fileLinkFormat;
+ private $dataCount = 0;
+ private $isCollected = true;
+ private $clonesCount = 0;
+ private $clonesIndex = 0;
+ private $rootRefs;
+ private $charset;
+ private $requestStack;
+ private $dumper;
+ private $dumperIsInjected;
+
+ public function __construct(Stopwatch $stopwatch = null, $fileLinkFormat = null, $charset = null, RequestStack $requestStack = null, DataDumperInterface $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->data,
+ &$this->dataCount,
+ &$this->isCollected,
+ &$this->clonesCount,
+ );
+ }
+
+ public function __clone()
+ {
+ $this->clonesIndex = ++$this->clonesCount;
+ }
+
+ public function dump(Data $data)
+ {
+ 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;
+ }
+ }
+
+ if (false === $name) {
+ $name = str_replace('\\', '/', $file);
+ $name = substr($name, strrpos($name, '/') + 1);
+ }
+
+ if ($this->dumper) {
+ $this->doDump($data, $name, $file, $line);
+ }
+
+ $this->data[] = compact('data', 'name', 'file', 'line', 'fileExcerpt');
+ ++$this->dataCount;
+
+ if ($this->stopwatch) {
+ $this->stopwatch->stop('dump');
+ }
+ }
+
+ public function collect(Request $request, Response $response, \Exception $exception = null)
+ {
+ // 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;
+ }
+
+ // In all other conditions that remove the web debug toolbar, dumps are written on the output.
+ if (!$this->requestStack
+ || !$response->headers->has('X-Debug-Token')
+ || $response->isRedirection()
+ || ($response->headers->has('Content-Type') && false === strpos($response->headers->get('Content-Type'), 'html'))
+ || 'html' !== $request->getRequestFormat()
+ || 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));
+ } else {
+ $this->dumper = new CliDumper('php://output', $this->charset);
+ }
+
+ foreach ($this->data as $dump) {
+ $this->doDump($dump['data'], $dump['name'], $dump['file'], $dump['line']);
+ }
+ }
+ }
+
+ public function serialize()
+ {
+ if ($this->clonesCount !== $this->clonesIndex) {
+ return 'a:0:{}';
+ }
+
+ $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;
+ }
+
+ public function unserialize($data)
+ {
+ parent::unserialize($data);
+ $charset = array_pop($this->data);
+ $fileLinkFormat = array_pop($this->data);
+ $this->dataCount = count($this->data);
+ self::__construct($this->stopwatch, $fileLinkFormat, $charset);
+ }
+
+ public function getDumpsCount()
+ {
+ return $this->dataCount;
+ }
+
+ public function getDumps($format, $maxDepthLimit = -1, $maxItemsPerDepth = -1)
+ {
+ $data = fopen('php://memory', 'r+b');
+
+ if ('html' === $format) {
+ $dumper = new HtmlDumper($data, $this->charset);
+ $dumper->setDisplayOptions(array('fileLinkFormat' => $this->fileLinkFormat));
+ } else {
+ throw new \InvalidArgumentException(sprintf('Invalid dump format: %s', $format));
+ }
+ $dumps = array();
+
+ foreach ($this->data as $dump) {
+ $dumper->dump($dump['data']->withMaxDepth($maxDepthLimit)->withMaxItemsPerDepth($maxItemsPerDepth));
+ $dump['data'] = stream_get_contents($data, -1, 0);
+ ftruncate($data, 0);
+ rewind($data);
+ $dumps[] = $dump;
+ }
+
+ return $dumps;
+ }
+
+ public function getName()
+ {
+ return 'dump';
+ }
+
+ public function __destruct()
+ {
+ if (0 === $this->clonesCount-- && !$this->isCollected && $this->data) {
+ $this->clonesCount = 0;
+ $this->isCollected = true;
+
+ $h = headers_list();
+ $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));
+ } else {
+ $this->dumper = new CliDumper('php://output', $this->charset);
+ }
+
+ foreach ($this->data as $i => $dump) {
+ $this->data[$i] = null;
+ $this->doDump($dump['data'], $dump['name'], $dump['file'], $dump['line']);
+ }
+
+ $this->data = array();
+ $this->dataCount = 0;
+ }
+ }
+
+ private function doDump($data, $name, $file, $line)
+ {
+ if ($this->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)) {
+ $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);
+ }
+ } else {
+ $name = $this->style('meta', $name);
+ }
+ $this->line = $name.' on line '.$this->style('meta', $line).':';
+ } else {
+ $this->line = $this->style('meta', $name).' on line '.$this->style('meta', $line).':';
+ }
+ $this->dumpLine(0);
+ };
+ $contextDumper = $contextDumper->bindTo($this->dumper, $this->dumper);
+ $contextDumper($name, $file, $line, $this->fileLinkFormat);
+ } else {
+ $cloner = new VarCloner();
+ $this->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);
+ }
+}
diff --git a/vendor/symfony/http-kernel/DataCollector/EventDataCollector.php b/vendor/symfony/http-kernel/DataCollector/EventDataCollector.php
new file mode 100644
index 0000000000..3d75f322d8
--- /dev/null
+++ b/vendor/symfony/http-kernel/DataCollector/EventDataCollector.php
@@ -0,0 +1,108 @@
+<?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;
+
+use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\HttpFoundation\Response;
+use Symfony\Component\EventDispatcher\EventDispatcherInterface;
+use Symfony\Component\EventDispatcher\Debug\TraceableEventDispatcherInterface;
+
+/**
+ * EventDataCollector.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+class EventDataCollector extends DataCollector implements LateDataCollectorInterface
+{
+ protected $dispatcher;
+
+ public function __construct(EventDispatcherInterface $dispatcher = null)
+ {
+ $this->dispatcher = $dispatcher;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function collect(Request $request, Response $response, \Exception $exception = null)
+ {
+ $this->data = array(
+ 'called_listeners' => array(),
+ 'not_called_listeners' => array(),
+ );
+ }
+
+ public function lateCollect()
+ {
+ if ($this->dispatcher instanceof TraceableEventDispatcherInterface) {
+ $this->setCalledListeners($this->dispatcher->getCalledListeners());
+ $this->setNotCalledListeners($this->dispatcher->getNotCalledListeners());
+ }
+ $this->data = $this->cloneVar($this->data);
+ }
+
+ /**
+ * Sets the called listeners.
+ *
+ * @param array $listeners An array of called listeners
+ *
+ * @see TraceableEventDispatcherInterface
+ */
+ public function setCalledListeners(array $listeners)
+ {
+ $this->data['called_listeners'] = $listeners;
+ }
+
+ /**
+ * Gets the called listeners.
+ *
+ * @return array An array of called listeners
+ *
+ * @see TraceableEventDispatcherInterface
+ */
+ public function getCalledListeners()
+ {
+ return $this->data['called_listeners'];
+ }
+
+ /**
+ * Sets the not called listeners.
+ *
+ * @param array $listeners An array of not called listeners
+ *
+ * @see TraceableEventDispatcherInterface
+ */
+ public function setNotCalledListeners(array $listeners)
+ {
+ $this->data['not_called_listeners'] = $listeners;
+ }
+
+ /**
+ * Gets the not called listeners.
+ *
+ * @return array An array of not called listeners
+ *
+ * @see TraceableEventDispatcherInterface
+ */
+ public function getNotCalledListeners()
+ {
+ return $this->data['not_called_listeners'];
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getName()
+ {
+ return 'events';
+ }
+}
diff --git a/vendor/symfony/http-kernel/DataCollector/ExceptionDataCollector.php b/vendor/symfony/http-kernel/DataCollector/ExceptionDataCollector.php
new file mode 100644
index 0000000000..9fe826446b
--- /dev/null
+++ b/vendor/symfony/http-kernel/DataCollector/ExceptionDataCollector.php
@@ -0,0 +1,104 @@
+<?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;
+
+use Symfony\Component\Debug\Exception\FlattenException;
+use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\HttpFoundation\Response;
+
+/**
+ * ExceptionDataCollector.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+class ExceptionDataCollector extends DataCollector
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function collect(Request $request, Response $response, \Exception $exception = null)
+ {
+ if (null !== $exception) {
+ $this->data = array(
+ 'exception' => FlattenException::create($exception),
+ );
+ }
+ }
+
+ /**
+ * Checks if the exception is not null.
+ *
+ * @return bool true if the exception is not null, false otherwise
+ */
+ public function hasException()
+ {
+ return isset($this->data['exception']);
+ }
+
+ /**
+ * Gets the exception.
+ *
+ * @return \Exception The exception
+ */
+ public function getException()
+ {
+ return $this->data['exception'];
+ }
+
+ /**
+ * Gets the exception message.
+ *
+ * @return string The exception message
+ */
+ public function getMessage()
+ {
+ return $this->data['exception']->getMessage();
+ }
+
+ /**
+ * Gets the exception code.
+ *
+ * @return int The exception code
+ */
+ public function getCode()
+ {
+ return $this->data['exception']->getCode();
+ }
+
+ /**
+ * Gets the status code.
+ *
+ * @return int The status code
+ */
+ public function getStatusCode()
+ {
+ return $this->data['exception']->getStatusCode();
+ }
+
+ /**
+ * Gets the exception trace.
+ *
+ * @return array The exception trace
+ */
+ public function getTrace()
+ {
+ return $this->data['exception']->getTrace();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getName()
+ {
+ return 'exception';
+ }
+}
diff --git a/vendor/symfony/http-kernel/DataCollector/LateDataCollectorInterface.php b/vendor/symfony/http-kernel/DataCollector/LateDataCollectorInterface.php
new file mode 100644
index 0000000000..012332de47
--- /dev/null
+++ b/vendor/symfony/http-kernel/DataCollector/LateDataCollectorInterface.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\DataCollector;
+
+/**
+ * LateDataCollectorInterface.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+interface LateDataCollectorInterface
+{
+ /**
+ * Collects data as late as possible.
+ */
+ public function lateCollect();
+}
diff --git a/vendor/symfony/http-kernel/DataCollector/LoggerDataCollector.php b/vendor/symfony/http-kernel/DataCollector/LoggerDataCollector.php
new file mode 100644
index 0000000000..92fd0da71e
--- /dev/null
+++ b/vendor/symfony/http-kernel/DataCollector/LoggerDataCollector.php
@@ -0,0 +1,262 @@
+<?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;
+
+use Symfony\Component\Debug\Exception\SilencedErrorContext;
+use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\HttpFoundation\Response;
+use Symfony\Component\HttpKernel\Log\DebugLoggerInterface;
+
+/**
+ * LogDataCollector.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+class LoggerDataCollector extends DataCollector implements LateDataCollectorInterface
+{
+ private $logger;
+ private $containerPathPrefix;
+
+ public function __construct($logger = null, $containerPathPrefix = null)
+ {
+ if (null !== $logger && $logger instanceof DebugLoggerInterface) {
+ $this->logger = $logger;
+ }
+
+ $this->containerPathPrefix = $containerPathPrefix;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function collect(Request $request, Response $response, \Exception $exception = null)
+ {
+ // everything is done as late as possible
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function lateCollect()
+ {
+ 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));
+ $this->data = $this->cloneVar($this->data);
+ }
+ }
+
+ /**
+ * Gets the logs.
+ *
+ * @return array An array of logs
+ */
+ public function getLogs()
+ {
+ return isset($this->data['logs']) ? $this->data['logs'] : array();
+ }
+
+ public function getPriorities()
+ {
+ return isset($this->data['priorities']) ? $this->data['priorities'] : array();
+ }
+
+ public function countErrors()
+ {
+ return isset($this->data['error_count']) ? $this->data['error_count'] : 0;
+ }
+
+ public function countDeprecations()
+ {
+ return isset($this->data['deprecation_count']) ? $this->data['deprecation_count'] : 0;
+ }
+
+ public function countWarnings()
+ {
+ return isset($this->data['warning_count']) ? $this->data['warning_count'] : 0;
+ }
+
+ public function countScreams()
+ {
+ return isset($this->data['scream_count']) ? $this->data['scream_count'] : 0;
+ }
+
+ public function getCompilerLogs()
+ {
+ return isset($this->data['compiler_logs']) ? $this->data['compiler_logs'] : array();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getName()
+ {
+ return 'logger';
+ }
+
+ private function getContainerDeprecationLogs()
+ {
+ if (null === $this->containerPathPrefix || !file_exists($file = $this->containerPathPrefix.'Deprecations.log')) {
+ return array();
+ }
+
+ $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']));
+ $log['timestamp'] = $bootTime;
+ $log['priority'] = 100;
+ $log['priorityName'] = 'DEBUG';
+ $log['channel'] = '-';
+ $log['scream'] = false;
+ unset($log['type'], $log['file'], $log['line'], $log['trace'], $log['trace'], $log['count']);
+ $logs[] = $log;
+ }
+
+ return $logs;
+ }
+
+ private function getContainerCompilerLogs()
+ {
+ if (null === $this->containerPathPrefix || !file_exists($file = $this->containerPathPrefix.'Compiler.log')) {
+ return array();
+ }
+
+ $logs = array();
+ foreach (file($file, 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));
+ }
+
+ $logs[$log[0]][] = array('message' => $log[1]);
+ }
+
+ return $logs;
+ }
+
+ private function sanitizeLogs($logs)
+ {
+ $sanitizedLogs = array();
+
+ foreach ($logs as $log) {
+ if (!$this->isSilencedOrDeprecationErrorLog($log)) {
+ $sanitizedLogs[] = $log;
+
+ continue;
+ }
+
+ $message = $log['message'];
+ $exception = $log['context']['exception'];
+
+ if ($exception instanceof SilencedErrorContext) {
+ if (isset($silencedLogs[$h = spl_object_hash($exception)])) {
+ continue;
+ }
+ $silencedLogs[$h] = true;
+
+ if (!isset($sanitizedLogs[$message])) {
+ $sanitizedLogs[$message] = $log + array(
+ 'errorCount' => 0,
+ 'scream' => true,
+ );
+ }
+ $sanitizedLogs[$message]['errorCount'] += $exception->count;
+
+ continue;
+ }
+
+ $errorId = md5("{$exception->getSeverity()}/{$exception->getLine()}/{$exception->getFile()}\0{$message}", true);
+
+ if (isset($sanitizedLogs[$errorId])) {
+ ++$sanitizedLogs[$errorId]['errorCount'];
+ } else {
+ $log += array(
+ 'errorCount' => 1,
+ 'scream' => false,
+ );
+
+ $sanitizedLogs[$errorId] = $log;
+ }
+ }
+
+ return array_values($sanitizedLogs);
+ }
+
+ private function isSilencedOrDeprecationErrorLog(array $log)
+ {
+ if (!isset($log['context']['exception'])) {
+ return false;
+ }
+
+ $exception = $log['context']['exception'];
+
+ if ($exception instanceof SilencedErrorContext) {
+ return true;
+ }
+
+ if ($exception instanceof \ErrorException && in_array($exception->getSeverity(), array(E_DEPRECATED, E_USER_DEPRECATED), true)) {
+ return true;
+ }
+
+ return false;
+ }
+
+ private function computeErrorsCount(array $containerDeprecationLogs)
+ {
+ $silencedLogs = array();
+ $count = array(
+ 'error_count' => $this->logger->countErrors(),
+ 'deprecation_count' => 0,
+ 'warning_count' => 0,
+ 'scream_count' => 0,
+ 'priorities' => array(),
+ );
+
+ foreach ($this->logger->getLogs() as $log) {
+ if (isset($count['priorities'][$log['priority']])) {
+ ++$count['priorities'][$log['priority']]['count'];
+ } else {
+ $count['priorities'][$log['priority']] = array(
+ 'count' => 1,
+ 'name' => $log['priorityName'],
+ );
+ }
+ if ('WARNING' === $log['priorityName']) {
+ ++$count['warning_count'];
+ }
+
+ if ($this->isSilencedOrDeprecationErrorLog($log)) {
+ $exception = $log['context']['exception'];
+ if ($exception instanceof SilencedErrorContext) {
+ if (isset($silencedLogs[$h = spl_object_hash($exception)])) {
+ continue;
+ }
+ $silencedLogs[$h] = true;
+ $count['scream_count'] += $exception->count;
+ } else {
+ ++$count['deprecation_count'];
+ }
+ }
+ }
+
+ foreach ($containerDeprecationLogs as $deprecationLog) {
+ $count['deprecation_count'] += $deprecationLog['context']['exception']->count;
+ }
+
+ ksort($count['priorities']);
+
+ return $count;
+ }
+}
diff --git a/vendor/symfony/http-kernel/DataCollector/MemoryDataCollector.php b/vendor/symfony/http-kernel/DataCollector/MemoryDataCollector.php
new file mode 100644
index 0000000000..9385010844
--- /dev/null
+++ b/vendor/symfony/http-kernel/DataCollector/MemoryDataCollector.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\DataCollector;
+
+use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\HttpFoundation\Response;
+
+/**
+ * MemoryDataCollector.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+class MemoryDataCollector extends DataCollector implements LateDataCollectorInterface
+{
+ public function __construct()
+ {
+ $this->data = array(
+ 'memory' => 0,
+ 'memory_limit' => $this->convertToBytes(ini_get('memory_limit')),
+ );
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function collect(Request $request, Response $response, \Exception $exception = null)
+ {
+ $this->updateMemoryUsage();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function lateCollect()
+ {
+ $this->updateMemoryUsage();
+ }
+
+ /**
+ * Gets the memory.
+ *
+ * @return int The memory
+ */
+ public function getMemory()
+ {
+ return $this->data['memory'];
+ }
+
+ /**
+ * Gets the PHP memory limit.
+ *
+ * @return int The memory limit
+ */
+ public function getMemoryLimit()
+ {
+ return $this->data['memory_limit'];
+ }
+
+ /**
+ * Updates the memory usage data.
+ */
+ public function updateMemoryUsage()
+ {
+ $this->data['memory'] = memory_get_peak_usage(true);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getName()
+ {
+ return 'memory';
+ }
+
+ private function convertToBytes($memoryLimit)
+ {
+ if ('-1' === $memoryLimit) {
+ return -1;
+ }
+
+ $memoryLimit = strtolower($memoryLimit);
+ $max = strtolower(ltrim($memoryLimit, '+'));
+ if (0 === strpos($max, '0x')) {
+ $max = intval($max, 16);
+ } elseif (0 === strpos($max, '0')) {
+ $max = intval($max, 8);
+ } else {
+ $max = (int) $max;
+ }
+
+ switch (substr($memoryLimit, -1)) {
+ case 't': $max *= 1024;
+ case 'g': $max *= 1024;
+ case 'm': $max *= 1024;
+ case 'k': $max *= 1024;
+ }
+
+ return $max;
+ }
+}
diff --git a/vendor/symfony/http-kernel/DataCollector/RequestDataCollector.php b/vendor/symfony/http-kernel/DataCollector/RequestDataCollector.php
new file mode 100644
index 0000000000..7049844f9e
--- /dev/null
+++ b/vendor/symfony/http-kernel/DataCollector/RequestDataCollector.php
@@ -0,0 +1,397 @@
+<?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;
+
+use Symfony\Component\HttpFoundation\ParameterBag;
+use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\HttpFoundation\Response;
+use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
+use Symfony\Component\HttpKernel\KernelEvents;
+use Symfony\Component\HttpKernel\Event\FilterControllerEvent;
+use Symfony\Component\EventDispatcher\EventSubscriberInterface;
+
+/**
+ * RequestDataCollector.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+class RequestDataCollector extends DataCollector implements EventSubscriberInterface, LateDataCollectorInterface
+{
+ /** @var \SplObjectStorage */
+ protected $controllers;
+
+ public function __construct()
+ {
+ $this->controllers = new \SplObjectStorage();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ 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();
+ $route = '';
+ foreach ($request->attributes->all() as $key => $value) {
+ if ('_route' === $key) {
+ $route = is_object($value) ? $value->getPath() : $value;
+ $attributes[$key] = $route;
+ } else {
+ $attributes[$key] = $value;
+ }
+ }
+
+ $content = null;
+ try {
+ $content = $request->getContent();
+ } catch (\LogicException $e) {
+ // the user already got the request content as a resource
+ $content = false;
+ }
+
+ $sessionMetadata = array();
+ $sessionAttributes = array();
+ $session = null;
+ $flashes = array();
+ if ($request->hasSession()) {
+ $session = $request->getSession();
+ if ($session->isStarted()) {
+ $sessionMetadata['Created'] = date(DATE_RFC822, $session->getMetadataBag()->getCreated());
+ $sessionMetadata['Last used'] = date(DATE_RFC822, $session->getMetadataBag()->getLastUsed());
+ $sessionMetadata['Lifetime'] = $session->getMetadataBag()->getLifetime();
+ $sessionAttributes = $session->all();
+ $flashes = $session->getFlashBag()->peekAll();
+ }
+ }
+
+ $statusCode = $response->getStatusCode();
+
+ $responseCookies = array();
+ foreach ($response->headers->getCookies() as $cookie) {
+ $responseCookies[$cookie->getName()] = $cookie;
+ }
+
+ $this->data = array(
+ 'method' => $request->getMethod(),
+ 'format' => $request->getRequestFormat(),
+ 'content' => $content,
+ 'content_type' => $response->headers->get('Content-Type', 'text/html'),
+ 'status_text' => isset(Response::$statusTexts[$statusCode]) ? Response::$statusTexts[$statusCode] : '',
+ 'status_code' => $statusCode,
+ 'request_query' => $request->query->all(),
+ 'request_request' => $request->request->all(),
+ 'request_headers' => $request->headers->all(),
+ 'request_server' => $request->server->all(),
+ 'request_cookies' => $request->cookies->all(),
+ 'request_attributes' => $attributes,
+ 'route' => $route,
+ 'response_headers' => $response->headers->all(),
+ 'response_cookies' => $responseCookies,
+ 'session_metadata' => $sessionMetadata,
+ 'session_attributes' => $sessionAttributes,
+ 'flashes' => $flashes,
+ 'path_info' => $request->getPathInfo(),
+ 'controller' => 'n/a',
+ 'locale' => $request->getLocale(),
+ );
+
+ if (isset($this->data['request_headers']['php-auth-pw'])) {
+ $this->data['request_headers']['php-auth-pw'] = '******';
+ }
+
+ if (isset($this->data['request_server']['PHP_AUTH_PW'])) {
+ $this->data['request_server']['PHP_AUTH_PW'] = '******';
+ }
+
+ if (isset($this->data['request_request']['_password'])) {
+ $this->data['request_request']['_password'] = '******';
+ }
+
+ foreach ($this->data as $key => $value) {
+ if (!is_array($value)) {
+ continue;
+ }
+ if ('request_headers' === $key || 'response_headers' === $key) {
+ $this->data[$key] = array_map(function ($v) { return isset($v[0]) && !isset($v[1]) ? $v[0] : $v; }, $value);
+ }
+ }
+
+ if (isset($this->controllers[$request])) {
+ $this->data['controller'] = $this->parseController($this->controllers[$request]);
+ unset($this->controllers[$request]);
+ }
+
+ if (null !== $session && $session->isStarted()) {
+ if ($request->attributes->has('_redirected')) {
+ $this->data['redirect'] = $session->remove('sf_redirect');
+ }
+
+ if ($response->isRedirect()) {
+ $session->set('sf_redirect', array(
+ '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],
+ ));
+ }
+ }
+
+ $this->data['identifier'] = $this->data['route'] ?: (is_array($this->data['controller']) ? $this->data['controller']['class'].'::'.$this->data['controller']['method'].'()' : $this->data['controller']);
+ }
+
+ public function lateCollect()
+ {
+ $this->data = $this->cloneVar($this->data);
+ }
+
+ public function getMethod()
+ {
+ return $this->data['method'];
+ }
+
+ public function getPathInfo()
+ {
+ return $this->data['path_info'];
+ }
+
+ public function getRequestRequest()
+ {
+ return new ParameterBag($this->data['request_request']->getValue());
+ }
+
+ public function getRequestQuery()
+ {
+ return new ParameterBag($this->data['request_query']->getValue());
+ }
+
+ public function getRequestHeaders()
+ {
+ return new ParameterBag($this->data['request_headers']->getValue());
+ }
+
+ public function getRequestServer($raw = false)
+ {
+ return new ParameterBag($this->data['request_server']->getValue($raw));
+ }
+
+ public function getRequestCookies($raw = false)
+ {
+ return new ParameterBag($this->data['request_cookies']->getValue($raw));
+ }
+
+ public function getRequestAttributes()
+ {
+ return new ParameterBag($this->data['request_attributes']->getValue());
+ }
+
+ public function getResponseHeaders()
+ {
+ return new ParameterBag($this->data['response_headers']->getValue());
+ }
+
+ public function getResponseCookies()
+ {
+ return new ParameterBag($this->data['response_cookies']->getValue());
+ }
+
+ public function getSessionMetadata()
+ {
+ return $this->data['session_metadata']->getValue();
+ }
+
+ public function getSessionAttributes()
+ {
+ return $this->data['session_attributes']->getValue();
+ }
+
+ public function getFlashes()
+ {
+ return $this->data['flashes']->getValue();
+ }
+
+ public function getContent()
+ {
+ return $this->data['content'];
+ }
+
+ public function getContentType()
+ {
+ return $this->data['content_type'];
+ }
+
+ public function getStatusText()
+ {
+ return $this->data['status_text'];
+ }
+
+ public function getStatusCode()
+ {
+ return $this->data['status_code'];
+ }
+
+ public function getFormat()
+ {
+ return $this->data['format'];
+ }
+
+ public function getLocale()
+ {
+ return $this->data['locale'];
+ }
+
+ /**
+ * Gets the route name.
+ *
+ * The _route request attributes is automatically set by the Router Matcher.
+ *
+ * @return string The route
+ */
+ public function getRoute()
+ {
+ return $this->data['route'];
+ }
+
+ public function getIdentifier()
+ {
+ return $this->data['identifier'];
+ }
+
+ /**
+ * Gets the route parameters.
+ *
+ * The _route_params request attributes is automatically set by the RouterListener.
+ *
+ * @return array The parameters
+ */
+ public function getRouteParams()
+ {
+ return isset($this->data['request_attributes']['_route_params']) ? $this->data['request_attributes']['_route_params']->getValue() : array();
+ }
+
+ /**
+ * Gets the parsed controller.
+ *
+ * @return array|string The controller as a string or array of data
+ * with keys 'class', 'method', 'file' and 'line'
+ */
+ public function getController()
+ {
+ return $this->data['controller'];
+ }
+
+ /**
+ * Gets the previous request attributes.
+ *
+ * @return array|bool A legacy array of data from the previous redirection response
+ * or false otherwise
+ */
+ public function getRedirect()
+ {
+ return isset($this->data['redirect']) ? $this->data['redirect'] : false;
+ }
+
+ public function onKernelController(FilterControllerEvent $event)
+ {
+ $this->controllers[$event->getRequest()] = $event->getController();
+ }
+
+ public function onKernelResponse(FilterResponseEvent $event)
+ {
+ if (!$event->isMasterRequest() || !$event->getRequest()->hasSession() || !$event->getRequest()->getSession()->isStarted()) {
+ return;
+ }
+
+ if ($event->getRequest()->getSession()->has('sf_redirect')) {
+ $event->getRequest()->attributes->set('_redirected', true);
+ }
+ }
+
+ public static function getSubscribedEvents()
+ {
+ return array(
+ KernelEvents::CONTROLLER => 'onKernelController',
+ KernelEvents::RESPONSE => 'onKernelResponse',
+ );
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getName()
+ {
+ return 'request';
+ }
+
+ /**
+ * Parse a controller.
+ *
+ * @param mixed $controller The controller to parse
+ *
+ * @return array|string An array of controller data or a simple string
+ */
+ protected function parseController($controller)
+ {
+ if (is_string($controller) && false !== strpos($controller, '::')) {
+ $controller = explode('::', $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],
+ 'method' => $controller[1],
+ 'file' => $r->getFileName(),
+ 'line' => $r->getStartLine(),
+ );
+ } catch (\ReflectionException $e) {
+ if (is_callable($controller)) {
+ // using __call or __callStatic
+ return array(
+ 'class' => is_object($controller[0]) ? get_class($controller[0]) : $controller[0],
+ 'method' => $controller[1],
+ 'file' => 'n/a',
+ 'line' => 'n/a',
+ );
+ }
+ }
+ }
+
+ if ($controller instanceof \Closure) {
+ $r = new \ReflectionFunction($controller);
+
+ return array(
+ 'class' => $r->getName(),
+ 'method' => null,
+ 'file' => $r->getFileName(),
+ 'line' => $r->getStartLine(),
+ );
+ }
+
+ if (is_object($controller)) {
+ $r = new \ReflectionClass($controller);
+
+ return array(
+ 'class' => $r->getName(),
+ 'method' => null,
+ 'file' => $r->getFileName(),
+ 'line' => $r->getStartLine(),
+ );
+ }
+
+ 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
new file mode 100644
index 0000000000..76d9623461
--- /dev/null
+++ b/vendor/symfony/http-kernel/DataCollector/RouterDataCollector.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\HttpKernel\DataCollector;
+
+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
+{
+ protected $controllers;
+
+ public function __construct()
+ {
+ $this->controllers = new \SplObjectStorage();
+
+ $this->data = array(
+ 'redirect' => false,
+ 'url' => null,
+ 'route' => null,
+ );
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function collect(Request $request, Response $response, \Exception $exception = null)
+ {
+ if ($response instanceof RedirectResponse) {
+ $this->data['redirect'] = true;
+ $this->data['url'] = $response->getTargetUrl();
+
+ if ($this->controllers->contains($request)) {
+ $this->data['route'] = $this->guessRoute($request, $this->controllers[$request]);
+ }
+ }
+
+ unset($this->controllers[$request]);
+ }
+
+ protected function guessRoute(Request $request, $controller)
+ {
+ return 'n/a';
+ }
+
+ /**
+ * Remembers the controller associated to each request.
+ *
+ * @param FilterControllerEvent $event The filter controller event
+ */
+ public function onKernelController(FilterControllerEvent $event)
+ {
+ $this->controllers[$event->getRequest()] = $event->getController();
+ }
+
+ /**
+ * @return bool Whether this request will result in a redirect
+ */
+ public function getRedirect()
+ {
+ return $this->data['redirect'];
+ }
+
+ /**
+ * @return string|null The target URL
+ */
+ public function getTargetUrl()
+ {
+ return $this->data['url'];
+ }
+
+ /**
+ * @return string|null The target route
+ */
+ public function getTargetRoute()
+ {
+ return $this->data['route'];
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getName()
+ {
+ return 'router';
+ }
+}
diff --git a/vendor/symfony/http-kernel/DataCollector/TimeDataCollector.php b/vendor/symfony/http-kernel/DataCollector/TimeDataCollector.php
new file mode 100644
index 0000000000..2d39156e69
--- /dev/null
+++ b/vendor/symfony/http-kernel/DataCollector/TimeDataCollector.php
@@ -0,0 +1,136 @@
+<?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;
+
+use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\HttpFoundation\Response;
+use Symfony\Component\HttpKernel\KernelInterface;
+
+/**
+ * TimeDataCollector.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+class TimeDataCollector extends DataCollector implements LateDataCollectorInterface
+{
+ protected $kernel;
+ protected $stopwatch;
+
+ public function __construct(KernelInterface $kernel = null, $stopwatch = null)
+ {
+ $this->kernel = $kernel;
+ $this->stopwatch = $stopwatch;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function collect(Request $request, Response $response, \Exception $exception = null)
+ {
+ if (null !== $this->kernel) {
+ $startTime = $this->kernel->getStartTime();
+ } else {
+ $startTime = $request->server->get('REQUEST_TIME_FLOAT');
+ }
+
+ $this->data = array(
+ 'token' => $response->headers->get('X-Debug-Token'),
+ 'start_time' => $startTime * 1000,
+ 'events' => array(),
+ );
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function lateCollect()
+ {
+ if (null !== $this->stopwatch && isset($this->data['token'])) {
+ $this->setEvents($this->stopwatch->getSectionEvents($this->data['token']));
+ }
+ unset($this->data['token']);
+ }
+
+ /**
+ * Sets the request events.
+ *
+ * @param array $events The request events
+ */
+ public function setEvents(array $events)
+ {
+ foreach ($events as $event) {
+ $event->ensureStopped();
+ }
+
+ $this->data['events'] = $events;
+ }
+
+ /**
+ * Gets the request events.
+ *
+ * @return array The request events
+ */
+ public function getEvents()
+ {
+ return $this->data['events'];
+ }
+
+ /**
+ * Gets the request elapsed time.
+ *
+ * @return float The elapsed time
+ */
+ public function getDuration()
+ {
+ if (!isset($this->data['events']['__section__'])) {
+ return 0;
+ }
+
+ $lastEvent = $this->data['events']['__section__'];
+
+ return $lastEvent->getOrigin() + $lastEvent->getDuration() - $this->getStartTime();
+ }
+
+ /**
+ * Gets the initialization time.
+ *
+ * This is the time spent until the beginning of the request handling.
+ *
+ * @return float The elapsed time
+ */
+ public function getInitTime()
+ {
+ if (!isset($this->data['events']['__section__'])) {
+ return 0;
+ }
+
+ return $this->data['events']['__section__']->getOrigin() - $this->getStartTime();
+ }
+
+ /**
+ * Gets the request time.
+ *
+ * @return int The time
+ */
+ public function getStartTime()
+ {
+ return $this->data['start_time'];
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getName()
+ {
+ return 'time';
+ }
+}
diff --git a/vendor/symfony/http-kernel/DataCollector/Util/ValueExporter.php b/vendor/symfony/http-kernel/DataCollector/Util/ValueExporter.php
new file mode 100644
index 0000000000..f1e48311c0
--- /dev/null
+++ b/vendor/symfony/http-kernel/DataCollector/Util/ValueExporter.php
@@ -0,0 +1,99 @@
+<?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 version 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
new file mode 100644
index 0000000000..c340d9b672
--- /dev/null
+++ b/vendor/symfony/http-kernel/Debug/FileLinkFormatter.php
@@ -0,0 +1,88 @@
+<?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\Debug;
+
+use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\HttpFoundation\RequestStack;
+
+/**
+ * Formats debug file links.
+ *
+ * @author Jérémy Romey <jeremy@free-agent.fr>
+ */
+class FileLinkFormatter implements \Serializable
+{
+ private $fileLinkFormat;
+ private $requestStack;
+ private $baseDir;
+ private $urlFormat;
+
+ public function __construct($fileLinkFormat = null, RequestStack $requestStack = null, $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);
+ }
+
+ $this->fileLinkFormat = $fileLinkFormat;
+ $this->requestStack = $requestStack;
+ $this->baseDir = $baseDir;
+ $this->urlFormat = $urlFormat;
+ }
+
+ public function format($file, $line)
+ {
+ 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));
+ break;
+ }
+ }
+
+ return strtr($fmt[0], array('%f' => $file, '%l' => $line));
+ }
+
+ return false;
+ }
+
+ public function serialize()
+ {
+ return serialize($this->getFileLinkFormat());
+ }
+
+ public function unserialize($serialized)
+ {
+ if (\PHP_VERSION_ID >= 70000) {
+ $this->fileLinkFormat = unserialize($serialized, array('allowed_classes' => false));
+ } else {
+ $this->fileLinkFormat = unserialize($serialized);
+ }
+ }
+
+ private function getFileLinkFormat()
+ {
+ 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, '',
+ );
+ }
+ }
+ }
+}
diff --git a/vendor/symfony/http-kernel/Debug/TraceableEventDispatcher.php b/vendor/symfony/http-kernel/Debug/TraceableEventDispatcher.php
new file mode 100644
index 0000000000..fbc49dffc8
--- /dev/null
+++ b/vendor/symfony/http-kernel/Debug/TraceableEventDispatcher.php
@@ -0,0 +1,82 @@
+<?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\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.
+ *
+ * This event dispatcher delegates the dispatching to another one.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+class TraceableEventDispatcher extends BaseTraceableEventDispatcher
+{
+ /**
+ * {@inheritdoc}
+ */
+ protected function preDispatch($eventName, Event $event)
+ {
+ switch ($eventName) {
+ case KernelEvents::REQUEST:
+ $this->stopwatch->openSection();
+ break;
+ case KernelEvents::VIEW:
+ case KernelEvents::RESPONSE:
+ // stop only if a controller has been executed
+ if ($this->stopwatch->isStarted('controller')) {
+ $this->stopwatch->stop('controller');
+ }
+ break;
+ case KernelEvents::TERMINATE:
+ $token = $event->getResponse()->headers->get('X-Debug-Token');
+ // 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
+ // is equal to the [A] debug token. Trying to reopen section with the [B] token throws an exception
+ // which must be caught.
+ try {
+ $this->stopwatch->openSection($token);
+ } catch (\LogicException $e) {
+ }
+ break;
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ protected function postDispatch($eventName, Event $event)
+ {
+ switch ($eventName) {
+ case KernelEvents::CONTROLLER_ARGUMENTS:
+ $this->stopwatch->start('controller', 'section');
+ break;
+ case KernelEvents::RESPONSE:
+ $token = $event->getResponse()->headers->get('X-Debug-Token');
+ $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');
+ try {
+ $this->stopwatch->stopSection($token);
+ } catch (\LogicException $e) {
+ }
+ break;
+ }
+ }
+}
diff --git a/vendor/symfony/http-kernel/DependencyInjection/AddAnnotatedClassesToCachePass.php b/vendor/symfony/http-kernel/DependencyInjection/AddAnnotatedClassesToCachePass.php
new file mode 100644
index 0000000000..9235ae4e96
--- /dev/null
+++ b/vendor/symfony/http-kernel/DependencyInjection/AddAnnotatedClassesToCachePass.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\DependencyInjection;
+
+use Composer\Autoload\ClassLoader;
+use Symfony\Component\Debug\DebugClassLoader;
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
+use Symfony\Component\HttpKernel\Kernel;
+
+/**
+ * Sets the classes to compile in the cache for the container.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+class AddAnnotatedClassesToCachePass implements CompilerPassInterface
+{
+ private $kernel;
+
+ public function __construct(Kernel $kernel)
+ {
+ $this->kernel = $kernel;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function process(ContainerBuilder $container)
+ {
+ $classes = array();
+ $annotatedClasses = array();
+ 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));
+ }
+
+ /**
+ * Expands the given class patterns using a list of existing classes.
+ *
+ * @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
+ */
+ private function expandClasses(array $patterns, array $classes)
+ {
+ $expanded = array();
+
+ // Explicit classes declared in the patterns are returned directly
+ foreach ($patterns as $key => $pattern) {
+ if (substr($pattern, -1) !== '\\' && false === strpos($pattern, '*')) {
+ unset($patterns[$key]);
+ $expanded[] = ltrim($pattern, '\\');
+ }
+ }
+
+ // Match patterns with the classes list
+ $regexps = $this->patternsToRegexps($patterns);
+
+ foreach ($classes as $class) {
+ $class = ltrim($class, '\\');
+
+ if ($this->matchAnyRegexps($class, $regexps)) {
+ $expanded[] = $class;
+ }
+ }
+
+ return array_unique($expanded);
+ }
+
+ private function getClassesInComposerClassMaps()
+ {
+ $classes = array();
+
+ foreach (spl_autoload_functions() as $function) {
+ if (!is_array($function)) {
+ continue;
+ }
+
+ if ($function[0] instanceof DebugClassLoader) {
+ $function = $function[0]->getClassLoader();
+ }
+
+ if (is_array($function) && $function[0] instanceof ClassLoader) {
+ $classes += array_filter($function[0]->getClassMap());
+ }
+ }
+
+ return array_keys($classes);
+ }
+
+ private function patternsToRegexps($patterns)
+ {
+ $regexps = array();
+
+ foreach ($patterns as $pattern) {
+ // Escape user input
+ $regex = preg_quote(ltrim($pattern, '\\'));
+
+ // Wildcards * and **
+ $regex = strtr($regex, array('\\*\\*' => '.*?', '\\*' => '[^\\\\]*?'));
+
+ // If this class does not end by a slash, anchor the end
+ if (substr($regex, -1) !== '\\') {
+ $regex .= '$';
+ }
+
+ $regexps[] = '{^\\\\'.$regex.'}';
+ }
+
+ return $regexps;
+ }
+
+ private function matchAnyRegexps($class, $regexps)
+ {
+ $blacklisted = false !== strpos($class, 'Test');
+
+ foreach ($regexps as $regex) {
+ if ($blacklisted && false === strpos($regex, 'Test')) {
+ continue;
+ }
+
+ if (preg_match($regex, '\\'.$class)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+}
diff --git a/vendor/symfony/http-kernel/DependencyInjection/AddClassesToCachePass.php b/vendor/symfony/http-kernel/DependencyInjection/AddClassesToCachePass.php
new file mode 100644
index 0000000000..4ffa17511d
--- /dev/null
+++ b/vendor/symfony/http-kernel/DependencyInjection/AddClassesToCachePass.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\DependencyInjection;
+
+@trigger_error('The '.__NAMESPACE__.'\AddClassesToCachePass class is deprecated since version 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/ConfigurableExtension.php b/vendor/symfony/http-kernel/DependencyInjection/ConfigurableExtension.php
new file mode 100644
index 0000000000..c7eca3063c
--- /dev/null
+++ b/vendor/symfony/http-kernel/DependencyInjection/ConfigurableExtension.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\HttpKernel\DependencyInjection;
+
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+
+/**
+ * This extension sub-class provides first-class integration with the
+ * Config/Definition Component.
+ *
+ * You can use this as base class if
+ *
+ * a) you use the Config/Definition component for configuration,
+ * b) your configuration class is named "Configuration", and
+ * c) the configuration class resides in the DependencyInjection sub-folder.
+ *
+ * @author Johannes M. Schmitt <schmittjoh@gmail.com>
+ */
+abstract class ConfigurableExtension extends Extension
+{
+ /**
+ * {@inheritdoc}
+ */
+ final public function load(array $configs, ContainerBuilder $container)
+ {
+ $this->loadInternal($this->processConfiguration($this->getConfiguration($configs, $container), $configs), $container);
+ }
+
+ /**
+ * Configures the passed container according to the merged configuration.
+ *
+ * @param array $mergedConfig
+ * @param ContainerBuilder $container
+ */
+ abstract protected function loadInternal(array $mergedConfig, ContainerBuilder $container);
+}
diff --git a/vendor/symfony/http-kernel/DependencyInjection/ControllerArgumentValueResolverPass.php b/vendor/symfony/http-kernel/DependencyInjection/ControllerArgumentValueResolverPass.php
new file mode 100644
index 0000000000..343e217b96
--- /dev/null
+++ b/vendor/symfony/http-kernel/DependencyInjection/ControllerArgumentValueResolverPass.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\HttpKernel\DependencyInjection;
+
+use Symfony\Component\DependencyInjection\Argument\IteratorArgument;
+use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
+use Symfony\Component\DependencyInjection\Compiler\PriorityTaggedServiceTrait;
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+
+/**
+ * Gathers and configures the argument value resolvers.
+ *
+ * @author Iltar van der Berg <kjarli@gmail.com>
+ */
+class ControllerArgumentValueResolverPass implements CompilerPassInterface
+{
+ use PriorityTaggedServiceTrait;
+
+ private $argumentResolverService;
+ private $argumentValueResolverTag;
+
+ public function __construct($argumentResolverService = 'argument_resolver', $argumentValueResolverTag = 'controller.argument_value_resolver')
+ {
+ $this->argumentResolverService = $argumentResolverService;
+ $this->argumentValueResolverTag = $argumentValueResolverTag;
+ }
+
+ public function process(ContainerBuilder $container)
+ {
+ if (!$container->hasDefinition($this->argumentResolverService)) {
+ return;
+ }
+
+ $container
+ ->getDefinition($this->argumentResolverService)
+ ->replaceArgument(1, new IteratorArgument($this->findAndSortTaggedServices($this->argumentValueResolverTag, $container)))
+ ;
+ }
+}
diff --git a/vendor/symfony/http-kernel/DependencyInjection/Extension.php b/vendor/symfony/http-kernel/DependencyInjection/Extension.php
new file mode 100644
index 0000000000..f6449f4e52
--- /dev/null
+++ b/vendor/symfony/http-kernel/DependencyInjection/Extension.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\HttpKernel\DependencyInjection;
+
+use Symfony\Component\DependencyInjection\Extension\Extension as BaseExtension;
+
+/**
+ * Allow adding classes to the class cache.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+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 version 3.3, to be removed in 4.0.', E_USER_DEPRECATED);
+ }
+
+ return $this->classes;
+ }
+
+ /**
+ * Gets the annotated classes to cache.
+ *
+ * @return array An array of classes
+ */
+ public function getAnnotatedClassesToCompile()
+ {
+ 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 version 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.
+ *
+ * @param array $annotatedClasses An array of class patterns
+ */
+ public function addAnnotatedClassesToCompile(array $annotatedClasses)
+ {
+ $this->annotatedClasses = array_merge($this->annotatedClasses, $annotatedClasses);
+ }
+}
diff --git a/vendor/symfony/http-kernel/DependencyInjection/FragmentRendererPass.php b/vendor/symfony/http-kernel/DependencyInjection/FragmentRendererPass.php
new file mode 100644
index 0000000000..ac52c8732b
--- /dev/null
+++ b/vendor/symfony/http-kernel/DependencyInjection/FragmentRendererPass.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\HttpKernel\DependencyInjection;
+
+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;
+
+/**
+ * Adds services tagged kernel.fragment_renderer as HTTP content rendering strategies.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+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')
+ {
+ $this->handlerService = $handlerService;
+ $this->rendererTag = $rendererTag;
+ }
+
+ public function process(ContainerBuilder $container)
+ {
+ if (!$container->hasDefinition($this->handlerService)) {
+ return;
+ }
+
+ $definition = $container->getDefinition($this->handlerService);
+ $renderers = array();
+ foreach ($container->findTaggedServiceIds($this->rendererTag, true) as $id => $tags) {
+ $def = $container->getDefinition($id);
+ $class = $container->getParameterBag()->resolveValue($def->getClass());
+
+ if (!$r = $container->getReflectionClass($class)) {
+ throw new InvalidArgumentException(sprintf('Class "%s" used for service "%s" cannot be found.', $class, $id));
+ }
+ if (!$r->isSubclassOf(FragmentRendererInterface::class)) {
+ throw new InvalidArgumentException(sprintf('Service "%s" must implement interface "%s".', $id, FragmentRendererInterface::class));
+ }
+
+ foreach ($tags as $tag) {
+ $renderers[$tag['alias']] = new Reference($id);
+ }
+ }
+
+ $definition->replaceArgument(0, ServiceLocatorTagPass::register($container, $renderers));
+ }
+}
diff --git a/vendor/symfony/http-kernel/DependencyInjection/LazyLoadingFragmentHandler.php b/vendor/symfony/http-kernel/DependencyInjection/LazyLoadingFragmentHandler.php
new file mode 100644
index 0000000000..d6f4dab141
--- /dev/null
+++ b/vendor/symfony/http-kernel/DependencyInjection/LazyLoadingFragmentHandler.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\DependencyInjection;
+
+use Psr\Container\ContainerInterface;
+use Symfony\Component\HttpFoundation\RequestStack;
+use Symfony\Component\HttpKernel\Fragment\FragmentHandler;
+
+/**
+ * Lazily loads fragment renderers from the dependency injection container.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+class LazyLoadingFragmentHandler extends FragmentHandler
+{
+ private $container;
+ /**
+ * @deprecated since version 3.3, to be removed in 4.0
+ */
+ private $rendererIds = array();
+ private $initialized = array();
+
+ /**
+ * Constructor.
+ *
+ * @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)
+ {
+ $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 version 3.3 and will be removed in 4.0.', __METHOD__), E_USER_DEPRECATED);
+
+ $this->rendererIds[$name] = $renderer;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function render($uri, $renderer = 'inline', array $options = array())
+ {
+ // 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;
+ }
+
+ return parent::render($uri, $renderer, $options);
+ }
+}
diff --git a/vendor/symfony/http-kernel/DependencyInjection/MergeExtensionConfigurationPass.php b/vendor/symfony/http-kernel/DependencyInjection/MergeExtensionConfigurationPass.php
new file mode 100644
index 0000000000..dcd73828de
--- /dev/null
+++ b/vendor/symfony/http-kernel/DependencyInjection/MergeExtensionConfigurationPass.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\HttpKernel\DependencyInjection;
+
+use Symfony\Component\DependencyInjection\Compiler\MergeExtensionConfigurationPass as BaseMergeExtensionConfigurationPass;
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+
+/**
+ * Ensures certain extensions are always loaded.
+ *
+ * @author Kris Wallsmith <kris@symfony.com>
+ */
+class MergeExtensionConfigurationPass extends BaseMergeExtensionConfigurationPass
+{
+ private $extensions;
+
+ public function __construct(array $extensions)
+ {
+ $this->extensions = $extensions;
+ }
+
+ public function process(ContainerBuilder $container)
+ {
+ foreach ($this->extensions as $extension) {
+ if (!count($container->getExtensionConfig($extension))) {
+ $container->loadFromExtension($extension, array());
+ }
+ }
+
+ parent::process($container);
+ }
+}
diff --git a/vendor/symfony/http-kernel/DependencyInjection/RegisterControllerArgumentLocatorsPass.php b/vendor/symfony/http-kernel/DependencyInjection/RegisterControllerArgumentLocatorsPass.php
new file mode 100644
index 0000000000..222185f527
--- /dev/null
+++ b/vendor/symfony/http-kernel/DependencyInjection/RegisterControllerArgumentLocatorsPass.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\HttpKernel\DependencyInjection;
+
+use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
+use Symfony\Component\DependencyInjection\ChildDefinition;
+use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
+use Symfony\Component\DependencyInjection\Compiler\ServiceLocatorTagPass;
+use Symfony\Component\DependencyInjection\ContainerAwareInterface;
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
+use Symfony\Component\DependencyInjection\LazyProxy\ProxyHelper;
+use Symfony\Component\DependencyInjection\Reference;
+use Symfony\Component\DependencyInjection\TypedReference;
+
+/**
+ * Creates the service-locators required by ServiceValueResolver.
+ *
+ * @author Nicolas Grekas <p@tchwork.com>
+ */
+class RegisterControllerArgumentLocatorsPass implements CompilerPassInterface
+{
+ private $resolverServiceId;
+ private $controllerTag;
+
+ public function __construct($resolverServiceId = 'argument_resolver.service', $controllerTag = 'controller.service_arguments')
+ {
+ $this->resolverServiceId = $resolverServiceId;
+ $this->controllerTag = $controllerTag;
+ }
+
+ public function process(ContainerBuilder $container)
+ {
+ if (false === $container->hasDefinition($this->resolverServiceId)) {
+ return;
+ }
+
+ $parameterBag = $container->getParameterBag();
+ $controllers = array();
+
+ foreach ($container->findTaggedServiceIds($this->controllerTag, true) as $id => $tags) {
+ $def = $container->getDefinition($id);
+ $class = $def->getClass();
+ $autowire = $def->isAutowired();
+
+ // resolve service class, taking parent definitions into account
+ while (!$class && $def instanceof ChildDefinition) {
+ $def = $container->findDefinition($def->getParent());
+ $class = $def->getClass();
+ }
+ $class = $parameterBag->resolveValue($class);
+
+ if (!$r = $container->getReflectionClass($class)) {
+ throw new InvalidArgumentException(sprintf('Class "%s" used for service "%s" cannot be found.', $class, $id));
+ }
+ $isContainerAware = $r->implementsInterface(ContainerAwareInterface::class) || is_subclass_of($class, AbstractController::class);
+
+ // get regular public methods
+ $methods = array();
+ $arguments = array();
+ 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());
+ }
+ }
+
+ // validate and collect explicit per-actions and per-arguments service references
+ foreach ($tags as $attributes) {
+ if (!isset($attributes['action']) && !isset($attributes['argument']) && !isset($attributes['id'])) {
+ $autowire = true;
+ continue;
+ }
+ foreach (array('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));
+ }
+ }
+ if (!isset($methods[$action = strtolower($attributes['action'])])) {
+ throw new InvalidArgumentException(sprintf('Invalid "action" attribute on tag "%s" for service "%s": no public "%s()" method found on class "%s".', $this->controllerTag, $id, $attributes['action'], $class));
+ }
+ list($r, $parameters) = $methods[$action];
+ $found = false;
+
+ foreach ($parameters as $p) {
+ if ($attributes['argument'] === $p->name) {
+ if (!isset($arguments[$r->name][$p->name])) {
+ $arguments[$r->name][$p->name] = $attributes['id'];
+ }
+ $found = true;
+ break;
+ }
+ }
+
+ if (!$found) {
+ throw new InvalidArgumentException(sprintf('Invalid "%s" tag for service "%s": method "%s()" has no "%s" argument on class "%s".', $this->controllerTag, $id, $r->name, $attributes['argument'], $class));
+ }
+ }
+
+ foreach ($methods as list($r, $parameters)) {
+ /** @var \ReflectionMethod $r */
+
+ // create a per-method map of argument-names to service/type-references
+ $args = array();
+ foreach ($parameters as $p) {
+ /** @var \ReflectionParameter $p */
+ $type = $target = ProxyHelper::getTypeHint($r, $p, true);
+ $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;
+ } 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 (!$type || !$autowire) {
+ continue;
+ }
+
+ if ($type && !$p->isOptional() && !$p->allowsNull() && !class_exists($type) && !interface_exists($type, false)) {
+ $message = sprintf('Cannot determine controller argument for "%s::%s()": the $%s argument is type-hinted with the non-existent class or interface: "%s".', $class, $r->name, $p->name, $type);
+
+ // see if the type-hint lives in the same namespace as the controller
+ if (0 === strncmp($type, $class, strrpos($class, '\\'))) {
+ $message .= ' Did you forget to add a use statement?';
+ }
+
+ throw new InvalidArgumentException($message);
+ }
+
+ $args[$p->name] = $type ? new TypedReference($target, $type, $r->class, $invalidBehavior) : new Reference($target, $invalidBehavior);
+ }
+ // register the maps as a per-method service-locators
+ if ($args) {
+ $controllers[$id.':'.$r->name] = ServiceLocatorTagPass::register($container, $args);
+ }
+ }
+ }
+
+ $container->getDefinition($this->resolverServiceId)
+ ->replaceArgument(0, ServiceLocatorTagPass::register($container, $controllers));
+ }
+}
diff --git a/vendor/symfony/http-kernel/DependencyInjection/RemoveEmptyControllerArgumentLocatorsPass.php b/vendor/symfony/http-kernel/DependencyInjection/RemoveEmptyControllerArgumentLocatorsPass.php
new file mode 100644
index 0000000000..440b0d0025
--- /dev/null
+++ b/vendor/symfony/http-kernel/DependencyInjection/RemoveEmptyControllerArgumentLocatorsPass.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\DependencyInjection;
+
+use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+
+/**
+ * Removes empty service-locators registered for ServiceValueResolver.
+ *
+ * @author Nicolas Grekas <p@tchwork.com>
+ */
+class RemoveEmptyControllerArgumentLocatorsPass implements CompilerPassInterface
+{
+ private $resolverServiceId;
+
+ public function __construct($resolverServiceId = 'argument_resolver.service')
+ {
+ $this->resolverServiceId = $resolverServiceId;
+ }
+
+ public function process(ContainerBuilder $container)
+ {
+ if (false === $container->hasDefinition($this->resolverServiceId)) {
+ return;
+ }
+
+ $serviceResolver = $container->getDefinition($this->resolverServiceId);
+ $controllerLocator = $container->getDefinition((string) $serviceResolver->getArgument(0));
+ $controllers = $controllerLocator->getArgument(0);
+
+ foreach ($controllers as $controller => $argumentRef) {
+ $argumentLocator = $container->getDefinition((string) $argumentRef->getValues()[0]);
+
+ if (!$argumentLocator->getArgument(0)) {
+ // remove empty argument locators
+ $reason = sprintf('Removing service-argument resolver for controller "%s": no corresponding services exist for the referenced types.', $controller);
+ } 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));
+ $controllerDef = $container->getDefinition($id);
+ foreach ($controllerDef->getMethodCalls() as list($method, $args)) {
+ if (0 === strcasecmp($action, $method)) {
+ $reason = sprintf('Removing method "%s" of service "%s" from controller candidates: the method is called at instantiation, thus cannot be an action.', $action, $id);
+ break;
+ }
+ }
+ if (!$reason) {
+ if ($controllerDef->getClass() === $id) {
+ $controllers[$id.'::'.$action] = $argumentRef;
+ }
+ if ('__invoke' === $action) {
+ $controllers[$id] = $argumentRef;
+ }
+ continue;
+ }
+ }
+
+ unset($controllers[$controller]);
+ $container->log($this, $reason);
+ }
+
+ $controllerLocator->replaceArgument(0, $controllers);
+ }
+}
diff --git a/vendor/symfony/http-kernel/Event/FilterControllerArgumentsEvent.php b/vendor/symfony/http-kernel/Event/FilterControllerArgumentsEvent.php
new file mode 100644
index 0000000000..1dc784ed52
--- /dev/null
+++ b/vendor/symfony/http-kernel/Event/FilterControllerArgumentsEvent.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\HttpKernel\Event;
+
+use Symfony\Component\HttpKernel\HttpKernelInterface;
+use Symfony\Component\HttpFoundation\Request;
+
+/**
+ * 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 FilterControllerArgumentsEvent extends FilterControllerEvent
+{
+ private $arguments;
+
+ public function __construct(HttpKernelInterface $kernel, callable $controller, array $arguments, Request $request, $requestType)
+ {
+ parent::__construct($kernel, $controller, $request, $requestType);
+
+ $this->arguments = $arguments;
+ }
+
+ /**
+ * @return array
+ */
+ public function getArguments()
+ {
+ return $this->arguments;
+ }
+
+ /**
+ * @param array $arguments
+ */
+ public function setArguments(array $arguments)
+ {
+ $this->arguments = $arguments;
+ }
+}
diff --git a/vendor/symfony/http-kernel/Event/FilterControllerEvent.php b/vendor/symfony/http-kernel/Event/FilterControllerEvent.php
new file mode 100644
index 0000000000..e0d46aa4ce
--- /dev/null
+++ b/vendor/symfony/http-kernel/Event/FilterControllerEvent.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\HttpKernel\Event;
+
+use Symfony\Component\HttpKernel\HttpKernelInterface;
+use Symfony\Component\HttpFoundation\Request;
+
+/**
+ * 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 FilterControllerEvent extends KernelEvent
+{
+ /**
+ * The current controller.
+ */
+ private $controller;
+
+ public function __construct(HttpKernelInterface $kernel, callable $controller, Request $request, $requestType)
+ {
+ parent::__construct($kernel, $request, $requestType);
+
+ $this->setController($controller);
+ }
+
+ /**
+ * Returns the current controller.
+ *
+ * @return callable
+ */
+ public function getController()
+ {
+ return $this->controller;
+ }
+
+ /**
+ * Sets a new controller.
+ *
+ * @param callable $controller
+ */
+ public function setController(callable $controller)
+ {
+ $this->controller = $controller;
+ }
+}
diff --git a/vendor/symfony/http-kernel/Event/FilterResponseEvent.php b/vendor/symfony/http-kernel/Event/FilterResponseEvent.php
new file mode 100644
index 0000000000..ed816a9d32
--- /dev/null
+++ b/vendor/symfony/http-kernel/Event/FilterResponseEvent.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\Event;
+
+use Symfony\Component\HttpKernel\HttpKernelInterface;
+use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\HttpFoundation\Response;
+
+/**
+ * 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 FilterResponseEvent extends KernelEvent
+{
+ /**
+ * The current response object.
+ *
+ * @var Response
+ */
+ private $response;
+
+ public function __construct(HttpKernelInterface $kernel, Request $request, $requestType, Response $response)
+ {
+ parent::__construct($kernel, $request, $requestType);
+
+ $this->setResponse($response);
+ }
+
+ /**
+ * Returns the current response object.
+ *
+ * @return Response
+ */
+ public function getResponse()
+ {
+ return $this->response;
+ }
+
+ /**
+ * Sets a new response object.
+ *
+ * @param Response $response
+ */
+ public function setResponse(Response $response)
+ {
+ $this->response = $response;
+ }
+}
diff --git a/vendor/symfony/http-kernel/Event/FinishRequestEvent.php b/vendor/symfony/http-kernel/Event/FinishRequestEvent.php
new file mode 100644
index 0000000000..ee724843cd
--- /dev/null
+++ b/vendor/symfony/http-kernel/Event/FinishRequestEvent.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\HttpKernel\Event;
+
+/**
+ * Triggered whenever a request is fully processed.
+ *
+ * @author Benjamin Eberlei <kontakt@beberlei.de>
+ */
+class FinishRequestEvent extends KernelEvent
+{
+}
diff --git a/vendor/symfony/http-kernel/Event/GetResponseEvent.php b/vendor/symfony/http-kernel/Event/GetResponseEvent.php
new file mode 100644
index 0000000000..4c96a4b7d9
--- /dev/null
+++ b/vendor/symfony/http-kernel/Event/GetResponseEvent.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\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>
+ */
+class GetResponseEvent extends KernelEvent
+{
+ /**
+ * The response object.
+ *
+ * @var Response
+ */
+ private $response;
+
+ /**
+ * Returns the response object.
+ *
+ * @return Response
+ */
+ public function getResponse()
+ {
+ return $this->response;
+ }
+
+ /**
+ * Sets a response and stops event propagation.
+ *
+ * @param Response $response
+ */
+ public function setResponse(Response $response)
+ {
+ $this->response = $response;
+
+ $this->stopPropagation();
+ }
+
+ /**
+ * Returns whether a response was set.
+ *
+ * @return bool Whether a response was set
+ */
+ public function hasResponse()
+ {
+ return null !== $this->response;
+ }
+}
diff --git a/vendor/symfony/http-kernel/Event/GetResponseForControllerResultEvent.php b/vendor/symfony/http-kernel/Event/GetResponseForControllerResultEvent.php
new file mode 100644
index 0000000000..f70ce09e0a
--- /dev/null
+++ b/vendor/symfony/http-kernel/Event/GetResponseForControllerResultEvent.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\HttpKernel\Event;
+
+use Symfony\Component\HttpKernel\HttpKernelInterface;
+use Symfony\Component\HttpFoundation\Request;
+
+/**
+ * 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 GetResponseForControllerResultEvent extends GetResponseEvent
+{
+ /**
+ * The return value of the controller.
+ *
+ * @var mixed
+ */
+ private $controllerResult;
+
+ public function __construct(HttpKernelInterface $kernel, Request $request, $requestType, $controllerResult)
+ {
+ parent::__construct($kernel, $request, $requestType);
+
+ $this->controllerResult = $controllerResult;
+ }
+
+ /**
+ * Returns the return value of the controller.
+ *
+ * @return mixed The controller return value
+ */
+ public function getControllerResult()
+ {
+ return $this->controllerResult;
+ }
+
+ /**
+ * Assigns the return value of the controller.
+ *
+ * @param mixed $controllerResult The controller return value
+ */
+ public function setControllerResult($controllerResult)
+ {
+ $this->controllerResult = $controllerResult;
+ }
+}
diff --git a/vendor/symfony/http-kernel/Event/GetResponseForExceptionEvent.php b/vendor/symfony/http-kernel/Event/GetResponseForExceptionEvent.php
new file mode 100644
index 0000000000..751b74515b
--- /dev/null
+++ b/vendor/symfony/http-kernel/Event/GetResponseForExceptionEvent.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\HttpKernel\Event;
+
+use Symfony\Component\HttpKernel\HttpKernelInterface;
+use Symfony\Component\HttpFoundation\Request;
+
+/**
+ * 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 GetResponseForExceptionEvent extends GetResponseEvent
+{
+ /**
+ * The exception object.
+ *
+ * @var \Exception
+ */
+ private $exception;
+
+ /**
+ * @var bool
+ */
+ private $allowCustomResponseCode = false;
+
+ public function __construct(HttpKernelInterface $kernel, Request $request, $requestType, \Exception $e)
+ {
+ parent::__construct($kernel, $request, $requestType);
+
+ $this->setException($e);
+ }
+
+ /**
+ * Returns the thrown exception.
+ *
+ * @return \Exception The thrown exception
+ */
+ public function getException()
+ {
+ return $this->exception;
+ }
+
+ /**
+ * Replaces the thrown exception.
+ *
+ * This exception will be thrown if no response is set in the event.
+ *
+ * @param \Exception $exception The thrown exception
+ */
+ public function setException(\Exception $exception)
+ {
+ $this->exception = $exception;
+ }
+
+ /**
+ * Mark the event as allowing a custom response code.
+ */
+ public function allowCustomResponseCode()
+ {
+ $this->allowCustomResponseCode = true;
+ }
+
+ /**
+ * Returns true if the event allows a custom response code.
+ *
+ * @return bool
+ */
+ public function isAllowingCustomResponseCode()
+ {
+ return $this->allowCustomResponseCode;
+ }
+}
diff --git a/vendor/symfony/http-kernel/Event/KernelEvent.php b/vendor/symfony/http-kernel/Event/KernelEvent.php
new file mode 100644
index 0000000000..2043a01758
--- /dev/null
+++ b/vendor/symfony/http-kernel/Event/KernelEvent.php
@@ -0,0 +1,94 @@
+<?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;
+
+use Symfony\Component\HttpKernel\HttpKernelInterface;
+use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\EventDispatcher\Event;
+
+/**
+ * Base class for events thrown in the HttpKernel component.
+ *
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+class KernelEvent extends Event
+{
+ /**
+ * The kernel in which this event was thrown.
+ *
+ * @var HttpKernelInterface
+ */
+ private $kernel;
+
+ /**
+ * The request the kernel is currently processing.
+ *
+ * @var Request
+ */
+ private $request;
+
+ /**
+ * The request type the kernel is currently processing. One of
+ * HttpKernelInterface::MASTER_REQUEST and HttpKernelInterface::SUB_REQUEST.
+ *
+ * @var int
+ */
+ private $requestType;
+
+ public function __construct(HttpKernelInterface $kernel, Request $request, $requestType)
+ {
+ $this->kernel = $kernel;
+ $this->request = $request;
+ $this->requestType = $requestType;
+ }
+
+ /**
+ * Returns the kernel in which this event was thrown.
+ *
+ * @return HttpKernelInterface
+ */
+ public function getKernel()
+ {
+ return $this->kernel;
+ }
+
+ /**
+ * Returns the request the kernel is currently processing.
+ *
+ * @return Request
+ */
+ public function getRequest()
+ {
+ return $this->request;
+ }
+
+ /**
+ * Returns the request type the kernel is currently processing.
+ *
+ * @return int One of HttpKernelInterface::MASTER_REQUEST and
+ * HttpKernelInterface::SUB_REQUEST
+ */
+ public function getRequestType()
+ {
+ return $this->requestType;
+ }
+
+ /**
+ * Checks if this is a master request.
+ *
+ * @return bool True if the request is a master request
+ */
+ public function isMasterRequest()
+ {
+ return HttpKernelInterface::MASTER_REQUEST === $this->requestType;
+ }
+}
diff --git a/vendor/symfony/http-kernel/Event/PostResponseEvent.php b/vendor/symfony/http-kernel/Event/PostResponseEvent.php
new file mode 100644
index 0000000000..2406fddbe8
--- /dev/null
+++ b/vendor/symfony/http-kernel/Event/PostResponseEvent.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\HttpKernel\Event;
+
+use Symfony\Component\HttpKernel\HttpKernelInterface;
+use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\HttpFoundation\Response;
+
+/**
+ * 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 PostResponseEvent extends KernelEvent
+{
+ private $response;
+
+ public function __construct(HttpKernelInterface $kernel, Request $request, Response $response)
+ {
+ parent::__construct($kernel, $request, HttpKernelInterface::MASTER_REQUEST);
+
+ $this->response = $response;
+ }
+
+ /**
+ * Returns the response for which this event was thrown.
+ *
+ * @return Response
+ */
+ public function getResponse()
+ {
+ return $this->response;
+ }
+}
diff --git a/vendor/symfony/http-kernel/EventListener/AbstractSessionListener.php b/vendor/symfony/http-kernel/EventListener/AbstractSessionListener.php
new file mode 100644
index 0000000000..7a6c20734b
--- /dev/null
+++ b/vendor/symfony/http-kernel/EventListener/AbstractSessionListener.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\HttpKernel\EventListener;
+
+use Symfony\Component\HttpFoundation\Session\SessionInterface;
+use Symfony\Component\HttpKernel\Event\GetResponseEvent;
+use Symfony\Component\HttpKernel\KernelEvents;
+use Symfony\Component\EventDispatcher\EventSubscriberInterface;
+
+/**
+ * Sets the session in the request.
+ *
+ * @author Johannes M. Schmitt <schmittjoh@gmail.com>
+ */
+abstract class AbstractSessionListener implements EventSubscriberInterface
+{
+ public function onKernelRequest(GetResponseEvent $event)
+ {
+ if (!$event->isMasterRequest()) {
+ return;
+ }
+
+ $request = $event->getRequest();
+ $session = $this->getSession();
+ if (null === $session || $request->hasSession()) {
+ return;
+ }
+
+ $request->setSession($session);
+ }
+
+ public static function getSubscribedEvents()
+ {
+ return array(
+ KernelEvents::REQUEST => array('onKernelRequest', 128),
+ );
+ }
+
+ /**
+ * Gets the session object.
+ *
+ * @return SessionInterface|null A SessionInterface instance or null if no session is available
+ */
+ abstract protected function getSession();
+}
diff --git a/vendor/symfony/http-kernel/EventListener/AbstractTestSessionListener.php b/vendor/symfony/http-kernel/EventListener/AbstractTestSessionListener.php
new file mode 100644
index 0000000000..eb6e66c0eb
--- /dev/null
+++ b/vendor/symfony/http-kernel/EventListener/AbstractTestSessionListener.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\EventListener;
+
+use Symfony\Component\HttpFoundation\Cookie;
+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;
+
+/**
+ * TestSessionListener.
+ *
+ * Saves session in test environment.
+ *
+ * @author Bulat Shakirzyanov <mallluhuct@gmail.com>
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+abstract class AbstractTestSessionListener implements EventSubscriberInterface
+{
+ public function onKernelRequest(GetResponseEvent $event)
+ {
+ if (!$event->isMasterRequest()) {
+ return;
+ }
+
+ // bootstrap the session
+ $session = $this->getSession();
+ if (!$session) {
+ return;
+ }
+
+ $cookies = $event->getRequest()->cookies;
+
+ if ($cookies->has($session->getName())) {
+ $session->setId($cookies->get($session->getName()));
+ }
+ }
+
+ /**
+ * Checks if session was initialized and saves if current request is master
+ * Runs on 'kernel.response' in test environment.
+ *
+ * @param FilterResponseEvent $event
+ */
+ public function onKernelResponse(FilterResponseEvent $event)
+ {
+ if (!$event->isMasterRequest()) {
+ return;
+ }
+
+ $session = $event->getRequest()->getSession();
+ if ($session && $session->isStarted()) {
+ $session->save();
+ $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']));
+ }
+ }
+
+ public static function getSubscribedEvents()
+ {
+ return array(
+ KernelEvents::REQUEST => array('onKernelRequest', 192),
+ KernelEvents::RESPONSE => array('onKernelResponse', -128),
+ );
+ }
+
+ /**
+ * Gets the session object.
+ *
+ * @return SessionInterface|null A SessionInterface instance or null if no session is available
+ */
+ abstract protected function getSession();
+}
diff --git a/vendor/symfony/http-kernel/EventListener/AddRequestFormatsListener.php b/vendor/symfony/http-kernel/EventListener/AddRequestFormatsListener.php
new file mode 100644
index 0000000000..280844c183
--- /dev/null
+++ b/vendor/symfony/http-kernel/EventListener/AddRequestFormatsListener.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\HttpKernel\EventListener;
+
+use Symfony\Component\EventDispatcher\EventSubscriberInterface;
+use Symfony\Component\HttpKernel\KernelEvents;
+use Symfony\Component\HttpKernel\Event\GetResponseEvent;
+
+/**
+ * Adds configured formats to each request.
+ *
+ * @author Gildas Quemener <gildas.quemener@gmail.com>
+ */
+class AddRequestFormatsListener implements EventSubscriberInterface
+{
+ /**
+ * @var array
+ */
+ protected $formats;
+
+ /**
+ * @param array $formats
+ */
+ public function __construct(array $formats)
+ {
+ $this->formats = $formats;
+ }
+
+ /**
+ * Adds request formats.
+ *
+ * @param GetResponseEvent $event
+ */
+ public function onKernelRequest(GetResponseEvent $event)
+ {
+ foreach ($this->formats as $format => $mimeTypes) {
+ $event->getRequest()->setFormat($format, $mimeTypes);
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public static function getSubscribedEvents()
+ {
+ return array(KernelEvents::REQUEST => array('onKernelRequest', 1));
+ }
+}
diff --git a/vendor/symfony/http-kernel/EventListener/DebugHandlersListener.php b/vendor/symfony/http-kernel/EventListener/DebugHandlersListener.php
new file mode 100644
index 0000000000..29e1725adc
--- /dev/null
+++ b/vendor/symfony/http-kernel/EventListener/DebugHandlersListener.php
@@ -0,0 +1,146 @@
+<?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 Psr\Log\LoggerInterface;
+use Symfony\Component\Debug\ErrorHandler;
+use Symfony\Component\Debug\ExceptionHandler;
+use Symfony\Component\EventDispatcher\Event;
+use Symfony\Component\EventDispatcher\EventSubscriberInterface;
+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.
+ *
+ * @author Nicolas Grekas <p@tchwork.com>
+ */
+class DebugHandlersListener implements EventSubscriberInterface
+{
+ private $exceptionHandler;
+ private $logger;
+ private $levels;
+ private $throwAt;
+ private $scream;
+ private $fileLinkFormat;
+ private $scope;
+ private $firstCall = true;
+
+ /**
+ * @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
+ */
+ public function __construct(callable $exceptionHandler = null, LoggerInterface $logger = null, $levels = E_ALL, $throwAt = E_ALL, $scream = true, $fileLinkFormat = null, $scope = true)
+ {
+ $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->fileLinkFormat = $fileLinkFormat;
+ $this->scope = (bool) $scope;
+ }
+
+ /**
+ * Configures the error handler.
+ *
+ * @param Event|null $event The triggering event
+ */
+ public function configure(Event $event = null)
+ {
+ if (!$this->firstCall) {
+ return;
+ }
+ $this->firstCall = false;
+ if ($this->logger || null !== $this->throwAt) {
+ $handler = set_error_handler('var_dump');
+ $handler = is_array($handler) ? $handler[0] : null;
+ restore_error_handler();
+ if ($handler instanceof ErrorHandler) {
+ if ($this->logger) {
+ $handler->setDefaultLogger($this->logger, $this->levels);
+ if (is_array($this->levels)) {
+ $levels = 0;
+ foreach ($this->levels as $type => $log) {
+ $levels |= $type;
+ }
+ } else {
+ $levels = $this->levels;
+ }
+ if ($this->scream) {
+ $handler->screamAt($levels);
+ }
+ if ($this->scope) {
+ $handler->scopeAt($this->levels);
+ } else {
+ $handler->scopeAt(0, true);
+ }
+ $this->logger = $this->levels = null;
+ }
+ if (null !== $this->throwAt) {
+ $handler->throwAt($this->throwAt, true);
+ }
+ }
+ }
+ if (!$this->exceptionHandler) {
+ if ($event instanceof KernelEvent) {
+ if (method_exists($event->getKernel(), 'terminateWithException')) {
+ $this->exceptionHandler = array($event->getKernel(), 'terminateWithException');
+ }
+ } elseif ($event instanceof ConsoleEvent && $app = $event->getCommand()->getApplication()) {
+ $output = $event->getOutput();
+ if ($output instanceof ConsoleOutputInterface) {
+ $output = $output->getErrorOutput();
+ }
+ $this->exceptionHandler = function ($e) use ($app, $output) {
+ $app->renderException($e, $output);
+ };
+ }
+ }
+ if ($this->exceptionHandler) {
+ $handler = set_exception_handler('var_dump');
+ $handler = is_array($handler) ? $handler[0] : null;
+ restore_exception_handler();
+ if ($handler instanceof ErrorHandler) {
+ $h = $handler->setExceptionHandler('var_dump') ?: $this->exceptionHandler;
+ $handler->setExceptionHandler($h);
+ $handler = is_array($h) ? $h[0] : null;
+ }
+ if ($handler instanceof ExceptionHandler) {
+ $handler->setHandler($this->exceptionHandler);
+ if (null !== $this->fileLinkFormat) {
+ $handler->setFileLinkFormat($this->fileLinkFormat);
+ }
+ }
+ $this->exceptionHandler = null;
+ }
+ }
+
+ public static function getSubscribedEvents()
+ {
+ $events = array(KernelEvents::REQUEST => array('configure', 2048));
+
+ if ('cli' === PHP_SAPI && defined('Symfony\Component\Console\ConsoleEvents::COMMAND')) {
+ $events[ConsoleEvents::COMMAND] = array('configure', 2048);
+ }
+
+ return $events;
+ }
+}
diff --git a/vendor/symfony/http-kernel/EventListener/DumpListener.php b/vendor/symfony/http-kernel/EventListener/DumpListener.php
new file mode 100644
index 0000000000..88acef3187
--- /dev/null
+++ b/vendor/symfony/http-kernel/EventListener/DumpListener.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\HttpKernel\EventListener;
+
+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\VarDumper;
+
+/**
+ * Configures dump() handler.
+ *
+ * @author Nicolas Grekas <p@tchwork.com>
+ */
+class DumpListener implements EventSubscriberInterface
+{
+ private $cloner;
+ private $dumper;
+
+ /**
+ * @param ClonerInterface $cloner Cloner service
+ * @param DataDumperInterface $dumper Dumper service
+ */
+ public function __construct(ClonerInterface $cloner, DataDumperInterface $dumper)
+ {
+ $this->cloner = $cloner;
+ $this->dumper = $dumper;
+ }
+
+ public function configure()
+ {
+ $cloner = $this->cloner;
+ $dumper = $this->dumper;
+
+ VarDumper::setHandler(function ($var) use ($cloner, $dumper) {
+ $dumper->dump($cloner->cloneVar($var));
+ });
+ }
+
+ public static function getSubscribedEvents()
+ {
+ if (!class_exists(ConsoleEvents::class)) {
+ return array();
+ }
+
+ // Register early to have a working dump() as early as possible
+ return array(ConsoleEvents::COMMAND => array('configure', 1024));
+ }
+}
diff --git a/vendor/symfony/http-kernel/EventListener/ExceptionListener.php b/vendor/symfony/http-kernel/EventListener/ExceptionListener.php
new file mode 100644
index 0000000000..cf3a2f0a53
--- /dev/null
+++ b/vendor/symfony/http-kernel/EventListener/ExceptionListener.php
@@ -0,0 +1,116 @@
+<?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 Psr\Log\LoggerInterface;
+use Symfony\Component\Debug\Exception\FlattenException;
+use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\HttpKernel\Log\DebugLoggerInterface;
+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;
+
+/**
+ * ExceptionListener.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+class ExceptionListener implements EventSubscriberInterface
+{
+ protected $controller;
+ protected $logger;
+
+ public function __construct($controller, LoggerInterface $logger = null)
+ {
+ $this->controller = $controller;
+ $this->logger = $logger;
+ }
+
+ public function onKernelException(GetResponseForExceptionEvent $event)
+ {
+ $exception = $event->getException();
+ $request = $event->getRequest();
+
+ $this->logException($exception, sprintf('Uncaught PHP Exception %s: "%s" at %s line %s', get_class($exception), $exception->getMessage(), $exception->getFile(), $exception->getLine()));
+
+ $request = $this->duplicateRequest($exception, $request);
+
+ 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()));
+
+ $wrapper = $e;
+
+ while ($prev = $wrapper->getPrevious()) {
+ if ($exception === $wrapper = $prev) {
+ throw $e;
+ }
+ }
+
+ $prev = new \ReflectionProperty('Exception', 'previous');
+ $prev->setAccessible(true);
+ $prev->setValue($wrapper, $exception);
+
+ throw $e;
+ }
+
+ $event->setResponse($response);
+ }
+
+ public static function getSubscribedEvents()
+ {
+ return array(
+ KernelEvents::EXCEPTION => array('onKernelException', -128),
+ );
+ }
+
+ /**
+ * Logs an exception.
+ *
+ * @param \Exception $exception The \Exception instance
+ * @param string $message The error message to log
+ */
+ protected function logException(\Exception $exception, $message)
+ {
+ if (null !== $this->logger) {
+ if (!$exception instanceof HttpExceptionInterface || $exception->getStatusCode() >= 500) {
+ $this->logger->critical($message, array('exception' => $exception));
+ } else {
+ $this->logger->error($message, array('exception' => $exception));
+ }
+ }
+ }
+
+ /**
+ * Clones the request for the exception.
+ *
+ * @param \Exception $exception The thrown exception
+ * @param Request $request The original request
+ *
+ * @return Request $request The cloned request
+ */
+ protected function duplicateRequest(\Exception $exception, Request $request)
+ {
+ $attributes = array(
+ '_controller' => $this->controller,
+ 'exception' => FlattenException::create($exception),
+ 'logger' => $this->logger instanceof DebugLoggerInterface ? $this->logger : null,
+ );
+ $request = $request->duplicate(null, null, $attributes);
+ $request->setMethod('GET');
+
+ return $request;
+ }
+}
diff --git a/vendor/symfony/http-kernel/EventListener/FragmentListener.php b/vendor/symfony/http-kernel/EventListener/FragmentListener.php
new file mode 100644
index 0000000000..37bf15c3a0
--- /dev/null
+++ b/vendor/symfony/http-kernel/EventListener/FragmentListener.php
@@ -0,0 +1,103 @@
+<?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\HttpFoundation\Request;
+use Symfony\Component\HttpKernel\Event\GetResponseEvent;
+use Symfony\Component\HttpKernel\KernelEvents;
+use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
+use Symfony\Component\HttpKernel\UriSigner;
+use Symfony\Component\EventDispatcher\EventSubscriberInterface;
+
+/**
+ * Handles content fragments represented by special URIs.
+ *
+ * All URL paths starting with /_fragment are handled as
+ * content fragments by this listener.
+ *
+ * If 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>
+ */
+class FragmentListener implements EventSubscriberInterface
+{
+ private $signer;
+ private $fragmentPath;
+
+ /**
+ * Constructor.
+ *
+ * @param UriSigner $signer A UriSigner instance
+ * @param string $fragmentPath The path that triggers this listener
+ */
+ public function __construct(UriSigner $signer, $fragmentPath = '/_fragment')
+ {
+ $this->signer = $signer;
+ $this->fragmentPath = $fragmentPath;
+ }
+
+ /**
+ * Fixes request attributes when the path is '/_fragment'.
+ *
+ * @param GetResponseEvent $event A GetResponseEvent instance
+ *
+ * @throws AccessDeniedHttpException if the request does not come from a trusted IP.
+ */
+ public function onKernelRequest(GetResponseEvent $event)
+ {
+ $request = $event->getRequest();
+
+ if ($this->fragmentPath !== rawurldecode($request->getPathInfo())) {
+ return;
+ }
+
+ if ($request->attributes->has('_controller')) {
+ // Is a sub-request: no need to parse _path but it should still be removed from query parameters as below.
+ $request->query->remove('_path');
+
+ return;
+ }
+
+ if ($event->isMasterRequest()) {
+ $this->validateRequest($request);
+ }
+
+ 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->query->remove('_path');
+ }
+
+ protected function validateRequest(Request $request)
+ {
+ // is the Request safe?
+ if (!$request->isMethodSafe(false)) {
+ throw new AccessDeniedHttpException();
+ }
+
+ // is the Request signed?
+ // we cannot use $request->getUri() here as we want to work with the original URI (no query string reordering)
+ if ($this->signer->check($request->getSchemeAndHttpHost().$request->getBaseUrl().$request->getPathInfo().(null !== ($qs = $request->server->get('QUERY_STRING')) ? '?'.$qs : ''))) {
+ return;
+ }
+
+ throw new AccessDeniedHttpException();
+ }
+
+ public static function getSubscribedEvents()
+ {
+ return array(
+ KernelEvents::REQUEST => array(array('onKernelRequest', 48)),
+ );
+ }
+}
diff --git a/vendor/symfony/http-kernel/EventListener/LocaleListener.php b/vendor/symfony/http-kernel/EventListener/LocaleListener.php
new file mode 100644
index 0000000000..99fc786793
--- /dev/null
+++ b/vendor/symfony/http-kernel/EventListener/LocaleListener.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\HttpKernel\EventListener;
+
+use Symfony\Component\HttpKernel\Event\GetResponseEvent;
+use Symfony\Component\HttpKernel\Event\FinishRequestEvent;
+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>
+ */
+class LocaleListener implements EventSubscriberInterface
+{
+ private $router;
+ private $defaultLocale;
+ private $requestStack;
+
+ /**
+ * Constructor.
+ *
+ * @param RequestStack $requestStack A RequestStack instance
+ * @param string $defaultLocale The default locale
+ * @param RequestContextAwareInterface|null $router The router
+ */
+ public function __construct(RequestStack $requestStack, $defaultLocale = 'en', RequestContextAwareInterface $router = null)
+ {
+ $this->defaultLocale = $defaultLocale;
+ $this->requestStack = $requestStack;
+ $this->router = $router;
+ }
+
+ public function onKernelRequest(GetResponseEvent $event)
+ {
+ $request = $event->getRequest();
+ $request->setDefaultLocale($this->defaultLocale);
+
+ $this->setLocale($request);
+ $this->setRouterContext($request);
+ }
+
+ public function onKernelFinishRequest(FinishRequestEvent $event)
+ {
+ if (null !== $parentRequest = $this->requestStack->getParentRequest()) {
+ $this->setRouterContext($parentRequest);
+ }
+ }
+
+ private function setLocale(Request $request)
+ {
+ if ($locale = $request->attributes->get('_locale')) {
+ $request->setLocale($locale);
+ }
+ }
+
+ private function setRouterContext(Request $request)
+ {
+ if (null !== $this->router) {
+ $this->router->getContext()->setParameter('_locale', $request->getLocale());
+ }
+ }
+
+ 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)),
+ );
+ }
+}
diff --git a/vendor/symfony/http-kernel/EventListener/ProfilerListener.php b/vendor/symfony/http-kernel/EventListener/ProfilerListener.php
new file mode 100644
index 0000000000..c3772b688e
--- /dev/null
+++ b/vendor/symfony/http-kernel/EventListener/ProfilerListener.php
@@ -0,0 +1,135 @@
+<?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\HttpKernel\Event\GetResponseForExceptionEvent;
+use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
+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>
+ */
+class ProfilerListener implements EventSubscriberInterface
+{
+ protected $profiler;
+ protected $matcher;
+ protected $onlyException;
+ protected $onlyMasterRequests;
+ protected $exception;
+ protected $profiles;
+ protected $requestStack;
+ protected $parents;
+
+ /**
+ * Constructor.
+ *
+ * @param Profiler $profiler A Profiler instance
+ * @param RequestStack $requestStack A RequestStack instance
+ * @param RequestMatcherInterface|null $matcher A RequestMatcher instance
+ * @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)
+ {
+ $this->profiler = $profiler;
+ $this->matcher = $matcher;
+ $this->onlyException = (bool) $onlyException;
+ $this->onlyMasterRequests = (bool) $onlyMasterRequests;
+ $this->profiles = new \SplObjectStorage();
+ $this->parents = new \SplObjectStorage();
+ $this->requestStack = $requestStack;
+ }
+
+ /**
+ * Handles the onKernelException event.
+ *
+ * @param GetResponseForExceptionEvent $event A GetResponseForExceptionEvent instance
+ */
+ public function onKernelException(GetResponseForExceptionEvent $event)
+ {
+ if ($this->onlyMasterRequests && !$event->isMasterRequest()) {
+ return;
+ }
+
+ $this->exception = $event->getException();
+ }
+
+ /**
+ * Handles the onKernelResponse event.
+ *
+ * @param FilterResponseEvent $event A FilterResponseEvent instance
+ */
+ public function onKernelResponse(FilterResponseEvent $event)
+ {
+ $master = $event->isMasterRequest();
+ if ($this->onlyMasterRequests && !$master) {
+ return;
+ }
+
+ if ($this->onlyException && null === $this->exception) {
+ return;
+ }
+
+ $request = $event->getRequest();
+ $exception = $this->exception;
+ $this->exception = null;
+
+ if (null !== $this->matcher && !$this->matcher->matches($request)) {
+ return;
+ }
+
+ if (!$profile = $this->profiler->collect($request, $event->getResponse(), $exception)) {
+ return;
+ }
+
+ $this->profiles[$request] = $profile;
+
+ $this->parents[$request] = $this->requestStack->getParentRequest();
+ }
+
+ public function onKernelTerminate(PostResponseEvent $event)
+ {
+ // attach children to parents
+ foreach ($this->profiles as $request) {
+ // isset call should be removed when requestStack is required
+ if (isset($this->parents[$request]) && null !== $parentRequest = $this->parents[$request]) {
+ if (isset($this->profiles[$parentRequest])) {
+ $this->profiles[$parentRequest]->addChild($this->profiles[$request]);
+ }
+ }
+ }
+
+ // save profiles
+ foreach ($this->profiles as $request) {
+ $this->profiler->saveProfile($this->profiles[$request]);
+ }
+
+ $this->profiles = new \SplObjectStorage();
+ $this->parents = new \SplObjectStorage();
+ }
+
+ public static function getSubscribedEvents()
+ {
+ return array(
+ KernelEvents::RESPONSE => array('onKernelResponse', -100),
+ KernelEvents::EXCEPTION => 'onKernelException',
+ KernelEvents::TERMINATE => array('onKernelTerminate', -1024),
+ );
+ }
+}
diff --git a/vendor/symfony/http-kernel/EventListener/ResponseListener.php b/vendor/symfony/http-kernel/EventListener/ResponseListener.php
new file mode 100644
index 0000000000..eeb2b0fcb2
--- /dev/null
+++ b/vendor/symfony/http-kernel/EventListener/ResponseListener.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\EventListener;
+
+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>
+ */
+class ResponseListener implements EventSubscriberInterface
+{
+ private $charset;
+
+ public function __construct($charset)
+ {
+ $this->charset = $charset;
+ }
+
+ /**
+ * Filters the Response.
+ *
+ * @param FilterResponseEvent $event A FilterResponseEvent instance
+ */
+ public function onKernelResponse(FilterResponseEvent $event)
+ {
+ if (!$event->isMasterRequest()) {
+ return;
+ }
+
+ $response = $event->getResponse();
+
+ if (null === $response->getCharset()) {
+ $response->setCharset($this->charset);
+ }
+
+ $response->prepare($event->getRequest());
+ }
+
+ public static function getSubscribedEvents()
+ {
+ return array(
+ KernelEvents::RESPONSE => 'onKernelResponse',
+ );
+ }
+}
diff --git a/vendor/symfony/http-kernel/EventListener/RouterListener.php b/vendor/symfony/http-kernel/EventListener/RouterListener.php
new file mode 100644
index 0000000000..3c46be8608
--- /dev/null
+++ b/vendor/symfony/http-kernel/EventListener/RouterListener.php
@@ -0,0 +1,140 @@
+<?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 Psr\Log\LoggerInterface;
+use Symfony\Component\HttpKernel\Event\GetResponseEvent;
+use Symfony\Component\HttpKernel\Event\FinishRequestEvent;
+use Symfony\Component\HttpKernel\KernelEvents;
+use Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException;
+use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
+use Symfony\Component\HttpFoundation\RequestStack;
+use Symfony\Component\Routing\Exception\MethodNotAllowedException;
+use Symfony\Component\Routing\Exception\ResourceNotFoundException;
+use Symfony\Component\Routing\Matcher\UrlMatcherInterface;
+use Symfony\Component\Routing\Matcher\RequestMatcherInterface;
+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>
+ */
+class RouterListener implements EventSubscriberInterface
+{
+ private $matcher;
+ private $context;
+ private $logger;
+ private $requestStack;
+
+ /**
+ * Constructor.
+ *
+ * @param UrlMatcherInterface|RequestMatcherInterface $matcher The Url or Request matcher
+ * @param RequestStack $requestStack A RequestStack instance
+ * @param RequestContext|null $context The RequestContext (can be null when $matcher implements RequestContextAwareInterface)
+ * @param LoggerInterface|null $logger The logger
+ *
+ * @throws \InvalidArgumentException
+ */
+ public function __construct($matcher, RequestStack $requestStack, RequestContext $context = null, LoggerInterface $logger = null)
+ {
+ if (!$matcher instanceof UrlMatcherInterface && !$matcher instanceof RequestMatcherInterface) {
+ throw new \InvalidArgumentException('Matcher must either implement UrlMatcherInterface or RequestMatcherInterface.');
+ }
+
+ if (null === $context && !$matcher instanceof RequestContextAwareInterface) {
+ throw new \InvalidArgumentException('You must either pass a RequestContext or the matcher must implement RequestContextAwareInterface.');
+ }
+
+ $this->matcher = $matcher;
+ $this->context = $context ?: $matcher->getContext();
+ $this->requestStack = $requestStack;
+ $this->logger = $logger;
+ }
+
+ private function setCurrentRequest(Request $request = null)
+ {
+ if (null !== $request) {
+ $this->context->fromRequest($request);
+ }
+ }
+
+ /**
+ * 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)
+ {
+ $this->setCurrentRequest($this->requestStack->getParentRequest());
+ }
+
+ public function onKernelRequest(GetResponseEvent $event)
+ {
+ $request = $event->getRequest();
+
+ $this->setCurrentRequest($request);
+
+ if ($request->attributes->has('_controller')) {
+ // routing is already done
+ return;
+ }
+
+ // add attributes based on the request (routing)
+ try {
+ // matching a request is more powerful than matching a URL path + context, so try that first
+ if ($this->matcher instanceof RequestMatcherInterface) {
+ $parameters = $this->matcher->matchRequest($request);
+ } else {
+ $parameters = $this->matcher->match($request->getPathInfo());
+ }
+
+ if (null !== $this->logger) {
+ $this->logger->info('Matched route "{route}".', array(
+ '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) {
+ $message = sprintf('No route found for "%s %s"', $request->getMethod(), $request->getPathInfo());
+
+ if ($referer = $request->headers->get('referer')) {
+ $message .= sprintf(' (from "%s")', $referer);
+ }
+
+ throw new NotFoundHttpException($message, $e);
+ } catch (MethodNotAllowedException $e) {
+ $message = sprintf('No route found for "%s %s": Method Not Allowed (Allow: %s)', $request->getMethod(), $request->getPathInfo(), implode(', ', $e->getAllowedMethods()));
+
+ throw new MethodNotAllowedHttpException($e->getAllowedMethods(), $message, $e);
+ }
+ }
+
+ public static function getSubscribedEvents()
+ {
+ return array(
+ KernelEvents::REQUEST => array(array('onKernelRequest', 32)),
+ KernelEvents::FINISH_REQUEST => array(array('onKernelFinishRequest', 0)),
+ );
+ }
+}
diff --git a/vendor/symfony/http-kernel/EventListener/SaveSessionListener.php b/vendor/symfony/http-kernel/EventListener/SaveSessionListener.php
new file mode 100644
index 0000000000..36809b59af
--- /dev/null
+++ b/vendor/symfony/http-kernel/EventListener/SaveSessionListener.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\HttpKernel\EventListener;
+
+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>
+ */
+class SaveSessionListener implements EventSubscriberInterface
+{
+ public function onKernelResponse(FilterResponseEvent $event)
+ {
+ if (!$event->isMasterRequest()) {
+ return;
+ }
+
+ $session = $event->getRequest()->getSession();
+ if ($session && $session->isStarted()) {
+ $session->save();
+ }
+ }
+
+ public static function getSubscribedEvents()
+ {
+ return array(
+ // low priority but higher than StreamedResponseListener
+ KernelEvents::RESPONSE => array(array('onKernelResponse', -1000)),
+ );
+ }
+}
diff --git a/vendor/symfony/http-kernel/EventListener/SessionListener.php b/vendor/symfony/http-kernel/EventListener/SessionListener.php
new file mode 100644
index 0000000000..39ebfd922f
--- /dev/null
+++ b/vendor/symfony/http-kernel/EventListener/SessionListener.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\HttpKernel\EventListener;
+
+use Psr\Container\ContainerInterface;
+
+/**
+ * Sets the session in the request.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ *
+ * @final since version 3.3
+ */
+class SessionListener extends AbstractSessionListener
+{
+ private $container;
+
+ public function __construct(ContainerInterface $container)
+ {
+ $this->container = $container;
+ }
+
+ protected function getSession()
+ {
+ if (!$this->container->has('session')) {
+ return;
+ }
+
+ return $this->container->get('session');
+ }
+}
diff --git a/vendor/symfony/http-kernel/EventListener/StreamedResponseListener.php b/vendor/symfony/http-kernel/EventListener/StreamedResponseListener.php
new file mode 100644
index 0000000000..571cd74e34
--- /dev/null
+++ b/vendor/symfony/http-kernel/EventListener/StreamedResponseListener.php
@@ -0,0 +1,51 @@
+<?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\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>
+ */
+class StreamedResponseListener implements EventSubscriberInterface
+{
+ /**
+ * Filters the Response.
+ *
+ * @param FilterResponseEvent $event A FilterResponseEvent instance
+ */
+ public function onKernelResponse(FilterResponseEvent $event)
+ {
+ if (!$event->isMasterRequest()) {
+ return;
+ }
+
+ $response = $event->getResponse();
+
+ if ($response instanceof StreamedResponse) {
+ $response->send();
+ }
+ }
+
+ public static function getSubscribedEvents()
+ {
+ return array(
+ KernelEvents::RESPONSE => array('onKernelResponse', -1024),
+ );
+ }
+}
diff --git a/vendor/symfony/http-kernel/EventListener/SurrogateListener.php b/vendor/symfony/http-kernel/EventListener/SurrogateListener.php
new file mode 100644
index 0000000000..a207ab6731
--- /dev/null
+++ b/vendor/symfony/http-kernel/EventListener/SurrogateListener.php
@@ -0,0 +1,72 @@
+<?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\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>
+ */
+class SurrogateListener implements EventSubscriberInterface
+{
+ private $surrogate;
+
+ /**
+ * Constructor.
+ *
+ * @param SurrogateInterface $surrogate An SurrogateInterface instance
+ */
+ public function __construct(SurrogateInterface $surrogate = null)
+ {
+ $this->surrogate = $surrogate;
+ }
+
+ /**
+ * Filters the Response.
+ *
+ * @param FilterResponseEvent $event A FilterResponseEvent instance
+ */
+ public function onKernelResponse(FilterResponseEvent $event)
+ {
+ if (!$event->isMasterRequest()) {
+ return;
+ }
+
+ $kernel = $event->getKernel();
+ $surrogate = $this->surrogate;
+ if ($kernel instanceof HttpCache) {
+ $surrogate = $kernel->getSurrogate();
+ if (null !== $this->surrogate && $this->surrogate->getName() !== $surrogate->getName()) {
+ $surrogate = $this->surrogate;
+ }
+ }
+
+ if (null === $surrogate) {
+ return;
+ }
+
+ $surrogate->addSurrogateControl($event->getResponse());
+ }
+
+ public static function getSubscribedEvents()
+ {
+ return array(
+ KernelEvents::RESPONSE => 'onKernelResponse',
+ );
+ }
+}
diff --git a/vendor/symfony/http-kernel/EventListener/TestSessionListener.php b/vendor/symfony/http-kernel/EventListener/TestSessionListener.php
new file mode 100644
index 0000000000..36abb422f4
--- /dev/null
+++ b/vendor/symfony/http-kernel/EventListener/TestSessionListener.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\HttpKernel\EventListener;
+
+use Psr\Container\ContainerInterface;
+
+/**
+ * Sets the session in the request.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ *
+ * @final since version 3.3
+ */
+class TestSessionListener extends AbstractTestSessionListener
+{
+ private $container;
+
+ public function __construct(ContainerInterface $container)
+ {
+ $this->container = $container;
+ }
+
+ protected function getSession()
+ {
+ if (!$this->container->has('session')) {
+ return;
+ }
+
+ return $this->container->get('session');
+ }
+}
diff --git a/vendor/symfony/http-kernel/EventListener/TranslatorListener.php b/vendor/symfony/http-kernel/EventListener/TranslatorListener.php
new file mode 100644
index 0000000000..6967ad0298
--- /dev/null
+++ b/vendor/symfony/http-kernel/EventListener/TranslatorListener.php
@@ -0,0 +1,69 @@
+<?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\HttpKernel\Event\GetResponseEvent;
+use Symfony\Component\HttpKernel\Event\FinishRequestEvent;
+use Symfony\Component\HttpKernel\KernelEvents;
+use Symfony\Component\HttpFoundation\RequestStack;
+use Symfony\Component\Translation\TranslatorInterface;
+
+/**
+ * Synchronizes the locale between the request and the translator.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+class TranslatorListener implements EventSubscriberInterface
+{
+ private $translator;
+ private $requestStack;
+
+ public function __construct(TranslatorInterface $translator, RequestStack $requestStack)
+ {
+ $this->translator = $translator;
+ $this->requestStack = $requestStack;
+ }
+
+ public function onKernelRequest(GetResponseEvent $event)
+ {
+ $this->setLocale($event->getRequest());
+ }
+
+ public function onKernelFinishRequest(FinishRequestEvent $event)
+ {
+ if (null === $parentRequest = $this->requestStack->getParentRequest()) {
+ return;
+ }
+
+ $this->setLocale($parentRequest);
+ }
+
+ public static function getSubscribedEvents()
+ {
+ return array(
+ // must be registered after the Locale listener
+ KernelEvents::REQUEST => array(array('onKernelRequest', 10)),
+ KernelEvents::FINISH_REQUEST => array(array('onKernelFinishRequest', 0)),
+ );
+ }
+
+ private function setLocale(Request $request)
+ {
+ try {
+ $this->translator->setLocale($request->getLocale());
+ } catch (\InvalidArgumentException $e) {
+ $this->translator->setLocale($request->getDefaultLocale());
+ }
+ }
+}
diff --git a/vendor/symfony/http-kernel/EventListener/ValidateRequestListener.php b/vendor/symfony/http-kernel/EventListener/ValidateRequestListener.php
new file mode 100644
index 0000000000..b96c7814ee
--- /dev/null
+++ b/vendor/symfony/http-kernel/EventListener/ValidateRequestListener.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\HttpKernel\EventListener;
+
+use Symfony\Component\EventDispatcher\EventSubscriberInterface;
+use Symfony\Component\HttpKernel\Event\GetResponseEvent;
+use Symfony\Component\HttpKernel\KernelEvents;
+
+/**
+ * Validates Requests.
+ *
+ * @author Magnus Nordlander <magnus@fervo.se>
+ */
+class ValidateRequestListener implements EventSubscriberInterface
+{
+ /**
+ * Performs the validation.
+ *
+ * @param GetResponseEvent $event
+ */
+ public function onKernelRequest(GetResponseEvent $event)
+ {
+ if (!$event->isMasterRequest()) {
+ return;
+ }
+ $request = $event->getRequest();
+
+ if ($request::getTrustedProxies()) {
+ $request->getClientIps();
+ }
+
+ $request->getHost();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public static function getSubscribedEvents()
+ {
+ return array(
+ KernelEvents::REQUEST => array(
+ array('onKernelRequest', 256),
+ ),
+ );
+ }
+}
diff --git a/vendor/symfony/http-kernel/Exception/AccessDeniedHttpException.php b/vendor/symfony/http-kernel/Exception/AccessDeniedHttpException.php
new file mode 100644
index 0000000000..79d8639a5f
--- /dev/null
+++ b/vendor/symfony/http-kernel/Exception/AccessDeniedHttpException.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\HttpKernel\Exception;
+
+/**
+ * AccessDeniedHttpException.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ * @author Christophe Coevoet <stof@notk.org>
+ */
+class AccessDeniedHttpException extends HttpException
+{
+ /**
+ * Constructor.
+ *
+ * @param string $message The internal exception message
+ * @param \Exception $previous The previous exception
+ * @param int $code The internal exception code
+ */
+ public function __construct($message = null, \Exception $previous = null, $code = 0)
+ {
+ parent::__construct(403, $message, $previous, array(), $code);
+ }
+}
diff --git a/vendor/symfony/http-kernel/Exception/BadRequestHttpException.php b/vendor/symfony/http-kernel/Exception/BadRequestHttpException.php
new file mode 100644
index 0000000000..5f68172a8d
--- /dev/null
+++ b/vendor/symfony/http-kernel/Exception/BadRequestHttpException.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\HttpKernel\Exception;
+
+/**
+ * BadRequestHttpException.
+ *
+ * @author Ben Ramsey <ben@benramsey.com>
+ */
+class BadRequestHttpException extends HttpException
+{
+ /**
+ * Constructor.
+ *
+ * @param string $message The internal exception message
+ * @param \Exception $previous The previous exception
+ * @param int $code The internal exception code
+ */
+ public function __construct($message = null, \Exception $previous = null, $code = 0)
+ {
+ parent::__construct(400, $message, $previous, array(), $code);
+ }
+}
diff --git a/vendor/symfony/http-kernel/Exception/ConflictHttpException.php b/vendor/symfony/http-kernel/Exception/ConflictHttpException.php
new file mode 100644
index 0000000000..34d738ed12
--- /dev/null
+++ b/vendor/symfony/http-kernel/Exception/ConflictHttpException.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\HttpKernel\Exception;
+
+/**
+ * ConflictHttpException.
+ *
+ * @author Ben Ramsey <ben@benramsey.com>
+ */
+class ConflictHttpException extends HttpException
+{
+ /**
+ * Constructor.
+ *
+ * @param string $message The internal exception message
+ * @param \Exception $previous The previous exception
+ * @param int $code The internal exception code
+ */
+ public function __construct($message = null, \Exception $previous = null, $code = 0)
+ {
+ parent::__construct(409, $message, $previous, array(), $code);
+ }
+}
diff --git a/vendor/symfony/http-kernel/Exception/GoneHttpException.php b/vendor/symfony/http-kernel/Exception/GoneHttpException.php
new file mode 100644
index 0000000000..16ea223fae
--- /dev/null
+++ b/vendor/symfony/http-kernel/Exception/GoneHttpException.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\HttpKernel\Exception;
+
+/**
+ * GoneHttpException.
+ *
+ * @author Ben Ramsey <ben@benramsey.com>
+ */
+class GoneHttpException extends HttpException
+{
+ /**
+ * Constructor.
+ *
+ * @param string $message The internal exception message
+ * @param \Exception $previous The previous exception
+ * @param int $code The internal exception code
+ */
+ public function __construct($message = null, \Exception $previous = null, $code = 0)
+ {
+ parent::__construct(410, $message, $previous, array(), $code);
+ }
+}
diff --git a/vendor/symfony/http-kernel/Exception/HttpException.php b/vendor/symfony/http-kernel/Exception/HttpException.php
new file mode 100644
index 0000000000..e8e3760583
--- /dev/null
+++ b/vendor/symfony/http-kernel/Exception/HttpException.php
@@ -0,0 +1,51 @@
+<?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;
+
+/**
+ * HttpException.
+ *
+ * @author Kris Wallsmith <kris@symfony.com>
+ */
+class HttpException extends \RuntimeException implements HttpExceptionInterface
+{
+ private $statusCode;
+ private $headers;
+
+ public function __construct($statusCode, $message = null, \Exception $previous = null, array $headers = array(), $code = 0)
+ {
+ $this->statusCode = $statusCode;
+ $this->headers = $headers;
+
+ parent::__construct($message, $code, $previous);
+ }
+
+ public function getStatusCode()
+ {
+ return $this->statusCode;
+ }
+
+ public function getHeaders()
+ {
+ return $this->headers;
+ }
+
+ /**
+ * Set response headers.
+ *
+ * @param array $headers Response headers
+ */
+ public function setHeaders(array $headers)
+ {
+ $this->headers = $headers;
+ }
+}
diff --git a/vendor/symfony/http-kernel/Exception/HttpExceptionInterface.php b/vendor/symfony/http-kernel/Exception/HttpExceptionInterface.php
new file mode 100644
index 0000000000..8aa50a9f41
--- /dev/null
+++ b/vendor/symfony/http-kernel/Exception/HttpExceptionInterface.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\HttpKernel\Exception;
+
+/**
+ * Interface for HTTP error exceptions.
+ *
+ * @author Kris Wallsmith <kris@symfony.com>
+ */
+interface HttpExceptionInterface
+{
+ /**
+ * Returns the status code.
+ *
+ * @return int An HTTP response status code
+ */
+ public function getStatusCode();
+
+ /**
+ * Returns response headers.
+ *
+ * @return array Response headers
+ */
+ public function getHeaders();
+}
diff --git a/vendor/symfony/http-kernel/Exception/LengthRequiredHttpException.php b/vendor/symfony/http-kernel/Exception/LengthRequiredHttpException.php
new file mode 100644
index 0000000000..0c4b9431f4
--- /dev/null
+++ b/vendor/symfony/http-kernel/Exception/LengthRequiredHttpException.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\HttpKernel\Exception;
+
+/**
+ * LengthRequiredHttpException.
+ *
+ * @author Ben Ramsey <ben@benramsey.com>
+ */
+class LengthRequiredHttpException extends HttpException
+{
+ /**
+ * Constructor.
+ *
+ * @param string $message The internal exception message
+ * @param \Exception $previous The previous exception
+ * @param int $code The internal exception code
+ */
+ public function __construct($message = null, \Exception $previous = null, $code = 0)
+ {
+ parent::__construct(411, $message, $previous, array(), $code);
+ }
+}
diff --git a/vendor/symfony/http-kernel/Exception/MethodNotAllowedHttpException.php b/vendor/symfony/http-kernel/Exception/MethodNotAllowedHttpException.php
new file mode 100644
index 0000000000..78dd26bf0f
--- /dev/null
+++ b/vendor/symfony/http-kernel/Exception/MethodNotAllowedHttpException.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\HttpKernel\Exception;
+
+/**
+ * MethodNotAllowedHttpException.
+ *
+ * @author Kris Wallsmith <kris@symfony.com>
+ */
+class MethodNotAllowedHttpException extends HttpException
+{
+ /**
+ * Constructor.
+ *
+ * @param array $allow An array of allowed methods
+ * @param string $message The internal exception message
+ * @param \Exception $previous The previous exception
+ * @param int $code The internal exception code
+ */
+ public function __construct(array $allow, $message = null, \Exception $previous = null, $code = 0)
+ {
+ $headers = array('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
new file mode 100644
index 0000000000..cc6be4ba45
--- /dev/null
+++ b/vendor/symfony/http-kernel/Exception/NotAcceptableHttpException.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\HttpKernel\Exception;
+
+/**
+ * NotAcceptableHttpException.
+ *
+ * @author Ben Ramsey <ben@benramsey.com>
+ */
+class NotAcceptableHttpException extends HttpException
+{
+ /**
+ * Constructor.
+ *
+ * @param string $message The internal exception message
+ * @param \Exception $previous The previous exception
+ * @param int $code The internal exception code
+ */
+ public function __construct($message = null, \Exception $previous = null, $code = 0)
+ {
+ parent::__construct(406, $message, $previous, array(), $code);
+ }
+}
diff --git a/vendor/symfony/http-kernel/Exception/NotFoundHttpException.php b/vendor/symfony/http-kernel/Exception/NotFoundHttpException.php
new file mode 100644
index 0000000000..4639e379b9
--- /dev/null
+++ b/vendor/symfony/http-kernel/Exception/NotFoundHttpException.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\HttpKernel\Exception;
+
+/**
+ * NotFoundHttpException.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+class NotFoundHttpException extends HttpException
+{
+ /**
+ * Constructor.
+ *
+ * @param string $message The internal exception message
+ * @param \Exception $previous The previous exception
+ * @param int $code The internal exception code
+ */
+ public function __construct($message = null, \Exception $previous = null, $code = 0)
+ {
+ parent::__construct(404, $message, $previous, array(), $code);
+ }
+}
diff --git a/vendor/symfony/http-kernel/Exception/PreconditionFailedHttpException.php b/vendor/symfony/http-kernel/Exception/PreconditionFailedHttpException.php
new file mode 100644
index 0000000000..9df0e7b49a
--- /dev/null
+++ b/vendor/symfony/http-kernel/Exception/PreconditionFailedHttpException.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\HttpKernel\Exception;
+
+/**
+ * PreconditionFailedHttpException.
+ *
+ * @author Ben Ramsey <ben@benramsey.com>
+ */
+class PreconditionFailedHttpException extends HttpException
+{
+ /**
+ * Constructor.
+ *
+ * @param string $message The internal exception message
+ * @param \Exception $previous The previous exception
+ * @param int $code The internal exception code
+ */
+ public function __construct($message = null, \Exception $previous = null, $code = 0)
+ {
+ parent::__construct(412, $message, $previous, array(), $code);
+ }
+}
diff --git a/vendor/symfony/http-kernel/Exception/PreconditionRequiredHttpException.php b/vendor/symfony/http-kernel/Exception/PreconditionRequiredHttpException.php
new file mode 100644
index 0000000000..08ebca2241
--- /dev/null
+++ b/vendor/symfony/http-kernel/Exception/PreconditionRequiredHttpException.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\HttpKernel\Exception;
+
+/**
+ * PreconditionRequiredHttpException.
+ *
+ * @author Ben Ramsey <ben@benramsey.com>
+ *
+ * @see http://tools.ietf.org/html/rfc6585
+ */
+class PreconditionRequiredHttpException extends HttpException
+{
+ /**
+ * Constructor.
+ *
+ * @param string $message The internal exception message
+ * @param \Exception $previous The previous exception
+ * @param int $code The internal exception code
+ */
+ public function __construct($message = null, \Exception $previous = null, $code = 0)
+ {
+ parent::__construct(428, $message, $previous, array(), $code);
+ }
+}
diff --git a/vendor/symfony/http-kernel/Exception/ServiceUnavailableHttpException.php b/vendor/symfony/http-kernel/Exception/ServiceUnavailableHttpException.php
new file mode 100644
index 0000000000..32b9e2d261
--- /dev/null
+++ b/vendor/symfony/http-kernel/Exception/ServiceUnavailableHttpException.php
@@ -0,0 +1,38 @@
+<?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;
+
+/**
+ * ServiceUnavailableHttpException.
+ *
+ * @author Ben Ramsey <ben@benramsey.com>
+ */
+class ServiceUnavailableHttpException extends HttpException
+{
+ /**
+ * Constructor.
+ *
+ * @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 int $code The internal exception code
+ */
+ public function __construct($retryAfter = null, $message = null, \Exception $previous = null, $code = 0)
+ {
+ $headers = array();
+ if ($retryAfter) {
+ $headers = array('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
new file mode 100644
index 0000000000..ab86e0920b
--- /dev/null
+++ b/vendor/symfony/http-kernel/Exception/TooManyRequestsHttpException.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\HttpKernel\Exception;
+
+/**
+ * TooManyRequestsHttpException.
+ *
+ * @author Ben Ramsey <ben@benramsey.com>
+ *
+ * @see http://tools.ietf.org/html/rfc6585
+ */
+class TooManyRequestsHttpException extends HttpException
+{
+ /**
+ * Constructor.
+ *
+ * @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 int $code The internal exception code
+ */
+ public function __construct($retryAfter = null, $message = null, \Exception $previous = null, $code = 0)
+ {
+ $headers = array();
+ if ($retryAfter) {
+ $headers = array('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
new file mode 100644
index 0000000000..0dfe42db97
--- /dev/null
+++ b/vendor/symfony/http-kernel/Exception/UnauthorizedHttpException.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\HttpKernel\Exception;
+
+/**
+ * UnauthorizedHttpException.
+ *
+ * @author Ben Ramsey <ben@benramsey.com>
+ */
+class UnauthorizedHttpException extends HttpException
+{
+ /**
+ * Constructor.
+ *
+ * @param string $challenge WWW-Authenticate challenge string
+ * @param string $message The internal exception message
+ * @param \Exception $previous The previous exception
+ * @param int $code The internal exception code
+ */
+ public function __construct($challenge, $message = null, \Exception $previous = null, $code = 0)
+ {
+ $headers = array('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
new file mode 100644
index 0000000000..eb13f563f6
--- /dev/null
+++ b/vendor/symfony/http-kernel/Exception/UnprocessableEntityHttpException.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\HttpKernel\Exception;
+
+/**
+ * UnprocessableEntityHttpException.
+ *
+ * @author Steve Hutchins <hutchinsteve@gmail.com>
+ */
+class UnprocessableEntityHttpException extends HttpException
+{
+ /**
+ * Constructor.
+ *
+ * @param string $message The internal exception message
+ * @param \Exception $previous The previous exception
+ * @param int $code The internal exception code
+ */
+ public function __construct($message = null, \Exception $previous = null, $code = 0)
+ {
+ parent::__construct(422, $message, $previous, array(), $code);
+ }
+}
diff --git a/vendor/symfony/http-kernel/Exception/UnsupportedMediaTypeHttpException.php b/vendor/symfony/http-kernel/Exception/UnsupportedMediaTypeHttpException.php
new file mode 100644
index 0000000000..a9d8fa086f
--- /dev/null
+++ b/vendor/symfony/http-kernel/Exception/UnsupportedMediaTypeHttpException.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\HttpKernel\Exception;
+
+/**
+ * UnsupportedMediaTypeHttpException.
+ *
+ * @author Ben Ramsey <ben@benramsey.com>
+ */
+class UnsupportedMediaTypeHttpException extends HttpException
+{
+ /**
+ * Constructor.
+ *
+ * @param string $message The internal exception message
+ * @param \Exception $previous The previous exception
+ * @param int $code The internal exception code
+ */
+ public function __construct($message = null, \Exception $previous = null, $code = 0)
+ {
+ parent::__construct(415, $message, $previous, array(), $code);
+ }
+}
diff --git a/vendor/symfony/http-kernel/Fragment/AbstractSurrogateFragmentRenderer.php b/vendor/symfony/http-kernel/Fragment/AbstractSurrogateFragmentRenderer.php
new file mode 100644
index 0000000000..0d4d26b676
--- /dev/null
+++ b/vendor/symfony/http-kernel/Fragment/AbstractSurrogateFragmentRenderer.php
@@ -0,0 +1,112 @@
+<?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\Fragment;
+
+use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\HttpFoundation\Response;
+use Symfony\Component\HttpKernel\Controller\ControllerReference;
+use Symfony\Component\HttpKernel\HttpCache\SurrogateInterface;
+use Symfony\Component\HttpKernel\UriSigner;
+
+/**
+ * Implements Surrogate rendering strategy.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+abstract class AbstractSurrogateFragmentRenderer extends RoutableFragmentRenderer
+{
+ private $surrogate;
+ private $inlineStrategy;
+ private $signer;
+
+ /**
+ * Constructor.
+ *
+ * The "fallback" strategy when surrogate is not available should always be an
+ * instance of InlineFragmentRenderer.
+ *
+ * @param SurrogateInterface $surrogate An Surrogate instance
+ * @param FragmentRendererInterface $inlineStrategy The inline strategy to use when the surrogate is not supported
+ * @param UriSigner $signer
+ */
+ public function __construct(SurrogateInterface $surrogate = null, FragmentRendererInterface $inlineStrategy, UriSigner $signer = null)
+ {
+ $this->surrogate = $surrogate;
+ $this->inlineStrategy = $inlineStrategy;
+ $this->signer = $signer;
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * Note that if the current Request has no surrogate capability, this method
+ * falls back to use the inline rendering strategy.
+ *
+ * Additional available options:
+ *
+ * * alt: an alternative URI to render in case of an error
+ * * comment: a comment to add when returning the surrogate tag
+ *
+ * Note, that not all surrogate strategies support all options. For now
+ * 'alt' and 'comment' are only supported by ESI.
+ *
+ * @see Symfony\Component\HttpKernel\HttpCache\SurrogateInterface
+ */
+ public function render($uri, Request $request, array $options = array())
+ {
+ 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 version 3.1, and will be removed in 4.0. Use a different rendering strategy or pass scalar values.', E_USER_DEPRECATED);
+ }
+
+ return $this->inlineStrategy->render($uri, $request, $options);
+ }
+
+ if ($uri instanceof ControllerReference) {
+ $uri = $this->generateSignedFragmentUri($uri, $request);
+ }
+
+ $alt = isset($options['alt']) ? $options['alt'] : null;
+ if ($alt instanceof ControllerReference) {
+ $alt = $this->generateSignedFragmentUri($alt, $request);
+ }
+
+ $tag = $this->surrogate->renderIncludeTag($uri, $alt, isset($options['ignore_errors']) ? $options['ignore_errors'] : false, isset($options['comment']) ? $options['comment'] : '');
+
+ return new Response($tag);
+ }
+
+ private function generateSignedFragmentUri($uri, Request $request)
+ {
+ if (null === $this->signer) {
+ throw new \LogicException('You must use a URI when using the ESI rendering strategy or set a URL signer.');
+ }
+
+ // 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()));
+ }
+
+ private function containsNonScalars(array $values)
+ {
+ foreach ($values as $value) {
+ if (is_array($value) && $this->containsNonScalars($value)) {
+ return true;
+ } elseif (!is_scalar($value) && null !== $value) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+}
diff --git a/vendor/symfony/http-kernel/Fragment/EsiFragmentRenderer.php b/vendor/symfony/http-kernel/Fragment/EsiFragmentRenderer.php
new file mode 100644
index 0000000000..a4570e3beb
--- /dev/null
+++ b/vendor/symfony/http-kernel/Fragment/EsiFragmentRenderer.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\Fragment;
+
+/**
+ * Implements the ESI rendering strategy.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+class EsiFragmentRenderer extends AbstractSurrogateFragmentRenderer
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function getName()
+ {
+ return 'esi';
+ }
+}
diff --git a/vendor/symfony/http-kernel/Fragment/FragmentHandler.php b/vendor/symfony/http-kernel/Fragment/FragmentHandler.php
new file mode 100644
index 0000000000..0d0a042460
--- /dev/null
+++ b/vendor/symfony/http-kernel/Fragment/FragmentHandler.php
@@ -0,0 +1,118 @@
+<?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\Fragment;
+
+use Symfony\Component\HttpFoundation\Response;
+use Symfony\Component\HttpFoundation\StreamedResponse;
+use Symfony\Component\HttpFoundation\RequestStack;
+use Symfony\Component\HttpKernel\Controller\ControllerReference;
+
+/**
+ * Renders a URI that represents a resource fragment.
+ *
+ * This class handles the rendering of resource fragments that are included into
+ * a main resource. The handling of the rendering is managed by specialized renderers.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ *
+ * @see FragmentRendererInterface
+ */
+class FragmentHandler
+{
+ private $debug;
+ private $renderers = array();
+ private $requestStack;
+
+ /**
+ * Constructor.
+ *
+ * @param RequestStack $requestStack The Request stack that controls the lifecycle of requests
+ * @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)
+ {
+ $this->requestStack = $requestStack;
+ foreach ($renderers as $renderer) {
+ $this->addRenderer($renderer);
+ }
+ $this->debug = $debug;
+ }
+
+ /**
+ * Adds a renderer.
+ *
+ * @param FragmentRendererInterface $renderer A FragmentRendererInterface instance
+ */
+ public function addRenderer(FragmentRendererInterface $renderer)
+ {
+ $this->renderers[$renderer->getName()] = $renderer;
+ }
+
+ /**
+ * Renders a URI and returns the Response content.
+ *
+ * Available options:
+ *
+ * * ignore_errors: true to return an empty string in case of an error
+ *
+ * @param string|ControllerReference $uri A URI as a string or a ControllerReference instance
+ * @param string $renderer The renderer name
+ * @param array $options An array of options
+ *
+ * @return string|null The Response content or null when the Response is streamed
+ *
+ * @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())
+ {
+ if (!isset($options['ignore_errors'])) {
+ $options['ignore_errors'] = !$this->debug;
+ }
+
+ if (!isset($this->renderers[$renderer])) {
+ throw new \InvalidArgumentException(sprintf('The "%s" renderer does not exist.', $renderer));
+ }
+
+ if (!$request = $this->requestStack->getCurrentRequest()) {
+ throw new \LogicException('Rendering a fragment can only be done when handling a Request.');
+ }
+
+ return $this->deliver($this->renderers[$renderer]->render($uri, $request, $options));
+ }
+
+ /**
+ * Delivers the Response as a string.
+ *
+ * When the Response is a StreamedResponse, the content is streamed immediately
+ * instead of being returned.
+ *
+ * @param Response $response A Response instance
+ *
+ * @return string|null The Response content or null when the Response is streamed
+ *
+ * @throws \RuntimeException when the Response is not successful
+ */
+ protected function deliver(Response $response)
+ {
+ if (!$response->isSuccessful()) {
+ throw new \RuntimeException(sprintf('Error when rendering "%s" (Status code is %s).', $this->requestStack->getCurrentRequest()->getUri(), $response->getStatusCode()));
+ }
+
+ if (!$response instanceof StreamedResponse) {
+ return $response->getContent();
+ }
+
+ $response->sendContent();
+ }
+}
diff --git a/vendor/symfony/http-kernel/Fragment/FragmentRendererInterface.php b/vendor/symfony/http-kernel/Fragment/FragmentRendererInterface.php
new file mode 100644
index 0000000000..b177c3ac12
--- /dev/null
+++ b/vendor/symfony/http-kernel/Fragment/FragmentRendererInterface.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\HttpKernel\Fragment;
+
+use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\HttpKernel\Controller\ControllerReference;
+use Symfony\Component\HttpFoundation\Response;
+
+/**
+ * Interface implemented by all rendering strategies.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+interface FragmentRendererInterface
+{
+ /**
+ * Renders a URI and returns the Response content.
+ *
+ * @param string|ControllerReference $uri A URI as a string or a ControllerReference instance
+ * @param Request $request A Request instance
+ * @param array $options An array of options
+ *
+ * @return Response A Response instance
+ */
+ public function render($uri, Request $request, array $options = array());
+
+ /**
+ * Gets the name of the strategy.
+ *
+ * @return string The strategy name
+ */
+ public function getName();
+}
diff --git a/vendor/symfony/http-kernel/Fragment/HIncludeFragmentRenderer.php b/vendor/symfony/http-kernel/Fragment/HIncludeFragmentRenderer.php
new file mode 100644
index 0000000000..ec2a40716a
--- /dev/null
+++ b/vendor/symfony/http-kernel/Fragment/HIncludeFragmentRenderer.php
@@ -0,0 +1,167 @@
+<?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\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 Twig\Environment;
+use Twig\Error\LoaderError;
+use Twig\Loader\ExistsLoaderInterface;
+
+/**
+ * Implements the Hinclude rendering strategy.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+class HIncludeFragmentRenderer extends RoutableFragmentRenderer
+{
+ private $globalDefaultTemplate;
+ private $signer;
+ private $templating;
+ private $charset;
+
+ /**
+ * Constructor.
+ *
+ * @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')
+ {
+ $this->setTemplating($templating);
+ $this->globalDefaultTemplate = $globalDefaultTemplate;
+ $this->signer = $signer;
+ $this->charset = $charset;
+ }
+
+ /**
+ * Sets the templating engine to use to render the default content.
+ *
+ * @param EngineInterface|Environment|null $templating An EngineInterface or an Environment instance
+ *
+ * @throws \InvalidArgumentException
+ */
+ public function setTemplating($templating)
+ {
+ if (null !== $templating && !$templating instanceof EngineInterface && !$templating instanceof Environment) {
+ throw new \InvalidArgumentException('The hinclude rendering strategy needs an instance of Twig\Environment or Symfony\Component\Templating\EngineInterface');
+ }
+
+ $this->templating = $templating;
+ }
+
+ /**
+ * Checks if a templating engine has been set.
+ *
+ * @return bool true if the templating engine has been set, false otherwise
+ */
+ public function hasTemplating()
+ {
+ return null !== $this->templating;
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * Additional available options:
+ *
+ * * default: The default content (it can be a template name or the content)
+ * * 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())
+ {
+ if ($uri instanceof ControllerReference) {
+ if (null === $this->signer) {
+ throw new \LogicException('You must use a proper URI when using the Hinclude rendering strategy or set a URL signer.');
+ }
+
+ // 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()));
+ }
+
+ // We need to replace ampersands in the URI with the encoded form in order to return valid html/xml content.
+ $uri = str_replace('&', '&amp;', $uri);
+
+ $template = isset($options['default']) ? $options['default'] : $this->globalDefaultTemplate;
+ if (null !== $this->templating && $template && $this->templateExists($template)) {
+ $content = $this->templating->render($template);
+ } else {
+ $content = $template;
+ }
+
+ $attributes = isset($options['attributes']) && is_array($options['attributes']) ? $options['attributes'] : array();
+ if (isset($options['id']) && $options['id']) {
+ $attributes['id'] = $options['id'];
+ }
+ $renderedAttributes = '';
+ if (count($attributes) > 0) {
+ $flags = ENT_QUOTES | ENT_SUBSTITUTE;
+ foreach ($attributes as $attribute => $value) {
+ $renderedAttributes .= sprintf(
+ ' %s="%s"',
+ htmlspecialchars($attribute, $flags, $this->charset, false),
+ htmlspecialchars($value, $flags, $this->charset, false)
+ );
+ }
+ }
+
+ return new Response(sprintf('<hx:include src="%s"%s>%s</hx:include>', $uri, $renderedAttributes, $content));
+ }
+
+ /**
+ * @param string $template
+ *
+ * @return bool
+ */
+ private function templateExists($template)
+ {
+ if ($this->templating instanceof EngineInterface) {
+ try {
+ return $this->templating->exists($template);
+ } catch (\InvalidArgumentException $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);
+ }
+
+ return true;
+ } catch (LoaderError $e) {
+ }
+
+ return false;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getName()
+ {
+ return 'hinclude';
+ }
+}
diff --git a/vendor/symfony/http-kernel/Fragment/InlineFragmentRenderer.php b/vendor/symfony/http-kernel/Fragment/InlineFragmentRenderer.php
new file mode 100644
index 0000000000..437b40bf95
--- /dev/null
+++ b/vendor/symfony/http-kernel/Fragment/InlineFragmentRenderer.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\HttpKernel\Fragment;
+
+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\KernelEvents;
+use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
+use Symfony\Component\EventDispatcher\EventDispatcherInterface;
+
+/**
+ * Implements the inline rendering strategy where the Request is rendered by the current HTTP kernel.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+class InlineFragmentRenderer extends RoutableFragmentRenderer
+{
+ private $kernel;
+ private $dispatcher;
+
+ /**
+ * Constructor.
+ *
+ * @param HttpKernelInterface $kernel A HttpKernelInterface instance
+ * @param EventDispatcherInterface $dispatcher A EventDispatcherInterface instance
+ */
+ public function __construct(HttpKernelInterface $kernel, EventDispatcherInterface $dispatcher = null)
+ {
+ $this->kernel = $kernel;
+ $this->dispatcher = $dispatcher;
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * Additional available options:
+ *
+ * * alt: an alternative URI to render in case of an error
+ */
+ public function render($uri, Request $request, array $options = array())
+ {
+ $reference = null;
+ if ($uri instanceof ControllerReference) {
+ $reference = $uri;
+
+ // Remove attributes from the generated URI because if not, the Symfony
+ // routing system will use them to populate the Request attributes. We don't
+ // want that as we want to preserve objects (so we manually set Request attributes
+ // below instead)
+ $attributes = $reference->attributes;
+ $reference->attributes = array();
+
+ // The request format and locale might have been overridden by the user
+ foreach (array('_format', '_locale') as $key) {
+ if (isset($attributes[$key])) {
+ $reference->attributes[$key] = $attributes[$key];
+ }
+ }
+
+ $uri = $this->generateFragmentUri($uri, $request, false, false);
+
+ $reference->attributes = array_merge($attributes, $reference->attributes);
+ }
+
+ $subRequest = $this->createSubRequest($uri, $request);
+
+ // override Request attributes as they can be objects (which are not supported by the generated URI)
+ if (null !== $reference) {
+ $subRequest->attributes->add($reference->attributes);
+ }
+
+ $level = ob_get_level();
+ try {
+ return $this->kernel->handle($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
+ if (isset($options['ignore_errors']) && $options['ignore_errors'] && $this->dispatcher) {
+ $event = new GetResponseForExceptionEvent($this->kernel, $request, HttpKernelInterface::SUB_REQUEST, $e);
+
+ $this->dispatcher->dispatch(KernelEvents::EXCEPTION, $event);
+ }
+
+ // let's clean up the output buffers that were created by the sub-request
+ Response::closeOutputBuffers($level, false);
+
+ if (isset($options['alt'])) {
+ $alt = $options['alt'];
+ unset($options['alt']);
+
+ return $this->render($alt, $request, $options);
+ }
+
+ if (!isset($options['ignore_errors']) || !$options['ignore_errors']) {
+ throw $e;
+ }
+
+ return new Response();
+ }
+ }
+
+ protected function createSubRequest($uri, Request $request)
+ {
+ $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);
+ if ($request->headers->has('Surrogate-Capability')) {
+ $subRequest->headers->set('Surrogate-Capability', $request->headers->get('Surrogate-Capability'));
+ }
+
+ if ($session = $request->getSession()) {
+ $subRequest->setSession($session);
+ }
+
+ return $subRequest;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getName()
+ {
+ return 'inline';
+ }
+}
diff --git a/vendor/symfony/http-kernel/Fragment/RoutableFragmentRenderer.php b/vendor/symfony/http-kernel/Fragment/RoutableFragmentRenderer.php
new file mode 100644
index 0000000000..d7eeb89a6b
--- /dev/null
+++ b/vendor/symfony/http-kernel/Fragment/RoutableFragmentRenderer.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\HttpKernel\Fragment;
+
+use Symfony\Component\HttpKernel\Controller\ControllerReference;
+use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\HttpKernel\EventListener\FragmentListener;
+
+/**
+ * Adds the possibility to generate a fragment URI for a given Controller.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+abstract class RoutableFragmentRenderer implements FragmentRendererInterface
+{
+ private $fragmentPath = '/_fragment';
+
+ /**
+ * Sets the fragment path that triggers the fragment listener.
+ *
+ * @param string $path The path
+ *
+ * @see FragmentListener
+ */
+ public function setFragmentPath($path)
+ {
+ $this->fragmentPath = $path;
+ }
+
+ /**
+ * Generates a fragment URI for a given controller.
+ *
+ * @param ControllerReference $reference A ControllerReference instance
+ * @param Request $request A Request instance
+ * @param bool $absolute Whether to generate an absolute URL or not
+ * @param bool $strict Whether to allow non-scalar attributes or not
+ *
+ * @return string A fragment URI
+ */
+ protected function generateFragmentUri(ControllerReference $reference, Request $request, $absolute = false, $strict = true)
+ {
+ if ($strict) {
+ $this->checkNonScalar($reference->attributes);
+ }
+
+ // We need to forward the current _format and _locale values as we don't have
+ // a proper routing pattern to do the job for us.
+ // This makes things inconsistent if you switch from rendering a controller
+ // to rendering a route if the route pattern does not contain the special
+ // _format and _locale placeholders.
+ if (!isset($reference->attributes['_format'])) {
+ $reference->attributes['_format'] = $request->getRequestFormat();
+ }
+ if (!isset($reference->attributes['_locale'])) {
+ $reference->attributes['_locale'] = $request->getLocale();
+ }
+
+ $reference->attributes['_controller'] = $reference->controller;
+
+ $reference->query['_path'] = http_build_query($reference->attributes, '', '&');
+
+ $path = $this->fragmentPath.'?'.http_build_query($reference->query, '', '&');
+
+ if ($absolute) {
+ return $request->getUriForPath($path);
+ }
+
+ return $request->getBaseUrl().$path;
+ }
+
+ private function checkNonScalar($values)
+ {
+ foreach ($values as $key => $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/Fragment/SsiFragmentRenderer.php b/vendor/symfony/http-kernel/Fragment/SsiFragmentRenderer.php
new file mode 100644
index 0000000000..45e7122f05
--- /dev/null
+++ b/vendor/symfony/http-kernel/Fragment/SsiFragmentRenderer.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\Fragment;
+
+/**
+ * Implements the SSI rendering strategy.
+ *
+ * @author Sebastian Krebs <krebs.seb@gmail.com>
+ */
+class SsiFragmentRenderer extends AbstractSurrogateFragmentRenderer
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function getName()
+ {
+ return 'ssi';
+ }
+}
diff --git a/vendor/symfony/http-kernel/HttpCache/AbstractSurrogate.php b/vendor/symfony/http-kernel/HttpCache/AbstractSurrogate.php
new file mode 100644
index 0000000000..af94bea9ba
--- /dev/null
+++ b/vendor/symfony/http-kernel/HttpCache/AbstractSurrogate.php
@@ -0,0 +1,138 @@
+<?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\Request;
+use Symfony\Component\HttpFoundation\Response;
+use Symfony\Component\HttpKernel\HttpKernelInterface;
+
+/**
+ * Abstract class implementing Surrogate capabilities to Request and Response instances.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ * @author Robin Chalas <robin.chalas@gmail.com>
+ */
+abstract class AbstractSurrogate implements SurrogateInterface
+{
+ protected $contentTypes;
+ protected $phpEscapeMap = array(
+ array('<?', '<%', '<s', '<S'),
+ array('<?php echo "<?"; ?>', '<?php echo "<%"; ?>', '<?php echo "<s"; ?>', '<?php echo "<S"; ?>'),
+ );
+
+ /**
+ * Constructor.
+ *
+ * @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'))
+ {
+ $this->contentTypes = $contentTypes;
+ }
+
+ /**
+ * Returns a new cache strategy instance.
+ *
+ * @return ResponseCacheStrategyInterface A ResponseCacheStrategyInterface instance
+ */
+ public function createCacheStrategy()
+ {
+ return new ResponseCacheStrategy();
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function hasSurrogateCapability(Request $request)
+ {
+ if (null === $value = $request->headers->get('Surrogate-Capability')) {
+ return false;
+ }
+
+ return false !== strpos($value, sprintf('%s/1.0', strtoupper($this->getName())));
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function addSurrogateCapability(Request $request)
+ {
+ $current = $request->headers->get('Surrogate-Capability');
+ $new = sprintf('symfony="%s/1.0"', strtoupper($this->getName()));
+
+ $request->headers->set('Surrogate-Capability', $current ? $current.', '.$new : $new);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function needsParsing(Response $response)
+ {
+ if (!$control = $response->headers->get('Surrogate-Control')) {
+ return false;
+ }
+
+ $pattern = sprintf('#content="[^"]*%s/1.0[^"]*"#', strtoupper($this->getName()));
+
+ return (bool) preg_match($pattern, $control);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ 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());
+
+ try {
+ $response = $cache->handle($subRequest, HttpKernelInterface::SUB_REQUEST, true);
+
+ if (!$response->isSuccessful()) {
+ throw new \RuntimeException(sprintf('Error when rendering "%s" (Status code is %s).', $subRequest->getUri(), $response->getStatusCode()));
+ }
+
+ return $response->getContent();
+ } catch (\Exception $e) {
+ if ($alt) {
+ return $this->handle($cache, $alt, '', $ignoreErrors);
+ }
+
+ if (!$ignoreErrors) {
+ throw $e;
+ }
+ }
+ }
+
+ /**
+ * Remove the Surrogate from the Surrogate-Control header.
+ *
+ * @param Response $response
+ */
+ protected function removeFromControl(Response $response)
+ {
+ if (!$response->headers->has('Surrogate-Control')) {
+ return;
+ }
+
+ $value = $response->headers->get('Surrogate-Control');
+ $upperName = strtoupper($this->getName());
+
+ if (sprintf('content="%s/1.0"', $upperName) == $value) {
+ $response->headers->remove('Surrogate-Control');
+ } elseif (preg_match(sprintf('#,\s*content="%s/1.0"#', $upperName), $value)) {
+ $response->headers->set('Surrogate-Control', preg_replace(sprintf('#,\s*content="%s/1.0"#', $upperName), '', $value));
+ } elseif (preg_match(sprintf('#content="%s/1.0",\s*#', $upperName), $value)) {
+ $response->headers->set('Surrogate-Control', preg_replace(sprintf('#content="%s/1.0",\s*#', $upperName), '', $value));
+ }
+ }
+}
diff --git a/vendor/symfony/http-kernel/HttpCache/Esi.php b/vendor/symfony/http-kernel/HttpCache/Esi.php
new file mode 100644
index 0000000000..d09907ea62
--- /dev/null
+++ b/vendor/symfony/http-kernel/HttpCache/Esi.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\HttpKernel\HttpCache;
+
+use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\HttpFoundation\Response;
+
+/**
+ * Esi implements the ESI capabilities to Request and Response instances.
+ *
+ * For more information, read the following W3C notes:
+ *
+ * * ESI Language Specification 1.0 (http://www.w3.org/TR/esi-lang)
+ *
+ * * Edge Architecture Specification (http://www.w3.org/TR/edge-arch)
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+class Esi extends AbstractSurrogate
+{
+ public function getName()
+ {
+ return 'esi';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function addSurrogateControl(Response $response)
+ {
+ if (false !== strpos($response->getContent(), '<esi:include')) {
+ $response->headers->set('Surrogate-Control', 'content="ESI/1.0"');
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function renderIncludeTag($uri, $alt = null, $ignoreErrors = true, $comment = '')
+ {
+ $html = sprintf('<esi:include src="%s"%s%s />',
+ $uri,
+ $ignoreErrors ? ' onerror="continue"' : '',
+ $alt ? sprintf(' alt="%s"', $alt) : ''
+ );
+
+ if (!empty($comment)) {
+ return sprintf("<esi:comment text=\"%s\" />\n%s", $comment, $html);
+ }
+
+ return $html;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function process(Request $request, Response $response)
+ {
+ $type = $response->headers->get('Content-Type');
+ if (empty($type)) {
+ $type = 'text/html';
+ }
+
+ $parts = explode(';', $type);
+ if (!in_array($parts[0], $this->contentTypes)) {
+ return $response;
+ }
+
+ // we don't use a proper XML parser here as we can have ESI tags in a plain text response
+ $content = $response->getContent();
+ $content = preg_replace('#<esi\:remove>.*?</esi\:remove>#s', '', $content);
+ $content = preg_replace('#<esi\:comment[^>]+>#s', '', $content);
+
+ $chunks = preg_split('#<esi\:include\s+(.*?)\s*(?:/|</esi\:include)>#', $content, -1, PREG_SPLIT_DELIM_CAPTURE);
+ $chunks[0] = str_replace($this->phpEscapeMap[0], $this->phpEscapeMap[1], $chunks[0]);
+
+ $i = 1;
+ while (isset($chunks[$i])) {
+ $options = array();
+ preg_match_all('/(src|onerror|alt)="([^"]*?)"/', $chunks[$i], $matches, PREG_SET_ORDER);
+ foreach ($matches as $set) {
+ $options[$set[1]] = $set[2];
+ }
+
+ if (!isset($options['src'])) {
+ throw new \RuntimeException('Unable to process an ESI tag without a "src" attribute.');
+ }
+
+ $chunks[$i] = sprintf('<?php echo $this->surrogate->handle($this, %s, %s, %s) ?>'."\n",
+ var_export($options['src'], true),
+ var_export(isset($options['alt']) ? $options['alt'] : '', true),
+ isset($options['onerror']) && 'continue' === $options['onerror'] ? 'true' : 'false'
+ );
+ ++$i;
+ $chunks[$i] = str_replace($this->phpEscapeMap[0], $this->phpEscapeMap[1], $chunks[$i]);
+ ++$i;
+ }
+ $content = implode('', $chunks);
+
+ $response->setContent($content);
+ $response->headers->set('X-Body-Eval', 'ESI');
+
+ // remove ESI/1.0 from the Surrogate-Control header
+ $this->removeFromControl($response);
+ }
+}
diff --git a/vendor/symfony/http-kernel/HttpCache/HttpCache.php b/vendor/symfony/http-kernel/HttpCache/HttpCache.php
new file mode 100644
index 0000000000..be2bc63dda
--- /dev/null
+++ b/vendor/symfony/http-kernel/HttpCache/HttpCache.php
@@ -0,0 +1,737 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (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.
+ */
+
+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;
+
+/**
+ * Cache provides HTTP caching.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+class HttpCache implements HttpKernelInterface, TerminableInterface
+{
+ private $kernel;
+ private $store;
+ private $request;
+ private $surrogate;
+ private $surrogateCacheStrategy;
+ private $options = array();
+ private $traces = array();
+
+ /**
+ * Constructor.
+ *
+ * The available options are:
+ *
+ * * debug: If true, the traces are added as a HTTP header to ease debugging
+ *
+ * * default_ttl The number of seconds that a cache entry should be considered
+ * fresh when no explicit freshness information is provided in
+ * a response. Explicit Cache-Control or Expires headers
+ * override this value. (default: 0)
+ *
+ * * private_headers Set of request headers that trigger "private" cache-control behavior
+ * on responses that don't explicitly state whether the response is
+ * public or private via a Cache-Control directive. (default: Authorization and Cookie)
+ *
+ * * allow_reload Specifies whether the client can force a cache reload by including a
+ * Cache-Control "no-cache" directive in the request. Set it to ``true``
+ * for compliance with RFC 2616. (default: false)
+ *
+ * * allow_revalidate Specifies whether the client can force a cache revalidate by including
+ * a Cache-Control "max-age=0" directive in the request. Set it to ``true``
+ * for compliance with RFC 2616. (default: false)
+ *
+ * * stale_while_revalidate Specifies the default number of seconds (the granularity is the second as the
+ * Response TTL precision is a second) during which the cache can immediately return
+ * a stale response while it revalidates it in the background (default: 2).
+ * This setting is overridden by the stale-while-revalidate HTTP Cache-Control
+ * extension (see RFC 5861).
+ *
+ * * stale_if_error Specifies the default number of seconds (the granularity is the second) during which
+ * the cache can serve a stale response when an error is encountered (default: 60).
+ * This setting is overridden by the stale-if-error HTTP Cache-Control extension
+ * (see RFC 5861).
+ *
+ * @param HttpKernelInterface $kernel An HttpKernelInterface instance
+ * @param StoreInterface $store A Store instance
+ * @param SurrogateInterface $surrogate A SurrogateInterface instance
+ * @param array $options An array of options
+ */
+ public function __construct(HttpKernelInterface $kernel, StoreInterface $store, SurrogateInterface $surrogate = null, array $options = array())
+ {
+ $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'));
+
+ $this->options = array_merge(array(
+ 'debug' => false,
+ 'default_ttl' => 0,
+ 'private_headers' => array('Authorization', 'Cookie'),
+ 'allow_reload' => false,
+ 'allow_revalidate' => false,
+ 'stale_while_revalidate' => 2,
+ 'stale_if_error' => 60,
+ ), $options);
+ }
+
+ /**
+ * Gets the current store.
+ *
+ * @return StoreInterface $store A StoreInterface instance
+ */
+ public function getStore()
+ {
+ return $this->store;
+ }
+
+ /**
+ * Returns an array of events that took place during processing of the last request.
+ *
+ * @return array An array of events
+ */
+ public function getTraces()
+ {
+ return $this->traces;
+ }
+
+ /**
+ * Returns a log message for the events of the last request processing.
+ *
+ * @return string A log message
+ */
+ public function getLog()
+ {
+ $log = array();
+ foreach ($this->traces as $request => $traces) {
+ $log[] = sprintf('%s: %s', $request, implode(', ', $traces));
+ }
+
+ return implode('; ', $log);
+ }
+
+ /**
+ * Gets the Request instance associated with the master request.
+ *
+ * @return Request A Request instance
+ */
+ public function getRequest()
+ {
+ return $this->request;
+ }
+
+ /**
+ * Gets the Kernel instance.
+ *
+ * @return HttpKernelInterface An HttpKernelInterface instance
+ */
+ public function getKernel()
+ {
+ return $this->kernel;
+ }
+
+ /**
+ * Gets the Surrogate instance.
+ *
+ * @return SurrogateInterface A Surrogate instance
+ *
+ * @throws \LogicException
+ */
+ public function getSurrogate()
+ {
+ return $this->surrogate;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function handle(Request $request, $type = HttpKernelInterface::MASTER_REQUEST, $catch = true)
+ {
+ // 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;
+ if (null !== $this->surrogate) {
+ $this->surrogateCacheStrategy = $this->surrogate->createCacheStrategy();
+ }
+ }
+
+ $this->traces[$this->getTraceKey($request)] = array();
+
+ if (!$request->isMethodSafe(false)) {
+ $response = $this->invalidate($request, $catch);
+ } elseif ($request->headers->has('expect') || !$request->isMethodCacheable()) {
+ $response = $this->pass($request, $catch);
+ } elseif ($this->options['allow_reload'] && $request->isNoCache()) {
+ /*
+ If allow_reload is configured and the client requests "Cache-Control: no-cache",
+ reload the cache by fetching a fresh response and caching it (if possible).
+ */
+ $this->record($request, 'reload');
+ $response = $this->fetch($request, $catch);
+ } else {
+ $response = $this->lookup($request, $catch);
+ }
+
+ $this->restoreResponseBody($request, $response);
+
+ if (HttpKernelInterface::MASTER_REQUEST === $type && $this->options['debug']) {
+ $response->headers->set('X-Symfony-Cache', $this->getLog());
+ }
+
+ if (null !== $this->surrogate) {
+ if (HttpKernelInterface::MASTER_REQUEST === $type) {
+ $this->surrogateCacheStrategy->update($response);
+ } else {
+ $this->surrogateCacheStrategy->add($response);
+ }
+ }
+
+ $response->prepare($request);
+
+ $response->isNotModified($request);
+
+ return $response;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function terminate(Request $request, Response $response)
+ {
+ if ($this->getKernel() instanceof TerminableInterface) {
+ $this->getKernel()->terminate($request, $response);
+ }
+ }
+
+ /**
+ * Forwards the Request to the backend without storing the Response in the cache.
+ *
+ * @param Request $request A Request instance
+ * @param bool $catch Whether to process exceptions
+ *
+ * @return Response A Response instance
+ */
+ protected function pass(Request $request, $catch = false)
+ {
+ $this->record($request, 'pass');
+
+ return $this->forward($request, $catch);
+ }
+
+ /**
+ * Invalidates non-safe methods (like POST, PUT, and DELETE).
+ *
+ * @param Request $request A Request instance
+ * @param bool $catch Whether to process exceptions
+ *
+ * @return Response A Response instance
+ *
+ * @throws \Exception
+ *
+ * @see RFC2616 13.10
+ */
+ protected function invalidate(Request $request, $catch = false)
+ {
+ $response = $this->pass($request, $catch);
+
+ // invalidate only when the response is successful
+ if ($response->isSuccessful() || $response->isRedirect()) {
+ try {
+ $this->store->invalidate($request);
+
+ // As per the RFC, invalidate Location and Content-Location URLs if present
+ foreach (array('Location', 'Content-Location') as $header) {
+ if ($uri = $response->headers->get($header)) {
+ $subRequest = Request::create($uri, 'get', array(), array(), array(), $request->server->all());
+
+ $this->store->invalidate($subRequest);
+ }
+ }
+
+ $this->record($request, 'invalidate');
+ } catch (\Exception $e) {
+ $this->record($request, 'invalidate-failed');
+
+ if ($this->options['debug']) {
+ throw $e;
+ }
+ }
+ }
+
+ return $response;
+ }
+
+ /**
+ * Lookups a Response from the cache for the given Request.
+ *
+ * When a matching cache entry is found and is fresh, it uses it as the
+ * response without forwarding any request to the backend. When a matching
+ * cache entry is found but is stale, it attempts to "validate" the entry with
+ * the backend using conditional GET. When no matching cache entry is found,
+ * it triggers "miss" processing.
+ *
+ * @param Request $request A Request instance
+ * @param bool $catch whether to process exceptions
+ *
+ * @return Response A Response instance
+ *
+ * @throws \Exception
+ */
+ protected function lookup(Request $request, $catch = false)
+ {
+ try {
+ $entry = $this->store->lookup($request);
+ } catch (\Exception $e) {
+ $this->record($request, 'lookup-failed');
+
+ if ($this->options['debug']) {
+ throw $e;
+ }
+
+ return $this->pass($request, $catch);
+ }
+
+ if (null === $entry) {
+ $this->record($request, 'miss');
+
+ return $this->fetch($request, $catch);
+ }
+
+ if (!$this->isFreshEnough($request, $entry)) {
+ $this->record($request, 'stale');
+
+ return $this->validate($request, $entry, $catch);
+ }
+
+ $this->record($request, 'fresh');
+
+ $entry->headers->set('Age', $entry->getAge());
+
+ return $entry;
+ }
+
+ /**
+ * Validates that a cache entry is fresh.
+ *
+ * The original request is used as a template for a conditional
+ * GET request with the backend.
+ *
+ * @param Request $request A Request instance
+ * @param Response $entry A Response instance to validate
+ * @param bool $catch Whether to process exceptions
+ *
+ * @return Response A Response instance
+ */
+ protected function validate(Request $request, Response $entry, $catch = false)
+ {
+ $subRequest = clone $request;
+
+ // send no head requests because we want content
+ if ('HEAD' === $request->getMethod()) {
+ $subRequest->setMethod('GET');
+ }
+
+ // add our cached last-modified validator
+ $subRequest->headers->set('if_modified_since', $entry->headers->get('Last-Modified'));
+
+ // 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();
+ $requestEtags = $request->getETags();
+ if ($etags = array_unique(array_merge($cachedEtags, $requestEtags))) {
+ $subRequest->headers->set('if_none_match', implode(', ', $etags));
+ }
+
+ $response = $this->forward($subRequest, $catch, $entry);
+
+ if (304 == $response->getStatusCode()) {
+ $this->record($request, 'valid');
+
+ // 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)) {
+ return $response;
+ }
+
+ $entry = clone $entry;
+ $entry->headers->remove('Date');
+
+ foreach (array('Date', 'Expires', 'Cache-Control', 'ETag', 'Last-Modified') as $name) {
+ if ($response->headers->has($name)) {
+ $entry->headers->set($name, $response->headers->get($name));
+ }
+ }
+
+ $response = $entry;
+ } else {
+ $this->record($request, 'invalid');
+ }
+
+ if ($response->isCacheable()) {
+ $this->store($request, $response);
+ }
+
+ return $response;
+ }
+
+ /**
+ * Unconditionally fetches a fresh response from the backend and
+ * stores it in the cache if is cacheable.
+ *
+ * @param Request $request A Request instance
+ * @param bool $catch whether to process exceptions
+ *
+ * @return Response A Response instance
+ */
+ protected function fetch(Request $request, $catch = false)
+ {
+ $subRequest = clone $request;
+
+ // send no head requests because we want content
+ if ('HEAD' === $request->getMethod()) {
+ $subRequest->setMethod('GET');
+ }
+
+ // avoid that the backend sends no content
+ $subRequest->headers->remove('if_modified_since');
+ $subRequest->headers->remove('if_none_match');
+
+ $response = $this->forward($subRequest, $catch);
+
+ if ($response->isCacheable()) {
+ $this->store($request, $response);
+ }
+
+ return $response;
+ }
+
+ /**
+ * Forwards the Request to the backend and returns the Response.
+ *
+ * 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)
+ *
+ * @return Response A Response instance
+ */
+ protected function forward(Request $request, $catch = false, Response $entry = null)
+ {
+ if ($this->surrogate) {
+ $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
+
+ // 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 === $age = $entry->headers->getCacheControlDirective('stale-if-error')) {
+ $age = $this->options['stale_if_error'];
+ }
+
+ if (abs($entry->getTtl()) < $age) {
+ $this->record($request, 'stale-if-error');
+
+ return $entry;
+ }
+ }
+
+ /*
+ RFC 7231 Sect. 7.1.1.2 says that a server that does not have a reasonably accurate
+ clock MUST NOT send a "Date" header, although it MUST send one in most other cases
+ except for 1xx or 5xx responses where it MAY do so.
+
+ Anyway, a client that received a message without a "Date" header MUST add it.
+ */
+ if (!$response->headers->has('Date')) {
+ $response->setDate(\DateTime::createFromFormat('U', time()));
+ }
+
+ $this->processResponseBody($request, $response);
+
+ if ($this->isPrivateRequest($request) && !$response->headers->hasCacheControlDirective('public')) {
+ $response->setPrivate();
+ } elseif ($this->options['default_ttl'] > 0 && null === $response->getTtl() && !$response->headers->getCacheControlDirective('must-revalidate')) {
+ $response->setTtl($this->options['default_ttl']);
+ }
+
+ return $response;
+ }
+
+ /**
+ * Checks whether the cache entry is "fresh enough" to satisfy the Request.
+ *
+ * @param Request $request A Request instance
+ * @param Response $entry A Response instance
+ *
+ * @return bool true if the cache entry if fresh enough, false otherwise
+ */
+ protected function isFreshEnough(Request $request, Response $entry)
+ {
+ if (!$entry->isFresh()) {
+ return $this->lock($request, $entry);
+ }
+
+ if ($this->options['allow_revalidate'] && null !== $maxAge = $request->headers->getCacheControlDirective('max-age')) {
+ return $maxAge > 0 && $maxAge >= $entry->getAge();
+ }
+
+ return true;
+ }
+
+ /**
+ * Locks a Request during the call to the backend.
+ *
+ * @param Request $request A Request instance
+ * @param Response $entry A Response instance
+ *
+ * @return bool true if the cache entry can be returned even if it is staled, false otherwise
+ */
+ protected function lock(Request $request, Response $entry)
+ {
+ // try to acquire a lock to call the backend
+ $lock = $this->store->lock($request);
+
+ if (true === $lock) {
+ // we have the lock, call the backend
+ return false;
+ }
+
+ // there is already another process calling the backend
+
+ // May we serve a stale response?
+ if ($this->mayServeStaleWhileRevalidate($entry)) {
+ $this->record($request, 'stale-while-revalidate');
+
+ return true;
+ }
+
+ // wait for the lock to be released
+ if ($this->waitForLock($request)) {
+ // replace the current entry with the fresh one
+ $new = $this->lookup($request);
+ $entry->headers = $new->headers;
+ $entry->setContent($new->getContent());
+ $entry->setStatusCode($new->getStatusCode());
+ $entry->setProtocolVersion($new->getProtocolVersion());
+ foreach ($new->headers->getCookies() as $cookie) {
+ $entry->headers->setCookie($cookie);
+ }
+ } else {
+ // backend is slow as hell, send a 503 response (to avoid the dog pile effect)
+ $entry->setStatusCode(503);
+ $entry->setContent('503 Service Unavailable');
+ $entry->headers->set('Retry-After', 10);
+ }
+
+ return true;
+ }
+
+ /**
+ * Writes the Response to the cache.
+ *
+ * @param Request $request A Request instance
+ * @param Response $response A Response instance
+ *
+ * @throws \Exception
+ */
+ protected function store(Request $request, Response $response)
+ {
+ try {
+ $this->store->write($request, $response);
+
+ $this->record($request, 'store');
+
+ $response->headers->set('Age', $response->getAge());
+ } catch (\Exception $e) {
+ $this->record($request, 'store-failed');
+
+ if ($this->options['debug']) {
+ throw $e;
+ }
+ }
+
+ // now that the response is cached, release the lock
+ $this->store->unlock($request);
+ }
+
+ /**
+ * Restores the Response body.
+ *
+ * @param Request $request A Request instance
+ * @param Response $response A Response instance
+ */
+ private function restoreResponseBody(Request $request, Response $response)
+ {
+ if ($request->isMethod('HEAD') || 304 === $response->getStatusCode()) {
+ $response->setContent(null);
+ $response->headers->remove('X-Body-Eval');
+ $response->headers->remove('X-Body-File');
+
+ return;
+ }
+
+ if ($response->headers->has('X-Body-Eval')) {
+ ob_start();
+
+ if ($response->headers->has('X-Body-File')) {
+ include $response->headers->get('X-Body-File');
+ } else {
+ eval('; ?>'.$response->getContent().'<?php ;');
+ }
+
+ $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()));
+ }
+ } elseif ($response->headers->has('X-Body-File')) {
+ $response->setContent(file_get_contents($response->headers->get('X-Body-File')));
+ } else {
+ return;
+ }
+
+ $response->headers->remove('X-Body-File');
+ }
+
+ protected function processResponseBody(Request $request, Response $response)
+ {
+ if (null !== $this->surrogate && $this->surrogate->needsParsing($response)) {
+ $this->surrogate->process($request, $response);
+ }
+ }
+
+ /**
+ * Checks if the Request includes authorization or other sensitive information
+ * that should cause the Response to be considered private by default.
+ *
+ * @param Request $request A Request instance
+ *
+ * @return bool true if the Request is private, false otherwise
+ */
+ private function isPrivateRequest(Request $request)
+ {
+ foreach ($this->options['private_headers'] as $key) {
+ $key = strtolower(str_replace('HTTP_', '', $key));
+
+ if ('cookie' === $key) {
+ if (count($request->cookies->all())) {
+ return true;
+ }
+ } elseif ($request->headers->has($key)) {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Records that an event took place.
+ *
+ * @param Request $request A Request instance
+ * @param string $event The event name
+ */
+ private function record(Request $request, $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)
+ {
+ $path = $request->getPathInfo();
+ if ($qs = $request->getQueryString()) {
+ $path .= '?'.$qs;
+ }
+
+ return $request->getMethod().' '.$path;
+ }
+
+ /**
+ * 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)
+ {
+ $timeout = $entry->headers->getCacheControlDirective('stale-while-revalidate');
+
+ if (null === $timeout) {
+ $timeout = $this->options['stale_while_revalidate'];
+ }
+
+ return abs($entry->getTtl()) < $timeout;
+ }
+
+ /**
+ * 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)
+ {
+ $wait = 0;
+ while ($this->store->isLocked($request) && $wait < 5000000) {
+ usleep(50000);
+ $wait += 50000;
+ }
+
+ return $wait < 5000000;
+ }
+}
diff --git a/vendor/symfony/http-kernel/HttpCache/ResponseCacheStrategy.php b/vendor/symfony/http-kernel/HttpCache/ResponseCacheStrategy.php
new file mode 100644
index 0000000000..027b2b1761
--- /dev/null
+++ b/vendor/symfony/http-kernel/HttpCache/ResponseCacheStrategy.php
@@ -0,0 +1,96 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (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.
+ */
+
+namespace Symfony\Component\HttpKernel\HttpCache;
+
+use Symfony\Component\HttpFoundation\Response;
+
+/**
+ * ResponseCacheStrategy knows how to compute the Response cache HTTP header
+ * based on the different response cache headers.
+ *
+ * This implementation changes the master response TTL to the smallest TTL received
+ * or force validation if one of the surrogates has validation cache strategy.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+class ResponseCacheStrategy implements ResponseCacheStrategyInterface
+{
+ private $cacheable = true;
+ private $embeddedResponses = 0;
+ private $ttls = array();
+ private $maxAges = array();
+ private $isNotCacheableResponseEmbedded = false;
+
+ /**
+ * {@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;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function update(Response $response)
+ {
+ // if we have no embedded Response, do nothing
+ if (0 === $this->embeddedResponses) {
+ 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);
+ }
+
+ if (!$response->isFresh()) {
+ $this->cacheable = false;
+ }
+
+ if (!$this->cacheable) {
+ $response->headers->set('Cache-Control', 'no-cache, must-revalidate');
+
+ return;
+ }
+
+ $this->ttls[] = $response->getTtl();
+ $this->maxAges[] = $response->getMaxAge();
+
+ 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));
+ }
+ $response->setMaxAge(0);
+ }
+}
diff --git a/vendor/symfony/http-kernel/HttpCache/ResponseCacheStrategyInterface.php b/vendor/symfony/http-kernel/HttpCache/ResponseCacheStrategyInterface.php
new file mode 100644
index 0000000000..d70c2e06ec
--- /dev/null
+++ b/vendor/symfony/http-kernel/HttpCache/ResponseCacheStrategyInterface.php
@@ -0,0 +1,41 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (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.
+ */
+
+namespace Symfony\Component\HttpKernel\HttpCache;
+
+use Symfony\Component\HttpFoundation\Response;
+
+/**
+ * ResponseCacheStrategyInterface implementations know how to compute the
+ * Response cache HTTP header based on the different response cache headers.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+interface ResponseCacheStrategyInterface
+{
+ /**
+ * Adds a Response.
+ *
+ * @param Response $response
+ */
+ public function add(Response $response);
+
+ /**
+ * Updates the Response HTTP headers based on the embedded Responses.
+ *
+ * @param Response $response
+ */
+ public function update(Response $response);
+}
diff --git a/vendor/symfony/http-kernel/HttpCache/Ssi.php b/vendor/symfony/http-kernel/HttpCache/Ssi.php
new file mode 100644
index 0000000000..3178c33515
--- /dev/null
+++ b/vendor/symfony/http-kernel/HttpCache/Ssi.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\HttpKernel\HttpCache;
+
+use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\HttpFoundation\Response;
+
+/**
+ * Ssi implements the SSI capabilities to Request and Response instances.
+ *
+ * @author Sebastian Krebs <krebs.seb@gmail.com>
+ */
+class Ssi extends AbstractSurrogate
+{
+ /**
+ * {@inheritdoc}
+ */
+ public function getName()
+ {
+ return 'ssi';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function addSurrogateControl(Response $response)
+ {
+ if (false !== strpos($response->getContent(), '<!--#include')) {
+ $response->headers->set('Surrogate-Control', 'content="SSI/1.0"');
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function renderIncludeTag($uri, $alt = null, $ignoreErrors = true, $comment = '')
+ {
+ return sprintf('<!--#include virtual="%s" -->', $uri);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function process(Request $request, Response $response)
+ {
+ $type = $response->headers->get('Content-Type');
+ if (empty($type)) {
+ $type = 'text/html';
+ }
+
+ $parts = explode(';', $type);
+ if (!in_array($parts[0], $this->contentTypes)) {
+ return $response;
+ }
+
+ // we don't use a proper XML parser here as we can have SSI tags in a plain text response
+ $content = $response->getContent();
+
+ $chunks = preg_split('#<!--\#include\s+(.*?)\s*-->#', $content, -1, PREG_SPLIT_DELIM_CAPTURE);
+ $chunks[0] = str_replace($this->phpEscapeMap[0], $this->phpEscapeMap[1], $chunks[0]);
+
+ $i = 1;
+ while (isset($chunks[$i])) {
+ $options = array();
+ preg_match_all('/(virtual)="([^"]*?)"/', $chunks[$i], $matches, PREG_SET_ORDER);
+ foreach ($matches as $set) {
+ $options[$set[1]] = $set[2];
+ }
+
+ if (!isset($options['virtual'])) {
+ throw new \RuntimeException('Unable to process an SSI tag without a "virtual" attribute.');
+ }
+
+ $chunks[$i] = sprintf('<?php echo $this->surrogate->handle($this, %s, \'\', false) ?>'."\n",
+ var_export($options['virtual'], true)
+ );
+ ++$i;
+ $chunks[$i] = str_replace($this->phpEscapeMap[0], $this->phpEscapeMap[1], $chunks[$i]);
+ ++$i;
+ }
+ $content = implode('', $chunks);
+
+ $response->setContent($content);
+ $response->headers->set('X-Body-Eval', 'SSI');
+
+ // remove SSI/1.0 from the Surrogate-Control header
+ $this->removeFromControl($response);
+ }
+}
diff --git a/vendor/symfony/http-kernel/HttpCache/Store.php b/vendor/symfony/http-kernel/HttpCache/Store.php
new file mode 100644
index 0000000000..c4d961e68f
--- /dev/null
+++ b/vendor/symfony/http-kernel/HttpCache/Store.php
@@ -0,0 +1,508 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (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.
+ *
+ * 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\Request;
+use Symfony\Component\HttpFoundation\Response;
+
+/**
+ * Store implements all the logic for storing cache metadata (Request and Response headers).
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+class Store implements StoreInterface
+{
+ protected $root;
+ private $keyCache;
+ private $locks;
+
+ /**
+ * Constructor.
+ *
+ * @param string $root The path to the cache directory
+ *
+ * @throws \RuntimeException
+ */
+ public function __construct($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();
+ }
+
+ /**
+ * Cleanups storage.
+ */
+ public function cleanup()
+ {
+ // unlock everything
+ foreach ($this->locks as $lock) {
+ flock($lock, LOCK_UN);
+ fclose($lock);
+ }
+
+ $this->locks = array();
+ }
+
+ /**
+ * Tries to lock the cache for a given Request, without blocking.
+ *
+ * @param Request $request A Request instance
+ *
+ * @return bool|string true if the lock is acquired, the path to the current lock otherwise
+ */
+ public function lock(Request $request)
+ {
+ $key = $this->getCacheKey($request);
+
+ if (!isset($this->locks[$key])) {
+ $path = $this->getPath($key);
+ if (!file_exists(dirname($path)) && false === @mkdir(dirname($path), 0777, true) && !is_dir(dirname($path))) {
+ return $path;
+ }
+ $h = fopen($path, 'cb');
+ if (!flock($h, LOCK_EX | LOCK_NB)) {
+ fclose($h);
+
+ return $path;
+ }
+
+ $this->locks[$key] = $h;
+ }
+
+ return true;
+ }
+
+ /**
+ * Releases the lock for the given Request.
+ *
+ * @param Request $request A Request instance
+ *
+ * @return bool False if the lock file does not exist or cannot be unlocked, true otherwise
+ */
+ public function unlock(Request $request)
+ {
+ $key = $this->getCacheKey($request);
+
+ if (isset($this->locks[$key])) {
+ flock($this->locks[$key], LOCK_UN);
+ fclose($this->locks[$key]);
+ unset($this->locks[$key]);
+
+ return true;
+ }
+
+ return false;
+ }
+
+ public function isLocked(Request $request)
+ {
+ $key = $this->getCacheKey($request);
+
+ if (isset($this->locks[$key])) {
+ return true; // shortcut if lock held by this process
+ }
+
+ if (!file_exists($path = $this->getPath($key))) {
+ return false;
+ }
+
+ $h = fopen($path, 'rb');
+ flock($h, LOCK_EX | LOCK_NB, $wouldBlock);
+ flock($h, LOCK_UN); // release the lock we just acquired
+ fclose($h);
+
+ return (bool) $wouldBlock;
+ }
+
+ /**
+ * Locates a cached Response for the Request provided.
+ *
+ * @param Request $request A Request instance
+ *
+ * @return Response|null A Response instance, or null if no cache entry was found
+ */
+ public function lookup(Request $request)
+ {
+ $key = $this->getCacheKey($request);
+
+ if (!$entries = $this->getMetadata($key)) {
+ return;
+ }
+
+ // find a cached entry that matches the request.
+ $match = null;
+ foreach ($entries as $entry) {
+ if ($this->requestsMatch(isset($entry[1]['vary'][0]) ? implode(', ', $entry[1]['vary']) : '', $request->headers->all(), $entry[0])) {
+ $match = $entry;
+
+ break;
+ }
+ }
+
+ if (null === $match) {
+ return;
+ }
+
+ list($req, $headers) = $match;
+ if (file_exists($body = $this->getPath($headers['x-content-digest'][0]))) {
+ return $this->restoreResponse($headers, $body);
+ }
+
+ // 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.
+ }
+
+ /**
+ * Writes a cache entry to the store for the given Request and Response.
+ *
+ * Existing entries are read and any that match the response are removed. This
+ * method calls write with the new list of cache entries.
+ *
+ * @param Request $request A Request instance
+ * @param Response $response A Response instance
+ *
+ * @return string The key under which the response is stored
+ *
+ * @throws \RuntimeException
+ */
+ public function write(Request $request, Response $response)
+ {
+ $key = $this->getCacheKey($request);
+ $storedEnv = $this->persistRequest($request);
+
+ // write the response body to the entity store if this is the original response
+ if (!$response->headers->has('X-Content-Digest')) {
+ $digest = $this->generateContentDigest($response);
+
+ if (false === $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()));
+ }
+ }
+
+ // read existing cache entries, remove non-varying, and add this one to the list
+ $entries = array();
+ $vary = $response->headers->get('vary');
+ foreach ($this->getMetadata($key) as $entry) {
+ if (!isset($entry[1]['vary'][0])) {
+ $entry[1]['vary'] = array('');
+ }
+
+ if ($vary != $entry[1]['vary'][0] || !$this->requestsMatch($vary, $entry[0], $storedEnv)) {
+ $entries[] = $entry;
+ }
+ }
+
+ $headers = $this->persistResponse($response);
+ unset($headers['age']);
+
+ array_unshift($entries, array($storedEnv, $headers));
+
+ if (false === $this->save($key, serialize($entries))) {
+ throw new \RuntimeException('Unable to store the metadata.');
+ }
+
+ return $key;
+ }
+
+ /**
+ * Returns content digest for $response.
+ *
+ * @param Response $response
+ *
+ * @return string
+ */
+ protected function generateContentDigest(Response $response)
+ {
+ return 'en'.hash('sha256', $response->getContent());
+ }
+
+ /**
+ * Invalidates all cache entries that match the request.
+ *
+ * @param Request $request A Request instance
+ *
+ * @throws \RuntimeException
+ */
+ public function invalidate(Request $request)
+ {
+ $modified = false;
+ $key = $this->getCacheKey($request);
+
+ $entries = array();
+ 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));
+ } else {
+ $entries[] = $entry;
+ }
+ }
+
+ if ($modified && false === $this->save($key, serialize($entries))) {
+ throw new \RuntimeException('Unable to store the metadata.');
+ }
+ }
+
+ /**
+ * Determines whether two Request HTTP header sets are non-varying based on
+ * the vary response header value provided.
+ *
+ * @param string $vary A Response vary header
+ * @param array $env1 A Request HTTP header array
+ * @param array $env2 A Request HTTP header array
+ *
+ * @return bool true if the two environments match, false otherwise
+ */
+ private function requestsMatch($vary, $env1, $env2)
+ {
+ if (empty($vary)) {
+ return true;
+ }
+
+ foreach (preg_split('/[\s,]+/', $vary) as $header) {
+ $key = str_replace('_', '-', strtolower($header));
+ $v1 = isset($env1[$key]) ? $env1[$key] : null;
+ $v2 = isset($env2[$key]) ? $env2[$key] : null;
+ if ($v1 !== $v2) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ /**
+ * Gets all data associated with the given key.
+ *
+ * Use this method only if you know what you are doing.
+ *
+ * @param string $key The store key
+ *
+ * @return array An array of data associated with the key
+ */
+ private function getMetadata($key)
+ {
+ if (!$entries = $this->load($key)) {
+ return array();
+ }
+
+ return unserialize($entries);
+ }
+
+ /**
+ * Purges data for the given URL.
+ *
+ * This method purges both the HTTP and the HTTPS version of the cache entry.
+ *
+ * @param string $url A URL
+ *
+ * @return bool true if the URL exists with either HTTP or HTTPS scheme and has been purged, false otherwise
+ */
+ public function purge($url)
+ {
+ $http = preg_replace('#^https:#', 'http:', $url);
+ $https = preg_replace('#^http:#', 'https:', $url);
+
+ $purgedHttp = $this->doPurge($http);
+ $purgedHttps = $this->doPurge($https);
+
+ return $purgedHttp || $purgedHttps;
+ }
+
+ /**
+ * Purges data for the given URL.
+ *
+ * @param string $url A URL
+ *
+ * @return bool true if the URL exists and has been purged, false otherwise
+ */
+ private function doPurge($url)
+ {
+ $key = $this->getCacheKey(Request::create($url));
+ if (isset($this->locks[$key])) {
+ flock($this->locks[$key], LOCK_UN);
+ fclose($this->locks[$key]);
+ unset($this->locks[$key]);
+ }
+
+ if (file_exists($path = $this->getPath($key))) {
+ unlink($path);
+
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Loads data for the given key.
+ *
+ * @param string $key The store key
+ *
+ * @return string The data associated with the key
+ */
+ private function load($key)
+ {
+ $path = $this->getPath($key);
+
+ return file_exists($path) ? file_get_contents($path) : false;
+ }
+
+ /**
+ * Save data for the given key.
+ *
+ * @param string $key The store key
+ * @param string $data The data to store
+ *
+ * @return bool
+ */
+ private function save($key, $data)
+ {
+ $path = $this->getPath($key);
+
+ if (isset($this->locks[$key])) {
+ $fp = $this->locks[$key];
+ @ftruncate($fp, 0);
+ @fseek($fp, 0);
+ $len = @fwrite($fp, $data);
+ 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))) {
+ return false;
+ }
+
+ $tmpFile = tempnam(dirname($path), basename($path));
+ if (false === $fp = @fopen($tmpFile, 'wb')) {
+ return false;
+ }
+ @fwrite($fp, $data);
+ @fclose($fp);
+
+ if ($data != file_get_contents($tmpFile)) {
+ return false;
+ }
+
+ if (false === @rename($tmpFile, $path)) {
+ return false;
+ }
+ }
+
+ @chmod($path, 0666 & ~umask());
+ }
+
+ 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);
+ }
+
+ /**
+ * Generates a cache key for the given Request.
+ *
+ * This method should return a key that must only depend on a
+ * normalized version of the request URI.
+ *
+ * If the same URI can have more than one representation, based on some
+ * headers, use a Vary header to indicate them, and each representation will
+ * be stored independently under the same cache key.
+ *
+ * @param Request $request A Request instance
+ *
+ * @return string A key for the given Request
+ */
+ protected function generateCacheKey(Request $request)
+ {
+ return 'md'.hash('sha256', $request->getUri());
+ }
+
+ /**
+ * Returns a cache key for the given Request.
+ *
+ * @param Request $request A Request instance
+ *
+ * @return string A key for the given Request
+ */
+ private function getCacheKey(Request $request)
+ {
+ if (isset($this->keyCache[$request])) {
+ return $this->keyCache[$request];
+ }
+
+ return $this->keyCache[$request] = $this->generateCacheKey($request);
+ }
+
+ /**
+ * Persists the Request HTTP headers.
+ *
+ * @param Request $request A Request instance
+ *
+ * @return array An array of HTTP headers
+ */
+ private function persistRequest(Request $request)
+ {
+ return $request->headers->all();
+ }
+
+ /**
+ * Persists the Response HTTP headers.
+ *
+ * @param Response $response A Response instance
+ *
+ * @return array An array of HTTP headers
+ */
+ private function persistResponse(Response $response)
+ {
+ $headers = $response->headers->all();
+ $headers['X-Status'] = array($response->getStatusCode());
+
+ return $headers;
+ }
+
+ /**
+ * Restores a Response from the HTTP headers and body.
+ *
+ * @param array $headers An array of HTTP headers for the Response
+ * @param string $body The Response body
+ *
+ * @return Response
+ */
+ private function restoreResponse($headers, $body = null)
+ {
+ $status = $headers['X-Status'][0];
+ unset($headers['X-Status']);
+
+ if (null !== $body) {
+ $headers['X-Body-File'] = array($body);
+ }
+
+ return new Response($body, $status, $headers);
+ }
+}
diff --git a/vendor/symfony/http-kernel/HttpCache/StoreInterface.php b/vendor/symfony/http-kernel/HttpCache/StoreInterface.php
new file mode 100644
index 0000000000..ddc0c04ee3
--- /dev/null
+++ b/vendor/symfony/http-kernel/HttpCache/StoreInterface.php
@@ -0,0 +1,96 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (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.
+ *
+ * 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\Request;
+use Symfony\Component\HttpFoundation\Response;
+
+/**
+ * Interface implemented by HTTP cache stores.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+interface StoreInterface
+{
+ /**
+ * Locates a cached Response for the Request provided.
+ *
+ * @param Request $request A Request instance
+ *
+ * @return Response|null A Response instance, or null if no cache entry was found
+ */
+ public function lookup(Request $request);
+
+ /**
+ * Writes a cache entry to the store for the given Request and Response.
+ *
+ * Existing entries are read and any that match the response are removed. This
+ * method calls write with the new list of cache entries.
+ *
+ * @param Request $request A Request instance
+ * @param Response $response A Response instance
+ *
+ * @return string The key under which the response is stored
+ */
+ public function write(Request $request, Response $response);
+
+ /**
+ * Invalidates all cache entries that match the request.
+ *
+ * @param Request $request A Request instance
+ */
+ public function invalidate(Request $request);
+
+ /**
+ * Locks the cache for a given Request.
+ *
+ * @param Request $request A Request instance
+ *
+ * @return bool|string true if the lock is acquired, the path to the current lock otherwise
+ */
+ public function lock(Request $request);
+
+ /**
+ * Releases the lock for the given Request.
+ *
+ * @param Request $request A Request instance
+ *
+ * @return bool False if the lock file does not exist or cannot be unlocked, true otherwise
+ */
+ public function unlock(Request $request);
+
+ /**
+ * Returns whether or not a lock exists.
+ *
+ * @param Request $request A Request instance
+ *
+ * @return bool true if lock exists, false otherwise
+ */
+ public function isLocked(Request $request);
+
+ /**
+ * Purges data for the given URL.
+ *
+ * @param string $url A URL
+ *
+ * @return bool true if the URL exists and has been purged, false otherwise
+ */
+ public function purge($url);
+
+ /**
+ * Cleanups storage.
+ */
+ public function cleanup();
+}
diff --git a/vendor/symfony/http-kernel/HttpCache/SurrogateInterface.php b/vendor/symfony/http-kernel/HttpCache/SurrogateInterface.php
new file mode 100644
index 0000000000..5d65fd65a4
--- /dev/null
+++ b/vendor/symfony/http-kernel/HttpCache/SurrogateInterface.php
@@ -0,0 +1,103 @@
+<?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\Request;
+use Symfony\Component\HttpFoundation\Response;
+
+interface SurrogateInterface
+{
+ /**
+ * Returns surrogate name.
+ *
+ * @return string
+ */
+ public function getName();
+
+ /**
+ * Returns a new cache strategy instance.
+ *
+ * @return ResponseCacheStrategyInterface A ResponseCacheStrategyInterface instance
+ */
+ public function createCacheStrategy();
+
+ /**
+ * Checks that at least one surrogate has Surrogate capability.
+ *
+ * @param Request $request A Request instance
+ *
+ * @return bool true if one surrogate has Surrogate capability, false otherwise
+ */
+ public function hasSurrogateCapability(Request $request);
+
+ /**
+ * Adds Surrogate-capability to the given Request.
+ *
+ * @param Request $request A Request instance
+ */
+ public function addSurrogateCapability(Request $request);
+
+ /**
+ * Adds HTTP headers to specify that the Response needs to be parsed for Surrogate.
+ *
+ * This method only adds an Surrogate HTTP header if the Response has some Surrogate tags.
+ *
+ * @param Response $response A Response instance
+ */
+ public function addSurrogateControl(Response $response);
+
+ /**
+ * Checks that the Response needs to be parsed for Surrogate tags.
+ *
+ * @param Response $response A Response instance
+ *
+ * @return bool true if the Response needs to be parsed, false otherwise
+ */
+ public function needsParsing(Response $response);
+
+ /**
+ * Renders a Surrogate tag.
+ *
+ * @param string $uri A URI
+ * @param string $alt An alternate URI
+ * @param bool $ignoreErrors Whether to ignore errors or not
+ * @param string $comment A comment to add as an esi:include tag
+ *
+ * @return string
+ */
+ public function renderIncludeTag($uri, $alt = null, $ignoreErrors = true, $comment = '');
+
+ /**
+ * Replaces a Response Surrogate tags with the included resource content.
+ *
+ * @param Request $request A Request instance
+ * @param Response $response A Response instance
+ *
+ * @return Response
+ */
+ public function process(Request $request, Response $response);
+
+ /**
+ * Handles a Surrogate from the cache.
+ *
+ * @param HttpCache $cache An HttpCache instance
+ * @param string $uri The main URI
+ * @param string $alt An alternative URI
+ * @param bool $ignoreErrors Whether to ignore errors or not
+ *
+ * @return string
+ *
+ * @throws \RuntimeException
+ * @throws \Exception
+ */
+ public function handle(HttpCache $cache, $uri, $alt, $ignoreErrors);
+}
diff --git a/vendor/symfony/http-kernel/HttpKernel.php b/vendor/symfony/http-kernel/HttpKernel.php
new file mode 100644
index 0000000000..8d55ccde1c
--- /dev/null
+++ b/vendor/symfony/http-kernel/HttpKernel.php
@@ -0,0 +1,301 @@
+<?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\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\Exception\BadRequestHttpException;
+use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
+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;
+
+/**
+ * HttpKernel notifies events to convert a Request object to a Response one.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+class HttpKernel implements HttpKernelInterface, TerminableInterface
+{
+ protected $dispatcher;
+ protected $resolver;
+ protected $requestStack;
+ private $argumentResolver;
+
+ public function __construct(EventDispatcherInterface $dispatcher, ControllerResolverInterface $resolver, RequestStack $requestStack = null, ArgumentResolverInterface $argumentResolver = null)
+ {
+ $this->dispatcher = $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;
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function handle(Request $request, $type = HttpKernelInterface::MASTER_REQUEST, $catch = true)
+ {
+ $request->headers->set('X-Php-Ob-Level', ob_get_level());
+
+ try {
+ return $this->handleRaw($request, $type);
+ } catch (\Exception $e) {
+ if ($e instanceof RequestExceptionInterface) {
+ $e = new BadRequestHttpException($e->getMessage(), $e);
+ }
+ if (false === $catch) {
+ $this->finishRequest($request, $type);
+
+ throw $e;
+ }
+
+ return $this->handleException($e, $request, $type);
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function terminate(Request $request, Response $response)
+ {
+ $this->dispatcher->dispatch(KernelEvents::TERMINATE, new PostResponseEvent($this, $request, $response));
+ }
+
+ /**
+ * @throws \LogicException If the request stack is empty
+ *
+ * @internal
+ */
+ public function terminateWithException(\Exception $exception)
+ {
+ if (!$request = $this->requestStack->getMasterRequest()) {
+ throw new \LogicException('Request stack is empty', 0, $exception);
+ }
+
+ $response = $this->handleException($exception, $request, self::MASTER_REQUEST);
+
+ $response->sendHeaders();
+ $response->sendContent();
+
+ $this->terminate($request, $response);
+ }
+
+ /**
+ * Handles a request to convert it to a response.
+ *
+ * Exceptions are not caught.
+ *
+ * @param Request $request A Request instance
+ * @param int $type The type of the request (one of HttpKernelInterface::MASTER_REQUEST or HttpKernelInterface::SUB_REQUEST)
+ *
+ * @return Response A Response instance
+ *
+ * @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)
+ {
+ $this->requestStack->push($request);
+
+ // request
+ $event = new GetResponseEvent($this, $request, $type);
+ $this->dispatcher->dispatch(KernelEvents::REQUEST, $event);
+
+ if ($event->hasResponse()) {
+ return $this->filterResponse($event->getResponse(), $request, $type);
+ }
+
+ // load controller
+ if (false === $controller = $this->resolver->getController($request)) {
+ 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);
+ $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);
+ $controller = $event->getController();
+ $arguments = $event->getArguments();
+
+ // call controller
+ $response = call_user_func_array($controller, $arguments);
+
+ // view
+ if (!$response instanceof Response) {
+ $event = new GetResponseForControllerResultEvent($this, $request, $type, $response);
+ $this->dispatcher->dispatch(KernelEvents::VIEW, $event);
+
+ if ($event->hasResponse()) {
+ $response = $event->getResponse();
+ }
+
+ if (!$response instanceof Response) {
+ $msg = sprintf('The controller must return a response (%s given).', $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);
+ }
+ }
+
+ return $this->filterResponse($response, $request, $type);
+ }
+
+ /**
+ * Filters a response object.
+ *
+ * @param Response $response A Response instance
+ * @param Request $request An error message in case the response is not a Response object
+ * @param int $type The type of the request (one of HttpKernelInterface::MASTER_REQUEST or HttpKernelInterface::SUB_REQUEST)
+ *
+ * @return Response The filtered Response instance
+ *
+ * @throws \RuntimeException if the passed object is not a Response instance
+ */
+ private function filterResponse(Response $response, Request $request, $type)
+ {
+ $event = new FilterResponseEvent($this, $request, $type, $response);
+
+ $this->dispatcher->dispatch(KernelEvents::RESPONSE, $event);
+
+ $this->finishRequest($request, $type);
+
+ return $event->getResponse();
+ }
+
+ /**
+ * Publishes the finish request event, then pop the request from the stack.
+ *
+ * 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)
+ {
+ $this->dispatcher->dispatch(KernelEvents::FINISH_REQUEST, new FinishRequestEvent($this, $request, $type));
+ $this->requestStack->pop();
+ }
+
+ /**
+ * Handles an exception by trying to convert it to a Response.
+ *
+ * @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
+ *
+ * @throws \Exception
+ */
+ private function handleException(\Exception $e, $request, $type)
+ {
+ $event = new GetResponseForExceptionEvent($this, $request, $type, $e);
+ $this->dispatcher->dispatch(KernelEvents::EXCEPTION, $event);
+
+ // a listener might have replaced the exception
+ $e = $event->getException();
+
+ if (!$event->hasResponse()) {
+ $this->finishRequest($request, $type);
+
+ throw $e;
+ }
+
+ $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 version 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()) {
+ // ensure that we actually have an error response
+ if ($e instanceof HttpExceptionInterface) {
+ // keep the HTTP status code and headers
+ $response->setStatusCode($e->getStatusCode());
+ $response->headers->add($e->getHeaders());
+ } else {
+ $response->setStatusCode(500);
+ }
+ }
+
+ try {
+ return $this->filterResponse($response, $request, $type);
+ } catch (\Exception $e) {
+ return $response;
+ }
+ }
+
+ private function varToString($var)
+ {
+ if (is_object($var)) {
+ return sprintf('Object(%s)', get_class($var));
+ }
+
+ if (is_array($var)) {
+ $a = array();
+ foreach ($var as $k => $v) {
+ $a[] = sprintf('%s => %s', $k, $this->varToString($v));
+ }
+
+ return sprintf('Array(%s)', implode(', ', $a));
+ }
+
+ if (is_resource($var)) {
+ return sprintf('Resource(%s)', get_resource_type($var));
+ }
+
+ if (null === $var) {
+ return 'null';
+ }
+
+ if (false === $var) {
+ return 'false';
+ }
+
+ if (true === $var) {
+ return 'true';
+ }
+
+ return (string) $var;
+ }
+}
diff --git a/vendor/symfony/http-kernel/HttpKernelInterface.php b/vendor/symfony/http-kernel/HttpKernelInterface.php
new file mode 100644
index 0000000000..5050bfcfba
--- /dev/null
+++ b/vendor/symfony/http-kernel/HttpKernelInterface.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;
+
+use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\HttpFoundation\Response;
+
+/**
+ * HttpKernelInterface handles a Request to convert it to a Response.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+interface HttpKernelInterface
+{
+ const MASTER_REQUEST = 1;
+ const SUB_REQUEST = 2;
+
+ /**
+ * Handles a Request to convert it to a Response.
+ *
+ * When $catch is true, the implementation must catch all exceptions
+ * and do its best to convert them to a Response instance.
+ *
+ * @param Request $request A Request instance
+ * @param int $type The type of the request
+ * (one of HttpKernelInterface::MASTER_REQUEST or HttpKernelInterface::SUB_REQUEST)
+ * @param bool $catch Whether to catch exceptions or not
+ *
+ * @return Response A Response instance
+ *
+ * @throws \Exception When an Exception occurs during processing
+ */
+ public function handle(Request $request, $type = self::MASTER_REQUEST, $catch = true);
+}
diff --git a/vendor/symfony/http-kernel/Kernel.php b/vendor/symfony/http-kernel/Kernel.php
new file mode 100644
index 0000000000..0372a86cf7
--- /dev/null
+++ b/vendor/symfony/http-kernel/Kernel.php
@@ -0,0 +1,866 @@
+<?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\Bridge\ProxyManager\LazyProxy\Instantiator\RuntimeInstantiator;
+use Symfony\Bridge\ProxyManager\LazyProxy\PhpDumper\ProxyDumper;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\DependencyInjection\Dumper\PhpDumper;
+use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
+use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
+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\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;
+
+/**
+ * The Kernel is the heart of the Symfony system.
+ *
+ * It manages an environment made of bundles.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+abstract class Kernel implements KernelInterface, TerminableInterface
+{
+ /**
+ * @var BundleInterface[]
+ */
+ protected $bundles = array();
+
+ protected $bundleMap;
+ protected $container;
+ protected $rootDir;
+ protected $environment;
+ protected $debug;
+ protected $booted = false;
+ protected $name;
+ protected $startTime;
+ protected $loadClassCache;
+
+ private $projectDir;
+
+ const VERSION = '3.3.6';
+ const VERSION_ID = 30306;
+ const MAJOR_VERSION = 3;
+ const MINOR_VERSION = 3;
+ const RELEASE_VERSION = 6;
+ const EXTRA_VERSION = '';
+
+ const END_OF_MAINTENANCE = '01/2018';
+ const END_OF_LIFE = '07/2018';
+
+ /**
+ * Constructor.
+ *
+ * @param string $environment The environment
+ * @param bool $debug Whether to enable debugging or not
+ */
+ public function __construct($environment, $debug)
+ {
+ $this->environment = $environment;
+ $this->debug = (bool) $debug;
+ $this->rootDir = $this->getRootDir();
+ $this->name = $this->getName();
+
+ if ($this->debug) {
+ $this->startTime = microtime(true);
+ }
+ }
+
+ public function __clone()
+ {
+ if ($this->debug) {
+ $this->startTime = microtime(true);
+ }
+
+ $this->booted = false;
+ $this->container = null;
+ }
+
+ /**
+ * Boots the current kernel.
+ */
+ public function boot()
+ {
+ if (true === $this->booted) {
+ return;
+ }
+
+ if ($this->loadClassCache) {
+ $this->doLoadClassCache($this->loadClassCache[0], $this->loadClassCache[1]);
+ }
+
+ // init bundles
+ $this->initializeBundles();
+
+ // init container
+ $this->initializeContainer();
+
+ foreach ($this->getBundles() as $bundle) {
+ $bundle->setContainer($this->container);
+ $bundle->boot();
+ }
+
+ $this->booted = true;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function terminate(Request $request, Response $response)
+ {
+ if (false === $this->booted) {
+ return;
+ }
+
+ if ($this->getHttpKernel() instanceof TerminableInterface) {
+ $this->getHttpKernel()->terminate($request, $response);
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function shutdown()
+ {
+ if (false === $this->booted) {
+ return;
+ }
+
+ $this->booted = false;
+
+ foreach ($this->getBundles() as $bundle) {
+ $bundle->shutdown();
+ $bundle->setContainer(null);
+ }
+
+ $this->container = null;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function handle(Request $request, $type = HttpKernelInterface::MASTER_REQUEST, $catch = true)
+ {
+ if (false === $this->booted) {
+ $this->boot();
+ }
+
+ return $this->getHttpKernel()->handle($request, $type, $catch);
+ }
+
+ /**
+ * Gets a HTTP kernel from the container.
+ *
+ * @return HttpKernel
+ */
+ protected function getHttpKernel()
+ {
+ return $this->container->get('http_kernel');
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getBundles()
+ {
+ return $this->bundles;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getBundle($name, $first = true)
+ {
+ 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];
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @throws \RuntimeException if a custom resource is hidden by a resource in a derived bundle
+ */
+ public function locateResource($name, $dir = null, $first = true)
+ {
+ if ('@' !== $name[0]) {
+ throw new \InvalidArgumentException(sprintf('A resource name must start with @ ("%s" given).', $name));
+ }
+
+ if (false !== strpos($name, '..')) {
+ throw new \RuntimeException(sprintf('File name "%s" contains invalid characters (..).', $name));
+ }
+
+ $bundleName = substr($name, 1);
+ $path = '';
+ if (false !== strpos($bundleName, '/')) {
+ list($bundleName, $path) = explode('/', $bundleName, 2);
+ }
+
+ $isResource = 0 === strpos($path, 'Resources') && null !== $dir;
+ $overridePath = substr($path, 9);
+ $resourceBundle = null;
+ $bundles = $this->getBundle($bundleName, false);
+ $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
+ ));
+ }
+
+ if ($first) {
+ return $file;
+ }
+ $files[] = $file;
+ }
+
+ if (file_exists($file = $bundle->getPath().'/'.$path)) {
+ if ($first && !$isResource) {
+ return $file;
+ }
+ $files[] = $file;
+ $resourceBundle = $bundle->getName();
+ }
+ }
+
+ if (count($files) > 0) {
+ return $first && $isResource ? $files[0] : $files;
+ }
+
+ throw new \InvalidArgumentException(sprintf('Unable to find file "%s".', $name));
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getName()
+ {
+ if (null === $this->name) {
+ $this->name = preg_replace('/[^a-zA-Z0-9_]+/', '', basename($this->rootDir));
+ if (ctype_digit($this->name[0])) {
+ $this->name = '_'.$this->name;
+ }
+ }
+
+ return $this->name;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getEnvironment()
+ {
+ return $this->environment;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function isDebug()
+ {
+ return $this->debug;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getRootDir()
+ {
+ if (null === $this->rootDir) {
+ $r = new \ReflectionObject($this);
+ $this->rootDir = dirname($r->getFileName());
+ }
+
+ return $this->rootDir;
+ }
+
+ /**
+ * Gets the application root dir (path of the project's composer file).
+ *
+ * @return string The project root dir
+ */
+ public function getProjectDir()
+ {
+ if (null === $this->projectDir) {
+ $r = new \ReflectionObject($this);
+ $dir = $rootDir = dirname($r->getFileName());
+ while (!file_exists($dir.'/composer.json')) {
+ if ($dir === dirname($dir)) {
+ return $this->projectDir = $rootDir;
+ }
+ $dir = dirname($dir);
+ }
+ $this->projectDir = $dir;
+ }
+
+ return $this->projectDir;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getContainer()
+ {
+ 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.
+ */
+ public function loadClassCache($name = 'classes', $extension = '.php')
+ {
+ if (\PHP_VERSION_ID >= 70000) {
+ @trigger_error(__METHOD__.'() is deprecated since version 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 version 3.3, to be removed in 4.0.', E_USER_DEPRECATED);
+ }
+
+ file_put_contents($this->getCacheDir().'/classes.map', sprintf('<?php return %s;', var_export($classes, true)));
+ }
+
+ /**
+ * @internal
+ */
+ public function setAnnotatedClassCache(array $annotatedClasses)
+ {
+ file_put_contents($this->getCacheDir().'/annotations.map', sprintf('<?php return %s;', var_export($annotatedClasses, true)));
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getStartTime()
+ {
+ return $this->debug ? $this->startTime : -INF;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getCacheDir()
+ {
+ return $this->rootDir.'/cache/'.$this->environment;
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getLogDir()
+ {
+ return $this->rootDir.'/logs';
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function getCharset()
+ {
+ return 'UTF-8';
+ }
+
+ /**
+ * @deprecated since version 3.3, to be removed in 4.0.
+ */
+ protected function doLoadClassCache($name, $extension)
+ {
+ if (\PHP_VERSION_ID >= 70000) {
+ @trigger_error(__METHOD__.'() is deprecated since version 3.3, to be removed in 4.0.', E_USER_DEPRECATED);
+ }
+
+ if (!$this->booted && is_file($this->getCacheDir().'/classes.map')) {
+ ClassCollectionLoader::load(include($this->getCacheDir().'/classes.map'), $this->getCacheDir(), $name, $this->debug, false, $extension);
+ }
+ }
+
+ /**
+ * 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).
+ *
+ * @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();
+
+ 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()) {
+ 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);
+ }
+ }
+ }
+
+ /**
+ * The extension point similar to the Bundle::build() method.
+ *
+ * Use this method to register compiler passes and manipulate the container during the building process.
+ *
+ * @param ContainerBuilder $container
+ */
+ protected function build(ContainerBuilder $container)
+ {
+ }
+
+ /**
+ * Gets the container class.
+ *
+ * @return string The container class
+ */
+ protected function getContainerClass()
+ {
+ return $this->name.ucfirst($this->environment).($this->debug ? 'Debug' : '').'ProjectContainer';
+ }
+
+ /**
+ * Gets the container's base class.
+ *
+ * All names except Container must be fully qualified.
+ *
+ * @return string
+ */
+ protected function getContainerBaseClass()
+ {
+ return 'Container';
+ }
+
+ /**
+ * Initializes the service container.
+ *
+ * The cached version of the service container is used when fresh, otherwise the
+ * container is built.
+ */
+ protected function initializeContainer()
+ {
+ $class = $this->getContainerClass();
+ $cache = new ConfigCache($this->getCacheDir().'/'.$class.'.php', $this->debug);
+ $fresh = true;
+ if (!$cache->isFresh()) {
+ if ($this->debug) {
+ $collectedLogs = array();
+ $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;
+ }
+
+ $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] = array(
+ 'type' => $type,
+ 'message' => $message,
+ 'file' => $file,
+ 'line' => $line,
+ 'trace' => $backtrace,
+ 'count' => 1,
+ );
+ });
+ }
+
+ try {
+ $container = null;
+ $container = $this->buildContainer();
+ $container->compile();
+ } finally {
+ if ($this->debug) {
+ restore_error_handler();
+
+ file_put_contents($this->getCacheDir().'/'.$class.'Deprecations.log', serialize(array_values($collectedLogs)));
+ file_put_contents($this->getCacheDir().'/'.$class.'Compiler.log', null !== $container ? implode("\n", $container->getCompiler()->getLog()) : '');
+ }
+ }
+ $this->dumpContainer($cache, $container, $class, $this->getContainerBaseClass());
+
+ $fresh = false;
+ }
+
+ require_once $cache->getPath();
+
+ $this->container = new $class();
+ $this->container->set('kernel', $this);
+
+ if (!$fresh && $this->container->has('cache_warmer')) {
+ $this->container->get('cache_warmer')->warmUp($this->container->getParameter('kernel.cache_dir'));
+ }
+ }
+
+ /**
+ * Returns the kernel parameters.
+ *
+ * @return array An array of kernel parameters
+ */
+ protected function getKernelParameters()
+ {
+ $bundles = array();
+ $bundlesMetadata = array();
+
+ foreach ($this->bundles as $name => $bundle) {
+ $bundles[$name] = get_class($bundle);
+ $bundlesMetadata[$name] = array(
+ 'parent' => $bundle->getParent(),
+ '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($this->getCacheDir()) ?: $this->getCacheDir(),
+ '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;
+ }
+
+ /**
+ * Builds the service container.
+ *
+ * @return ContainerBuilder The compiled service container
+ *
+ * @throws \RuntimeException
+ */
+ protected function buildContainer()
+ {
+ foreach (array('cache' => $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));
+ }
+ } elseif (!is_writable($dir)) {
+ throw new \RuntimeException(sprintf("Unable to write in the %s directory (%s)\n", $name, $dir));
+ }
+ }
+
+ $container = $this->getContainerBuilder();
+ $container->addObjectResource($this);
+ $this->prepareContainer($container);
+
+ if (null !== $cont = $this->registerContainerConfiguration($this->getContainerLoader($container))) {
+ $container->merge($cont);
+ }
+
+ $container->addCompilerPass(new AddAnnotatedClassesToCachePass($this));
+ $container->addResource(new EnvParametersResource('SYMFONY__'));
+
+ return $container;
+ }
+
+ /**
+ * Prepares the ContainerBuilder before it is compiled.
+ *
+ * @param ContainerBuilder $container A ContainerBuilder instance
+ */
+ protected function prepareContainer(ContainerBuilder $container)
+ {
+ $extensions = array();
+ foreach ($this->bundles as $bundle) {
+ if ($extension = $bundle->getContainerExtension()) {
+ $container->registerExtension($extension);
+ $extensions[] = $extension->getAlias();
+ }
+
+ if ($this->debug) {
+ $container->addObjectResource($bundle);
+ }
+ }
+
+ foreach ($this->bundles as $bundle) {
+ $bundle->build($container);
+ }
+
+ $this->build($container);
+
+ // ensure these extensions are implicitly loaded
+ $container->getCompilerPassConfig()->setMergePass(new MergeExtensionConfigurationPass($extensions));
+ }
+
+ /**
+ * Gets a new ContainerBuilder instance used to build the service container.
+ *
+ * @return ContainerBuilder
+ */
+ protected function getContainerBuilder()
+ {
+ $container = new ContainerBuilder();
+ $container->getParameterBag()->add($this->getKernelParameters());
+
+ if (class_exists('ProxyManager\Configuration') && class_exists('Symfony\Bridge\ProxyManager\LazyProxy\Instantiator\RuntimeInstantiator')) {
+ $container->setProxyInstantiator(new RuntimeInstantiator());
+ }
+
+ return $container;
+ }
+
+ /**
+ * Dumps the service container to PHP code in the cache.
+ *
+ * @param ConfigCache $cache The config cache
+ * @param ContainerBuilder $container The service container
+ * @param string $class The name of the class to generate
+ * @param string $baseClass The name of the container's base class
+ */
+ protected function dumpContainer(ConfigCache $cache, ContainerBuilder $container, $class, $baseClass)
+ {
+ // cache the container
+ $dumper = new PhpDumper($container);
+
+ if (class_exists('ProxyManager\Configuration') && class_exists('Symfony\Bridge\ProxyManager\LazyProxy\PhpDumper\ProxyDumper')) {
+ $dumper->setProxyDumper(new ProxyDumper(md5($cache->getPath())));
+ }
+
+ $content = $dumper->dump(array('class' => $class, 'base_class' => $baseClass, 'file' => $cache->getPath(), 'debug' => $this->debug));
+
+ $cache->write($content, $container->getResources());
+ }
+
+ /**
+ * Returns a loader for the container.
+ *
+ * @param ContainerInterface $container The service container
+ *
+ * @return DelegatingLoader The loader
+ */
+ protected function getContainerLoader(ContainerInterface $container)
+ {
+ $locator = new FileLocator($this);
+ $resolver = new LoaderResolver(array(
+ new XmlFileLoader($container, $locator),
+ new YamlFileLoader($container, $locator),
+ new IniFileLoader($container, $locator),
+ new PhpFileLoader($container, $locator),
+ new GlobFileLoader($locator),
+ new DirectoryLoader($container, $locator),
+ new ClosureLoader($container),
+ ));
+
+ return new DelegatingLoader($resolver);
+ }
+
+ /**
+ * Removes comments from a PHP source string.
+ *
+ * We don't use the PHP php_strip_whitespace() function
+ * as we want the content to be readable and well-formatted.
+ *
+ * @param string $source A PHP string
+ *
+ * @return string The PHP string with the comments removed
+ */
+ public static function stripComments($source)
+ {
+ if (!function_exists('token_get_all')) {
+ return $source;
+ }
+
+ $rawChunk = '';
+ $output = '';
+ $tokens = token_get_all($source);
+ $ignoreSpace = false;
+ for ($i = 0; isset($tokens[$i]); ++$i) {
+ $token = $tokens[$i];
+ if (!isset($token[1]) || 'b"' === $token) {
+ $rawChunk .= $token;
+ } elseif (T_START_HEREDOC === $token[0]) {
+ $output .= $rawChunk.$token[1];
+ do {
+ $token = $tokens[++$i];
+ $output .= isset($token[1]) && 'b"' !== $token ? $token[1] : $token;
+ } while ($token[0] !== T_END_HEREDOC);
+ $rawChunk = '';
+ } elseif (T_WHITESPACE === $token[0]) {
+ if ($ignoreSpace) {
+ $ignoreSpace = false;
+
+ continue;
+ }
+
+ // 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))) {
+ $ignoreSpace = true;
+ } else {
+ $rawChunk .= $token[1];
+
+ // The PHP-open tag already has a new-line
+ if (T_OPEN_TAG === $token[0]) {
+ $ignoreSpace = true;
+ }
+ }
+ }
+
+ $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();
+ }
+
+ return $output;
+ }
+
+ public function serialize()
+ {
+ return serialize(array($this->environment, $this->debug));
+ }
+
+ public function unserialize($data)
+ {
+ if (\PHP_VERSION_ID >= 70000) {
+ list($environment, $debug) = unserialize($data, array('allowed_classes' => false));
+ } else {
+ list($environment, $debug) = unserialize($data);
+ }
+
+ $this->__construct($environment, $debug);
+ }
+}
diff --git a/vendor/symfony/http-kernel/KernelEvents.php b/vendor/symfony/http-kernel/KernelEvents.php
new file mode 100644
index 0000000000..3e961737b8
--- /dev/null
+++ b/vendor/symfony/http-kernel/KernelEvents.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;
+
+/**
+ * Contains all events thrown in the HttpKernel component.
+ *
+ * @author Bernhard Schussek <bschussek@gmail.com>
+ */
+final class KernelEvents
+{
+ /**
+ * The REQUEST event occurs at the very beginning of request
+ * dispatching.
+ *
+ * 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")
+ *
+ * @var string
+ */
+ const REQUEST = 'kernel.request';
+
+ /**
+ * The EXCEPTION event occurs when an uncaught exception appears.
+ *
+ * This event allows you to create a response for a thrown exception or
+ * to modify the thrown exception.
+ *
+ * @Event("Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent")
+ *
+ * @var string
+ */
+ const EXCEPTION = 'kernel.exception';
+
+ /**
+ * The VIEW event occurs when the return value of a controller
+ * is not a Response instance.
+ *
+ * This event allows you to create a response for the return value of the
+ * controller.
+ *
+ * @Event("Symfony\Component\HttpKernel\Event\GetResponseForControllerResultEvent")
+ *
+ * @var string
+ */
+ const VIEW = 'kernel.view';
+
+ /**
+ * The CONTROLLER event occurs once a controller was found for
+ * handling a request.
+ *
+ * This event allows you to change the controller that will handle the
+ * request.
+ *
+ * @Event("Symfony\Component\HttpKernel\Event\FilterControllerEvent")
+ *
+ * @var string
+ */
+ const CONTROLLER = 'kernel.controller';
+
+ /**
+ * The CONTROLLER_ARGUMENTS event occurs once controller arguments have been resolved.
+ *
+ * This event allows you to change the arguments that will be passed to
+ * the controller.
+ *
+ * @Event("Symfony\Component\HttpKernel\Event\FilterControllerArgumentsEvent")
+ *
+ * @var string
+ */
+ const CONTROLLER_ARGUMENTS = 'kernel.controller_arguments';
+
+ /**
+ * The RESPONSE event occurs once a response was created for
+ * replying to a request.
+ *
+ * This event allows you to modify or replace the response that will be
+ * replied.
+ *
+ * @Event("Symfony\Component\HttpKernel\Event\FilterResponseEvent")
+ *
+ * @var string
+ */
+ const RESPONSE = 'kernel.response';
+
+ /**
+ * The TERMINATE event occurs once a response was sent.
+ *
+ * This event allows you to run expensive post-response jobs.
+ *
+ * @Event("Symfony\Component\HttpKernel\Event\PostResponseEvent")
+ *
+ * @var string
+ */
+ const TERMINATE = 'kernel.terminate';
+
+ /**
+ * The FINISH_REQUEST event occurs when a response was generated for a request.
+ *
+ * This event allows you to reset the global and environmental state of
+ * the application, when it was changed during the request.
+ *
+ * @Event("Symfony\Component\HttpKernel\Event\FinishRequestEvent")
+ *
+ * @var string
+ */
+ const FINISH_REQUEST = 'kernel.finish_request';
+}
diff --git a/vendor/symfony/http-kernel/KernelInterface.php b/vendor/symfony/http-kernel/KernelInterface.php
new file mode 100644
index 0000000000..b8609b9ede
--- /dev/null
+++ b/vendor/symfony/http-kernel/KernelInterface.php
@@ -0,0 +1,164 @@
+<?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\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.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+interface KernelInterface extends HttpKernelInterface, \Serializable
+{
+ /**
+ * Returns an array of bundles to register.
+ *
+ * @return BundleInterface[] An array of bundle instances
+ */
+ public function registerBundles();
+
+ /**
+ * Loads the container configuration.
+ *
+ * @param LoaderInterface $loader A LoaderInterface instance
+ */
+ public function registerContainerConfiguration(LoaderInterface $loader);
+
+ /**
+ * Boots the current kernel.
+ */
+ public function boot();
+
+ /**
+ * Shutdowns the kernel.
+ *
+ * This method is mainly useful when doing functional testing.
+ */
+ public function shutdown();
+
+ /**
+ * Gets the registered bundle instances.
+ *
+ * @return BundleInterface[] An array of registered bundle instances
+ */
+ public function getBundles();
+
+ /**
+ * Returns a bundle and optionally its descendants by its 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
+ *
+ * @throws \InvalidArgumentException when the bundle is not enabled
+ */
+ public function getBundle($name, $first = true);
+
+ /**
+ * Returns the file path for a given resource.
+ *
+ * A Resource can be a file or a directory.
+ *
+ * The resource name must follow the following pattern:
+ *
+ * "@BundleName/path/to/a/file.something"
+ *
+ * where BundleName is the name of the bundle
+ * and the remaining part is the relative path in the bundle.
+ *
+ * If $dir is passed, and the first segment of the path is "Resources",
+ * this method will look for a file named:
+ *
+ * $dir/<BundleName>/path/without/Resources
+ *
+ * before looking in the bundle resource folder.
+ *
+ * @param string $name A resource name to locate
+ * @param string $dir A directory where to look for the resource first
+ * @param bool $first Whether to return the first path or paths for all matching bundles
+ *
+ * @return string|array The absolute path of the resource or an array if $first is false
+ *
+ * @throws \InvalidArgumentException if the file cannot be found or the name is not valid
+ * @throws \RuntimeException if the name contains invalid/unsafe characters
+ */
+ public function locateResource($name, $dir = null, $first = true);
+
+ /**
+ * Gets the name of the kernel.
+ *
+ * @return string The kernel name
+ */
+ public function getName();
+
+ /**
+ * Gets the environment.
+ *
+ * @return string The current environment
+ */
+ public function getEnvironment();
+
+ /**
+ * Checks if debug mode is enabled.
+ *
+ * @return bool true if debug mode is enabled, false otherwise
+ */
+ public function isDebug();
+
+ /**
+ * Gets the application root dir (path of the project's Kernel class).
+ *
+ * @return string The Kernel root dir
+ */
+ public function getRootDir();
+
+ /**
+ * Gets the current container.
+ *
+ * @return ContainerInterface A ContainerInterface instance
+ */
+ public function getContainer();
+
+ /**
+ * Gets the request start time (not available if debug is disabled).
+ *
+ * @return int The request start timestamp
+ */
+ public function getStartTime();
+
+ /**
+ * Gets the cache directory.
+ *
+ * @return string The cache directory
+ */
+ public function getCacheDir();
+
+ /**
+ * Gets the log directory.
+ *
+ * @return string The log directory
+ */
+ public function getLogDir();
+
+ /**
+ * Gets the charset of the application.
+ *
+ * @return string The charset
+ */
+ public function getCharset();
+}
diff --git a/vendor/symfony/http-kernel/LICENSE b/vendor/symfony/http-kernel/LICENSE
new file mode 100644
index 0000000000..17d16a1336
--- /dev/null
+++ b/vendor/symfony/http-kernel/LICENSE
@@ -0,0 +1,19 @@
+Copyright (c) 2004-2017 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/http-kernel/Log/DebugLoggerInterface.php b/vendor/symfony/http-kernel/Log/DebugLoggerInterface.php
new file mode 100644
index 0000000000..5635a2184f
--- /dev/null
+++ b/vendor/symfony/http-kernel/Log/DebugLoggerInterface.php
@@ -0,0 +1,38 @@
+<?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\Log;
+
+/**
+ * DebugLoggerInterface.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+interface DebugLoggerInterface
+{
+ /**
+ * Returns an array of logs.
+ *
+ * A log is an array with the following mandatory keys:
+ * timestamp, message, priority, and priorityName.
+ * It can also have an optional context key containing an array.
+ *
+ * @return array An array of logs
+ */
+ public function getLogs();
+
+ /**
+ * Returns the number of errors.
+ *
+ * @return int The number of errors
+ */
+ public function countErrors();
+}
diff --git a/vendor/symfony/http-kernel/Profiler/FileProfilerStorage.php b/vendor/symfony/http-kernel/Profiler/FileProfilerStorage.php
new file mode 100644
index 0000000000..bd8761f5dd
--- /dev/null
+++ b/vendor/symfony/http-kernel/Profiler/FileProfilerStorage.php
@@ -0,0 +1,284 @@
+<?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\Profiler;
+
+/**
+ * Storage for profiler using files.
+ *
+ * @author Alexandre Salomé <alexandre.salome@gmail.com>
+ */
+class FileProfilerStorage implements ProfilerStorageInterface
+{
+ /**
+ * Folder where profiler data are stored.
+ *
+ * @var string
+ */
+ private $folder;
+
+ /**
+ * Constructs the file storage using a "dsn-like" path.
+ *
+ * Example : "file:/path/to/the/storage/folder"
+ *
+ * @param string $dsn The DSN
+ *
+ * @throws \RuntimeException
+ */
+ public function __construct($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));
+ }
+ $this->folder = substr($dsn, 5);
+
+ if (!is_dir($this->folder) && false === @mkdir($this->folder, 0777, true) && !is_dir($this->folder)) {
+ throw new \RuntimeException(sprintf('Unable to create the storage directory (%s).', $this->folder));
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function find($ip, $url, $limit, $method, $start = null, $end = null, $statusCode = null)
+ {
+ $file = $this->getIndexFilename();
+
+ if (!file_exists($file)) {
+ return array();
+ }
+
+ $file = fopen($file, 'r');
+ fseek($file, 0, SEEK_END);
+
+ $result = array();
+ while (count($result) < $limit && $line = $this->readLineFromFile($file)) {
+ $values = str_getcsv($line);
+ list($csvToken, $csvIp, $csvMethod, $csvUrl, $csvTime, $csvParent, $csvStatusCode) = $values;
+ $csvTime = (int) $csvTime;
+
+ if ($ip && false === strpos($csvIp, $ip) || $url && false === strpos($csvUrl, $url) || $method && false === strpos($csvMethod, $method) || $statusCode && false === strpos($csvStatusCode, $statusCode)) {
+ continue;
+ }
+
+ if (!empty($start) && $csvTime < $start) {
+ continue;
+ }
+
+ if (!empty($end) && $csvTime > $end) {
+ continue;
+ }
+
+ $result[$csvToken] = array(
+ 'token' => $csvToken,
+ 'ip' => $csvIp,
+ 'method' => $csvMethod,
+ 'url' => $csvUrl,
+ 'time' => $csvTime,
+ 'parent' => $csvParent,
+ 'status_code' => $csvStatusCode,
+ );
+ }
+
+ fclose($file);
+
+ return array_values($result);
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function purge()
+ {
+ $flags = \FilesystemIterator::SKIP_DOTS;
+ $iterator = new \RecursiveDirectoryIterator($this->folder, $flags);
+ $iterator = new \RecursiveIteratorIterator($iterator, \RecursiveIteratorIterator::CHILD_FIRST);
+
+ foreach ($iterator as $file) {
+ if (is_file($file)) {
+ unlink($file);
+ } else {
+ rmdir($file);
+ }
+ }
+ }
+
+ /**
+ * {@inheritdoc}
+ */
+ public function read($token)
+ {
+ if (!$token || !file_exists($file = $this->getFilename($token))) {
+ return;
+ }
+
+ return $this->createProfileFromData($token, unserialize(file_get_contents($file)));
+ }
+
+ /**
+ * {@inheritdoc}
+ *
+ * @throws \RuntimeException
+ */
+ public function write(Profile $profile)
+ {
+ $file = $this->getFilename($profile->getToken());
+
+ $profileIndexed = is_file($file);
+ if (!$profileIndexed) {
+ // Create directory
+ $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));
+ }
+ }
+
+ // Store profile
+ $data = array(
+ 'token' => $profile->getToken(),
+ 'parent' => $profile->getParentToken(),
+ 'children' => array_map(function ($p) { return $p->getToken(); }, $profile->getChildren()),
+ 'data' => $profile->getCollectors(),
+ 'ip' => $profile->getIp(),
+ 'method' => $profile->getMethod(),
+ 'url' => $profile->getUrl(),
+ 'time' => $profile->getTime(),
+ 'status_code' => $profile->getStatusCode(),
+ );
+
+ if (false === file_put_contents($file, serialize($data))) {
+ return false;
+ }
+
+ if (!$profileIndexed) {
+ // Add to index
+ if (false === $file = fopen($this->getIndexFilename(), 'a')) {
+ return false;
+ }
+
+ fputcsv($file, array(
+ $profile->getToken(),
+ $profile->getIp(),
+ $profile->getMethod(),
+ $profile->getUrl(),
+ $profile->getTime(),
+ $profile->getParentToken(),
+ $profile->getStatusCode(),
+ ));
+ fclose($file);
+ }
+
+ return true;
+ }
+
+ /**
+ * Gets filename to store data, associated to the token.
+ *
+ * @param string $token
+ *
+ * @return string The profile filename
+ */
+ protected function getFilename($token)
+ {
+ // Uses 4 last characters, because first are mostly the same.
+ $folderA = substr($token, -2, 2);
+ $folderB = substr($token, -4, 2);
+
+ return $this->folder.'/'.$folderA.'/'.$folderB.'/'.$token;
+ }
+
+ /**
+ * Gets the index filename.
+ *
+ * @return string The index filename
+ */
+ protected function getIndexFilename()
+ {
+ return $this->folder.'/index.csv';
+ }
+
+ /**
+ * Reads a line in the file, backward.
+ *
+ * This function automatically skips the empty lines and do not include the line return in result value.
+ *
+ * @param resource $file The file resource, with the pointer placed at the end of the line to read
+ *
+ * @return mixed A string representing the line or null if beginning of file is reached
+ */
+ protected function readLineFromFile($file)
+ {
+ $line = '';
+ $position = ftell($file);
+
+ if (0 === $position) {
+ return;
+ }
+
+ while (true) {
+ $chunkSize = min($position, 1024);
+ $position -= $chunkSize;
+ fseek($file, $position);
+
+ if (0 === $chunkSize) {
+ // bof reached
+ break;
+ }
+
+ $buffer = fread($file, $chunkSize);
+
+ if (false === ($upTo = strrpos($buffer, "\n"))) {
+ $line = $buffer.$line;
+ continue;
+ }
+
+ $position += $upTo;
+ $line = substr($buffer, $upTo + 1).$line;
+ fseek($file, max(0, $position), SEEK_SET);
+
+ if ('' !== $line) {
+ break;
+ }
+ }
+
+ return '' === $line ? null : $line;
+ }
+
+ protected function createProfileFromData($token, $data, $parent = null)
+ {
+ $profile = new Profile($token);
+ $profile->setIp($data['ip']);
+ $profile->setMethod($data['method']);
+ $profile->setUrl($data['url']);
+ $profile->setTime($data['time']);
+ $profile->setStatusCode($data['status_code']);
+ $profile->setCollectors($data['data']);
+
+ if (!$parent && $data['parent']) {
+ $parent = $this->read($data['parent']);
+ }
+
+ if ($parent) {
+ $profile->setParent($parent);
+ }
+
+ foreach ($data['children'] as $token) {
+ if (!$token || !file_exists($file = $this->getFilename($token))) {
+ continue;
+ }
+
+ $profile->addChild($this->createProfileFromData($token, unserialize(file_get_contents($file)), $profile));
+ }
+
+ return $profile;
+ }
+}
diff --git a/vendor/symfony/http-kernel/Profiler/Profile.php b/vendor/symfony/http-kernel/Profiler/Profile.php
new file mode 100644
index 0000000000..fab8b41da4
--- /dev/null
+++ b/vendor/symfony/http-kernel/Profiler/Profile.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\HttpKernel\Profiler;
+
+use Symfony\Component\HttpKernel\DataCollector\DataCollectorInterface;
+
+/**
+ * Profile.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+class Profile
+{
+ private $token;
+
+ /**
+ * @var DataCollectorInterface[]
+ */
+ private $collectors = array();
+
+ private $ip;
+ private $method;
+ private $url;
+ private $time;
+ private $statusCode;
+
+ /**
+ * @var Profile
+ */
+ private $parent;
+
+ /**
+ * @var Profile[]
+ */
+ private $children = array();
+
+ /**
+ * Constructor.
+ *
+ * @param string $token The token
+ */
+ public function __construct($token)
+ {
+ $this->token = $token;
+ }
+
+ /**
+ * Sets the token.
+ *
+ * @param string $token The token
+ */
+ public function setToken($token)
+ {
+ $this->token = $token;
+ }
+
+ /**
+ * Gets the token.
+ *
+ * @return string The token
+ */
+ public function getToken()
+ {
+ return $this->token;
+ }
+
+ /**
+ * Sets the parent token.
+ *
+ * @param Profile $parent
+ */
+ public function setParent(Profile $parent)
+ {
+ $this->parent = $parent;
+ }
+
+ /**
+ * Returns the parent profile.
+ *
+ * @return self
+ */
+ public function getParent()
+ {
+ return $this->parent;
+ }
+
+ /**
+ * Returns the parent token.
+ *
+ * @return null|string The parent token
+ */
+ public function getParentToken()
+ {
+ return $this->parent ? $this->parent->getToken() : null;
+ }
+
+ /**
+ * Returns the IP.
+ *
+ * @return string The IP
+ */
+ public function getIp()
+ {
+ return $this->ip;
+ }
+
+ /**
+ * Sets the IP.
+ *
+ * @param string $ip
+ */
+ public function setIp($ip)
+ {
+ $this->ip = $ip;
+ }
+
+ /**
+ * Returns the request method.
+ *
+ * @return string The request method
+ */
+ public function getMethod()
+ {
+ return $this->method;
+ }
+
+ public function setMethod($method)
+ {
+ $this->method = $method;
+ }
+
+ /**
+ * Returns the URL.
+ *
+ * @return string The URL
+ */
+ public function getUrl()
+ {
+ return $this->url;
+ }
+
+ public function setUrl($url)
+ {
+ $this->url = $url;
+ }
+
+ /**
+ * Returns the time.
+ *
+ * @return int The time
+ */
+ public function getTime()
+ {
+ if (null === $this->time) {
+ return 0;
+ }
+
+ return $this->time;
+ }
+
+ /**
+ * @param int The time
+ */
+ public function setTime($time)
+ {
+ $this->time = $time;
+ }
+
+ /**
+ * @param int $statusCode
+ */
+ public function setStatusCode($statusCode)
+ {
+ $this->statusCode = $statusCode;
+ }
+
+ /**
+ * @return int
+ */
+ public function getStatusCode()
+ {
+ return $this->statusCode;
+ }
+
+ /**
+ * Finds children profilers.
+ *
+ * @return self[]
+ */
+ public function getChildren()
+ {
+ return $this->children;
+ }
+
+ /**
+ * Sets children profiler.
+ *
+ * @param Profile[] $children
+ */
+ public function setChildren(array $children)
+ {
+ $this->children = array();
+ foreach ($children as $child) {
+ $this->addChild($child);
+ }
+ }
+
+ /**
+ * Adds the child token.
+ *
+ * @param Profile $child
+ */
+ public function addChild(Profile $child)
+ {
+ $this->children[] = $child;
+ $child->setParent($this);
+ }
+
+ /**
+ * Gets a Collector by name.
+ *
+ * @param string $name A collector name
+ *
+ * @return DataCollectorInterface A DataCollectorInterface instance
+ *
+ * @throws \InvalidArgumentException if the collector does not exist
+ */
+ public function getCollector($name)
+ {
+ if (!isset($this->collectors[$name])) {
+ throw new \InvalidArgumentException(sprintf('Collector "%s" does not exist.', $name));
+ }
+
+ return $this->collectors[$name];
+ }
+
+ /**
+ * Gets the Collectors associated with this profile.
+ *
+ * @return DataCollectorInterface[]
+ */
+ public function getCollectors()
+ {
+ return $this->collectors;
+ }
+
+ /**
+ * Sets the Collectors associated with this profile.
+ *
+ * @param DataCollectorInterface[] $collectors
+ */
+ public function setCollectors(array $collectors)
+ {
+ $this->collectors = array();
+ foreach ($collectors as $collector) {
+ $this->addCollector($collector);
+ }
+ }
+
+ /**
+ * Adds a Collector.
+ *
+ * @param DataCollectorInterface $collector A DataCollectorInterface instance
+ */
+ public function addCollector(DataCollectorInterface $collector)
+ {
+ $this->collectors[$collector->getName()] = $collector;
+ }
+
+ /**
+ * Returns true if a Collector for the given name exists.
+ *
+ * @param string $name A collector name
+ *
+ * @return bool
+ */
+ public function hasCollector($name)
+ {
+ return isset($this->collectors[$name]);
+ }
+
+ public function __sleep()
+ {
+ return array('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
new file mode 100644
index 0000000000..f31e243770
--- /dev/null
+++ b/vendor/symfony/http-kernel/Profiler/Profiler.php
@@ -0,0 +1,270 @@
+<?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\Profiler;
+
+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;
+
+/**
+ * Profiler.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+class Profiler
+{
+ /**
+ * @var ProfilerStorageInterface
+ */
+ private $storage;
+
+ /**
+ * @var DataCollectorInterface[]
+ */
+ private $collectors = array();
+
+ /**
+ * @var LoggerInterface
+ */
+ private $logger;
+
+ /**
+ * @var bool
+ */
+ private $enabled = true;
+
+ /**
+ * Constructor.
+ *
+ * @param ProfilerStorageInterface $storage A ProfilerStorageInterface instance
+ * @param LoggerInterface $logger A LoggerInterface instance
+ */
+ public function __construct(ProfilerStorageInterface $storage, LoggerInterface $logger = null)
+ {
+ $this->storage = $storage;
+ $this->logger = $logger;
+ }
+
+ /**
+ * Disables the profiler.
+ */
+ public function disable()
+ {
+ $this->enabled = false;
+ }
+
+ /**
+ * Enables the profiler.
+ */
+ public function enable()
+ {
+ $this->enabled = true;
+ }
+
+ /**
+ * Loads the Profile for the given Response.
+ *
+ * @param Response $response A Response instance
+ *
+ * @return Profile|false A Profile instance
+ */
+ public function loadProfileFromResponse(Response $response)
+ {
+ if (!$token = $response->headers->get('X-Debug-Token')) {
+ return false;
+ }
+
+ return $this->loadProfile($token);
+ }
+
+ /**
+ * Loads the Profile for the given token.
+ *
+ * @param string $token A token
+ *
+ * @return Profile A Profile instance
+ */
+ public function loadProfile($token)
+ {
+ return $this->storage->read($token);
+ }
+
+ /**
+ * Saves a Profile.
+ *
+ * @param Profile $profile A Profile instance
+ *
+ * @return bool
+ */
+ public function saveProfile(Profile $profile)
+ {
+ // late collect
+ foreach ($profile->getCollectors() as $collector) {
+ if ($collector instanceof LateDataCollectorInterface) {
+ $collector->lateCollect();
+ }
+ }
+
+ 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)));
+ }
+
+ return $ret;
+ }
+
+ /**
+ * Purges all data from the storage.
+ */
+ public function purge()
+ {
+ $this->storage->purge();
+ }
+
+ /**
+ * Finds profiler tokens for the given criteria.
+ *
+ * @param string $ip The IP
+ * @param string $url The URL
+ * @param string $limit The maximum number of tokens to return
+ * @param string $method The request method
+ * @param string $start The start date to search from
+ * @param string $end The end date to search to
+ * @param string $statusCode The request status code
+ *
+ * @return array An array of tokens
+ *
+ * @see http://php.net/manual/en/datetime.formats.php for the supported date/time formats
+ */
+ public function find($ip, $url, $limit, $method, $start, $end, $statusCode = null)
+ {
+ return $this->storage->find($ip, $url, $limit, $method, $this->getTimestamp($start), $this->getTimestamp($end), $statusCode);
+ }
+
+ /**
+ * Collects data for the given Response.
+ *
+ * @param Request $request A Request instance
+ * @param Response $response A Response instance
+ * @param \Exception $exception An exception instance if the request threw one
+ *
+ * @return Profile|null A Profile instance or null if the profiler is disabled
+ */
+ public function collect(Request $request, Response $response, \Exception $exception = null)
+ {
+ if (false === $this->enabled) {
+ return;
+ }
+
+ $profile = new Profile(substr(hash('sha256', uniqid(mt_rand(), true)), 0, 6));
+ $profile->setTime(time());
+ $profile->setUrl($request->getUri());
+ $profile->setMethod($request->getMethod());
+ $profile->setStatusCode($response->getStatusCode());
+ try {
+ $profile->setIp($request->getClientIp());
+ } catch (ConflictingHeadersException $e) {
+ $profile->setIp('Unknown');
+ }
+
+ $response->headers->set('X-Debug-Token', $profile->getToken());
+
+ foreach ($this->collectors as $collector) {
+ $collector->collect($request, $response, $exception);
+
+ // we need to clone for sub-requests
+ $profile->addCollector(clone $collector);
+ }
+
+ return $profile;
+ }
+
+ /**
+ * Gets the Collectors associated with this profiler.
+ *
+ * @return array An array of collectors
+ */
+ public function all()
+ {
+ return $this->collectors;
+ }
+
+ /**
+ * Sets the Collectors associated with this profiler.
+ *
+ * @param DataCollectorInterface[] $collectors An array of collectors
+ */
+ public function set(array $collectors = array())
+ {
+ $this->collectors = array();
+ foreach ($collectors as $collector) {
+ $this->add($collector);
+ }
+ }
+
+ /**
+ * Adds a Collector.
+ *
+ * @param DataCollectorInterface $collector A DataCollectorInterface instance
+ */
+ public function add(DataCollectorInterface $collector)
+ {
+ $this->collectors[$collector->getName()] = $collector;
+ }
+
+ /**
+ * Returns true if a Collector for the given name exists.
+ *
+ * @param string $name A collector name
+ *
+ * @return bool
+ */
+ public function has($name)
+ {
+ return isset($this->collectors[$name]);
+ }
+
+ /**
+ * Gets a Collector by name.
+ *
+ * @param string $name A collector name
+ *
+ * @return DataCollectorInterface A DataCollectorInterface instance
+ *
+ * @throws \InvalidArgumentException if the collector does not exist
+ */
+ public function get($name)
+ {
+ if (!isset($this->collectors[$name])) {
+ throw new \InvalidArgumentException(sprintf('Collector "%s" does not exist.', $name));
+ }
+
+ return $this->collectors[$name];
+ }
+
+ private function getTimestamp($value)
+ {
+ if (null === $value || '' == $value) {
+ return;
+ }
+
+ try {
+ $value = new \DateTime(is_numeric($value) ? '@'.$value : $value);
+ } catch (\Exception $e) {
+ return;
+ }
+
+ return $value->getTimestamp();
+ }
+}
diff --git a/vendor/symfony/http-kernel/Profiler/ProfilerStorageInterface.php b/vendor/symfony/http-kernel/Profiler/ProfilerStorageInterface.php
new file mode 100644
index 0000000000..ea72af2314
--- /dev/null
+++ b/vendor/symfony/http-kernel/Profiler/ProfilerStorageInterface.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\HttpKernel\Profiler;
+
+/**
+ * ProfilerStorageInterface.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+interface ProfilerStorageInterface
+{
+ /**
+ * Finds profiler tokens for the given criteria.
+ *
+ * @param string $ip The IP
+ * @param string $url The URL
+ * @param string $limit The maximum number of tokens to return
+ * @param string $method The request method
+ * @param int|null $start The start date to search from
+ * @param int|null $end The end date to search to
+ *
+ * @return array An array of tokens
+ */
+ public function find($ip, $url, $limit, $method, $start = null, $end = null);
+
+ /**
+ * Reads data associated with the given token.
+ *
+ * The method returns false if the token does not exist in the storage.
+ *
+ * @param string $token A token
+ *
+ * @return Profile The profile associated with token
+ */
+ public function read($token);
+
+ /**
+ * Saves a Profile.
+ *
+ * @param Profile $profile A Profile instance
+ *
+ * @return bool Write operation successful
+ */
+ public function write(Profile $profile);
+
+ /**
+ * Purges all data from the database.
+ */
+ public function purge();
+}
diff --git a/vendor/symfony/http-kernel/README.md b/vendor/symfony/http-kernel/README.md
new file mode 100644
index 0000000000..cc5e74b6bc
--- /dev/null
+++ b/vendor/symfony/http-kernel/README.md
@@ -0,0 +1,16 @@
+HttpKernel Component
+====================
+
+The HttpKernel component provides a structured process for converting a Request
+into a Response by making use of the EventDispatcher component. It's flexible
+enough to create a full-stack framework (Symfony), a micro-framework (Silex) or
+an advanced CMS system (Drupal).
+
+Resources
+---------
+
+ * [Documentation](https://symfony.com/doc/current/components/http_kernel/index.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/http-kernel/TerminableInterface.php b/vendor/symfony/http-kernel/TerminableInterface.php
new file mode 100644
index 0000000000..d55a15b87e
--- /dev/null
+++ b/vendor/symfony/http-kernel/TerminableInterface.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\HttpKernel;
+
+use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\HttpFoundation\Response;
+
+/**
+ * Terminable extends the Kernel request/response cycle with dispatching a post
+ * response event after sending the response and before shutting down the kernel.
+ *
+ * @author Jordi Boggiano <j.boggiano@seld.be>
+ * @author Pierre Minnieur <pierre.minnieur@sensiolabs.de>
+ */
+interface TerminableInterface
+{
+ /**
+ * Terminates a request/response cycle.
+ *
+ * Should be called after sending the response and before shutting down the kernel.
+ *
+ * @param Request $request A Request instance
+ * @param Response $response A Response instance
+ */
+ public function terminate(Request $request, Response $response);
+}
diff --git a/vendor/symfony/http-kernel/Tests/Bundle/BundleTest.php b/vendor/symfony/http-kernel/Tests/Bundle/BundleTest.php
new file mode 100644
index 0000000000..eeefccab81
--- /dev/null
+++ b/vendor/symfony/http-kernel/Tests/Bundle/BundleTest.php
@@ -0,0 +1,100 @@
+<?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\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
+{
+ public function testGetContainerExtension()
+ {
+ $bundle = new ExtensionPresentBundle();
+
+ $this->assertInstanceOf(
+ 'Symfony\Component\HttpKernel\Tests\Fixtures\ExtensionPresentBundle\DependencyInjection\ExtensionPresentExtension',
+ $bundle->getContainerExtension()
+ );
+ }
+
+ 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()
+ {
+ $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();
+
+ $this->assertSame('Symfony\Component\HttpKernel\Tests\Bundle', $bundle->getNamespace());
+ $this->assertSame('GuessedNameBundle', $bundle->getName());
+ }
+
+ public function testBundleNameCanBeExplicitlyProvided()
+ {
+ $bundle = new NamedBundle();
+
+ $this->assertSame('ExplicitlyNamedBundle', $bundle->getName());
+ $this->assertSame('Symfony\Component\HttpKernel\Tests\Bundle', $bundle->getNamespace());
+ $this->assertSame('ExplicitlyNamedBundle', $bundle->getName());
+ }
+}
+
+class NamedBundle extends Bundle
+{
+ public function __construct()
+ {
+ $this->name = 'ExplicitlyNamedBundle';
+ }
+}
+
+class GuessedNameBundle extends Bundle
+{
+}
diff --git a/vendor/symfony/http-kernel/Tests/CacheClearer/ChainCacheClearerTest.php b/vendor/symfony/http-kernel/Tests/CacheClearer/ChainCacheClearerTest.php
new file mode 100644
index 0000000000..1bc853349f
--- /dev/null
+++ b/vendor/symfony/http-kernel/Tests/CacheClearer/ChainCacheClearerTest.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\Tests\CacheClearer;
+
+use PHPUnit\Framework\TestCase;
+use Symfony\Component\HttpKernel\CacheClearer\ChainCacheClearer;
+
+class ChainCacheClearerTest extends TestCase
+{
+ protected static $cacheDir;
+
+ public static function setUpBeforeClass()
+ {
+ self::$cacheDir = tempnam(sys_get_temp_dir(), 'sf2_cache_clearer_dir');
+ }
+
+ public static function tearDownAfterClass()
+ {
+ @unlink(self::$cacheDir);
+ }
+
+ public function testInjectClearersInConstructor()
+ {
+ $clearer = $this->getMockClearer();
+ $clearer
+ ->expects($this->once())
+ ->method('clear');
+
+ $chainClearer = new ChainCacheClearer(array($clearer));
+ $chainClearer->clear(self::$cacheDir);
+ }
+
+ public function testInjectClearerUsingAdd()
+ {
+ $clearer = $this->getMockClearer();
+ $clearer
+ ->expects($this->once())
+ ->method('clear');
+
+ $chainClearer = new ChainCacheClearer();
+ $chainClearer->add($clearer);
+ $chainClearer->clear(self::$cacheDir);
+ }
+
+ protected function getMockClearer()
+ {
+ return $this->getMockBuilder('Symfony\Component\HttpKernel\CacheClearer\CacheClearerInterface')->getMock();
+ }
+}
diff --git a/vendor/symfony/http-kernel/Tests/CacheClearer/Psr6CacheClearerTest.php b/vendor/symfony/http-kernel/Tests/CacheClearer/Psr6CacheClearerTest.php
new file mode 100644
index 0000000000..a5d9b6ef4d
--- /dev/null
+++ b/vendor/symfony/http-kernel/Tests/CacheClearer/Psr6CacheClearerTest.php
@@ -0,0 +1,69 @@
+<?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\CacheClearer;
+
+use PHPUnit\Framework\TestCase;
+use Symfony\Component\HttpKernel\CacheClearer\Psr6CacheClearer;
+use Psr\Cache\CacheItemPoolInterface;
+
+class Psr6CacheClearerTest extends TestCase
+{
+ public function testClearPoolsInjectedInConstructor()
+ {
+ $pool = $this->getMockBuilder(CacheItemPoolInterface::class)->getMock();
+ $pool
+ ->expects($this->once())
+ ->method('clear');
+
+ (new Psr6CacheClearer(array('pool' => $pool)))->clear('');
+ }
+
+ public function testClearPool()
+ {
+ $pool = $this->getMockBuilder(CacheItemPoolInterface::class)->getMock();
+ $pool
+ ->expects($this->once())
+ ->method('clear');
+
+ (new Psr6CacheClearer(array('pool' => $pool)))->clearPool('pool');
+ }
+
+ /**
+ * @expectedException \InvalidArgumentException
+ * @expectedExceptionMessage Cache pool not found: unknown
+ */
+ public function testClearPoolThrowsExceptionOnUnreferencedPool()
+ {
+ (new Psr6CacheClearer())->clearPool('unknown');
+ }
+
+ /**
+ * @group legacy
+ * @expectedDeprecation The Symfony\Component\HttpKernel\CacheClearer\Psr6CacheClearer::addPool() method is deprecated since version 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
new file mode 100644
index 0000000000..d07ade303f
--- /dev/null
+++ b/vendor/symfony/http-kernel/Tests/CacheWarmer/CacheWarmerAggregateTest.php
@@ -0,0 +1,101 @@
+<?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\CacheWarmer;
+
+use PHPUnit\Framework\TestCase;
+use Symfony\Component\HttpKernel\CacheWarmer\CacheWarmerAggregate;
+
+class CacheWarmerAggregateTest extends TestCase
+{
+ protected static $cacheDir;
+
+ public static function setUpBeforeClass()
+ {
+ self::$cacheDir = tempnam(sys_get_temp_dir(), 'sf2_cache_warmer_dir');
+ }
+
+ public static function tearDownAfterClass()
+ {
+ @unlink(self::$cacheDir);
+ }
+
+ public function testInjectWarmersUsingConstructor()
+ {
+ $warmer = $this->getCacheWarmerMock();
+ $warmer
+ ->expects($this->once())
+ ->method('warmUp');
+ $aggregate = new CacheWarmerAggregate(array($warmer));
+ $aggregate->warmUp(self::$cacheDir);
+ }
+
+ public function testInjectWarmersUsingAdd()
+ {
+ $warmer = $this->getCacheWarmerMock();
+ $warmer
+ ->expects($this->once())
+ ->method('warmUp');
+ $aggregate = new CacheWarmerAggregate();
+ $aggregate->add($warmer);
+ $aggregate->warmUp(self::$cacheDir);
+ }
+
+ public function testInjectWarmersUsingSetWarmers()
+ {
+ $warmer = $this->getCacheWarmerMock();
+ $warmer
+ ->expects($this->once())
+ ->method('warmUp');
+ $aggregate = new CacheWarmerAggregate();
+ $aggregate->setWarmers(array($warmer));
+ $aggregate->warmUp(self::$cacheDir);
+ }
+
+ public function testWarmupDoesCallWarmupOnOptionalWarmersWhenEnableOptionalWarmersIsEnabled()
+ {
+ $warmer = $this->getCacheWarmerMock();
+ $warmer
+ ->expects($this->never())
+ ->method('isOptional');
+ $warmer
+ ->expects($this->once())
+ ->method('warmUp');
+
+ $aggregate = new CacheWarmerAggregate(array($warmer));
+ $aggregate->enableOptionalWarmers();
+ $aggregate->warmUp(self::$cacheDir);
+ }
+
+ public function testWarmupDoesNotCallWarmupOnOptionalWarmersWhenEnableOptionalWarmersIsNotEnabled()
+ {
+ $warmer = $this->getCacheWarmerMock();
+ $warmer
+ ->expects($this->once())
+ ->method('isOptional')
+ ->will($this->returnValue(true));
+ $warmer
+ ->expects($this->never())
+ ->method('warmUp');
+
+ $aggregate = new CacheWarmerAggregate(array($warmer));
+ $aggregate->warmUp(self::$cacheDir);
+ }
+
+ protected function getCacheWarmerMock()
+ {
+ $warmer = $this->getMockBuilder('Symfony\Component\HttpKernel\CacheWarmer\CacheWarmerInterface')
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ return $warmer;
+ }
+}
diff --git a/vendor/symfony/http-kernel/Tests/CacheWarmer/CacheWarmerTest.php b/vendor/symfony/http-kernel/Tests/CacheWarmer/CacheWarmerTest.php
new file mode 100644
index 0000000000..05666cb0dc
--- /dev/null
+++ b/vendor/symfony/http-kernel/Tests/CacheWarmer/CacheWarmerTest.php
@@ -0,0 +1,68 @@
+<?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\CacheWarmer;
+
+use PHPUnit\Framework\TestCase;
+use Symfony\Component\HttpKernel\CacheWarmer\CacheWarmer;
+
+class CacheWarmerTest extends TestCase
+{
+ protected static $cacheFile;
+
+ public static function setUpBeforeClass()
+ {
+ self::$cacheFile = tempnam(sys_get_temp_dir(), 'sf2_cache_warmer_dir');
+ }
+
+ public static function tearDownAfterClass()
+ {
+ @unlink(self::$cacheFile);
+ }
+
+ public function testWriteCacheFileCreatesTheFile()
+ {
+ $warmer = new TestCacheWarmer(self::$cacheFile);
+ $warmer->warmUp(dirname(self::$cacheFile));
+
+ $this->assertFileExists(self::$cacheFile);
+ }
+
+ /**
+ * @expectedException \RuntimeException
+ */
+ public function testWriteNonWritableCacheFileThrowsARuntimeException()
+ {
+ $nonWritableFile = '/this/file/is/very/probably/not/writable';
+ $warmer = new TestCacheWarmer($nonWritableFile);
+ $warmer->warmUp(dirname($nonWritableFile));
+ }
+}
+
+class TestCacheWarmer extends CacheWarmer
+{
+ protected $file;
+
+ public function __construct($file)
+ {
+ $this->file = $file;
+ }
+
+ public function warmUp($cacheDir)
+ {
+ $this->writeCacheFile($this->file, 'content');
+ }
+
+ public function isOptional()
+ {
+ return false;
+ }
+}
diff --git a/vendor/symfony/http-kernel/Tests/ClientTest.php b/vendor/symfony/http-kernel/Tests/ClientTest.php
new file mode 100644
index 0000000000..1ac72c7359
--- /dev/null
+++ b/vendor/symfony/http-kernel/Tests/ClientTest.php
@@ -0,0 +1,183 @@
+<?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;
+
+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\HttpKernel\Tests\Fixtures\TestClient;
+
+/**
+ * @group time-sensitive
+ */
+class ClientTest extends TestCase
+{
+ public function testDoRequest()
+ {
+ $client = new Client(new TestHttpKernel());
+
+ $client->request('GET', '/');
+ $this->assertEquals('Request: /', $client->getResponse()->getContent(), '->doRequest() uses the request handler to make the request');
+ $this->assertInstanceOf('Symfony\Component\BrowserKit\Request', $client->getInternalRequest());
+ $this->assertInstanceOf('Symfony\Component\HttpFoundation\Request', $client->getRequest());
+ $this->assertInstanceOf('Symfony\Component\BrowserKit\Response', $client->getInternalResponse());
+ $this->assertInstanceOf('Symfony\Component\HttpFoundation\Response', $client->getResponse());
+
+ $client->request('GET', 'http://www.example.com/');
+ $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');
+ }
+
+ public function testGetScript()
+ {
+ $client = new TestClient(new TestHttpKernel());
+ $client->insulate();
+ $client->request('GET', '/');
+
+ $this->assertEquals('Request: /', $client->getResponse()->getContent(), '->getScript() returns a script that uses the request handler to make the request');
+ }
+
+ public function testFilterResponseConvertsCookies()
+ {
+ $client = new Client(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));
+ $domResponse = $m->invoke($client, $response);
+ $this->assertEquals($expected[0], $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));
+ $domResponse = $m->invoke($client, $response);
+ $this->assertEquals($expected[0], $domResponse->getHeader('Set-Cookie'));
+ $this->assertEquals($expected, $domResponse->getHeader('Set-Cookie', false));
+ }
+
+ public function testFilterResponseSupportsStreamedResponses()
+ {
+ $client = new Client(new TestHttpKernel());
+
+ $r = new \ReflectionObject($client);
+ $m = $r->getMethod('filterResponse');
+ $m->setAccessible(true);
+
+ $response = new StreamedResponse(function () {
+ echo 'foo';
+ });
+
+ $domResponse = $m->invoke($client, $response);
+ $this->assertEquals('foo', $domResponse->getContent());
+ }
+
+ public function testUploadedFile()
+ {
+ $source = tempnam(sys_get_temp_dir(), 'source');
+ $target = sys_get_temp_dir().'/sf.moved.file';
+ @unlink($target);
+
+ $kernel = new TestHttpKernel();
+ $client = new Client($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),
+ );
+
+ $file = null;
+ foreach ($files as $file) {
+ $client->request('POST', '/', array(), array('foo' => $file));
+
+ $files = $client->getRequest()->files->all();
+
+ $this->assertCount(1, $files);
+
+ $file = $files['foo'];
+
+ $this->assertEquals('original', $file->getClientOriginalName());
+ $this->assertEquals('mime/original', $file->getClientMimeType());
+ $this->assertEquals('123', $file->getClientSize());
+ $this->assertTrue($file->isValid());
+ }
+
+ $file->move(dirname($target), basename($target));
+
+ $this->assertFileExists($target);
+ unlink($target);
+ }
+
+ public function testUploadedFileWhenNoFileSelected()
+ {
+ $kernel = new TestHttpKernel();
+ $client = new Client($kernel);
+
+ $file = array('tmp_name' => '', 'name' => '', 'type' => '', 'size' => 0, 'error' => UPLOAD_ERR_NO_FILE);
+
+ $client->request('POST', '/', array(), array('foo' => $file));
+
+ $files = $client->getRequest()->files->all();
+
+ $this->assertCount(1, $files);
+ $this->assertNull($files['foo']);
+ }
+
+ public function testUploadedFileWhenSizeExceedsUploadMaxFileSize()
+ {
+ $source = tempnam(sys_get_temp_dir(), 'source');
+
+ $kernel = new TestHttpKernel();
+ $client = new Client($kernel);
+
+ $file = $this
+ ->getMockBuilder('Symfony\Component\HttpFoundation\File\UploadedFile')
+ ->setConstructorArgs(array($source, 'original', 'mime/original', 123, UPLOAD_ERR_OK, true))
+ ->setMethods(array('getSize'))
+ ->getMock()
+ ;
+
+ $file->expects($this->once())
+ ->method('getSize')
+ ->will($this->returnValue(INF))
+ ;
+
+ $client->request('POST', '/', array(), array($file));
+
+ $files = $client->getRequest()->files->all();
+
+ $this->assertCount(1, $files);
+
+ $file = $files[0];
+
+ $this->assertFalse($file->isValid());
+ $this->assertEquals(UPLOAD_ERR_INI_SIZE, $file->getError());
+ $this->assertEquals('mime/original', $file->getClientMimeType());
+ $this->assertEquals('original', $file->getClientOriginalName());
+ $this->assertEquals(0, $file->getClientSize());
+
+ unlink($source);
+ }
+}
diff --git a/vendor/symfony/http-kernel/Tests/Config/EnvParametersResourceTest.php b/vendor/symfony/http-kernel/Tests/Config/EnvParametersResourceTest.php
new file mode 100644
index 0000000000..6fe8a67568
--- /dev/null
+++ b/vendor/symfony/http-kernel/Tests/Config/EnvParametersResourceTest.php
@@ -0,0 +1,107 @@
+<?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;
+
+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
new file mode 100644
index 0000000000..6265f02755
--- /dev/null
+++ b/vendor/symfony/http-kernel/Tests/Config/FileLocatorTest.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\HttpKernel\Tests\Config;
+
+use PHPUnit\Framework\TestCase;
+use Symfony\Component\HttpKernel\Config\FileLocator;
+
+class FileLocatorTest extends TestCase
+{
+ public function testLocate()
+ {
+ $kernel = $this->getMockBuilder('Symfony\Component\HttpKernel\KernelInterface')->getMock();
+ $kernel
+ ->expects($this->atLeastOnce())
+ ->method('locateResource')
+ ->with('@BundleName/some/path', null, true)
+ ->will($this->returnValue('/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');
+ $locator->locate('/some/path');
+ }
+
+ public function testLocateWithGlobalResourcePath()
+ {
+ $kernel = $this->getMockBuilder('Symfony\Component\HttpKernel\KernelInterface')->getMock();
+ $kernel
+ ->expects($this->atLeastOnce())
+ ->method('locateResource')
+ ->with('@BundleName/some/path', '/global/resource/path', false);
+
+ $locator = new FileLocator($kernel, '/global/resource/path');
+ $locator->locate('@BundleName/some/path', null, false);
+ }
+}
diff --git a/vendor/symfony/http-kernel/Tests/Controller/ArgumentResolverTest.php b/vendor/symfony/http-kernel/Tests/Controller/ArgumentResolverTest.php
new file mode 100644
index 0000000000..0804139030
--- /dev/null
+++ b/vendor/symfony/http-kernel/Tests/Controller/ArgumentResolverTest.php
@@ -0,0 +1,349 @@
+<?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;
+
+use PHPUnit\Framework\TestCase;
+use Symfony\Component\HttpFoundation\Session\Session;
+use Symfony\Component\HttpFoundation\Session\SessionInterface;
+use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage;
+use Symfony\Component\HttpKernel\Controller\ArgumentResolver;
+use Symfony\Component\HttpKernel\Controller\ArgumentResolver\RequestAttributeValueResolver;
+use Symfony\Component\HttpKernel\Controller\ArgumentValueResolverInterface;
+use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadataFactory;
+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()
+ {
+ $factory = new ArgumentMetadataFactory();
+
+ self::$resolver = new ArgumentResolver($factory);
+ }
+
+ public function testDefaultState()
+ {
+ $this->assertEquals(self::$resolver, new ArgumentResolver());
+ $this->assertNotEquals(self::$resolver, new ArgumentResolver(null, array(new RequestAttributeValueResolver())));
+ }
+
+ public function testGetArguments()
+ {
+ $request = Request::create('/');
+ $request->attributes->set('foo', 'foo');
+ $controller = array(new self(), 'controllerWithFoo');
+
+ $this->assertEquals(array('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');
+
+ $this->assertEquals(array(), 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');
+
+ $this->assertEquals(array('foo', null), self::$resolver->getArguments($request, $controller), '->getArguments() uses default values if present');
+ }
+
+ public function testGetArgumentsOverrideDefaultValueByRequestAttribute()
+ {
+ $request = Request::create('/');
+ $request->attributes->set('foo', 'foo');
+ $request->attributes->set('bar', 'bar');
+ $controller = array(new self(), 'controllerWithFooAndDefaultBar');
+
+ $this->assertEquals(array('foo', 'bar'), self::$resolver->getArguments($request, $controller), '->getArguments() overrides default values if provided in the request attributes');
+ }
+
+ public function testGetArgumentsFromClosure()
+ {
+ $request = Request::create('/');
+ $request->attributes->set('foo', 'foo');
+ $controller = function ($foo) {};
+
+ $this->assertEquals(array('foo'), self::$resolver->getArguments($request, $controller));
+ }
+
+ public function testGetArgumentsUsesDefaultValueFromClosure()
+ {
+ $request = Request::create('/');
+ $request->attributes->set('foo', 'foo');
+ $controller = function ($foo, $bar = 'bar') {};
+
+ $this->assertEquals(array('foo', 'bar'), self::$resolver->getArguments($request, $controller));
+ }
+
+ public function testGetArgumentsFromInvokableObject()
+ {
+ $request = Request::create('/');
+ $request->attributes->set('foo', 'foo');
+ $controller = new self();
+
+ $this->assertEquals(array('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));
+ }
+
+ public function testGetArgumentsFromFunctionName()
+ {
+ $request = Request::create('/');
+ $request->attributes->set('foo', 'foo');
+ $request->attributes->set('foobar', 'foobar');
+ $controller = __NAMESPACE__.'\controller_function';
+
+ $this->assertEquals(array('foo', 'foobar'), self::$resolver->getArguments($request, $controller));
+ }
+
+ public function testGetArgumentsFailsOnUnresolvedValue()
+ {
+ $request = Request::create('/');
+ $request->attributes->set('foo', 'foo');
+ $request->attributes->set('foobar', 'foobar');
+ $controller = array(new self(), 'controllerWithFooBarFoobar');
+
+ try {
+ self::$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');
+ }
+ }
+
+ public function testGetArgumentsInjectsRequest()
+ {
+ $request = Request::create('/');
+ $controller = array(new self(), 'controllerWithRequest');
+
+ $this->assertEquals(array($request), self::$resolver->getArguments($request, $controller), '->getArguments() injects the request');
+ }
+
+ public function testGetArgumentsInjectsExtendingRequest()
+ {
+ $request = ExtendingRequest::create('/');
+ $controller = array(new self(), 'controllerWithExtendingRequest');
+
+ $this->assertEquals(array($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');
+
+ $this->assertEquals(array('foo', 'foo', 'bar'), self::$resolver->getArguments($request, $controller));
+ }
+
+ /**
+ * @requires PHP 5.6
+ * @expectedException \InvalidArgumentException
+ */
+ public function testGetVariadicArgumentsWithoutArrayInRequest()
+ {
+ $request = Request::create('/');
+ $request->attributes->set('foo', 'foo');
+ $request->attributes->set('bar', 'foo');
+ $controller = array(new VariadicController(), 'action');
+
+ self::$resolver->getArguments($request, $controller);
+ }
+
+ /**
+ * @requires PHP 5.6
+ * @expectedException \InvalidArgumentException
+ */
+ public function testGetArgumentWithoutArray()
+ {
+ $factory = new ArgumentMetadataFactory();
+ $valueResolver = $this->getMockBuilder(ArgumentValueResolverInterface::class)->getMock();
+ $resolver = new ArgumentResolver($factory, array($valueResolver));
+
+ $valueResolver->expects($this->any())->method('supports')->willReturn(true);
+ $valueResolver->expects($this->any())->method('resolve')->willReturn('foo');
+
+ $request = Request::create('/');
+ $request->attributes->set('foo', 'foo');
+ $request->attributes->set('bar', 'foo');
+ $controller = array($this, 'controllerWithFooAndDefaultBar');
+ $resolver->getArguments($request, $controller);
+ }
+
+ /**
+ * @expectedException \RuntimeException
+ */
+ public function testIfExceptionIsThrownWhenMissingAnArgument()
+ {
+ $request = Request::create('/');
+ $controller = array($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');
+
+ $this->assertEquals(array('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');
+
+ $this->assertEquals(array(null, null, 'value', 'mandatory'), self::$resolver->getArguments($request, $controller));
+ }
+
+ public function testGetSessionArguments()
+ {
+ $session = new Session(new MockArraySessionStorage());
+ $request = Request::create('/');
+ $request->setSession($session);
+ $controller = array($this, 'controllerWithSession');
+
+ $this->assertEquals(array($session), self::$resolver->getArguments($request, $controller));
+ }
+
+ public function testGetSessionArgumentsWithExtendedSession()
+ {
+ $session = new ExtendingSession(new MockArraySessionStorage());
+ $request = Request::create('/');
+ $request->setSession($session);
+ $controller = array($this, 'controllerWithExtendingSession');
+
+ $this->assertEquals(array($session), self::$resolver->getArguments($request, $controller));
+ }
+
+ public function testGetSessionArgumentsWithInterface()
+ {
+ $session = $this->getMockBuilder(SessionInterface::class)->getMock();
+ $request = Request::create('/');
+ $request->setSession($session);
+ $controller = array($this, 'controllerWithSessionInterface');
+
+ $this->assertEquals(array($session), self::$resolver->getArguments($request, $controller));
+ }
+
+ /**
+ * @expectedException \RuntimeException
+ */
+ public function testGetSessionMissMatchWithInterface()
+ {
+ $session = $this->getMockBuilder(SessionInterface::class)->getMock();
+ $request = Request::create('/');
+ $request->setSession($session);
+ $controller = array($this, 'controllerWithExtendingSession');
+
+ self::$resolver->getArguments($request, $controller);
+ }
+
+ /**
+ * @expectedException \RuntimeException
+ */
+ public function testGetSessionMissMatchWithImplementation()
+ {
+ $session = new Session(new MockArraySessionStorage());
+ $request = Request::create('/');
+ $request->setSession($session);
+ $controller = array($this, 'controllerWithExtendingSession');
+
+ self::$resolver->getArguments($request, $controller);
+ }
+
+ /**
+ * @expectedException \RuntimeException
+ */
+ public function testGetSessionMissMatchOnNull()
+ {
+ $request = Request::create('/');
+ $controller = array($this, 'controllerWithExtendingSession');
+
+ self::$resolver->getArguments($request, $controller);
+ }
+
+ public function __invoke($foo, $bar = null)
+ {
+ }
+
+ public function controllerWithFoo($foo)
+ {
+ }
+
+ public function controllerWithoutArguments()
+ {
+ }
+
+ protected function controllerWithFooAndDefaultBar($foo, $bar = null)
+ {
+ }
+
+ protected function controllerWithFooBarFoobar($foo, $bar, $foobar)
+ {
+ }
+
+ protected function controllerWithRequest(Request $request)
+ {
+ }
+
+ protected function controllerWithExtendingRequest(ExtendingRequest $request)
+ {
+ }
+
+ protected function controllerWithSession(Session $session)
+ {
+ }
+
+ protected function controllerWithSessionInterface(SessionInterface $session)
+ {
+ }
+
+ protected function controllerWithExtendingSession(ExtendingSession $session)
+ {
+ }
+}
+
+function controller_function($foo, $foobar)
+{
+}
diff --git a/vendor/symfony/http-kernel/Tests/Controller/ContainerControllerResolverTest.php b/vendor/symfony/http-kernel/Tests/Controller/ContainerControllerResolverTest.php
new file mode 100644
index 0000000000..30b535e825
--- /dev/null
+++ b/vendor/symfony/http-kernel/Tests/Controller/ContainerControllerResolverTest.php
@@ -0,0 +1,148 @@
+<?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;
+
+use Psr\Container\ContainerInterface;
+use Psr\Log\LoggerInterface;
+use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\HttpKernel\Controller\ContainerControllerResolver;
+
+class ContainerControllerResolverTest extends ControllerResolverTest
+{
+ public function testGetControllerService()
+ {
+ $container = $this->createMockContainer();
+ $container->expects($this->once())
+ ->method('get')
+ ->with('foo')
+ ->will($this->returnValue($this))
+ ;
+
+ $resolver = $this->createControllerResolver(null, $container);
+ $request = Request::create('/');
+ $request->attributes->set('_controller', 'foo:controllerMethod1');
+
+ $controller = $resolver->getController($request);
+
+ $this->assertInstanceOf(get_class($this), $controller[0]);
+ $this->assertSame('controllerMethod1', $controller[1]);
+ }
+
+ public function testGetControllerInvokableService()
+ {
+ $invokableController = new InvokableController('bar');
+
+ $container = $this->createMockContainer();
+ $container->expects($this->once())
+ ->method('has')
+ ->with('foo')
+ ->will($this->returnValue(true))
+ ;
+ $container->expects($this->once())
+ ->method('get')
+ ->with('foo')
+ ->will($this->returnValue($invokableController))
+ ;
+
+ $resolver = $this->createControllerResolver(null, $container);
+ $request = Request::create('/');
+ $request->attributes->set('_controller', 'foo');
+
+ $controller = $resolver->getController($request);
+
+ $this->assertEquals($invokableController, $controller);
+ }
+
+ public function testGetControllerInvokableServiceWithClassNameAsName()
+ {
+ $invokableController = new InvokableController('bar');
+ $className = __NAMESPACE__.'\InvokableController';
+
+ $container = $this->createMockContainer();
+ $container->expects($this->once())
+ ->method('has')
+ ->with($className)
+ ->will($this->returnValue(true))
+ ;
+ $container->expects($this->once())
+ ->method('get')
+ ->with($className)
+ ->will($this->returnValue($invokableController))
+ ;
+
+ $resolver = $this->createControllerResolver(null, $container);
+ $request = Request::create('/');
+ $request->attributes->set('_controller', $className);
+
+ $controller = $resolver->getController($request);
+
+ $this->assertEquals($invokableController, $controller);
+ }
+
+ /**
+ * @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, '/Unable to parse the controller name "foo"\./'),
+ array('oof::bar', \InvalidArgumentException::class, '/Class "oof" does not exist\./'),
+ array('stdClass', \LogicException::class, '/Unable to parse the controller name "stdClass"\./'),
+ array(
+ 'Symfony\Component\HttpKernel\Tests\Controller\ControllerResolverTest::bar',
+ \InvalidArgumentException::class,
+ '/.?[cC]ontroller(.*?) for URI "\/" is not callable\.( Expected method(.*) Available methods)?/',
+ ),
+ );
+ }
+
+ protected function createControllerResolver(LoggerInterface $logger = null, ContainerInterface $container = null)
+ {
+ if (!$container) {
+ $container = $this->createMockContainer();
+ }
+
+ return new ContainerControllerResolver($container, $logger);
+ }
+
+ protected function createMockContainer()
+ {
+ return $this->getMockBuilder(ContainerInterface::class)->getMock();
+ }
+}
+
+class InvokableController
+{
+ public function __construct($bar) // mandatory argument to prevent automatic instantiation
+ {
+ }
+
+ public function __invoke()
+ {
+ }
+}
diff --git a/vendor/symfony/http-kernel/Tests/Controller/ControllerResolverTest.php b/vendor/symfony/http-kernel/Tests/Controller/ControllerResolverTest.php
new file mode 100644
index 0000000000..190e15ad67
--- /dev/null
+++ b/vendor/symfony/http-kernel/Tests/Controller/ControllerResolverTest.php
@@ -0,0 +1,331 @@
+<?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;
+
+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;
+
+class ControllerResolverTest extends TestCase
+{
+ public function testGetControllerWithoutControllerParameter()
+ {
+ $logger = $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock();
+ $logger->expects($this->once())->method('warning')->with('Unable to look for the controller as the "_controller" parameter is missing.');
+ $resolver = $this->createControllerResolver($logger);
+
+ $request = Request::create('/');
+ $this->assertFalse($resolver->getController($request), '->getController() returns false when the request has no _controller attribute');
+ }
+
+ public function testGetControllerWithLambda()
+ {
+ $resolver = $this->createControllerResolver();
+
+ $request = Request::create('/');
+ $request->attributes->set('_controller', $lambda = function () {});
+ $controller = $resolver->getController($request);
+ $this->assertSame($lambda, $controller);
+ }
+
+ public function testGetControllerWithObjectAndInvokeMethod()
+ {
+ $resolver = $this->createControllerResolver();
+
+ $request = Request::create('/');
+ $request->attributes->set('_controller', $this);
+ $controller = $resolver->getController($request);
+ $this->assertSame($this, $controller);
+ }
+
+ public function testGetControllerWithObjectAndMethod()
+ {
+ $resolver = $this->createControllerResolver();
+
+ $request = Request::create('/');
+ $request->attributes->set('_controller', array($this, 'controllerMethod1'));
+ $controller = $resolver->getController($request);
+ $this->assertSame(array($this, 'controllerMethod1'), $controller);
+ }
+
+ public function testGetControllerWithClassAndMethod()
+ {
+ $resolver = $this->createControllerResolver();
+
+ $request = Request::create('/');
+ $request->attributes->set('_controller', array('Symfony\Component\HttpKernel\Tests\Controller\ControllerResolverTest', 'controllerMethod4'));
+ $controller = $resolver->getController($request);
+ $this->assertSame(array('Symfony\Component\HttpKernel\Tests\Controller\ControllerResolverTest', 'controllerMethod4'), $controller);
+ }
+
+ public function testGetControllerWithObjectAndMethodAsString()
+ {
+ $resolver = $this->createControllerResolver();
+
+ $request = Request::create('/');
+ $request->attributes->set('_controller', 'Symfony\Component\HttpKernel\Tests\Controller\ControllerResolverTest::controllerMethod1');
+ $controller = $resolver->getController($request);
+ $this->assertInstanceOf('Symfony\Component\HttpKernel\Tests\Controller\ControllerResolverTest', $controller[0], '->getController() returns a PHP callable');
+ }
+
+ public function testGetControllerWithClassAndInvokeMethod()
+ {
+ $resolver = $this->createControllerResolver();
+
+ $request = Request::create('/');
+ $request->attributes->set('_controller', 'Symfony\Component\HttpKernel\Tests\Controller\ControllerResolverTest');
+ $controller = $resolver->getController($request);
+ $this->assertInstanceOf('Symfony\Component\HttpKernel\Tests\Controller\ControllerResolverTest', $controller);
+ }
+
+ /**
+ * @expectedException \InvalidArgumentException
+ */
+ public function testGetControllerOnObjectWithoutInvokeMethod()
+ {
+ $resolver = $this->createControllerResolver();
+
+ $request = Request::create('/');
+ $request->attributes->set('_controller', new \stdClass());
+ $resolver->getController($request);
+ }
+
+ public function testGetControllerWithFunction()
+ {
+ $resolver = $this->createControllerResolver();
+
+ $request = Request::create('/');
+ $request->attributes->set('_controller', 'Symfony\Component\HttpKernel\Tests\Controller\some_controller_function');
+ $controller = $resolver->getController($request);
+ $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()
+ {
+ $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');
+
+ $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');
+ }
+
+ /**
+ * @requires PHP 5.6
+ * @group legacy
+ */
+ 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()
+ {
+ $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'));
+
+ $request = Request::create('/');
+ $request->attributes->set('_controller', 'foobar');
+ $mock->getController($request);
+ }
+
+ /**
+ * @expectedException \RuntimeException
+ * @group legacy
+ */
+ public function testIfExceptionIsThrownWhenMissingAnArgument()
+ {
+ $resolver = new ControllerResolver();
+ $request = Request::create('/');
+
+ $controller = array($this, 'controllerMethod1');
+
+ $resolver->getArguments($request, $controller);
+ }
+
+ /**
+ * @requires PHP 7.1
+ * @group legacy
+ */
+ public function testGetNullableArguments()
+ {
+ $resolver = new ControllerResolver();
+
+ $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));
+ }
+
+ /**
+ * @requires PHP 7.1
+ * @group legacy
+ */
+ public function testGetNullableArgumentsWithDefaults()
+ {
+ $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));
+ }
+
+ protected function createControllerResolver(LoggerInterface $logger = null)
+ {
+ return new ControllerResolver($logger);
+ }
+
+ public function __invoke($foo, $bar = null)
+ {
+ }
+
+ public function controllerMethod1($foo)
+ {
+ }
+
+ protected function controllerMethod2($foo, $bar = null)
+ {
+ }
+
+ protected function controllerMethod3($foo, $bar, $foobar)
+ {
+ }
+
+ protected static function controllerMethod4()
+ {
+ }
+
+ protected function controllerMethod5(Request $request)
+ {
+ }
+}
+
+function some_controller_function($foo, $foobar)
+{
+}
+
+class ControllerTest
+{
+ public function publicAction()
+ {
+ }
+
+ private function privateAction()
+ {
+ }
+
+ protected function protectedAction()
+ {
+ }
+
+ public static function staticAction()
+ {
+ }
+}
diff --git a/vendor/symfony/http-kernel/Tests/ControllerMetadata/ArgumentMetadataFactoryTest.php b/vendor/symfony/http-kernel/Tests/ControllerMetadata/ArgumentMetadataFactoryTest.php
new file mode 100644
index 0000000000..b4b449f358
--- /dev/null
+++ b/vendor/symfony/http-kernel/Tests/ControllerMetadata/ArgumentMetadataFactoryTest.php
@@ -0,0 +1,148 @@
+<?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\ControllerMetadata;
+
+use Fake\ImportedAndFake;
+use PHPUnit\Framework\TestCase;
+use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata;
+use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadataFactory;
+use Symfony\Component\HttpKernel\Tests\Fixtures\Controller\BasicTypesController;
+use Symfony\Component\HttpKernel\Tests\Fixtures\Controller\NullableController;
+use Symfony\Component\HttpKernel\Tests\Fixtures\Controller\VariadicController;
+
+class ArgumentMetadataFactoryTest extends TestCase
+{
+ /**
+ * @var ArgumentMetadataFactory
+ */
+ private $factory;
+
+ protected function setUp()
+ {
+ $this->factory = new ArgumentMetadataFactory();
+ }
+
+ public function testSignature1()
+ {
+ $arguments = $this->factory->createArgumentMetadata(array($this, 'signature1'));
+
+ $this->assertEquals(array(
+ new ArgumentMetadata('foo', self::class, false, false, null),
+ new ArgumentMetadata('bar', 'array', false, false, null),
+ new ArgumentMetadata('baz', 'callable', false, false, null),
+ ), $arguments);
+ }
+
+ public function testSignature2()
+ {
+ $arguments = $this->factory->createArgumentMetadata(array($this, 'signature2'));
+
+ $this->assertEquals(array(
+ 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);
+ }
+
+ public function testSignature3()
+ {
+ $arguments = $this->factory->createArgumentMetadata(array($this, 'signature3'));
+
+ $this->assertEquals(array(
+ new ArgumentMetadata('bar', __NAMESPACE__.'\FakeClassThatDoesNotExist', false, false, null),
+ new ArgumentMetadata('baz', 'Fake\ImportedAndFake', false, false, null),
+ ), $arguments);
+ }
+
+ public function testSignature4()
+ {
+ $arguments = $this->factory->createArgumentMetadata(array($this, 'signature4'));
+
+ $this->assertEquals(array(
+ new ArgumentMetadata('foo', null, false, true, 'default'),
+ new ArgumentMetadata('bar', null, false, true, 500),
+ new ArgumentMetadata('baz', null, false, true, array()),
+ ), $arguments);
+ }
+
+ public function testSignature5()
+ {
+ $arguments = $this->factory->createArgumentMetadata(array($this, 'signature5'));
+
+ $this->assertEquals(array(
+ new ArgumentMetadata('foo', 'array', false, true, null, true),
+ new ArgumentMetadata('bar', null, false, false, null),
+ ), $arguments);
+ }
+
+ /**
+ * @requires PHP 5.6
+ */
+ public function testVariadicSignature()
+ {
+ $arguments = $this->factory->createArgumentMetadata(array(new VariadicController(), 'action'));
+
+ $this->assertEquals(array(
+ new ArgumentMetadata('foo', null, false, false, null),
+ new ArgumentMetadata('bar', null, true, false, null),
+ ), $arguments);
+ }
+
+ /**
+ * @requires PHP 7.0
+ */
+ public function testBasicTypesSignature()
+ {
+ $arguments = $this->factory->createArgumentMetadata(array(new BasicTypesController(), 'action'));
+
+ $this->assertEquals(array(
+ new ArgumentMetadata('foo', 'string', false, false, null),
+ new ArgumentMetadata('bar', 'int', false, false, null),
+ new ArgumentMetadata('baz', 'float', false, false, null),
+ ), $arguments);
+ }
+
+ /**
+ * @requires PHP 7.1
+ */
+ public function testNullableTypesSignature()
+ {
+ $arguments = $this->factory->createArgumentMetadata(array(new NullableController(), 'action'));
+
+ $this->assertEquals(array(
+ 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);
+ }
+
+ private function signature1(ArgumentMetadataFactoryTest $foo, array $bar, callable $baz)
+ {
+ }
+
+ private function signature2(ArgumentMetadataFactoryTest $foo = null, FakeClassThatDoesNotExist $bar = null, ImportedAndFake $baz = null)
+ {
+ }
+
+ private function signature3(FakeClassThatDoesNotExist $bar, ImportedAndFake $baz)
+ {
+ }
+
+ private function signature4($foo = 'default', $bar = 500, $baz = array())
+ {
+ }
+
+ private function signature5(array $foo = null, $bar)
+ {
+ }
+}
diff --git a/vendor/symfony/http-kernel/Tests/ControllerMetadata/ArgumentMetadataTest.php b/vendor/symfony/http-kernel/Tests/ControllerMetadata/ArgumentMetadataTest.php
new file mode 100644
index 0000000000..05351445e0
--- /dev/null
+++ b/vendor/symfony/http-kernel/Tests/ControllerMetadata/ArgumentMetadataTest.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\HttpKernel\Tests\ControllerMetadata;
+
+use PHPUnit\Framework\TestCase;
+use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadata;
+
+class ArgumentMetadataTest extends TestCase
+{
+ public function testWithBcLayerWithDefault()
+ {
+ $argument = new ArgumentMetadata('foo', 'string', false, true, 'default value');
+
+ $this->assertFalse($argument->isNullable());
+ }
+
+ public function testDefaultValueAvailable()
+ {
+ $argument = new ArgumentMetadata('foo', 'string', false, true, 'default value', true);
+
+ $this->assertTrue($argument->isNullable());
+ $this->assertTrue($argument->hasDefaultValue());
+ $this->assertSame('default value', $argument->getDefaultValue());
+ }
+
+ /**
+ * @expectedException \LogicException
+ */
+ public function testDefaultValueUnavailable()
+ {
+ $argument = new ArgumentMetadata('foo', 'string', false, false, null, false);
+
+ $this->assertFalse($argument->isNullable());
+ $this->assertFalse($argument->hasDefaultValue());
+ $argument->getDefaultValue();
+ }
+}
diff --git a/vendor/symfony/http-kernel/Tests/DataCollector/Compiler.log b/vendor/symfony/http-kernel/Tests/DataCollector/Compiler.log
new file mode 100644
index 0000000000..88b6840eae
--- /dev/null
+++ b/vendor/symfony/http-kernel/Tests/DataCollector/Compiler.log
@@ -0,0 +1,4 @@
+Symfony\Component\DependencyInjection\Compiler\RemovePrivateAliasesPass: Removed service "Psr\Container\ContainerInterface"; reason: private alias.
+Symfony\Component\DependencyInjection\Compiler\RemovePrivateAliasesPass: Removed service "Symfony\Component\DependencyInjection\ContainerInterface"; reason: private alias.
+Some custom logging message
+With ending :
diff --git a/vendor/symfony/http-kernel/Tests/DataCollector/ConfigDataCollectorTest.php b/vendor/symfony/http-kernel/Tests/DataCollector/ConfigDataCollectorTest.php
new file mode 100644
index 0000000000..4fb36afda2
--- /dev/null
+++ b/vendor/symfony/http-kernel/Tests/DataCollector/ConfigDataCollectorTest.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\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;
+
+class ConfigDataCollectorTest extends TestCase
+{
+ public function testCollect()
+ {
+ $kernel = new KernelForTest('test', true);
+ $c = new ConfigDataCollector();
+ $c->setKernel($kernel);
+ $c->collect(new Request(), new Response());
+
+ $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());
+ $this->assertSame(class_exists('Locale', false) && \Locale::getDefault() ? \Locale::getDefault() : 'n/a', $c->getPhpIntlLocale());
+ $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());
+ }
+}
+
+class KernelForTest extends Kernel
+{
+ public function getName()
+ {
+ return 'testkernel';
+ }
+
+ public function registerBundles()
+ {
+ }
+
+ public function getBundles()
+ {
+ return array();
+ }
+
+ 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
new file mode 100644
index 0000000000..54fd39e0d8
--- /dev/null
+++ b/vendor/symfony/http-kernel/Tests/DataCollector/DataCollectorTest.php
@@ -0,0 +1,38 @@
+<?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;
+
+use PHPUnit\Framework\TestCase;
+use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\HttpFoundation\Response;
+use Symfony\Component\HttpKernel\Tests\Fixtures\DataCollector\CloneVarDataCollector;
+use Symfony\Component\VarDumper\Cloner\VarCloner;
+
+class DataCollectorTest extends TestCase
+{
+ public function testCloneVarStringWithScheme()
+ {
+ $c = new CloneVarDataCollector('scheme://foo');
+ $c->collect(new Request(), new Response());
+ $cloner = new VarCloner();
+
+ $this->assertEquals($cloner->cloneVar('scheme://foo'), $c->getData());
+ }
+
+ public function testCloneVarExistingFilePath()
+ {
+ $c = new CloneVarDataCollector(array($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
new file mode 100644
index 0000000000..e642e3c337
--- /dev/null
+++ b/vendor/symfony/http-kernel/Tests/DataCollector/DumpDataCollectorTest.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\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\VarDumper\Cloner\Data;
+
+/**
+ * @author Nicolas Grekas <p@tchwork.com>
+ */
+class DumpDataCollectorTest extends TestCase
+{
+ public function testDump()
+ {
+ $data = new Data(array(array(123)));
+
+ $collector = new DumpDataCollector();
+
+ $this->assertSame('dump', $collector->getName());
+
+ $collector->dump($data);
+ $line = __LINE__ - 1;
+ $this->assertSame(1, $collector->getDumpsCount());
+
+ $dump = $collector->getDumps('html');
+ $this->assertTrue(isset($dump[0]['data']));
+ $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(
+ '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->assertSame(0, $collector->getDumpsCount());
+ $this->assertSame('a:2:{i:0;b:0;i:1;s:5:"UTF-8";}', $collector->serialize());
+ }
+
+ public function testCollectDefault()
+ {
+ $data = new Data(array(array(123)));
+
+ $collector = new DumpDataCollector();
+
+ $collector->dump($data);
+ $line = __LINE__ - 1;
+
+ ob_start();
+ $collector->collect(new Request(), new Response());
+ $output = ob_get_clean();
+
+ $this->assertSame("DumpDataCollectorTest.php on line {$line}:\n123\n", $output);
+ $this->assertSame(1, $collector->getDumpsCount());
+ $collector->serialize();
+ }
+
+ public function testCollectHtml()
+ {
+ $data = new Data(array(array(123)));
+
+ $collector = new DumpDataCollector(null, 'test://%f:%l');
+
+ $collector->dump($data);
+ $line = __LINE__ - 1;
+ $file = __FILE__;
+ $xOutput = <<<EOTXT
+<pre class=sf-dump id=sf-dump data-indent-pad=" "><a href="test://{$file}:{$line}" title="{$file}"><span class=sf-dump-meta>DumpDataCollectorTest.php</span></a> on line <span class=sf-dump-meta>{$line}</span>:
+<span class=sf-dump-num>123</span>
+</pre>
+EOTXT;
+
+ ob_start();
+ $response = new Response();
+ $response->headers->set('Content-Type', 'text/html');
+ $collector->collect(new Request(), $response);
+ $output = ob_get_clean();
+ $output = preg_replace('#<(script|style).*?</\1>#s', '', $output);
+ $output = preg_replace('/sf-dump-\d+/', 'sf-dump', $output);
+
+ $this->assertSame($xOutput, trim($output));
+ $this->assertSame(1, $collector->getDumpsCount());
+ $collector->serialize();
+ }
+
+ public function testFlush()
+ {
+ $data = new Data(array(array(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());
+ }
+}
diff --git a/vendor/symfony/http-kernel/Tests/DataCollector/ExceptionDataCollectorTest.php b/vendor/symfony/http-kernel/Tests/DataCollector/ExceptionDataCollectorTest.php
new file mode 100644
index 0000000000..afad9f58af
--- /dev/null
+++ b/vendor/symfony/http-kernel/Tests/DataCollector/ExceptionDataCollectorTest.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\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;
+
+class ExceptionDataCollectorTest extends TestCase
+{
+ public function testCollect()
+ {
+ $e = new \Exception('foo', 500);
+ $c = new ExceptionDataCollector();
+ $flattened = FlattenException::create($e);
+ $trace = $flattened->getTrace();
+
+ $this->assertFalse($c->hasException());
+
+ $c->collect(new Request(), new Response(), $e);
+
+ $this->assertTrue($c->hasException());
+ $this->assertEquals($flattened, $c->getException());
+ $this->assertSame('foo', $c->getMessage());
+ $this->assertSame(500, $c->getCode());
+ $this->assertSame('exception', $c->getName());
+ $this->assertSame($trace, $c->getTrace());
+ }
+}
diff --git a/vendor/symfony/http-kernel/Tests/DataCollector/LoggerDataCollectorTest.php b/vendor/symfony/http-kernel/Tests/DataCollector/LoggerDataCollectorTest.php
new file mode 100644
index 0000000000..62bf2c00c7
--- /dev/null
+++ b/vendor/symfony/http-kernel/Tests/DataCollector/LoggerDataCollectorTest.php
@@ -0,0 +1,126 @@
+<?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;
+
+use PHPUnit\Framework\TestCase;
+use Symfony\Component\Debug\Exception\SilencedErrorContext;
+use Symfony\Component\HttpKernel\DataCollector\LoggerDataCollector;
+
+class LoggerDataCollectorTest extends TestCase
+{
+ public function testCollectWithUnexpectedFormat()
+ {
+ $logger = $this->getMockBuilder('Symfony\Component\HttpKernel\Log\DebugLoggerInterface')->getMock();
+ $logger->expects($this->once())->method('countErrors')->will($this->returnValue('foo'));
+ $logger->expects($this->exactly(2))->method('getLogs')->will($this->returnValue(array()));
+
+ $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(array(
+ array('message' => 'Some custom logging message'),
+ array('message' => 'With ending :'),
+ ), $compilerLogs['Unknown Compiler Pass']);
+ }
+
+ /**
+ * @dataProvider getCollectTestData
+ */
+ public function testCollect($nb, $logs, $expectedLogs, $expectedDeprecationCount, $expectedScreamCount, $expectedPriorities = null)
+ {
+ $logger = $this->getMockBuilder('Symfony\Component\HttpKernel\Log\DebugLoggerInterface')->getMock();
+ $logger->expects($this->once())->method('countErrors')->will($this->returnValue($nb));
+ $logger->expects($this->exactly(2))->method('getLogs')->will($this->returnValue($logs));
+
+ $c = new LoggerDataCollector($logger);
+ $c->lateCollect();
+
+ $this->assertEquals('logger', $c->getName());
+ $this->assertEquals($nb, $c->countErrors());
+
+ $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"]);
+ }
+
+ return $v;
+ }, $c->getLogs()->getValue(true));
+ $this->assertEquals($expectedLogs, $logs);
+ $this->assertEquals($expectedDeprecationCount, $c->countDeprecations());
+ $this->assertEquals($expectedScreamCount, $c->countScreams());
+
+ if (isset($expectedPriorities)) {
+ $this->assertSame($expectedPriorities, $c->getPriorities()->getValue(true));
+ }
+ }
+
+ public function getCollectTestData()
+ {
+ yield 'simple log' => array(
+ 1,
+ array(array('message' => 'foo', 'context' => array(), 'priority' => 100, 'priorityName' => 'DEBUG')),
+ array(array('message' => 'foo', 'context' => array(), 'priority' => 100, 'priorityName' => 'DEBUG')),
+ 0,
+ 0,
+ );
+
+ yield 'log with a context' => array(
+ 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')),
+ 0,
+ 0,
+ );
+
+ if (!class_exists(SilencedErrorContext::class)) {
+ return;
+ }
+
+ yield 'logs with some deprecations' => array(
+ 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),
+ ),
+ 2,
+ 0,
+ array(100 => array('count' => 3, 'name' => 'DEBUG')),
+ );
+
+ yield 'logs with some silent errors' => array(
+ 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),
+ ),
+ 0,
+ 1,
+ );
+ }
+}
diff --git a/vendor/symfony/http-kernel/Tests/DataCollector/MemoryDataCollectorTest.php b/vendor/symfony/http-kernel/Tests/DataCollector/MemoryDataCollectorTest.php
new file mode 100644
index 0000000000..ab78e9e8e1
--- /dev/null
+++ b/vendor/symfony/http-kernel/Tests/DataCollector/MemoryDataCollectorTest.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\HttpKernel\Tests\DataCollector;
+
+use PHPUnit\Framework\TestCase;
+use Symfony\Component\HttpKernel\DataCollector\MemoryDataCollector;
+use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\HttpFoundation\Response;
+
+class MemoryDataCollectorTest extends TestCase
+{
+ public function testCollect()
+ {
+ $collector = new MemoryDataCollector();
+ $collector->collect(new Request(), new Response());
+
+ $this->assertInternalType('integer', $collector->getMemory());
+ $this->assertInternalType('integer', $collector->getMemoryLimit());
+ $this->assertSame('memory', $collector->getName());
+ }
+
+ /** @dataProvider getBytesConversionTestData */
+ public function testBytesConversion($limit, $bytes)
+ {
+ $collector = new MemoryDataCollector();
+ $method = new \ReflectionMethod($collector, 'convertToBytes');
+ $method->setAccessible(true);
+ $this->assertEquals($bytes, $method->invoke($collector, $limit));
+ }
+
+ 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'
+ );
+ }
+}
diff --git a/vendor/symfony/http-kernel/Tests/DataCollector/RequestDataCollectorTest.php b/vendor/symfony/http-kernel/Tests/DataCollector/RequestDataCollectorTest.php
new file mode 100644
index 0000000000..93767b9684
--- /dev/null
+++ b/vendor/symfony/http-kernel/Tests/DataCollector/RequestDataCollectorTest.php
@@ -0,0 +1,287 @@
+<?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;
+
+use PHPUnit\Framework\TestCase;
+use Symfony\Component\HttpFoundation\ParameterBag;
+use Symfony\Component\HttpFoundation\RedirectResponse;
+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\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
+{
+ public function testCollect()
+ {
+ $c = new RequestDataCollector();
+
+ $c->collect($request = $this->createRequest(), $this->createResponse());
+ $c->lateCollect();
+
+ $attributes = $c->getRequestAttributes();
+
+ $this->assertSame('request', $c->getName());
+ $this->assertInstanceOf('Symfony\Component\HttpFoundation\ParameterBag', $c->getRequestHeaders());
+ $this->assertInstanceOf('Symfony\Component\HttpFoundation\ParameterBag', $c->getRequestServer());
+ $this->assertInstanceOf('Symfony\Component\HttpFoundation\ParameterBag', $c->getRequestCookies());
+ $this->assertInstanceOf('Symfony\Component\HttpFoundation\ParameterBag', $attributes);
+ $this->assertInstanceOf('Symfony\Component\HttpFoundation\ParameterBag', $c->getRequestRequest());
+ $this->assertInstanceOf('Symfony\Component\HttpFoundation\ParameterBag', $c->getRequestQuery());
+ $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->assertSame('en', $c->getLocale());
+ $this->assertContains(__FILE__, $attributes->get('resource'));
+ $this->assertSame('stdClass', $attributes->get('object')->getType());
+
+ $this->assertInstanceOf('Symfony\Component\HttpFoundation\ParameterBag', $c->getResponseHeaders());
+ $this->assertSame('OK', $c->getStatusText());
+ $this->assertSame(200, $c->getStatusCode());
+ $this->assertSame('application/json', $c->getContentType());
+ }
+
+ public function testCollectWithoutRouteParams()
+ {
+ $request = $this->createRequest(array());
+
+ $c = new RequestDataCollector();
+ $c->collect($request, $this->createResponse());
+ $c->lateCollect();
+
+ $this->assertEquals(array(), $c->getRouteParams());
+ }
+
+ public function testKernelResponseDoesNotStartSession()
+ {
+ $kernel = $this->getMockBuilder(HttpKernelInterface::class)->getMock();
+ $request = new Request();
+ $session = new Session(new MockArraySessionStorage());
+ $request->setSession($session);
+ $response = new Response();
+
+ $c = new RequestDataCollector();
+ $c->onKernelResponse(new FilterResponseEvent($kernel, $request, HttpKernelInterface::MASTER_REQUEST, $response));
+
+ $this->assertFalse($session->isStarted());
+ }
+
+ /**
+ * @dataProvider provideControllerCallables
+ */
+ public function testControllerInspection($name, $callable, $expected)
+ {
+ $c = new RequestDataCollector();
+ $request = $this->createRequest();
+ $response = $this->createResponse();
+ $this->injectController($c, $callable, $request);
+ $c->collect($request, $response);
+ $c->lateCollect();
+
+ $this->assertSame($expected, $c->getController()->getValue(true), sprintf('Testing: %s', $name));
+ }
+
+ public function provideControllerCallables()
+ {
+ // make sure we always match the line number
+ $r1 = new \ReflectionMethod($this, 'testControllerInspection');
+ $r2 = new \ReflectionMethod($this, 'staticControllerMethod');
+ $r3 = new \ReflectionClass($this);
+
+ // test name, callable, expected
+ return array(
+ array(
+ '"Regular" callable',
+ array($this, 'testControllerInspection'),
+ array(
+ '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(
+ '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(
+ '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(
+ '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(
+ '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()
+ {
+ $request = $this->createRequestWithSession();
+ $response = new RedirectResponse('/');
+
+ $c = new RequestDataCollector();
+ $c->collect($request, $response);
+
+ $this->assertSame('n/a', $c->getController());
+ }
+
+ protected function createRequest($routeParams = array('name' => 'foo'))
+ {
+ $request = Request::create('http://test.com/foo?bar=baz');
+ $request->attributes->set('foo', 'bar');
+ $request->attributes->set('_route', 'foobar');
+ $request->attributes->set('_route_params', $routeParams);
+ $request->attributes->set('resource', fopen(__FILE__, 'r'));
+ $request->attributes->set('object', new \stdClass());
+
+ return $request;
+ }
+
+ private function createRequestWithSession()
+ {
+ $request = $this->createRequest();
+ $request->attributes->set('_controller', 'Foo::bar');
+ $request->setSession(new Session(new MockArraySessionStorage()));
+ $request->getSession()->start();
+
+ return $request;
+ }
+
+ protected function createResponse()
+ {
+ $response = new Response();
+ $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'));
+
+ return $response;
+ }
+
+ /**
+ * Inject the given controller callable into the data collector.
+ */
+ protected function injectController($collector, $controller, $request)
+ {
+ $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);
+ $collector->onKernelController($event);
+ }
+
+ /**
+ * Dummy method used as controller callable.
+ */
+ public static function staticControllerMethod()
+ {
+ throw new \LogicException('Unexpected method call');
+ }
+
+ /**
+ * Magic method to allow non existing methods to be called and delegated.
+ */
+ public function __call($method, $args)
+ {
+ throw new \LogicException('Unexpected method call');
+ }
+
+ /**
+ * Magic method to allow non existing methods to be called and delegated.
+ */
+ public static function __callStatic($method, $args)
+ {
+ throw new \LogicException('Unexpected method call');
+ }
+
+ public function __invoke()
+ {
+ throw new \LogicException('Unexpected method call');
+ }
+}
diff --git a/vendor/symfony/http-kernel/Tests/DataCollector/TimeDataCollectorTest.php b/vendor/symfony/http-kernel/Tests/DataCollector/TimeDataCollectorTest.php
new file mode 100644
index 0000000000..8048cc37a5
--- /dev/null
+++ b/vendor/symfony/http-kernel/Tests/DataCollector/TimeDataCollectorTest.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\HttpKernel\Tests\DataCollector;
+
+use PHPUnit\Framework\TestCase;
+use Symfony\Component\HttpKernel\DataCollector\TimeDataCollector;
+use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\HttpFoundation\Response;
+
+/**
+ * @group time-sensitive
+ */
+class TimeDataCollectorTest extends TestCase
+{
+ public function testCollect()
+ {
+ $c = new TimeDataCollector();
+
+ $request = new Request();
+ $request->server->set('REQUEST_TIME', 1);
+
+ $c->collect($request, new Response());
+
+ $this->assertEquals(0, $c->getStartTime());
+
+ $request->server->set('REQUEST_TIME_FLOAT', 2);
+
+ $c->collect($request, new Response());
+
+ $this->assertEquals(2000, $c->getStartTime());
+
+ $request = new Request();
+ $c->collect($request, new Response());
+ $this->assertEquals(0, $c->getStartTime());
+
+ $kernel = $this->getMockBuilder('Symfony\Component\HttpKernel\KernelInterface')->getMock();
+ $kernel->expects($this->once())->method('getStartTime')->will($this->returnValue(123456));
+
+ $c = new TimeDataCollector($kernel);
+ $request = new Request();
+ $request->server->set('REQUEST_TIME', 1);
+
+ $c->collect($request, new Response());
+ $this->assertEquals(123456000, $c->getStartTime());
+ }
+}
diff --git a/vendor/symfony/http-kernel/Tests/DataCollector/Util/ValueExporterTest.php b/vendor/symfony/http-kernel/Tests/DataCollector/Util/ValueExporterTest.php
new file mode 100644
index 0000000000..5fe92d60e0
--- /dev/null
+++ b/vendor/symfony/http-kernel/Tests/DataCollector/Util/ValueExporterTest.php
@@ -0,0 +1,51 @@
+<?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
new file mode 100644
index 0000000000..d616098a54
--- /dev/null
+++ b/vendor/symfony/http-kernel/Tests/Debug/FileLinkFormatterTest.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\HttpKernel\Tests\Debug;
+
+use PHPUnit\Framework\TestCase;
+use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\HttpFoundation\RequestStack;
+use Symfony\Component\HttpKernel\Debug\FileLinkFormatter;
+
+class FileLinkFormatterTest extends TestCase
+{
+ public function testWhenNoFileLinkFormatAndNoRequest()
+ {
+ $sut = new FileLinkFormatter();
+
+ $this->assertFalse($sut->format('/kernel/root/src/my/very/best/file.php', 3));
+ }
+
+ public function testWhenFileLinkFormatAndNoRequest()
+ {
+ $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';
+ $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');
+
+ $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));
+ }
+}
diff --git a/vendor/symfony/http-kernel/Tests/Debug/TraceableEventDispatcherTest.php b/vendor/symfony/http-kernel/Tests/Debug/TraceableEventDispatcherTest.php
new file mode 100644
index 0000000000..aaa82d524c
--- /dev/null
+++ b/vendor/symfony/http-kernel/Tests/Debug/TraceableEventDispatcherTest.php
@@ -0,0 +1,121 @@
+<?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\Debug;
+
+use PHPUnit\Framework\TestCase;
+use Symfony\Component\EventDispatcher\EventDispatcher;
+use Symfony\Component\HttpFoundation\RequestStack;
+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
+{
+ public function testStopwatchSections()
+ {
+ $dispatcher = new TraceableEventDispatcher(new EventDispatcher(), $stopwatch = new Stopwatch());
+ $kernel = $this->getHttpKernel($dispatcher, function () { return new Response(); });
+ $request = Request::create('/');
+ $response = $kernel->handle($request);
+ $kernel->terminate($request, $response);
+
+ $events = $stopwatch->getSectionEvents($response->headers->get('X-Debug-Token'));
+ $this->assertEquals(array(
+ '__section__',
+ 'kernel.request',
+ 'kernel.controller',
+ 'kernel.controller_arguments',
+ 'controller',
+ 'kernel.response',
+ 'kernel.terminate',
+ ), array_keys($events));
+ }
+
+ public function testStopwatchCheckControllerOnRequestEvent()
+ {
+ $stopwatch = $this->getMockBuilder('Symfony\Component\Stopwatch\Stopwatch')
+ ->setMethods(array('isStarted'))
+ ->getMock();
+ $stopwatch->expects($this->once())
+ ->method('isStarted')
+ ->will($this->returnValue(false));
+
+ $dispatcher = new TraceableEventDispatcher(new EventDispatcher(), $stopwatch);
+
+ $kernel = $this->getHttpKernel($dispatcher, function () { return new Response(); });
+ $request = Request::create('/');
+ $kernel->handle($request);
+ }
+
+ public function testStopwatchStopControllerOnRequestEvent()
+ {
+ $stopwatch = $this->getMockBuilder('Symfony\Component\Stopwatch\Stopwatch')
+ ->setMethods(array('isStarted', 'stop', 'stopSection'))
+ ->getMock();
+ $stopwatch->expects($this->once())
+ ->method('isStarted')
+ ->will($this->returnValue(true));
+ $stopwatch->expects($this->once())
+ ->method('stop');
+ $stopwatch->expects($this->once())
+ ->method('stopSection');
+
+ $dispatcher = new TraceableEventDispatcher(new EventDispatcher(), $stopwatch);
+
+ $kernel = $this->getHttpKernel($dispatcher, function () { return new Response(); });
+ $request = Request::create('/');
+ $kernel->handle($request);
+ }
+
+ public function testAddListenerNested()
+ {
+ $called1 = false;
+ $called2 = false;
+ $dispatcher = new TraceableEventDispatcher(new EventDispatcher(), new Stopwatch());
+ $dispatcher->addListener('my-event', function () use ($dispatcher, &$called1, &$called2) {
+ $called1 = true;
+ $dispatcher->addListener('my-event', function () use (&$called2) {
+ $called2 = true;
+ });
+ });
+ $dispatcher->dispatch('my-event');
+ $this->assertTrue($called1);
+ $this->assertFalse($called2);
+ $dispatcher->dispatch('my-event');
+ $this->assertTrue($called2);
+ }
+
+ public function testListenerCanRemoveItselfWhenExecuted()
+ {
+ $eventDispatcher = new TraceableEventDispatcher(new EventDispatcher(), new Stopwatch());
+ $listener1 = function () use ($eventDispatcher, &$listener1) {
+ $eventDispatcher->removeListener('foo', $listener1);
+ };
+ $eventDispatcher->addListener('foo', $listener1);
+ $eventDispatcher->addListener('foo', function () {});
+ $eventDispatcher->dispatch('foo');
+
+ $this->assertCount(1, $eventDispatcher->getListeners('foo'), 'expected listener1 to be removed');
+ }
+
+ protected function getHttpKernel($dispatcher, $controller)
+ {
+ $controllerResolver = $this->getMockBuilder('Symfony\Component\HttpKernel\Controller\ControllerResolverInterface')->getMock();
+ $controllerResolver->expects($this->once())->method('getController')->will($this->returnValue($controller));
+ $argumentResolver = $this->getMockBuilder('Symfony\Component\HttpKernel\Controller\ArgumentResolverInterface')->getMock();
+ $argumentResolver->expects($this->once())->method('getArguments')->will($this->returnValue(array()));
+
+ 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
new file mode 100644
index 0000000000..a2fb6afca4
--- /dev/null
+++ b/vendor/symfony/http-kernel/Tests/DependencyInjection/AddAnnotatedClassesToCachePassTest.php
@@ -0,0 +1,99 @@
+<?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\DependencyInjection;
+
+use PHPUnit\Framework\TestCase;
+use Symfony\Component\HttpKernel\DependencyInjection\AddAnnotatedClassesToCachePass;
+
+class AddAnnotatedClassesToCachePassTest extends TestCase
+{
+ public function testExpandClasses()
+ {
+ $r = new \ReflectionClass(AddAnnotatedClassesToCachePass::class);
+ $pass = $r->newInstanceWithoutConstructor();
+ $r = new \ReflectionMethod(AddAnnotatedClassesToCachePass::class, 'expandClasses');
+ $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\\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('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', $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('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(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('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('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\\Bar', $expand(array('Foo\\*'), array('\\Foo\\Bar'))[0]);
+ $this->assertEmpty($expand(array('Foo\\*'), array('\\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(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(
+ 'Acme\\FooBundle\\Controller\\DefaultController',
+ $expand(array('**Bundle\\Controller\\'), array('\\Acme\\FooBundle\\Controller\\DefaultController'))[0]
+ );
+
+ $this->assertSame(
+ 'FooBundle\\Controller\\DefaultController',
+ $expand(array('**Bundle\\Controller\\'), array('\\FooBundle\\Controller\\DefaultController'))[0]
+ );
+
+ $this->assertSame(
+ 'Acme\\FooBundle\\Controller\\Bar\\DefaultController',
+ $expand(array('**Bundle\\Controller\\'), array('\\Acme\\FooBundle\\Controller\\Bar\\DefaultController'))[0]
+ );
+
+ $this->assertSame(
+ 'Bundle\\Controller\\Bar\\DefaultController',
+ $expand(array('**Bundle\\Controller\\'), array('\\Bundle\\Controller\\Bar\\DefaultController'))[0]
+ );
+
+ $this->assertSame(
+ 'Acme\\Bundle\\Controller\\Bar\\DefaultController',
+ $expand(array('**Bundle\\Controller\\'), array('\\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]);
+ }
+}
diff --git a/vendor/symfony/http-kernel/Tests/DependencyInjection/ControllerArgumentValueResolverPassTest.php b/vendor/symfony/http-kernel/Tests/DependencyInjection/ControllerArgumentValueResolverPassTest.php
new file mode 100644
index 0000000000..df8977de0b
--- /dev/null
+++ b/vendor/symfony/http-kernel/Tests/DependencyInjection/ControllerArgumentValueResolverPassTest.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\HttpKernel\Tests\DependencyInjection;
+
+use PHPUnit\Framework\TestCase;
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\DependencyInjection\Definition;
+use Symfony\Component\DependencyInjection\Reference;
+use Symfony\Component\HttpKernel\Controller\ArgumentResolver;
+use Symfony\Component\HttpKernel\DependencyInjection\ControllerArgumentValueResolverPass;
+
+class ControllerArgumentValueResolverPassTest extends TestCase
+{
+ public function testServicesAreOrderedAccordingToPriority()
+ {
+ $services = array(
+ 'n3' => array(array()),
+ 'n1' => array(array('priority' => 200)),
+ 'n2' => array(array('priority' => 100)),
+ );
+
+ $expected = array(
+ new Reference('n1'),
+ new Reference('n2'),
+ new Reference('n3'),
+ );
+
+ $definition = new Definition(ArgumentResolver::class, array(null, array()));
+ $container = new ContainerBuilder();
+ $container->setDefinition('argument_resolver', $definition);
+
+ foreach ($services as $id => list($tag)) {
+ $container->register($id)->addTag('controller.argument_value_resolver', $tag);
+ }
+
+ (new ControllerArgumentValueResolverPass())->process($container);
+ $this->assertEquals($expected, $definition->getArgument(1)->getValues());
+ }
+
+ public function testReturningEmptyArrayWhenNoService()
+ {
+ $definition = new Definition(ArgumentResolver::class, array(null, array()));
+ $container = new ContainerBuilder();
+ $container->setDefinition('argument_resolver', $definition);
+
+ (new ControllerArgumentValueResolverPass())->process($container);
+ $this->assertEquals(array(), $definition->getArgument(1)->getValues());
+ }
+
+ public function testNoArgumentResolver()
+ {
+ $container = new ContainerBuilder();
+
+ (new ControllerArgumentValueResolverPass())->process($container);
+
+ $this->assertFalse($container->hasDefinition('argument_resolver'));
+ }
+}
diff --git a/vendor/symfony/http-kernel/Tests/DependencyInjection/FragmentRendererPassTest.php b/vendor/symfony/http-kernel/Tests/DependencyInjection/FragmentRendererPassTest.php
new file mode 100644
index 0000000000..d28c6eca57
--- /dev/null
+++ b/vendor/symfony/http-kernel/Tests/DependencyInjection/FragmentRendererPassTest.php
@@ -0,0 +1,105 @@
+<?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\DependencyInjection;
+
+use PHPUnit\Framework\TestCase;
+use Symfony\Component\DependencyInjection\Definition;
+use Symfony\Component\DependencyInjection\Reference;
+use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\HttpKernel\DependencyInjection\FragmentRendererPass;
+use Symfony\Component\HttpKernel\Fragment\FragmentRendererInterface;
+
+class FragmentRendererPassTest extends TestCase
+{
+ /**
+ * Tests that content rendering not implementing FragmentRendererInterface
+ * trigger an exception.
+ *
+ * @expectedException \InvalidArgumentException
+ */
+ 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));
+
+ $pass = new FragmentRendererPass();
+ $pass->process($builder);
+ }
+
+ 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')));
+
+ $pass = new FragmentRendererPass();
+ $pass->process($builder);
+
+ $this->assertInstanceOf(Reference::class, $renderer->getArgument(0));
+ }
+}
+
+class RendererService implements FragmentRendererInterface
+{
+ public function render($uri, Request $request = null, array $options = array())
+ {
+ }
+
+ public function getName()
+ {
+ return 'test';
+ }
+}
diff --git a/vendor/symfony/http-kernel/Tests/DependencyInjection/LazyLoadingFragmentHandlerTest.php b/vendor/symfony/http-kernel/Tests/DependencyInjection/LazyLoadingFragmentHandlerTest.php
new file mode 100644
index 0000000000..0406345d96
--- /dev/null
+++ b/vendor/symfony/http-kernel/Tests/DependencyInjection/LazyLoadingFragmentHandlerTest.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\HttpKernel\Tests\DependencyInjection;
+
+use PHPUnit\Framework\TestCase;
+use Symfony\Component\HttpKernel\DependencyInjection\LazyLoadingFragmentHandler;
+use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\HttpFoundation\Response;
+
+class LazyLoadingFragmentHandlerTest extends TestCase
+{
+ /**
+ * @group legacy
+ * @expectedDeprecation The Symfony\Component\HttpKernel\DependencyInjection\LazyLoadingFragmentHandler::addRendererService() method is deprecated since version 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()));
+
+ $requestStack = $this->getMockBuilder('Symfony\Component\HttpFoundation\RequestStack')->getMock();
+ $requestStack->expects($this->any())->method('getCurrentRequest')->will($this->returnValue(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));
+
+ $handler = new LazyLoadingFragmentHandler($container, $requestStack, false);
+
+ $handler->render('/foo', 'foo');
+
+ // second call should not lazy-load anymore (see once() above on the get() method)
+ $handler->render('/foo', 'foo');
+ }
+}
diff --git a/vendor/symfony/http-kernel/Tests/DependencyInjection/MergeExtensionConfigurationPassTest.php b/vendor/symfony/http-kernel/Tests/DependencyInjection/MergeExtensionConfigurationPassTest.php
new file mode 100644
index 0000000000..81fc8b455d
--- /dev/null
+++ b/vendor/symfony/http-kernel/Tests/DependencyInjection/MergeExtensionConfigurationPassTest.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\HttpKernel\Tests\DependencyInjection;
+
+use PHPUnit\Framework\TestCase;
+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'));
+ $configPass->process($container);
+ }
+}
diff --git a/vendor/symfony/http-kernel/Tests/DependencyInjection/RegisterControllerArgumentLocatorsPassTest.php b/vendor/symfony/http-kernel/Tests/DependencyInjection/RegisterControllerArgumentLocatorsPassTest.php
new file mode 100644
index 0000000000..0542698d69
--- /dev/null
+++ b/vendor/symfony/http-kernel/Tests/DependencyInjection/RegisterControllerArgumentLocatorsPassTest.php
@@ -0,0 +1,329 @@
+<?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\DependencyInjection;
+
+use PHPUnit\Framework\TestCase;
+use Symfony\Component\DependencyInjection\Argument\ServiceClosureArgument;
+use Symfony\Component\DependencyInjection\ContainerAwareInterface;
+use Symfony\Component\DependencyInjection\ContainerAwareTrait;
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\DependencyInjection\ContainerInterface;
+use Symfony\Component\DependencyInjection\ServiceLocator;
+use Symfony\Component\DependencyInjection\TypedReference;
+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()
+ {
+ $container = new ContainerBuilder();
+ $container->register('argument_resolver.service')->addArgument(array());
+
+ $container->register('foo', NotFound::class)
+ ->addTag('controller.service_arguments')
+ ;
+
+ $pass = new RegisterControllerArgumentLocatorsPass();
+ $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()
+ {
+ $container = new ContainerBuilder();
+ $container->register('argument_resolver.service')->addArgument(array());
+
+ $container->register('foo', RegisterTestController::class)
+ ->addTag('controller.service_arguments', array('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()
+ {
+ $container = new ContainerBuilder();
+ $container->register('argument_resolver.service')->addArgument(array());
+
+ $container->register('foo', RegisterTestController::class)
+ ->addTag('controller.service_arguments', array('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()
+ {
+ $container = new ContainerBuilder();
+ $container->register('argument_resolver.service')->addArgument(array());
+
+ $container->register('foo', RegisterTestController::class)
+ ->addTag('controller.service_arguments', array('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()
+ {
+ $container = new ContainerBuilder();
+ $container->register('argument_resolver.service')->addArgument(array());
+
+ $container->register('foo', RegisterTestController::class)
+ ->addTag('controller.service_arguments', array('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()
+ {
+ $container = new ContainerBuilder();
+ $container->register('argument_resolver.service')->addArgument(array());
+
+ $container->register('foo', RegisterTestController::class)
+ ->addTag('controller.service_arguments', array('action' => 'fooAction', 'argument' => 'baz', 'id' => 'bar'))
+ ;
+
+ $pass = new RegisterControllerArgumentLocatorsPass();
+ $pass->process($container);
+ }
+
+ public function testAllActions()
+ {
+ $container = new ContainerBuilder();
+ $resolver = $container->register('argument_resolver.service')->addArgument(array());
+
+ $container->register('foo', RegisterTestController::class)
+ ->addTag('controller.service_arguments')
+ ;
+
+ $pass = new RegisterControllerArgumentLocatorsPass();
+ $pass->process($container);
+
+ $locator = $container->getDefinition((string) $resolver->getArgument(0))->getArgument(0);
+
+ $this->assertEquals(array('foo:fooAction'), array_keys($locator));
+ $this->assertInstanceof(ServiceClosureArgument::class, $locator['foo:fooAction']);
+
+ $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)));
+ $this->assertEquals($expected, $locator->getArgument(0));
+ }
+
+ public function testExplicitArgument()
+ {
+ $container = new ContainerBuilder();
+ $resolver = $container->register('argument_resolver.service')->addArgument(array());
+
+ $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
+ ;
+
+ $pass = new RegisterControllerArgumentLocatorsPass();
+ $pass->process($container);
+
+ $locator = $container->getDefinition((string) $resolver->getArgument(0))->getArgument(0);
+ $locator = $container->getDefinition((string) $locator['foo:fooAction']->getValues()[0]);
+
+ $expected = array('bar' => new ServiceClosureArgument(new TypedReference('bar', ControllerDummy::class, RegisterTestController::class)));
+ $this->assertEquals($expected, $locator->getArgument(0));
+ }
+
+ public function testOptionalArgument()
+ {
+ $container = new ContainerBuilder();
+ $resolver = $container->register('argument_resolver.service')->addArgument(array());
+
+ $container->register('foo', RegisterTestController::class)
+ ->addTag('controller.service_arguments', array('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]);
+
+ $expected = array('bar' => new ServiceClosureArgument(new TypedReference('bar', ControllerDummy::class, RegisterTestController::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());
+
+ $container->register('foo', ContainerAwareRegisterTestController::class)
+ ->addTag('controller.service_arguments');
+
+ $pass = new RegisterControllerArgumentLocatorsPass();
+ $pass->process($container);
+
+ $locator = $container->getDefinition((string) $resolver->getArgument(0))->getArgument(0);
+ $this->assertSame(array('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()
+ {
+ $container = new ContainerBuilder();
+ $container->register('argument_resolver.service')->addArgument(array());
+
+ $container->register('foo', NonExistentClassController::class)
+ ->addTag('controller.service_arguments');
+
+ $pass = new RegisterControllerArgumentLocatorsPass();
+ $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()
+ {
+ $container = new ContainerBuilder();
+ $container->register('argument_resolver.service')->addArgument(array());
+
+ $container->register('foo', NonExistentClassDifferentNamespaceController::class)
+ ->addTag('controller.service_arguments');
+
+ $pass = new RegisterControllerArgumentLocatorsPass();
+ $pass->process($container);
+ }
+
+ public function testNoExceptionOnNonExistentTypeHintOptionalArg()
+ {
+ $container = new ContainerBuilder();
+ $resolver = $container->register('argument_resolver.service')->addArgument(array());
+
+ $container->register('foo', NonExistentClassOptionalController::class)
+ ->addTag('controller.service_arguments');
+
+ $pass = new RegisterControllerArgumentLocatorsPass();
+ $pass->process($container);
+
+ $locator = $container->getDefinition((string) $resolver->getArgument(0))->getArgument(0);
+ $this->assertSame(array('foo:barAction', 'foo:fooAction'), array_keys($locator));
+ }
+
+ public function testArgumentWithNoTypeHintIsOk()
+ {
+ $container = new ContainerBuilder();
+ $resolver = $container->register('argument_resolver.service')->addArgument(array());
+
+ $container->register('foo', ArgumentWithoutTypeController::class)
+ ->addTag('controller.service_arguments');
+
+ $pass = new RegisterControllerArgumentLocatorsPass();
+ $pass->process($container);
+
+ $locator = $container->getDefinition((string) $resolver->getArgument(0))->getArgument(0);
+ $this->assertEmpty(array_keys($locator));
+ }
+}
+
+class RegisterTestController
+{
+ public function __construct(ControllerDummy $bar)
+ {
+ }
+
+ public function fooAction(ControllerDummy $bar)
+ {
+ }
+
+ protected function barAction(ControllerDummy $bar)
+ {
+ }
+}
+
+class ContainerAwareRegisterTestController implements ContainerAwareInterface
+{
+ use ContainerAwareTrait;
+
+ public function fooAction(ControllerDummy $bar)
+ {
+ }
+}
+
+class ControllerDummy
+{
+}
+
+class NonExistentClassController
+{
+ public function fooAction(NonExistentClass $nonExistent)
+ {
+ }
+}
+
+class NonExistentClassDifferentNamespaceController
+{
+ public function fooAction(\Acme\NonExistentClass $nonExistent)
+ {
+ }
+}
+
+class NonExistentClassOptionalController
+{
+ public function fooAction(NonExistentClass $nonExistent = null)
+ {
+ }
+
+ public function barAction(NonExistentClass $nonExistent = null, $bar)
+ {
+ }
+}
+
+class ArgumentWithoutTypeController
+{
+ public function fooAction($someArg)
+ {
+ }
+}
diff --git a/vendor/symfony/http-kernel/Tests/DependencyInjection/RemoveEmptyControllerArgumentLocatorsPassTest.php b/vendor/symfony/http-kernel/Tests/DependencyInjection/RemoveEmptyControllerArgumentLocatorsPassTest.php
new file mode 100644
index 0000000000..9cac968185
--- /dev/null
+++ b/vendor/symfony/http-kernel/Tests/DependencyInjection/RemoveEmptyControllerArgumentLocatorsPassTest.php
@@ -0,0 +1,148 @@
+<?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\DependencyInjection;
+
+use PHPUnit\Framework\TestCase;
+use Symfony\Component\DependencyInjection\Compiler\ResolveInvalidReferencesPass;
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\DependencyInjection\Reference;
+use Symfony\Component\HttpKernel\DependencyInjection\RegisterControllerArgumentLocatorsPass;
+use Symfony\Component\HttpKernel\DependencyInjection\RemoveEmptyControllerArgumentLocatorsPass;
+
+class RemoveEmptyControllerArgumentLocatorsPassTest extends TestCase
+{
+ public function testProcess()
+ {
+ $container = new ContainerBuilder();
+ $resolver = $container->register('argument_resolver.service')->addArgument(array());
+
+ $container->register('stdClass', 'stdClass');
+ $container->register(parent::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')));
+
+ $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));
+
+ (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));
+
+ (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)));
+
+ $expectedLog = array(
+ '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());
+
+ $container->register('invokable', InvokableRegisterTestController::class)
+ ->addTag('controller.service_arguments')
+ ;
+
+ (new RegisterControllerArgumentLocatorsPass())->process($container);
+ (new RemoveEmptyControllerArgumentLocatorsPass())->process($container);
+
+ $this->assertEquals(
+ array('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)
+ {
+ }
+}
+
+class RemoveTestController2
+{
+ public function setTestCase(TestCase $test)
+ {
+ }
+
+ public function fooAction(ClassNotInContainer $bar)
+ {
+ }
+}
+
+class InvokableRegisterTestController
+{
+ public function __invoke(\stdClass $bar)
+ {
+ }
+}
+
+class ClassNotInContainer
+{
+}
diff --git a/vendor/symfony/http-kernel/Tests/Event/GetResponseForExceptionEventTest.php b/vendor/symfony/http-kernel/Tests/Event/GetResponseForExceptionEventTest.php
new file mode 100644
index 0000000000..7242579301
--- /dev/null
+++ b/vendor/symfony/http-kernel/Tests/Event/GetResponseForExceptionEventTest.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\Tests\Event;
+
+use PHPUnit\Framework\TestCase;
+use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
+use Symfony\Component\HttpKernel\Tests\TestHttpKernel;
+
+class GetResponseForExceptionEventTest extends TestCase
+{
+ public function testAllowSuccessfulResponseIsFalseByDefault()
+ {
+ $event = new GetResponseForExceptionEvent(new TestHttpKernel(), new Request(), 1, new \Exception());
+
+ $this->assertFalse($event->isAllowingCustomResponseCode());
+ }
+}
diff --git a/vendor/symfony/http-kernel/Tests/EventListener/AddRequestFormatsListenerTest.php b/vendor/symfony/http-kernel/Tests/EventListener/AddRequestFormatsListenerTest.php
new file mode 100644
index 0000000000..f4878f626f
--- /dev/null
+++ b/vendor/symfony/http-kernel/Tests/EventListener/AddRequestFormatsListenerTest.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\Tests\EventListener;
+
+use PHPUnit\Framework\TestCase;
+use Symfony\Component\HttpKernel\EventListener\AddRequestFormatsListener;
+use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\HttpKernel\KernelEvents;
+
+/**
+ * Test AddRequestFormatsListener class.
+ *
+ * @author Gildas Quemener <gildas.quemener@gmail.com>
+ */
+class AddRequestFormatsListenerTest extends TestCase
+{
+ /**
+ * @var AddRequestFormatsListener
+ */
+ private $listener;
+
+ protected function setUp()
+ {
+ $this->listener = new AddRequestFormatsListener(array('csv' => array('text/csv', 'text/plain')));
+ }
+
+ protected function tearDown()
+ {
+ $this->listener = null;
+ }
+
+ public function testIsAnEventSubscriber()
+ {
+ $this->assertInstanceOf('Symfony\Component\EventDispatcher\EventSubscriberInterface', $this->listener);
+ }
+
+ public function testRegisteredEvent()
+ {
+ $this->assertEquals(
+ array(KernelEvents::REQUEST => array('onKernelRequest', 1)),
+ AddRequestFormatsListener::getSubscribedEvents()
+ );
+ }
+
+ public function testSetAdditionalFormats()
+ {
+ $request = $this->getRequestMock();
+ $event = $this->getGetResponseEventMock($request);
+
+ $request->expects($this->once())
+ ->method('setFormat')
+ ->with('csv', array('text/csv', 'text/plain'));
+
+ $this->listener->onKernelRequest($event);
+ }
+
+ protected function getRequestMock()
+ {
+ return $this->getMockBuilder('Symfony\Component\HttpFoundation\Request')->getMock();
+ }
+
+ protected function getGetResponseEventMock(Request $request)
+ {
+ $event = $this
+ ->getMockBuilder('Symfony\Component\HttpKernel\Event\GetResponseEvent')
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $event->expects($this->any())
+ ->method('getRequest')
+ ->will($this->returnValue($request));
+
+ return $event;
+ }
+}
diff --git a/vendor/symfony/http-kernel/Tests/EventListener/DebugHandlersListenerTest.php b/vendor/symfony/http-kernel/Tests/EventListener/DebugHandlersListenerTest.php
new file mode 100644
index 0000000000..d1349906bb
--- /dev/null
+++ b/vendor/symfony/http-kernel/Tests/EventListener/DebugHandlersListenerTest.php
@@ -0,0 +1,135 @@
+<?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 Psr\Log\LogLevel;
+use Symfony\Component\Console\Event\ConsoleEvent;
+use Symfony\Component\Console\Command\Command;
+use Symfony\Component\Console\ConsoleEvents;
+use Symfony\Component\Console\Helper\HelperSet;
+use Symfony\Component\Console\Input\ArgvInput;
+use Symfony\Component\Console\Output\ConsoleOutput;
+use Symfony\Component\Debug\ErrorHandler;
+use Symfony\Component\Debug\ExceptionHandler;
+use Symfony\Component\EventDispatcher\EventDispatcher;
+use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\HttpKernel\Event\KernelEvent;
+use Symfony\Component\HttpKernel\EventListener\DebugHandlersListener;
+use Symfony\Component\HttpKernel\HttpKernelInterface;
+use Symfony\Component\HttpKernel\KernelEvents;
+
+/**
+ * DebugHandlersListenerTest.
+ *
+ * @author Nicolas Grekas <p@tchwork.com>
+ */
+class DebugHandlersListenerTest extends TestCase
+{
+ public function testConfigure()
+ {
+ $logger = $this->getMockBuilder('Psr\Log\LoggerInterface')->getMock();
+ $userHandler = function () {};
+ $listener = new DebugHandlersListener($userHandler, $logger);
+ $xHandler = new ExceptionHandler();
+ $eHandler = new ErrorHandler();
+ $eHandler->setExceptionHandler(array($xHandler, 'handle'));
+
+ $exception = null;
+ set_error_handler(array($eHandler, 'handleError'));
+ set_exception_handler(array($eHandler, 'handleException'));
+ try {
+ $listener->configure();
+ } catch (\Exception $exception) {
+ }
+ restore_exception_handler();
+ restore_error_handler();
+
+ if (null !== $exception) {
+ throw $exception;
+ }
+
+ $this->assertSame($userHandler, $xHandler->setHandler('var_dump'));
+
+ $loggers = $eHandler->setLoggers(array());
+
+ $this->assertArrayHasKey(E_DEPRECATED, $loggers);
+ $this->assertSame(array($logger, LogLevel::INFO), $loggers[E_DEPRECATED]);
+ }
+
+ public function testConfigureForHttpKernelWithNoTerminateWithException()
+ {
+ $listener = new DebugHandlersListener(null);
+ $eHandler = new ErrorHandler();
+ $event = new KernelEvent(
+ $this->getMockBuilder('Symfony\Component\HttpKernel\HttpKernelInterface')->getMock(),
+ Request::create('/'),
+ HttpKernelInterface::MASTER_REQUEST
+ );
+
+ $exception = null;
+ $h = set_exception_handler(array($eHandler, 'handleException'));
+ try {
+ $listener->configure($event);
+ } catch (\Exception $exception) {
+ }
+ restore_exception_handler();
+
+ if (null !== $exception) {
+ throw $exception;
+ }
+
+ $this->assertNull($h);
+ }
+
+ public function testConsoleEvent()
+ {
+ $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()));
+ $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')),
+ );
+ $this->assertSame($xListeners, $dispatcher->getListeners());
+
+ $exception = null;
+ $eHandler = new ErrorHandler();
+ set_error_handler(array($eHandler, 'handleError'));
+ set_exception_handler(array($eHandler, 'handleException'));
+ try {
+ $dispatcher->dispatch(ConsoleEvents::COMMAND, $event);
+ } catch (\Exception $exception) {
+ }
+ restore_exception_handler();
+ restore_error_handler();
+
+ if (null !== $exception) {
+ throw $exception;
+ }
+
+ $xHandler = $eHandler->setExceptionHandler('var_dump');
+ $this->assertInstanceOf('Closure', $xHandler);
+
+ $app->expects($this->once())
+ ->method('renderException');
+
+ $xHandler(new \Exception());
+ }
+}
diff --git a/vendor/symfony/http-kernel/Tests/EventListener/DumpListenerTest.php b/vendor/symfony/http-kernel/Tests/EventListener/DumpListenerTest.php
new file mode 100644
index 0000000000..509f443087
--- /dev/null
+++ b/vendor/symfony/http-kernel/Tests/EventListener/DumpListenerTest.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\Tests\EventListener;
+
+use PHPUnit\Framework\TestCase;
+use Symfony\Component\Console\ConsoleEvents;
+use Symfony\Component\HttpKernel\EventListener\DumpListener;
+use Symfony\Component\VarDumper\Cloner\ClonerInterface;
+use Symfony\Component\VarDumper\Cloner\Data;
+use Symfony\Component\VarDumper\Dumper\DataDumperInterface;
+use Symfony\Component\VarDumper\VarDumper;
+
+/**
+ * DumpListenerTest.
+ *
+ * @author Nicolas Grekas <p@tchwork.com>
+ */
+class DumpListenerTest extends TestCase
+{
+ public function testSubscribedEvents()
+ {
+ $this->assertSame(
+ array(ConsoleEvents::COMMAND => array('configure', 1024)),
+ DumpListener::getSubscribedEvents()
+ );
+ }
+
+ public function testConfigure()
+ {
+ $prevDumper = VarDumper::setHandler('var_dump');
+ VarDumper::setHandler($prevDumper);
+
+ $cloner = new MockCloner();
+ $dumper = new MockDumper();
+
+ ob_start();
+ $exception = null;
+ $listener = new DumpListener($cloner, $dumper);
+
+ try {
+ $listener->configure();
+
+ VarDumper::dump('foo');
+ VarDumper::dump('bar');
+
+ $this->assertSame('+foo-+bar-', ob_get_clean());
+ } catch (\Exception $exception) {
+ }
+
+ VarDumper::setHandler($prevDumper);
+
+ if (null !== $exception) {
+ throw $exception;
+ }
+ }
+}
+
+class MockCloner implements ClonerInterface
+{
+ public function cloneVar($var)
+ {
+ return new Data(array(array($var.'-')));
+ }
+}
+
+class MockDumper implements DataDumperInterface
+{
+ public function dump(Data $data)
+ {
+ echo '+'.$data->getValue();
+ }
+}
diff --git a/vendor/symfony/http-kernel/Tests/EventListener/ExceptionListenerTest.php b/vendor/symfony/http-kernel/Tests/EventListener/ExceptionListenerTest.php
new file mode 100644
index 0000000000..f5501a3f59
--- /dev/null
+++ b/vendor/symfony/http-kernel/Tests/EventListener/ExceptionListenerTest.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\HttpKernel\Tests\EventListener;
+
+use PHPUnit\Framework\TestCase;
+use Symfony\Component\HttpKernel\HttpKernelInterface;
+use Symfony\Component\HttpKernel\EventListener\ExceptionListener;
+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;
+
+/**
+ * ExceptionListenerTest.
+ *
+ * @author Robert Schönthal <seroscho@googlemail.com>
+ *
+ * @group time-sensitive
+ */
+class ExceptionListenerTest extends TestCase
+{
+ public function testConstruct()
+ {
+ $logger = new TestLogger();
+ $l = new ExceptionListener('foo', $logger);
+
+ $_logger = new \ReflectionProperty(get_class($l), 'logger');
+ $_logger->setAccessible(true);
+ $_controller = new \ReflectionProperty(get_class($l), 'controller');
+ $_controller->setAccessible(true);
+
+ $this->assertSame($logger, $_logger->getValue($l));
+ $this->assertSame('foo', $_controller->getValue($l));
+ }
+
+ /**
+ * @dataProvider provider
+ */
+ public function testHandleWithoutLogger($event, $event2)
+ {
+ $this->iniSet('error_log', file_exists('/dev/null') ? '/dev/null' : 'nul');
+
+ $l = new ExceptionListener('foo');
+ $l->onKernelException($event);
+
+ $this->assertEquals(new Response('foo'), $event->getResponse());
+
+ try {
+ $l->onKernelException($event2);
+ $this->fail('RuntimeException expected');
+ } catch (\RuntimeException $e) {
+ $this->assertSame('bar', $e->getMessage());
+ $this->assertSame('foo', $e->getPrevious()->getMessage());
+ }
+ }
+
+ /**
+ * @dataProvider provider
+ */
+ public function testHandleWithLogger($event, $event2)
+ {
+ $logger = new TestLogger();
+
+ $l = new ExceptionListener('foo', $logger);
+ $l->onKernelException($event);
+
+ $this->assertEquals(new Response('foo'), $event->getResponse());
+
+ try {
+ $l->onKernelException($event2);
+ $this->fail('RuntimeException expected');
+ } catch (\RuntimeException $e) {
+ $this->assertSame('bar', $e->getMessage());
+ $this->assertSame('foo', $e->getPrevious()->getMessage());
+ }
+
+ $this->assertEquals(3, $logger->countErrors());
+ $this->assertCount(3, $logger->getLogs('critical'));
+ }
+
+ public function provider()
+ {
+ if (!class_exists('Symfony\Component\HttpFoundation\Request')) {
+ return array(array(null, null));
+ }
+
+ $request = new Request();
+ $exception = new \Exception('foo');
+ $event = new GetResponseForExceptionEvent(new TestKernel(), $request, 'foo', $exception);
+ $event2 = new GetResponseForExceptionEvent(new TestKernelThatThrowsException(), $request, 'foo', $exception);
+
+ return array(
+ array($event, $event2),
+ );
+ }
+
+ public function testSubRequestFormat()
+ {
+ $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) {
+ return new Response($request->getRequestFormat());
+ }));
+
+ $request = Request::create('/');
+ $request->setRequestFormat('xml');
+
+ $event = new GetResponseForExceptionEvent($kernel, $request, 'foo', new \Exception('foo'));
+ $listener->onKernelException($event);
+
+ $response = $event->getResponse();
+ $this->assertEquals('xml', $response->getContent());
+ }
+}
+
+class TestLogger extends Logger implements DebugLoggerInterface
+{
+ public function countErrors()
+ {
+ return count($this->logs['critical']);
+ }
+}
+
+class TestKernel implements HttpKernelInterface
+{
+ public function handle(Request $request, $type = self::MASTER_REQUEST, $catch = true)
+ {
+ return new Response('foo');
+ }
+}
+
+class TestKernelThatThrowsException implements HttpKernelInterface
+{
+ public function handle(Request $request, $type = self::MASTER_REQUEST, $catch = true)
+ {
+ throw new \RuntimeException('bar');
+ }
+}
diff --git a/vendor/symfony/http-kernel/Tests/EventListener/FragmentListenerTest.php b/vendor/symfony/http-kernel/Tests/EventListener/FragmentListenerTest.php
new file mode 100644
index 0000000000..464b2ab462
--- /dev/null
+++ b/vendor/symfony/http-kernel/Tests/EventListener/FragmentListenerTest.php
@@ -0,0 +1,122 @@
+<?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\HttpKernel\EventListener\FragmentListener;
+use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\HttpKernel\HttpKernelInterface;
+use Symfony\Component\HttpKernel\Event\GetResponseEvent;
+use Symfony\Component\HttpKernel\UriSigner;
+
+class FragmentListenerTest extends TestCase
+{
+ public function testOnlyTriggeredOnFragmentRoute()
+ {
+ $request = Request::create('http://example.com/foo?_path=foo%3Dbar%26_controller%3Dfoo');
+
+ $listener = new FragmentListener(new UriSigner('foo'));
+ $event = $this->createGetResponseEvent($request);
+
+ $expected = $request->attributes->all();
+
+ $listener->onKernelRequest($event);
+
+ $this->assertEquals($expected, $request->attributes->all());
+ $this->assertTrue($request->query->has('_path'));
+ }
+
+ public function testOnlyTriggeredIfControllerWasNotDefinedYet()
+ {
+ $request = Request::create('http://example.com/_fragment?_path=foo%3Dbar%26_controller%3Dfoo');
+ $request->attributes->set('_controller', 'bar');
+
+ $listener = new FragmentListener(new UriSigner('foo'));
+ $event = $this->createGetResponseEvent($request, HttpKernelInterface::SUB_REQUEST);
+
+ $expected = $request->attributes->all();
+
+ $listener->onKernelRequest($event);
+
+ $this->assertEquals($expected, $request->attributes->all());
+ }
+
+ /**
+ * @expectedException \Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException
+ */
+ public function testAccessDeniedWithNonSafeMethods()
+ {
+ $request = Request::create('http://example.com/_fragment', 'POST');
+
+ $listener = new FragmentListener(new UriSigner('foo'));
+ $event = $this->createGetResponseEvent($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'));
+
+ $listener = new FragmentListener(new UriSigner('foo'));
+ $event = $this->createGetResponseEvent($request);
+
+ $listener->onKernelRequest($event);
+ }
+
+ 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'));
+
+ $listener = new FragmentListener($signer);
+ $event = $this->createGetResponseEvent($request);
+
+ $listener->onKernelRequest($event);
+
+ $this->assertEquals(array('foo' => 'bar', '_controller' => 'foo'), $request->attributes->get('_route_params'));
+ $this->assertFalse($request->query->has('_path'));
+ }
+
+ public function testRemovesPathWithControllerDefined()
+ {
+ $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);
+
+ $listener->onKernelRequest($event);
+
+ $this->assertFalse($request->query->has('_path'));
+ }
+
+ 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'));
+
+ $listener = new FragmentListener($signer);
+ $event = $this->createGetResponseEvent($request);
+
+ $listener->onKernelRequest($event);
+
+ $this->assertFalse($request->query->has('_path'));
+ }
+
+ private function createGetResponseEvent(Request $request, $requestType = HttpKernelInterface::MASTER_REQUEST)
+ {
+ return new GetResponseEvent($this->getMockBuilder('Symfony\Component\HttpKernel\HttpKernelInterface')->getMock(), $request, $requestType);
+ }
+}
diff --git a/vendor/symfony/http-kernel/Tests/EventListener/LocaleListenerTest.php b/vendor/symfony/http-kernel/Tests/EventListener/LocaleListenerTest.php
new file mode 100644
index 0000000000..2ce32819e1
--- /dev/null
+++ b/vendor/symfony/http-kernel/Tests/EventListener/LocaleListenerTest.php
@@ -0,0 +1,103 @@
+<?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\HttpKernel\EventListener\LocaleListener;
+use Symfony\Component\HttpKernel\HttpKernelInterface;
+use Symfony\Component\HttpKernel\Event\GetResponseEvent;
+
+class LocaleListenerTest extends TestCase
+{
+ private $requestStack;
+
+ protected function setUp()
+ {
+ $this->requestStack = $this->getMockBuilder('Symfony\Component\HttpFoundation\RequestStack')->disableOriginalConstructor()->getMock();
+ }
+
+ public function testDefaultLocaleWithoutSession()
+ {
+ $listener = new LocaleListener($this->requestStack, 'fr');
+ $event = $this->getEvent($request = Request::create('/'));
+
+ $listener->onKernelRequest($event);
+ $this->assertEquals('fr', $request->getLocale());
+ }
+
+ public function testLocaleFromRequestAttribute()
+ {
+ $request = Request::create('/');
+ session_name('foo');
+ $request->cookies->set('foo', 'value');
+
+ $request->attributes->set('_locale', 'es');
+ $listener = new LocaleListener($this->requestStack, 'fr');
+ $event = $this->getEvent($request);
+
+ $listener->onKernelRequest($event);
+ $this->assertEquals('es', $request->getLocale());
+ }
+
+ public function testLocaleSetForRoutingContext()
+ {
+ // the request context is updated
+ $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));
+
+ $request = Request::create('/');
+
+ $request->attributes->set('_locale', 'es');
+ $listener = new LocaleListener($this->requestStack, 'fr', $router);
+ $listener->onKernelRequest($this->getEvent($request));
+ }
+
+ public function testRouterResetWithParentRequestOnKernelFinishRequest()
+ {
+ // the request context is updated
+ $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));
+
+ $parentRequest = Request::create('/');
+ $parentRequest->setLocale('es');
+
+ $this->requestStack->expects($this->once())->method('getParentRequest')->will($this->returnValue($parentRequest));
+
+ $event = $this->getMockBuilder('Symfony\Component\HttpKernel\Event\FinishRequestEvent')->disableOriginalConstructor()->getMock();
+
+ $listener = new LocaleListener($this->requestStack, 'fr', $router);
+ $listener->onKernelFinishRequest($event);
+ }
+
+ public function testRequestLocaleIsNotOverridden()
+ {
+ $request = Request::create('/');
+ $request->setLocale('de');
+ $listener = new LocaleListener($this->requestStack, 'fr');
+ $event = $this->getEvent($request);
+
+ $listener->onKernelRequest($event);
+ $this->assertEquals('de', $request->getLocale());
+ }
+
+ private function getEvent(Request $request)
+ {
+ return new GetResponseEvent($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
new file mode 100644
index 0000000000..751aee8695
--- /dev/null
+++ b/vendor/symfony/http-kernel/Tests/EventListener/ProfilerListenerTest.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\HttpKernel\Tests\EventListener;
+
+use PHPUnit\Framework\TestCase;
+use Symfony\Component\HttpFoundation\RequestStack;
+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;
+
+class ProfilerListenerTest extends TestCase
+{
+ /**
+ * Test a master and sub request with an exception and `onlyException` profiler option enabled.
+ */
+ public function testKernelTerminate()
+ {
+ $profile = $this->getMockBuilder('Symfony\Component\HttpKernel\Profiler\Profile')
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $profiler = $this->getMockBuilder('Symfony\Component\HttpKernel\Profiler\Profiler')
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $profiler->expects($this->once())
+ ->method('collect')
+ ->will($this->returnValue($profile));
+
+ $kernel = $this->getMockBuilder('Symfony\Component\HttpKernel\HttpKernelInterface')->getMock();
+
+ $masterRequest = $this->getMockBuilder('Symfony\Component\HttpFoundation\Request')
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $subRequest = $this->getMockBuilder('Symfony\Component\HttpFoundation\Request')
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $response = $this->getMockBuilder('Symfony\Component\HttpFoundation\Response')
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $requestStack = new RequestStack();
+ $requestStack->push($masterRequest);
+
+ $onlyException = true;
+ $listener = new ProfilerListener($profiler, $requestStack, null, $onlyException);
+
+ // master request
+ $listener->onKernelResponse(new FilterResponseEvent($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->onKernelTerminate(new PostResponseEvent($kernel, $masterRequest, $response));
+ }
+}
diff --git a/vendor/symfony/http-kernel/Tests/EventListener/ResponseListenerTest.php b/vendor/symfony/http-kernel/Tests/EventListener/ResponseListenerTest.php
new file mode 100644
index 0000000000..12a31eb3ee
--- /dev/null
+++ b/vendor/symfony/http-kernel/Tests/EventListener/ResponseListenerTest.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\HttpKernel\Tests\EventListener;
+
+use PHPUnit\Framework\TestCase;
+use Symfony\Component\HttpKernel\EventListener\ResponseListener;
+use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\HttpFoundation\Response;
+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
+{
+ private $dispatcher;
+
+ private $kernel;
+
+ protected function setUp()
+ {
+ $this->dispatcher = new EventDispatcher();
+ $listener = new ResponseListener('UTF-8');
+ $this->dispatcher->addListener(KernelEvents::RESPONSE, array($listener, 'onKernelResponse'));
+
+ $this->kernel = $this->getMockBuilder('Symfony\Component\HttpKernel\HttpKernelInterface')->getMock();
+ }
+
+ protected function tearDown()
+ {
+ $this->dispatcher = null;
+ $this->kernel = null;
+ }
+
+ public function testFilterDoesNothingForSubRequests()
+ {
+ $response = new Response('foo');
+
+ $event = new FilterResponseEvent($this->kernel, new Request(), HttpKernelInterface::SUB_REQUEST, $response);
+ $this->dispatcher->dispatch(KernelEvents::RESPONSE, $event);
+
+ $this->assertEquals('', $event->getResponse()->headers->get('content-type'));
+ }
+
+ public function testFilterSetsNonDefaultCharsetIfNotOverridden()
+ {
+ $listener = new ResponseListener('ISO-8859-15');
+ $this->dispatcher->addListener(KernelEvents::RESPONSE, array($listener, 'onKernelResponse'), 1);
+
+ $response = new Response('foo');
+
+ $event = new FilterResponseEvent($this->kernel, Request::create('/'), HttpKernelInterface::MASTER_REQUEST, $response);
+ $this->dispatcher->dispatch(KernelEvents::RESPONSE, $event);
+
+ $this->assertEquals('ISO-8859-15', $response->getCharset());
+ }
+
+ public function testFilterDoesNothingIfCharsetIsOverridden()
+ {
+ $listener = new ResponseListener('ISO-8859-15');
+ $this->dispatcher->addListener(KernelEvents::RESPONSE, array($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);
+
+ $this->assertEquals('ISO-8859-1', $response->getCharset());
+ }
+
+ public function testFiltersSetsNonDefaultCharsetIfNotOverriddenOnNonTextContentType()
+ {
+ $listener = new ResponseListener('ISO-8859-15');
+ $this->dispatcher->addListener(KernelEvents::RESPONSE, array($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);
+
+ $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
new file mode 100644
index 0000000000..a40e57998d
--- /dev/null
+++ b/vendor/symfony/http-kernel/Tests/EventListener/RouterListenerTest.php
@@ -0,0 +1,188 @@
+<?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\EventDispatcher\EventDispatcher;
+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\ControllerResolver;
+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\Routing\RequestContext;
+
+class RouterListenerTest extends TestCase
+{
+ private $requestStack;
+
+ protected function setUp()
+ {
+ $this->requestStack = $this->getMockBuilder('Symfony\Component\HttpFoundation\RequestStack')->disableOriginalConstructor()->getMock();
+ }
+
+ /**
+ * @dataProvider getPortData
+ */
+ public function testPort($defaultHttpPort, $defaultHttpsPort, $uri, $expectedHttpPort, $expectedHttpsPort)
+ {
+ $urlMatcher = $this->getMockBuilder('Symfony\Component\Routing\Matcher\UrlMatcherInterface')
+ ->disableOriginalConstructor()
+ ->getMock();
+ $context = new RequestContext();
+ $context->setHttpPort($defaultHttpPort);
+ $context->setHttpsPort($defaultHttpsPort);
+ $urlMatcher->expects($this->any())
+ ->method('getContext')
+ ->will($this->returnValue($context));
+
+ $listener = new RouterListener($urlMatcher, $this->requestStack);
+ $event = $this->createGetResponseEventForUri($uri);
+ $listener->onKernelRequest($event);
+
+ $this->assertEquals($expectedHttpPort, $context->getHttpPort());
+ $this->assertEquals($expectedHttpsPort, $context->getHttpsPort());
+ $this->assertEquals(0 === strpos($uri, 'https') ? 'https' : 'http', $context->getScheme());
+ }
+
+ 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),
+ );
+ }
+
+ /**
+ * @param string $uri
+ *
+ * @return GetResponseEvent
+ */
+ private function createGetResponseEventForUri($uri)
+ {
+ $kernel = $this->getMockBuilder('Symfony\Component\HttpKernel\HttpKernelInterface')->getMock();
+ $request = Request::create($uri);
+ $request->attributes->set('_controller', null); // Prevents going in to routing process
+
+ return new GetResponseEvent($kernel, $request, HttpKernelInterface::MASTER_REQUEST);
+ }
+
+ /**
+ * @expectedException \InvalidArgumentException
+ */
+ public function testInvalidMatcher()
+ {
+ new RouterListener(new \stdClass(), $this->requestStack);
+ }
+
+ public function testRequestMatcher()
+ {
+ $kernel = $this->getMockBuilder('Symfony\Component\HttpKernel\HttpKernelInterface')->getMock();
+ $request = Request::create('http://localhost/');
+ $event = new GetResponseEvent($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()));
+
+ $listener = new RouterListener($requestMatcher, $this->requestStack, new RequestContext());
+ $listener->onKernelRequest($event);
+ }
+
+ public function testSubRequestWithDifferentMethod()
+ {
+ $kernel = $this->getMockBuilder('Symfony\Component\HttpKernel\HttpKernelInterface')->getMock();
+ $request = Request::create('http://localhost/', 'post');
+ $event = new GetResponseEvent($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()));
+
+ $context = new RequestContext();
+
+ $listener = new RouterListener($requestMatcher, $this->requestStack, new RequestContext());
+ $listener->onKernelRequest($event);
+
+ // sub-request with another HTTP method
+ $kernel = $this->getMockBuilder('Symfony\Component\HttpKernel\HttpKernelInterface')->getMock();
+ $request = Request::create('http://localhost/', 'get');
+ $event = new GetResponseEvent($kernel, $request, HttpKernelInterface::SUB_REQUEST);
+
+ $listener->onKernelRequest($event);
+
+ $this->assertEquals('GET', $context->getMethod());
+ }
+
+ /**
+ * @dataProvider getLoggingParameterData
+ */
+ public function testLoggingParameter($parameter, $log, $parameters)
+ {
+ $requestMatcher = $this->getMockBuilder('Symfony\Component\Routing\Matcher\RequestMatcherInterface')->getMock();
+ $requestMatcher->expects($this->once())
+ ->method('matchRequest')
+ ->will($this->returnValue($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();
+ $request = Request::create('http://localhost/');
+
+ $listener = new RouterListener($requestMatcher, $this->requestStack, new RequestContext(), $logger);
+ $listener->onKernelRequest(new GetResponseEvent($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')),
+ );
+ }
+
+ public function testWithBadRequest()
+ {
+ $requestStack = new RequestStack();
+
+ $requestMatcher = $this->getMockBuilder('Symfony\Component\Routing\Matcher\RequestMatcherInterface')->getMock();
+ $requestMatcher->expects($this->never())->method('matchRequest');
+
+ $dispatcher = new EventDispatcher();
+ $dispatcher->addSubscriber(new ValidateRequestListener());
+ $dispatcher->addSubscriber(new RouterListener($requestMatcher, $requestStack, new RequestContext()));
+ $dispatcher->addSubscriber(new ExceptionListener(function () {
+ return new Response('Exception handled', 400);
+ }));
+
+ $kernel = new HttpKernel($dispatcher, new ControllerResolver(), $requestStack, new ArgumentResolver());
+
+ $request = Request::create('http://localhost/');
+ $request->headers->set('host', '###');
+ $response = $kernel->handle($request);
+ $this->assertSame(400, $response->getStatusCode());
+ }
+}
diff --git a/vendor/symfony/http-kernel/Tests/EventListener/SurrogateListenerTest.php b/vendor/symfony/http-kernel/Tests/EventListener/SurrogateListenerTest.php
new file mode 100644
index 0000000000..1e79ebe052
--- /dev/null
+++ b/vendor/symfony/http-kernel/Tests/EventListener/SurrogateListenerTest.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\HttpKernel\Tests\EventListener;
+
+use PHPUnit\Framework\TestCase;
+use Symfony\Component\HttpKernel\HttpCache\Esi;
+use Symfony\Component\HttpKernel\EventListener\SurrogateListener;
+use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
+use Symfony\Component\HttpKernel\KernelEvents;
+use Symfony\Component\HttpKernel\HttpKernelInterface;
+use Symfony\Component\HttpFoundation\Response;
+use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\EventDispatcher\EventDispatcher;
+
+class SurrogateListenerTest extends TestCase
+{
+ public function testFilterDoesNothingForSubRequests()
+ {
+ $dispatcher = new EventDispatcher();
+ $kernel = $this->getMockBuilder('Symfony\Component\HttpKernel\HttpKernelInterface')->getMock();
+ $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);
+
+ $this->assertEquals('', $event->getResponse()->headers->get('Surrogate-Control'));
+ }
+
+ public function testFilterWhenThereIsSomeEsiIncludes()
+ {
+ $dispatcher = new EventDispatcher();
+ $kernel = $this->getMockBuilder('Symfony\Component\HttpKernel\HttpKernelInterface')->getMock();
+ $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);
+
+ $this->assertEquals('content="ESI/1.0"', $event->getResponse()->headers->get('Surrogate-Control'));
+ }
+
+ public function testFilterWhenThereIsNoEsiIncludes()
+ {
+ $dispatcher = new EventDispatcher();
+ $kernel = $this->getMockBuilder('Symfony\Component\HttpKernel\HttpKernelInterface')->getMock();
+ $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);
+
+ $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
new file mode 100644
index 0000000000..8ada8e7dd8
--- /dev/null
+++ b/vendor/symfony/http-kernel/Tests/EventListener/TestSessionListenerTest.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\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\HttpKernel\EventListener\SessionListener;
+use Symfony\Component\HttpKernel\EventListener\TestSessionListener;
+use Symfony\Component\HttpFoundation\Session\SessionInterface;
+
+/**
+ * SessionListenerTest.
+ *
+ * Tests SessionListener.
+ *
+ * @author Bulat Shakirzyanov <mallluhuct@gmail.com>
+ */
+class TestSessionListenerTest extends TestCase
+{
+ /**
+ * @var TestSessionListener
+ */
+ private $listener;
+
+ /**
+ * @var SessionInterface
+ */
+ private $session;
+
+ protected function setUp()
+ {
+ $this->listener = $this->getMockForAbstractClass('Symfony\Component\HttpKernel\EventListener\AbstractTestSessionListener');
+ $this->session = $this->getSession();
+ }
+
+ public function testShouldSaveMasterRequestSession()
+ {
+ $this->sessionHasBeenStarted();
+ $this->sessionMustBeSaved();
+
+ $this->filterResponse(new Request());
+ }
+
+ public function testShouldNotSaveSubRequestSession()
+ {
+ $this->sessionMustNotBeSaved();
+
+ $this->filterResponse(new Request(), HttpKernelInterface::SUB_REQUEST);
+ }
+
+ public function testDoesNotDeleteCookieIfUsingSessionLifetime()
+ {
+ $this->sessionHasBeenStarted();
+
+ $params = session_get_cookie_params();
+ session_set_cookie_params(0, $params['path'], $params['domain'], $params['secure'], $params['httponly']);
+
+ $response = $this->filterResponse(new Request(), HttpKernelInterface::MASTER_REQUEST);
+ $cookies = $response->headers->getCookies();
+
+ $this->assertEquals(0, reset($cookies)->getExpiresTime());
+ }
+
+ public function testUnstartedSessionIsNotSave()
+ {
+ $this->sessionHasNotBeenStarted();
+ $this->sessionMustNotBeSaved();
+
+ $this->filterResponse(new Request());
+ }
+
+ public function testDoesNotImplementServiceSubscriberInterface()
+ {
+ $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'));
+ }
+
+ private function filterResponse(Request $request, $type = HttpKernelInterface::MASTER_REQUEST)
+ {
+ $request->setSession($this->session);
+ $response = new Response();
+ $kernel = $this->getMockBuilder('Symfony\Component\HttpKernel\HttpKernelInterface')->getMock();
+ $event = new FilterResponseEvent($kernel, $request, $type, $response);
+
+ $this->listener->onKernelResponse($event);
+
+ $this->assertSame($response, $event->getResponse());
+
+ return $response;
+ }
+
+ private function sessionMustNotBeSaved()
+ {
+ $this->session->expects($this->never())
+ ->method('save');
+ }
+
+ private function sessionMustBeSaved()
+ {
+ $this->session->expects($this->once())
+ ->method('save');
+ }
+
+ private function sessionHasBeenStarted()
+ {
+ $this->session->expects($this->once())
+ ->method('isStarted')
+ ->will($this->returnValue(true));
+ }
+
+ private function sessionHasNotBeenStarted()
+ {
+ $this->session->expects($this->once())
+ ->method('isStarted')
+ ->will($this->returnValue(false));
+ }
+
+ private function getSession()
+ {
+ $mock = $this->getMockBuilder('Symfony\Component\HttpFoundation\Session\Session')
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ // set return value for getName()
+ $mock->expects($this->any())->method('getName')->will($this->returnValue('MOCKSESSID'));
+
+ return $mock;
+ }
+}
diff --git a/vendor/symfony/http-kernel/Tests/EventListener/TranslatorListenerTest.php b/vendor/symfony/http-kernel/Tests/EventListener/TranslatorListenerTest.php
new file mode 100644
index 0000000000..23b833177a
--- /dev/null
+++ b/vendor/symfony/http-kernel/Tests/EventListener/TranslatorListenerTest.php
@@ -0,0 +1,118 @@
+<?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\HttpKernel\Event\FinishRequestEvent;
+use Symfony\Component\HttpKernel\Event\GetResponseEvent;
+use Symfony\Component\HttpKernel\EventListener\TranslatorListener;
+use Symfony\Component\HttpKernel\HttpKernelInterface;
+
+class TranslatorListenerTest extends TestCase
+{
+ private $listener;
+ private $translator;
+ private $requestStack;
+
+ protected function setUp()
+ {
+ $this->translator = $this->getMockBuilder('Symfony\Component\Translation\TranslatorInterface')->getMock();
+ $this->requestStack = $this->getMockBuilder('Symfony\Component\HttpFoundation\RequestStack')->getMock();
+ $this->listener = new TranslatorListener($this->translator, $this->requestStack);
+ }
+
+ public function testLocaleIsSetInOnKernelRequest()
+ {
+ $this->translator
+ ->expects($this->once())
+ ->method('setLocale')
+ ->with($this->equalTo('fr'));
+
+ $event = new GetResponseEvent($this->createHttpKernel(), $this->createRequest('fr'), HttpKernelInterface::MASTER_REQUEST);
+ $this->listener->onKernelRequest($event);
+ }
+
+ public function testDefaultLocaleIsUsedOnExceptionsInOnKernelRequest()
+ {
+ $this->translator
+ ->expects($this->at(0))
+ ->method('setLocale')
+ ->will($this->throwException(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);
+ $this->listener->onKernelRequest($event);
+ }
+
+ public function testLocaleIsSetInOnKernelFinishRequestWhenParentRequestExists()
+ {
+ $this->translator
+ ->expects($this->once())
+ ->method('setLocale')
+ ->with($this->equalTo('fr'));
+
+ $this->setMasterRequest($this->createRequest('fr'));
+ $event = new FinishRequestEvent($this->createHttpKernel(), $this->createRequest('de'), HttpKernelInterface::SUB_REQUEST);
+ $this->listener->onKernelFinishRequest($event);
+ }
+
+ public function testLocaleIsNotSetInOnKernelFinishRequestWhenParentRequestDoesNotExist()
+ {
+ $this->translator
+ ->expects($this->never())
+ ->method('setLocale');
+
+ $event = new FinishRequestEvent($this->createHttpKernel(), $this->createRequest('de'), HttpKernelInterface::SUB_REQUEST);
+ $this->listener->onKernelFinishRequest($event);
+ }
+
+ public function testDefaultLocaleIsUsedOnExceptionsInOnKernelFinishRequest()
+ {
+ $this->translator
+ ->expects($this->at(0))
+ ->method('setLocale')
+ ->will($this->throwException(new \InvalidArgumentException()));
+ $this->translator
+ ->expects($this->at(1))
+ ->method('setLocale')
+ ->with($this->equalTo('en'));
+
+ $this->setMasterRequest($this->createRequest('fr'));
+ $event = new FinishRequestEvent($this->createHttpKernel(), $this->createRequest('de'), 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;
+ }
+
+ private function setMasterRequest($request)
+ {
+ $this->requestStack
+ ->expects($this->any())
+ ->method('getParentRequest')
+ ->will($this->returnValue($request));
+ }
+}
diff --git a/vendor/symfony/http-kernel/Tests/EventListener/ValidateRequestListenerTest.php b/vendor/symfony/http-kernel/Tests/EventListener/ValidateRequestListenerTest.php
new file mode 100644
index 0000000000..d060943255
--- /dev/null
+++ b/vendor/symfony/http-kernel/Tests/EventListener/ValidateRequestListenerTest.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\Tests\EventListener;
+
+use PHPUnit\Framework\TestCase;
+use Symfony\Component\EventDispatcher\EventDispatcher;
+use Symfony\Component\HttpFoundation\Request;
+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
+ */
+ public function testListenerThrowsWhenMasterRequestHasInconsistentClientIps()
+ {
+ $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->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->dispatch(KernelEvents::REQUEST, $event);
+ }
+}
diff --git a/vendor/symfony/http-kernel/Tests/Exception/AccessDeniedHttpExceptionTest.php b/vendor/symfony/http-kernel/Tests/Exception/AccessDeniedHttpExceptionTest.php
new file mode 100644
index 0000000000..2bfcb2bf80
--- /dev/null
+++ b/vendor/symfony/http-kernel/Tests/Exception/AccessDeniedHttpExceptionTest.php
@@ -0,0 +1,13 @@
+<?php
+
+namespace Symfony\Component\HttpKernel\Tests\Exception;
+
+use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
+
+class AccessDeniedHttpExceptionTest extends HttpExceptionTest
+{
+ protected function createException()
+ {
+ return new AccessDeniedHttpException();
+ }
+}
diff --git a/vendor/symfony/http-kernel/Tests/Exception/BadRequestHttpExceptionTest.php b/vendor/symfony/http-kernel/Tests/Exception/BadRequestHttpExceptionTest.php
new file mode 100644
index 0000000000..5fd54ccf44
--- /dev/null
+++ b/vendor/symfony/http-kernel/Tests/Exception/BadRequestHttpExceptionTest.php
@@ -0,0 +1,13 @@
+<?php
+
+namespace Symfony\Component\HttpKernel\Tests\Exception;
+
+use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
+
+class BadRequestHttpExceptionTest extends HttpExceptionTest
+{
+ protected function createException()
+ {
+ return new BadRequestHttpException();
+ }
+}
diff --git a/vendor/symfony/http-kernel/Tests/Exception/ConflictHttpExceptionTest.php b/vendor/symfony/http-kernel/Tests/Exception/ConflictHttpExceptionTest.php
new file mode 100644
index 0000000000..63cb49e6e0
--- /dev/null
+++ b/vendor/symfony/http-kernel/Tests/Exception/ConflictHttpExceptionTest.php
@@ -0,0 +1,13 @@
+<?php
+
+namespace Symfony\Component\HttpKernel\Tests\Exception;
+
+use Symfony\Component\HttpKernel\Exception\ConflictHttpException;
+
+class ConflictHttpExceptionTest extends HttpExceptionTest
+{
+ protected function createException()
+ {
+ return new ConflictHttpException();
+ }
+}
diff --git a/vendor/symfony/http-kernel/Tests/Exception/GoneHttpExceptionTest.php b/vendor/symfony/http-kernel/Tests/Exception/GoneHttpExceptionTest.php
new file mode 100644
index 0000000000..ec5339d2af
--- /dev/null
+++ b/vendor/symfony/http-kernel/Tests/Exception/GoneHttpExceptionTest.php
@@ -0,0 +1,13 @@
+<?php
+
+namespace Symfony\Component\HttpKernel\Tests\Exception;
+
+use Symfony\Component\HttpKernel\Exception\GoneHttpException;
+
+class GoneHttpExceptionTest extends HttpExceptionTest
+{
+ protected function createException()
+ {
+ return new GoneHttpException();
+ }
+}
diff --git a/vendor/symfony/http-kernel/Tests/Exception/HttpExceptionTest.php b/vendor/symfony/http-kernel/Tests/Exception/HttpExceptionTest.php
new file mode 100644
index 0000000000..b64773551e
--- /dev/null
+++ b/vendor/symfony/http-kernel/Tests/Exception/HttpExceptionTest.php
@@ -0,0 +1,53 @@
+<?php
+
+namespace Symfony\Component\HttpKernel\Tests\Exception;
+
+use PHPUnit\Framework\TestCase;
+use Symfony\Component\HttpKernel\Exception\HttpException;
+
+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'),
+ ),
+ ),
+ );
+ }
+
+ public function testHeadersDefault()
+ {
+ $exception = $this->createException();
+ $this->assertSame(array(), $exception->getHeaders());
+ }
+
+ /**
+ * @dataProvider headerDataProvider
+ */
+ public function testHeadersConstructor($headers)
+ {
+ $exception = new HttpException(200, null, null, $headers);
+ $this->assertSame($headers, $exception->getHeaders());
+ }
+
+ /**
+ * @dataProvider headerDataProvider
+ */
+ public function testHeadersSetter($headers)
+ {
+ $exception = $this->createException();
+ $exception->setHeaders($headers);
+ $this->assertSame($headers, $exception->getHeaders());
+ }
+
+ protected function createException()
+ {
+ return new HttpException(200);
+ }
+}
diff --git a/vendor/symfony/http-kernel/Tests/Exception/LengthRequiredHttpExceptionTest.php b/vendor/symfony/http-kernel/Tests/Exception/LengthRequiredHttpExceptionTest.php
new file mode 100644
index 0000000000..462d3ca4fc
--- /dev/null
+++ b/vendor/symfony/http-kernel/Tests/Exception/LengthRequiredHttpExceptionTest.php
@@ -0,0 +1,13 @@
+<?php
+
+namespace Symfony\Component\HttpKernel\Tests\Exception;
+
+use Symfony\Component\HttpKernel\Exception\LengthRequiredHttpException;
+
+class LengthRequiredHttpExceptionTest extends HttpExceptionTest
+{
+ protected function createException()
+ {
+ return new LengthRequiredHttpException();
+ }
+}
diff --git a/vendor/symfony/http-kernel/Tests/Exception/MethodNotAllowedHttpExceptionTest.php b/vendor/symfony/http-kernel/Tests/Exception/MethodNotAllowedHttpExceptionTest.php
new file mode 100644
index 0000000000..b5def13ce3
--- /dev/null
+++ b/vendor/symfony/http-kernel/Tests/Exception/MethodNotAllowedHttpExceptionTest.php
@@ -0,0 +1,24 @@
+<?php
+
+namespace Symfony\Component\HttpKernel\Tests\Exception;
+
+use Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException;
+
+class MethodNotAllowedHttpExceptionTest extends HttpExceptionTest
+{
+ public function testHeadersDefault()
+ {
+ $exception = new MethodNotAllowedHttpException(array('GET', 'PUT'));
+ $this->assertSame(array('Allow' => 'GET, PUT'), $exception->getHeaders());
+ }
+
+ /**
+ * @dataProvider headerDataProvider
+ */
+ public function testHeadersSetter($headers)
+ {
+ $exception = new MethodNotAllowedHttpException(array('GET'));
+ $exception->setHeaders($headers);
+ $this->assertSame($headers, $exception->getHeaders());
+ }
+}
diff --git a/vendor/symfony/http-kernel/Tests/Exception/NotAcceptableHttpExceptionTest.php b/vendor/symfony/http-kernel/Tests/Exception/NotAcceptableHttpExceptionTest.php
new file mode 100644
index 0000000000..4c0db7a3cb
--- /dev/null
+++ b/vendor/symfony/http-kernel/Tests/Exception/NotAcceptableHttpExceptionTest.php
@@ -0,0 +1,13 @@
+<?php
+
+namespace Symfony\Component\HttpKernel\Tests\Exception;
+
+use Symfony\Component\HttpKernel\Exception\NotAcceptableHttpException;
+
+class NotAcceptableHttpExceptionTest extends HttpExceptionTest
+{
+ protected function createException()
+ {
+ return new NotAcceptableHttpException();
+ }
+}
diff --git a/vendor/symfony/http-kernel/Tests/Exception/NotFoundHttpExceptionTest.php b/vendor/symfony/http-kernel/Tests/Exception/NotFoundHttpExceptionTest.php
new file mode 100644
index 0000000000..62ede5b4b8
--- /dev/null
+++ b/vendor/symfony/http-kernel/Tests/Exception/NotFoundHttpExceptionTest.php
@@ -0,0 +1,13 @@
+<?php
+
+namespace Symfony\Component\HttpKernel\Tests\Exception;
+
+use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
+
+class NotFoundHttpExceptionTest extends HttpExceptionTest
+{
+ protected function createException()
+ {
+ return new NotFoundHttpException();
+ }
+}
diff --git a/vendor/symfony/http-kernel/Tests/Exception/PreconditionFailedHttpExceptionTest.php b/vendor/symfony/http-kernel/Tests/Exception/PreconditionFailedHttpExceptionTest.php
new file mode 100644
index 0000000000..809252b757
--- /dev/null
+++ b/vendor/symfony/http-kernel/Tests/Exception/PreconditionFailedHttpExceptionTest.php
@@ -0,0 +1,13 @@
+<?php
+
+namespace Symfony\Component\HttpKernel\Tests\Exception;
+
+use Symfony\Component\HttpKernel\Exception\PreconditionFailedHttpException;
+
+class PreconditionFailedHttpExceptionTest extends HttpExceptionTest
+{
+ protected function createException()
+ {
+ return new PreconditionFailedHttpException();
+ }
+}
diff --git a/vendor/symfony/http-kernel/Tests/Exception/PreconditionRequiredHttpExceptionTest.php b/vendor/symfony/http-kernel/Tests/Exception/PreconditionRequiredHttpExceptionTest.php
new file mode 100644
index 0000000000..69d362e3f6
--- /dev/null
+++ b/vendor/symfony/http-kernel/Tests/Exception/PreconditionRequiredHttpExceptionTest.php
@@ -0,0 +1,13 @@
+<?php
+
+namespace Symfony\Component\HttpKernel\Tests\Exception;
+
+use Symfony\Component\HttpKernel\Exception\PreconditionRequiredHttpException;
+
+class PreconditionRequiredHttpExceptionTest extends HttpExceptionTest
+{
+ protected function createException()
+ {
+ return new PreconditionRequiredHttpException();
+ }
+}
diff --git a/vendor/symfony/http-kernel/Tests/Exception/ServiceUnavailableHttpExceptionTest.php b/vendor/symfony/http-kernel/Tests/Exception/ServiceUnavailableHttpExceptionTest.php
new file mode 100644
index 0000000000..e41a23d4e7
--- /dev/null
+++ b/vendor/symfony/http-kernel/Tests/Exception/ServiceUnavailableHttpExceptionTest.php
@@ -0,0 +1,29 @@
+<?php
+
+namespace Symfony\Component\HttpKernel\Tests\Exception;
+
+use Symfony\Component\HttpKernel\Exception\ServiceUnavailableHttpException;
+
+class ServiceUnavailableHttpExceptionTest extends HttpExceptionTest
+{
+ public function testHeadersDefaultRetryAfter()
+ {
+ $exception = new ServiceUnavailableHttpException(10);
+ $this->assertSame(array('Retry-After' => 10), $exception->getHeaders());
+ }
+
+ /**
+ * @dataProvider headerDataProvider
+ */
+ public function testHeadersSetter($headers)
+ {
+ $exception = new ServiceUnavailableHttpException(10);
+ $exception->setHeaders($headers);
+ $this->assertSame($headers, $exception->getHeaders());
+ }
+
+ protected function createException()
+ {
+ return new ServiceUnavailableHttpException();
+ }
+}
diff --git a/vendor/symfony/http-kernel/Tests/Exception/TooManyRequestsHttpExceptionTest.php b/vendor/symfony/http-kernel/Tests/Exception/TooManyRequestsHttpExceptionTest.php
new file mode 100644
index 0000000000..2079bb3380
--- /dev/null
+++ b/vendor/symfony/http-kernel/Tests/Exception/TooManyRequestsHttpExceptionTest.php
@@ -0,0 +1,29 @@
+<?php
+
+namespace Symfony\Component\HttpKernel\Tests\Exception;
+
+use Symfony\Component\HttpKernel\Exception\TooManyRequestsHttpException;
+
+class TooManyRequestsHttpExceptionTest extends HttpExceptionTest
+{
+ public function testHeadersDefaultRertyAfter()
+ {
+ $exception = new TooManyRequestsHttpException(10);
+ $this->assertSame(array('Retry-After' => 10), $exception->getHeaders());
+ }
+
+ /**
+ * @dataProvider headerDataProvider
+ */
+ public function testHeadersSetter($headers)
+ {
+ $exception = new TooManyRequestsHttpException(10);
+ $exception->setHeaders($headers);
+ $this->assertSame($headers, $exception->getHeaders());
+ }
+
+ protected function createException()
+ {
+ return new TooManyRequestsHttpException();
+ }
+}
diff --git a/vendor/symfony/http-kernel/Tests/Exception/UnauthorizedHttpExceptionTest.php b/vendor/symfony/http-kernel/Tests/Exception/UnauthorizedHttpExceptionTest.php
new file mode 100644
index 0000000000..37a0028dc8
--- /dev/null
+++ b/vendor/symfony/http-kernel/Tests/Exception/UnauthorizedHttpExceptionTest.php
@@ -0,0 +1,24 @@
+<?php
+
+namespace Symfony\Component\HttpKernel\Tests\Exception;
+
+use Symfony\Component\HttpKernel\Exception\UnauthorizedHttpException;
+
+class UnauthorizedHttpExceptionTest extends HttpExceptionTest
+{
+ public function testHeadersDefault()
+ {
+ $exception = new UnauthorizedHttpException('Challenge');
+ $this->assertSame(array('WWW-Authenticate' => 'Challenge'), $exception->getHeaders());
+ }
+
+ /**
+ * @dataProvider headerDataProvider
+ */
+ public function testHeadersSetter($headers)
+ {
+ $exception = new UnauthorizedHttpException('Challenge');
+ $exception->setHeaders($headers);
+ $this->assertSame($headers, $exception->getHeaders());
+ }
+}
diff --git a/vendor/symfony/http-kernel/Tests/Exception/UnprocessableEntityHttpExceptionTest.php b/vendor/symfony/http-kernel/Tests/Exception/UnprocessableEntityHttpExceptionTest.php
new file mode 100644
index 0000000000..760366c694
--- /dev/null
+++ b/vendor/symfony/http-kernel/Tests/Exception/UnprocessableEntityHttpExceptionTest.php
@@ -0,0 +1,28 @@
+<?php
+
+namespace Symfony\Component\HttpKernel\Tests\Exception;
+
+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)
+ {
+ $exception = new UnprocessableEntityHttpException(10);
+ $exception->setHeaders($headers);
+ $this->assertSame($headers, $exception->getHeaders());
+ }
+
+ protected function createException()
+ {
+ return new UnprocessableEntityHttpException();
+ }
+}
diff --git a/vendor/symfony/http-kernel/Tests/Exception/UnsupportedMediaTypeHttpExceptionTest.php b/vendor/symfony/http-kernel/Tests/Exception/UnsupportedMediaTypeHttpExceptionTest.php
new file mode 100644
index 0000000000..d47287a1fb
--- /dev/null
+++ b/vendor/symfony/http-kernel/Tests/Exception/UnsupportedMediaTypeHttpExceptionTest.php
@@ -0,0 +1,23 @@
+<?php
+
+namespace Symfony\Component\HttpKernel\Tests\Exception;
+
+use Symfony\Component\HttpKernel\Exception\UnsupportedMediaTypeHttpException;
+
+class UnsupportedMediaTypeHttpExceptionTest extends HttpExceptionTest
+{
+ /**
+ * @dataProvider headerDataProvider
+ */
+ public function testHeadersSetter($headers)
+ {
+ $exception = new UnsupportedMediaTypeHttpException(10);
+ $exception->setHeaders($headers);
+ $this->assertSame($headers, $exception->getHeaders());
+ }
+
+ protected function createException($headers = array())
+ {
+ return new UnsupportedMediaTypeHttpException();
+ }
+}
diff --git a/vendor/symfony/http-kernel/Tests/Fixtures/123/Kernel123.php b/vendor/symfony/http-kernel/Tests/Fixtures/123/Kernel123.php
new file mode 100644
index 0000000000..b6cf1cba20
--- /dev/null
+++ b/vendor/symfony/http-kernel/Tests/Fixtures/123/Kernel123.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\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/BaseBundle/Resources/foo.txt
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/vendor/symfony/http-kernel/Tests/Fixtures/BaseBundle/Resources/foo.txt
diff --git a/vendor/symfony/http-kernel/Tests/Fixtures/BaseBundle/Resources/hide.txt b/vendor/symfony/http-kernel/Tests/Fixtures/BaseBundle/Resources/hide.txt
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/vendor/symfony/http-kernel/Tests/Fixtures/BaseBundle/Resources/hide.txt
diff --git a/vendor/symfony/http-kernel/Tests/Fixtures/Bundle1Bundle/Resources/foo.txt b/vendor/symfony/http-kernel/Tests/Fixtures/Bundle1Bundle/Resources/foo.txt
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/vendor/symfony/http-kernel/Tests/Fixtures/Bundle1Bundle/Resources/foo.txt
diff --git a/vendor/symfony/http-kernel/Tests/Fixtures/Bundle1Bundle/bar.txt b/vendor/symfony/http-kernel/Tests/Fixtures/Bundle1Bundle/bar.txt
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/vendor/symfony/http-kernel/Tests/Fixtures/Bundle1Bundle/bar.txt
diff --git a/vendor/symfony/http-kernel/Tests/Fixtures/Bundle1Bundle/foo.txt b/vendor/symfony/http-kernel/Tests/Fixtures/Bundle1Bundle/foo.txt
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/vendor/symfony/http-kernel/Tests/Fixtures/Bundle1Bundle/foo.txt
diff --git a/vendor/symfony/http-kernel/Tests/Fixtures/Bundle2Bundle/foo.txt b/vendor/symfony/http-kernel/Tests/Fixtures/Bundle2Bundle/foo.txt
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/vendor/symfony/http-kernel/Tests/Fixtures/Bundle2Bundle/foo.txt
diff --git a/vendor/symfony/http-kernel/Tests/Fixtures/ChildBundle/Resources/foo.txt b/vendor/symfony/http-kernel/Tests/Fixtures/ChildBundle/Resources/foo.txt
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/vendor/symfony/http-kernel/Tests/Fixtures/ChildBundle/Resources/foo.txt
diff --git a/vendor/symfony/http-kernel/Tests/Fixtures/ChildBundle/Resources/hide.txt b/vendor/symfony/http-kernel/Tests/Fixtures/ChildBundle/Resources/hide.txt
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/vendor/symfony/http-kernel/Tests/Fixtures/ChildBundle/Resources/hide.txt
diff --git a/vendor/symfony/http-kernel/Tests/Fixtures/Controller/BasicTypesController.php b/vendor/symfony/http-kernel/Tests/Fixtures/Controller/BasicTypesController.php
new file mode 100644
index 0000000000..e8e0b60346
--- /dev/null
+++ b/vendor/symfony/http-kernel/Tests/Fixtures/Controller/BasicTypesController.php
@@ -0,0 +1,19 @@
+<?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\Controller;
+
+class BasicTypesController
+{
+ public function action(string $foo, int $bar, float $baz)
+ {
+ }
+}
diff --git a/vendor/symfony/http-kernel/Tests/Fixtures/Controller/ExtendingRequest.php b/vendor/symfony/http-kernel/Tests/Fixtures/Controller/ExtendingRequest.php
new file mode 100644
index 0000000000..9b4754b46f
--- /dev/null
+++ b/vendor/symfony/http-kernel/Tests/Fixtures/Controller/ExtendingRequest.php
@@ -0,0 +1,18 @@
+<?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\Controller;
+
+use Symfony\Component\HttpFoundation\Request;
+
+class ExtendingRequest extends Request
+{
+}
diff --git a/vendor/symfony/http-kernel/Tests/Fixtures/Controller/ExtendingSession.php b/vendor/symfony/http-kernel/Tests/Fixtures/Controller/ExtendingSession.php
new file mode 100644
index 0000000000..9fa54ee8bb
--- /dev/null
+++ b/vendor/symfony/http-kernel/Tests/Fixtures/Controller/ExtendingSession.php
@@ -0,0 +1,18 @@
+<?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\Controller;
+
+use Symfony\Component\HttpFoundation\Session\Session;
+
+class ExtendingSession extends Session
+{
+}
diff --git a/vendor/symfony/http-kernel/Tests/Fixtures/Controller/NullableController.php b/vendor/symfony/http-kernel/Tests/Fixtures/Controller/NullableController.php
new file mode 100644
index 0000000000..9db4df7b4c
--- /dev/null
+++ b/vendor/symfony/http-kernel/Tests/Fixtures/Controller/NullableController.php
@@ -0,0 +1,19 @@
+<?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\Controller;
+
+class NullableController
+{
+ public function action(?string $foo, ?\stdClass $bar, ?string $baz = 'value', $mandatory)
+ {
+ }
+}
diff --git a/vendor/symfony/http-kernel/Tests/Fixtures/Controller/VariadicController.php b/vendor/symfony/http-kernel/Tests/Fixtures/Controller/VariadicController.php
new file mode 100644
index 0000000000..c39812453b
--- /dev/null
+++ b/vendor/symfony/http-kernel/Tests/Fixtures/Controller/VariadicController.php
@@ -0,0 +1,19 @@
+<?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\Controller;
+
+class VariadicController
+{
+ public function action($foo, ...$bar)
+ {
+ }
+}
diff --git a/vendor/symfony/http-kernel/Tests/Fixtures/DataCollector/CloneVarDataCollector.php b/vendor/symfony/http-kernel/Tests/Fixtures/DataCollector/CloneVarDataCollector.php
new file mode 100644
index 0000000000..867ccdce57
--- /dev/null
+++ b/vendor/symfony/http-kernel/Tests/Fixtures/DataCollector/CloneVarDataCollector.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\HttpKernel\Tests\Fixtures\DataCollector;
+
+use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\HttpFoundation\Response;
+use Symfony\Component\HttpKernel\DataCollector\DataCollector;
+
+class CloneVarDataCollector extends DataCollector
+{
+ private $varToClone;
+
+ public function __construct($varToClone)
+ {
+ $this->varToClone = $varToClone;
+ }
+
+ public function collect(Request $request, Response $response, \Exception $exception = null)
+ {
+ $this->data = $this->cloneVar($this->varToClone);
+ }
+
+ public function getData()
+ {
+ return $this->data;
+ }
+
+ public function getName()
+ {
+ return 'clone_var';
+ }
+}
diff --git a/vendor/symfony/http-kernel/Tests/Fixtures/ExtensionAbsentBundle/ExtensionAbsentBundle.php b/vendor/symfony/http-kernel/Tests/Fixtures/ExtensionAbsentBundle/ExtensionAbsentBundle.php
new file mode 100644
index 0000000000..c8bfd36e66
--- /dev/null
+++ b/vendor/symfony/http-kernel/Tests/Fixtures/ExtensionAbsentBundle/ExtensionAbsentBundle.php
@@ -0,0 +1,18 @@
+<?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\ExtensionAbsentBundle;
+
+use Symfony\Component\HttpKernel\Bundle\Bundle;
+
+class ExtensionAbsentBundle extends Bundle
+{
+}
diff --git a/vendor/symfony/http-kernel/Tests/Fixtures/ExtensionLoadedBundle/DependencyInjection/ExtensionLoadedExtension.php b/vendor/symfony/http-kernel/Tests/Fixtures/ExtensionLoadedBundle/DependencyInjection/ExtensionLoadedExtension.php
new file mode 100644
index 0000000000..b43bc665a8
--- /dev/null
+++ b/vendor/symfony/http-kernel/Tests/Fixtures/ExtensionLoadedBundle/DependencyInjection/ExtensionLoadedExtension.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\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/ExtensionLoadedBundle/ExtensionLoadedBundle.php b/vendor/symfony/http-kernel/Tests/Fixtures/ExtensionLoadedBundle/ExtensionLoadedBundle.php
new file mode 100644
index 0000000000..3af81cb073
--- /dev/null
+++ b/vendor/symfony/http-kernel/Tests/Fixtures/ExtensionLoadedBundle/ExtensionLoadedBundle.php
@@ -0,0 +1,18 @@
+<?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;
+
+use Symfony\Component\HttpKernel\Bundle\Bundle;
+
+class ExtensionLoadedBundle extends Bundle
+{
+}
diff --git a/vendor/symfony/http-kernel/Tests/Fixtures/ExtensionNotValidBundle/DependencyInjection/ExtensionNotValidExtension.php b/vendor/symfony/http-kernel/Tests/Fixtures/ExtensionNotValidBundle/DependencyInjection/ExtensionNotValidExtension.php
new file mode 100644
index 0000000000..0fd64316fb
--- /dev/null
+++ b/vendor/symfony/http-kernel/Tests/Fixtures/ExtensionNotValidBundle/DependencyInjection/ExtensionNotValidExtension.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\HttpKernel\Tests\Fixtures\ExtensionNotValidBundle\DependencyInjection;
+
+class ExtensionNotValidExtension
+{
+ public function getAlias()
+ {
+ return 'extension_not_valid';
+ }
+}
diff --git a/vendor/symfony/http-kernel/Tests/Fixtures/ExtensionNotValidBundle/ExtensionNotValidBundle.php b/vendor/symfony/http-kernel/Tests/Fixtures/ExtensionNotValidBundle/ExtensionNotValidBundle.php
new file mode 100644
index 0000000000..34e2920392
--- /dev/null
+++ b/vendor/symfony/http-kernel/Tests/Fixtures/ExtensionNotValidBundle/ExtensionNotValidBundle.php
@@ -0,0 +1,18 @@
+<?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\ExtensionNotValidBundle;
+
+use Symfony\Component\HttpKernel\Bundle\Bundle;
+
+class ExtensionNotValidBundle extends Bundle
+{
+}
diff --git a/vendor/symfony/http-kernel/Tests/Fixtures/ExtensionPresentBundle/Command/BarCommand.php b/vendor/symfony/http-kernel/Tests/Fixtures/ExtensionPresentBundle/Command/BarCommand.php
new file mode 100644
index 0000000000..977976b75f
--- /dev/null
+++ b/vendor/symfony/http-kernel/Tests/Fixtures/ExtensionPresentBundle/Command/BarCommand.php
@@ -0,0 +1,17 @@
+<?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
new file mode 100644
index 0000000000..c6570aa046
--- /dev/null
+++ b/vendor/symfony/http-kernel/Tests/Fixtures/ExtensionPresentBundle/Command/FooCommand.php
@@ -0,0 +1,22 @@
+<?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/ExtensionPresentBundle/DependencyInjection/ExtensionPresentExtension.php b/vendor/symfony/http-kernel/Tests/Fixtures/ExtensionPresentBundle/DependencyInjection/ExtensionPresentExtension.php
new file mode 100644
index 0000000000..108571718d
--- /dev/null
+++ b/vendor/symfony/http-kernel/Tests/Fixtures/ExtensionPresentBundle/DependencyInjection/ExtensionPresentExtension.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\HttpKernel\Tests\Fixtures\ExtensionPresentBundle\DependencyInjection;
+
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\DependencyInjection\Extension\Extension;
+
+class ExtensionPresentExtension extends Extension
+{
+ public function load(array $configs, ContainerBuilder $container)
+ {
+ }
+}
diff --git a/vendor/symfony/http-kernel/Tests/Fixtures/ExtensionPresentBundle/ExtensionPresentBundle.php b/vendor/symfony/http-kernel/Tests/Fixtures/ExtensionPresentBundle/ExtensionPresentBundle.php
new file mode 100644
index 0000000000..36a7ad404a
--- /dev/null
+++ b/vendor/symfony/http-kernel/Tests/Fixtures/ExtensionPresentBundle/ExtensionPresentBundle.php
@@ -0,0 +1,18 @@
+<?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\ExtensionPresentBundle;
+
+use Symfony\Component\HttpKernel\Bundle\Bundle;
+
+class ExtensionPresentBundle extends Bundle
+{
+}
diff --git a/vendor/symfony/http-kernel/Tests/Fixtures/KernelForOverrideName.php b/vendor/symfony/http-kernel/Tests/Fixtures/KernelForOverrideName.php
new file mode 100644
index 0000000000..a1102ab784
--- /dev/null
+++ b/vendor/symfony/http-kernel/Tests/Fixtures/KernelForOverrideName.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\Tests\Fixtures;
+
+use Symfony\Component\HttpKernel\Kernel;
+use Symfony\Component\Config\Loader\LoaderInterface;
+
+class KernelForOverrideName extends Kernel
+{
+ protected $name = 'overridden';
+
+ public function registerBundles()
+ {
+ }
+
+ public function registerContainerConfiguration(LoaderInterface $loader)
+ {
+ }
+}
diff --git a/vendor/symfony/http-kernel/Tests/Fixtures/KernelForTest.php b/vendor/symfony/http-kernel/Tests/Fixtures/KernelForTest.php
new file mode 100644
index 0000000000..5fd61bbc7e
--- /dev/null
+++ b/vendor/symfony/http-kernel/Tests/Fixtures/KernelForTest.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\HttpKernel\Tests\Fixtures;
+
+use Symfony\Component\HttpKernel\Kernel;
+use Symfony\Component\Config\Loader\LoaderInterface;
+
+class KernelForTest extends Kernel
+{
+ public function getBundleMap()
+ {
+ return $this->bundleMap;
+ }
+
+ public function registerBundles()
+ {
+ return array();
+ }
+
+ public function registerContainerConfiguration(LoaderInterface $loader)
+ {
+ }
+
+ public function isBooted()
+ {
+ return $this->booted;
+ }
+}
diff --git a/vendor/symfony/http-kernel/Tests/Fixtures/KernelWithoutBundles.php b/vendor/symfony/http-kernel/Tests/Fixtures/KernelWithoutBundles.php
new file mode 100644
index 0000000000..cee1b09fb2
--- /dev/null
+++ b/vendor/symfony/http-kernel/Tests/Fixtures/KernelWithoutBundles.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\HttpKernel\Tests\Fixtures;
+
+use Symfony\Component\Config\Loader\LoaderInterface;
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\HttpKernel\Kernel;
+
+class KernelWithoutBundles extends Kernel
+{
+ public function registerBundles()
+ {
+ return array();
+ }
+
+ public function registerContainerConfiguration(LoaderInterface $loader)
+ {
+ }
+
+ 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
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/vendor/symfony/http-kernel/Tests/Fixtures/Resources/BaseBundle/hide.txt
diff --git a/vendor/symfony/http-kernel/Tests/Fixtures/Resources/Bundle1Bundle/foo.txt b/vendor/symfony/http-kernel/Tests/Fixtures/Resources/Bundle1Bundle/foo.txt
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/vendor/symfony/http-kernel/Tests/Fixtures/Resources/Bundle1Bundle/foo.txt
diff --git a/vendor/symfony/http-kernel/Tests/Fixtures/Resources/ChildBundle/foo.txt b/vendor/symfony/http-kernel/Tests/Fixtures/Resources/ChildBundle/foo.txt
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/vendor/symfony/http-kernel/Tests/Fixtures/Resources/ChildBundle/foo.txt
diff --git a/vendor/symfony/http-kernel/Tests/Fixtures/Resources/FooBundle/foo.txt b/vendor/symfony/http-kernel/Tests/Fixtures/Resources/FooBundle/foo.txt
new file mode 100644
index 0000000000..e69de29bb2
--- /dev/null
+++ b/vendor/symfony/http-kernel/Tests/Fixtures/Resources/FooBundle/foo.txt
diff --git a/vendor/symfony/http-kernel/Tests/Fixtures/TestClient.php b/vendor/symfony/http-kernel/Tests/Fixtures/TestClient.php
new file mode 100644
index 0000000000..e7d60cff3d
--- /dev/null
+++ b/vendor/symfony/http-kernel/Tests/Fixtures/TestClient.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\HttpKernel\Tests\Fixtures;
+
+use Symfony\Component\HttpKernel\Client;
+
+class TestClient extends Client
+{
+ protected function getScript($request)
+ {
+ $script = parent::getScript($request);
+
+ $autoload = file_exists(__DIR__.'/../../vendor/autoload.php')
+ ? __DIR__.'/../../vendor/autoload.php'
+ : __DIR__.'/../../../../../../vendor/autoload.php'
+ ;
+
+ $script = preg_replace('/(\->register\(\);)/', "$0\nrequire_once '$autoload';\n", $script);
+
+ return $script;
+ }
+}
diff --git a/vendor/symfony/http-kernel/Tests/Fixtures/TestEventDispatcher.php b/vendor/symfony/http-kernel/Tests/Fixtures/TestEventDispatcher.php
new file mode 100644
index 0000000000..da7ef5bd60
--- /dev/null
+++ b/vendor/symfony/http-kernel/Tests/Fixtures/TestEventDispatcher.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\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');
+ }
+}
diff --git a/vendor/symfony/http-kernel/Tests/Fragment/EsiFragmentRendererTest.php b/vendor/symfony/http-kernel/Tests/Fragment/EsiFragmentRendererTest.php
new file mode 100644
index 0000000000..bfe922e22c
--- /dev/null
+++ b/vendor/symfony/http-kernel/Tests/Fragment/EsiFragmentRendererTest.php
@@ -0,0 +1,110 @@
+<?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\Fragment;
+
+use PHPUnit\Framework\TestCase;
+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
+{
+ public function testRenderFallbackToInlineStrategyIfEsiNotSupported()
+ {
+ $strategy = new EsiFragmentRenderer(new Esi(), $this->getInlineStrategy(true));
+ $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' => array('a' => array(), 'b' => new \stdClass())), array());
+ $strategy->render($reference, $request);
+ }
+
+ public function testRender()
+ {
+ $strategy = new EsiFragmentRenderer(new Esi(), $this->getInlineStrategy());
+
+ $request = Request::create('/');
+ $request->setLocale('fr');
+ $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());
+ }
+
+ public function testRenderControllerReference()
+ {
+ $signer = new UriSigner('foo');
+ $strategy = new EsiFragmentRenderer(new Esi(), $this->getInlineStrategy(), $signer);
+
+ $request = Request::create('/');
+ $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());
+
+ $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()
+ );
+ }
+
+ /**
+ * @expectedException \LogicException
+ */
+ public function testRenderControllerReferenceWithoutSignerThrowsException()
+ {
+ $strategy = new EsiFragmentRenderer(new Esi(), $this->getInlineStrategy());
+
+ $request = Request::create('/');
+ $request->setLocale('fr');
+ $request->headers->set('Surrogate-Capability', 'ESI/1.0');
+
+ $strategy->render(new ControllerReference('main_controller'), $request);
+ }
+
+ /**
+ * @expectedException \LogicException
+ */
+ public function testRenderAltControllerReferenceWithoutSignerThrowsException()
+ {
+ $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')));
+ }
+
+ private function getInlineStrategy($called = false)
+ {
+ $inline = $this->getMockBuilder('Symfony\Component\HttpKernel\Fragment\InlineFragmentRenderer')->disableOriginalConstructor()->getMock();
+
+ if ($called) {
+ $inline->expects($this->once())->method('render');
+ }
+
+ return $inline;
+ }
+}
diff --git a/vendor/symfony/http-kernel/Tests/Fragment/FragmentHandlerTest.php b/vendor/symfony/http-kernel/Tests/Fragment/FragmentHandlerTest.php
new file mode 100644
index 0000000000..9c906b50a0
--- /dev/null
+++ b/vendor/symfony/http-kernel/Tests/Fragment/FragmentHandlerTest.php
@@ -0,0 +1,99 @@
+<?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\Fragment;
+
+use PHPUnit\Framework\TestCase;
+use Symfony\Component\HttpKernel\Fragment\FragmentHandler;
+use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\HttpFoundation\Response;
+
+/**
+ * @group time-sensitive
+ */
+class FragmentHandlerTest extends TestCase
+{
+ private $requestStack;
+
+ protected function setUp()
+ {
+ $this->requestStack = $this->getMockBuilder('Symfony\\Component\\HttpFoundation\\RequestStack')
+ ->disableOriginalConstructor()
+ ->getMock()
+ ;
+ $this->requestStack
+ ->expects($this->any())
+ ->method('getCurrentRequest')
+ ->will($this->returnValue(Request::create('/')))
+ ;
+ }
+
+ /**
+ * @expectedException \InvalidArgumentException
+ */
+ public function testRenderWhenRendererDoesNotExist()
+ {
+ $handler = new FragmentHandler($this->requestStack);
+ $handler->render('/', 'foo');
+ }
+
+ /**
+ * @expectedException \InvalidArgumentException
+ */
+ public function testRenderWithUnknownRenderer()
+ {
+ $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()
+ {
+ $handler = $this->getHandler($this->returnValue(new Response('foo', 404)));
+
+ $handler->render('/', 'foo');
+ }
+
+ public function testRender()
+ {
+ $handler = $this->getHandler($this->returnValue(new Response('foo')), array('/', Request::create('/'), array('foo' => 'foo', 'ignore_errors' => true)));
+
+ $this->assertEquals('foo', $handler->render('/', 'foo', array('foo' => 'foo')));
+ }
+
+ protected function getHandler($returnValue, $arguments = array())
+ {
+ $renderer = $this->getMockBuilder('Symfony\Component\HttpKernel\Fragment\FragmentRendererInterface')->getMock();
+ $renderer
+ ->expects($this->any())
+ ->method('getName')
+ ->will($this->returnValue('foo'))
+ ;
+ $e = $renderer
+ ->expects($this->any())
+ ->method('render')
+ ->will($returnValue)
+ ;
+
+ if ($arguments) {
+ call_user_func_array(array($e, 'with'), $arguments);
+ }
+
+ $handler = new FragmentHandler($this->requestStack);
+ $handler->addRenderer($renderer);
+
+ return $handler;
+ }
+}
diff --git a/vendor/symfony/http-kernel/Tests/Fragment/HIncludeFragmentRendererTest.php b/vendor/symfony/http-kernel/Tests/Fragment/HIncludeFragmentRendererTest.php
new file mode 100644
index 0000000000..1be052e5e6
--- /dev/null
+++ b/vendor/symfony/http-kernel/Tests/Fragment/HIncludeFragmentRendererTest.php
@@ -0,0 +1,89 @@
+<?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\Fragment;
+
+use PHPUnit\Framework\TestCase;
+use Symfony\Component\HttpKernel\Controller\ControllerReference;
+use Symfony\Component\HttpKernel\Fragment\HIncludeFragmentRenderer;
+use Symfony\Component\HttpKernel\UriSigner;
+use Symfony\Component\HttpFoundation\Request;
+
+class HIncludeFragmentRendererTest extends TestCase
+{
+ /**
+ * @expectedException \LogicException
+ */
+ public function testRenderExceptionWhenControllerAndNoSigner()
+ {
+ $strategy = new HIncludeFragmentRenderer();
+ $strategy->render(new ControllerReference('main_controller', array(), array()), 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&amp;_hash=BP%2BOzCD5MRUI%2BHJpgPDOmoju00FnzLhP3TGcSHbbBLs%3D"></hx:include>', $strategy->render(new ControllerReference('main_controller', array(), array()), Request::create('/'))->getContent());
+ }
+
+ public function testRenderWithUri()
+ {
+ $strategy = new HIncludeFragmentRenderer();
+ $this->assertEquals('<hx:include src="/foo"></hx:include>', $strategy->render('/foo', Request::create('/'))->getContent());
+
+ $strategy = new HIncludeFragmentRenderer(null, new UriSigner('foo'));
+ $this->assertEquals('<hx:include src="/foo"></hx:include>', $strategy->render('/foo', Request::create('/'))->getContent());
+ }
+
+ public function testRenderWithDefault()
+ {
+ // only default
+ $strategy = new HIncludeFragmentRenderer();
+ $this->assertEquals('<hx:include src="/foo">default</hx:include>', $strategy->render('/foo', Request::create('/'), array('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());
+
+ // 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());
+ }
+
+ 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());
+
+ // 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());
+
+ // 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());
+ }
+
+ public function testRenderWithDefaultText()
+ {
+ $engine = $this->getMockBuilder('Symfony\\Component\\Templating\\EngineInterface')->getMock();
+ $engine->expects($this->once())
+ ->method('exists')
+ ->with('default')
+ ->will($this->throwException(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());
+ }
+}
diff --git a/vendor/symfony/http-kernel/Tests/Fragment/InlineFragmentRendererTest.php b/vendor/symfony/http-kernel/Tests/Fragment/InlineFragmentRendererTest.php
new file mode 100644
index 0000000000..18e55a5be0
--- /dev/null
+++ b/vendor/symfony/http-kernel/Tests/Fragment/InlineFragmentRendererTest.php
@@ -0,0 +1,250 @@
+<?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\Fragment;
+
+use PHPUnit\Framework\TestCase;
+use Symfony\Component\HttpFoundation\RequestStack;
+use Symfony\Component\HttpKernel\Controller\ArgumentResolver;
+use Symfony\Component\HttpKernel\Controller\ControllerResolverInterface;
+use Symfony\Component\HttpKernel\Controller\ControllerReference;
+use Symfony\Component\HttpKernel\HttpKernel;
+use Symfony\Component\HttpKernel\Fragment\InlineFragmentRenderer;
+use Symfony\Component\HttpKernel\KernelEvents;
+use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\HttpFoundation\Response;
+use Symfony\Component\EventDispatcher\EventDispatcher;
+
+class InlineFragmentRendererTest extends TestCase
+{
+ public function testRender()
+ {
+ $strategy = new InlineFragmentRenderer($this->getKernel($this->returnValue(new Response('foo'))));
+
+ $this->assertEquals('foo', $strategy->render('/', Request::create('/'))->getContent());
+ }
+
+ public function testRenderWithControllerReference()
+ {
+ $strategy = new InlineFragmentRenderer($this->getKernel($this->returnValue(new Response('foo'))));
+
+ $this->assertEquals('foo', $strategy->render(new ControllerReference('main_controller', array(), array()), Request::create('/'))->getContent());
+ }
+
+ public function testRenderWithObjectsAsAttributes()
+ {
+ $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->server->set('HTTP_X_FORWARDED_FOR', '127.0.0.1');
+
+ $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());
+ }
+
+ public function testRenderWithTrustedHeaderDisabled()
+ {
+ Request::setTrustedProxies(array(), 0);
+
+ $strategy = new InlineFragmentRenderer($this->getKernelExpectingRequest(Request::create('/')));
+ $this->assertSame('foo', $strategy->render('/', Request::create('/'))->getContent());
+
+ Request::setTrustedProxies(array(), -1);
+ }
+
+ /**
+ * @expectedException \RuntimeException
+ */
+ public function testRenderExceptionNoIgnoreErrors()
+ {
+ $dispatcher = $this->getMockBuilder('Symfony\Component\EventDispatcher\EventDispatcherInterface')->getMock();
+ $dispatcher->expects($this->never())->method('dispatch');
+
+ $strategy = new InlineFragmentRenderer($this->getKernel($this->throwException(new \RuntimeException('foo'))), $dispatcher);
+
+ $this->assertEquals('foo', $strategy->render('/', Request::create('/'))->getContent());
+ }
+
+ public function testRenderExceptionIgnoreErrors()
+ {
+ $dispatcher = $this->getMockBuilder('Symfony\Component\EventDispatcher\EventDispatcherInterface')->getMock();
+ $dispatcher->expects($this->once())->method('dispatch')->with(KernelEvents::EXCEPTION);
+
+ $strategy = new InlineFragmentRenderer($this->getKernel($this->throwException(new \RuntimeException('foo'))), $dispatcher);
+
+ $this->assertEmpty($strategy->render('/', Request::create('/'), array('ignore_errors' => true))->getContent());
+ }
+
+ public function testRenderExceptionIgnoreErrorsWithAlt()
+ {
+ $strategy = new InlineFragmentRenderer($this->getKernel($this->onConsecutiveCalls(
+ $this->throwException(new \RuntimeException('foo')),
+ $this->returnValue(new Response('bar'))
+ )));
+
+ $this->assertEquals('bar', $strategy->render('/', Request::create('/'), array('ignore_errors' => true, 'alt' => '/foo'))->getContent());
+ }
+
+ private function getKernel($returnValue)
+ {
+ $kernel = $this->getMockBuilder('Symfony\Component\HttpKernel\HttpKernelInterface')->getMock();
+ $kernel
+ ->expects($this->any())
+ ->method('handle')
+ ->will($returnValue)
+ ;
+
+ return $kernel;
+ }
+
+ public function testExceptionInSubRequestsDoesNotMangleOutputBuffers()
+ {
+ $controllerResolver = $this->getMockBuilder('Symfony\\Component\\HttpKernel\\Controller\\ControllerResolverInterface')->getMock();
+ $controllerResolver
+ ->expects($this->once())
+ ->method('getController')
+ ->will($this->returnValue(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()))
+ ;
+
+ $kernel = new HttpKernel(new EventDispatcher(), $controllerResolver, new RequestStack(), $argumentResolver);
+ $renderer = new InlineFragmentRenderer($kernel);
+
+ // simulate a main request with output buffering
+ ob_start();
+ echo 'Foo';
+
+ // simulate a sub-request with output buffering and an exception
+ $renderer->render('/', Request::create('/'), array('ignore_errors' => true));
+
+ $this->assertEquals('Foo', ob_get_clean());
+ }
+
+ 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->server->set('HTTP_X_FORWARDED_FOR', '127.0.0.1');
+ }
+
+ $strategy = new InlineFragmentRenderer($this->getKernelExpectingRequest($expectedSubRequest));
+
+ $request = Request::create('/');
+ $request->headers->set('Surrogate-Capability', 'abc="ESI/1.0"');
+ $strategy->render('/', $request);
+ }
+
+ public function testESIHeaderIsKeptInSubrequestWithTrustedHeaderDisabled()
+ {
+ Request::setTrustedProxies(array(), 0);
+
+ $this->testESIHeaderIsKeptInSubrequest();
+
+ Request::setTrustedProxies(array(), -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');
+ }
+
+ $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' => '*'));
+ $strategy->render('/', $request);
+ }
+
+ /**
+ * Creates a Kernel expecting a request equals to $request
+ * Allows delta in comparison in case REQUEST_TIME changed by 1 second.
+ */
+ private function getKernelExpectingRequest(Request $request, $strict = false)
+ {
+ $kernel = $this->getMockBuilder('Symfony\Component\HttpKernel\HttpKernelInterface')->getMock();
+ $kernel
+ ->expects($this->once())
+ ->method('handle')
+ ->with($this->equalTo($request, 1))
+ ->willReturn(new Response('foo'));
+
+ return $kernel;
+ }
+}
+
+class Bar
+{
+ public $bar = 'bar';
+
+ public function getBar()
+ {
+ return $this->bar;
+ }
+}
diff --git a/vendor/symfony/http-kernel/Tests/Fragment/RoutableFragmentRendererTest.php b/vendor/symfony/http-kernel/Tests/Fragment/RoutableFragmentRendererTest.php
new file mode 100644
index 0000000000..3a040dedd6
--- /dev/null
+++ b/vendor/symfony/http-kernel/Tests/Fragment/RoutableFragmentRendererTest.php
@@ -0,0 +1,94 @@
+<?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\Fragment;
+
+use PHPUnit\Framework\TestCase;
+use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\HttpKernel\Controller\ControllerReference;
+
+class RoutableFragmentRendererTest extends TestCase
+{
+ /**
+ * @dataProvider getGenerateFragmentUriData
+ */
+ public function testGenerateFragmentUri($uri, $controller)
+ {
+ $this->assertEquals($uri, $this->callGenerateFragmentUriMethod($controller, Request::create('/')));
+ }
+
+ /**
+ * @dataProvider getGenerateFragmentUriData
+ */
+ public function testGenerateAbsoluteFragmentUri($uri, $controller)
+ {
+ $this->assertEquals('http://localhost'.$uri, $this->callGenerateFragmentUriMethod($controller, Request::create('/'), true));
+ }
+
+ 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())),
+ );
+ }
+
+ public function testGenerateFragmentUriWithARequest()
+ {
+ $request = Request::create('/');
+ $request->attributes->set('_format', 'json');
+ $request->setLocale('fr');
+ $controller = new ControllerReference('controller', array(), array());
+
+ $this->assertEquals('/_fragment?_path=_format%3Djson%26_locale%3Dfr%26_controller%3Dcontroller', $this->callGenerateFragmentUriMethod($controller, $request));
+ }
+
+ /**
+ * @expectedException \LogicException
+ * @dataProvider getGenerateFragmentUriDataWithNonScalar
+ */
+ public function testGenerateFragmentUriWithNonScalar($controller)
+ {
+ $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())),
+ );
+ }
+
+ private function callGenerateFragmentUriMethod(ControllerReference $reference, Request $request, $absolute = false)
+ {
+ $renderer = $this->getMockForAbstractClass('Symfony\Component\HttpKernel\Fragment\RoutableFragmentRenderer');
+ $r = new \ReflectionObject($renderer);
+ $m = $r->getMethod('generateFragmentUri');
+ $m->setAccessible(true);
+
+ return $m->invoke($renderer, $reference, $request, $absolute);
+ }
+}
+
+class Foo
+{
+ public $foo;
+
+ public function getFoo()
+ {
+ return $this->foo;
+ }
+}
diff --git a/vendor/symfony/http-kernel/Tests/Fragment/SsiFragmentRendererTest.php b/vendor/symfony/http-kernel/Tests/Fragment/SsiFragmentRendererTest.php
new file mode 100644
index 0000000000..b537625f24
--- /dev/null
+++ b/vendor/symfony/http-kernel/Tests/Fragment/SsiFragmentRendererTest.php
@@ -0,0 +1,97 @@
+<?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\Fragment;
+
+use PHPUnit\Framework\TestCase;
+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
+{
+ public function testRenderFallbackToInlineStrategyIfSsiNotSupported()
+ {
+ $strategy = new SsiFragmentRenderer(new Ssi(), $this->getInlineStrategy(true));
+ $strategy->render('/', Request::create('/'));
+ }
+
+ public function testRender()
+ {
+ $strategy = new SsiFragmentRenderer(new Ssi(), $this->getInlineStrategy());
+
+ $request = Request::create('/');
+ $request->setLocale('fr');
+ $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');
+ }
+
+ public function testRenderControllerReference()
+ {
+ $signer = new UriSigner('foo');
+ $strategy = new SsiFragmentRenderer(new Ssi(), $this->getInlineStrategy(), $signer);
+
+ $request = Request::create('/');
+ $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());
+
+ $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()
+ );
+ }
+
+ /**
+ * @expectedException \LogicException
+ */
+ public function testRenderControllerReferenceWithoutSignerThrowsException()
+ {
+ $strategy = new SsiFragmentRenderer(new Ssi(), $this->getInlineStrategy());
+
+ $request = Request::create('/');
+ $request->setLocale('fr');
+ $request->headers->set('Surrogate-Capability', 'SSI/1.0');
+
+ $strategy->render(new ControllerReference('main_controller'), $request);
+ }
+
+ /**
+ * @expectedException \LogicException
+ */
+ public function testRenderAltControllerReferenceWithoutSignerThrowsException()
+ {
+ $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')));
+ }
+
+ private function getInlineStrategy($called = false)
+ {
+ $inline = $this->getMockBuilder('Symfony\Component\HttpKernel\Fragment\InlineFragmentRenderer')->disableOriginalConstructor()->getMock();
+
+ if ($called) {
+ $inline->expects($this->once())->method('render');
+ }
+
+ return $inline;
+ }
+}
diff --git a/vendor/symfony/http-kernel/Tests/HttpCache/EsiTest.php b/vendor/symfony/http-kernel/Tests/HttpCache/EsiTest.php
new file mode 100644
index 0000000000..a8662b2a2b
--- /dev/null
+++ b/vendor/symfony/http-kernel/Tests/HttpCache/EsiTest.php
@@ -0,0 +1,248 @@
+<?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\HttpKernel\HttpCache\Esi;
+use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\HttpFoundation\Response;
+
+class EsiTest extends TestCase
+{
+ public function testHasSurrogateEsiCapability()
+ {
+ $esi = new Esi();
+
+ $request = Request::create('/');
+ $request->headers->set('Surrogate-Capability', 'abc="ESI/1.0"');
+ $this->assertTrue($esi->hasSurrogateCapability($request));
+
+ $request = Request::create('/');
+ $request->headers->set('Surrogate-Capability', 'foobar');
+ $this->assertFalse($esi->hasSurrogateCapability($request));
+
+ $request = Request::create('/');
+ $this->assertFalse($esi->hasSurrogateCapability($request));
+ }
+
+ public function testAddSurrogateEsiCapability()
+ {
+ $esi = new Esi();
+
+ $request = Request::create('/');
+ $esi->addSurrogateCapability($request);
+ $this->assertEquals('symfony="ESI/1.0"', $request->headers->get('Surrogate-Capability'));
+
+ $esi->addSurrogateCapability($request);
+ $this->assertEquals('symfony="ESI/1.0", symfony="ESI/1.0"', $request->headers->get('Surrogate-Capability'));
+ }
+
+ public function testAddSurrogateControl()
+ {
+ $esi = new Esi();
+
+ $response = new Response('foo <esi:include src="" />');
+ $esi->addSurrogateControl($response);
+ $this->assertEquals('content="ESI/1.0"', $response->headers->get('Surrogate-Control'));
+
+ $response = new Response('foo');
+ $esi->addSurrogateControl($response);
+ $this->assertEquals('', $response->headers->get('Surrogate-Control'));
+ }
+
+ public function testNeedsEsiParsing()
+ {
+ $esi = new Esi();
+
+ $response = new Response();
+ $response->headers->set('Surrogate-Control', 'content="ESI/1.0"');
+ $this->assertTrue($esi->needsParsing($response));
+
+ $response = new Response();
+ $this->assertFalse($esi->needsParsing($response));
+ }
+
+ public function testRenderIncludeTag()
+ {
+ $esi = new Esi();
+
+ $this->assertEquals('<esi:include src="/" onerror="continue" alt="/alt" />', $esi->renderIncludeTag('/', '/alt', true));
+ $this->assertEquals('<esi:include src="/" alt="/alt" />', $esi->renderIncludeTag('/', '/alt', false));
+ $this->assertEquals('<esi:include src="/" onerror="continue" />', $esi->renderIncludeTag('/'));
+ $this->assertEquals('<esi:comment text="some comment" />'."\n".'<esi:include src="/" onerror="continue" alt="/alt" />', $esi->renderIncludeTag('/', '/alt', true, 'some comment'));
+ }
+
+ public function testProcessDoesNothingIfContentTypeIsNotHtml()
+ {
+ $esi = new Esi();
+
+ $request = Request::create('/');
+ $response = new Response();
+ $response->headers->set('Content-Type', 'text/plain');
+ $esi->process($request, $response);
+
+ $this->assertFalse($response->headers->has('x-body-eval'));
+ }
+
+ public function testMultilineEsiRemoveTagsAreRemoved()
+ {
+ $esi = new Esi();
+
+ $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->assertEquals(' Keep this And this', $response->getContent());
+ }
+
+ public function testCommentTagsAreRemoved()
+ {
+ $esi = new Esi();
+
+ $request = Request::create('/');
+ $response = new Response('<esi:comment text="some comment &gt;" /> Keep this');
+ $esi->process($request, $response);
+
+ $this->assertEquals(' Keep this', $response->getContent());
+ }
+
+ public function testProcess()
+ {
+ $esi = new Esi();
+
+ $request = Request::create('/');
+ $response = new Response('foo <esi:comment text="some comment" /><esi:include src="..." alt="alt" onerror="continue" />');
+ $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->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->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->assertEquals('foo <?php echo $this->surrogate->handle($this, \'...\', \'\', false) ?>'."\n", $response->getContent());
+ }
+
+ public function testProcessEscapesPhpTags()
+ {
+ $esi = new Esi();
+
+ $request = Request::create('/');
+ $response = new Response('<?php <? <% <script language=php>');
+ $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()
+ {
+ $esi = new Esi();
+
+ $request = Request::create('/');
+ $response = new Response('foo <esi:include />');
+ $esi->process($request, $response);
+ }
+
+ public function testProcessRemoveSurrogateControlHeader()
+ {
+ $esi = new Esi();
+
+ $request = Request::create('/');
+ $response = new Response('foo <esi:include src="..." />');
+ $response->headers->set('Surrogate-Control', 'content="ESI/1.0"');
+ $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->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->assertEquals('ESI', $response->headers->get('x-body-eval'));
+ $this->assertEquals('no-store', $response->headers->get('surrogate-control'));
+ }
+
+ public function testHandle()
+ {
+ $esi = new Esi();
+ $cache = $this->getCache(Request::create('/'), new Response('foo'));
+ $this->assertEquals('foo', $esi->handle($cache, '/', '/alt', true));
+ }
+
+ /**
+ * @expectedException \RuntimeException
+ */
+ public function testHandleWhenResponseIsNot200()
+ {
+ $esi = new Esi();
+ $response = new Response('foo');
+ $response->setStatusCode(404);
+ $cache = $this->getCache(Request::create('/'), $response);
+ $esi->handle($cache, '/', '/alt', false);
+ }
+
+ public function testHandleWhenResponseIsNot200AndErrorsAreIgnored()
+ {
+ $esi = new Esi();
+ $response = new Response('foo');
+ $response->setStatusCode(404);
+ $cache = $this->getCache(Request::create('/'), $response);
+ $this->assertEquals('', $esi->handle($cache, '/', '/alt', true));
+ }
+
+ public function testHandleWhenResponseIsNot200AndAltIsPresent()
+ {
+ $esi = new Esi();
+ $response1 = new Response('foo');
+ $response1->setStatusCode(404);
+ $response2 = new Response('bar');
+ $cache = $this->getCache(Request::create('/'), array($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->expects($this->any())
+ ->method('getRequest')
+ ->will($this->returnValue($request))
+ ;
+ if (is_array($response)) {
+ $cache->expects($this->any())
+ ->method('handle')
+ ->will(call_user_func_array(array($this, 'onConsecutiveCalls'), $response))
+ ;
+ } else {
+ $cache->expects($this->any())
+ ->method('handle')
+ ->will($this->returnValue($response))
+ ;
+ }
+
+ return $cache;
+ }
+}
diff --git a/vendor/symfony/http-kernel/Tests/HttpCache/HttpCacheTest.php b/vendor/symfony/http-kernel/Tests/HttpCache/HttpCacheTest.php
new file mode 100644
index 0000000000..a24380c406
--- /dev/null
+++ b/vendor/symfony/http-kernel/Tests/HttpCache/HttpCacheTest.php
@@ -0,0 +1,1367 @@
+<?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 Symfony\Component\HttpKernel\HttpCache\HttpCache;
+use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\HttpFoundation\Response;
+use Symfony\Component\HttpKernel\HttpKernelInterface;
+
+/**
+ * @group time-sensitive
+ */
+class HttpCacheTest extends HttpCacheTestCase
+{
+ public function testTerminateDelegatesTerminationOnlyForTerminableInterface()
+ {
+ $storeMock = $this->getMockBuilder('Symfony\\Component\\HttpKernel\\HttpCache\\StoreInterface')
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ // does not implement TerminableInterface
+ $kernel = new TestKernel();
+ $httpCache = new HttpCache($kernel, $storeMock);
+ $httpCache->terminate(Request::create('/'), new Response());
+
+ $this->assertFalse($kernel->terminateCalled, 'terminate() is never called if the kernel class does not implement TerminableInterface');
+
+ // implements TerminableInterface
+ $kernelMock = $this->getMockBuilder('Symfony\\Component\\HttpKernel\\Kernel')
+ ->disableOriginalConstructor()
+ ->setMethods(array('terminate', 'registerBundles', 'registerContainerConfiguration'))
+ ->getMock();
+
+ $kernelMock->expects($this->once())
+ ->method('terminate');
+
+ $kernel = new HttpCache($kernelMock, $storeMock);
+ $kernel->terminate(Request::create('/'), new Response());
+ }
+
+ public function testPassesOnNonGetHeadRequests()
+ {
+ $this->setNextResponse(200);
+ $this->request('POST', '/');
+ $this->assertHttpKernelIsCalled();
+ $this->assertResponseOk();
+ $this->assertTraceContains('pass');
+ $this->assertFalse($this->response->headers->has('Age'));
+ }
+
+ public function testInvalidatesOnPostPutDeleteRequests()
+ {
+ foreach (array('post', 'put', 'delete') as $method) {
+ $this->setNextResponse(200);
+ $this->request($method, '/');
+
+ $this->assertHttpKernelIsCalled();
+ $this->assertResponseOk();
+ $this->assertTraceContains('invalidate');
+ $this->assertTraceContains('pass');
+ }
+ }
+
+ public function testDoesNotCacheWithAuthorizationRequestHeaderAndNonPublicResponse()
+ {
+ $this->setNextResponse(200, array('ETag' => '"Foo"'));
+ $this->request('GET', '/', array('HTTP_AUTHORIZATION' => 'basic foobarbaz'));
+
+ $this->assertHttpKernelIsCalled();
+ $this->assertResponseOk();
+ $this->assertEquals('private', $this->response->headers->get('Cache-Control'));
+
+ $this->assertTraceContains('miss');
+ $this->assertTraceNotContains('store');
+ $this->assertFalse($this->response->headers->has('Age'));
+ }
+
+ public function testDoesCacheWithAuthorizationRequestHeaderAndPublicResponse()
+ {
+ $this->setNextResponse(200, array('Cache-Control' => 'public', 'ETag' => '"Foo"'));
+ $this->request('GET', '/', array('HTTP_AUTHORIZATION' => 'basic foobarbaz'));
+
+ $this->assertHttpKernelIsCalled();
+ $this->assertResponseOk();
+ $this->assertTraceContains('miss');
+ $this->assertTraceContains('store');
+ $this->assertTrue($this->response->headers->has('Age'));
+ $this->assertEquals('public', $this->response->headers->get('Cache-Control'));
+ }
+
+ public function testDoesNotCacheWithCookieHeaderAndNonPublicResponse()
+ {
+ $this->setNextResponse(200, array('ETag' => '"Foo"'));
+ $this->request('GET', '/', array(), array('foo' => 'bar'));
+
+ $this->assertHttpKernelIsCalled();
+ $this->assertResponseOk();
+ $this->assertEquals('private', $this->response->headers->get('Cache-Control'));
+ $this->assertTraceContains('miss');
+ $this->assertTraceNotContains('store');
+ $this->assertFalse($this->response->headers->has('Age'));
+ }
+
+ public function testDoesNotCacheRequestsWithACookieHeader()
+ {
+ $this->setNextResponse(200);
+ $this->request('GET', '/', array(), array('foo' => 'bar'));
+
+ $this->assertHttpKernelIsCalled();
+ $this->assertResponseOk();
+ $this->assertEquals('private', $this->response->headers->get('Cache-Control'));
+ $this->assertTraceContains('miss');
+ $this->assertTraceNotContains('store');
+ $this->assertFalse($this->response->headers->has('Age'));
+ }
+
+ public function testRespondsWith304WhenIfModifiedSinceMatchesLastModified()
+ {
+ $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->assertHttpKernelIsCalled();
+ $this->assertEquals(304, $this->response->getStatusCode());
+ $this->assertEquals('', $this->response->headers->get('Content-Type'));
+ $this->assertEmpty($this->response->getContent());
+ $this->assertTraceContains('miss');
+ $this->assertTraceContains('store');
+ }
+
+ 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->assertHttpKernelIsCalled();
+ $this->assertEquals(304, $this->response->getStatusCode());
+ $this->assertEquals('', $this->response->headers->get('Content-Type'));
+ $this->assertTrue($this->response->headers->has('ETag'));
+ $this->assertEmpty($this->response->getContent());
+ $this->assertTraceContains('miss');
+ $this->assertTraceContains('store');
+ }
+
+ public function testRespondsWith304OnlyIfIfNoneMatchAndIfModifiedSinceBothMatch()
+ {
+ $time = \DateTime::createFromFormat('U', time());
+
+ $this->setNextResponse(200, array(), '', function ($request, $response) use ($time) {
+ $response->setStatusCode(200);
+ $response->headers->set('ETag', '12345');
+ $response->headers->set('Last-Modified', $time->format(DATE_RFC2822));
+ $response->headers->set('Content-Type', 'text/plain');
+ $response->setContent('Hello World');
+ });
+
+ // 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->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->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->assertHttpKernelIsCalled();
+ $this->assertEquals(304, $this->response->getStatusCode());
+ }
+
+ public function testIncrementsMaxAgeWhenNoDateIsSpecifiedEventWhenUsingETag()
+ {
+ $this->setNextResponse(
+ 200,
+ array(
+ 'ETag' => '1234',
+ 'Cache-Control' => 'public, s-maxage=60',
+ )
+ );
+
+ $this->request('GET', '/');
+ $this->assertHttpKernelIsCalled();
+ $this->assertEquals(200, $this->response->getStatusCode());
+ $this->assertTraceContains('miss');
+ $this->assertTraceContains('store');
+
+ sleep(2);
+
+ $this->request('GET', '/');
+ $this->assertHttpKernelIsNotCalled();
+ $this->assertEquals(200, $this->response->getStatusCode());
+ $this->assertTraceContains('fresh');
+ $this->assertEquals(2, $this->response->headers->get('Age'));
+ }
+
+ public function testValidatesPrivateResponsesCachedOnTheClient()
+ {
+ $this->setNextResponse(200, array(), '', 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)) {
+ $response->setStatusCode(304);
+ } else {
+ $response->setStatusCode(200);
+ $response->headers->set('Content-Type', 'text/plain');
+ $response->setContent('private data');
+ }
+ } else {
+ $response->headers->set('Cache-Control', 'public');
+ $response->setETag('"public tag"');
+ if (in_array('"public tag"', $etags)) {
+ $response->setStatusCode(304);
+ } else {
+ $response->setStatusCode(200);
+ $response->headers->set('Content-Type', 'text/plain');
+ $response->setContent('public data');
+ }
+ }
+ });
+
+ $this->request('GET', '/');
+ $this->assertHttpKernelIsCalled();
+ $this->assertEquals(200, $this->response->getStatusCode());
+ $this->assertEquals('"public tag"', $this->response->headers->get('ETag'));
+ $this->assertEquals('public data', $this->response->getContent());
+ $this->assertTraceContains('miss');
+ $this->assertTraceContains('store');
+
+ $this->request('GET', '/', array(), array('authenticated' => ''));
+ $this->assertHttpKernelIsCalled();
+ $this->assertEquals(200, $this->response->getStatusCode());
+ $this->assertEquals('"private tag"', $this->response->headers->get('ETag'));
+ $this->assertEquals('private data', $this->response->getContent());
+ $this->assertTraceContains('stale');
+ $this->assertTraceContains('invalid');
+ $this->assertTraceNotContains('store');
+ }
+
+ public function testStoresResponsesWhenNoCacheRequestDirectivePresent()
+ {
+ $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->assertHttpKernelIsCalled();
+ $this->assertTraceContains('store');
+ $this->assertTrue($this->response->headers->has('Age'));
+ }
+
+ public function testReloadsResponsesWhenCacheHitsButNoCacheRequestDirectivePresentWhenAllowReloadIsSetTrue()
+ {
+ $count = 0;
+
+ $this->setNextResponse(200, array('Cache-Control' => 'public, max-age=10000'), '', function ($request, $response) use (&$count) {
+ ++$count;
+ $response->setContent(1 == $count ? 'Hello World' : 'Goodbye World');
+ });
+
+ $this->request('GET', '/');
+ $this->assertEquals(200, $this->response->getStatusCode());
+ $this->assertEquals('Hello World', $this->response->getContent());
+ $this->assertTraceContains('store');
+
+ $this->request('GET', '/');
+ $this->assertEquals(200, $this->response->getStatusCode());
+ $this->assertEquals('Hello World', $this->response->getContent());
+ $this->assertTraceContains('fresh');
+
+ $this->cacheConfig['allow_reload'] = true;
+ $this->request('GET', '/', array('HTTP_CACHE_CONTROL' => 'no-cache'));
+ $this->assertEquals(200, $this->response->getStatusCode());
+ $this->assertEquals('Goodbye World', $this->response->getContent());
+ $this->assertTraceContains('reload');
+ $this->assertTraceContains('store');
+ }
+
+ public function testDoesNotReloadResponsesWhenAllowReloadIsSetFalseDefault()
+ {
+ $count = 0;
+
+ $this->setNextResponse(200, array('Cache-Control' => 'public, max-age=10000'), '', function ($request, $response) use (&$count) {
+ ++$count;
+ $response->setContent(1 == $count ? 'Hello World' : 'Goodbye World');
+ });
+
+ $this->request('GET', '/');
+ $this->assertEquals(200, $this->response->getStatusCode());
+ $this->assertEquals('Hello World', $this->response->getContent());
+ $this->assertTraceContains('store');
+
+ $this->request('GET', '/');
+ $this->assertEquals(200, $this->response->getStatusCode());
+ $this->assertEquals('Hello World', $this->response->getContent());
+ $this->assertTraceContains('fresh');
+
+ $this->cacheConfig['allow_reload'] = false;
+ $this->request('GET', '/', array('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->assertEquals(200, $this->response->getStatusCode());
+ $this->assertEquals('Hello World', $this->response->getContent());
+ $this->assertTraceNotContains('reload');
+ }
+
+ public function testRevalidatesFreshCacheEntryWhenMaxAgeRequestDirectiveIsExceededWhenAllowRevalidateOptionIsSetTrue()
+ {
+ $count = 0;
+
+ $this->setNextResponse(200, array(), '', function ($request, $response) use (&$count) {
+ ++$count;
+ $response->headers->set('Cache-Control', 'public, max-age=10000');
+ $response->setETag($count);
+ $response->setContent(1 == $count ? 'Hello World' : 'Goodbye World');
+ });
+
+ $this->request('GET', '/');
+ $this->assertEquals(200, $this->response->getStatusCode());
+ $this->assertEquals('Hello World', $this->response->getContent());
+ $this->assertTraceContains('store');
+
+ $this->request('GET', '/');
+ $this->assertEquals(200, $this->response->getStatusCode());
+ $this->assertEquals('Hello World', $this->response->getContent());
+ $this->assertTraceContains('fresh');
+
+ $this->cacheConfig['allow_revalidate'] = true;
+ $this->request('GET', '/', array('HTTP_CACHE_CONTROL' => 'max-age=0'));
+ $this->assertEquals(200, $this->response->getStatusCode());
+ $this->assertEquals('Goodbye World', $this->response->getContent());
+ $this->assertTraceContains('stale');
+ $this->assertTraceContains('invalid');
+ $this->assertTraceContains('store');
+ }
+
+ public function testDoesNotRevalidateFreshCacheEntryWhenEnableRevalidateOptionIsSetFalseDefault()
+ {
+ $count = 0;
+
+ $this->setNextResponse(200, array(), '', function ($request, $response) use (&$count) {
+ ++$count;
+ $response->headers->set('Cache-Control', 'public, max-age=10000');
+ $response->setETag($count);
+ $response->setContent(1 == $count ? 'Hello World' : 'Goodbye World');
+ });
+
+ $this->request('GET', '/');
+ $this->assertEquals(200, $this->response->getStatusCode());
+ $this->assertEquals('Hello World', $this->response->getContent());
+ $this->assertTraceContains('store');
+
+ $this->request('GET', '/');
+ $this->assertEquals(200, $this->response->getStatusCode());
+ $this->assertEquals('Hello World', $this->response->getContent());
+ $this->assertTraceContains('fresh');
+
+ $this->cacheConfig['allow_revalidate'] = false;
+ $this->request('GET', '/', array('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->assertEquals(200, $this->response->getStatusCode());
+ $this->assertEquals('Hello World', $this->response->getContent());
+ $this->assertTraceNotContains('stale');
+ $this->assertTraceNotContains('invalid');
+ $this->assertTraceContains('fresh');
+ }
+
+ public function testFetchesResponseFromBackendWhenCacheMisses()
+ {
+ $time = \DateTime::createFromFormat('U', time() + 5);
+ $this->setNextResponse(200, array('Cache-Control' => 'public', 'Expires' => $time->format(DATE_RFC2822)));
+
+ $this->request('GET', '/');
+ $this->assertEquals(200, $this->response->getStatusCode());
+ $this->assertTraceContains('miss');
+ $this->assertTrue($this->response->headers->has('Age'));
+ }
+
+ public function testDoesNotCacheSomeStatusCodeResponses()
+ {
+ 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->request('GET', '/');
+ $this->assertEquals($code, $this->response->getStatusCode());
+ $this->assertTraceNotContains('store');
+ $this->assertFalse($this->response->headers->has('Age'));
+ }
+ }
+
+ public function testDoesNotCacheResponsesWithExplicitNoStoreDirective()
+ {
+ $time = \DateTime::createFromFormat('U', time() + 5);
+ $this->setNextResponse(200, array('Expires' => $time->format(DATE_RFC2822), 'Cache-Control' => 'no-store'));
+
+ $this->request('GET', '/');
+ $this->assertTraceNotContains('store');
+ $this->assertFalse($this->response->headers->has('Age'));
+ }
+
+ public function testDoesNotCacheResponsesWithoutFreshnessInformationOrAValidator()
+ {
+ $this->setNextResponse();
+
+ $this->request('GET', '/');
+ $this->assertEquals(200, $this->response->getStatusCode());
+ $this->assertTraceNotContains('store');
+ }
+
+ public function testCachesResponsesWithExplicitNoCacheDirective()
+ {
+ $time = \DateTime::createFromFormat('U', time() + 5);
+ $this->setNextResponse(200, array('Expires' => $time->format(DATE_RFC2822), 'Cache-Control' => 'public, no-cache'));
+
+ $this->request('GET', '/');
+ $this->assertTraceContains('store');
+ $this->assertTrue($this->response->headers->has('Age'));
+ }
+
+ public function testCachesResponsesWithAnExpirationHeader()
+ {
+ $time = \DateTime::createFromFormat('U', time() + 5);
+ $this->setNextResponse(200, array('Cache-Control' => 'public', 'Expires' => $time->format(DATE_RFC2822)));
+
+ $this->request('GET', '/');
+ $this->assertEquals(200, $this->response->getStatusCode());
+ $this->assertEquals('Hello World', $this->response->getContent());
+ $this->assertNotNull($this->response->headers->get('Date'));
+ $this->assertNotNull($this->response->headers->get('X-Content-Digest'));
+ $this->assertTraceContains('miss');
+ $this->assertTraceContains('store');
+
+ $values = $this->getMetaStorageValues();
+ $this->assertCount(1, $values);
+ }
+
+ public function testCachesResponsesWithAMaxAgeDirective()
+ {
+ $this->setNextResponse(200, array('Cache-Control' => 'public, max-age=5'));
+
+ $this->request('GET', '/');
+ $this->assertEquals(200, $this->response->getStatusCode());
+ $this->assertEquals('Hello World', $this->response->getContent());
+ $this->assertNotNull($this->response->headers->get('Date'));
+ $this->assertNotNull($this->response->headers->get('X-Content-Digest'));
+ $this->assertTraceContains('miss');
+ $this->assertTraceContains('store');
+
+ $values = $this->getMetaStorageValues();
+ $this->assertCount(1, $values);
+ }
+
+ public function testCachesResponsesWithASMaxAgeDirective()
+ {
+ $this->setNextResponse(200, array('Cache-Control' => 's-maxage=5'));
+
+ $this->request('GET', '/');
+ $this->assertEquals(200, $this->response->getStatusCode());
+ $this->assertEquals('Hello World', $this->response->getContent());
+ $this->assertNotNull($this->response->headers->get('Date'));
+ $this->assertNotNull($this->response->headers->get('X-Content-Digest'));
+ $this->assertTraceContains('miss');
+ $this->assertTraceContains('store');
+
+ $values = $this->getMetaStorageValues();
+ $this->assertCount(1, $values);
+ }
+
+ public function testCachesResponsesWithALastModifiedValidatorButNoFreshnessInformation()
+ {
+ $time = \DateTime::createFromFormat('U', time());
+ $this->setNextResponse(200, array('Cache-Control' => 'public', 'Last-Modified' => $time->format(DATE_RFC2822)));
+
+ $this->request('GET', '/');
+ $this->assertEquals(200, $this->response->getStatusCode());
+ $this->assertEquals('Hello World', $this->response->getContent());
+ $this->assertTraceContains('miss');
+ $this->assertTraceContains('store');
+ }
+
+ public function testCachesResponsesWithAnETagValidatorButNoFreshnessInformation()
+ {
+ $this->setNextResponse(200, array('Cache-Control' => 'public', 'ETag' => '"123456"'));
+
+ $this->request('GET', '/');
+ $this->assertEquals(200, $this->response->getStatusCode());
+ $this->assertEquals('Hello World', $this->response->getContent());
+ $this->assertTraceContains('miss');
+ $this->assertTraceContains('store');
+ }
+
+ public function testHitsCachedResponsesWithExpiresHeader()
+ {
+ $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->request('GET', '/');
+ $this->assertHttpKernelIsCalled();
+ $this->assertEquals(200, $this->response->getStatusCode());
+ $this->assertNotNull($this->response->headers->get('Date'));
+ $this->assertTraceContains('miss');
+ $this->assertTraceContains('store');
+ $this->assertEquals('Hello World', $this->response->getContent());
+
+ $this->request('GET', '/');
+ $this->assertHttpKernelIsNotCalled();
+ $this->assertEquals(200, $this->response->getStatusCode());
+ $this->assertTrue(strtotime($this->responses[0]->headers->get('Date')) - strtotime($this->response->headers->get('Date')) < 2);
+ $this->assertTrue($this->response->headers->get('Age') > 0);
+ $this->assertNotNull($this->response->headers->get('X-Content-Digest'));
+ $this->assertTraceContains('fresh');
+ $this->assertTraceNotContains('store');
+ $this->assertEquals('Hello World', $this->response->getContent());
+ }
+
+ 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->request('GET', '/');
+ $this->assertHttpKernelIsCalled();
+ $this->assertEquals(200, $this->response->getStatusCode());
+ $this->assertNotNull($this->response->headers->get('Date'));
+ $this->assertTraceContains('miss');
+ $this->assertTraceContains('store');
+ $this->assertEquals('Hello World', $this->response->getContent());
+
+ $this->request('GET', '/');
+ $this->assertHttpKernelIsNotCalled();
+ $this->assertEquals(200, $this->response->getStatusCode());
+ $this->assertTrue(strtotime($this->responses[0]->headers->get('Date')) - strtotime($this->response->headers->get('Date')) < 2);
+ $this->assertTrue($this->response->headers->get('Age') > 0);
+ $this->assertNotNull($this->response->headers->get('X-Content-Digest'));
+ $this->assertTraceContains('fresh');
+ $this->assertTraceNotContains('store');
+ $this->assertEquals('Hello World', $this->response->getContent());
+ }
+
+ public function testDegradationWhenCacheLocked()
+ {
+ 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->request('GET', '/'); // warm the cache
+
+ // Now, lock the cache
+ $concurrentRequest = Request::create('/', 'GET');
+ $this->store->lock($concurrentRequest);
+
+ /*
+ * After 10s, the cached response has become stale. Yet, we're still within the "stale_while_revalidate"
+ * timeout so we may serve the stale response.
+ */
+ sleep(10);
+
+ $this->request('GET', '/');
+ $this->assertHttpKernelIsNotCalled();
+ $this->assertEquals(200, $this->response->getStatusCode());
+ $this->assertTraceContains('stale-while-revalidate');
+ $this->assertEquals('Old response', $this->response->getContent());
+
+ /*
+ * Another 10s later, stale_while_revalidate is over. Resort to serving the old response, but
+ * do so with a "server unavailable" message.
+ */
+ sleep(10);
+
+ $this->request('GET', '/');
+ $this->assertHttpKernelIsNotCalled();
+ $this->assertEquals(503, $this->response->getStatusCode());
+ $this->assertEquals('Old response', $this->response->getContent());
+ }
+
+ 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->request('GET', '/');
+ $this->assertHttpKernelIsCalled();
+ $this->assertEquals(200, $this->response->getStatusCode());
+ $this->assertNotNull($this->response->headers->get('Date'));
+ $this->assertTraceContains('miss');
+ $this->assertTraceContains('store');
+ $this->assertEquals('Hello World', $this->response->getContent());
+
+ $this->request('GET', '/');
+ $this->assertHttpKernelIsNotCalled();
+ $this->assertEquals(200, $this->response->getStatusCode());
+ $this->assertTrue(strtotime($this->responses[0]->headers->get('Date')) - strtotime($this->response->headers->get('Date')) < 2);
+ $this->assertTrue($this->response->headers->get('Age') > 0);
+ $this->assertNotNull($this->response->headers->get('X-Content-Digest'));
+ $this->assertTraceContains('fresh');
+ $this->assertTraceNotContains('store');
+ $this->assertEquals('Hello World', $this->response->getContent());
+ }
+
+ public function testAssignsDefaultTtlWhenResponseHasNoFreshnessInformation()
+ {
+ $this->setNextResponse();
+
+ $this->cacheConfig['default_ttl'] = 10;
+ $this->request('GET', '/');
+ $this->assertHttpKernelIsCalled();
+ $this->assertTraceContains('miss');
+ $this->assertTraceContains('store');
+ $this->assertEquals('Hello World', $this->response->getContent());
+ $this->assertRegExp('/s-maxage=10/', $this->response->headers->get('Cache-Control'));
+
+ $this->cacheConfig['default_ttl'] = 10;
+ $this->request('GET', '/');
+ $this->assertHttpKernelIsNotCalled();
+ $this->assertEquals(200, $this->response->getStatusCode());
+ $this->assertTraceContains('fresh');
+ $this->assertTraceNotContains('store');
+ $this->assertEquals('Hello World', $this->response->getContent());
+ $this->assertRegExp('/s-maxage=10/', $this->response->headers->get('Cache-Control'));
+ }
+
+ public function testAssignsDefaultTtlWhenResponseHasNoFreshnessInformationAndAfterTtlWasExpired()
+ {
+ $this->setNextResponse();
+
+ $this->cacheConfig['default_ttl'] = 2;
+ $this->request('GET', '/');
+ $this->assertHttpKernelIsCalled();
+ $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->request('GET', '/');
+ $this->assertHttpKernelIsNotCalled();
+ $this->assertEquals(200, $this->response->getStatusCode());
+ $this->assertTraceContains('fresh');
+ $this->assertTraceNotContains('store');
+ $this->assertEquals('Hello World', $this->response->getContent());
+ $this->assertRegExp('/s-maxage=2/', $this->response->headers->get('Cache-Control'));
+
+ // expires the cache
+ $values = $this->getMetaStorageValues();
+ $this->assertCount(1, $values);
+ $tmp = unserialize($values[0]);
+ $time = \DateTime::createFromFormat('U', time() - 5);
+ $tmp[0][1]['date'] = $time->format(DATE_RFC2822);
+ $r = new \ReflectionObject($this->store);
+ $m = $r->getMethod('save');
+ $m->setAccessible(true);
+ $m->invoke($this->store, 'md'.hash('sha256', 'http://localhost/'), serialize($tmp));
+
+ $this->request('GET', '/');
+ $this->assertHttpKernelIsCalled();
+ $this->assertEquals(200, $this->response->getStatusCode());
+ $this->assertTraceContains('stale');
+ $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->setNextResponse();
+
+ $this->request('GET', '/');
+ $this->assertHttpKernelIsNotCalled();
+ $this->assertEquals(200, $this->response->getStatusCode());
+ $this->assertTraceContains('fresh');
+ $this->assertTraceNotContains('store');
+ $this->assertEquals('Hello World', $this->response->getContent());
+ $this->assertRegExp('/s-maxage=2/', $this->response->headers->get('Cache-Control'));
+ }
+
+ public function testAssignsDefaultTtlWhenResponseHasNoFreshnessInformationAndAfterTtlWasExpiredWithStatus304()
+ {
+ $this->setNextResponse();
+
+ $this->cacheConfig['default_ttl'] = 2;
+ $this->request('GET', '/');
+ $this->assertHttpKernelIsCalled();
+ $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->request('GET', '/');
+ $this->assertHttpKernelIsNotCalled();
+ $this->assertEquals(200, $this->response->getStatusCode());
+ $this->assertTraceContains('fresh');
+ $this->assertTraceNotContains('store');
+ $this->assertEquals('Hello World', $this->response->getContent());
+
+ // expires the cache
+ $values = $this->getMetaStorageValues();
+ $this->assertCount(1, $values);
+ $tmp = unserialize($values[0]);
+ $time = \DateTime::createFromFormat('U', time() - 5);
+ $tmp[0][1]['date'] = $time->format(DATE_RFC2822);
+ $r = new \ReflectionObject($this->store);
+ $m = $r->getMethod('save');
+ $m->setAccessible(true);
+ $m->invoke($this->store, 'md'.hash('sha256', 'http://localhost/'), serialize($tmp));
+
+ $this->request('GET', '/');
+ $this->assertHttpKernelIsCalled();
+ $this->assertEquals(200, $this->response->getStatusCode());
+ $this->assertTraceContains('stale');
+ $this->assertTraceContains('valid');
+ $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->request('GET', '/');
+ $this->assertHttpKernelIsNotCalled();
+ $this->assertEquals(200, $this->response->getStatusCode());
+ $this->assertTraceContains('fresh');
+ $this->assertTraceNotContains('store');
+ $this->assertEquals('Hello World', $this->response->getContent());
+ $this->assertRegExp('/s-maxage=2/', $this->response->headers->get('Cache-Control'));
+ }
+
+ public function testDoesNotAssignDefaultTtlWhenResponseHasMustRevalidateDirective()
+ {
+ $this->setNextResponse(200, array('Cache-Control' => 'must-revalidate'));
+
+ $this->cacheConfig['default_ttl'] = 10;
+ $this->request('GET', '/');
+ $this->assertHttpKernelIsCalled();
+ $this->assertEquals(200, $this->response->getStatusCode());
+ $this->assertTraceContains('miss');
+ $this->assertTraceNotContains('store');
+ $this->assertNotRegExp('/s-maxage/', $this->response->headers->get('Cache-Control'));
+ $this->assertEquals('Hello World', $this->response->getContent());
+ }
+
+ public function testFetchesFullResponseWhenCacheStaleAndNoValidatorsPresent()
+ {
+ $time = \DateTime::createFromFormat('U', time() + 5);
+ $this->setNextResponse(200, array('Cache-Control' => 'public', 'Expires' => $time->format(DATE_RFC2822)));
+
+ // build initial request
+ $this->request('GET', '/');
+ $this->assertHttpKernelIsCalled();
+ $this->assertEquals(200, $this->response->getStatusCode());
+ $this->assertNotNull($this->response->headers->get('Date'));
+ $this->assertNotNull($this->response->headers->get('X-Content-Digest'));
+ $this->assertNotNull($this->response->headers->get('Age'));
+ $this->assertTraceContains('miss');
+ $this->assertTraceContains('store');
+ $this->assertEquals('Hello World', $this->response->getContent());
+
+ // go in and play around with the cached metadata directly ...
+ $values = $this->getMetaStorageValues();
+ $this->assertCount(1, $values);
+ $tmp = unserialize($values[0]);
+ $time = \DateTime::createFromFormat('U', time());
+ $tmp[0][1]['expires'] = $time->format(DATE_RFC2822);
+ $r = new \ReflectionObject($this->store);
+ $m = $r->getMethod('save');
+ $m->setAccessible(true);
+ $m->invoke($this->store, 'md'.hash('sha256', 'http://localhost/'), serialize($tmp));
+
+ // build subsequent request; should be found but miss due to freshness
+ $this->request('GET', '/');
+ $this->assertHttpKernelIsCalled();
+ $this->assertEquals(200, $this->response->getStatusCode());
+ $this->assertTrue($this->response->headers->get('Age') <= 1);
+ $this->assertNotNull($this->response->headers->get('X-Content-Digest'));
+ $this->assertTraceContains('stale');
+ $this->assertTraceNotContains('fresh');
+ $this->assertTraceNotContains('miss');
+ $this->assertTraceContains('store');
+ $this->assertEquals('Hello World', $this->response->getContent());
+ }
+
+ public function testValidatesCachedResponsesWithLastModifiedAndNoFreshnessInformation()
+ {
+ $time = \DateTime::createFromFormat('U', time());
+ $this->setNextResponse(200, array(), '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')) {
+ $response->setStatusCode(304);
+ $response->setContent('');
+ }
+ });
+
+ // build initial request
+ $this->request('GET', '/');
+ $this->assertHttpKernelIsCalled();
+ $this->assertEquals(200, $this->response->getStatusCode());
+ $this->assertNotNull($this->response->headers->get('Last-Modified'));
+ $this->assertNotNull($this->response->headers->get('X-Content-Digest'));
+ $this->assertEquals('Hello World', $this->response->getContent());
+ $this->assertTraceContains('miss');
+ $this->assertTraceContains('store');
+ $this->assertTraceNotContains('stale');
+
+ // build subsequent request; should be found but miss due to freshness
+ $this->request('GET', '/');
+ $this->assertHttpKernelIsCalled();
+ $this->assertEquals(200, $this->response->getStatusCode());
+ $this->assertNotNull($this->response->headers->get('Last-Modified'));
+ $this->assertNotNull($this->response->headers->get('X-Content-Digest'));
+ $this->assertTrue($this->response->headers->get('Age') <= 1);
+ $this->assertEquals('Hello World', $this->response->getContent());
+ $this->assertTraceContains('stale');
+ $this->assertTraceContains('valid');
+ $this->assertTraceContains('store');
+ $this->assertTraceNotContains('miss');
+ }
+
+ public function testValidatesCachedResponsesUseSameHttpMethod()
+ {
+ $test = $this;
+
+ $this->setNextResponse(200, array(), 'Hello World', function ($request, $response) use ($test) {
+ $test->assertSame('OPTIONS', $request->getMethod());
+ });
+
+ // build initial request
+ $this->request('OPTIONS', '/');
+
+ // build subsequent request
+ $this->request('OPTIONS', '/');
+ }
+
+ public function testValidatesCachedResponsesWithETagAndNoFreshnessInformation()
+ {
+ $this->setNextResponse(200, array(), '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')) {
+ $response->setStatusCode(304);
+ $response->setContent('');
+ }
+ });
+
+ // build initial request
+ $this->request('GET', '/');
+ $this->assertHttpKernelIsCalled();
+ $this->assertEquals(200, $this->response->getStatusCode());
+ $this->assertNotNull($this->response->headers->get('ETag'));
+ $this->assertNotNull($this->response->headers->get('X-Content-Digest'));
+ $this->assertEquals('Hello World', $this->response->getContent());
+ $this->assertTraceContains('miss');
+ $this->assertTraceContains('store');
+
+ // build subsequent request; should be found but miss due to freshness
+ $this->request('GET', '/');
+ $this->assertHttpKernelIsCalled();
+ $this->assertEquals(200, $this->response->getStatusCode());
+ $this->assertNotNull($this->response->headers->get('ETag'));
+ $this->assertNotNull($this->response->headers->get('X-Content-Digest'));
+ $this->assertTrue($this->response->headers->get('Age') <= 1);
+ $this->assertEquals('Hello World', $this->response->getContent());
+ $this->assertTraceContains('stale');
+ $this->assertTraceContains('valid');
+ $this->assertTraceContains('store');
+ $this->assertTraceNotContains('miss');
+ }
+
+ public function testServesResponseWhileFreshAndRevalidatesWithLastModifiedInformation()
+ {
+ $time = \DateTime::createFromFormat('U', time());
+
+ $this->setNextResponse(200, array(), 'Hello World', function (Request $request, Response $response) use ($time) {
+ $response->setSharedMaxAge(10);
+ $response->headers->set('Last-Modified', $time->format(DATE_RFC2822));
+ });
+
+ // prime the cache
+ $this->request('GET', '/');
+
+ // next request before s-maxage has expired: Serve from cache
+ // without hitting the backend
+ $this->request('GET', '/');
+ $this->assertHttpKernelIsNotCalled();
+ $this->assertEquals(200, $this->response->getStatusCode());
+ $this->assertEquals('Hello World', $this->response->getContent());
+ $this->assertTraceContains('fresh');
+
+ sleep(15); // expire the cache
+
+ $this->setNextResponse(304, array(), '', function (Request $request, Response $response) use ($time) {
+ $this->assertEquals($time->format(DATE_RFC2822), $request->headers->get('IF_MODIFIED_SINCE'));
+ });
+
+ $this->request('GET', '/');
+ $this->assertHttpKernelIsCalled();
+ $this->assertEquals(200, $this->response->getStatusCode());
+ $this->assertEquals('Hello World', $this->response->getContent());
+ $this->assertTraceContains('stale');
+ $this->assertTraceContains('valid');
+ }
+
+ public function testReplacesCachedResponsesWhenValidationResultsInNon304Response()
+ {
+ $time = \DateTime::createFromFormat('U', time());
+ $count = 0;
+ $this->setNextResponse(200, array(), '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) {
+ case 1:
+ $response->setContent('first response');
+ break;
+ case 2:
+ $response->setContent('second response');
+ break;
+ case 3:
+ $response->setContent('');
+ $response->setStatusCode(304);
+ break;
+ }
+ });
+
+ // first request should fetch from backend and store in cache
+ $this->request('GET', '/');
+ $this->assertEquals(200, $this->response->getStatusCode());
+ $this->assertEquals('first response', $this->response->getContent());
+
+ // second request is validated, is invalid, and replaces cached entry
+ $this->request('GET', '/');
+ $this->assertEquals(200, $this->response->getStatusCode());
+ $this->assertEquals('second response', $this->response->getContent());
+
+ // third response is validated, valid, and returns cached entry
+ $this->request('GET', '/');
+ $this->assertEquals(200, $this->response->getStatusCode());
+ $this->assertEquals('second response', $this->response->getContent());
+
+ $this->assertEquals(3, $count);
+ }
+
+ public function testPassesHeadRequestsThroughDirectlyOnPass()
+ {
+ $this->setNextResponse(200, array(), 'Hello World', function ($request, $response) {
+ $response->setContent('');
+ $response->setStatusCode(200);
+ $this->assertEquals('HEAD', $request->getMethod());
+ });
+
+ $this->request('HEAD', '/', array('HTTP_EXPECT' => 'something ...'));
+ $this->assertHttpKernelIsCalled();
+ $this->assertEquals('', $this->response->getContent());
+ }
+
+ public function testUsesCacheToRespondToHeadRequestsWhenFresh()
+ {
+ $this->setNextResponse(200, array(), 'Hello World', function ($request, $response) {
+ $response->headers->set('Cache-Control', 'public, max-age=10');
+ $response->setContent('Hello World');
+ $response->setStatusCode(200);
+ $this->assertNotEquals('HEAD', $request->getMethod());
+ });
+
+ $this->request('GET', '/');
+ $this->assertHttpKernelIsCalled();
+ $this->assertEquals('Hello World', $this->response->getContent());
+
+ $this->request('HEAD', '/');
+ $this->assertHttpKernelIsNotCalled();
+ $this->assertEquals(200, $this->response->getStatusCode());
+ $this->assertEquals('', $this->response->getContent());
+ $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) {
+ $response->headers->set('Cache-Control', 'public, max-age=10');
+ $response->headers->set('Last-Modified', $time->format(DATE_RFC2822));
+ });
+
+ $this->request('GET', '/');
+ $this->assertHttpKernelIsCalled();
+ $this->assertEquals('Hello World', $this->response->getContent());
+
+ $this->request('GET', '/', array('HTTP_IF_MODIFIED_SINCE' => $time->format(DATE_RFC2822)));
+ $this->assertHttpKernelIsNotCalled();
+ $this->assertEquals(304, $this->response->getStatusCode());
+ $this->assertEquals('', $this->response->getContent());
+ }
+
+ public function testInvalidatesCachedResponsesOnPost()
+ {
+ $this->setNextResponse(200, array(), 'Hello World', function ($request, $response) {
+ if ('GET' == $request->getMethod()) {
+ $response->setStatusCode(200);
+ $response->headers->set('Cache-Control', 'public, max-age=500');
+ $response->setContent('Hello World');
+ } elseif ('POST' == $request->getMethod()) {
+ $response->setStatusCode(303);
+ $response->headers->set('Location', '/');
+ $response->headers->remove('Cache-Control');
+ $response->setContent('');
+ }
+ });
+
+ // build initial request to enter into the cache
+ $this->request('GET', '/');
+ $this->assertHttpKernelIsCalled();
+ $this->assertEquals(200, $this->response->getStatusCode());
+ $this->assertEquals('Hello World', $this->response->getContent());
+ $this->assertTraceContains('miss');
+ $this->assertTraceContains('store');
+
+ // make sure it is valid
+ $this->request('GET', '/');
+ $this->assertHttpKernelIsNotCalled();
+ $this->assertEquals(200, $this->response->getStatusCode());
+ $this->assertEquals('Hello World', $this->response->getContent());
+ $this->assertTraceContains('fresh');
+
+ // now POST to same URL
+ $this->request('POST', '/helloworld');
+ $this->assertHttpKernelIsCalled();
+ $this->assertEquals('/', $this->response->headers->get('Location'));
+ $this->assertTraceContains('invalidate');
+ $this->assertTraceContains('pass');
+ $this->assertEquals('', $this->response->getContent());
+
+ // now make sure it was actually invalidated
+ $this->request('GET', '/');
+ $this->assertHttpKernelIsCalled();
+ $this->assertEquals(200, $this->response->getStatusCode());
+ $this->assertEquals('Hello World', $this->response->getContent());
+ $this->assertTraceContains('stale');
+ $this->assertTraceContains('invalid');
+ $this->assertTraceContains('store');
+ }
+
+ public function testServesFromCacheWhenHeadersMatch()
+ {
+ $count = 0;
+ $this->setNextResponse(200, array('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->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->assertEquals(200, $this->response->getStatusCode());
+ $this->assertEquals('Bob/1.0', $this->response->getContent());
+ $this->assertTraceContains('fresh');
+ $this->assertTraceNotContains('store');
+ $this->assertNotNull($this->response->headers->get('X-Content-Digest'));
+ }
+
+ public function testStoresMultipleResponsesWhenHeadersDiffer()
+ {
+ $count = 0;
+ $this->setNextResponse(200, array('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->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->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->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->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->assertTraceContains('miss');
+ $this->assertEquals('Bob/2.0', $this->response->getContent());
+ $this->assertEquals(3, $this->response->headers->get('X-Response-Count'));
+ }
+
+ public function testShouldCatchExceptions()
+ {
+ $this->catchExceptions();
+
+ $this->setNextResponse();
+ $this->request('GET', '/');
+
+ $this->assertExceptionsAreCaught();
+ }
+
+ public function testShouldCatchExceptionsWhenReloadingAndNoCacheRequest()
+ {
+ $this->catchExceptions();
+
+ $this->setNextResponse();
+ $this->cacheConfig['allow_reload'] = true;
+ $this->request('GET', '/', array(), array(), false, array('Pragma' => 'no-cache'));
+
+ $this->assertExceptionsAreCaught();
+ }
+
+ public function testShouldNotCatchExceptions()
+ {
+ $this->catchExceptions(false);
+
+ $this->setNextResponse();
+ $this->request('GET', '/');
+
+ $this->assertExceptionsAreNotCaught();
+ }
+
+ public function testEsiCacheSendsTheLowestTtl()
+ {
+ $responses = array(
+ array(
+ 'status' => 200,
+ 'body' => '<esi:include src="/foo" /> <esi:include src="/bar" />',
+ 'headers' => array(
+ 'Cache-Control' => 's-maxage=300',
+ 'Surrogate-Control' => 'content="ESI/1.0"',
+ ),
+ ),
+ array(
+ 'status' => 200,
+ 'body' => 'Hello World!',
+ 'headers' => array('Cache-Control' => 's-maxage=300'),
+ ),
+ array(
+ 'status' => 200,
+ 'body' => 'My name is Bobby.',
+ 'headers' => array('Cache-Control' => 's-maxage=100'),
+ ),
+ );
+
+ $this->setNextResponses($responses);
+
+ $this->request('GET', '/', array(), array(), true);
+ $this->assertEquals('Hello World! My name is Bobby.', $this->response->getContent());
+
+ // check for 100 or 99 as the test can be executed after a second change
+ $this->assertTrue(in_array($this->response->getTtl(), array(99, 100)));
+ }
+
+ public function testEsiCacheForceValidation()
+ {
+ $responses = array(
+ array(
+ 'status' => 200,
+ 'body' => '<esi:include src="/foo" /> <esi:include src="/bar" />',
+ 'headers' => array(
+ 'Cache-Control' => 's-maxage=300',
+ 'Surrogate-Control' => 'content="ESI/1.0"',
+ ),
+ ),
+ array(
+ 'status' => 200,
+ 'body' => 'Hello World!',
+ 'headers' => array('ETag' => 'foobar'),
+ ),
+ array(
+ 'status' => 200,
+ 'body' => 'My name is Bobby.',
+ 'headers' => array('Cache-Control' => 's-maxage=100'),
+ ),
+ );
+
+ $this->setNextResponses($responses);
+
+ $this->request('GET', '/', array(), array(), true);
+ $this->assertEquals('Hello World! My name is Bobby.', $this->response->getContent());
+ $this->assertNull($this->response->getTtl());
+ $this->assertTrue($this->response->mustRevalidate());
+ $this->assertTrue($this->response->headers->hasCacheControlDirective('private'));
+ $this->assertTrue($this->response->headers->hasCacheControlDirective('no-cache'));
+ }
+
+ public function testEsiRecalculateContentLengthHeader()
+ {
+ $responses = array(
+ array(
+ 'status' => 200,
+ 'body' => '<esi:include src="/foo" />',
+ 'headers' => array(
+ 'Content-Length' => 26,
+ 'Cache-Control' => 's-maxage=300',
+ 'Surrogate-Control' => 'content="ESI/1.0"',
+ ),
+ ),
+ array(
+ 'status' => 200,
+ 'body' => 'Hello World!',
+ 'headers' => array(),
+ ),
+ );
+
+ $this->setNextResponses($responses);
+
+ $this->request('GET', '/', array(), array(), true);
+ $this->assertEquals('Hello World!', $this->response->getContent());
+ $this->assertEquals(12, $this->response->headers->get('Content-Length'));
+ }
+
+ public function testClientIpIsAlwaysLocalhostForForwardedRequests()
+ {
+ $this->setNextResponse();
+ $this->request('GET', '/', array('REMOTE_ADDR' => '10.0.0.1'));
+
+ $this->assertEquals('127.0.0.1', $this->kernel->getBackendRequest()->server->get('REMOTE_ADDR'));
+ }
+
+ /**
+ * @dataProvider getTrustedProxyData
+ */
+ public function testHttpCacheIsSetAsATrustedProxy(array $existing, array $expected)
+ {
+ Request::setTrustedProxies($existing, Request::HEADER_X_FORWARDED_ALL);
+
+ $this->setNextResponse();
+ $this->request('GET', '/', array('REMOTE_ADDR' => '10.0.0.1'));
+
+ $this->assertEquals($expected, Request::getTrustedProxies());
+ }
+
+ 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')),
+ );
+ }
+
+ /**
+ * @dataProvider getXForwardedForData
+ */
+ public function testXForwarderForHeaderForForwardedRequests($xForwardedFor, $expected)
+ {
+ $this->setNextResponse();
+ $server = array('REMOTE_ADDR' => '10.0.0.1');
+ if (false !== $xForwardedFor) {
+ $server['HTTP_X_FORWARDED_FOR'] = $xForwardedFor;
+ }
+ $this->request('GET', '/', $server);
+
+ $this->assertEquals($expected, $this->kernel->getBackendRequest()->headers->get('X-Forwarded-For'));
+ }
+
+ 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'),
+ );
+ }
+
+ public function testXForwarderForHeaderForPassRequests()
+ {
+ $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'));
+ }
+
+ public function testEsiCacheRemoveValidationHeadersIfEmbeddedResponses()
+ {
+ $time = \DateTime::createFromFormat('U', time());
+
+ $responses = array(
+ array(
+ 'status' => 200,
+ 'body' => '<esi:include src="/hey" />',
+ 'headers' => array(
+ 'Surrogate-Control' => 'content="ESI/1.0"',
+ 'ETag' => 'hey',
+ 'Last-Modified' => $time->format(DATE_RFC2822),
+ ),
+ ),
+ array(
+ 'status' => 200,
+ 'body' => 'Hey!',
+ 'headers' => array(),
+ ),
+ );
+
+ $this->setNextResponses($responses);
+
+ $this->request('GET', '/', array(), array(), true);
+ $this->assertNull($this->response->getETag());
+ $this->assertNull($this->response->getLastModified());
+ }
+
+ public function testDoesNotCacheOptionsRequest()
+ {
+ $this->setNextResponse(200, array('Cache-Control' => 'public, s-maxage=60'), 'get');
+ $this->request('GET', '/');
+ $this->assertHttpKernelIsCalled();
+
+ $this->setNextResponse(200, array('Cache-Control' => 'public, s-maxage=60'), 'options');
+ $this->request('OPTIONS', '/');
+ $this->assertHttpKernelIsCalled();
+
+ $this->request('GET', '/');
+ $this->assertHttpKernelIsNotCalled();
+ $this->assertSame('get', $this->response->getContent());
+ }
+}
+
+class TestKernel implements HttpKernelInterface
+{
+ public $terminateCalled = false;
+
+ public function terminate(Request $request, Response $response)
+ {
+ $this->terminateCalled = true;
+ }
+
+ public function handle(Request $request, $type = self::MASTER_REQUEST, $catch = true)
+ {
+ }
+}
diff --git a/vendor/symfony/http-kernel/Tests/HttpCache/HttpCacheTestCase.php b/vendor/symfony/http-kernel/Tests/HttpCache/HttpCacheTestCase.php
new file mode 100644
index 0000000000..ed5c690d60
--- /dev/null
+++ b/vendor/symfony/http-kernel/Tests/HttpCache/HttpCacheTestCase.php
@@ -0,0 +1,185 @@
+<?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\HttpKernel\HttpCache\Esi;
+use Symfony\Component\HttpKernel\HttpCache\HttpCache;
+use Symfony\Component\HttpKernel\HttpCache\Store;
+use Symfony\Component\HttpKernel\HttpKernelInterface;
+
+class HttpCacheTestCase extends TestCase
+{
+ protected $kernel;
+ protected $cache;
+ protected $caches;
+ protected $cacheConfig;
+ protected $request;
+ protected $response;
+ protected $responses;
+ protected $catch;
+ protected $esi;
+
+ /**
+ * @var Store
+ */
+ protected $store;
+
+ protected function setUp()
+ {
+ $this->kernel = null;
+
+ $this->cache = null;
+ $this->esi = null;
+ $this->caches = array();
+ $this->cacheConfig = array();
+
+ $this->request = null;
+ $this->response = null;
+ $this->responses = array();
+
+ $this->catch = false;
+
+ $this->clearDirectory(sys_get_temp_dir().'/http_cache');
+ }
+
+ protected function tearDown()
+ {
+ if ($this->cache) {
+ $this->cache->getStore()->cleanup();
+ }
+ $this->kernel = null;
+ $this->cache = null;
+ $this->caches = null;
+ $this->request = null;
+ $this->response = null;
+ $this->responses = null;
+ $this->cacheConfig = null;
+ $this->catch = null;
+ $this->esi = null;
+
+ $this->clearDirectory(sys_get_temp_dir().'/http_cache');
+ }
+
+ public function assertHttpKernelIsCalled()
+ {
+ $this->assertTrue($this->kernel->hasBeenCalled());
+ }
+
+ public function assertHttpKernelIsNotCalled()
+ {
+ $this->assertFalse($this->kernel->hasBeenCalled());
+ }
+
+ public function assertResponseOk()
+ {
+ $this->assertEquals(200, $this->response->getStatusCode());
+ }
+
+ public function assertTraceContains($trace)
+ {
+ $traces = $this->cache->getTraces();
+ $traces = current($traces);
+
+ $this->assertRegExp('/'.$trace.'/', implode(', ', $traces));
+ }
+
+ public function assertTraceNotContains($trace)
+ {
+ $traces = $this->cache->getTraces();
+ $traces = current($traces);
+
+ $this->assertNotRegExp('/'.$trace.'/', implode(', ', $traces));
+ }
+
+ public function assertExceptionsAreCaught()
+ {
+ $this->assertTrue($this->kernel->isCatchingExceptions());
+ }
+
+ public function assertExceptionsAreNotCaught()
+ {
+ $this->assertFalse($this->kernel->isCatchingExceptions());
+ }
+
+ public function request($method, $uri = '/', $server = array(), $cookies = array(), $esi = false, $headers = array())
+ {
+ if (null === $this->kernel) {
+ throw new \LogicException('You must call setNextResponse() before calling request().');
+ }
+
+ $this->kernel->reset();
+
+ $this->store = new Store(sys_get_temp_dir().'/http_cache');
+
+ $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->headers->add($headers);
+
+ $this->response = $this->cache->handle($this->request, HttpKernelInterface::MASTER_REQUEST, $this->catch);
+
+ $this->responses[] = $this->response;
+ }
+
+ public function getMetaStorageValues()
+ {
+ $values = array();
+ 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);
+ }
+
+ return $values;
+ }
+
+ // 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)
+ {
+ $this->kernel = new TestHttpKernel($body, $statusCode, $headers, $customizer);
+ }
+
+ public function setNextResponses($responses)
+ {
+ $this->kernel = new TestMultipleHttpKernel($responses);
+ }
+
+ public function catchExceptions($catch = true)
+ {
+ $this->catch = $catch;
+ }
+
+ public static function clearDirectory($directory)
+ {
+ if (!is_dir($directory)) {
+ return;
+ }
+
+ $fp = opendir($directory);
+ while (false !== $file = readdir($fp)) {
+ if (!in_array($file, array('.', '..'))) {
+ if (is_link($directory.'/'.$file)) {
+ unlink($directory.'/'.$file);
+ } elseif (is_dir($directory.'/'.$file)) {
+ self::clearDirectory($directory.'/'.$file);
+ rmdir($directory.'/'.$file);
+ } else {
+ unlink($directory.'/'.$file);
+ }
+ }
+ }
+
+ closedir($fp);
+ }
+}
diff --git a/vendor/symfony/http-kernel/Tests/HttpCache/ResponseCacheStrategyTest.php b/vendor/symfony/http-kernel/Tests/HttpCache/ResponseCacheStrategyTest.php
new file mode 100644
index 0000000000..5e4c322223
--- /dev/null
+++ b/vendor/symfony/http-kernel/Tests/HttpCache/ResponseCacheStrategyTest.php
@@ -0,0 +1,222 @@
+<?php
+
+/*
+ * This file is part of the Symfony package.
+ *
+ * (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.
+ */
+
+namespace Symfony\Component\HttpKernel\Tests\HttpCache;
+
+use PHPUnit\Framework\TestCase;
+use Symfony\Component\HttpFoundation\Response;
+use Symfony\Component\HttpKernel\HttpCache\ResponseCacheStrategy;
+
+class ResponseCacheStrategyTest extends TestCase
+{
+ public function testMinimumSharedMaxAgeWins()
+ {
+ $cacheStrategy = new ResponseCacheStrategy();
+
+ $response1 = new Response();
+ $response1->setSharedMaxAge(60);
+ $cacheStrategy->add($response1);
+
+ $response2 = new Response();
+ $response2->setSharedMaxAge(3600);
+ $cacheStrategy->add($response2);
+
+ $response = new Response();
+ $response->setSharedMaxAge(86400);
+ $cacheStrategy->update($response);
+
+ $this->assertSame('60', $response->headers->getCacheControlDirective('s-maxage'));
+ }
+
+ public function testSharedMaxAgeNotSetIfNotSetInAnyEmbeddedRequest()
+ {
+ $cacheStrategy = new ResponseCacheStrategy();
+
+ $response1 = new Response();
+ $response1->setSharedMaxAge(60);
+ $cacheStrategy->add($response1);
+
+ $response2 = new Response();
+ $cacheStrategy->add($response2);
+
+ $response = new Response();
+ $response->setSharedMaxAge(86400);
+ $cacheStrategy->update($response);
+
+ $this->assertFalse($response->headers->hasCacheControlDirective('s-maxage'));
+ }
+
+ public function testSharedMaxAgeNotSetIfNotSetInMasterRequest()
+ {
+ $cacheStrategy = new ResponseCacheStrategy();
+
+ $response1 = new Response();
+ $response1->setSharedMaxAge(60);
+ $cacheStrategy->add($response1);
+
+ $response2 = new Response();
+ $response2->setSharedMaxAge(3600);
+ $cacheStrategy->add($response2);
+
+ $response = new Response();
+ $cacheStrategy->update($response);
+
+ $this->assertFalse($response->headers->hasCacheControlDirective('s-maxage'));
+ }
+
+ public function testMasterResponseNotCacheableWhenEmbeddedResponseRequiresValidation()
+ {
+ $cacheStrategy = new ResponseCacheStrategy();
+
+ $embeddedResponse = new Response();
+ $embeddedResponse->setLastModified(new \DateTime());
+ $cacheStrategy->add($embeddedResponse);
+
+ $masterResponse = new Response();
+ $masterResponse->setSharedMaxAge(3600);
+ $cacheStrategy->update($masterResponse);
+
+ $this->assertTrue($masterResponse->headers->hasCacheControlDirective('no-cache'));
+ $this->assertTrue($masterResponse->headers->hasCacheControlDirective('must-revalidate'));
+ $this->assertFalse($masterResponse->isFresh());
+ }
+
+ public function testValidationOnMasterResponseIsNotPossibleWhenItContainsEmbeddedResponses()
+ {
+ $cacheStrategy = new ResponseCacheStrategy();
+
+ // This master response uses the "validation" model
+ $masterResponse = new Response();
+ $masterResponse->setLastModified(new \DateTime());
+ $masterResponse->setEtag('foo');
+
+ // Embedded response uses "expiry" model
+ $embeddedResponse = new Response();
+ $masterResponse->setSharedMaxAge(3600);
+ $cacheStrategy->add($embeddedResponse);
+
+ $cacheStrategy->update($masterResponse);
+
+ $this->assertFalse($masterResponse->isValidateable());
+ $this->assertFalse($masterResponse->headers->has('Last-Modified'));
+ $this->assertFalse($masterResponse->headers->has('ETag'));
+ $this->assertTrue($masterResponse->headers->hasCacheControlDirective('no-cache'));
+ $this->assertTrue($masterResponse->headers->hasCacheControlDirective('must-revalidate'));
+ }
+
+ public function testMasterResponseWithValidationIsUnchangedWhenThereIsNoEmbeddedResponse()
+ {
+ $cacheStrategy = new ResponseCacheStrategy();
+
+ $masterResponse = new Response();
+ $masterResponse->setLastModified(new \DateTime());
+ $cacheStrategy->update($masterResponse);
+
+ $this->assertTrue($masterResponse->isValidateable());
+ }
+
+ public function testMasterResponseWithExpirationIsUnchangedWhenThereIsNoEmbeddedResponse()
+ {
+ $cacheStrategy = new ResponseCacheStrategy();
+
+ $masterResponse = new Response();
+ $masterResponse->setSharedMaxAge(3600);
+ $cacheStrategy->update($masterResponse);
+
+ $this->assertTrue($masterResponse->isFresh());
+ }
+
+ public function testMasterResponseIsNotCacheableWhenEmbeddedResponseIsNotCacheable()
+ {
+ $cacheStrategy = new ResponseCacheStrategy();
+
+ $masterResponse = new Response();
+ $masterResponse->setSharedMaxAge(3600); // Public, cacheable
+
+ /* This response has no validation or expiration information.
+ That makes it uncacheable, it is always stale.
+ (It does *not* make this private, though.) */
+ $embeddedResponse = new Response();
+ $this->assertFalse($embeddedResponse->isFresh()); // not fresh, as no lifetime is provided
+
+ $cacheStrategy->add($embeddedResponse);
+ $cacheStrategy->update($masterResponse);
+
+ $this->assertTrue($masterResponse->headers->hasCacheControlDirective('no-cache'));
+ $this->assertTrue($masterResponse->headers->hasCacheControlDirective('must-revalidate'));
+ $this->assertFalse($masterResponse->isFresh());
+ }
+
+ public function testEmbeddingPrivateResponseMakesMainResponsePrivate()
+ {
+ $cacheStrategy = new ResponseCacheStrategy();
+
+ $masterResponse = new Response();
+ $masterResponse->setSharedMaxAge(3600); // public, cacheable
+
+ // The embedded response might for example contain per-user data that remains valid for 60 seconds
+ $embeddedResponse = new Response();
+ $embeddedResponse->setPrivate();
+ $embeddedResponse->setMaxAge(60); // this would implicitly set "private" as well, but let's be explicit
+
+ $cacheStrategy->add($embeddedResponse);
+ $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...?
+ }
+
+ public function testResponseIsExiprableWhenEmbeddedResponseCombinesExpiryAndValidation()
+ {
+ /* When "expiration wins over validation" (https://symfony.com/doc/current/http_cache/validation.html)
+ * and both the main and embedded response provide s-maxage, then the more restricting value of both
+ * should be fine, regardless of whether the embedded response can be validated later on or must be
+ * completely regenerated.
+ */
+ $cacheStrategy = new ResponseCacheStrategy();
+
+ $masterResponse = new Response();
+ $masterResponse->setSharedMaxAge(3600);
+
+ $embeddedResponse = new Response();
+ $embeddedResponse->setSharedMaxAge(60);
+ $embeddedResponse->setEtag('foo');
+
+ $cacheStrategy->add($embeddedResponse);
+ $cacheStrategy->update($masterResponse);
+
+ $this->assertSame('60', $masterResponse->headers->getCacheControlDirective('s-maxage'));
+ }
+
+ public function testResponseIsExpirableButNotValidateableWhenMasterResponseCombinesExpirationAndValidation()
+ {
+ $cacheStrategy = new ResponseCacheStrategy();
+
+ $masterResponse = new Response();
+ $masterResponse->setSharedMaxAge(3600);
+ $masterResponse->setEtag('foo');
+ $masterResponse->setLastModified(new \DateTime());
+
+ $embeddedResponse = new Response();
+ $embeddedResponse->setSharedMaxAge(60);
+
+ $cacheStrategy->add($embeddedResponse);
+ $cacheStrategy->update($masterResponse);
+
+ $this->assertSame('60', $masterResponse->headers->getCacheControlDirective('s-maxage'));
+ $this->assertFalse($masterResponse->isValidateable());
+ }
+}
diff --git a/vendor/symfony/http-kernel/Tests/HttpCache/SsiTest.php b/vendor/symfony/http-kernel/Tests/HttpCache/SsiTest.php
new file mode 100644
index 0000000000..1079d37a27
--- /dev/null
+++ b/vendor/symfony/http-kernel/Tests/HttpCache/SsiTest.php
@@ -0,0 +1,215 @@
+<?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\Ssi;
+
+class SsiTest extends TestCase
+{
+ public function testHasSurrogateSsiCapability()
+ {
+ $ssi = new Ssi();
+
+ $request = Request::create('/');
+ $request->headers->set('Surrogate-Capability', 'abc="SSI/1.0"');
+ $this->assertTrue($ssi->hasSurrogateCapability($request));
+
+ $request = Request::create('/');
+ $request->headers->set('Surrogate-Capability', 'foobar');
+ $this->assertFalse($ssi->hasSurrogateCapability($request));
+
+ $request = Request::create('/');
+ $this->assertFalse($ssi->hasSurrogateCapability($request));
+ }
+
+ public function testAddSurrogateSsiCapability()
+ {
+ $ssi = new Ssi();
+
+ $request = Request::create('/');
+ $ssi->addSurrogateCapability($request);
+ $this->assertEquals('symfony="SSI/1.0"', $request->headers->get('Surrogate-Capability'));
+
+ $ssi->addSurrogateCapability($request);
+ $this->assertEquals('symfony="SSI/1.0", symfony="SSI/1.0"', $request->headers->get('Surrogate-Capability'));
+ }
+
+ public function testAddSurrogateControl()
+ {
+ $ssi = new Ssi();
+
+ $response = new Response('foo <!--#include virtual="" -->');
+ $ssi->addSurrogateControl($response);
+ $this->assertEquals('content="SSI/1.0"', $response->headers->get('Surrogate-Control'));
+
+ $response = new Response('foo');
+ $ssi->addSurrogateControl($response);
+ $this->assertEquals('', $response->headers->get('Surrogate-Control'));
+ }
+
+ public function testNeedsSsiParsing()
+ {
+ $ssi = new Ssi();
+
+ $response = new Response();
+ $response->headers->set('Surrogate-Control', 'content="SSI/1.0"');
+ $this->assertTrue($ssi->needsParsing($response));
+
+ $response = new Response();
+ $this->assertFalse($ssi->needsParsing($response));
+ }
+
+ public function testRenderIncludeTag()
+ {
+ $ssi = new Ssi();
+
+ $this->assertEquals('<!--#include virtual="/" -->', $ssi->renderIncludeTag('/', '/alt', true));
+ $this->assertEquals('<!--#include virtual="/" -->', $ssi->renderIncludeTag('/', '/alt', false));
+ $this->assertEquals('<!--#include virtual="/" -->', $ssi->renderIncludeTag('/'));
+ }
+
+ public function testProcessDoesNothingIfContentTypeIsNotHtml()
+ {
+ $ssi = new Ssi();
+
+ $request = Request::create('/');
+ $response = new Response();
+ $response->headers->set('Content-Type', 'text/plain');
+ $ssi->process($request, $response);
+
+ $this->assertFalse($response->headers->has('x-body-eval'));
+ }
+
+ public function testProcess()
+ {
+ $ssi = new Ssi();
+
+ $request = Request::create('/');
+ $response = new Response('foo <!--#include virtual="..." -->');
+ $ssi->process($request, $response);
+
+ $this->assertEquals('foo <?php echo $this->surrogate->handle($this, \'...\', \'\', false) ?>'."\n", $response->getContent());
+ $this->assertEquals('SSI', $response->headers->get('x-body-eval'));
+
+ $response = new Response('foo <!--#include virtual="foo\'" -->');
+ $ssi->process($request, $response);
+
+ $this->assertEquals("foo <?php echo \$this->surrogate->handle(\$this, 'foo\\'', '', false) ?>"."\n", $response->getContent());
+ }
+
+ public function testProcessEscapesPhpTags()
+ {
+ $ssi = new Ssi();
+
+ $request = Request::create('/');
+ $response = new Response('<?php <? <% <script language=php>');
+ $ssi->process($request, $response);
+
+ $this->assertEquals('<?php echo "<?"; ?>php <?php echo "<?"; ?> <?php echo "<%"; ?> <?php echo "<s"; ?>cript language=php>', $response->getContent());
+ }
+
+ /**
+ * @expectedException \RuntimeException
+ */
+ public function testProcessWhenNoSrcInAnSsi()
+ {
+ $ssi = new Ssi();
+
+ $request = Request::create('/');
+ $response = new Response('foo <!--#include -->');
+ $ssi->process($request, $response);
+ }
+
+ public function testProcessRemoveSurrogateControlHeader()
+ {
+ $ssi = new Ssi();
+
+ $request = Request::create('/');
+ $response = new Response('foo <!--#include virtual="..." -->');
+ $response->headers->set('Surrogate-Control', 'content="SSI/1.0"');
+ $ssi->process($request, $response);
+ $this->assertEquals('SSI', $response->headers->get('x-body-eval'));
+
+ $response->headers->set('Surrogate-Control', 'no-store, content="SSI/1.0"');
+ $ssi->process($request, $response);
+ $this->assertEquals('SSI', $response->headers->get('x-body-eval'));
+ $this->assertEquals('no-store', $response->headers->get('surrogate-control'));
+
+ $response->headers->set('Surrogate-Control', 'content="SSI/1.0", no-store');
+ $ssi->process($request, $response);
+ $this->assertEquals('SSI', $response->headers->get('x-body-eval'));
+ $this->assertEquals('no-store', $response->headers->get('surrogate-control'));
+ }
+
+ public function testHandle()
+ {
+ $ssi = new Ssi();
+ $cache = $this->getCache(Request::create('/'), new Response('foo'));
+ $this->assertEquals('foo', $ssi->handle($cache, '/', '/alt', true));
+ }
+
+ /**
+ * @expectedException \RuntimeException
+ */
+ public function testHandleWhenResponseIsNot200()
+ {
+ $ssi = new Ssi();
+ $response = new Response('foo');
+ $response->setStatusCode(404);
+ $cache = $this->getCache(Request::create('/'), $response);
+ $ssi->handle($cache, '/', '/alt', false);
+ }
+
+ public function testHandleWhenResponseIsNot200AndErrorsAreIgnored()
+ {
+ $ssi = new Ssi();
+ $response = new Response('foo');
+ $response->setStatusCode(404);
+ $cache = $this->getCache(Request::create('/'), $response);
+ $this->assertEquals('', $ssi->handle($cache, '/', '/alt', true));
+ }
+
+ public function testHandleWhenResponseIsNot200AndAltIsPresent()
+ {
+ $ssi = new Ssi();
+ $response1 = new Response('foo');
+ $response1->setStatusCode(404);
+ $response2 = new Response('bar');
+ $cache = $this->getCache(Request::create('/'), array($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->expects($this->any())
+ ->method('getRequest')
+ ->will($this->returnValue($request))
+ ;
+ if (is_array($response)) {
+ $cache->expects($this->any())
+ ->method('handle')
+ ->will(call_user_func_array(array($this, 'onConsecutiveCalls'), $response))
+ ;
+ } else {
+ $cache->expects($this->any())
+ ->method('handle')
+ ->will($this->returnValue($response))
+ ;
+ }
+
+ return $cache;
+ }
+}
diff --git a/vendor/symfony/http-kernel/Tests/HttpCache/StoreTest.php b/vendor/symfony/http-kernel/Tests/HttpCache/StoreTest.php
new file mode 100644
index 0000000000..cef019167a
--- /dev/null
+++ b/vendor/symfony/http-kernel/Tests/HttpCache/StoreTest.php
@@ -0,0 +1,301 @@
+<?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\Store;
+
+class StoreTest extends TestCase
+{
+ protected $request;
+ protected $response;
+
+ /**
+ * @var Store
+ */
+ protected $store;
+
+ protected function setUp()
+ {
+ $this->request = Request::create('/');
+ $this->response = new Response('hello world', 200, array());
+
+ HttpCacheTestCase::clearDirectory(sys_get_temp_dir().'/http_cache');
+
+ $this->store = new Store(sys_get_temp_dir().'/http_cache');
+ }
+
+ protected function tearDown()
+ {
+ $this->store = null;
+ $this->request = null;
+ $this->response = null;
+
+ HttpCacheTestCase::clearDirectory(sys_get_temp_dir().'/http_cache');
+ }
+
+ public function testReadsAnEmptyArrayWithReadWhenNothingCachedAtKey()
+ {
+ $this->assertEmpty($this->getStoreMetadata('/nothing'));
+ }
+
+ public function testUnlockFileThatDoesExist()
+ {
+ $cacheKey = $this->storeSimpleEntry();
+ $this->store->lock($this->request);
+
+ $this->assertTrue($this->store->unlock($this->request));
+ }
+
+ public function testUnlockFileThatDoesNotExist()
+ {
+ $this->assertFalse($this->store->unlock($this->request));
+ }
+
+ public function testRemovesEntriesForKeyWithPurge()
+ {
+ $request = Request::create('/foo');
+ $this->store->write($request, new Response('foo'));
+
+ $metadata = $this->getStoreMetadata($request);
+ $this->assertNotEmpty($metadata);
+
+ $this->assertTrue($this->store->purge('/foo'));
+ $this->assertEmpty($this->getStoreMetadata($request));
+
+ // cached content should be kept after purging
+ $path = $this->store->getPath($metadata[0][1]['x-content-digest'][0]);
+ $this->assertTrue(is_file($path));
+
+ $this->assertFalse($this->store->purge('/bar'));
+ }
+
+ public function testStoresACacheEntry()
+ {
+ $cacheKey = $this->storeSimpleEntry();
+
+ $this->assertNotEmpty($this->getStoreMetadata($cacheKey));
+ }
+
+ public function testSetsTheXContentDigestResponseHeaderBeforeStoring()
+ {
+ $cacheKey = $this->storeSimpleEntry();
+ $entries = $this->getStoreMetadata($cacheKey);
+ list($req, $res) = $entries[0];
+
+ $this->assertEquals('en9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08', $res['x-content-digest'][0]);
+ }
+
+ public function testFindsAStoredEntryWithLookup()
+ {
+ $this->storeSimpleEntry();
+ $response = $this->store->lookup($this->request);
+
+ $this->assertNotNull($response);
+ $this->assertInstanceOf('Symfony\Component\HttpFoundation\Response', $response);
+ }
+
+ public function testDoesNotFindAnEntryWithLookupWhenNoneExists()
+ {
+ $request = Request::create('/test', 'get', array(), array(), array(), array('HTTP_FOO' => 'Foo', 'HTTP_BAR' => 'Bar'));
+
+ $this->assertNull($this->store->lookup($request));
+ }
+
+ public function testCanonizesUrlsForCacheKeys()
+ {
+ $this->storeSimpleEntry($path = '/test?x=y&p=q');
+ $hitsReq = Request::create($path);
+ $missReq = Request::create('/test?p=x');
+
+ $this->assertNotNull($this->store->lookup($hitsReq));
+ $this->assertNull($this->store->lookup($missReq));
+ }
+
+ public function testDoesNotFindAnEntryWithLookupWhenTheBodyDoesNotExist()
+ {
+ $this->storeSimpleEntry();
+ $this->assertNotNull($this->response->headers->get('X-Content-Digest'));
+ $path = $this->getStorePath($this->response->headers->get('X-Content-Digest'));
+ @unlink($path);
+ $this->assertNull($this->store->lookup($this->request));
+ }
+
+ public function testRestoresResponseHeadersProperlyWithLookup()
+ {
+ $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()));
+ }
+
+ public function testRestoresResponseContentFromEntityStoreWithLookup()
+ {
+ $this->storeSimpleEntry();
+ $response = $this->store->lookup($this->request);
+ $this->assertEquals($this->getStorePath('en'.hash('sha256', 'test')), $response->getContent());
+ }
+
+ public function testInvalidatesMetaAndEntityStoreEntriesWithInvalidate()
+ {
+ $this->storeSimpleEntry();
+ $this->store->invalidate($this->request);
+ $response = $this->store->lookup($this->request);
+ $this->assertInstanceOf('Symfony\Component\HttpFoundation\Response', $response);
+ $this->assertFalse($response->isFresh());
+ }
+
+ public function testSucceedsQuietlyWhenInvalidateCalledWithNoMatchingEntries()
+ {
+ $req = Request::create('/test');
+ $this->store->invalidate($req);
+ $this->assertNull($this->store->lookup($this->request));
+ }
+
+ 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'));
+ $this->store->write($req1, $res);
+
+ $this->assertNull($this->store->lookup($req2));
+ }
+
+ 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')));
+ $this->store->write($req1, $res);
+
+ $this->assertNull($this->store->lookup($req2));
+ }
+
+ 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'));
+ $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'));
+ $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'));
+ $this->store->write($req3, $res3);
+
+ $this->assertEquals($this->getStorePath('en'.hash('sha256', 'test 3')), $this->store->lookup($req3)->getContent());
+ $this->assertEquals($this->getStorePath('en'.hash('sha256', 'test 2')), $this->store->lookup($req2)->getContent());
+ $this->assertEquals($this->getStorePath('en'.hash('sha256', 'test 1')), $this->store->lookup($req1)->getContent());
+
+ $this->assertCount(3, $this->getStoreMetadata($key));
+ }
+
+ 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'));
+ $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'));
+ $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'));
+ $key = $this->store->write($req3, $res3);
+ $this->assertEquals($this->getStorePath('en'.hash('sha256', 'test 3')), $this->store->lookup($req3)->getContent());
+
+ $this->assertCount(2, $this->getStoreMetadata($key));
+ }
+
+ public function testLocking()
+ {
+ $req = Request::create('/test', 'get', array(), array(), array(), array('HTTP_FOO' => 'Foo', 'HTTP_BAR' => 'Bar'));
+ $this->assertTrue($this->store->lock($req));
+
+ $path = $this->store->lock($req);
+ $this->assertTrue($this->store->isLocked($req));
+
+ $this->store->unlock($req);
+ $this->assertFalse($this->store->isLocked($req));
+ }
+
+ public function testPurgeHttps()
+ {
+ $request = Request::create('https://example.com/foo');
+ $this->store->write($request, new Response('foo'));
+
+ $this->assertNotEmpty($this->getStoreMetadata($request));
+
+ $this->assertTrue($this->store->purge('https://example.com/foo'));
+ $this->assertEmpty($this->getStoreMetadata($request));
+ }
+
+ public function testPurgeHttpAndHttps()
+ {
+ $requestHttp = Request::create('https://example.com/foo');
+ $this->store->write($requestHttp, new Response('foo'));
+
+ $requestHttps = Request::create('http://example.com/foo');
+ $this->store->write($requestHttps, new Response('foo'));
+
+ $this->assertNotEmpty($this->getStoreMetadata($requestHttp));
+ $this->assertNotEmpty($this->getStoreMetadata($requestHttps));
+
+ $this->assertTrue($this->store->purge('http://example.com/foo'));
+ $this->assertEmpty($this->getStoreMetadata($requestHttp));
+ $this->assertEmpty($this->getStoreMetadata($requestHttps));
+ }
+
+ protected function storeSimpleEntry($path = null, $headers = array())
+ {
+ 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'));
+
+ return $this->store->write($this->request, $this->response);
+ }
+
+ protected function getStoreMetadata($key)
+ {
+ $r = new \ReflectionObject($this->store);
+ $m = $r->getMethod('getMetadata');
+ $m->setAccessible(true);
+
+ if ($key instanceof Request) {
+ $m1 = $r->getMethod('getCacheKey');
+ $m1->setAccessible(true);
+ $key = $m1->invoke($this->store, $key);
+ }
+
+ return $m->invoke($this->store, $key);
+ }
+
+ protected function getStorePath($key)
+ {
+ $r = new \ReflectionObject($this->store);
+ $m = $r->getMethod('getPath');
+ $m->setAccessible(true);
+
+ return $m->invoke($this->store, $key);
+ }
+}
diff --git a/vendor/symfony/http-kernel/Tests/HttpCache/TestHttpKernel.php b/vendor/symfony/http-kernel/Tests/HttpCache/TestHttpKernel.php
new file mode 100644
index 0000000000..946c7a31cb
--- /dev/null
+++ b/vendor/symfony/http-kernel/Tests/HttpCache/TestHttpKernel.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\HttpKernel\Tests\HttpCache;
+
+use Symfony\Component\HttpKernel\Controller\ArgumentResolverInterface;
+use Symfony\Component\HttpKernel\HttpKernel;
+use Symfony\Component\HttpKernel\HttpKernelInterface;
+use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\HttpFoundation\Response;
+use Symfony\Component\HttpKernel\Controller\ControllerResolverInterface;
+use Symfony\Component\EventDispatcher\EventDispatcher;
+
+class TestHttpKernel extends HttpKernel implements ControllerResolverInterface, ArgumentResolverInterface
+{
+ protected $body;
+ protected $status;
+ protected $headers;
+ protected $called = false;
+ protected $customizer;
+ protected $catch = false;
+ protected $backendRequest;
+
+ public function __construct($body, $status, $headers, \Closure $customizer = null)
+ {
+ $this->body = $body;
+ $this->status = $status;
+ $this->headers = $headers;
+ $this->customizer = $customizer;
+
+ parent::__construct(new EventDispatcher(), $this, null, $this);
+ }
+
+ public function getBackendRequest()
+ {
+ return $this->backendRequest;
+ }
+
+ public function handle(Request $request, $type = HttpKernelInterface::MASTER_REQUEST, $catch = false)
+ {
+ $this->catch = $catch;
+ $this->backendRequest = $request;
+
+ return parent::handle($request, $type, $catch);
+ }
+
+ public function isCatchingExceptions()
+ {
+ return $this->catch;
+ }
+
+ public function getController(Request $request)
+ {
+ return array($this, 'callController');
+ }
+
+ public function getArguments(Request $request, $controller)
+ {
+ return array($request);
+ }
+
+ public function callController(Request $request)
+ {
+ $this->called = true;
+
+ $response = new Response($this->body, $this->status, $this->headers);
+
+ if (null !== $customizer = $this->customizer) {
+ $customizer($request, $response);
+ }
+
+ return $response;
+ }
+
+ public function hasBeenCalled()
+ {
+ return $this->called;
+ }
+
+ public function reset()
+ {
+ $this->called = false;
+ }
+}
diff --git a/vendor/symfony/http-kernel/Tests/HttpCache/TestMultipleHttpKernel.php b/vendor/symfony/http-kernel/Tests/HttpCache/TestMultipleHttpKernel.php
new file mode 100644
index 0000000000..926d8daf53
--- /dev/null
+++ b/vendor/symfony/http-kernel/Tests/HttpCache/TestMultipleHttpKernel.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\Tests\HttpCache;
+
+use Symfony\Component\HttpKernel\Controller\ArgumentResolverInterface;
+use Symfony\Component\HttpKernel\HttpKernel;
+use Symfony\Component\HttpKernel\HttpKernelInterface;
+use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\HttpFoundation\Response;
+use Symfony\Component\HttpKernel\Controller\ControllerResolverInterface;
+use Symfony\Component\EventDispatcher\EventDispatcher;
+
+class TestMultipleHttpKernel extends HttpKernel implements ControllerResolverInterface, ArgumentResolverInterface
+{
+ protected $bodies = array();
+ protected $statuses = array();
+ protected $headers = array();
+ protected $called = false;
+ protected $backendRequest;
+
+ public function __construct($responses)
+ {
+ foreach ($responses as $response) {
+ $this->bodies[] = $response['body'];
+ $this->statuses[] = $response['status'];
+ $this->headers[] = $response['headers'];
+ }
+
+ parent::__construct(new EventDispatcher(), $this, null, $this);
+ }
+
+ public function getBackendRequest()
+ {
+ return $this->backendRequest;
+ }
+
+ public function handle(Request $request, $type = HttpKernelInterface::MASTER_REQUEST, $catch = false)
+ {
+ $this->backendRequest = $request;
+
+ return parent::handle($request, $type, $catch);
+ }
+
+ public function getController(Request $request)
+ {
+ return array($this, 'callController');
+ }
+
+ public function getArguments(Request $request, $controller)
+ {
+ return array($request);
+ }
+
+ public function callController(Request $request)
+ {
+ $this->called = true;
+
+ $response = new Response(array_shift($this->bodies), array_shift($this->statuses), array_shift($this->headers));
+
+ return $response;
+ }
+
+ public function hasBeenCalled()
+ {
+ return $this->called;
+ }
+
+ public function reset()
+ {
+ $this->called = false;
+ }
+}
diff --git a/vendor/symfony/http-kernel/Tests/HttpKernelTest.php b/vendor/symfony/http-kernel/Tests/HttpKernelTest.php
new file mode 100644
index 0000000000..7aed26aa59
--- /dev/null
+++ b/vendor/symfony/http-kernel/Tests/HttpKernelTest.php
@@ -0,0 +1,403 @@
+<?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;
+
+use PHPUnit\Framework\TestCase;
+use Symfony\Component\EventDispatcher\EventDispatcherInterface;
+use Symfony\Component\HttpFoundation\RequestStack;
+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\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()
+ {
+ $kernel = $this->getHttpKernel(new EventDispatcher(), function () { throw new \RuntimeException(); });
+
+ $kernel->handle(new Request(), HttpKernelInterface::MASTER_REQUEST, true);
+ }
+
+ /**
+ * @expectedException \RuntimeException
+ */
+ public function testHandleWhenControllerThrowsAnExceptionAndCatchIsFalseAndNoListenerIsRegistered()
+ {
+ $kernel = $this->getHttpKernel(new EventDispatcher(), function () { throw new \RuntimeException(); });
+
+ $kernel->handle(new Request(), HttpKernelInterface::MASTER_REQUEST, false);
+ }
+
+ public function testHandleWhenControllerThrowsAnExceptionAndCatchIsTrueWithAHandlingListener()
+ {
+ $dispatcher = new EventDispatcher();
+ $dispatcher->addListener(KernelEvents::EXCEPTION, function ($event) {
+ $event->setResponse(new Response($event->getException()->getMessage()));
+ });
+
+ $kernel = $this->getHttpKernel($dispatcher, function () { throw new \RuntimeException('foo'); });
+ $response = $kernel->handle(new Request(), HttpKernelInterface::MASTER_REQUEST, true);
+
+ $this->assertEquals('500', $response->getStatusCode());
+ $this->assertEquals('foo', $response->getContent());
+ }
+
+ public function testHandleWhenControllerThrowsAnExceptionAndCatchIsTrueWithANonHandlingListener()
+ {
+ $exception = new \RuntimeException();
+
+ $dispatcher = new EventDispatcher();
+ $dispatcher->addListener(KernelEvents::EXCEPTION, function ($event) {
+ // should set a response, but does not
+ });
+
+ $kernel = $this->getHttpKernel($dispatcher, function () use ($exception) { throw $exception; });
+
+ try {
+ $kernel->handle(new Request(), HttpKernelInterface::MASTER_REQUEST, true);
+ $this->fail('LogicException expected');
+ } catch (\RuntimeException $e) {
+ $this->assertSame($exception, $e);
+ }
+ }
+
+ public function testHandleExceptionWithARedirectionResponse()
+ {
+ $dispatcher = new EventDispatcher();
+ $dispatcher->addListener(KernelEvents::EXCEPTION, function ($event) {
+ $event->setResponse(new RedirectResponse('/login', 301));
+ });
+
+ $kernel = $this->getHttpKernel($dispatcher, function () { throw new AccessDeniedHttpException(); });
+ $response = $kernel->handle(new Request());
+
+ $this->assertEquals('301', $response->getStatusCode());
+ $this->assertEquals('/login', $response->headers->get('Location'));
+ }
+
+ public function testHandleHttpException()
+ {
+ $dispatcher = new EventDispatcher();
+ $dispatcher->addListener(KernelEvents::EXCEPTION, function ($event) {
+ $event->setResponse(new Response($event->getException()->getMessage()));
+ });
+
+ $kernel = $this->getHttpKernel($dispatcher, function () { throw new MethodNotAllowedHttpException(array('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),
+ );
+ }
+
+ /**
+ * @dataProvider getSpecificStatusCodes
+ */
+ public function testHandleWhenAnExceptionIsHandledWithASpecificStatusCode($expectedStatusCode)
+ {
+ $dispatcher = new EventDispatcher();
+ $dispatcher->addListener(KernelEvents::EXCEPTION, function (GetResponseForExceptionEvent $event) use ($expectedStatusCode) {
+ $event->allowCustomResponseCode();
+ $event->setResponse(new Response('', $expectedStatusCode));
+ });
+
+ $kernel = $this->getHttpKernel($dispatcher, function () { throw new \RuntimeException(); });
+ $response = $kernel->handle(new Request());
+
+ $this->assertEquals($expectedStatusCode, $response->getStatusCode());
+ }
+
+ public function getSpecificStatusCodes()
+ {
+ return array(
+ array(200),
+ array(302),
+ array(403),
+ );
+ }
+
+ public function testHandleWhenAListenerReturnsAResponse()
+ {
+ $dispatcher = new EventDispatcher();
+ $dispatcher->addListener(KernelEvents::REQUEST, function ($event) {
+ $event->setResponse(new Response('hello'));
+ });
+
+ $kernel = $this->getHttpKernel($dispatcher);
+
+ $this->assertEquals('hello', $kernel->handle(new Request())->getContent());
+ }
+
+ /**
+ * @expectedException \Symfony\Component\HttpKernel\Exception\NotFoundHttpException
+ */
+ public function testHandleWhenNoControllerIsFound()
+ {
+ $dispatcher = new EventDispatcher();
+ $kernel = $this->getHttpKernel($dispatcher, false);
+
+ $kernel->handle(new Request());
+ }
+
+ public function testHandleWhenTheControllerIsAClosure()
+ {
+ $response = new Response('foo');
+ $dispatcher = new EventDispatcher();
+ $kernel = $this->getHttpKernel($dispatcher, function () use ($response) { return $response; });
+
+ $this->assertSame($response, $kernel->handle(new Request()));
+ }
+
+ public function testHandleWhenTheControllerIsAnObjectWithInvoke()
+ {
+ $dispatcher = new EventDispatcher();
+ $kernel = $this->getHttpKernel($dispatcher, new Controller());
+
+ $this->assertResponseEquals(new Response('foo'), $kernel->handle(new Request()));
+ }
+
+ public function testHandleWhenTheControllerIsAFunction()
+ {
+ $dispatcher = new EventDispatcher();
+ $kernel = $this->getHttpKernel($dispatcher, 'Symfony\Component\HttpKernel\Tests\controller_func');
+
+ $this->assertResponseEquals(new Response('foo'), $kernel->handle(new Request()));
+ }
+
+ public function testHandleWhenTheControllerIsAnArray()
+ {
+ $dispatcher = new EventDispatcher();
+ $kernel = $this->getHttpKernel($dispatcher, array(new Controller(), 'controller'));
+
+ $this->assertResponseEquals(new Response('foo'), $kernel->handle(new Request()));
+ }
+
+ public function testHandleWhenTheControllerIsAStaticArray()
+ {
+ $dispatcher = new EventDispatcher();
+ $kernel = $this->getHttpKernel($dispatcher, array('Symfony\Component\HttpKernel\Tests\Controller', '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->handle(new Request());
+ }
+
+ public function testHandleWhenTheControllerDoesNotReturnAResponseButAViewIsRegistered()
+ {
+ $dispatcher = new EventDispatcher();
+ $dispatcher->addListener(KernelEvents::VIEW, function ($event) {
+ $event->setResponse(new Response($event->getControllerResult()));
+ });
+
+ $kernel = $this->getHttpKernel($dispatcher, function () { return 'foo'; });
+
+ $this->assertEquals('foo', $kernel->handle(new Request())->getContent());
+ }
+
+ public function testHandleWithAResponseListener()
+ {
+ $dispatcher = new EventDispatcher();
+ $dispatcher->addListener(KernelEvents::RESPONSE, function ($event) {
+ $event->setResponse(new Response('foo'));
+ });
+ $kernel = $this->getHttpKernel($dispatcher);
+
+ $this->assertEquals('foo', $kernel->handle(new Request())->getContent());
+ }
+
+ public function testHandleAllowChangingControllerArguments()
+ {
+ $dispatcher = new EventDispatcher();
+ $dispatcher->addListener(KernelEvents::CONTROLLER_ARGUMENTS, function (FilterControllerArgumentsEvent $event) {
+ $event->setArguments(array('foo'));
+ });
+
+ $kernel = $this->getHttpKernel($dispatcher, function ($content) { return new Response($content); });
+
+ $this->assertResponseEquals(new Response('foo'), $kernel->handle(new Request()));
+ }
+
+ public function testHandleAllowChangingControllerAndArguments()
+ {
+ $dispatcher = new EventDispatcher();
+ $dispatcher->addListener(KernelEvents::CONTROLLER_ARGUMENTS, function (FilterControllerArgumentsEvent $event) {
+ $oldController = $event->getController();
+ $oldArguments = $event->getArguments();
+
+ $newController = function ($id) use ($oldController, $oldArguments) {
+ $response = call_user_func_array($oldController, $oldArguments);
+
+ $response->headers->set('X-Id', $id);
+
+ return $response;
+ };
+
+ $event->setController($newController);
+ $event->setArguments(array('bar'));
+ });
+
+ $kernel = $this->getHttpKernel($dispatcher, function ($content) { return new Response($content); }, null, array('foo'));
+
+ $this->assertResponseEquals(new Response('foo', 200, array('X-Id' => 'bar')), $kernel->handle(new Request()));
+ }
+
+ public function testTerminate()
+ {
+ $dispatcher = new EventDispatcher();
+ $kernel = $this->getHttpKernel($dispatcher);
+ $dispatcher->addListener(KernelEvents::TERMINATE, function ($event) use (&$called, &$capturedKernel, &$capturedRequest, &$capturedResponse) {
+ $called = true;
+ $capturedKernel = $event->getKernel();
+ $capturedRequest = $event->getRequest();
+ $capturedResponse = $event->getResponse();
+ });
+
+ $kernel->terminate($request = Request::create('/'), $response = new Response());
+ $this->assertTrue($called);
+ $this->assertEquals($kernel, $capturedKernel);
+ $this->assertEquals($request, $capturedRequest);
+ $this->assertEquals($response, $capturedResponse);
+ }
+
+ public function testVerifyRequestStackPushPopDuringHandle()
+ {
+ $request = new Request();
+
+ $stack = $this->getMockBuilder('Symfony\Component\HttpFoundation\RequestStack')->setMethods(array('push', 'pop'))->getMock();
+ $stack->expects($this->at(0))->method('push')->with($this->equalTo($request));
+ $stack->expects($this->at(1))->method('pop');
+
+ $dispatcher = new EventDispatcher();
+ $kernel = $this->getHttpKernel($dispatcher, null, $stack);
+
+ $kernel->handle($request, HttpKernelInterface::MASTER_REQUEST);
+ }
+
+ /**
+ * @expectedException \Symfony\Component\HttpKernel\Exception\BadRequestHttpException
+ */
+ public function testInconsistentClientIpsOnMasterRequests()
+ {
+ $request = new Request();
+ $request->setTrustedProxies(array('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 = new EventDispatcher();
+ $dispatcher->addListener(KernelEvents::REQUEST, function ($event) {
+ $event->getRequest()->getClientIp();
+ });
+
+ $kernel = $this->getHttpKernel($dispatcher);
+ $kernel->handle($request, $kernel::MASTER_REQUEST, false);
+ }
+
+ private function getHttpKernel(EventDispatcherInterface $eventDispatcher, $controller = null, RequestStack $requestStack = null, array $arguments = array())
+ {
+ if (null === $controller) {
+ $controller = function () { return new Response('Hello'); };
+ }
+
+ $controllerResolver = $this->getMockBuilder(ControllerResolverInterface::class)->getMock();
+ $controllerResolver
+ ->expects($this->any())
+ ->method('getController')
+ ->will($this->returnValue($controller));
+
+ $argumentResolver = $this->getMockBuilder(ArgumentResolverInterface::class)->getMock();
+ $argumentResolver
+ ->expects($this->any())
+ ->method('getArguments')
+ ->will($this->returnValue($arguments));
+
+ return new HttpKernel($eventDispatcher, $controllerResolver, $requestStack, $argumentResolver);
+ }
+
+ private function assertResponseEquals(Response $expected, Response $actual)
+ {
+ $expected->setDate($actual->getDate());
+ $this->assertEquals($expected, $actual);
+ }
+}
+
+class Controller
+{
+ public function __invoke()
+ {
+ return new Response('foo');
+ }
+
+ public function controller()
+ {
+ return new Response('foo');
+ }
+
+ public static function staticController()
+ {
+ return new Response('foo');
+ }
+}
+
+function controller_func()
+{
+ return new Response('foo');
+}
diff --git a/vendor/symfony/http-kernel/Tests/KernelTest.php b/vendor/symfony/http-kernel/Tests/KernelTest.php
new file mode 100644
index 0000000000..d2a27d03aa
--- /dev/null
+++ b/vendor/symfony/http-kernel/Tests/KernelTest.php
@@ -0,0 +1,900 @@
+<?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;
+
+use PHPUnit\Framework\TestCase;
+use Symfony\Component\Config\Loader\LoaderInterface;
+use Symfony\Component\DependencyInjection\ContainerBuilder;
+use Symfony\Component\HttpKernel\Bundle\BundleInterface;
+use Symfony\Component\HttpKernel\Config\EnvParametersResource;
+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\Tests\Fixtures\KernelForOverrideName;
+use Symfony\Component\HttpKernel\Tests\Fixtures\KernelWithoutBundles;
+
+class KernelTest extends TestCase
+{
+ public function testConstructor()
+ {
+ $env = 'test_env';
+ $debug = true;
+ $kernel = new KernelForTest($env, $debug);
+
+ $this->assertEquals($env, $kernel->getEnvironment());
+ $this->assertEquals($debug, $kernel->isDebug());
+ $this->assertFalse($kernel->isBooted());
+ $this->assertLessThanOrEqual(microtime(true), $kernel->getStartTime());
+ $this->assertNull($kernel->getContainer());
+ }
+
+ public function testClone()
+ {
+ $env = 'test_env';
+ $debug = true;
+ $kernel = new KernelForTest($env, $debug);
+
+ $clone = clone $kernel;
+
+ $this->assertEquals($env, $clone->getEnvironment());
+ $this->assertEquals($debug, $clone->isDebug());
+ $this->assertFalse($clone->isBooted());
+ $this->assertLessThanOrEqual(microtime(true), $clone->getStartTime());
+ $this->assertNull($clone->getContainer());
+ }
+
+ public function testBootInitializesBundlesAndContainer()
+ {
+ $kernel = $this->getKernel(array('initializeBundles', 'initializeContainer'));
+ $kernel->expects($this->once())
+ ->method('initializeBundles');
+ $kernel->expects($this->once())
+ ->method('initializeContainer');
+
+ $kernel->boot();
+ }
+
+ public function testBootSetsTheContainerToTheBundles()
+ {
+ $bundle = $this->getMockBuilder('Symfony\Component\HttpKernel\Bundle\Bundle')->getMock();
+ $bundle->expects($this->once())
+ ->method('setContainer');
+
+ $kernel = $this->getKernel(array('initializeBundles', 'initializeContainer', 'getBundles'));
+ $kernel->expects($this->once())
+ ->method('getBundles')
+ ->will($this->returnValue(array($bundle)));
+
+ $kernel->boot();
+ }
+
+ public function testBootSetsTheBootedFlagToTrue()
+ {
+ // use test kernel to access isBooted()
+ $kernel = $this->getKernelForTest(array('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->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->expects($this->once())
+ ->method('initializeBundles');
+
+ $kernel->boot();
+ $kernel->boot();
+ }
+
+ public function testShutdownCallsShutdownOnAllBundles()
+ {
+ $bundle = $this->getMockBuilder('Symfony\Component\HttpKernel\Bundle\Bundle')->getMock();
+ $bundle->expects($this->once())
+ ->method('shutdown');
+
+ $kernel = $this->getKernel(array(), array($bundle));
+
+ $kernel->boot();
+ $kernel->shutdown();
+ }
+
+ public function testShutdownGivesNullContainerToAllBundles()
+ {
+ $bundle = $this->getMockBuilder('Symfony\Component\HttpKernel\Bundle\Bundle')->getMock();
+ $bundle->expects($this->at(3))
+ ->method('setContainer')
+ ->with(null);
+
+ $kernel = $this->getKernel(array('getBundles'));
+ $kernel->expects($this->any())
+ ->method('getBundles')
+ ->will($this->returnValue(array($bundle)));
+
+ $kernel->boot();
+ $kernel->shutdown();
+ }
+
+ public function testHandleCallsHandleOnHttpKernel()
+ {
+ $type = HttpKernelInterface::MASTER_REQUEST;
+ $catch = true;
+ $request = new Request();
+
+ $httpKernelMock = $this->getMockBuilder('Symfony\Component\HttpKernel\HttpKernel')
+ ->disableOriginalConstructor()
+ ->getMock();
+ $httpKernelMock
+ ->expects($this->once())
+ ->method('handle')
+ ->with($request, $type, $catch);
+
+ $kernel = $this->getKernel(array('getHttpKernel'));
+ $kernel->expects($this->once())
+ ->method('getHttpKernel')
+ ->will($this->returnValue($httpKernelMock));
+
+ $kernel->handle($request, $type, $catch);
+ }
+
+ public function testHandleBootsTheKernel()
+ {
+ $type = HttpKernelInterface::MASTER_REQUEST;
+ $catch = true;
+ $request = new Request();
+
+ $httpKernelMock = $this->getMockBuilder('Symfony\Component\HttpKernel\HttpKernel')
+ ->disableOriginalConstructor()
+ ->getMock();
+
+ $kernel = $this->getKernel(array('getHttpKernel', 'boot'));
+ $kernel->expects($this->once())
+ ->method('getHttpKernel')
+ ->will($this->returnValue($httpKernelMock));
+
+ $kernel->expects($this->once())
+ ->method('boot');
+
+ $kernel->handle($request, $type, $catch);
+ }
+
+ public function testStripComments()
+ {
+ $source = <<<'EOF'
+<?php
+
+$string = 'string should not be modified';
+
+$string = 'string should not be
+
+modified';
+
+
+$heredoc = <<<HD
+
+
+Heredoc should not be modified {$a[1+$b]}
+
+
+HD;
+
+$nowdoc = <<<'ND'
+
+
+Nowdoc should not be modified
+
+
+ND;
+
+/**
+ * some class comments to strip
+ */
+class TestClass
+{
+ /**
+ * some method comments to strip
+ */
+ public function doStuff()
+ {
+ // inline comment
+ }
+}
+EOF;
+ $expected = <<<'EOF'
+<?php
+$string = 'string should not be modified';
+$string = 'string should not be
+
+modified';
+$heredoc = <<<HD
+
+
+Heredoc should not be modified {$a[1+$b]}
+
+
+HD;
+$nowdoc = <<<'ND'
+
+
+Nowdoc should not be modified
+
+
+ND;
+class TestClass
+{
+ public function doStuff()
+ {
+ }
+}
+EOF;
+
+ $output = Kernel::stripComments($source);
+
+ // Heredocs are preserved, making the output mixing Unix and Windows line
+ // endings, switching to "\n" everywhere on Windows to avoid failure.
+ if ('\\' === DIRECTORY_SEPARATOR) {
+ $expected = str_replace("\r\n", "\n", $expected);
+ $output = str_replace("\r\n", "\n", $output);
+ }
+
+ $this->assertEquals($expected, $output);
+ }
+
+ public function testGetRootDir()
+ {
+ $kernel = new KernelForTest('test', true);
+
+ $this->assertEquals(__DIR__.DIRECTORY_SEPARATOR.'Fixtures', realpath($kernel->getRootDir()));
+ }
+
+ public function testGetName()
+ {
+ $kernel = new KernelForTest('test', true);
+
+ $this->assertEquals('Fixtures', $kernel->getName());
+ }
+
+ public function testOverrideGetName()
+ {
+ $kernel = new KernelForOverrideName('test', true);
+
+ $this->assertEquals('overridden', $kernel->getName());
+ }
+
+ public function testSerialize()
+ {
+ $env = 'test_env';
+ $debug = true;
+ $kernel = new KernelForTest($env, $debug);
+
+ $expected = serialize(array($env, $debug));
+ $this->assertEquals($expected, $kernel->serialize());
+ }
+
+ /**
+ * @expectedException \InvalidArgumentException
+ */
+ public function testLocateResourceThrowsExceptionWhenNameIsNotValid()
+ {
+ $this->getKernel()->locateResource('Foo');
+ }
+
+ /**
+ * @expectedException \RuntimeException
+ */
+ public function testLocateResourceThrowsExceptionWhenNameIsUnsafe()
+ {
+ $this->getKernel()->locateResource('@FooBundle/../bar');
+ }
+
+ /**
+ * @expectedException \InvalidArgumentException
+ */
+ public function testLocateResourceThrowsExceptionWhenBundleDoesNotExist()
+ {
+ $this->getKernel()->locateResource('@FooBundle/config/routing.xml');
+ }
+
+ /**
+ * @expectedException \InvalidArgumentException
+ */
+ public function testLocateResourceThrowsExceptionWhenResourceDoesNotExist()
+ {
+ $kernel = $this->getKernel(array('getBundle'));
+ $kernel
+ ->expects($this->once())
+ ->method('getBundle')
+ ->will($this->returnValue(array($this->getBundle(__DIR__.'/Fixtures/Bundle1Bundle'))))
+ ;
+
+ $kernel->locateResource('@Bundle1Bundle/config/routing.xml');
+ }
+
+ public function testLocateResourceReturnsTheFirstThatMatches()
+ {
+ $kernel = $this->getKernel(array('getBundle'));
+ $kernel
+ ->expects($this->once())
+ ->method('getBundle')
+ ->will($this->returnValue(array($this->getBundle(__DIR__.'/Fixtures/Bundle1Bundle'))))
+ ;
+
+ $this->assertEquals(__DIR__.'/Fixtures/Bundle1Bundle/foo.txt', $kernel->locateResource('@Bundle1Bundle/foo.txt'));
+ }
+
+ 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'));
+ }
+
+ 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));
+ }
+
+ 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
+ ->expects($this->once())
+ ->method('getBundle')
+ ->will($this->returnValue(array($this->getBundle(__DIR__.'/Fixtures/Bundle1Bundle'))))
+ ;
+
+ $this->assertEquals(
+ __DIR__.'/Fixtures/Bundle1Bundle/foo.txt',
+ $kernel->locateResource('@Bundle1Bundle/foo.txt', __DIR__.'/Fixtures')
+ );
+ }
+
+ public function testLocateResourceReturnsTheDirOneForResources()
+ {
+ $kernel = $this->getKernel(array('getBundle'));
+ $kernel
+ ->expects($this->once())
+ ->method('getBundle')
+ ->will($this->returnValue(array($this->getBundle(__DIR__.'/Fixtures/FooBundle', null, null, 'FooBundle'))))
+ ;
+
+ $this->assertEquals(
+ __DIR__.'/Fixtures/Resources/FooBundle/foo.txt',
+ $kernel->locateResource('@FooBundle/Resources/foo.txt', __DIR__.'/Fixtures/Resources')
+ );
+ }
+
+ 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)
+ );
+ }
+
+ 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
+ ->expects($this->exactly(2))
+ ->method('getBundle')
+ ->will($this->returnValue(array($this->getBundle(__DIR__.'/Fixtures/FooBundle', null, null, 'FooBundle'))))
+ ;
+
+ $this->assertEquals(
+ __DIR__.'/Fixtures/Resources/FooBundle/',
+ $kernel->locateResource('@FooBundle/Resources/', __DIR__.'/Fixtures/Resources')
+ );
+ $this->assertEquals(
+ __DIR__.'/Fixtures/Resources/FooBundle',
+ $kernel->locateResource('@FooBundle/Resources', __DIR__.'/Fixtures/Resources')
+ );
+
+ $kernel = $this->getKernel(array('getBundle'));
+ $kernel
+ ->expects($this->exactly(2))
+ ->method('getBundle')
+ ->will($this->returnValue(array($this->getBundle(__DIR__.'/Fixtures/Bundle1Bundle', null, null, 'Bundle1Bundle'))))
+ ;
+
+ $this->assertEquals(
+ __DIR__.'/Fixtures/Bundle1Bundle/Resources/',
+ $kernel->locateResource('@Bundle1Bundle/Resources/')
+ );
+ $this->assertEquals(
+ __DIR__.'/Fixtures/Bundle1Bundle/Resources',
+ $kernel->locateResource('@Bundle1Bundle/Resources')
+ );
+ }
+
+ 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']);
+ }
+
+ 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']);
+ }
+
+ /**
+ * @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();
+ }
+
+ 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']);
+ }
+
+ /**
+ * @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();
+ }
+
+ /**
+ * @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');
+
+ $kernel = $this->getKernel(array(), array($fooBundle, $barBundle));
+ $kernel->boot();
+ }
+
+ /**
+ * @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->boot();
+ }
+
+ public function testTerminateReturnsSilentlyIfKernelIsNotBooted()
+ {
+ $kernel = $this->getKernel(array('getHttpKernel'));
+ $kernel->expects($this->never())
+ ->method('getHttpKernel');
+
+ $kernel->terminate(Request::create('/'), new Response());
+ }
+
+ public function testTerminateDelegatesTerminationOnlyForTerminableInterface()
+ {
+ // does not implement TerminableInterface
+ $httpKernel = new TestKernel();
+
+ $kernel = $this->getKernel(array('getHttpKernel'));
+ $kernel->expects($this->once())
+ ->method('getHttpKernel')
+ ->willReturn($httpKernel);
+
+ $kernel->boot();
+ $kernel->terminate(Request::create('/'), new Response());
+
+ $this->assertFalse($httpKernel->terminateCalled, 'terminate() is never called if the kernel class does not implement TerminableInterface');
+
+ // implements TerminableInterface
+ $httpKernelMock = $this->getMockBuilder('Symfony\Component\HttpKernel\HttpKernel')
+ ->disableOriginalConstructor()
+ ->setMethods(array('terminate'))
+ ->getMock();
+
+ $httpKernelMock
+ ->expects($this->once())
+ ->method('terminate');
+
+ $kernel = $this->getKernel(array('getHttpKernel'));
+ $kernel->expects($this->exactly(2))
+ ->method('getHttpKernel')
+ ->will($this->returnValue($httpKernelMock));
+
+ $kernel->boot();
+ $kernel->terminate(Request::create('/'), new Response());
+ }
+
+ public function testKernelWithoutBundles()
+ {
+ $kernel = new KernelWithoutBundles('test', true);
+ $kernel->boot();
+
+ $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('test', true);
+ $kernel->boot();
+
+ $this->assertSame('foo', $kernel->getProjectDir());
+ $this->assertSame('foo', $kernel->getContainer()->getParameter('kernel.project_dir'));
+ }
+
+ /**
+ * Returns a mock for the BundleInterface.
+ *
+ * @return BundleInterface
+ */
+ protected function getBundle($dir = null, $parent = null, $className = null, $bundleName = null)
+ {
+ $bundle = $this
+ ->getMockBuilder('Symfony\Component\HttpKernel\Bundle\BundleInterface')
+ ->setMethods(array('getPath', 'getParent', 'getName'))
+ ->disableOriginalConstructor()
+ ;
+
+ if ($className) {
+ $bundle->setMockClassName($className);
+ }
+
+ $bundle = $bundle->getMockForAbstractClass();
+
+ $bundle
+ ->expects($this->any())
+ ->method('getName')
+ ->will($this->returnValue(null === $bundleName ? get_class($bundle) : $bundleName))
+ ;
+
+ $bundle
+ ->expects($this->any())
+ ->method('getPath')
+ ->will($this->returnValue($dir))
+ ;
+
+ $bundle
+ ->expects($this->any())
+ ->method('getParent')
+ ->will($this->returnValue($parent))
+ ;
+
+ return $bundle;
+ }
+
+ /**
+ * Returns a mock for the abstract kernel.
+ *
+ * @param array $methods Additional methods to mock (besides the abstract ones)
+ * @param array $bundles Bundles to register
+ *
+ * @return Kernel
+ */
+ protected function getKernel(array $methods = array(), array $bundles = array())
+ {
+ $methods[] = 'registerBundles';
+
+ $kernel = $this
+ ->getMockBuilder('Symfony\Component\HttpKernel\Kernel')
+ ->setMethods($methods)
+ ->setConstructorArgs(array('test', false))
+ ->getMockForAbstractClass()
+ ;
+ $kernel->expects($this->any())
+ ->method('registerBundles')
+ ->will($this->returnValue($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;
+ }
+}
+
+class TestKernel implements HttpKernelInterface
+{
+ public $terminateCalled = false;
+
+ public function terminate()
+ {
+ $this->terminateCalled = true;
+ }
+
+ public function handle(Request $request, $type = self::MASTER_REQUEST, $catch = true)
+ {
+ }
+}
+
+class CustomProjectDirKernel extends Kernel
+{
+ private $baseDir;
+
+ public function __construct()
+ {
+ parent::__construct('test', false);
+
+ $this->baseDir = 'foo';
+ }
+
+ public function registerBundles()
+ {
+ return array();
+ }
+
+ public function registerContainerConfiguration(LoaderInterface $loader)
+ {
+ }
+
+ public function getProjectDir()
+ {
+ return $this->baseDir;
+ }
+
+ public function getRootDir()
+ {
+ return __DIR__.'/Fixtures';
+ }
+}
diff --git a/vendor/symfony/http-kernel/Tests/Logger.php b/vendor/symfony/http-kernel/Tests/Logger.php
new file mode 100644
index 0000000000..63c70bf67a
--- /dev/null
+++ b/vendor/symfony/http-kernel/Tests/Logger.php
@@ -0,0 +1,88 @@
+<?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;
+
+use Psr\Log\LoggerInterface;
+
+class Logger implements LoggerInterface
+{
+ protected $logs;
+
+ public function __construct()
+ {
+ $this->clear();
+ }
+
+ public function getLogs($level = false)
+ {
+ 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(),
+ );
+ }
+
+ public function log($level, $message, array $context = array())
+ {
+ $this->logs[$level][] = $message;
+ }
+
+ public function emergency($message, array $context = array())
+ {
+ $this->log('emergency', $message, $context);
+ }
+
+ public function alert($message, array $context = array())
+ {
+ $this->log('alert', $message, $context);
+ }
+
+ public function critical($message, array $context = array())
+ {
+ $this->log('critical', $message, $context);
+ }
+
+ public function error($message, array $context = array())
+ {
+ $this->log('error', $message, $context);
+ }
+
+ public function warning($message, array $context = array())
+ {
+ $this->log('warning', $message, $context);
+ }
+
+ public function notice($message, array $context = array())
+ {
+ $this->log('notice', $message, $context);
+ }
+
+ public function info($message, array $context = array())
+ {
+ $this->log('info', $message, $context);
+ }
+
+ public function debug($message, array $context = array())
+ {
+ $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
new file mode 100644
index 0000000000..99ff207567
--- /dev/null
+++ b/vendor/symfony/http-kernel/Tests/Profiler/FileProfilerStorageTest.php
@@ -0,0 +1,350 @@
+<?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\Profiler;
+
+use PHPUnit\Framework\TestCase;
+use Symfony\Component\HttpKernel\Profiler\FileProfilerStorage;
+use Symfony\Component\HttpKernel\Profiler\Profile;
+
+class FileProfilerStorageTest extends TestCase
+{
+ private $tmpDir;
+ private $storage;
+
+ protected function setUp()
+ {
+ $this->tmpDir = sys_get_temp_dir().'/sf2_profiler_file_storage';
+ if (is_dir($this->tmpDir)) {
+ self::cleanDir();
+ }
+ $this->storage = new FileProfilerStorage('file:'.$this->tmpDir);
+ $this->storage->purge();
+ }
+
+ protected function tearDown()
+ {
+ self::cleanDir();
+ }
+
+ public function testStore()
+ {
+ for ($i = 0; $i < 10; ++$i) {
+ $profile = new Profile('token_'.$i);
+ $profile->setIp('127.0.0.1');
+ $profile->setUrl('http://foo.bar');
+ $profile->setMethod('GET');
+ $this->storage->write($profile);
+ }
+ $this->assertCount(10, $this->storage->find('127.0.0.1', 'http://foo.bar', 20, 'GET'), '->write() stores data in the storage');
+ }
+
+ public function testChildren()
+ {
+ $parentProfile = new Profile('token_parent');
+ $parentProfile->setIp('127.0.0.1');
+ $parentProfile->setUrl('http://foo.bar/parent');
+
+ $childProfile = new Profile('token_child');
+ $childProfile->setIp('127.0.0.1');
+ $childProfile->setUrl('http://foo.bar/child');
+
+ $parentProfile->addChild($childProfile);
+
+ $this->storage->write($parentProfile);
+ $this->storage->write($childProfile);
+
+ // Load them from storage
+ $parentProfile = $this->storage->read('token_parent');
+ $childProfile = $this->storage->read('token_child');
+
+ // Check child has link to parent
+ $this->assertNotNull($childProfile->getParent());
+ $this->assertEquals($parentProfile->getToken(), $childProfile->getParentToken());
+
+ // Check parent has child
+ $children = $parentProfile->getChildren();
+ $this->assertCount(1, $children);
+ $this->assertEquals($childProfile->getToken(), $children[0]->getToken());
+ }
+
+ public function testStoreSpecialCharsInUrl()
+ {
+ // The storage accepts special characters in URLs (Even though URLs are not
+ // supposed to contain them)
+ $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');
+
+ $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');
+
+ $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');
+
+ $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');
+ }
+
+ public function testStoreDuplicateToken()
+ {
+ $profile = new Profile('token');
+ $profile->setUrl('http://example.com/');
+
+ $this->assertTrue($this->storage->write($profile), '->write() returns true when the token is unique');
+
+ $profile->setUrl('http://example.net/');
+
+ $this->assertTrue($this->storage->write($profile), '->write() returns true when the token is already present in the storage');
+ $this->assertEquals('http://example.net/', $this->storage->read('token')->getUrl(), '->write() overwrites the current profile data');
+
+ $this->assertCount(1, $this->storage->find('', '', 1000, ''), '->find() does not return the same profile twice');
+ }
+
+ public function testRetrieveByIp()
+ {
+ $profile = new Profile('token');
+ $profile->setIp('127.0.0.1');
+ $profile->setMethod('GET');
+ $this->storage->write($profile);
+
+ $this->assertCount(1, $this->storage->find('127.0.0.1', '', 10, 'GET'), '->find() retrieve a record by IP');
+ $this->assertCount(0, $this->storage->find('127.0.%.1', '', 10, 'GET'), '->find() does not interpret a "%" as a wildcard in the IP');
+ $this->assertCount(0, $this->storage->find('127.0._.1', '', 10, 'GET'), '->find() does not interpret a "_" as a wildcard in the IP');
+ }
+
+ public function testRetrieveByStatusCode()
+ {
+ $profile200 = new Profile('statuscode200');
+ $profile200->setStatusCode(200);
+ $this->storage->write($profile200);
+
+ $profile404 = new Profile('statuscode404');
+ $profile404->setStatusCode(404);
+ $this->storage->write($profile404);
+
+ $this->assertCount(1, $this->storage->find(null, null, 10, null, null, null, '200'), '->find() retrieve a record by Status code 200');
+ $this->assertCount(1, $this->storage->find(null, null, 10, null, null, null, '404'), '->find() retrieve a record by Status code 404');
+ }
+
+ public function testRetrieveByUrl()
+ {
+ $profile = new Profile('simple_quote');
+ $profile->setIp('127.0.0.1');
+ $profile->setUrl('http://foo.bar/\'');
+ $profile->setMethod('GET');
+ $this->storage->write($profile);
+
+ $profile = new Profile('double_quote');
+ $profile->setIp('127.0.0.1');
+ $profile->setUrl('http://foo.bar/"');
+ $profile->setMethod('GET');
+ $this->storage->write($profile);
+
+ $profile = new Profile('backslash');
+ $profile->setIp('127.0.0.1');
+ $profile->setUrl('http://foo\\bar/');
+ $profile->setMethod('GET');
+ $this->storage->write($profile);
+
+ $profile = new Profile('percent');
+ $profile->setIp('127.0.0.1');
+ $profile->setUrl('http://foo.bar/%');
+ $profile->setMethod('GET');
+ $this->storage->write($profile);
+
+ $profile = new Profile('underscore');
+ $profile->setIp('127.0.0.1');
+ $profile->setUrl('http://foo.bar/_');
+ $profile->setMethod('GET');
+ $this->storage->write($profile);
+
+ $profile = new Profile('semicolon');
+ $profile->setIp('127.0.0.1');
+ $profile->setUrl('http://foo.bar/;');
+ $profile->setMethod('GET');
+ $this->storage->write($profile);
+
+ $this->assertCount(1, $this->storage->find('127.0.0.1', 'http://foo.bar/\'', 10, 'GET'), '->find() accepts single quotes in URLs');
+ $this->assertCount(1, $this->storage->find('127.0.0.1', 'http://foo.bar/"', 10, 'GET'), '->find() accepts double quotes in URLs');
+ $this->assertCount(1, $this->storage->find('127.0.0.1', 'http://foo\\bar/', 10, 'GET'), '->find() accepts backslash in URLs');
+ $this->assertCount(1, $this->storage->find('127.0.0.1', 'http://foo.bar/;', 10, 'GET'), '->find() accepts semicolon in URLs');
+ $this->assertCount(1, $this->storage->find('127.0.0.1', 'http://foo.bar/%', 10, 'GET'), '->find() does not interpret a "%" as a wildcard in the URL');
+ $this->assertCount(1, $this->storage->find('127.0.0.1', 'http://foo.bar/_', 10, 'GET'), '->find() does not interpret a "_" as a wildcard in the URL');
+ }
+
+ public function testStoreTime()
+ {
+ $dt = new \DateTime('now');
+ $start = $dt->getTimestamp();
+
+ for ($i = 0; $i < 3; ++$i) {
+ $dt->modify('+1 minute');
+ $profile = new Profile('time_'.$i);
+ $profile->setIp('127.0.0.1');
+ $profile->setUrl('http://foo.bar');
+ $profile->setTime($dt->getTimestamp());
+ $profile->setMethod('GET');
+ $this->storage->write($profile);
+ }
+
+ $records = $this->storage->find('', '', 3, 'GET', $start, time() + 3 * 60);
+ $this->assertCount(3, $records, '->find() returns all previously added records');
+ $this->assertEquals($records[0]['token'], 'time_2', '->find() returns records ordered by time in descendant order');
+ $this->assertEquals($records[1]['token'], 'time_1', '->find() returns records ordered by time in descendant order');
+ $this->assertEquals($records[2]['token'], 'time_0', '->find() returns records ordered by time in descendant order');
+
+ $records = $this->storage->find('', '', 3, 'GET', $start, time() + 2 * 60);
+ $this->assertCount(2, $records, '->find() should return only first two of the previously added records');
+ }
+
+ public function testRetrieveByEmptyUrlAndIp()
+ {
+ for ($i = 0; $i < 5; ++$i) {
+ $profile = new Profile('token_'.$i);
+ $profile->setMethod('GET');
+ $this->storage->write($profile);
+ }
+ $this->assertCount(5, $this->storage->find('', '', 10, 'GET'), '->find() returns all previously added records');
+ $this->storage->purge();
+ }
+
+ public function testRetrieveByMethodAndLimit()
+ {
+ foreach (array('POST', 'GET') as $method) {
+ for ($i = 0; $i < 5; ++$i) {
+ $profile = new Profile('token_'.$i.$method);
+ $profile->setMethod($method);
+ $this->storage->write($profile);
+ }
+ }
+
+ $this->assertCount(5, $this->storage->find('', '', 5, 'POST'));
+
+ $this->storage->purge();
+ }
+
+ public function testPurge()
+ {
+ $profile = new Profile('token1');
+ $profile->setIp('127.0.0.1');
+ $profile->setUrl('http://example.com/');
+ $profile->setMethod('GET');
+ $this->storage->write($profile);
+
+ $this->assertTrue(false !== $this->storage->read('token1'));
+ $this->assertCount(1, $this->storage->find('127.0.0.1', '', 10, 'GET'));
+
+ $profile = new Profile('token2');
+ $profile->setIp('127.0.0.1');
+ $profile->setUrl('http://example.net/');
+ $profile->setMethod('GET');
+ $this->storage->write($profile);
+
+ $this->assertTrue(false !== $this->storage->read('token2'));
+ $this->assertCount(2, $this->storage->find('127.0.0.1', '', 10, 'GET'));
+
+ $this->storage->purge();
+
+ $this->assertEmpty($this->storage->read('token'), '->purge() removes all data stored by profiler');
+ $this->assertCount(0, $this->storage->find('127.0.0.1', '', 10, 'GET'), '->purge() removes all items from index');
+ }
+
+ public function testDuplicates()
+ {
+ for ($i = 1; $i <= 5; ++$i) {
+ $profile = new Profile('foo'.$i);
+ $profile->setIp('127.0.0.1');
+ $profile->setUrl('http://example.net/');
+ $profile->setMethod('GET');
+
+ ///three duplicates
+ $this->storage->write($profile);
+ $this->storage->write($profile);
+ $this->storage->write($profile);
+ }
+ $this->assertCount(3, $this->storage->find('127.0.0.1', 'http://example.net/', 3, 'GET'), '->find() method returns incorrect number of entries');
+ }
+
+ public function testStatusCode()
+ {
+ $profile = new Profile('token1');
+ $profile->setStatusCode(200);
+ $this->storage->write($profile);
+
+ $profile = new Profile('token2');
+ $profile->setStatusCode(404);
+ $this->storage->write($profile);
+
+ $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));
+ }
+
+ public function testMultiRowIndexFile()
+ {
+ $iteration = 3;
+ for ($i = 0; $i < $iteration; ++$i) {
+ $profile = new Profile('token'.$i);
+ $profile->setIp('127.0.0.'.$i);
+ $profile->setUrl('http://foo.bar/'.$i);
+
+ $this->storage->write($profile);
+ $this->storage->write($profile);
+ $this->storage->write($profile);
+ }
+
+ $handle = fopen($this->tmpDir.'/index.csv', 'r');
+ for ($i = 0; $i < $iteration; ++$i) {
+ $row = fgetcsv($handle);
+ $this->assertEquals('token'.$i, $row[0]);
+ $this->assertEquals('127.0.0.'.$i, $row[1]);
+ $this->assertEquals('http://foo.bar/'.$i, $row[3]);
+ }
+ $this->assertFalse(fgetcsv($handle));
+ }
+
+ public function testReadLineFromFile()
+ {
+ $r = new \ReflectionMethod($this->storage, 'readLineFromFile');
+
+ $r->setAccessible(true);
+
+ $h = tmpfile();
+
+ fwrite($h, "line1\n\n\nline2\n");
+ fseek($h, 0, SEEK_END);
+
+ $this->assertEquals('line2', $r->invoke($this->storage, $h));
+ $this->assertEquals('line1', $r->invoke($this->storage, $h));
+ }
+
+ protected function cleanDir()
+ {
+ $flags = \FilesystemIterator::SKIP_DOTS;
+ $iterator = new \RecursiveDirectoryIterator($this->tmpDir, $flags);
+ $iterator = new \RecursiveIteratorIterator($iterator, \RecursiveIteratorIterator::SELF_FIRST);
+
+ foreach ($iterator as $file) {
+ if (is_file($file)) {
+ unlink($file);
+ }
+ }
+ }
+}
diff --git a/vendor/symfony/http-kernel/Tests/Profiler/ProfilerTest.php b/vendor/symfony/http-kernel/Tests/Profiler/ProfilerTest.php
new file mode 100644
index 0000000000..1a6f54636a
--- /dev/null
+++ b/vendor/symfony/http-kernel/Tests/Profiler/ProfilerTest.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\Tests\Profiler;
+
+use PHPUnit\Framework\TestCase;
+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
+{
+ private $tmp;
+ private $storage;
+
+ public function testCollect()
+ {
+ $request = new Request();
+ $request->query->set('foo', 'bar');
+ $response = new Response('', 204);
+ $collector = new RequestDataCollector();
+
+ $profiler = new Profiler($this->storage);
+ $profiler->add($collector);
+ $profile = $profiler->collect($request, $response);
+ $profiler->saveProfile($profile);
+
+ $this->assertSame(204, $profile->getStatusCode());
+ $this->assertSame('GET', $profile->getMethod());
+ $this->assertSame('bar', $profile->getCollector('request')->getRequestQuery()->all()['foo']->getValue());
+ }
+
+ public function testFindWorksWithDates()
+ {
+ $profiler = new Profiler($this->storage);
+
+ $this->assertCount(0, $profiler->find(null, null, null, null, '7th April 2014', '9th April 2014'));
+ }
+
+ public function testFindWorksWithTimestamps()
+ {
+ $profiler = new Profiler($this->storage);
+
+ $this->assertCount(0, $profiler->find(null, null, null, null, '1396828800', '1397001600'));
+ }
+
+ public function testFindWorksWithInvalidDates()
+ {
+ $profiler = new Profiler($this->storage);
+
+ $this->assertCount(0, $profiler->find(null, null, null, null, 'some string', ''));
+ }
+
+ public function testFindWorksWithStatusCode()
+ {
+ $profiler = new Profiler($this->storage);
+
+ $this->assertCount(0, $profiler->find(null, null, null, null, null, null, '204'));
+ }
+
+ protected function setUp()
+ {
+ $this->tmp = tempnam(sys_get_temp_dir(), 'sf2_profiler');
+ if (file_exists($this->tmp)) {
+ @unlink($this->tmp);
+ }
+
+ $this->storage = new FileProfilerStorage('file:'.$this->tmp);
+ $this->storage->purge();
+ }
+
+ protected function tearDown()
+ {
+ if (null !== $this->storage) {
+ $this->storage->purge();
+ $this->storage = null;
+
+ @unlink($this->tmp);
+ }
+ }
+}
diff --git a/vendor/symfony/http-kernel/Tests/TestHttpKernel.php b/vendor/symfony/http-kernel/Tests/TestHttpKernel.php
new file mode 100644
index 0000000000..3ec5927254
--- /dev/null
+++ b/vendor/symfony/http-kernel/Tests/TestHttpKernel.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\HttpKernel\Tests;
+
+use Symfony\Component\HttpKernel\Controller\ArgumentResolverInterface;
+use Symfony\Component\HttpKernel\HttpKernel;
+use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\HttpFoundation\Response;
+use Symfony\Component\HttpKernel\Controller\ControllerResolverInterface;
+use Symfony\Component\EventDispatcher\EventDispatcher;
+
+class TestHttpKernel extends HttpKernel implements ControllerResolverInterface, ArgumentResolverInterface
+{
+ public function __construct()
+ {
+ parent::__construct(new EventDispatcher(), $this, null, $this);
+ }
+
+ public function getController(Request $request)
+ {
+ return array($this, 'callController');
+ }
+
+ public function getArguments(Request $request, $controller)
+ {
+ return array($request);
+ }
+
+ public function callController(Request $request)
+ {
+ return new Response('Request: '.$request->getRequestUri());
+ }
+}
diff --git a/vendor/symfony/http-kernel/Tests/UriSignerTest.php b/vendor/symfony/http-kernel/Tests/UriSignerTest.php
new file mode 100644
index 0000000000..253a4c91bd
--- /dev/null
+++ b/vendor/symfony/http-kernel/Tests/UriSignerTest.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\HttpKernel\Tests;
+
+use PHPUnit\Framework\TestCase;
+use Symfony\Component\HttpKernel\UriSigner;
+
+class UriSignerTest extends TestCase
+{
+ public function testSign()
+ {
+ $signer = new UriSigner('foobar');
+
+ $this->assertContains('?_hash=', $signer->sign('http://example.com/foo'));
+ $this->assertContains('&_hash=', $signer->sign('http://example.com/foo?foo=bar'));
+ }
+
+ public function testCheck()
+ {
+ $signer = new UriSigner('foobar');
+
+ $this->assertFalse($signer->check('http://example.com/foo?_hash=foo'));
+ $this->assertFalse($signer->check('http://example.com/foo?foo=bar&_hash=foo'));
+ $this->assertFalse($signer->check('http://example.com/foo?foo=bar&_hash=foo&bar=foo'));
+
+ $this->assertTrue($signer->check($signer->sign('http://example.com/foo')));
+ $this->assertTrue($signer->check($signer->sign('http://example.com/foo?foo=bar')));
+ $this->assertTrue($signer->check($signer->sign('http://example.com/foo?foo=bar&0=integer')));
+
+ $this->assertTrue($signer->sign('http://example.com/foo?foo=bar&bar=foo') === $signer->sign('http://example.com/foo?bar=foo&foo=bar'));
+ }
+
+ public function testCheckWithDifferentArgSeparator()
+ {
+ $this->iniSet('arg_separator.output', '&amp;');
+ $signer = new UriSigner('foobar');
+
+ $this->assertSame(
+ 'http://example.com/foo?baz=bay&foo=bar&_hash=rIOcC%2FF3DoEGo%2FvnESjSp7uU9zA9S%2F%2BOLhxgMexoPUM%3D',
+ $signer->sign('http://example.com/foo?foo=bar&baz=bay')
+ );
+ $this->assertTrue($signer->check($signer->sign('http://example.com/foo?foo=bar&baz=bay')));
+ }
+
+ public function testCheckWithDifferentParameter()
+ {
+ $signer = new UriSigner('foobar', 'qux');
+
+ $this->assertSame(
+ 'http://example.com/foo?baz=bay&foo=bar&qux=rIOcC%2FF3DoEGo%2FvnESjSp7uU9zA9S%2F%2BOLhxgMexoPUM%3D',
+ $signer->sign('http://example.com/foo?foo=bar&baz=bay')
+ );
+ $this->assertTrue($signer->check($signer->sign('http://example.com/foo?foo=bar&baz=bay')));
+ }
+}
diff --git a/vendor/symfony/http-kernel/UriSigner.php b/vendor/symfony/http-kernel/UriSigner.php
new file mode 100644
index 0000000000..6f4f8865e2
--- /dev/null
+++ b/vendor/symfony/http-kernel/UriSigner.php
@@ -0,0 +1,112 @@
+<?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;
+
+/**
+ * Signs URIs.
+ *
+ * @author Fabien Potencier <fabien@symfony.com>
+ */
+class UriSigner
+{
+ private $secret;
+ private $parameter;
+
+ /**
+ * Constructor.
+ *
+ * @param string $secret A secret
+ * @param string $parameter Query string parameter to use
+ */
+ public function __construct($secret, $parameter = '_hash')
+ {
+ $this->secret = $secret;
+ $this->parameter = $parameter;
+ }
+
+ /**
+ * Signs a URI.
+ *
+ * The given URI is signed by adding the query string parameter
+ * which value depends on the URI and the secret.
+ *
+ * @param string $uri A URI to sign
+ *
+ * @return string The signed URI
+ */
+ public function sign($uri)
+ {
+ $url = parse_url($uri);
+ if (isset($url['query'])) {
+ parse_str($url['query'], $params);
+ } else {
+ $params = array();
+ }
+
+ $uri = $this->buildUrl($url, $params);
+
+ return $uri.(false === strpos($uri, '?') ? '?' : '&').$this->parameter.'='.$this->computeHash($uri);
+ }
+
+ /**
+ * Checks that a URI contains the correct hash.
+ *
+ * The query string parameter must be the last one
+ * (as it is generated that way by the sign() method, it should
+ * never be a problem).
+ *
+ * @param string $uri A signed URI
+ *
+ * @return bool True if the URI is signed correctly, false otherwise
+ */
+ public function check($uri)
+ {
+ $url = parse_url($uri);
+ if (isset($url['query'])) {
+ parse_str($url['query'], $params);
+ } else {
+ $params = array();
+ }
+
+ if (empty($params[$this->parameter])) {
+ return false;
+ }
+
+ $hash = urlencode($params[$this->parameter]);
+ unset($params[$this->parameter]);
+
+ return $this->computeHash($this->buildUrl($url, $params)) === $hash;
+ }
+
+ private function computeHash($uri)
+ {
+ return urlencode(base64_encode(hash_hmac('sha256', $uri, $this->secret, true)));
+ }
+
+ private function buildUrl(array $url, array $params = array())
+ {
+ ksort($params, SORT_STRING);
+ $url['query'] = http_build_query($params, '', '&');
+
+ $scheme = isset($url['scheme']) ? $url['scheme'].'://' : '';
+ $host = isset($url['host']) ? $url['host'] : '';
+ $port = isset($url['port']) ? ':'.$url['port'] : '';
+ $user = isset($url['user']) ? $url['user'] : '';
+ $pass = isset($url['pass']) ? ':'.$url['pass'] : '';
+ $pass = ($user || $pass) ? "$pass@" : '';
+ $path = isset($url['path']) ? $url['path'] : '';
+ $query = isset($url['query']) && $url['query'] ? '?'.$url['query'] : '';
+ $fragment = isset($url['fragment']) ? '#'.$url['fragment'] : '';
+
+ return $scheme.$user.$pass.$host.$port.$path.$query.$fragment;
+ }
+}
diff --git a/vendor/symfony/http-kernel/composer.json b/vendor/symfony/http-kernel/composer.json
new file mode 100644
index 0000000000..babc8663b6
--- /dev/null
+++ b/vendor/symfony/http-kernel/composer.json
@@ -0,0 +1,70 @@
+{
+ "name": "symfony/http-kernel",
+ "type": "library",
+ "description": "Symfony HttpKernel Component",
+ "keywords": [],
+ "homepage": "https://symfony.com",
+ "license": "MIT",
+ "authors": [
+ {
+ "name": "Fabien Potencier",
+ "email": "fabien@symfony.com"
+ },
+ {
+ "name": "Symfony Community",
+ "homepage": "https://symfony.com/contributors"
+ }
+ ],
+ "require": {
+ "php": ">=5.5.9",
+ "symfony/event-dispatcher": "~2.8|~3.0",
+ "symfony/http-foundation": "~3.3",
+ "symfony/debug": "~2.8|~3.0",
+ "psr/log": "~1.0"
+ },
+ "require-dev": {
+ "symfony/browser-kit": "~2.8|~3.0",
+ "symfony/class-loader": "~2.8|~3.0",
+ "symfony/config": "~2.8|~3.0",
+ "symfony/console": "~2.8|~3.0",
+ "symfony/css-selector": "~2.8|~3.0",
+ "symfony/dependency-injection": "~3.3",
+ "symfony/dom-crawler": "~2.8|~3.0",
+ "symfony/expression-language": "~2.8|~3.0",
+ "symfony/finder": "~2.8|~3.0",
+ "symfony/process": "~2.8|~3.0",
+ "symfony/routing": "~2.8|~3.0",
+ "symfony/stopwatch": "~2.8|~3.0",
+ "symfony/templating": "~2.8|~3.0",
+ "symfony/translation": "~2.8|~3.0",
+ "symfony/var-dumper": "~3.3",
+ "psr/cache": "~1.0"
+ },
+ "conflict": {
+ "symfony/config": "<2.8",
+ "symfony/dependency-injection": "<3.3",
+ "symfony/var-dumper": "<3.3",
+ "twig/twig": "<1.34|<2.4,>=2"
+ },
+ "suggest": {
+ "symfony/browser-kit": "",
+ "symfony/class-loader": "",
+ "symfony/config": "",
+ "symfony/console": "",
+ "symfony/dependency-injection": "",
+ "symfony/finder": "",
+ "symfony/var-dumper": ""
+ },
+ "autoload": {
+ "psr-4": { "Symfony\\Component\\HttpKernel\\": "" },
+ "exclude-from-classmap": [
+ "/Tests/"
+ ]
+ },
+ "minimum-stability": "dev",
+ "extra": {
+ "branch-alias": {
+ "dev-master": "3.3-dev"
+ }
+ }
+}
diff --git a/vendor/symfony/http-kernel/phpunit.xml.dist b/vendor/symfony/http-kernel/phpunit.xml.dist
new file mode 100644
index 0000000000..e0de769dd7
--- /dev/null
+++ b/vendor/symfony/http-kernel/phpunit.xml.dist
@@ -0,0 +1,40 @@
+<?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"
+ backupGlobals="false"
+ colors="true"
+ bootstrap="vendor/autoload.php"
+ failOnRisky="true"
+ failOnWarning="true"
+>
+ <php>
+ <ini name="error_reporting" value="-1" />
+ </php>
+
+ <testsuites>
+ <testsuite name="Symfony HttpKernel Component Test Suite">
+ <directory>./Tests/</directory>
+ </testsuite>
+ </testsuites>
+
+ <filter>
+ <whitelist>
+ <directory>./</directory>
+ <exclude>
+ <directory>./Tests</directory>
+ <directory>./vendor</directory>
+ </exclude>
+ </whitelist>
+ </filter>
+
+ <listeners>
+ <listener class="Symfony\Bridge\PhpUnit\SymfonyTestsListener">
+ <arguments>
+ <array>
+ <element key="time-sensitive"><string>Symfony\Component\HttpFoundation</string></element>
+ </array>
+ </arguments>
+ </listener>
+ </listeners>
+</phpunit>