From 60b4089f707caebd2265f8cee35da1d29147b56e Mon Sep 17 00:00:00 2001 From: bnw Date: Thu, 3 Sep 2015 17:49:27 +0200 Subject: [PATCH 01/36] Introduce MetadataValidators to test arbitrary metadata for freshness. --- .../Resources/config/routing.xml | 3 ++ .../Resources/config/services.xml | 10 ++++++ .../Resources/config/translation.xml | 3 ++ src/Symfony/Component/Config/ConfigCache.php | 19 ++++++++--- .../Component/Config/ConfigCacheFactory.php | 15 ++++++++- .../DependencyInjection/ConfigCachePass.php | 33 +++++++++++++++++++ .../Config/MetadataValidatorInterface.php | 26 +++++++++++++++ .../Config/Resource/ResourceValidator.php | 32 ++++++++++++++++++ 8 files changed, 136 insertions(+), 5 deletions(-) create mode 100644 src/Symfony/Component/Config/DependencyInjection/ConfigCachePass.php create mode 100644 src/Symfony/Component/Config/MetadataValidatorInterface.php create mode 100644 src/Symfony/Component/Config/Resource/ResourceValidator.php diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/routing.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/routing.xml index 78a98177287db..95f4e837a8e67 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/routing.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/routing.xml @@ -75,6 +75,9 @@ + + + diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/services.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/services.xml index 2021505726fef..a102c3757d88d 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/services.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/services.xml @@ -13,6 +13,8 @@ Symfony\Component\HttpKernel\Config\FileLocator Symfony\Component\HttpKernel\UriSigner Symfony\Component\HttpFoundation\RequestStack + Symfony\Component\Config\ConfigCacheFactory + Symfony\Component\Config\Resource\ResourceValidator @@ -63,5 +65,13 @@ %kernel.secret% + + + %kernel.debug% + + + + + diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/translation.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/translation.xml index 0007a360c6e46..ff4c18f212f2d 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/translation.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/translation.xml @@ -45,6 +45,9 @@ %kernel.debug% + + + diff --git a/src/Symfony/Component/Config/ConfigCache.php b/src/Symfony/Component/Config/ConfigCache.php index cc99bc9211cde..9c16e5e4d85e1 100644 --- a/src/Symfony/Component/Config/ConfigCache.php +++ b/src/Symfony/Component/Config/ConfigCache.php @@ -12,6 +12,7 @@ namespace Symfony\Component\Config; use Symfony\Component\Config\Resource\ResourceInterface; +use Symfony\Component\Config\Resource\ResourceValidator; use Symfony\Component\Filesystem\Exception\IOException; use Symfony\Component\Filesystem\Filesystem; @@ -68,9 +69,10 @@ public function getPath() * This method always returns true when debug is off and the * cache file exists. * + * @param MetadataValidatorInterface[] $validators List of validators the metadata is checked against. * @return bool true if the cache is fresh, false otherwise */ - public function isFresh() + public function isFresh(array $validators = null) { if (!is_file($this->file)) { return false; @@ -87,9 +89,18 @@ public function isFresh() $time = filemtime($this->file); $meta = unserialize(file_get_contents($metadata)); - foreach ($meta as $resource) { - if (!$resource->isFresh($time)) { - return false; + + if (null === $validators) { + $validators = array(new ResourceValidator()); + } + foreach ($validators as $validator) { + foreach ($meta as $resource) { + if (!$validator->supports($resource)) { + continue; + } + if (!$validator->isFresh($resource, $time)) { + return false; + } } } diff --git a/src/Symfony/Component/Config/ConfigCacheFactory.php b/src/Symfony/Component/Config/ConfigCacheFactory.php index 5a8f4562388b0..2b787765176a6 100644 --- a/src/Symfony/Component/Config/ConfigCacheFactory.php +++ b/src/Symfony/Component/Config/ConfigCacheFactory.php @@ -24,6 +24,11 @@ class ConfigCacheFactory implements ConfigCacheFactoryInterface */ private $debug; + /** + * @var MetadataValidatorInterface[] List of validators used by the ConfigCache + */ + private $validators = array(); + /** * @param bool $debug The debug flag to pass to ConfigCache */ @@ -32,6 +37,14 @@ public function __construct($debug) $this->debug = $debug; } + /** + * @param MetadataValidatorInterface $validator + */ + public function addValidator(MetadataValidatorInterface $validator) + { + $validator[] = $validator; + } + /** * {@inheritdoc} */ @@ -42,7 +55,7 @@ public function cache($file, $callback) } $cache = new ConfigCache($file, $this->debug); - if (!$cache->isFresh()) { + if (!$cache->isFresh($this->validators)) { call_user_func($callback, $cache); } diff --git a/src/Symfony/Component/Config/DependencyInjection/ConfigCachePass.php b/src/Symfony/Component/Config/DependencyInjection/ConfigCachePass.php new file mode 100644 index 0000000000000..53717efc09864 --- /dev/null +++ b/src/Symfony/Component/Config/DependencyInjection/ConfigCachePass.php @@ -0,0 +1,33 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Config\DependencyInjection; + +use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Reference; + +/** + * Adds tagged metadata_validator services to config_cache_factory service. + * + * @author Benjamin Klotz + */ +class ConfigCachePass implements CompilerPassInterface +{ + public function process(ContainerBuilder $container) + { + $definition = $container->getDefinition('config_cache_factory'); + + foreach ($container->findTaggedServiceIds('config_cache.metadata_validator') as $id => $attributes) { + $definition->addMethodCall('addValidator', array(new Reference($id))); + } + } +} \ No newline at end of file diff --git a/src/Symfony/Component/Config/MetadataValidatorInterface.php b/src/Symfony/Component/Config/MetadataValidatorInterface.php new file mode 100644 index 0000000000000..f633dc562649e --- /dev/null +++ b/src/Symfony/Component/Config/MetadataValidatorInterface.php @@ -0,0 +1,26 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Config; + +/** + * Base interface to test arbitrary metadata for freshness. + * + * @author Benjamin Klotz + */ +interface MetadataValidatorInterface +{ + + public function supports($metadata); + + public function isFresh($metadata, $timestamp); + +} \ No newline at end of file diff --git a/src/Symfony/Component/Config/Resource/ResourceValidator.php b/src/Symfony/Component/Config/Resource/ResourceValidator.php new file mode 100644 index 0000000000000..47873b0d40c98 --- /dev/null +++ b/src/Symfony/Component/Config/Resource/ResourceValidator.php @@ -0,0 +1,32 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Config\Resource; + +use Symfony\Component\Config\MetadataValidatorInterface; + +/** + * Validator for Resources. + * + * @author Benjamin Klotz + */ +class ResourceValidator implements MetadataValidatorInterface +{ + public function supports($metadata) + { + return $metadata instanceof ResourceInterface; + } + + public function isFresh($metadata, $timestamp) + { + return $metadata->isFresh($timestamp); + } +} \ No newline at end of file From 673070b304a406df3108b71d1574d104b335a5fc Mon Sep 17 00:00:00 2001 From: bnw Date: Fri, 4 Sep 2015 10:27:16 +0200 Subject: [PATCH 02/36] Added trailing newline --- .../Component/Config/DependencyInjection/ConfigCachePass.php | 2 +- src/Symfony/Component/Config/MetadataValidatorInterface.php | 2 +- src/Symfony/Component/Config/Resource/ResourceValidator.php | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Component/Config/DependencyInjection/ConfigCachePass.php b/src/Symfony/Component/Config/DependencyInjection/ConfigCachePass.php index 53717efc09864..cb5d3c1417243 100644 --- a/src/Symfony/Component/Config/DependencyInjection/ConfigCachePass.php +++ b/src/Symfony/Component/Config/DependencyInjection/ConfigCachePass.php @@ -30,4 +30,4 @@ public function process(ContainerBuilder $container) $definition->addMethodCall('addValidator', array(new Reference($id))); } } -} \ No newline at end of file +} diff --git a/src/Symfony/Component/Config/MetadataValidatorInterface.php b/src/Symfony/Component/Config/MetadataValidatorInterface.php index f633dc562649e..c7562629d9bc6 100644 --- a/src/Symfony/Component/Config/MetadataValidatorInterface.php +++ b/src/Symfony/Component/Config/MetadataValidatorInterface.php @@ -23,4 +23,4 @@ public function supports($metadata); public function isFresh($metadata, $timestamp); -} \ No newline at end of file +} diff --git a/src/Symfony/Component/Config/Resource/ResourceValidator.php b/src/Symfony/Component/Config/Resource/ResourceValidator.php index 47873b0d40c98..170db9bb150a2 100644 --- a/src/Symfony/Component/Config/Resource/ResourceValidator.php +++ b/src/Symfony/Component/Config/Resource/ResourceValidator.php @@ -29,4 +29,4 @@ public function isFresh($metadata, $timestamp) { return $metadata->isFresh($timestamp); } -} \ No newline at end of file +} From ab3912965887d6fba3dab1e23fd6d4e89641cd3a Mon Sep 17 00:00:00 2001 From: bnw Date: Fri, 4 Sep 2015 13:12:58 +0200 Subject: [PATCH 03/36] Added new parameter to interface --- src/Symfony/Component/Config/ConfigCacheInterface.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/Config/ConfigCacheInterface.php b/src/Symfony/Component/Config/ConfigCacheInterface.php index e367ad187ee6c..fc449013a320c 100644 --- a/src/Symfony/Component/Config/ConfigCacheInterface.php +++ b/src/Symfony/Component/Config/ConfigCacheInterface.php @@ -32,9 +32,11 @@ public function getPath(); * * This check should take the metadata passed to the write() method into consideration. * + * @param MetadataValidatorInterface[] $validators List of validators the metadata is checked against. + * * @return bool Whether the cache is still fresh. */ - public function isFresh(); + public function isFresh(array $validators = null); /** * Writes the given content into the cache file. Metadata will be stored From 9546be901d0436e821e581b62da7a330ebf86062 Mon Sep 17 00:00:00 2001 From: bnw Date: Fri, 4 Sep 2015 13:29:49 +0200 Subject: [PATCH 04/36] Renamed ResourceValidator to ResourceInterfaceValidator Added test for ResourceInterfaceValidator ConfigCache::isFresh: Stop validation as soon as we found a supporting validator --- src/Symfony/Component/Config/ConfigCache.php | 29 ++++++---- ...tor.php => ResourceInterfaceValidator.php} | 4 +- .../Config/Tests/ConfigCacheTest.php | 16 ++++-- .../ResourceInterfaceValidatorTest.php | 56 +++++++++++++++++++ src/Symfony/Component/HttpKernel/Kernel.php | 2 +- 5 files changed, 87 insertions(+), 20 deletions(-) rename src/Symfony/Component/Config/Resource/{ResourceValidator.php => ResourceInterfaceValidator.php} (82%) create mode 100644 src/Symfony/Component/Config/Tests/Resource/ResourceInterfaceValidatorTest.php diff --git a/src/Symfony/Component/Config/ConfigCache.php b/src/Symfony/Component/Config/ConfigCache.php index 9c16e5e4d85e1..0831a9f0a0053 100644 --- a/src/Symfony/Component/Config/ConfigCache.php +++ b/src/Symfony/Component/Config/ConfigCache.php @@ -11,8 +11,7 @@ namespace Symfony\Component\Config; -use Symfony\Component\Config\Resource\ResourceInterface; -use Symfony\Component\Config\Resource\ResourceValidator; +use Symfony\Component\Config\Resource\ResourceInterfaceValidator; use Symfony\Component\Filesystem\Exception\IOException; use Symfony\Component\Filesystem\Filesystem; @@ -69,11 +68,17 @@ public function getPath() * This method always returns true when debug is off and the * cache file exists. * - * @param MetadataValidatorInterface[] $validators List of validators the metadata is checked against. + * @param MetadataValidatorInterface[] $validators List of validators the metadata is checked against. The first validator that supports a resource is considered authoritative. + * * @return bool true if the cache is fresh, false otherwise */ public function isFresh(array $validators = null) { + if (null === $validators) { + @trigger_error('ConfigCache::isFresh requires the $validators parameter as of version 2.8.', E_USER_DEPRECATED); + $validators = array(new ResourceInterfaceValidator()); + } + if (!is_file($this->file)) { return false; } @@ -90,18 +95,18 @@ public function isFresh(array $validators = null) $time = filemtime($this->file); $meta = unserialize(file_get_contents($metadata)); - if (null === $validators) { - $validators = array(new ResourceValidator()); - } - foreach ($validators as $validator) { - foreach ($meta as $resource) { + foreach ($meta as $resource) { + foreach ($validators as $validator) { if (!$validator->supports($resource)) { - continue; + continue; // next validator } - if (!$validator->isFresh($resource, $time)) { - return false; + if ($validator->isFresh($resource, $time)) { + continue; // no need to further check this resource + } else { + return false; // cache is stale } } + // no suitable validator found, ignore this resource } return true; @@ -111,7 +116,7 @@ public function isFresh(array $validators = null) * Writes cache. * * @param string $content The content to write in the cache - * @param ResourceInterface[] $metadata An array of ResourceInterface instances + * @param array $metadata An array of metadata * * @throws \RuntimeException When cache file can't be written */ diff --git a/src/Symfony/Component/Config/Resource/ResourceValidator.php b/src/Symfony/Component/Config/Resource/ResourceInterfaceValidator.php similarity index 82% rename from src/Symfony/Component/Config/Resource/ResourceValidator.php rename to src/Symfony/Component/Config/Resource/ResourceInterfaceValidator.php index 170db9bb150a2..50496f422179c 100644 --- a/src/Symfony/Component/Config/Resource/ResourceValidator.php +++ b/src/Symfony/Component/Config/Resource/ResourceInterfaceValidator.php @@ -14,11 +14,11 @@ use Symfony\Component\Config\MetadataValidatorInterface; /** - * Validator for Resources. + * Validator for metadata implementing the ResourceInterface. * * @author Benjamin Klotz */ -class ResourceValidator implements MetadataValidatorInterface +class ResourceInterfaceValidator implements MetadataValidatorInterface { public function supports($metadata) { diff --git a/src/Symfony/Component/Config/Tests/ConfigCacheTest.php b/src/Symfony/Component/Config/Tests/ConfigCacheTest.php index f3f2a446a2bf6..f6c2065607707 100644 --- a/src/Symfony/Component/Config/Tests/ConfigCacheTest.php +++ b/src/Symfony/Component/Config/Tests/ConfigCacheTest.php @@ -13,6 +13,7 @@ use Symfony\Component\Config\ConfigCache; use Symfony\Component\Config\Resource\FileResource; +use Symfony\Component\Config\Resource\ResourceInterfaceValidator; class ConfigCacheTest extends \PHPUnit_Framework_TestCase { @@ -56,7 +57,7 @@ public function testCacheIsNotFreshIfFileDoesNotExist() $cache = new ConfigCache($this->cacheFile, false); - $this->assertFalse($cache->isFresh()); + $this->assertFalse($this->callIsFreshWithResourceValidator($cache)); } public function testCacheIsAlwaysFreshIfFileExistsWithDebugDisabled() @@ -65,7 +66,7 @@ public function testCacheIsAlwaysFreshIfFileExistsWithDebugDisabled() $cache = new ConfigCache($this->cacheFile, false); - $this->assertTrue($cache->isFresh()); + $this->assertTrue($this->callIsFreshWithResourceValidator($cache)); } public function testCacheIsNotFreshWithoutMetaFile() @@ -74,14 +75,14 @@ public function testCacheIsNotFreshWithoutMetaFile() $cache = new ConfigCache($this->cacheFile, true); - $this->assertFalse($cache->isFresh()); + $this->assertFalse($this->callIsFreshWithResourceValidator($cache)); } public function testCacheIsFreshIfResourceIsFresh() { $cache = new ConfigCache($this->cacheFile, true); - $this->assertTrue($cache->isFresh()); + $this->assertTrue($this->callIsFreshWithResourceValidator($cache)); } public function testCacheIsNotFreshIfOneOfTheResourcesIsNotFresh() @@ -90,7 +91,7 @@ public function testCacheIsNotFreshIfOneOfTheResourcesIsNotFresh() $cache = new ConfigCache($this->cacheFile, true); - $this->assertFalse($cache->isFresh()); + $this->assertFalse($this->callIsFreshWithResourceValidator($cache)); } public function testWriteDumpsFile() @@ -121,6 +122,11 @@ public function testWriteDumpsMetaFileWithDebugEnabled() $this->assertSame(serialize($metadata), file_get_contents($this->metaFile)); } + private function callIsFreshWithResourceValidator(ConfigCache $cache) + { + return $cache->isFresh(array(new ResourceInterfaceValidator())); + } + private function makeCacheFresh() { touch($this->resourceFile, filemtime($this->cacheFile) - 3600); diff --git a/src/Symfony/Component/Config/Tests/Resource/ResourceInterfaceValidatorTest.php b/src/Symfony/Component/Config/Tests/Resource/ResourceInterfaceValidatorTest.php new file mode 100644 index 0000000000000..46bcc035d4bc0 --- /dev/null +++ b/src/Symfony/Component/Config/Tests/Resource/ResourceInterfaceValidatorTest.php @@ -0,0 +1,56 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Config\Tests\Resource; + +use Symfony\Component\Config\Resource\ResourceInterfaceValidator; + +class ResourceInterfaceValidatorTest extends \PHPUnit_Framework_TestCase +{ + protected $validator; + protected $metadataMock; + protected $timestamp; + + public function setUp() + { + $this->timestamp = 10; + $this->validator = new ResourceInterfaceValidator(); + $this->metadataMock = $this->getMock('\Symfony\Component\Config\Resource\ResourceInterface'); + } + + public function testSupportsResourceInterface() + { + $this->assertTrue($this->validator->supports($this->metadataMock), '->supports($metadata) returns true if $metadata implements ResourceInterface'); + $this->assertFalse($this->validator->supports(new \StdClass), '->supports($metadata) returns false if $metadata does not implement ResourceInterface'); + } + + /** + * @dataProvider testIsFreshDataProvider + */ + public function testIsFresh($result) + { + $this->metadataMock + ->expects($this->once()) + ->method('isFresh') + ->with($this->equalTo($this->timestamp)) + ->will($this->returnValue($result)); + $this->assertEquals($result, $this->validator->isFresh($this->metadataMock, $this->timestamp), '->isFresh($metadata) returns the same as $metadata->isFresh().'); + } + + public function testIsFreshDataProvider() + { + return array( + array(true), + array(false), + ); + } + +} diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php index fdec21632db31..01023db4d71e8 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -547,7 +547,7 @@ protected function initializeContainer() $class = $this->getContainerClass(); $cache = new ConfigCache($this->getCacheDir().'/'.$class.'.php', $this->debug); $fresh = true; - if (!$cache->isFresh()) { + if (!$cache->isFresh(array(new ResourceInterfaceValidator()))) { $container = $this->buildContainer(); $container->compile(); $this->dumpContainer($cache, $container, $class, $this->getContainerBaseClass()); From 0342b73711a3d1cd52ec80bf0422991c4ed6fe5d Mon Sep 17 00:00:00 2001 From: bnw Date: Fri, 4 Sep 2015 13:37:53 +0200 Subject: [PATCH 05/36] Added missing import --- src/Symfony/Component/HttpKernel/Kernel.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php index 01023db4d71e8..103ef034d1bb0 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -13,6 +13,7 @@ use Symfony\Bridge\ProxyManager\LazyProxy\Instantiator\RuntimeInstantiator; use Symfony\Bridge\ProxyManager\LazyProxy\PhpDumper\ProxyDumper; +use Symfony\Component\Config\Resource\ResourceInterfaceValidator; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Dumper\PhpDumper; From 7aee8910a1306ab3590f8df11d79584117f5b4c2 Mon Sep 17 00:00:00 2001 From: bnw Date: Fri, 4 Sep 2015 13:39:16 +0200 Subject: [PATCH 06/36] Correcting classname after renaming --- .../Bundle/FrameworkBundle/Resources/config/services.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/services.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/services.xml index a102c3757d88d..d257778e38404 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/services.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/services.xml @@ -14,7 +14,7 @@ Symfony\Component\HttpKernel\UriSigner Symfony\Component\HttpFoundation\RequestStack Symfony\Component\Config\ConfigCacheFactory - Symfony\Component\Config\Resource\ResourceValidator + Symfony\Component\Config\Resource\ResourceInterfaceValidator From df526c0474391e5ec546c22f3ab29e0a4f2f09d5 Mon Sep 17 00:00:00 2001 From: bnw Date: Fri, 4 Sep 2015 13:39:46 +0200 Subject: [PATCH 07/36] Added ConfigCachePass to framework --- src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php b/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php index 499f39c6c95c0..a617ac42894bc 100644 --- a/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php +++ b/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php @@ -28,6 +28,7 @@ use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\TranslationExtractorPass; use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\TranslationDumperPass; use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\SerializerPass; +use Symfony\Component\Config\DependencyInjection\ConfigCachePass; use Symfony\Component\Debug\ErrorHandler; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Compiler\PassConfig; @@ -71,6 +72,7 @@ public function build(ContainerBuilder $container) $container->addCompilerPass(new RoutingResolverPass()); $container->addCompilerPass(new ProfilerPass()); + $container->addCompilerPass(new ConfigCachePass()); // must be registered before removing private services as some might be listeners/subscribers // but as late as possible to get resolved parameters $container->addCompilerPass(new RegisterListenersPass(), PassConfig::TYPE_BEFORE_REMOVING); From 2555d5a1ee723aeeae4062133f7cd26902733d5c Mon Sep 17 00:00:00 2001 From: bnw Date: Fri, 4 Sep 2015 13:58:12 +0200 Subject: [PATCH 08/36] Fixed UnitTests --- .../Tests/DependencyInjection/FrameworkExtensionTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php index 6e220740a5107..ad0c427100ddf 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php @@ -250,7 +250,7 @@ public function testTranslator() ); $calls = $container->getDefinition('translator.default')->getMethodCalls(); - $this->assertEquals(array('fr'), $calls[0][1][0]); + $this->assertEquals(array('fr'), $calls[1][1][0]); } public function testTranslatorMultipleFallbacks() @@ -258,7 +258,7 @@ public function testTranslatorMultipleFallbacks() $container = $this->createContainerFromFile('translator_fallbacks'); $calls = $container->getDefinition('translator.default')->getMethodCalls(); - $this->assertEquals(array('en', 'fr'), $calls[0][1][0]); + $this->assertEquals(array('en', 'fr'), $calls[1][1][0]); } /** From 4145dc0264abbc7dd3a44b69e2f3a56d9d750e70 Mon Sep 17 00:00:00 2001 From: bnw Date: Fri, 4 Sep 2015 14:02:30 +0200 Subject: [PATCH 09/36] Bugfix --- src/Symfony/Component/Config/ConfigCacheFactory.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Config/ConfigCacheFactory.php b/src/Symfony/Component/Config/ConfigCacheFactory.php index 2b787765176a6..8dbccc0f0f4fc 100644 --- a/src/Symfony/Component/Config/ConfigCacheFactory.php +++ b/src/Symfony/Component/Config/ConfigCacheFactory.php @@ -42,7 +42,7 @@ public function __construct($debug) */ public function addValidator(MetadataValidatorInterface $validator) { - $validator[] = $validator; + $this->validators[] = $validator; } /** From 2e49fb2d8c1338b42c24eff67da46115fbd23a23 Mon Sep 17 00:00:00 2001 From: bnw Date: Fri, 4 Sep 2015 15:03:56 +0200 Subject: [PATCH 10/36] Better name --- .../Bundle/FrameworkBundle/Resources/config/services.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/services.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/services.xml index d257778e38404..d2e8890226027 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/services.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/services.xml @@ -14,7 +14,7 @@ Symfony\Component\HttpKernel\UriSigner Symfony\Component\HttpFoundation\RequestStack Symfony\Component\Config\ConfigCacheFactory - Symfony\Component\Config\Resource\ResourceInterfaceValidator + Symfony\Component\Config\Resource\ResourceInterfaceValidator @@ -70,7 +70,7 @@ %kernel.debug% - + From d0f1e2d255c87e39f5b8ca2c9121a6a4b6bbc711 Mon Sep 17 00:00:00 2001 From: Matthias Pigulla Date: Sat, 5 Sep 2015 10:35:40 +0200 Subject: [PATCH 11/36] Fix test --- .../Tests/Command/CacheClearCommand/CacheClearCommandTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/CacheClearCommand/CacheClearCommandTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/CacheClearCommand/CacheClearCommandTest.php index 745e015d57d68..79167f6680702 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/CacheClearCommand/CacheClearCommandTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/CacheClearCommand/CacheClearCommandTest.php @@ -50,7 +50,7 @@ public function testCacheIsFreshAfterCacheClearedWithWarmup() foreach ($metaFiles as $file) { $configCache = new ConfigCache(substr($file, 0, -5), true); $this->assertTrue( - $configCache->isFresh(), + $configCache->isFresh(array(new ResourceInterfaceValidator()))), sprintf( 'Meta file "%s" is not fresh', (string) $file From 3f9424fc9b3ef9b23164597107ae25d8df2d2732 Mon Sep 17 00:00:00 2001 From: Matthias Pigulla Date: Sat, 5 Sep 2015 10:41:26 +0200 Subject: [PATCH 12/36] Add docblock --- .../Config/MetadataValidatorInterface.php | 23 ++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/Config/MetadataValidatorInterface.php b/src/Symfony/Component/Config/MetadataValidatorInterface.php index c7562629d9bc6..e026262799522 100644 --- a/src/Symfony/Component/Config/MetadataValidatorInterface.php +++ b/src/Symfony/Component/Config/MetadataValidatorInterface.php @@ -12,15 +12,36 @@ namespace Symfony\Component\Config; /** - * Base interface to test arbitrary metadata for freshness. + * Interface for MetadataValidators. + * + * When a ConfigCache instance is checked for freshness, all its associated + * metadata resources are passed to MetadataValidators. The MetadataValidators + * can then inspect the resources and decide whether the cache can be considered + * fresh or not. * * @author Benjamin Klotz */ interface MetadataValidatorInterface { + /** + * Queries the MetadataValidator whether it can validate a given + * resource or not. + * + * @param $metadata The resource to be checked for freshness + * + * @return bool True if the MetadataValidator can handle this resource type, false if not + */ public function supports($metadata); + /** + * Validates the resource. + * + * @param $metadata The resource to be validated. + * @param $timestamp The timestamp at which the cache associated with this resource was created. + * + * @return bool True if the resource has not changed since the given timestamp, false otherwise. + */ public function isFresh($metadata, $timestamp); } From b8bb60a7cdba5757c75e516b28244875acacefa3 Mon Sep 17 00:00:00 2001 From: Matthias Pigulla Date: Sat, 5 Sep 2015 22:05:39 +0200 Subject: [PATCH 13/36] Fix tests while keeping ConfigCacheFactory unchanged (from a client perspective) --- .../Resources/config/services.xml | 2 +- .../CacheClearCommandTest.php | 2 +- .../Component/Config/ConfigCacheFactory.php | 22 ++----- .../Config/ValidatorConfigCacheFactory.php | 64 +++++++++++++++++++ 4 files changed, 72 insertions(+), 18 deletions(-) create mode 100644 src/Symfony/Component/Config/ValidatorConfigCacheFactory.php diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/services.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/services.xml index d2e8890226027..58acc94eb40e5 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/services.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/services.xml @@ -13,7 +13,7 @@ Symfony\Component\HttpKernel\Config\FileLocator Symfony\Component\HttpKernel\UriSigner Symfony\Component\HttpFoundation\RequestStack - Symfony\Component\Config\ConfigCacheFactory + Symfony\Component\Config\ValidatorConfigCacheFactory Symfony\Component\Config\Resource\ResourceInterfaceValidator diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/CacheClearCommand/CacheClearCommandTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/CacheClearCommand/CacheClearCommandTest.php index 79167f6680702..eb74d7fdd0850 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/CacheClearCommand/CacheClearCommandTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/CacheClearCommand/CacheClearCommandTest.php @@ -50,7 +50,7 @@ public function testCacheIsFreshAfterCacheClearedWithWarmup() foreach ($metaFiles as $file) { $configCache = new ConfigCache(substr($file, 0, -5), true); $this->assertTrue( - $configCache->isFresh(array(new ResourceInterfaceValidator()))), + $configCache->isFresh(array(new ResourceInterfaceValidator())), sprintf( 'Meta file "%s" is not fresh', (string) $file diff --git a/src/Symfony/Component/Config/ConfigCacheFactory.php b/src/Symfony/Component/Config/ConfigCacheFactory.php index 8dbccc0f0f4fc..29fcf1fc4ab08 100644 --- a/src/Symfony/Component/Config/ConfigCacheFactory.php +++ b/src/Symfony/Component/Config/ConfigCacheFactory.php @@ -11,9 +11,12 @@ namespace Symfony\Component\Config; +use Symfony\Component\Config\Resource\ResourceInterfaceValidator; + /** - * Basic implementation for ConfigCacheFactoryInterface - * that will simply create an instance of ConfigCache. + * Basic implementation of ConfigCacheFactoryInterface. + * Creates a ConfigCache instance that will be validated with the + * ResourceInterfaceValidator only. * * @author Matthias Pigulla */ @@ -24,11 +27,6 @@ class ConfigCacheFactory implements ConfigCacheFactoryInterface */ private $debug; - /** - * @var MetadataValidatorInterface[] List of validators used by the ConfigCache - */ - private $validators = array(); - /** * @param bool $debug The debug flag to pass to ConfigCache */ @@ -37,14 +35,6 @@ public function __construct($debug) $this->debug = $debug; } - /** - * @param MetadataValidatorInterface $validator - */ - public function addValidator(MetadataValidatorInterface $validator) - { - $this->validators[] = $validator; - } - /** * {@inheritdoc} */ @@ -55,7 +45,7 @@ public function cache($file, $callback) } $cache = new ConfigCache($file, $this->debug); - if (!$cache->isFresh($this->validators)) { + if (!$cache->isFresh(array(new ResourceInterfaceValidator()))) { call_user_func($callback, $cache); } diff --git a/src/Symfony/Component/Config/ValidatorConfigCacheFactory.php b/src/Symfony/Component/Config/ValidatorConfigCacheFactory.php new file mode 100644 index 0000000000000..cc614a151cf4f --- /dev/null +++ b/src/Symfony/Component/Config/ValidatorConfigCacheFactory.php @@ -0,0 +1,64 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Config; + +/** + * A ConfigCacheFactory implementation that validates the + * cache with an arbitrary set of metadata validators. + * + * @author Matthias Pigulla + */ +class ValidatorConfigCacheFactory implements ConfigCacheFactoryInterface +{ + /** + * @var bool + */ + private $debug; + + /** + * @var MetadataValidatorInterface[] + */ + private $validators = array(); + + /** + * @param bool $debug The debug flag to pass to ConfigCache + */ + public function __construct($debug) + { + $this->debug = $debug; + } + + /** + * @param MetadataValidatorInterface $validator + */ + public function addValidator(MetadataValidatorInterface $validator) + { + $this->validators[] = $validator; + } + + /** + * {@inheritdoc} + */ + public function cache($file, $callback) + { + if (!is_callable($callback)) { + throw new \InvalidArgumentException(sprintf('Invalid type for callback argument. Expected callable, but got "%s".', gettype($callback))); + } + + $cache = new ConfigCache($file, $this->debug); + if (!$cache->isFresh($this->validators)) { + call_user_func($callback, $cache); + } + + return $cache; + } +} From 2fac8f305c4e65166c87648ce22b80fce332bc93 Mon Sep 17 00:00:00 2001 From: Matthias Pigulla Date: Sat, 5 Sep 2015 22:07:34 +0200 Subject: [PATCH 14/36] Hello Fabbot --- src/Symfony/Component/Config/ConfigCache.php | 4 ++-- src/Symfony/Component/Config/MetadataValidatorInterface.php | 1 - .../Config/Tests/Resource/ResourceInterfaceValidatorTest.php | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Component/Config/ConfigCache.php b/src/Symfony/Component/Config/ConfigCache.php index 0831a9f0a0053..48a440d7b0e51 100644 --- a/src/Symfony/Component/Config/ConfigCache.php +++ b/src/Symfony/Component/Config/ConfigCache.php @@ -115,8 +115,8 @@ public function isFresh(array $validators = null) /** * Writes cache. * - * @param string $content The content to write in the cache - * @param array $metadata An array of metadata + * @param string $content The content to write in the cache + * @param array $metadata An array of metadata * * @throws \RuntimeException When cache file can't be written */ diff --git a/src/Symfony/Component/Config/MetadataValidatorInterface.php b/src/Symfony/Component/Config/MetadataValidatorInterface.php index e026262799522..179ccda770f73 100644 --- a/src/Symfony/Component/Config/MetadataValidatorInterface.php +++ b/src/Symfony/Component/Config/MetadataValidatorInterface.php @@ -23,7 +23,6 @@ */ interface MetadataValidatorInterface { - /** * Queries the MetadataValidator whether it can validate a given * resource or not. diff --git a/src/Symfony/Component/Config/Tests/Resource/ResourceInterfaceValidatorTest.php b/src/Symfony/Component/Config/Tests/Resource/ResourceInterfaceValidatorTest.php index 46bcc035d4bc0..97596912d29ed 100644 --- a/src/Symfony/Component/Config/Tests/Resource/ResourceInterfaceValidatorTest.php +++ b/src/Symfony/Component/Config/Tests/Resource/ResourceInterfaceValidatorTest.php @@ -29,7 +29,7 @@ public function setUp() public function testSupportsResourceInterface() { $this->assertTrue($this->validator->supports($this->metadataMock), '->supports($metadata) returns true if $metadata implements ResourceInterface'); - $this->assertFalse($this->validator->supports(new \StdClass), '->supports($metadata) returns false if $metadata does not implement ResourceInterface'); + $this->assertFalse($this->validator->supports(new \StdClass()), '->supports($metadata) returns false if $metadata does not implement ResourceInterface'); } /** From 1b62130034ec4a94353fd563faf6c2e91fb24da6 Mon Sep 17 00:00:00 2001 From: Matthias Pigulla Date: Sat, 5 Sep 2015 22:36:37 +0200 Subject: [PATCH 15/36] Forgot import statement --- .../Tests/Command/CacheClearCommand/CacheClearCommandTest.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/CacheClearCommand/CacheClearCommandTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/CacheClearCommand/CacheClearCommandTest.php index eb74d7fdd0850..34bc852a5ed13 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/CacheClearCommand/CacheClearCommandTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/CacheClearCommand/CacheClearCommandTest.php @@ -7,6 +7,7 @@ use Symfony\Bundle\FrameworkBundle\Tests\TestCase; use Symfony\Component\Config\ConfigCache; use Symfony\Component\Config\Resource\ResourceInterface; +use Symfony\Component\Config\Resource\ResourceInterfaceValidator; use Symfony\Component\Console\Input\ArrayInput; use Symfony\Component\Console\Output\NullOutput; use Symfony\Component\Filesystem\Filesystem; From b16d9de52509a6cbffe083f2079fe98b91a9ba5a Mon Sep 17 00:00:00 2001 From: Matthias Pigulla Date: Sun, 6 Sep 2015 09:18:47 +0200 Subject: [PATCH 16/36] The new ConfigCachePass is required --- src/Symfony/Bundle/FrameworkBundle/composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/composer.json b/src/Symfony/Bundle/FrameworkBundle/composer.json index 843a4cce7be4a..d3ae7d70b8854 100644 --- a/src/Symfony/Bundle/FrameworkBundle/composer.json +++ b/src/Symfony/Bundle/FrameworkBundle/composer.json @@ -19,7 +19,7 @@ "php": ">=5.3.9", "symfony/asset": "~2.7|~3.0.0", "symfony/dependency-injection": "~2.8", - "symfony/config": "~2.4", + "symfony/config": "~2.8", "symfony/event-dispatcher": "~2.8|~3.0.0", "symfony/http-foundation": "~2.4.9|~2.5,>=2.5.4|~3.0.0", "symfony/http-kernel": "~2.7", From 97a2cd050f108544c58ac6f9617f090309ae6c20 Mon Sep 17 00:00:00 2001 From: Matthias Pigulla Date: Sun, 6 Sep 2015 10:57:32 +0200 Subject: [PATCH 17/36] Bump deps --- src/Symfony/Component/HttpKernel/composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/HttpKernel/composer.json b/src/Symfony/Component/HttpKernel/composer.json index d702fac80863f..27fd41f6a0c8f 100644 --- a/src/Symfony/Component/HttpKernel/composer.json +++ b/src/Symfony/Component/HttpKernel/composer.json @@ -26,7 +26,7 @@ "symfony/phpunit-bridge": "~2.7|~3.0.0", "symfony/browser-kit": "~2.3|~3.0.0", "symfony/class-loader": "~2.1|~3.0.0", - "symfony/config": "~2.7", + "symfony/config": "~2.8", "symfony/console": "~2.3|~3.0.0", "symfony/css-selector": "~2.0,>=2.0.5|~3.0.0", "symfony/dependency-injection": "~2.8|~3.0.0", From aae0a78e8776c2cbd60bc534549a390010640a2d Mon Sep 17 00:00:00 2001 From: Matthias Pigulla Date: Sun, 6 Sep 2015 23:01:51 +0200 Subject: [PATCH 18/36] Avoid changing the interface --- .../CacheClearCommandTest.php | 18 ++++----- src/Symfony/Component/Config/ConfigCache.php | 39 ++++++++++++------- .../Component/Config/ConfigCacheFactory.php | 2 +- .../Component/Config/ConfigCacheInterface.php | 4 +- .../Config/MetadataValidatorInterface.php | 6 +-- .../Config/Tests/ConfigCacheTest.php | 14 +++---- .../Config/ValidatorConfigCacheFactory.php | 2 +- src/Symfony/Component/HttpKernel/Kernel.php | 7 +++- 8 files changed, 53 insertions(+), 39 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/CacheClearCommand/CacheClearCommandTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/CacheClearCommand/CacheClearCommandTest.php index 34bc852a5ed13..662a915d28777 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/CacheClearCommand/CacheClearCommandTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/CacheClearCommand/CacheClearCommandTest.php @@ -5,9 +5,9 @@ use Symfony\Bundle\FrameworkBundle\Console\Application; use Symfony\Bundle\FrameworkBundle\Tests\Command\CacheClearCommand\Fixture\TestAppKernel; use Symfony\Bundle\FrameworkBundle\Tests\TestCase; -use Symfony\Component\Config\ConfigCache; +use Symfony\Component\Config\ConfigCacheFactory; +use Symfony\Component\Config\ConfigCacheInterface; use Symfony\Component\Config\Resource\ResourceInterface; -use Symfony\Component\Config\Resource\ResourceInterfaceValidator; use Symfony\Component\Console\Input\ArrayInput; use Symfony\Component\Console\Output\NullOutput; use Symfony\Component\Filesystem\Filesystem; @@ -48,15 +48,13 @@ public function testCacheIsFreshAfterCacheClearedWithWarmup() $metaFiles = $finder->files()->in($this->kernel->getCacheDir())->name('*.php.meta'); // simply check that cache is warmed up $this->assertGreaterThanOrEqual(1, count($metaFiles)); + $configCacheFactory = new ConfigCacheFactory(true); + $that = $this; + foreach ($metaFiles as $file) { - $configCache = new ConfigCache(substr($file, 0, -5), true); - $this->assertTrue( - $configCache->isFresh(array(new ResourceInterfaceValidator())), - sprintf( - 'Meta file "%s" is not fresh', - (string) $file - ) - ); + $configCacheFactory->cache(substr($file, 0, -5), function () use ($that, $file) { + $that->fail(sprintf('Meta file "%s" is not fresh', (string) $file)); + }); } // check that app kernel file present in meta file of container's cache diff --git a/src/Symfony/Component/Config/ConfigCache.php b/src/Symfony/Component/Config/ConfigCache.php index 48a440d7b0e51..073f1f6efc288 100644 --- a/src/Symfony/Component/Config/ConfigCache.php +++ b/src/Symfony/Component/Config/ConfigCache.php @@ -16,12 +16,13 @@ use Symfony\Component\Filesystem\Filesystem; /** - * ConfigCache manages PHP cache files. + * ConfigCache caches arbitrary content in files on disk. * - * When debug is enabled, it knows when to flush the cache - * thanks to an array of ResourceInterface instances. + * Metadata can be stored alongside the cache and can later be + * used by MetadataValidators to check if the cache is still fresh. * * @author Fabien Potencier + * @author Matthias Pigulla */ class ConfigCache implements ConfigCacheInterface { @@ -68,25 +69,37 @@ public function getPath() * This method always returns true when debug is off and the * cache file exists. * - * @param MetadataValidatorInterface[] $validators List of validators the metadata is checked against. The first validator that supports a resource is considered authoritative. - * * @return bool true if the cache is fresh, false otherwise + * + * @deprecated since version 2.8, to be removed in 3.0. */ - public function isFresh(array $validators = null) + public function isFresh() { - if (null === $validators) { - @trigger_error('ConfigCache::isFresh requires the $validators parameter as of version 2.8.', E_USER_DEPRECATED); - $validators = array(new ResourceInterfaceValidator()); + @trigger_error(__NAMESPACE__.'\ConfigCache::isFresh() is deprecated since version 2.8 and will be removed in 3.0. Use the isValid() method instead and pass the appropriate MetadataValidators, or even better use a \Symfony\Component\Config\ConfigCacheFactoryInterface implementation to create and validate the cache.', E_USER_DEPRECATED); + + if (!$this->debug && is_file($this->file)) { + return true; } + return $this->isValid(array(new ResourceInterfaceValidator())); + } + + /** + * Use MetadataValidators to check if the cache is still valid. + * + * The first MetadataValidator that supports a given resource is considered authoritative. + * Resources with no matching MetadataValidators will silently be ignored. + * + * @param MetadataValidatorInterface[] $validators List of validators the metadata is checked against. The first validator that supports a resource is considered authoritative. + * + * @return bool True if all supported resources and valid, false otherwise + */ + public function isValid(array $validators = null) + { if (!is_file($this->file)) { return false; } - if (!$this->debug) { - return true; - } - $metadata = $this->getMetaFile(); if (!is_file($metadata)) { return false; diff --git a/src/Symfony/Component/Config/ConfigCacheFactory.php b/src/Symfony/Component/Config/ConfigCacheFactory.php index 29fcf1fc4ab08..748459a59b55c 100644 --- a/src/Symfony/Component/Config/ConfigCacheFactory.php +++ b/src/Symfony/Component/Config/ConfigCacheFactory.php @@ -45,7 +45,7 @@ public function cache($file, $callback) } $cache = new ConfigCache($file, $this->debug); - if (!$cache->isFresh(array(new ResourceInterfaceValidator()))) { + if (!$cache->isValid(array(new ResourceInterfaceValidator()))) { call_user_func($callback, $cache); } diff --git a/src/Symfony/Component/Config/ConfigCacheInterface.php b/src/Symfony/Component/Config/ConfigCacheInterface.php index fc449013a320c..e367ad187ee6c 100644 --- a/src/Symfony/Component/Config/ConfigCacheInterface.php +++ b/src/Symfony/Component/Config/ConfigCacheInterface.php @@ -32,11 +32,9 @@ public function getPath(); * * This check should take the metadata passed to the write() method into consideration. * - * @param MetadataValidatorInterface[] $validators List of validators the metadata is checked against. - * * @return bool Whether the cache is still fresh. */ - public function isFresh(array $validators = null); + public function isFresh(); /** * Writes the given content into the cache file. Metadata will be stored diff --git a/src/Symfony/Component/Config/MetadataValidatorInterface.php b/src/Symfony/Component/Config/MetadataValidatorInterface.php index 179ccda770f73..d3620f65ddee9 100644 --- a/src/Symfony/Component/Config/MetadataValidatorInterface.php +++ b/src/Symfony/Component/Config/MetadataValidatorInterface.php @@ -27,7 +27,7 @@ interface MetadataValidatorInterface * Queries the MetadataValidator whether it can validate a given * resource or not. * - * @param $metadata The resource to be checked for freshness + * @param object $metadata The resource to be checked for freshness * * @return bool True if the MetadataValidator can handle this resource type, false if not */ @@ -36,8 +36,8 @@ public function supports($metadata); /** * Validates the resource. * - * @param $metadata The resource to be validated. - * @param $timestamp The timestamp at which the cache associated with this resource was created. + * @param object $metadata The resource to be validated. + * @param int $timestamp The timestamp at which the cache associated with this resource was created. * * @return bool True if the resource has not changed since the given timestamp, false otherwise. */ diff --git a/src/Symfony/Component/Config/Tests/ConfigCacheTest.php b/src/Symfony/Component/Config/Tests/ConfigCacheTest.php index f6c2065607707..202d7f91fc51f 100644 --- a/src/Symfony/Component/Config/Tests/ConfigCacheTest.php +++ b/src/Symfony/Component/Config/Tests/ConfigCacheTest.php @@ -57,7 +57,7 @@ public function testCacheIsNotFreshIfFileDoesNotExist() $cache = new ConfigCache($this->cacheFile, false); - $this->assertFalse($this->callIsFreshWithResourceValidator($cache)); + $this->assertFalse($this->isCacheValid($cache)); } public function testCacheIsAlwaysFreshIfFileExistsWithDebugDisabled() @@ -66,7 +66,7 @@ public function testCacheIsAlwaysFreshIfFileExistsWithDebugDisabled() $cache = new ConfigCache($this->cacheFile, false); - $this->assertTrue($this->callIsFreshWithResourceValidator($cache)); + $this->assertTrue($this->isCacheValid($cache)); } public function testCacheIsNotFreshWithoutMetaFile() @@ -75,14 +75,14 @@ public function testCacheIsNotFreshWithoutMetaFile() $cache = new ConfigCache($this->cacheFile, true); - $this->assertFalse($this->callIsFreshWithResourceValidator($cache)); + $this->assertFalse($this->isCacheValid($cache)); } public function testCacheIsFreshIfResourceIsFresh() { $cache = new ConfigCache($this->cacheFile, true); - $this->assertTrue($this->callIsFreshWithResourceValidator($cache)); + $this->assertTrue($this->isCacheValid($cache)); } public function testCacheIsNotFreshIfOneOfTheResourcesIsNotFresh() @@ -91,7 +91,7 @@ public function testCacheIsNotFreshIfOneOfTheResourcesIsNotFresh() $cache = new ConfigCache($this->cacheFile, true); - $this->assertFalse($this->callIsFreshWithResourceValidator($cache)); + $this->assertFalse($this->isCacheValid($cache)); } public function testWriteDumpsFile() @@ -122,9 +122,9 @@ public function testWriteDumpsMetaFileWithDebugEnabled() $this->assertSame(serialize($metadata), file_get_contents($this->metaFile)); } - private function callIsFreshWithResourceValidator(ConfigCache $cache) + private function isCacheValid(ConfigCache $cache) { - return $cache->isFresh(array(new ResourceInterfaceValidator())); + return $cache->isValid(array(new ResourceInterfaceValidator())); } private function makeCacheFresh() diff --git a/src/Symfony/Component/Config/ValidatorConfigCacheFactory.php b/src/Symfony/Component/Config/ValidatorConfigCacheFactory.php index cc614a151cf4f..725d04135faeb 100644 --- a/src/Symfony/Component/Config/ValidatorConfigCacheFactory.php +++ b/src/Symfony/Component/Config/ValidatorConfigCacheFactory.php @@ -55,7 +55,7 @@ public function cache($file, $callback) } $cache = new ConfigCache($file, $this->debug); - if (!$cache->isFresh($this->validators)) { + if (!$cache->isValid($this->validators)) { call_user_func($callback, $cache); } diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php index 103ef034d1bb0..f482e45947061 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -548,7 +548,12 @@ protected function initializeContainer() $class = $this->getContainerClass(); $cache = new ConfigCache($this->getCacheDir().'/'.$class.'.php', $this->debug); $fresh = true; - if (!$cache->isFresh(array(new ResourceInterfaceValidator()))) { + + /* We probably should use the ConfigCacheFactory here, but that would require + * some wrapper methods because we cannot call protected methods from closures + * prior to PHP 5.4. Let's do this change later when we can require PHP 5.4. + */ + if (!$cache->isValid(array(new ResourceInterfaceValidator()))) { $container = $this->buildContainer(); $container->compile(); $this->dumpContainer($cache, $container, $class, $this->getContainerBaseClass()); From 024aa8c719134b7d84b78fbc545237b3baeeb4be Mon Sep 17 00:00:00 2001 From: Matthias Pigulla Date: Mon, 7 Sep 2015 09:39:02 +0200 Subject: [PATCH 19/36] Also validate this method in the interface --- src/Symfony/Component/Config/ConfigCacheInterface.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Symfony/Component/Config/ConfigCacheInterface.php b/src/Symfony/Component/Config/ConfigCacheInterface.php index e367ad187ee6c..8b3e840b21a03 100644 --- a/src/Symfony/Component/Config/ConfigCacheInterface.php +++ b/src/Symfony/Component/Config/ConfigCacheInterface.php @@ -33,6 +33,10 @@ public function getPath(); * This check should take the metadata passed to the write() method into consideration. * * @return bool Whether the cache is still fresh. + * + * @deprecated since 2.8, to be removed in 3.0. + * Use Symfony\Component\Config\ConfigCacheFactory instead, it will take care of + * validating the cache. */ public function isFresh(); From d617943a6b9c606b9e38945a622bb00b873193e0 Mon Sep 17 00:00:00 2001 From: Matthias Pigulla Date: Mon, 7 Sep 2015 09:47:45 +0200 Subject: [PATCH 20/36] Rename ResourceInterfaceValidator to ResourceValidator as suggested on GH --- .../Bundle/FrameworkBundle/Resources/config/services.xml | 4 ++-- src/Symfony/Component/Config/ConfigCache.php | 4 ++-- src/Symfony/Component/Config/ConfigCacheFactory.php | 6 +++--- ...ResourceInterfaceValidator.php => ResourceValidator.php} | 2 +- src/Symfony/Component/Config/Tests/ConfigCacheTest.php | 4 ++-- ...InterfaceValidatorTest.php => ResourceValidatorTest.php} | 6 +++--- src/Symfony/Component/HttpKernel/Kernel.php | 4 ++-- 7 files changed, 15 insertions(+), 15 deletions(-) rename src/Symfony/Component/Config/Resource/{ResourceInterfaceValidator.php => ResourceValidator.php} (90%) rename src/Symfony/Component/Config/Tests/Resource/{ResourceInterfaceValidatorTest.php => ResourceValidatorTest.php} (88%) diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/services.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/services.xml index 58acc94eb40e5..e613f60cf8cab 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/services.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/services.xml @@ -14,7 +14,7 @@ Symfony\Component\HttpKernel\UriSigner Symfony\Component\HttpFoundation\RequestStack Symfony\Component\Config\ValidatorConfigCacheFactory - Symfony\Component\Config\Resource\ResourceInterfaceValidator + Symfony\Component\Config\Resource\ResourceValidator @@ -70,7 +70,7 @@ %kernel.debug% - + diff --git a/src/Symfony/Component/Config/ConfigCache.php b/src/Symfony/Component/Config/ConfigCache.php index 073f1f6efc288..d252f83397732 100644 --- a/src/Symfony/Component/Config/ConfigCache.php +++ b/src/Symfony/Component/Config/ConfigCache.php @@ -11,7 +11,7 @@ namespace Symfony\Component\Config; -use Symfony\Component\Config\Resource\ResourceInterfaceValidator; +use Symfony\Component\Config\Resource\ResourceValidator; use Symfony\Component\Filesystem\Exception\IOException; use Symfony\Component\Filesystem\Filesystem; @@ -81,7 +81,7 @@ public function isFresh() return true; } - return $this->isValid(array(new ResourceInterfaceValidator())); + return $this->isValid(array(new ResourceValidator())); } /** diff --git a/src/Symfony/Component/Config/ConfigCacheFactory.php b/src/Symfony/Component/Config/ConfigCacheFactory.php index 748459a59b55c..a6e41aee5875f 100644 --- a/src/Symfony/Component/Config/ConfigCacheFactory.php +++ b/src/Symfony/Component/Config/ConfigCacheFactory.php @@ -11,12 +11,12 @@ namespace Symfony\Component\Config; -use Symfony\Component\Config\Resource\ResourceInterfaceValidator; +use Symfony\Component\Config\Resource\ResourceValidator; /** * Basic implementation of ConfigCacheFactoryInterface. * Creates a ConfigCache instance that will be validated with the - * ResourceInterfaceValidator only. + * ResourceValidator only. * * @author Matthias Pigulla */ @@ -45,7 +45,7 @@ public function cache($file, $callback) } $cache = new ConfigCache($file, $this->debug); - if (!$cache->isValid(array(new ResourceInterfaceValidator()))) { + if (!$cache->isValid(array(new ResourceValidator()))) { call_user_func($callback, $cache); } diff --git a/src/Symfony/Component/Config/Resource/ResourceInterfaceValidator.php b/src/Symfony/Component/Config/Resource/ResourceValidator.php similarity index 90% rename from src/Symfony/Component/Config/Resource/ResourceInterfaceValidator.php rename to src/Symfony/Component/Config/Resource/ResourceValidator.php index 50496f422179c..62dc402e7c74a 100644 --- a/src/Symfony/Component/Config/Resource/ResourceInterfaceValidator.php +++ b/src/Symfony/Component/Config/Resource/ResourceValidator.php @@ -18,7 +18,7 @@ * * @author Benjamin Klotz */ -class ResourceInterfaceValidator implements MetadataValidatorInterface +class ResourceValidator implements MetadataValidatorInterface { public function supports($metadata) { diff --git a/src/Symfony/Component/Config/Tests/ConfigCacheTest.php b/src/Symfony/Component/Config/Tests/ConfigCacheTest.php index 202d7f91fc51f..c544e38d64b22 100644 --- a/src/Symfony/Component/Config/Tests/ConfigCacheTest.php +++ b/src/Symfony/Component/Config/Tests/ConfigCacheTest.php @@ -13,7 +13,7 @@ use Symfony\Component\Config\ConfigCache; use Symfony\Component\Config\Resource\FileResource; -use Symfony\Component\Config\Resource\ResourceInterfaceValidator; +use Symfony\Component\Config\Resource\ResourceValidator; class ConfigCacheTest extends \PHPUnit_Framework_TestCase { @@ -124,7 +124,7 @@ public function testWriteDumpsMetaFileWithDebugEnabled() private function isCacheValid(ConfigCache $cache) { - return $cache->isValid(array(new ResourceInterfaceValidator())); + return $cache->isValid(array(new ResourceValidator())); } private function makeCacheFresh() diff --git a/src/Symfony/Component/Config/Tests/Resource/ResourceInterfaceValidatorTest.php b/src/Symfony/Component/Config/Tests/Resource/ResourceValidatorTest.php similarity index 88% rename from src/Symfony/Component/Config/Tests/Resource/ResourceInterfaceValidatorTest.php rename to src/Symfony/Component/Config/Tests/Resource/ResourceValidatorTest.php index 97596912d29ed..4ad8e03fca81b 100644 --- a/src/Symfony/Component/Config/Tests/Resource/ResourceInterfaceValidatorTest.php +++ b/src/Symfony/Component/Config/Tests/Resource/ResourceValidatorTest.php @@ -11,9 +11,9 @@ namespace Symfony\Component\Config\Tests\Resource; -use Symfony\Component\Config\Resource\ResourceInterfaceValidator; +use Symfony\Component\Config\Resource\ResourceValidator; -class ResourceInterfaceValidatorTest extends \PHPUnit_Framework_TestCase +class ResourceValidatorTest extends \PHPUnit_Framework_TestCase { protected $validator; protected $metadataMock; @@ -22,7 +22,7 @@ class ResourceInterfaceValidatorTest extends \PHPUnit_Framework_TestCase public function setUp() { $this->timestamp = 10; - $this->validator = new ResourceInterfaceValidator(); + $this->validator = new ResourceValidator(); $this->metadataMock = $this->getMock('\Symfony\Component\Config\Resource\ResourceInterface'); } diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php index f482e45947061..26f5ec90c0e48 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -13,7 +13,7 @@ use Symfony\Bridge\ProxyManager\LazyProxy\Instantiator\RuntimeInstantiator; use Symfony\Bridge\ProxyManager\LazyProxy\PhpDumper\ProxyDumper; -use Symfony\Component\Config\Resource\ResourceInterfaceValidator; +use Symfony\Component\Config\Resource\ResourceValidator; use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Dumper\PhpDumper; @@ -553,7 +553,7 @@ protected function initializeContainer() * some wrapper methods because we cannot call protected methods from closures * prior to PHP 5.4. Let's do this change later when we can require PHP 5.4. */ - if (!$cache->isValid(array(new ResourceInterfaceValidator()))) { + if (!$cache->isValid(array(new ResourceValidator()))) { $container = $this->buildContainer(); $container->compile(); $this->dumpContainer($cache, $container, $class, $this->getContainerBaseClass()); From 8907a21bc6ed18b54c433f839a103b9df6b74aa3 Mon Sep 17 00:00:00 2001 From: Matthias Pigulla Date: Mon, 7 Sep 2015 09:58:40 +0200 Subject: [PATCH 21/36] Oh Fabbot --- .../Tests/Command/CacheClearCommand/CacheClearCommandTest.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/CacheClearCommand/CacheClearCommandTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/CacheClearCommand/CacheClearCommandTest.php index 662a915d28777..0cfc92241b82f 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Command/CacheClearCommand/CacheClearCommandTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Command/CacheClearCommand/CacheClearCommandTest.php @@ -6,7 +6,6 @@ use Symfony\Bundle\FrameworkBundle\Tests\Command\CacheClearCommand\Fixture\TestAppKernel; use Symfony\Bundle\FrameworkBundle\Tests\TestCase; use Symfony\Component\Config\ConfigCacheFactory; -use Symfony\Component\Config\ConfigCacheInterface; use Symfony\Component\Config\Resource\ResourceInterface; use Symfony\Component\Console\Input\ArrayInput; use Symfony\Component\Console\Output\NullOutput; From e47189097670843bf3ee50beae58edf5ed7df0ab Mon Sep 17 00:00:00 2001 From: Matthias Pigulla Date: Mon, 7 Sep 2015 10:34:37 +0200 Subject: [PATCH 22/36] Add a note why the ResourceInterface::__toString method is important and unlikely to disappear in the future --- .../Component/Config/Resource/ResourceInterface.php | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Component/Config/Resource/ResourceInterface.php b/src/Symfony/Component/Config/Resource/ResourceInterface.php index db03d127a401e..2a6d16dd782c3 100644 --- a/src/Symfony/Component/Config/Resource/ResourceInterface.php +++ b/src/Symfony/Component/Config/Resource/ResourceInterface.php @@ -21,7 +21,13 @@ interface ResourceInterface /** * Returns a string representation of the Resource. * - * @return string A string representation of the Resource + * This method is necessary to allow for resource de-duplication, for example by means + * of array_unique(). The string returned need not have a particular meaning, but has + * to be identical for different ResourceInterface instances referring to the same + * resource; and it should be unlikely to collide with that of other, unrelated + * resource instances. + * + * @return string A string representation unique to the underlying Resource */ public function __toString(); From e9fd19714fd52fa8cea144f13bb178d454f75516 Mon Sep 17 00:00:00 2001 From: Matthias Pigulla Date: Mon, 7 Sep 2015 12:28:13 +0200 Subject: [PATCH 23/36] Remove totally broken test This may have worked in the past, but was based on assumptions how the cache was implemented. You cannot dump a cache in prod and then expect it to be fresh or not when switching back to dev. A useful test would: 1. Use a mock loader to detect reloads 2. In prod: Use a Translator to prime the cache; try again with another instance and see that the cache is used 3. In dev: Use a Translator to prime the cache; add an "always stale" resource; try again with another instance and see that the cache is refreshed. --- .../Tests/Translation/TranslatorTest.php | 28 ------------------- 1 file changed, 28 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Translation/TranslatorTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Translation/TranslatorTest.php index c7b61cb88170e..5bc45682cfd2b 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/Translation/TranslatorTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Translation/TranslatorTest.php @@ -104,34 +104,6 @@ public function testTransWithCachingWithInvalidLocale() $translator->trans('foo'); } - public function testLoadResourcesWithCaching() - { - $loader = new \Symfony\Component\Translation\Loader\YamlFileLoader(); - $resourceFiles = array( - 'fr' => array( - __DIR__.'/../Fixtures/Resources/translations/messages.fr.yml', - ), - ); - - // prime the cache - $translator = $this->getTranslator($loader, array('cache_dir' => $this->tmpDir, 'resource_files' => $resourceFiles), 'yml'); - $translator->setLocale('fr'); - - $this->assertEquals('répertoire', $translator->trans('folder')); - - // do it another time as the cache is primed now - $translator = $this->getTranslator($loader, array('cache_dir' => $this->tmpDir), 'yml'); - $translator->setLocale('fr'); - - $this->assertEquals('répertoire', $translator->trans('folder')); - - // refresh cache when resources is changed in debug mode. - $translator = $this->getTranslator($loader, array('cache_dir' => $this->tmpDir, 'debug' => true), 'yml'); - $translator->setLocale('fr'); - - $this->assertEquals('folder', $translator->trans('folder')); - } - public function testLoadResourcesWithoutCaching() { $loader = new \Symfony\Component\Translation\Loader\YamlFileLoader(); From 53ad659e18786ddd9edbd453a3b7b73ea5495cc2 Mon Sep 17 00:00:00 2001 From: Matthias Pigulla Date: Mon, 7 Sep 2015 13:18:15 +0200 Subject: [PATCH 24/36] Rewrite ConfigCacheTest because it made many assumptions about how the cache works internally --- .../Config/Tests/ConfigCacheTest.php | 131 +++++++++++------- 1 file changed, 82 insertions(+), 49 deletions(-) diff --git a/src/Symfony/Component/Config/Tests/ConfigCacheTest.php b/src/Symfony/Component/Config/Tests/ConfigCacheTest.php index c544e38d64b22..c13ff5af0abf5 100644 --- a/src/Symfony/Component/Config/Tests/ConfigCacheTest.php +++ b/src/Symfony/Component/Config/Tests/ConfigCacheTest.php @@ -12,30 +12,21 @@ namespace Symfony\Component\Config\Tests; use Symfony\Component\Config\ConfigCache; -use Symfony\Component\Config\Resource\FileResource; +use Symfony\Component\Config\Resource\ResourceInterface; use Symfony\Component\Config\Resource\ResourceValidator; class ConfigCacheTest extends \PHPUnit_Framework_TestCase { - private $resourceFile = null; - private $cacheFile = null; - private $metaFile = null; - protected function setUp() { - $this->resourceFile = tempnam(sys_get_temp_dir(), '_resource'); $this->cacheFile = tempnam(sys_get_temp_dir(), 'config_'); - $this->metaFile = $this->cacheFile.'.meta'; - - $this->makeCacheFresh(); - $this->generateMetaFile(); } protected function tearDown() { - $files = array($this->cacheFile, $this->metaFile, $this->resourceFile); + $files = array($this->cacheFile, "{$this->cacheFile}.meta"); foreach ($files as $file) { if (file_exists($file)) { @@ -51,94 +42,136 @@ public function testGetPath() $this->assertSame($this->cacheFile, $cache->getPath()); } - public function testCacheIsNotFreshIfFileDoesNotExist() + public function testCacheIsNotValidIfNothingHasBeenCached() { - unlink($this->cacheFile); - + unlink($this->cacheFile); // remove tempnam() side effect $cache = new ConfigCache($this->cacheFile, false); $this->assertFalse($this->isCacheValid($cache)); } - public function testCacheIsAlwaysFreshIfFileExistsWithDebugDisabled() + /** + * @group legacy + */ + public function testIsFreshAlwaysReturnsTrueInProduction() { - $this->makeCacheStale(); + $staleResource = new ResourceStub(); + $staleResource->setFresh(false); $cache = new ConfigCache($this->cacheFile, false); + $cache->write('', array($staleResource)); - $this->assertTrue($this->isCacheValid($cache)); + $this->assertTrue($cache->isFresh()); } - public function testCacheIsNotFreshWithoutMetaFile() + /** + * @group legacy + */ + public function testIsFreshWithFreshResourceInDebug() { - unlink($this->metaFile); + $freshResource = new ResourceStub(); + $freshResource->setFresh(true); $cache = new ConfigCache($this->cacheFile, true); + $cache->write('', array($freshResource)); - $this->assertFalse($this->isCacheValid($cache)); + $this->assertTrue($cache->isFresh()); } - public function testCacheIsFreshIfResourceIsFresh() + /** + * @group legacy + */ + public function testIsNotFreshWithStaleResourceInDebug() { + $staleResource = new ResourceStub(); + $staleResource->setFresh(false); + $cache = new ConfigCache($this->cacheFile, true); + $cache->write('', array($staleResource)); - $this->assertTrue($this->isCacheValid($cache)); + $this->assertFalse($cache->isFresh()); } - public function testCacheIsNotFreshIfOneOfTheResourcesIsNotFresh() + /** + * @dataProvider debugModes + */ + public function testIsValidWithFreshResource($debug) { - $this->makeCacheStale(); + $freshResource = new ResourceStub(); + $freshResource->setFresh(true); - $cache = new ConfigCache($this->cacheFile, true); + $cache = new ConfigCache($this->cacheFile, $debug); + $cache->write('', array($freshResource)); - $this->assertFalse($this->isCacheValid($cache)); + $this->assertTrue($this->isCacheValid($cache)); } - public function testWriteDumpsFile() + /** + * @dataProvider debugModes + */ + public function testIsNotValidWithStaleResource($debug) { - unlink($this->cacheFile); - unlink($this->metaFile); + $staleResource = new ResourceStub(); + $staleResource->setFresh(true); - $cache = new ConfigCache($this->cacheFile, false); - $cache->write('FOOBAR'); + $cache = new ConfigCache($this->cacheFile, $debug); + $cache->write('', array($staleResource)); - $this->assertFileExists($this->cacheFile, 'Cache file is created'); - $this->assertSame('FOOBAR', file_get_contents($this->cacheFile)); - $this->assertFileNotExists($this->metaFile, 'Meta file is not created'); + $this->assertTrue($this->isCacheValid($cache)); } - public function testWriteDumpsMetaFileWithDebugEnabled() + public function testResourcesWithoutValidatorsAreIgnoredAndConsideredFresh() { - unlink($this->cacheFile); - unlink($this->metaFile); - - $metadata = array(new FileResource($this->resourceFile)); + $staleResource = new ResourceStub(); + $staleResource->setFresh(false); $cache = new ConfigCache($this->cacheFile, true); - $cache->write('FOOBAR', $metadata); + $cache->write('', array($staleResource)); + + $this->assertTrue($cache->isValid(array())); // no (matching) MetadataValidator passed + } + + public function testCacheKeepsContent() + { + $cache = new ConfigCache($this->cacheFile, false); + $cache->write('FOOBAR'); - $this->assertFileExists($this->cacheFile, 'Cache file is created'); - $this->assertFileExists($this->metaFile, 'Meta file is created'); - $this->assertSame(serialize($metadata), file_get_contents($this->metaFile)); + $this->assertSame('FOOBAR', file_get_contents($cache->getPath())); + } + + public function debugModes() + { + return array( + array(true), + array(false) + ); } private function isCacheValid(ConfigCache $cache) { return $cache->isValid(array(new ResourceValidator())); } +} - private function makeCacheFresh() +class ResourceStub implements ResourceInterface { + private $fresh = true; + + public function setFresh($isFresh) { - touch($this->resourceFile, filemtime($this->cacheFile) - 3600); + $this->fresh = $isFresh; + } + + public function __toString() { + return 'stub'; } - private function makeCacheStale() + public function isFresh($timestamp) { - touch($this->cacheFile, filemtime($this->resourceFile) - 3600); + return $this->fresh; } - private function generateMetaFile() + public function getResource() { - file_put_contents($this->metaFile, serialize(array(new FileResource($this->resourceFile)))); + return 'stub'; } } From 594529c47a63fe241406aec7a2f43f5d5e95fc71 Mon Sep 17 00:00:00 2001 From: Matthias Pigulla Date: Mon, 7 Sep 2015 13:29:24 +0200 Subject: [PATCH 25/36] Fix ConfigCache and improve docblock --- src/Symfony/Component/Config/ConfigCache.php | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Component/Config/ConfigCache.php b/src/Symfony/Component/Config/ConfigCache.php index d252f83397732..89722f30ec1f7 100644 --- a/src/Symfony/Component/Config/ConfigCache.php +++ b/src/Symfony/Component/Config/ConfigCache.php @@ -88,9 +88,14 @@ public function isFresh() * Use MetadataValidators to check if the cache is still valid. * * The first MetadataValidator that supports a given resource is considered authoritative. - * Resources with no matching MetadataValidators will silently be ignored. + * Resources with no matching MetadataValidators will silently be ignored and considered fresh. * - * @param MetadataValidatorInterface[] $validators List of validators the metadata is checked against. The first validator that supports a resource is considered authoritative. + * This method does not take the debug flag into consideration: Whether or not a cache + * should be checked in production mode and/or which validators need to be applied is a decision + * left to the client of this method. + * + * @param MetadataValidatorInterface[] $validators List of validators the metadata is checked against. + * The first validator that supports a resource is considered authoritative. * * @return bool True if all supported resources and valid, false otherwise */ @@ -102,7 +107,7 @@ public function isValid(array $validators = null) $metadata = $this->getMetaFile(); if (!is_file($metadata)) { - return false; + return true; } $time = filemtime($this->file); From 32426ce77e45641fac25917de9e6404db741c45f Mon Sep 17 00:00:00 2001 From: Matthias Pigulla Date: Mon, 7 Sep 2015 13:32:23 +0200 Subject: [PATCH 26/36] If I had to pay just $0.02 for every Fabbot complaint, Fabien would be a rich man already --- src/Symfony/Component/Config/Tests/ConfigCacheTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Config/Tests/ConfigCacheTest.php b/src/Symfony/Component/Config/Tests/ConfigCacheTest.php index c13ff5af0abf5..d131db1b4e55a 100644 --- a/src/Symfony/Component/Config/Tests/ConfigCacheTest.php +++ b/src/Symfony/Component/Config/Tests/ConfigCacheTest.php @@ -143,7 +143,7 @@ public function debugModes() { return array( array(true), - array(false) + array(false), ); } From f3470e35b2567fdb238e9150a02f4d9567756745 Mon Sep 17 00:00:00 2001 From: Matthias Pigulla Date: Mon, 7 Sep 2015 21:41:44 +0200 Subject: [PATCH 27/36] Document deprecation in the CHANGELOG file --- src/Symfony/Component/Config/CHANGELOG.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/Symfony/Component/Config/CHANGELOG.md b/src/Symfony/Component/Config/CHANGELOG.md index e1b19e6cb6f91..a281f546485e4 100644 --- a/src/Symfony/Component/Config/CHANGELOG.md +++ b/src/Symfony/Component/Config/CHANGELOG.md @@ -1,6 +1,17 @@ CHANGELOG ========= +2.8.0 +----- + + * deprecated the `ConfigCache::isFresh()` method. Use the new `isValid()` method instead and + pass the `MetadataValidator` instances that shall be used to validate the cache. A single + `ResourceValidator` will do and perform the same validations (using `ResourceInterface`) + as `isFresh()` previously did. + + Note that an even better approach would be to use the `ConfigCacheFactory`; it will + perform the freshness check for you and runs a callback if the cache needs to be updated. + 2.7.0 ----- From 773987834ccb94dba78b7a075fb7e6647d697a9f Mon Sep 17 00:00:00 2001 From: Matthias Pigulla Date: Mon, 7 Sep 2015 23:35:57 +0200 Subject: [PATCH 28/36] Some more tweaks to the ConfigCacheTest --- src/Symfony/Component/Config/ConfigCache.php | 2 +- .../Config/Tests/ConfigCacheTest.php | 82 +++++++++++++------ 2 files changed, 57 insertions(+), 27 deletions(-) diff --git a/src/Symfony/Component/Config/ConfigCache.php b/src/Symfony/Component/Config/ConfigCache.php index 89722f30ec1f7..79ebf61d88df0 100644 --- a/src/Symfony/Component/Config/ConfigCache.php +++ b/src/Symfony/Component/Config/ConfigCache.php @@ -150,7 +150,7 @@ public function write($content, array $metadata = null) // discard chmod failure (some filesystem may not support it) } - if (null !== $metadata && true === $this->debug) { + if (null !== $metadata) { $filesystem->dumpFile($this->getMetaFile(), serialize($metadata), null); try { $filesystem->chmod($this->getMetaFile(), $mode, $umask); diff --git a/src/Symfony/Component/Config/Tests/ConfigCacheTest.php b/src/Symfony/Component/Config/Tests/ConfigCacheTest.php index d131db1b4e55a..2a8a50b889e3f 100644 --- a/src/Symfony/Component/Config/Tests/ConfigCacheTest.php +++ b/src/Symfony/Component/Config/Tests/ConfigCacheTest.php @@ -42,12 +42,44 @@ public function testGetPath() $this->assertSame($this->cacheFile, $cache->getPath()); } - public function testCacheIsNotValidIfNothingHasBeenCached() + /** + * @dataProvider debugModes + */ + public function testCacheIsValidIfNoValidatorProvided($debug) + { + /* For example in prod mode, you may choose not to run any validators + at all. In that case, the cache should always be considered fresh. */ + $cache = new ConfigCache($this->cacheFile, $debug); + $this->assertTrue($cache->isValid(array())); + } + + /** + * @dataProvider debugModes + */ + public function testResourcesWithoutValidatorsAreIgnoredAndConsideredFresh($debug) + { + /* As in the previous test, but this time we have a resource. */ + $cache = new ConfigCache($this->cacheFile, true); + $cache->write('', array(new ResourceStub())); + + $this->assertTrue($cache->isValid(array())); // no (matching) MetadataValidator passed + } + + /** + * @dataProvider debugModes + */ + public function testCacheIsNotValidIfNothingHasBeenCached($debug) { + $validator = $this->getMock('\Symfony\Component\Config\MetadataValidatorInterface') + ->expects($this->never())->method('supports'); + + /* If there is nothing in the cache, it needs to be filled (and thus it's not fresh). + It does not matter if you provide validators or not. */ + unlink($this->cacheFile); // remove tempnam() side effect - $cache = new ConfigCache($this->cacheFile, false); + $cache = new ConfigCache($this->cacheFile, $debug); - $this->assertFalse($this->isCacheValid($cache)); + $this->assertFalse($cache->isValid(array($validator))); } /** @@ -97,13 +129,20 @@ public function testIsNotFreshWithStaleResourceInDebug() */ public function testIsValidWithFreshResource($debug) { - $freshResource = new ResourceStub(); - $freshResource->setFresh(true); + $validator = $this->getMock('\Symfony\Component\Config\MetadataValidatorInterface'); + + $validator->expects($this->once()) + ->method('supports') + ->willReturn(true); + + $validator->expects($this->once()) + ->method('isFresh') + ->willReturn(true); $cache = new ConfigCache($this->cacheFile, $debug); - $cache->write('', array($freshResource)); + $cache->write('', array(new ResourceStub())); - $this->assertTrue($this->isCacheValid($cache)); + $this->assertTrue($cache->isValid(array($validator))); } /** @@ -111,24 +150,20 @@ public function testIsValidWithFreshResource($debug) */ public function testIsNotValidWithStaleResource($debug) { - $staleResource = new ResourceStub(); - $staleResource->setFresh(true); + $validator = $this->getMock('\Symfony\Component\Config\MetadataValidatorInterface'); - $cache = new ConfigCache($this->cacheFile, $debug); - $cache->write('', array($staleResource)); + $validator->expects($this->once()) + ->method('supports') + ->willReturn(true); - $this->assertTrue($this->isCacheValid($cache)); - } + $validator->expects($this->once()) + ->method('isFresh') + ->willReturn(false); - public function testResourcesWithoutValidatorsAreIgnoredAndConsideredFresh() - { - $staleResource = new ResourceStub(); - $staleResource->setFresh(false); - - $cache = new ConfigCache($this->cacheFile, true); - $cache->write('', array($staleResource)); + $cache = new ConfigCache($this->cacheFile, $debug); + $cache->write('', array(new ResourceStub())); - $this->assertTrue($cache->isValid(array())); // no (matching) MetadataValidator passed + $this->assertFalse($cache->isValid(array($validator))); } public function testCacheKeepsContent() @@ -146,11 +181,6 @@ public function debugModes() array(false), ); } - - private function isCacheValid(ConfigCache $cache) - { - return $cache->isValid(array(new ResourceValidator())); - } } class ResourceStub implements ResourceInterface { From f9c48a0f0351d2ba7d16ba4f53bf2fa74c0edf39 Mon Sep 17 00:00:00 2001 From: Matthias Pigulla Date: Mon, 7 Sep 2015 23:37:12 +0200 Subject: [PATCH 29/36] Remove unused import --- src/Symfony/Component/Config/Tests/ConfigCacheTest.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Symfony/Component/Config/Tests/ConfigCacheTest.php b/src/Symfony/Component/Config/Tests/ConfigCacheTest.php index 2a8a50b889e3f..2dfddb60da6f1 100644 --- a/src/Symfony/Component/Config/Tests/ConfigCacheTest.php +++ b/src/Symfony/Component/Config/Tests/ConfigCacheTest.php @@ -13,7 +13,6 @@ use Symfony\Component\Config\ConfigCache; use Symfony\Component\Config\Resource\ResourceInterface; -use Symfony\Component\Config\Resource\ResourceValidator; class ConfigCacheTest extends \PHPUnit_Framework_TestCase { From c0f416d09054bb002a550b3da287d1ab87efc7b3 Mon Sep 17 00:00:00 2001 From: Matthias Pigulla Date: Tue, 8 Sep 2015 10:30:02 +0200 Subject: [PATCH 30/36] Continue with next resource, not next validator --- src/Symfony/Component/Config/ConfigCache.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Config/ConfigCache.php b/src/Symfony/Component/Config/ConfigCache.php index 79ebf61d88df0..e153d72f7eefc 100644 --- a/src/Symfony/Component/Config/ConfigCache.php +++ b/src/Symfony/Component/Config/ConfigCache.php @@ -119,7 +119,7 @@ public function isValid(array $validators = null) continue; // next validator } if ($validator->isFresh($resource, $time)) { - continue; // no need to further check this resource + break; // no need to further check this resource } else { return false; // cache is stale } From 00b4efb66eda954e6683ba80a2e51f1d7bf23bb3 Mon Sep 17 00:00:00 2001 From: Matthias Pigulla Date: Tue, 8 Sep 2015 10:53:36 +0200 Subject: [PATCH 31/36] Add a shortcut for when we don't have any validators (might be in prod) --- src/Symfony/Component/Config/ConfigCache.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Symfony/Component/Config/ConfigCache.php b/src/Symfony/Component/Config/ConfigCache.php index e153d72f7eefc..2504293abc7a0 100644 --- a/src/Symfony/Component/Config/ConfigCache.php +++ b/src/Symfony/Component/Config/ConfigCache.php @@ -105,6 +105,10 @@ public function isValid(array $validators = null) return false; } + if (!$validators) { + return true; // shortcut - if we don't have any validators we don't need to bother with the meta file at all + } + $metadata = $this->getMetaFile(); if (!is_file($metadata)) { return true; From 23a4464fd059b56c48c7495a1e2c6f98e1de5ac6 Mon Sep 17 00:00:00 2001 From: Matthias Pigulla Date: Tue, 8 Sep 2015 11:58:33 +0200 Subject: [PATCH 32/36] Create a new ValidatorConfigCache class and pass metadata validators in the constructor. That way, we can keep the isFresh() method and get away without deprecations. --- .../FrameworkBundle/FrameworkBundle.php | 2 +- src/Symfony/Component/Config/CHANGELOG.md | 11 -- src/Symfony/Component/Config/ConfigCache.php | 124 ++-------------- .../Component/Config/ConfigCacheFactory.php | 2 +- .../Component/Config/ConfigCacheInterface.php | 4 - .../Config/Tests/ConfigCacheTest.php | 134 ++--------------- .../Config/Tests/Resource/ResourceStub.php | 28 ++++ .../Config/Tests/ValidatorConfigCacheTest.php | 118 +++++++++++++++ .../Component/Config/ValidatorConfigCache.php | 138 ++++++++++++++++++ .../Config/ValidatorConfigCacheFactory.php | 12 +- src/Symfony/Component/HttpKernel/Kernel.php | 2 +- 11 files changed, 311 insertions(+), 264 deletions(-) create mode 100644 src/Symfony/Component/Config/Tests/Resource/ResourceStub.php create mode 100644 src/Symfony/Component/Config/Tests/ValidatorConfigCacheTest.php create mode 100644 src/Symfony/Component/Config/ValidatorConfigCache.php diff --git a/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php b/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php index a617ac42894bc..835f67de3d9b0 100644 --- a/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php +++ b/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php @@ -72,7 +72,6 @@ public function build(ContainerBuilder $container) $container->addCompilerPass(new RoutingResolverPass()); $container->addCompilerPass(new ProfilerPass()); - $container->addCompilerPass(new ConfigCachePass()); // must be registered before removing private services as some might be listeners/subscribers // but as late as possible to get resolved parameters $container->addCompilerPass(new RegisterListenersPass(), PassConfig::TYPE_BEFORE_REMOVING); @@ -94,6 +93,7 @@ public function build(ContainerBuilder $container) if ($container->getParameter('kernel.debug')) { $container->addCompilerPass(new ContainerBuilderDebugDumpPass(), PassConfig::TYPE_AFTER_REMOVING); $container->addCompilerPass(new CompilerDebugDumpPass(), PassConfig::TYPE_AFTER_REMOVING); + $container->addCompilerPass(new ConfigCachePass()); } } } diff --git a/src/Symfony/Component/Config/CHANGELOG.md b/src/Symfony/Component/Config/CHANGELOG.md index a281f546485e4..e1b19e6cb6f91 100644 --- a/src/Symfony/Component/Config/CHANGELOG.md +++ b/src/Symfony/Component/Config/CHANGELOG.md @@ -1,17 +1,6 @@ CHANGELOG ========= -2.8.0 ------ - - * deprecated the `ConfigCache::isFresh()` method. Use the new `isValid()` method instead and - pass the `MetadataValidator` instances that shall be used to validate the cache. A single - `ResourceValidator` will do and perform the same validations (using `ResourceInterface`) - as `isFresh()` previously did. - - Note that an even better approach would be to use the `ConfigCacheFactory`; it will - perform the freshness check for you and runs a callback if the cache needs to be updated. - 2.7.0 ----- diff --git a/src/Symfony/Component/Config/ConfigCache.php b/src/Symfony/Component/Config/ConfigCache.php index 2504293abc7a0..e7ff1eb96c3f3 100644 --- a/src/Symfony/Component/Config/ConfigCache.php +++ b/src/Symfony/Component/Config/ConfigCache.php @@ -12,22 +12,20 @@ namespace Symfony\Component\Config; use Symfony\Component\Config\Resource\ResourceValidator; -use Symfony\Component\Filesystem\Exception\IOException; -use Symfony\Component\Filesystem\Filesystem; /** * ConfigCache caches arbitrary content in files on disk. * - * Metadata can be stored alongside the cache and can later be - * used by MetadataValidators to check if the cache is still fresh. + * When in debug mode, those metadata resources that implement + * \Symfony\Component\Config\Resource\ResourceInterface will + * be used to check cache freshness. * * @author Fabien Potencier * @author Matthias Pigulla */ -class ConfigCache implements ConfigCacheInterface +class ConfigCache extends ValidatorConfigCache { private $debug; - private $file; /** * @param string $file The absolute cache path @@ -35,7 +33,7 @@ class ConfigCache implements ConfigCacheInterface */ public function __construct($file, $debug) { - $this->file = $file; + parent::__construct($file, array(new ResourceValidator())); $this->debug = (bool) $debug; } @@ -50,127 +48,23 @@ public function __toString() { @trigger_error('ConfigCache::__toString() is deprecated since version 2.7 and will be removed in 3.0. Use the getPath() method instead.', E_USER_DEPRECATED); - return $this->file; - } - - /** - * Gets the cache file path. - * - * @return string The cache file path - */ - public function getPath() - { - return $this->file; + return $this->getPath(); } /** * Checks if the cache is still fresh. * - * This method always returns true when debug is off and the + * This implementation always returns true when debug is off and the * cache file exists. * * @return bool true if the cache is fresh, false otherwise - * - * @deprecated since version 2.8, to be removed in 3.0. */ public function isFresh() { - @trigger_error(__NAMESPACE__.'\ConfigCache::isFresh() is deprecated since version 2.8 and will be removed in 3.0. Use the isValid() method instead and pass the appropriate MetadataValidators, or even better use a \Symfony\Component\Config\ConfigCacheFactoryInterface implementation to create and validate the cache.', E_USER_DEPRECATED); - - if (!$this->debug && is_file($this->file)) { + if (!$this->debug && is_file($this->getPath())) { return true; } - return $this->isValid(array(new ResourceValidator())); - } - - /** - * Use MetadataValidators to check if the cache is still valid. - * - * The first MetadataValidator that supports a given resource is considered authoritative. - * Resources with no matching MetadataValidators will silently be ignored and considered fresh. - * - * This method does not take the debug flag into consideration: Whether or not a cache - * should be checked in production mode and/or which validators need to be applied is a decision - * left to the client of this method. - * - * @param MetadataValidatorInterface[] $validators List of validators the metadata is checked against. - * The first validator that supports a resource is considered authoritative. - * - * @return bool True if all supported resources and valid, false otherwise - */ - public function isValid(array $validators = null) - { - if (!is_file($this->file)) { - return false; - } - - if (!$validators) { - return true; // shortcut - if we don't have any validators we don't need to bother with the meta file at all - } - - $metadata = $this->getMetaFile(); - if (!is_file($metadata)) { - return true; - } - - $time = filemtime($this->file); - $meta = unserialize(file_get_contents($metadata)); - - foreach ($meta as $resource) { - foreach ($validators as $validator) { - if (!$validator->supports($resource)) { - continue; // next validator - } - if ($validator->isFresh($resource, $time)) { - break; // no need to further check this resource - } else { - return false; // cache is stale - } - } - // no suitable validator found, ignore this resource - } - - return true; - } - - /** - * Writes cache. - * - * @param string $content The content to write in the cache - * @param array $metadata An array of metadata - * - * @throws \RuntimeException When cache file can't be written - */ - public function write($content, array $metadata = null) - { - $mode = 0666; - $umask = umask(); - $filesystem = new Filesystem(); - $filesystem->dumpFile($this->file, $content, null); - try { - $filesystem->chmod($this->file, $mode, $umask); - } catch (IOException $e) { - // discard chmod failure (some filesystem may not support it) - } - - if (null !== $metadata) { - $filesystem->dumpFile($this->getMetaFile(), serialize($metadata), null); - try { - $filesystem->chmod($this->getMetaFile(), $mode, $umask); - } catch (IOException $e) { - // discard chmod failure (some filesystem may not support it) - } - } - } - - /** - * Gets the meta file path. - * - * @return string The meta file path - */ - private function getMetaFile() - { - return $this->file.'.meta'; + return parent::isFresh(); } } diff --git a/src/Symfony/Component/Config/ConfigCacheFactory.php b/src/Symfony/Component/Config/ConfigCacheFactory.php index a6e41aee5875f..b11b5dc86acf6 100644 --- a/src/Symfony/Component/Config/ConfigCacheFactory.php +++ b/src/Symfony/Component/Config/ConfigCacheFactory.php @@ -45,7 +45,7 @@ public function cache($file, $callback) } $cache = new ConfigCache($file, $this->debug); - if (!$cache->isValid(array(new ResourceValidator()))) { + if (!$cache->isFresh()) { call_user_func($callback, $cache); } diff --git a/src/Symfony/Component/Config/ConfigCacheInterface.php b/src/Symfony/Component/Config/ConfigCacheInterface.php index 8b3e840b21a03..e367ad187ee6c 100644 --- a/src/Symfony/Component/Config/ConfigCacheInterface.php +++ b/src/Symfony/Component/Config/ConfigCacheInterface.php @@ -33,10 +33,6 @@ public function getPath(); * This check should take the metadata passed to the write() method into consideration. * * @return bool Whether the cache is still fresh. - * - * @deprecated since 2.8, to be removed in 3.0. - * Use Symfony\Component\Config\ConfigCacheFactory instead, it will take care of - * validating the cache. */ public function isFresh(); diff --git a/src/Symfony/Component/Config/Tests/ConfigCacheTest.php b/src/Symfony/Component/Config/Tests/ConfigCacheTest.php index 2dfddb60da6f1..8959b267338b1 100644 --- a/src/Symfony/Component/Config/Tests/ConfigCacheTest.php +++ b/src/Symfony/Component/Config/Tests/ConfigCacheTest.php @@ -12,7 +12,7 @@ namespace Symfony\Component\Config\Tests; use Symfony\Component\Config\ConfigCache; -use Symfony\Component\Config\Resource\ResourceInterface; +use Symfony\Component\Config\Tests\Resource\ResourceStub; class ConfigCacheTest extends \PHPUnit_Framework_TestCase { @@ -34,57 +34,18 @@ protected function tearDown() } } - public function testGetPath() - { - $cache = new ConfigCache($this->cacheFile, true); - - $this->assertSame($this->cacheFile, $cache->getPath()); - } - - /** - * @dataProvider debugModes - */ - public function testCacheIsValidIfNoValidatorProvided($debug) - { - /* For example in prod mode, you may choose not to run any validators - at all. In that case, the cache should always be considered fresh. */ - $cache = new ConfigCache($this->cacheFile, $debug); - $this->assertTrue($cache->isValid(array())); - } - - /** - * @dataProvider debugModes - */ - public function testResourcesWithoutValidatorsAreIgnoredAndConsideredFresh($debug) - { - /* As in the previous test, but this time we have a resource. */ - $cache = new ConfigCache($this->cacheFile, true); - $cache->write('', array(new ResourceStub())); - - $this->assertTrue($cache->isValid(array())); // no (matching) MetadataValidator passed - } - /** * @dataProvider debugModes */ public function testCacheIsNotValidIfNothingHasBeenCached($debug) { - $validator = $this->getMock('\Symfony\Component\Config\MetadataValidatorInterface') - ->expects($this->never())->method('supports'); - - /* If there is nothing in the cache, it needs to be filled (and thus it's not fresh). - It does not matter if you provide validators or not. */ - unlink($this->cacheFile); // remove tempnam() side effect $cache = new ConfigCache($this->cacheFile, $debug); - $this->assertFalse($cache->isValid(array($validator))); + $this->assertFalse($cache->isFresh()); } - /** - * @group legacy - */ - public function testIsFreshAlwaysReturnsTrueInProduction() + public function testIsAlwaysFreshInProduction() { $staleResource = new ResourceStub(); $staleResource->setFresh(false); @@ -96,9 +57,16 @@ public function testIsFreshAlwaysReturnsTrueInProduction() } /** - * @group legacy + * @dataProvider debugModes */ - public function testIsFreshWithFreshResourceInDebug() + public function testIsFreshWhenNoResourceProvided($debug) + { + $cache = new ConfigCache($this->cacheFile, $debug); + $cache->write('', array()); + $this->assertTrue($cache->isFresh()); + } + + public function testFreshResourceInDebug() { $freshResource = new ResourceStub(); $freshResource->setFresh(true); @@ -109,10 +77,7 @@ public function testIsFreshWithFreshResourceInDebug() $this->assertTrue($cache->isFresh()); } - /** - * @group legacy - */ - public function testIsNotFreshWithStaleResourceInDebug() + public function testStaleResourceInDebug() { $staleResource = new ResourceStub(); $staleResource->setFresh(false); @@ -123,56 +88,6 @@ public function testIsNotFreshWithStaleResourceInDebug() $this->assertFalse($cache->isFresh()); } - /** - * @dataProvider debugModes - */ - public function testIsValidWithFreshResource($debug) - { - $validator = $this->getMock('\Symfony\Component\Config\MetadataValidatorInterface'); - - $validator->expects($this->once()) - ->method('supports') - ->willReturn(true); - - $validator->expects($this->once()) - ->method('isFresh') - ->willReturn(true); - - $cache = new ConfigCache($this->cacheFile, $debug); - $cache->write('', array(new ResourceStub())); - - $this->assertTrue($cache->isValid(array($validator))); - } - - /** - * @dataProvider debugModes - */ - public function testIsNotValidWithStaleResource($debug) - { - $validator = $this->getMock('\Symfony\Component\Config\MetadataValidatorInterface'); - - $validator->expects($this->once()) - ->method('supports') - ->willReturn(true); - - $validator->expects($this->once()) - ->method('isFresh') - ->willReturn(false); - - $cache = new ConfigCache($this->cacheFile, $debug); - $cache->write('', array(new ResourceStub())); - - $this->assertFalse($cache->isValid(array($validator))); - } - - public function testCacheKeepsContent() - { - $cache = new ConfigCache($this->cacheFile, false); - $cache->write('FOOBAR'); - - $this->assertSame('FOOBAR', file_get_contents($cache->getPath())); - } - public function debugModes() { return array( @@ -181,26 +96,3 @@ public function debugModes() ); } } - -class ResourceStub implements ResourceInterface { - private $fresh = true; - - public function setFresh($isFresh) - { - $this->fresh = $isFresh; - } - - public function __toString() { - return 'stub'; - } - - public function isFresh($timestamp) - { - return $this->fresh; - } - - public function getResource() - { - return 'stub'; - } -} diff --git a/src/Symfony/Component/Config/Tests/Resource/ResourceStub.php b/src/Symfony/Component/Config/Tests/Resource/ResourceStub.php new file mode 100644 index 0000000000000..447a2d67ffa3f --- /dev/null +++ b/src/Symfony/Component/Config/Tests/Resource/ResourceStub.php @@ -0,0 +1,28 @@ +fresh = $isFresh; + } + + public function __toString() { + return 'stub'; + } + + public function isFresh($timestamp) + { + return $this->fresh; + } + + public function getResource() + { + return 'stub'; + } +} diff --git a/src/Symfony/Component/Config/Tests/ValidatorConfigCacheTest.php b/src/Symfony/Component/Config/Tests/ValidatorConfigCacheTest.php new file mode 100644 index 0000000000000..030e1bfdf056e --- /dev/null +++ b/src/Symfony/Component/Config/Tests/ValidatorConfigCacheTest.php @@ -0,0 +1,118 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Config\Tests; + +use Symfony\Component\Config\Tests\Resource\ResourceStub; +use Symfony\Component\Config\ValidatorConfigCache; + +class ValidatorConfigCacheTest extends \PHPUnit_Framework_TestCase +{ + private $cacheFile = null; + + protected function setUp() + { + $this->cacheFile = tempnam(sys_get_temp_dir(), 'config_'); + } + + protected function tearDown() + { + $files = array($this->cacheFile, "{$this->cacheFile}.meta"); + + foreach ($files as $file) { + if (file_exists($file)) { + unlink($file); + } + } + } + + public function testGetPath() + { + $cache = new ValidatorConfigCache($this->cacheFile); + + $this->assertSame($this->cacheFile, $cache->getPath()); + } + + public function testCacheIsNotFreshIfEmpty() + { + $validator = $this->getMock('\Symfony\Component\Config\MetadataValidatorInterface') + ->expects($this->never())->method('supports'); + + /* If there is nothing in the cache, it needs to be filled (and thus it's not fresh). + It does not matter if you provide validators or not. */ + + unlink($this->cacheFile); // remove tempnam() side effect + $cache = new ValidatorConfigCache($this->cacheFile, array($validator)); + + $this->assertFalse($cache->isFresh()); + } + + public function testCacheIsFreshIfNoValidatorProvided() + { + /* For example in prod mode, you may choose not to run any validators + at all. In that case, the cache should always be considered fresh. */ + $cache = new ValidatorConfigCache($this->cacheFile); + $this->assertTrue($cache->isFresh()); + } + + public function testResourcesWithoutValidatorsAreIgnoredAndConsideredFresh() + { + /* As in the previous test, but this time we have a resource. */ + $cache = new ValidatorConfigCache($this->cacheFile); + $cache->write('', array(new ResourceStub())); + + $this->assertTrue($cache->isFresh()); // no (matching) MetadataValidator passed + } + + public function testIsFreshWithValidator() + { + $validator = $this->getMock('\Symfony\Component\Config\MetadataValidatorInterface'); + + $validator->expects($this->once()) + ->method('supports') + ->willReturn(true); + + $validator->expects($this->once()) + ->method('isFresh') + ->willReturn(true); + + $cache = new ValidatorConfigCache($this->cacheFile, array($validator)); + $cache->write('', array(new ResourceStub())); + + $this->assertTrue($cache->isFresh()); + } + + public function testIsNotFreshWithValidator() + { + $validator = $this->getMock('\Symfony\Component\Config\MetadataValidatorInterface'); + + $validator->expects($this->once()) + ->method('supports') + ->willReturn(true); + + $validator->expects($this->once()) + ->method('isFresh') + ->willReturn(false); + + $cache = new ValidatorConfigCache($this->cacheFile, array($validator)); + $cache->write('', array(new ResourceStub())); + + $this->assertFalse($cache->isFresh()); + } + + public function testCacheKeepsContent() + { + $cache = new ValidatorConfigCache($this->cacheFile); + $cache->write('FOOBAR'); + + $this->assertSame('FOOBAR', file_get_contents($cache->getPath())); + } +} diff --git a/src/Symfony/Component/Config/ValidatorConfigCache.php b/src/Symfony/Component/Config/ValidatorConfigCache.php new file mode 100644 index 0000000000000..b9724e9626495 --- /dev/null +++ b/src/Symfony/Component/Config/ValidatorConfigCache.php @@ -0,0 +1,138 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Config; + +use Symfony\Component\Filesystem\Exception\IOException; +use Symfony\Component\Filesystem\Filesystem; + +/** + * ValidatorConfigCache uses instances of MetadataValidatorInterface + * to check whether cached data is still fresh. + * + * @author Matthias Pigulla + */ +class ValidatorConfigCache implements ConfigCacheInterface +{ + /** + * @var string + */ + private $file; + + /** + * @var MetadataValidatorInterface[] + */ + private $validators; + + /** + * @param string $file The absolute cache path + * @param MetadataValidatorInterface[] $validators The MetadataValidators to use for the freshness check + */ + public function __construct($file, array $validators = array()) + { + $this->file = $file; + $this->validators = $validators; + } + + /** + * {@inheritdoc} + */ + public function getPath() + { + return $this->file; + } + + /** + * Checks if the cache is still fresh. + * + * This implementation will make a decision solely based on the MetadataValidators + * passed in the constructor. + * + * The first MetadataValidator that supports a given resource is considered authoritative. + * Resources with no matching MetadataValidators will silently be ignored and considered fresh. + * + * @return bool true if the cache is fresh, false otherwise + */ + public function isFresh() + { + if (!is_file($this->file)) { + return false; + } + + if (!$this->validators) { + return true; // shortcut - if we don't have any validators we don't need to bother with the meta file at all + } + + $metadata = $this->getMetaFile(); + if (!is_file($metadata)) { + return true; + } + + $time = filemtime($this->file); + $meta = unserialize(file_get_contents($metadata)); + + foreach ($meta as $resource) { + foreach ($this->validators as $validator) { + if (!$validator->supports($resource)) { + continue; // next validator + } + if ($validator->isFresh($resource, $time)) { + break; // no need to further check this resource + } else { + return false; // cache is stale + } + } + // no suitable validator found, ignore this resource + } + + return true; + } + + /** + * Writes cache. + * + * @param string $content The content to write in the cache + * @param array $metadata An array of metadata + * + * @throws \RuntimeException When cache file can't be written + */ + public function write($content, array $metadata = null) + { + $mode = 0666; + $umask = umask(); + $filesystem = new Filesystem(); + $filesystem->dumpFile($this->file, $content, null); + try { + $filesystem->chmod($this->file, $mode, $umask); + } catch (IOException $e) { + // discard chmod failure (some filesystem may not support it) + } + + if (null !== $metadata) { + $filesystem->dumpFile($this->getMetaFile(), serialize($metadata), null); + try { + $filesystem->chmod($this->getMetaFile(), $mode, $umask); + } catch (IOException $e) { + // discard chmod failure (some filesystem may not support it) + } + } + } + + /** + * Gets the meta file path. + * + * @return string The meta file path + */ + private function getMetaFile() + { + return $this->file.'.meta'; + } +} diff --git a/src/Symfony/Component/Config/ValidatorConfigCacheFactory.php b/src/Symfony/Component/Config/ValidatorConfigCacheFactory.php index 725d04135faeb..60556c38afc57 100644 --- a/src/Symfony/Component/Config/ValidatorConfigCacheFactory.php +++ b/src/Symfony/Component/Config/ValidatorConfigCacheFactory.php @@ -29,14 +29,6 @@ class ValidatorConfigCacheFactory implements ConfigCacheFactoryInterface */ private $validators = array(); - /** - * @param bool $debug The debug flag to pass to ConfigCache - */ - public function __construct($debug) - { - $this->debug = $debug; - } - /** * @param MetadataValidatorInterface $validator */ @@ -54,8 +46,8 @@ public function cache($file, $callback) throw new \InvalidArgumentException(sprintf('Invalid type for callback argument. Expected callable, but got "%s".', gettype($callback))); } - $cache = new ConfigCache($file, $this->debug); - if (!$cache->isValid($this->validators)) { + $cache = new ValidatorConfigCache($file, $this->validators); + if (!$cache->isFresh()) { call_user_func($callback, $cache); } diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php index 26f5ec90c0e48..dfdcd3c1e323a 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -553,7 +553,7 @@ protected function initializeContainer() * some wrapper methods because we cannot call protected methods from closures * prior to PHP 5.4. Let's do this change later when we can require PHP 5.4. */ - if (!$cache->isValid(array(new ResourceValidator()))) { + if (!$cache->isFresh()) { $container = $this->buildContainer(); $container->compile(); $this->dumpContainer($cache, $container, $class, $this->getContainerBaseClass()); From caf6bf15207287ba413897b5d2d9b699248fef8c Mon Sep 17 00:00:00 2001 From: Matthias Pigulla Date: Tue, 8 Sep 2015 12:01:47 +0200 Subject: [PATCH 33/36] Fabbot --- src/Symfony/Component/Config/Tests/Resource/ResourceStub.php | 1 + src/Symfony/Component/HttpKernel/Kernel.php | 1 - 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Config/Tests/Resource/ResourceStub.php b/src/Symfony/Component/Config/Tests/Resource/ResourceStub.php index 447a2d67ffa3f..4cfd14a6dc866 100644 --- a/src/Symfony/Component/Config/Tests/Resource/ResourceStub.php +++ b/src/Symfony/Component/Config/Tests/Resource/ResourceStub.php @@ -1,4 +1,5 @@ Date: Tue, 8 Sep 2015 12:19:45 +0200 Subject: [PATCH 34/36] This is not relevant for this PR --- src/Symfony/Component/HttpKernel/Kernel.php | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/Symfony/Component/HttpKernel/Kernel.php b/src/Symfony/Component/HttpKernel/Kernel.php index f2bf4d40181f2..fdec21632db31 100644 --- a/src/Symfony/Component/HttpKernel/Kernel.php +++ b/src/Symfony/Component/HttpKernel/Kernel.php @@ -547,11 +547,6 @@ protected function initializeContainer() $class = $this->getContainerClass(); $cache = new ConfigCache($this->getCacheDir().'/'.$class.'.php', $this->debug); $fresh = true; - - /* We probably should use the ConfigCacheFactory here, but that would require - * some wrapper methods because we cannot call protected methods from closures - * prior to PHP 5.4. Let's do this change later when we can require PHP 5.4. - */ if (!$cache->isFresh()) { $container = $this->buildContainer(); $container->compile(); From 7bc5ba2ad3e157699dfb8f918bffb800969baea6 Mon Sep 17 00:00:00 2001 From: Matthias Pigulla Date: Tue, 8 Sep 2015 15:06:06 +0200 Subject: [PATCH 35/36] Tweaks as suggested on GH --- src/Symfony/Component/Config/Tests/ConfigCacheTest.php | 2 +- src/Symfony/Component/Config/ValidatorConfigCache.php | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Component/Config/Tests/ConfigCacheTest.php b/src/Symfony/Component/Config/Tests/ConfigCacheTest.php index 8959b267338b1..faa37f0e9db0d 100644 --- a/src/Symfony/Component/Config/Tests/ConfigCacheTest.php +++ b/src/Symfony/Component/Config/Tests/ConfigCacheTest.php @@ -25,7 +25,7 @@ protected function setUp() protected function tearDown() { - $files = array($this->cacheFile, "{$this->cacheFile}.meta"); + $files = array($this->cacheFile, $this->cacheFile.'.meta'); foreach ($files as $file) { if (file_exists($file)) { diff --git a/src/Symfony/Component/Config/ValidatorConfigCache.php b/src/Symfony/Component/Config/ValidatorConfigCache.php index b9724e9626495..4c5be87778513 100644 --- a/src/Symfony/Component/Config/ValidatorConfigCache.php +++ b/src/Symfony/Component/Config/ValidatorConfigCache.php @@ -86,9 +86,9 @@ public function isFresh() } if ($validator->isFresh($resource, $time)) { break; // no need to further check this resource - } else { - return false; // cache is stale } + + return false; // cache is stale } // no suitable validator found, ignore this resource } From f5add4c419634e0e0024b6412bf119eb8fd4f653 Mon Sep 17 00:00:00 2001 From: Matthias Pigulla Date: Wed, 9 Sep 2015 13:43:42 +0200 Subject: [PATCH 36/36] Implement the plan(TM) * Add priorities so that new custom ResourceCheckers can be run first * Provide a default ResourceChecker with a very low priority that will validate through ResourceInterface::isFresh() but triggers a deprecation warning. * Add a new interface that extends ResourceInterface and contains the isFresh() method. * Add a ResourceChecker for this interface with a slightly higher priority and without deprecation warning. * Make FileResource et. al. implement the new interface. * Deprecate ResourceInterface::isFresh() but keep that method in the new interface subclass. --- .../Compiler/ConfigCachePass.php | 40 +++++++++++++ .../FrameworkBundle/FrameworkBundle.php | 2 +- .../Resources/config/services.xml | 19 +++++-- .../Compiler/ConfigCachePassTest.php | 54 ++++++++++++++++++ src/Symfony/Component/Config/ConfigCache.php | 17 ++++-- .../Component/Config/ConfigCacheFactory.php | 10 ++-- .../DependencyInjection/ConfigCachePass.php | 33 ----------- .../Resource/BCResourceInterfaceChecker.php | 36 ++++++++++++ .../Resource/DefaultResourceChecker.php | 36 ++++++++++++ .../Config/Resource/DirectoryResource.php | 2 +- .../Config/Resource/FileExistenceResource.php | 2 +- .../Config/Resource/FileResource.php | 2 +- .../Config/Resource/ResourceInterface.php | 3 + .../Config/Resource/ResourceValidator.php | 32 ----------- .../SelfCheckingResourceInterface.php | 30 ++++++++++ ...che.php => ResourceCheckerConfigCache.php} | 44 ++++++++------- ... => ResourceCheckerConfigCacheFactory.php} | 21 +++---- ...rface.php => ResourceCheckerInterface.php} | 21 ++++--- .../Config/Tests/Resource/ResourceStub.php | 4 +- .../Tests/Resource/ResourceValidatorTest.php | 56 ------------------- ...php => ResourceCheckerConfigCacheTest.php} | 46 +++++++-------- .../Config/EnvParametersResource.php | 4 +- .../Translation/Tests/TranslatorCacheTest.php | 2 +- 23 files changed, 305 insertions(+), 211 deletions(-) create mode 100644 src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/ConfigCachePass.php create mode 100644 src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/ConfigCachePassTest.php delete mode 100644 src/Symfony/Component/Config/DependencyInjection/ConfigCachePass.php create mode 100644 src/Symfony/Component/Config/Resource/BCResourceInterfaceChecker.php create mode 100644 src/Symfony/Component/Config/Resource/DefaultResourceChecker.php delete mode 100644 src/Symfony/Component/Config/Resource/ResourceValidator.php create mode 100644 src/Symfony/Component/Config/Resource/SelfCheckingResourceInterface.php rename src/Symfony/Component/Config/{ValidatorConfigCache.php => ResourceCheckerConfigCache.php} (63%) rename src/Symfony/Component/Config/{ValidatorConfigCacheFactory.php => ResourceCheckerConfigCacheFactory.php} (63%) rename src/Symfony/Component/Config/{MetadataValidatorInterface.php => ResourceCheckerInterface.php} (53%) delete mode 100644 src/Symfony/Component/Config/Tests/Resource/ResourceValidatorTest.php rename src/Symfony/Component/Config/Tests/{ValidatorConfigCacheTest.php => ResourceCheckerConfigCacheTest.php} (60%) diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/ConfigCachePass.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/ConfigCachePass.php new file mode 100644 index 0000000000000..ce36b1b2618ca --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/ConfigCachePass.php @@ -0,0 +1,40 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler; + +use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; +use Symfony\Component\DependencyInjection\ContainerBuilder; +use Symfony\Component\DependencyInjection\Reference; + +/** + * Adds services tagged config_cache.resource_checker to the config_cache_factory service, ordering them by priority. + * + * @author Matthias Pigulla + * @author Benjamin Klotz + */ +class ConfigCachePass implements CompilerPassInterface +{ + public function process(ContainerBuilder $container) + { + $resourceCheckers = array(); + foreach ($container->findTaggedServiceIds('config_cache.resource_checker') as $id => $attributes) { + $priority = isset($attributes[0]['priority']) ? $attributes[0]['priority'] : 0; + $resourceCheckers[$priority][] = new Reference($id); + } + + // sort by priority and flatten + krsort($resourceCheckers); + $resourceCheckers = call_user_func_array('array_merge', $resourceCheckers); + + $container->getDefinition('config_cache_factory')->addMethodCall('setResourceCheckers', array($resourceCheckers)); + } +} diff --git a/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php b/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php index 835f67de3d9b0..7b1c77f225e57 100644 --- a/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php +++ b/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php @@ -28,7 +28,7 @@ use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\TranslationExtractorPass; use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\TranslationDumperPass; use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\SerializerPass; -use Symfony\Component\Config\DependencyInjection\ConfigCachePass; +use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\ConfigCachePass; use Symfony\Component\Debug\ErrorHandler; use Symfony\Component\DependencyInjection\ContainerBuilder; use Symfony\Component\DependencyInjection\Compiler\PassConfig; diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/services.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/services.xml index e613f60cf8cab..1c2a2fe673961 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/services.xml +++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/services.xml @@ -13,8 +13,9 @@ Symfony\Component\HttpKernel\Config\FileLocator Symfony\Component\HttpKernel\UriSigner Symfony\Component\HttpFoundation\RequestStack - Symfony\Component\Config\ValidatorConfigCacheFactory - Symfony\Component\Config\Resource\ResourceValidator + Symfony\Component\Config\ResourceCheckerConfigCacheFactory + Symfony\Component\Config\Resource\DefaultResourceChecker + Symfony\Component\Config\Resource\BCResourceInterfaceChecker @@ -66,12 +67,18 @@ %kernel.secret% - - %kernel.debug% + + + + - - + + + + diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/ConfigCachePassTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/ConfigCachePassTest.php new file mode 100644 index 0000000000000..b4a2b2ee838b4 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/ConfigCachePassTest.php @@ -0,0 +1,54 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\Compiler; + +use Symfony\Component\DependencyInjection\Reference; +use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\ConfigCachePass; + +class ConfigCachePassTest extends \PHPUnit_Framework_TestCase +{ + public function testThatCheckersAreProcessedInPriorityOrder() + { + $services = array( + 'checker_2' => array(0 => array('priority' => 100)), + 'checker_1' => array(0 => array('priority' => 200)), + 'checker_3' => array(), + ); + + $definition = $this->getMock('Symfony\Component\DependencyInjection\Definition'); + $container = $this->getMock( + 'Symfony\Component\DependencyInjection\ContainerBuilder', + array('findTaggedServiceIds', 'getDefinition', 'hasDefinition') + ); + + $container->expects($this->atLeastOnce()) + ->method('findTaggedServiceIds') + ->will($this->returnValue($services)); + $container->expects($this->atLeastOnce()) + ->method('getDefinition') + ->with('config_cache_factory') + ->will($this->returnValue($definition)); + + $definition->expects($this->once()) + ->method('addMethodCall') + ->with('setResourceCheckers', array( + array( + new Reference('checker_1'), + new Reference('checker_2'), + new Reference('checker_3'), + ) + )); + + $pass = new ConfigCachePass(); + $pass->process($container); + } +} diff --git a/src/Symfony/Component/Config/ConfigCache.php b/src/Symfony/Component/Config/ConfigCache.php index e7ff1eb96c3f3..d021b1d5e948d 100644 --- a/src/Symfony/Component/Config/ConfigCache.php +++ b/src/Symfony/Component/Config/ConfigCache.php @@ -11,19 +11,25 @@ namespace Symfony\Component\Config; -use Symfony\Component\Config\Resource\ResourceValidator; +use Symfony\Component\Config\Resource\BCResourceInterfaceChecker; +use Symfony\Component\Config\Resource\DefaultResourceChecker; /** * ConfigCache caches arbitrary content in files on disk. * * When in debug mode, those metadata resources that implement - * \Symfony\Component\Config\Resource\ResourceInterface will + * \Symfony\Component\Config\Resource\SelfCheckingResourceInterface will * be used to check cache freshness. * + * During a transition period, also instances of + * \Symfony\Component\Config\Resource\ResourceInterface will be checked + * by means of the isFresh() method. This behaviour is deprecated since 2.8 + * and will be removed in 3.0. + * * @author Fabien Potencier * @author Matthias Pigulla */ -class ConfigCache extends ValidatorConfigCache +class ConfigCache extends ResourceCheckerConfigCache { private $debug; @@ -33,7 +39,10 @@ class ConfigCache extends ValidatorConfigCache */ public function __construct($file, $debug) { - parent::__construct($file, array(new ResourceValidator())); + parent::__construct($file, array( + new DefaultResourceChecker(), + new BCResourceInterfaceChecker() + )); $this->debug = (bool) $debug; } diff --git a/src/Symfony/Component/Config/ConfigCacheFactory.php b/src/Symfony/Component/Config/ConfigCacheFactory.php index b11b5dc86acf6..396536e2d8ed8 100644 --- a/src/Symfony/Component/Config/ConfigCacheFactory.php +++ b/src/Symfony/Component/Config/ConfigCacheFactory.php @@ -11,12 +11,12 @@ namespace Symfony\Component\Config; -use Symfony\Component\Config\Resource\ResourceValidator; - /** - * Basic implementation of ConfigCacheFactoryInterface. - * Creates a ConfigCache instance that will be validated with the - * ResourceValidator only. + * Basic implementation of ConfigCacheFactoryInterface that + * creates an instance of the default ConfigCache. + * + * This factory and/or cache do not support cache validation + * by means of ResourceChecker instances (that is, service-based). * * @author Matthias Pigulla */ diff --git a/src/Symfony/Component/Config/DependencyInjection/ConfigCachePass.php b/src/Symfony/Component/Config/DependencyInjection/ConfigCachePass.php deleted file mode 100644 index cb5d3c1417243..0000000000000 --- a/src/Symfony/Component/Config/DependencyInjection/ConfigCachePass.php +++ /dev/null @@ -1,33 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\DependencyInjection; - -use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Reference; - -/** - * Adds tagged metadata_validator services to config_cache_factory service. - * - * @author Benjamin Klotz - */ -class ConfigCachePass implements CompilerPassInterface -{ - public function process(ContainerBuilder $container) - { - $definition = $container->getDefinition('config_cache_factory'); - - foreach ($container->findTaggedServiceIds('config_cache.metadata_validator') as $id => $attributes) { - $definition->addMethodCall('addValidator', array(new Reference($id))); - } - } -} diff --git a/src/Symfony/Component/Config/Resource/BCResourceInterfaceChecker.php b/src/Symfony/Component/Config/Resource/BCResourceInterfaceChecker.php new file mode 100644 index 0000000000000..8ed26202a2809 --- /dev/null +++ b/src/Symfony/Component/Config/Resource/BCResourceInterfaceChecker.php @@ -0,0 +1,36 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Config\Resource; + +/** + * Resource checker for the ResourceInterface. Exists for BC. + * + * @author Matthias Pigulla + * + * @deprecated since 2.8, to be removed in 3.0. + */ +class BCResourceInterfaceChecker extends DefaultResourceChecker +{ + public function supports(ResourceInterface $metadata) + { + /* As all resources must be instanceof ResourceInterface, + we support them all. */ + return true; + } + + public function isFresh(ResourceInterface $metadata, $timestamp) + { + trigger_error('Resource checking through ResourceInterface::isFresh() is deprecated since 2.8 and will be removed in 3.0', E_USER_DEPRECATED); + + return parent::isFresh($metadata, $timestamp); // For now, $metadata features the isFresh() method, so off we go (quack quack) + } +} diff --git a/src/Symfony/Component/Config/Resource/DefaultResourceChecker.php b/src/Symfony/Component/Config/Resource/DefaultResourceChecker.php new file mode 100644 index 0000000000000..b14107d5f6754 --- /dev/null +++ b/src/Symfony/Component/Config/Resource/DefaultResourceChecker.php @@ -0,0 +1,36 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Config\Resource; + +use Symfony\Component\Config\ResourceCheckerInterface; + +/** + * Resource checker for instances of + * SelfCheckingResourceInterface. As these resources can + * perform the check themselves, we can support them in a generic + * way. + * + * @author Matthias Pigulla + */ +class DefaultResourceChecker implements ResourceCheckerInterface +{ + public function supports(ResourceInterface $metadata) + { + return $metadata instanceof SelfCheckingResourceInterface; + } + + public function isFresh(ResourceInterface $metadata, $timestamp) + { + /** @var SelfCheckingResourceInterface $metadata */ + return $metadata->isFresh($timestamp); + } +} diff --git a/src/Symfony/Component/Config/Resource/DirectoryResource.php b/src/Symfony/Component/Config/Resource/DirectoryResource.php index 515fb5c42d6a9..1921e5d377787 100644 --- a/src/Symfony/Component/Config/Resource/DirectoryResource.php +++ b/src/Symfony/Component/Config/Resource/DirectoryResource.php @@ -16,7 +16,7 @@ * * @author Fabien Potencier */ -class DirectoryResource implements ResourceInterface, \Serializable +class DirectoryResource implements SelfCheckingResourceInterface, \Serializable { private $resource; private $pattern; diff --git a/src/Symfony/Component/Config/Resource/FileExistenceResource.php b/src/Symfony/Component/Config/Resource/FileExistenceResource.php index 4e68e8ac105be..ba1584638186b 100644 --- a/src/Symfony/Component/Config/Resource/FileExistenceResource.php +++ b/src/Symfony/Component/Config/Resource/FileExistenceResource.php @@ -19,7 +19,7 @@ * * @author Charles-Henri Bruyand */ -class FileExistenceResource implements ResourceInterface, \Serializable +class FileExistenceResource implements SelfCheckingResourceInterface, \Serializable { private $resource; diff --git a/src/Symfony/Component/Config/Resource/FileResource.php b/src/Symfony/Component/Config/Resource/FileResource.php index 4c00ae4140abc..bd0ce03eafe80 100644 --- a/src/Symfony/Component/Config/Resource/FileResource.php +++ b/src/Symfony/Component/Config/Resource/FileResource.php @@ -18,7 +18,7 @@ * * @author Fabien Potencier */ -class FileResource implements ResourceInterface, \Serializable +class FileResource implements SelfCheckingResourceInterface, \Serializable { /** * @var string|false diff --git a/src/Symfony/Component/Config/Resource/ResourceInterface.php b/src/Symfony/Component/Config/Resource/ResourceInterface.php index 2a6d16dd782c3..c0f0e50e0688e 100644 --- a/src/Symfony/Component/Config/Resource/ResourceInterface.php +++ b/src/Symfony/Component/Config/Resource/ResourceInterface.php @@ -37,6 +37,9 @@ public function __toString(); * @param int $timestamp The last time the resource was loaded * * @return bool True if the resource has not been updated, false otherwise + * + * @deprecated since 2.8, to be removed in 3.0. If your resource can check itself for + * freshness implement the SelfCheckingResourceInterface instead. */ public function isFresh($timestamp); diff --git a/src/Symfony/Component/Config/Resource/ResourceValidator.php b/src/Symfony/Component/Config/Resource/ResourceValidator.php deleted file mode 100644 index 62dc402e7c74a..0000000000000 --- a/src/Symfony/Component/Config/Resource/ResourceValidator.php +++ /dev/null @@ -1,32 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Resource; - -use Symfony\Component\Config\MetadataValidatorInterface; - -/** - * Validator for metadata implementing the ResourceInterface. - * - * @author Benjamin Klotz - */ -class ResourceValidator implements MetadataValidatorInterface -{ - public function supports($metadata) - { - return $metadata instanceof ResourceInterface; - } - - public function isFresh($metadata, $timestamp) - { - return $metadata->isFresh($timestamp); - } -} diff --git a/src/Symfony/Component/Config/Resource/SelfCheckingResourceInterface.php b/src/Symfony/Component/Config/Resource/SelfCheckingResourceInterface.php new file mode 100644 index 0000000000000..b3260f2be3e58 --- /dev/null +++ b/src/Symfony/Component/Config/Resource/SelfCheckingResourceInterface.php @@ -0,0 +1,30 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Component\Config\Resource; + +/** + * Interface for Resources that can check for freshness autonomously, + * without special support from external services. + * + * @author Matthias Pigulla + */ +interface SelfCheckingResourceInterface extends ResourceInterface +{ + /** + * Returns true if the resource has not been updated since the given timestamp. + * + * @param int $timestamp The last time the resource was loaded + * + * @return bool True if the resource has not been updated, false otherwise + */ + public function isFresh($timestamp); +} diff --git a/src/Symfony/Component/Config/ValidatorConfigCache.php b/src/Symfony/Component/Config/ResourceCheckerConfigCache.php similarity index 63% rename from src/Symfony/Component/Config/ValidatorConfigCache.php rename to src/Symfony/Component/Config/ResourceCheckerConfigCache.php index 4c5be87778513..7ae31fa25535e 100644 --- a/src/Symfony/Component/Config/ValidatorConfigCache.php +++ b/src/Symfony/Component/Config/ResourceCheckerConfigCache.php @@ -11,16 +11,17 @@ namespace Symfony\Component\Config; +use Symfony\Component\Config\Resource\ResourceInterface; use Symfony\Component\Filesystem\Exception\IOException; use Symfony\Component\Filesystem\Filesystem; /** - * ValidatorConfigCache uses instances of MetadataValidatorInterface + * ResourceCheckerConfigCache uses instances of ResourceCheckerInterface * to check whether cached data is still fresh. * * @author Matthias Pigulla */ -class ValidatorConfigCache implements ConfigCacheInterface +class ResourceCheckerConfigCache implements ConfigCacheInterface { /** * @var string @@ -28,18 +29,18 @@ class ValidatorConfigCache implements ConfigCacheInterface private $file; /** - * @var MetadataValidatorInterface[] + * @var ResourceCheckerInterface[] */ - private $validators; + private $resourceCheckers; /** - * @param string $file The absolute cache path - * @param MetadataValidatorInterface[] $validators The MetadataValidators to use for the freshness check + * @param string $file The absolute cache path + * @param ResourceCheckerInterface[] $resourceCheckers The ResourceCheckers to use for the freshness check */ - public function __construct($file, array $validators = array()) + public function __construct($file, array $resourceCheckers = array()) { $this->file = $file; - $this->validators = $validators; + $this->resourceCheckers = $resourceCheckers; } /** @@ -53,11 +54,11 @@ public function getPath() /** * Checks if the cache is still fresh. * - * This implementation will make a decision solely based on the MetadataValidators + * This implementation will make a decision solely based on the ResourceCheckers * passed in the constructor. * - * The first MetadataValidator that supports a given resource is considered authoritative. - * Resources with no matching MetadataValidators will silently be ignored and considered fresh. + * The first ResourceChecker that supports a given resource is considered authoritative. + * Resources with no matching ResourceChecker will silently be ignored and considered fresh. * * @return bool true if the cache is fresh, false otherwise */ @@ -67,8 +68,8 @@ public function isFresh() return false; } - if (!$this->validators) { - return true; // shortcut - if we don't have any validators we don't need to bother with the meta file at all + if (!$this->resourceCheckers) { + return true; // shortcut - if we don't have any checkers we don't need to bother with the meta file at all } $metadata = $this->getMetaFile(); @@ -80,17 +81,18 @@ public function isFresh() $meta = unserialize(file_get_contents($metadata)); foreach ($meta as $resource) { - foreach ($this->validators as $validator) { - if (!$validator->supports($resource)) { - continue; // next validator + /** @var ResourceInterface $resource */ + foreach ($this->resourceCheckers as $checker) { + if (!$checker->supports($resource)) { + continue; // next checker } - if ($validator->isFresh($resource, $time)) { + if ($checker->isFresh($resource, $time)) { break; // no need to further check this resource } return false; // cache is stale } - // no suitable validator found, ignore this resource + // no suitable checker found, ignore this resource } return true; @@ -99,8 +101,8 @@ public function isFresh() /** * Writes cache. * - * @param string $content The content to write in the cache - * @param array $metadata An array of metadata + * @param string $content The content to write in the cache + * @param ResourceInterface[] $metadata An array of metadata * * @throws \RuntimeException When cache file can't be written */ @@ -133,6 +135,6 @@ public function write($content, array $metadata = null) */ private function getMetaFile() { - return $this->file.'.meta'; + return $this->file . '.meta'; } } diff --git a/src/Symfony/Component/Config/ValidatorConfigCacheFactory.php b/src/Symfony/Component/Config/ResourceCheckerConfigCacheFactory.php similarity index 63% rename from src/Symfony/Component/Config/ValidatorConfigCacheFactory.php rename to src/Symfony/Component/Config/ResourceCheckerConfigCacheFactory.php index 60556c38afc57..c9fd7c1bec13b 100644 --- a/src/Symfony/Component/Config/ValidatorConfigCacheFactory.php +++ b/src/Symfony/Component/Config/ResourceCheckerConfigCacheFactory.php @@ -13,28 +13,23 @@ /** * A ConfigCacheFactory implementation that validates the - * cache with an arbitrary set of metadata validators. + * cache with an arbitrary set of ResourceCheckers. * * @author Matthias Pigulla */ -class ValidatorConfigCacheFactory implements ConfigCacheFactoryInterface +class ResourceCheckerConfigCacheFactory implements ConfigCacheFactoryInterface { /** - * @var bool + * @var ResourceCheckerInterface[] */ - private $debug; + private $resourceCheckers = array(); /** - * @var MetadataValidatorInterface[] + * @param ResourceCheckerInterface[] $resourceCheckers */ - private $validators = array(); - - /** - * @param MetadataValidatorInterface $validator - */ - public function addValidator(MetadataValidatorInterface $validator) + public function setResourceCheckers(array $resourceCheckers) { - $this->validators[] = $validator; + $this->resourceCheckers = $resourceCheckers; } /** @@ -46,7 +41,7 @@ public function cache($file, $callback) throw new \InvalidArgumentException(sprintf('Invalid type for callback argument. Expected callable, but got "%s".', gettype($callback))); } - $cache = new ValidatorConfigCache($file, $this->validators); + $cache = new ResourceCheckerConfigCache($file, $this->resourceCheckers); if (!$cache->isFresh()) { call_user_func($callback, $cache); } diff --git a/src/Symfony/Component/Config/MetadataValidatorInterface.php b/src/Symfony/Component/Config/ResourceCheckerInterface.php similarity index 53% rename from src/Symfony/Component/Config/MetadataValidatorInterface.php rename to src/Symfony/Component/Config/ResourceCheckerInterface.php index d3620f65ddee9..5bffc437c92a6 100644 --- a/src/Symfony/Component/Config/MetadataValidatorInterface.php +++ b/src/Symfony/Component/Config/ResourceCheckerInterface.php @@ -11,27 +11,30 @@ namespace Symfony\Component\Config; +use Symfony\Component\Config\Resource\ResourceInterface; + /** - * Interface for MetadataValidators. + * Interface for ResourceCheckers. * - * When a ConfigCache instance is checked for freshness, all its associated - * metadata resources are passed to MetadataValidators. The MetadataValidators + * When a ResourceCheckerConfigCache instance is checked for freshness, all its associated + * metadata resources are passed to ResourceCheckers. The ResourceCheckers * can then inspect the resources and decide whether the cache can be considered * fresh or not. * + * @author Matthias Pigulla * @author Benjamin Klotz */ -interface MetadataValidatorInterface +interface ResourceCheckerInterface { /** - * Queries the MetadataValidator whether it can validate a given + * Queries the ResourceChecker whether it can validate a given * resource or not. * - * @param object $metadata The resource to be checked for freshness + * @param ResourceInterface $metadata The resource to be checked for freshness * - * @return bool True if the MetadataValidator can handle this resource type, false if not + * @return bool True if the ResourceChecker can handle this resource type, false if not */ - public function supports($metadata); + public function supports(ResourceInterface $metadata); /** * Validates the resource. @@ -41,6 +44,6 @@ public function supports($metadata); * * @return bool True if the resource has not changed since the given timestamp, false otherwise. */ - public function isFresh($metadata, $timestamp); + public function isFresh(ResourceInterface $metadata, $timestamp); } diff --git a/src/Symfony/Component/Config/Tests/Resource/ResourceStub.php b/src/Symfony/Component/Config/Tests/Resource/ResourceStub.php index 4cfd14a6dc866..be790db17124d 100644 --- a/src/Symfony/Component/Config/Tests/Resource/ResourceStub.php +++ b/src/Symfony/Component/Config/Tests/Resource/ResourceStub.php @@ -2,9 +2,9 @@ namespace Symfony\Component\Config\Tests\Resource; -use Symfony\Component\Config\Resource\ResourceInterface; +use Symfony\Component\Config\Resource\SelfCheckingResourceInterface; -class ResourceStub implements ResourceInterface +class ResourceStub implements SelfCheckingResourceInterface { private $fresh = true; diff --git a/src/Symfony/Component/Config/Tests/Resource/ResourceValidatorTest.php b/src/Symfony/Component/Config/Tests/Resource/ResourceValidatorTest.php deleted file mode 100644 index 4ad8e03fca81b..0000000000000 --- a/src/Symfony/Component/Config/Tests/Resource/ResourceValidatorTest.php +++ /dev/null @@ -1,56 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Symfony\Component\Config\Tests\Resource; - -use Symfony\Component\Config\Resource\ResourceValidator; - -class ResourceValidatorTest extends \PHPUnit_Framework_TestCase -{ - protected $validator; - protected $metadataMock; - protected $timestamp; - - public function setUp() - { - $this->timestamp = 10; - $this->validator = new ResourceValidator(); - $this->metadataMock = $this->getMock('\Symfony\Component\Config\Resource\ResourceInterface'); - } - - public function testSupportsResourceInterface() - { - $this->assertTrue($this->validator->supports($this->metadataMock), '->supports($metadata) returns true if $metadata implements ResourceInterface'); - $this->assertFalse($this->validator->supports(new \StdClass()), '->supports($metadata) returns false if $metadata does not implement ResourceInterface'); - } - - /** - * @dataProvider testIsFreshDataProvider - */ - public function testIsFresh($result) - { - $this->metadataMock - ->expects($this->once()) - ->method('isFresh') - ->with($this->equalTo($this->timestamp)) - ->will($this->returnValue($result)); - $this->assertEquals($result, $this->validator->isFresh($this->metadataMock, $this->timestamp), '->isFresh($metadata) returns the same as $metadata->isFresh().'); - } - - public function testIsFreshDataProvider() - { - return array( - array(true), - array(false), - ); - } - -} diff --git a/src/Symfony/Component/Config/Tests/ValidatorConfigCacheTest.php b/src/Symfony/Component/Config/Tests/ResourceCheckerConfigCacheTest.php similarity index 60% rename from src/Symfony/Component/Config/Tests/ValidatorConfigCacheTest.php rename to src/Symfony/Component/Config/Tests/ResourceCheckerConfigCacheTest.php index 030e1bfdf056e..6a915ffed724a 100644 --- a/src/Symfony/Component/Config/Tests/ValidatorConfigCacheTest.php +++ b/src/Symfony/Component/Config/Tests/ResourceCheckerConfigCacheTest.php @@ -12,9 +12,9 @@ namespace Symfony\Component\Config\Tests; use Symfony\Component\Config\Tests\Resource\ResourceStub; -use Symfony\Component\Config\ValidatorConfigCache; +use Symfony\Component\Config\ResourceCheckerConfigCache; -class ValidatorConfigCacheTest extends \PHPUnit_Framework_TestCase +class ResourceCheckerConfigCacheTest extends \PHPUnit_Framework_TestCase { private $cacheFile = null; @@ -36,73 +36,73 @@ protected function tearDown() public function testGetPath() { - $cache = new ValidatorConfigCache($this->cacheFile); + $cache = new ResourceCheckerConfigCache($this->cacheFile); $this->assertSame($this->cacheFile, $cache->getPath()); } public function testCacheIsNotFreshIfEmpty() { - $validator = $this->getMock('\Symfony\Component\Config\MetadataValidatorInterface') + $checker = $this->getMock('\Symfony\Component\Config\ResourceCheckerInterface') ->expects($this->never())->method('supports'); /* If there is nothing in the cache, it needs to be filled (and thus it's not fresh). - It does not matter if you provide validators or not. */ + It does not matter if you provide checkers or not. */ unlink($this->cacheFile); // remove tempnam() side effect - $cache = new ValidatorConfigCache($this->cacheFile, array($validator)); + $cache = new ResourceCheckerConfigCache($this->cacheFile, array($checker)); $this->assertFalse($cache->isFresh()); } - public function testCacheIsFreshIfNoValidatorProvided() + public function testCacheIsFreshIfNocheckerProvided() { - /* For example in prod mode, you may choose not to run any validators + /* For example in prod mode, you may choose not to run any checkers at all. In that case, the cache should always be considered fresh. */ - $cache = new ValidatorConfigCache($this->cacheFile); + $cache = new ResourceCheckerConfigCache($this->cacheFile); $this->assertTrue($cache->isFresh()); } - public function testResourcesWithoutValidatorsAreIgnoredAndConsideredFresh() + public function testResourcesWithoutcheckersAreIgnoredAndConsideredFresh() { /* As in the previous test, but this time we have a resource. */ - $cache = new ValidatorConfigCache($this->cacheFile); + $cache = new ResourceCheckerConfigCache($this->cacheFile); $cache->write('', array(new ResourceStub())); - $this->assertTrue($cache->isFresh()); // no (matching) MetadataValidator passed + $this->assertTrue($cache->isFresh()); // no (matching) ResourceChecker passed } - public function testIsFreshWithValidator() + public function testIsFreshWithchecker() { - $validator = $this->getMock('\Symfony\Component\Config\MetadataValidatorInterface'); + $checker = $this->getMock('\Symfony\Component\Config\ResourceCheckerInterface'); - $validator->expects($this->once()) + $checker->expects($this->once()) ->method('supports') ->willReturn(true); - $validator->expects($this->once()) + $checker->expects($this->once()) ->method('isFresh') ->willReturn(true); - $cache = new ValidatorConfigCache($this->cacheFile, array($validator)); + $cache = new ResourceCheckerConfigCache($this->cacheFile, array($checker)); $cache->write('', array(new ResourceStub())); $this->assertTrue($cache->isFresh()); } - public function testIsNotFreshWithValidator() + public function testIsNotFreshWithchecker() { - $validator = $this->getMock('\Symfony\Component\Config\MetadataValidatorInterface'); + $checker = $this->getMock('\Symfony\Component\Config\ResourceCheckerInterface'); - $validator->expects($this->once()) + $checker->expects($this->once()) ->method('supports') ->willReturn(true); - $validator->expects($this->once()) + $checker->expects($this->once()) ->method('isFresh') ->willReturn(false); - $cache = new ValidatorConfigCache($this->cacheFile, array($validator)); + $cache = new ResourceCheckerConfigCache($this->cacheFile, array($checker)); $cache->write('', array(new ResourceStub())); $this->assertFalse($cache->isFresh()); @@ -110,7 +110,7 @@ public function testIsNotFreshWithValidator() public function testCacheKeepsContent() { - $cache = new ValidatorConfigCache($this->cacheFile); + $cache = new ResourceCheckerConfigCache($this->cacheFile); $cache->write('FOOBAR'); $this->assertSame('FOOBAR', file_get_contents($cache->getPath())); diff --git a/src/Symfony/Component/HttpKernel/Config/EnvParametersResource.php b/src/Symfony/Component/HttpKernel/Config/EnvParametersResource.php index 5f54450137a71..b4178a50ee3e2 100644 --- a/src/Symfony/Component/HttpKernel/Config/EnvParametersResource.php +++ b/src/Symfony/Component/HttpKernel/Config/EnvParametersResource.php @@ -11,14 +11,14 @@ namespace Symfony\Component\HttpKernel\Config; -use Symfony\Component\Config\Resource\ResourceInterface; +use Symfony\Component\Config\Resource\SelfCheckingResourceInterface; /** * EnvParametersResource represents resources stored in prefixed environment variables. * * @author Chris Wilkinson */ -class EnvParametersResource implements ResourceInterface, \Serializable +class EnvParametersResource implements SelfCheckingResourceInterface, \Serializable { /** * @var string diff --git a/src/Symfony/Component/Translation/Tests/TranslatorCacheTest.php b/src/Symfony/Component/Translation/Tests/TranslatorCacheTest.php index abe364c7368c7..54b219d0f7e72 100644 --- a/src/Symfony/Component/Translation/Tests/TranslatorCacheTest.php +++ b/src/Symfony/Component/Translation/Tests/TranslatorCacheTest.php @@ -281,7 +281,7 @@ private function createFailingLoader() } } -class StaleResource implements ResourceInterface +class StaleResource implements SelfCheckingResourceInterface { public function isFresh($timestamp) {