From c414046608485cb81232c097440f1e26317d9e15 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Filip=20Proch=C3=A1zka?= Date: Wed, 15 Jul 2015 03:44:55 +0200 Subject: [PATCH] Fixed fallback circular reference in CatalogueFactory --- composer.json | 3 +- src/Kdyby/Translation/CatalogueFactory.php | 11 ++- .../Translation/CatalogueFactory.phpt | 75 +++++++++++++++++++ 3 files changed, 86 insertions(+), 3 deletions(-) create mode 100644 tests/KdybyTests/Translation/CatalogueFactory.phpt diff --git a/composer.json b/composer.json index b4242304..f2a94b61 100644 --- a/composer.json +++ b/composer.json @@ -60,7 +60,8 @@ "tracy/tracy": "~2.3@dev", "symfony/console": "~2.3", - "nette/tester": "~1.4" + "nette/tester": "~1.4", + "mockery/mockery": "~0.9" }, "autoload": { "psr-0": { diff --git a/src/Kdyby/Translation/CatalogueFactory.php b/src/Kdyby/Translation/CatalogueFactory.php index 15cf6d1f..d8e1ea4b 100644 --- a/src/Kdyby/Translation/CatalogueFactory.php +++ b/src/Kdyby/Translation/CatalogueFactory.php @@ -95,13 +95,20 @@ public function createCatalogue(Translator $translator, array &$availableCatalog $current = $availableCatalogues[$locale]; + $chain = array($locale => TRUE); foreach ($this->fallbackResolver->compute($translator, $locale) as $fallback) { if (!isset($availableCatalogues[$fallback])) { $this->doLoadCatalogue($availableCatalogues, $fallback); } - $current->addFallbackCatalogue($availableCatalogues[$fallback]); - $current = $availableCatalogues[$fallback]; + $newFallback = $availableCatalogues[$fallback]; + if (($newFallbackFallback = $newFallback->getFallbackCatalogue()) && isset($chain[$newFallbackFallback->getLocale()])) { + break; + } + + $current->addFallbackCatalogue($newFallback); + $current = $newFallback; + $chain[$fallback] = TRUE; } return $availableCatalogues[$locale]; diff --git a/tests/KdybyTests/Translation/CatalogueFactory.phpt b/tests/KdybyTests/Translation/CatalogueFactory.phpt new file mode 100644 index 00000000..c9eef50e --- /dev/null +++ b/tests/KdybyTests/Translation/CatalogueFactory.phpt @@ -0,0 +1,75 @@ + + * @package Kdyby\Translation + */ + +namespace KdybyTests\Translation; + +use Kdyby; +use Kdyby\Translation\CatalogueFactory; +use Kdyby\Translation\FallbackResolver; +use Kdyby\Translation\TranslationLoader; +use Nette; +use Symfony; +use Tester; +use Tester\Assert; + +require_once __DIR__ . '/../bootstrap.php'; + + + +/** + * @author Filip Procházka + */ +class CatalogueFactoryTest extends TestCase +{ + + public function testCircularFallback() + { + $fallbacks = new FallbackResolver(); + $fallbacks->setFallbackLocales(array('cs_CZ', 'cs')); + + $loader = new TranslationLoader(); + $loader->addLoader('neon', new Kdyby\Translation\Loader\NeonFileLoader()); + + /** @var \Kdyby\Translation\Translator|\Mockery\MockInterface $translator */ + $translator = \Mockery::mock('Kdyby\Translation\Translator'); + $translator->shouldReceive('getAvailableLocales')->andReturn(array('cs_CZ', 'en_US')); + + $factory = new CatalogueFactory($fallbacks, $loader); + $factory->addResource('neon', __DIR__ . '/lang/front.cs_CZ.neon', 'cs_CZ', 'front'); + $factory->addResource('neon', __DIR__ . '/lang/front.en_US.neon', 'en_US', 'front'); + + /** @var Symfony\Component\Translation\MessageCatalogueInterface[] $catalogues */ + $catalogues = array(); + $factory->createCatalogue($translator, $catalogues, 'cs'); + Assert::truthy(isset($catalogues['cs'])); + Assert::truthy(isset($catalogues['cs_CZ'])); + + Assert::same($catalogues['cs_CZ'], $catalogues['cs']->getFallbackCatalogue()); + Assert::null($catalogues['cs_CZ']->getFallbackCatalogue()); + + $factory->createCatalogue($translator, $catalogues, 'en'); + + Assert::same($catalogues['en_US'], $catalogues['en']->getFallbackCatalogue()); + Assert::same($catalogues['cs_CZ'], $catalogues['en_US']->getFallbackCatalogue()); + + Assert::same($catalogues['cs_CZ'], $catalogues['cs']->getFallbackCatalogue()); + Assert::null($catalogues['cs_CZ']->getFallbackCatalogue()); + } + + + + protected function tearDown() + { + \Mockery::close(); + } + +} + +\run(new CatalogueFactoryTest());