From 722709c4322a22ef110236817d3d271a41a24a3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julien=20Fastr=C3=A9?= Date: Thu, 5 Feb 2015 16:15:15 +0100 Subject: [PATCH] check config of available language check that the configuration is consistent with fallback locale : the fallback locale must be comprised in chill_main.available_languages. +tests refs #332 --- ChillMainBundle.php | 2 + .../ConfigConsistencyCompilerPass.php | 61 ++++++ .../ConfigConsistencyCompilerPassTest.php | 179 ++++++++++++++++++ 3 files changed, 242 insertions(+) create mode 100644 DependencyInjection/ConfigConsistencyCompilerPass.php create mode 100644 Tests/DependencyInjection/ConfigConsistencyCompilerPassTest.php diff --git a/ChillMainBundle.php b/ChillMainBundle.php index ba3afd7af..bb4c675a7 100644 --- a/ChillMainBundle.php +++ b/ChillMainBundle.php @@ -5,6 +5,7 @@ namespace Chill\MainBundle; use Symfony\Component\HttpKernel\Bundle\Bundle; use Symfony\Component\DependencyInjection\ContainerBuilder; use Chill\MainBundle\DependencyInjection\SearchableServicesCompilerPass; +use Chill\MainBundle\DependencyInjection\ConfigConsistencyCompilerPass; class ChillMainBundle extends Bundle { @@ -12,5 +13,6 @@ class ChillMainBundle extends Bundle { parent::build($container); $container->addCompilerPass(new SearchableServicesCompilerPass()); + $container->addCompilerPass(new ConfigConsistencyCompilerPass()); } } diff --git a/DependencyInjection/ConfigConsistencyCompilerPass.php b/DependencyInjection/ConfigConsistencyCompilerPass.php new file mode 100644 index 000000000..ba7e0052b --- /dev/null +++ b/DependencyInjection/ConfigConsistencyCompilerPass.php @@ -0,0 +1,61 @@ + + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +namespace Chill\MainBundle\DependencyInjection; + +use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; +use Symfony\Component\DependencyInjection\ContainerBuilder; + +/** + * Description of ConfigConsistencyCompilerPass + * + * @author Julien Fastré + */ +class ConfigConsistencyCompilerPass implements CompilerPassInterface +{ + public function process(ContainerBuilder $container) + { + $availableLanguages = $container + ->getParameter('chill_main.available_languages'); + $methodCallsTranslator = $container + ->findDefinition('translator.default') + ->getMethodCalls(); + + $fallbackLocales = array(); + foreach($methodCallsTranslator as $call) { + if ($call[0] === 'setFallbackLocales') { + $fallbackLocales = array_merge($fallbackLocales, + $call[1][0]); + } + } + + if (count($fallbackLocales) === 0) { + throw new \LogicException('the fallback locale are not defined. ' + . 'The framework config should not allow this.'); + } + + $diff = array_diff($fallbackLocales, $availableLanguages); + if (count($diff) > 0) { + throw new \RuntimeException(sprintf('The chill_main.available_languages' + . ' parameter does not contains fallback locales. The languages %s' + . ' are missing.', implode(', ', $diff))); + } + } +} diff --git a/Tests/DependencyInjection/ConfigConsistencyCompilerPassTest.php b/Tests/DependencyInjection/ConfigConsistencyCompilerPassTest.php new file mode 100644 index 000000000..bf0906266 --- /dev/null +++ b/Tests/DependencyInjection/ConfigConsistencyCompilerPassTest.php @@ -0,0 +1,179 @@ + + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see . + */ + +namespace Chill\MainBundle\Tests\DependencyInjection; + +use Chill\MainBundle\DependencyInjection\ConfigConsistencyCompilerPass; +use Symfony\Component\DependencyInjection\ContainerBuilderInterface; + +/** + * Description of ConfigConsistencyCompilerPassTest + * + * @author Julien Fastré + */ +class ConfigConsistencyCompilerPassTest extends \PHPUnit_Framework_TestCase +{ + + /** + * + * + * @var \Chill\MainBundle\DependencyInjection\ConfigConsistencyCompilerPass + */ + private $configConsistencyCompilerPass; + + public function setUp() + { + $this->configConsistencyCompilerPass = new ConfigConsistencyCompilerPass(); + } + + /** + * Test that everything is fine is configuration is correct + * + */ + public function testLanguagesArePresent() + { + try { + $this ->configConsistencyCompilerPass + ->process( + $this->mockContainer( + $this->mockTranslatorDefinition(array('fr')), + array('fr', 'nl') + ) + ); + $this->assertTrue(TRUE, 'the config consistency can process'); + } catch (\Exception $ex) { + $this->assertTrue(FALSE, + 'the config consistency can process'); + } + } + + /** + * Test that everything is fine is configuration is correct + * if multiple fallback languages are present + * + */ + public function testMultiplesLanguagesArePresent() + { + try { + $this ->configConsistencyCompilerPass + ->process( + $this->mockContainer( + $this->mockTranslatorDefinition(array('fr', 'nl')), + array('fr', 'nl', 'en') + ) + ); + $this->assertTrue(TRUE, 'the config consistency can process'); + } catch (\Exception $ex) { + $this->assertTrue(FALSE, + 'the config consistency can process'); + } + } + + + + /** + * Test that a runtime exception is throw if the available language does + * not contains the fallback locale + * + * @expectedException \RuntimeException + * @expectedExceptionMessageRegExp /The chill_main.available_languages parameter does not contains fallback locales./ + */ + public function testLanguageNotPresent() + { + $container = $this->mockContainer( + $this->mockTranslatorDefinition(array('en')), array('fr') + ); + + $this->configConsistencyCompilerPass->process($container); + } + + /** + * Test that a logic exception is thrown if the setFallbackLocale + * method is not defined in translator definition + * + * @expectedException \LogicException + */ + public function testSetFallbackNotDefined() + { + $container = $this->mockContainer( + $this->mockTranslatorDefinition(NULL), array('fr') + ); + $this->configConsistencyCompilerPass->process($container); + } + + /** + * @return ContainerBuilder + */ + private function mockContainer($definition, $availableLanguages) + { + $container = $this + ->getMockBuilder('Symfony\Component\DependencyInjection\ContainerBuilder') + ->getMock(); + + $container->method('getParameter') + ->will($this->returnCallback( + function($parameter) use ($availableLanguages) { + if ($parameter === 'chill_main.available_languages') { + return $availableLanguages; + } else { + throw new \LogicException("the parameter '$parameter' " + . "is not defined in stub test"); + } + } + )); + + $container->method('findDefinition') + ->will($this->returnCallback( + function($id) use ($definition) { + if (in_array($id, array('translator', 'translator.default'))) { + return $definition; + } else { + throw new \LogicException("the id $id is not defined in test"); + } + })); + + + return $container; + } + + /** + * + * @param type $languages + * @return 'Symfony\Component\DependencyInjection\Definition' + */ + private function mockTranslatorDefinition(array $languages = NULL) + { + $definition = $this + ->getMockBuilder('Symfony\Component\DependencyInjection\Definition') + ->getMock(); + + if (NULL !== $languages) { + $definition->method('getMethodCalls') + ->willReturn(array( + ['setFallbackLocales', array($languages)] + )); + } else { + $definition->method('getMethodCalls') + ->willReturn(array(['nothing', array()])); + } + + return $definition; + } +}