From 7b013a91b7a468442a416ca39dc03d5565adf155 Mon Sep 17 00:00:00 2001 From: Olivier Dolbeau Date: Fri, 29 Nov 2019 17:13:29 +0100 Subject: [PATCH] Deal with Translator interface coming from component (3.4) & contracts (5.0) --- .../Translator/EditInPlaceTranslatorTest.php | 19 +++++++++- .../Translator/FallbackTranslatorTest.php | 18 +++++++++- Translator/EditInPlaceTranslator.php | 23 +++++++++--- Translator/FallbackTranslator.php | 24 ++++++++++--- Translator/TranslatorInterface.php | 35 +++++++++++++++++++ phpstan.neon.dist | 4 +++ 6 files changed, 113 insertions(+), 10 deletions(-) create mode 100644 Translator/TranslatorInterface.php diff --git a/Tests/Unit/Translator/EditInPlaceTranslatorTest.php b/Tests/Unit/Translator/EditInPlaceTranslatorTest.php index a8db5274..4c77f46a 100644 --- a/Tests/Unit/Translator/EditInPlaceTranslatorTest.php +++ b/Tests/Unit/Translator/EditInPlaceTranslatorTest.php @@ -15,15 +15,32 @@ use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\Translation\Loader\ArrayLoader; -use Symfony\Component\Translation\TranslatorInterface; +use Symfony\Contracts\Translation\TranslatorInterface as NewTranslatorInterface; use Translation\Bundle\EditInPlace\ActivatorInterface; use Translation\Bundle\Translator\EditInPlaceTranslator; +use Translation\Bundle\Translator\TranslatorInterface; /** * @author Damien Alexandre */ final class EditInPlaceTranslatorTest extends TestCase { + public function testWithNotLocaleAwareTranslator() + { + if (!\interface_exists(NewTranslatorInterface::class)) { + $this->markTestSkipped('Relevant only when NewTranslatorInterface is available.'); + } + + $symfonyTranslator = $this->getMockBuilder(NewTranslatorInterface::class)->getMock(); + $activator = new FakeActivator(true); + $requestStack = new RequestStack(); + + $this->expectException(\InvalidArgumentException::class); + $this->expectExceptionMessage('The given translator must implements LocaleAwareInterface.'); + + new EditInPlaceTranslator($symfonyTranslator, $activator, $requestStack); + } + public function testEnabled(): void { $symfonyTranslator = $this->getMockBuilder(TranslatorInterface::class)->getMock(); diff --git a/Tests/Unit/Translator/FallbackTranslatorTest.php b/Tests/Unit/Translator/FallbackTranslatorTest.php index 36becf52..2620c3a7 100644 --- a/Tests/Unit/Translator/FallbackTranslatorTest.php +++ b/Tests/Unit/Translator/FallbackTranslatorTest.php @@ -13,8 +13,9 @@ use Nyholm\NSA; use PHPUnit\Framework\TestCase; -use Symfony\Component\Translation\TranslatorInterface; +use Symfony\Contracts\Translation\TranslatorInterface as NewTranslatorInterface; use Translation\Bundle\Translator\FallbackTranslator; +use Translation\Bundle\Translator\TranslatorInterface; use Translation\Translator\Translator; use Translation\Translator\TranslatorService; @@ -23,6 +24,21 @@ */ final class FallbackTranslatorTest extends TestCase { + public function testWithNotLocaleAwareTranslator() + { + if (!\interface_exists(NewTranslatorInterface::class)) { + $this->markTestSkipped('Relevant only when NewTranslatorInterface is available.'); + } + + $symfonyTranslator = $this->getMockBuilder(NewTranslatorInterface::class)->getMock(); + $translator = new Translator(); + + $this->expectException(\InvalidArgumentException::class); + $this->expectExceptionMessage('The given translator must implements LocaleAwareInterface.'); + + new FallbackTranslator('en', $symfonyTranslator, $translator); + } + public function testTranslateWithSubstitutedParameters(): void { $symfonyTranslator = $this->getMockBuilder(TranslatorInterface::class)->getMock(); diff --git a/Translator/EditInPlaceTranslator.php b/Translator/EditInPlaceTranslator.php index 62cd8467..1d94e95e 100644 --- a/Translator/EditInPlaceTranslator.php +++ b/Translator/EditInPlaceTranslator.php @@ -14,7 +14,9 @@ use Symfony\Component\HttpFoundation\RequestStack; use Symfony\Component\Translation\MessageCatalogueInterface; use Symfony\Component\Translation\TranslatorBagInterface; -use Symfony\Component\Translation\TranslatorInterface; +use Symfony\Component\Translation\TranslatorInterface as LegacyTranslatorInterface; +use Symfony\Contracts\Translation\LocaleAwareInterface; +use Symfony\Contracts\Translation\TranslatorInterface as NewTranslatorInterface; use Translation\Bundle\EditInPlace\ActivatorInterface; /** @@ -22,10 +24,10 @@ * * @author Damien Alexandre */ -final class EditInPlaceTranslator implements TranslatorInterface, TranslatorBagInterface +final class EditInPlaceTranslator implements TranslatorInterface { /** - * @var TranslatorInterface|TranslatorBagInterface + * @var LegacyTranslatorInterface|NewTranslatorInterface */ private $translator; @@ -39,8 +41,21 @@ final class EditInPlaceTranslator implements TranslatorInterface, TranslatorBagI */ private $requestStack; - public function __construct(TranslatorInterface $translator, ActivatorInterface $activator, RequestStack $requestStack) + /** + * $translator param can't be type hinted as we have to deal with both LegacyTranslatorInterface & NewTranslatorInterface. + * Once we won't support sf ^3.4 anymore, we will be able to type hint $translator with NewTranslatorInterface. + * + * @param LegacyTranslatorInterface|NewTranslatorInterface $translator + */ + public function __construct($translator, ActivatorInterface $activator, RequestStack $requestStack) { + if (!$translator instanceof LegacyTranslatorInterface && !$translator instanceof LocaleAwareInterface) { + throw new \InvalidArgumentException('The given translator must implements LocaleAwareInterface.'); + } + if (!$translator instanceof TranslatorBagInterface) { + throw new \InvalidArgumentException('The given translator must implements TranslatorBagInterface.'); + } + $this->translator = $translator; $this->activator = $activator; $this->requestStack = $requestStack; diff --git a/Translator/FallbackTranslator.php b/Translator/FallbackTranslator.php index 2c3793d1..9b53a74f 100644 --- a/Translator/FallbackTranslator.php +++ b/Translator/FallbackTranslator.php @@ -13,7 +13,9 @@ use Symfony\Component\Translation\MessageCatalogueInterface; use Symfony\Component\Translation\TranslatorBagInterface; -use Symfony\Component\Translation\TranslatorInterface; +use Symfony\Component\Translation\TranslatorInterface as LegacyTranslatorInterface; +use Symfony\Contracts\Translation\LocaleAwareInterface; +use Symfony\Contracts\Translation\TranslatorInterface as NewTranslatorInterface; use Translation\Translator\Translator; /** @@ -21,10 +23,10 @@ * * @author Tobias Nyholm */ -final class FallbackTranslator implements TranslatorInterface, TranslatorBagInterface +final class FallbackTranslator implements TranslatorInterface { /** - * @var TranslatorInterface|TranslatorBagInterface + * @var LegacyTranslatorInterface|NewTranslatorInterface */ private $symfonyTranslator; @@ -38,8 +40,22 @@ final class FallbackTranslator implements TranslatorInterface, TranslatorBagInte */ private $defaultLocale; - public function __construct(string $defaultLocale, TranslatorInterface $symfonyTranslator, Translator $externalTranslator) + /** + * $symfonyTranslator param can't be type hinted as we have to deal with both LegacyTranslatorInterface & NewTranslatorInterface. + * Once we won't support sf ^3.4 anymore, we will be able to type hint $symfonyTranslator with NewTranslatorInterface. + * + * @param LegacyTranslatorInterface|NewTranslatorInterface $symfonyTranslator + */ + public function __construct(string $defaultLocale, $symfonyTranslator, Translator $externalTranslator) { + if (!$symfonyTranslator instanceof LegacyTranslatorInterface && !$symfonyTranslator instanceof LocaleAwareInterface) { + throw new \InvalidArgumentException('The given translator must implements LocaleAwareInterface.'); + } + + if (!$symfonyTranslator instanceof TranslatorBagInterface) { + throw new \InvalidArgumentException('The given translator must implements TranslatorBagInterface.'); + } + $this->symfonyTranslator = $symfonyTranslator; $this->externalTranslator = $externalTranslator; $this->defaultLocale = $defaultLocale; diff --git a/Translator/TranslatorInterface.php b/Translator/TranslatorInterface.php new file mode 100644 index 00000000..e9bbdfd7 --- /dev/null +++ b/Translator/TranslatorInterface.php @@ -0,0 +1,35 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Translation\Bundle\Translator; + +use Symfony\Component\Translation\TranslatorBagInterface; +use Symfony\Component\Translation\TranslatorInterface as LegacyTranslatorInterface; +use Symfony\Contracts\Translation\LocaleAwareInterface; +use Symfony\Contracts\Translation\TranslatorInterface as NewTranslatorInterface; + +/* + * This interface is here to allow us to support both sf 3.x with + * LegacyTranslatorInterface & sf 5.x where this interface have been replaced + * by NewLocalAwareInterface. + * + * When sf 3.4 won't be supported anymore, this interface will become useless. + */ + +if (\interface_exists(NewTranslatorInterface::class)) { + interface TranslatorInterface extends NewTranslatorInterface, LocaleAwareInterface, TranslatorBagInterface + { + } +} else { + interface TranslatorInterface extends LegacyTranslatorInterface, TranslatorBagInterface + { + } +} diff --git a/phpstan.neon.dist b/phpstan.neon.dist index 2964a0af..f1aa2a34 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -39,3 +39,7 @@ parameters: - path: %currentWorkingDirectory%/DependencyInjection/Configuration.php message: '#Call to an undefined method Symfony\\Component\\Config\\Definition\\Builder\\TreeBuilder::root()#' + + - + path: %currentWorkingDirectory%/Translator + message: '#Call to an undefined method Symfony\\Component\\Translation\\TranslatorInterface|Symfony\\Contracts\\Translation\\TranslatorInterface::getCatalogue().#'