From 7d8736db14ab81523883abe9b8e6e99aa5de4f56 Mon Sep 17 00:00:00 2001 From: Olivier Dolbeau Date: Sat, 7 Dec 2019 18:16:09 +0100 Subject: [PATCH 1/6] SF 5.x compatibility --- Controller/EditInPlaceController.php | 26 ++- Controller/SymfonyProfilerController.php | 36 ++-- Controller/WebUIController.php | 92 ++++++--- DependencyInjection/Configuration.php | 9 +- DependencyInjection/TranslationExtension.php | 11 +- EventListener/AutoAddMissingTranslations.php | 12 +- EventListener/EditInPlaceResponseListener.php | 10 +- Makefile | 13 ++ Model/Configuration.php | 2 +- Resources/config/controllers.yml | 25 +++ Resources/config/services.yml | 12 ++ Resources/config/symfony_profiler.yml | 8 + Service/CacheClearer.php | 12 +- Service/Importer.php | 2 +- Tests/Functional/BundleInitializationTest.php | 2 +- .../Functional/Command/ExtractCommandTest.php | 11 +- Tests/Functional/Command/SyncCommandTest.php | 2 +- .../app/Controller/TestController.php | 4 +- .../app/Resources/views/translated.html.twig | 4 +- .../translated.html.twig | 16 ++ Tests/Functional/app/config/framework.yml | 4 +- Tests/Functional/app/config/normal_config.yml | 10 +- Tests/Functional/app/config/parameters.php | 2 +- Tests/Functional/app/config/services.yml | 5 + .../TranslationExtensionTest.php | 2 +- Tests/Unit/Twig/BaseTwigTestCase.php | 3 +- .../Twig/Fixture/simple_template.html.twig | 8 +- .../simple_template_compiled.html.twig | 8 +- ...mplate_compiled_with_transchoice.html.twig | 21 ++ ...simple_template_with_transchoice.html.twig | 21 ++ Tests/Unit/Twig/RemovingNodeVisitorTest.php | 13 +- Twig/TranslationExtension.php | 12 +- composer.json | 6 +- phpstan-baseline.neon | 191 ++++++++++++++++++ phpstan.neon.dist | 34 +--- 35 files changed, 515 insertions(+), 134 deletions(-) create mode 100644 Makefile create mode 100644 Resources/config/controllers.yml create mode 100644 Tests/Functional/app/Resources/views_with_transchoice/translated.html.twig create mode 100644 Tests/Unit/Twig/Fixture/simple_template_compiled_with_transchoice.html.twig create mode 100644 Tests/Unit/Twig/Fixture/simple_template_with_transchoice.html.twig create mode 100644 phpstan-baseline.neon diff --git a/Controller/EditInPlaceController.php b/Controller/EditInPlaceController.php index 52650b27..4ee7abf7 100644 --- a/Controller/EditInPlaceController.php +++ b/Controller/EditInPlaceController.php @@ -11,10 +11,13 @@ namespace Translation\Bundle\Controller; -use Symfony\Bundle\FrameworkBundle\Controller\Controller; +use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\Validator\Validator\ValidatorInterface; use Translation\Bundle\Exception\MessageValidationException; +use Translation\Bundle\Service\CacheClearer; +use Translation\Bundle\Service\StorageManager; use Translation\Bundle\Service\StorageService; use Translation\Common\Model\Message; use Translation\Common\Model\MessageInterface; @@ -22,8 +25,19 @@ /** * @author Damien Alexandre */ -class EditInPlaceController extends Controller +class EditInPlaceController extends AbstractController { + private $storageManager; + private $cacheClearer; + private $validator; + + public function __construct(StorageManager $storageManager, CacheClearer $cacheClearer, ValidatorInterface $validator) + { + $this->storageManager = $storageManager; + $this->cacheClearer = $cacheClearer; + $this->validator = $validator; + } + public function editAction(Request $request, string $configName, string $locale): Response { try { @@ -33,13 +47,12 @@ public function editAction(Request $request, string $configName, string $locale) } /** @var StorageService $storage */ - $storage = $this->get('php_translation.storage_manager')->getStorage($configName); + $storage = $this->storageManager->getStorage($configName); foreach ($messages as $message) { $storage->update($message); } - $cacheClearer = $this->get('php_translation.cache_clearer'); - $cacheClearer->clearAndWarmUp($locale); + $this->cacheClearer->clearAndWarmUp($locale); return new Response(); } @@ -56,14 +69,13 @@ private function getMessages(Request $request, string $locale, array $validation $json = $request->getContent(); $data = \json_decode($json, true); $messages = []; - $validator = $this->get('validator'); foreach ($data as $key => $value) { [$domain, $translationKey] = \explode('|', $key); $message = new Message($translationKey, $domain, $locale, $value); - $errors = $validator->validate($message, null, $validationGroups); + $errors = $this->validator->validate($message, null, $validationGroups); if (\count($errors) > 0) { throw MessageValidationException::create(); } diff --git a/Controller/SymfonyProfilerController.php b/Controller/SymfonyProfilerController.php index 6eb87f14..da003f54 100644 --- a/Controller/SymfonyProfilerController.php +++ b/Controller/SymfonyProfilerController.php @@ -11,9 +11,10 @@ namespace Translation\Bundle\Controller; -use Symfony\Bundle\FrameworkBundle\Controller\Controller; +use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; +use Symfony\Component\HttpKernel\Profiler\Profiler; use Symfony\Component\Translation\DataCollectorTranslator; use Symfony\Component\VarDumper\Cloner\Data; use Translation\Bundle\Model\SfProfilerMessage; @@ -23,11 +24,22 @@ /** * @author Tobias Nyholm */ -class SymfonyProfilerController extends Controller +class SymfonyProfilerController extends AbstractController { + private $storage; + private $profiler; + private $isToolbarAllowEdit; + + public function __construct(StorageService $storage, Profiler $profiler, bool $isToolbarAllowEdit) + { + $this->storage = $storage; + $this->profiler = $profiler; + $this->isToolbarAllowEdit = $isToolbarAllowEdit; + } + public function editAction(Request $request, string $token): Response { - if (!$this->getParameter('php_translation.toolbar.allow_edit')) { + if (!$this->isToolbarAllowEdit) { return new Response('You are not allowed to edit the translations.'); } @@ -36,11 +48,9 @@ public function editAction(Request $request, string $token): Response } $message = $this->getMessage($request, $token); - /** @var StorageService $storage */ - $storage = $this->get('php_translation.storage'); if ($request->isMethod('GET')) { - $translation = $storage->syncAndFetchMessage($message->getLocale(), $message->getDomain(), $message->getKey()); + $translation = $this->storage->syncAndFetchMessage($message->getLocale(), $message->getDomain(), $message->getKey()); return $this->render('@Translation/SymfonyProfiler/edit.html.twig', [ 'message' => $translation, @@ -50,7 +60,7 @@ public function editAction(Request $request, string $token): Response //Assert: This is a POST request $message->setTranslation($request->request->get('translation')); - $storage->update($message->convertToMessage()); + $this->storage->update($message->convertToMessage()); return new Response($message->getTranslation()); } @@ -61,10 +71,8 @@ public function syncAction(Request $request, string $token): Response return $this->redirectToRoute('_profiler', ['token' => $token]); } - /** @var StorageService $storage */ - $storage = $this->get('php_translation.storage'); $sfMessage = $this->getMessage($request, $token); - $message = $storage->syncAndFetchMessage($sfMessage->getLocale(), $sfMessage->getDomain(), $sfMessage->getKey()); + $message = $this->storage->syncAndFetchMessage($sfMessage->getLocale(), $sfMessage->getDomain(), $sfMessage->getKey()); if (null !== $message) { return new Response($message->getTranslation()); @@ -82,9 +90,7 @@ public function syncAllAction(Request $request, string $token): Response return $this->redirectToRoute('_profiler', ['token' => $token]); } - /** @var StorageService $storage */ - $storage = $this->get('php_translation.storage'); - $storage->sync(); + $this->storage->sync(); return new Response('Started synchronization of all translations'); } @@ -106,10 +112,8 @@ public function createAssetsAction(Request $request, string $token): Response } $uploaded = []; - /** @var StorageService $storage */ - $storage = $this->get('php_translation.storage'); foreach ($messages as $message) { - $storage->create($message); + $this->storage->create($message); $uploaded[] = $message; } diff --git a/Controller/WebUIController.php b/Controller/WebUIController.php index 451da68c..80520514 100644 --- a/Controller/WebUIController.php +++ b/Controller/WebUIController.php @@ -11,15 +11,20 @@ namespace Translation\Bundle\Controller; -use Symfony\Bundle\FrameworkBundle\Controller\Controller; +use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Response; use Symfony\Component\HttpKernel\Exception\BadRequestHttpException; use Symfony\Component\Intl\Intl; use Symfony\Component\Intl\Locales; use Symfony\Component\Translation\MessageCatalogue; +use Symfony\Component\Validator\Validator\ValidatorInterface; +use Translation\Bundle\Catalogue\CatalogueFetcher; +use Translation\Bundle\Catalogue\CatalogueManager; use Translation\Bundle\Exception\MessageValidationException; use Translation\Bundle\Model\CatalogueMessage; +use Translation\Bundle\Service\ConfigurationManager; +use Translation\Bundle\Service\StorageManager; use Translation\Bundle\Service\StorageService; use Translation\Common\Exception\StorageException; use Translation\Common\Model\Message; @@ -28,21 +33,55 @@ /** * @author Tobias Nyholm */ -class WebUIController extends Controller +class WebUIController extends AbstractController { + private $configurationManager; + private $catalogueFetcher; + private $catalogueManager; + private $storageManager; + private $validator; + private $locales; + private $isWebUIEnabled; + private $isWebUIAllowCreate; + private $isWebUIAllowDelete; + private $fileBasePath; + + public function __construct( + ConfigurationManager $configurationManager, + CatalogueFetcher $catalogueFetcher, + CatalogueManager $catalogueManager, + StorageManager $storageManager, + ValidatorInterface $validator, + array $locales, + bool $isWebUIEnabled, + bool $isWebUIAllowCreate, + bool $isWebUIAllowDelete, + string $fileBasePath + ) { + $this->configurationManager = $configurationManager; + $this->catalogueFetcher = $catalogueFetcher; + $this->catalogueManager = $catalogueManager; + $this->storageManager = $storageManager; + $this->validator = $validator; + $this->locales = $locales; + $this->isWebUIEnabled = $isWebUIEnabled; + $this->isWebUIAllowCreate = $isWebUIAllowCreate; + $this->isWebUIAllowDelete = $isWebUIAllowDelete; + $this->fileBasePath = $fileBasePath; + } + /** * Show a dashboard for the configuration. */ public function indexAction(?string $configName = null): Response { - if (!$this->getParameter('php_translation.webui.enabled')) { + if (!$this->isWebUIEnabled) { return new Response('You are not allowed here. Check you config. ', 400); } - $configManager = $this->get('php_translation.configuration_manager'); - $config = $configManager->getConfiguration($configName); + $config = $this->configurationManager->getConfiguration($configName); $localeMap = $this->getLocale2LanguageMap(); - $catalogues = $this->get('php_translation.catalogue_fetcher')->getCatalogues($config); + $catalogues = $this->catalogueFetcher->getCatalogues($config); $catalogueSize = []; $maxDomainSize = []; @@ -75,7 +114,7 @@ public function indexAction(?string $configName = null): Response 'maxCatalogueSize' => $maxCatalogueSize, 'localeMap' => $localeMap, 'configName' => $config->getName(), - 'configNames' => $configManager->getNames(), + 'configNames' => $this->configurationManager->getNames(), ]); } @@ -84,44 +123,42 @@ public function indexAction(?string $configName = null): Response */ public function showAction(string $configName, string $locale, string $domain): Response { - if (!$this->getParameter('php_translation.webui.enabled')) { + if (!$this->isWebUIEnabled) { return new Response('You are not allowed here. Check you config. ', 400); } - $configManager = $this->get('php_translation.configuration_manager'); - $config = $configManager->getConfiguration($configName); + $config = $this->configurationManager->getConfiguration($configName); // Get a catalogue manager and load it with all the catalogues - $catalogueManager = $this->get('php_translation.catalogue_manager'); - $catalogueManager->load($this->get('php_translation.catalogue_fetcher')->getCatalogues($config)); + $this->catalogueManager->load($this->catalogueFetcher->getCatalogues($config)); /** @var CatalogueMessage[] $messages */ - $messages = $catalogueManager->getMessages($locale, $domain); + $messages = $this->catalogueManager->getMessages($locale, $domain); \usort($messages, function (CatalogueMessage $a, CatalogueMessage $b) { return \strcmp($a->getKey(), $b->getKey()); }); return $this->render('@Translation/WebUI/show.html.twig', [ 'messages' => $messages, - 'domains' => $catalogueManager->getDomains(), + 'domains' => $this->catalogueManager->getDomains(), 'currentDomain' => $domain, - 'locales' => $this->getParameter('php_translation.locales'), + 'locales' => $this->locales, 'currentLocale' => $locale, 'configName' => $config->getName(), - 'configNames' => $configManager->getNames(), - 'allow_create' => $this->getParameter('php_translation.webui.allow_create'), - 'allow_delete' => $this->getParameter('php_translation.webui.allow_delete'), - 'file_base_path' => $this->getParameter('php_translation.webui.file_base_path'), + 'configNames' => $this->configurationManager->getNames(), + 'allow_create' => $this->isWebUIAllowCreate, + 'allow_delete' => $this->isWebUIAllowDelete, + 'file_base_path' => $this->fileBasePath, ]); } public function createAction(Request $request, string $configName, string $locale, string $domain): Response { - if (!$this->getParameter('php_translation.webui.enabled') || !$this->getParameter('php_translation.webui.allow_create')) { + if (!$this->isWebUIEnabled || !$this->isWebUIAllowCreate) { return new Response('You are not allowed to create. Check you config. ', 400); } /** @var StorageService $storage */ - $storage = $this->get('php_translation.storage_manager')->getStorage($configName); + $storage = $this->storageManager->getStorage($configName); try { $message = $this->getMessageFromRequest($request); @@ -145,7 +182,7 @@ public function createAction(Request $request, string $configName, string $local public function editAction(Request $request, string $configName, string $locale, string $domain): Response { - if (!$this->getParameter('php_translation.webui.enabled')) { + if (!$this->isWebUIEnabled) { return new Response('You are not allowed here. Check you config. ', 400); } @@ -159,7 +196,7 @@ public function editAction(Request $request, string $configName, string $locale, } /** @var StorageService $storage */ - $storage = $this->get('php_translation.storage_manager')->getStorage($configName); + $storage = $this->storageManager->getStorage($configName); $storage->update($message); return new Response('Translation updated'); @@ -167,7 +204,7 @@ public function editAction(Request $request, string $configName, string $locale, public function deleteAction(Request $request, string $configName, string $locale, string $domain): Response { - if (!$this->getParameter('php_translation.webui.enabled') || !$this->getParameter('php_translation.webui.allow_delete')) { + if (!$this->isWebUIEnabled || !$this->isWebUIAllowDelete) { return new Response('You are not allowed to create. Check you config. ', 400); } @@ -181,7 +218,7 @@ public function deleteAction(Request $request, string $configName, string $local } /** @var StorageService $storage */ - $storage = $this->get('php_translation.storage_manager')->getStorage($configName); + $storage = $this->storageManager->getStorage($configName); $storage->delete($locale, $domain, $message->getKey()); return new Response('Message was deleted'); @@ -206,12 +243,11 @@ private function getMessageFromRequest(Request $request): Message */ private function getLocale2LanguageMap(): array { - $configuredLocales = $this->getParameter('php_translation.locales'); $names = \class_exists(Locales::class) ? Locales::getNames('en') : Intl::getLocaleBundle()->getLocaleNames('en'); $map = []; - foreach ($configuredLocales as $l) { + foreach ($this->locales as $l) { $map[$l] = $names[$l] ?? $l; } @@ -223,7 +259,7 @@ private function getLocale2LanguageMap(): array */ private function validateMessage(MessageInterface $message, array $validationGroups): void { - $errors = $this->get('validator')->validate($message, null, $validationGroups); + $errors = $this->validator->validate($message, null, $validationGroups); if (\count($errors) > 0) { throw MessageValidationException::create(); } diff --git a/DependencyInjection/Configuration.php b/DependencyInjection/Configuration.php index 69051f6d..3b97088c 100644 --- a/DependencyInjection/Configuration.php +++ b/DependencyInjection/Configuration.php @@ -46,7 +46,8 @@ public function getConfigTreeBuilder(): TreeBuilder $this->addEditInPlaceNode($root); $this->addWebUINode($root); - $debug = $this->container->getParameter('kernel.debug'); + $isProfilerEnabled = $this->container->getParameter('kernel.debug') && $this->container->has('profiler'); + $root ->children() ->arrayNode('locales') @@ -57,12 +58,12 @@ public function getConfigTreeBuilder(): TreeBuilder ->addDefaultsIfNotSet() ->treatFalseLike(['enabled' => false]) ->treatTrueLike(['enabled' => true]) - ->treatNullLike(['enabled' => $debug]) + ->treatNullLike(['enabled' => $isProfilerEnabled]) ->info('Extend the debug profiler with information about requests.') ->children() ->booleanNode('enabled') ->info('Turn the symfony profiler integration on or off. Defaults to kernel debug mode.') - ->defaultValue($debug) + ->defaultValue($isProfilerEnabled) ->end() ->scalarNode('formatter')->defaultNull()->end() ->integerNode('captured_body_length') @@ -159,7 +160,7 @@ private function configsNode(ArrayNodeDefinition $root): void ->info('Service ids with to classes that supports local storage of translations.') ->prototype('scalar')->end() ->end() - ->scalarNode('output_dir')->cannotBeEmpty()->defaultValue('%kernel.root_dir%/Resources/translations')->end() + ->scalarNode('output_dir')->cannotBeEmpty()->defaultValue('%kernel.project_dir%/Resources/translations')->end() ->scalarNode('project_root')->info("The root dir of your project. By default this will be kernel_root's parent.")->end() ->scalarNode('xliff_version')->info('The version of XLIFF XML you want to use (if dumping to this format).')->defaultValue('2.0')->end() ->variableNode('local_file_storage_options') diff --git a/DependencyInjection/TranslationExtension.php b/DependencyInjection/TranslationExtension.php index ec495013..9c82806b 100644 --- a/DependencyInjection/TranslationExtension.php +++ b/DependencyInjection/TranslationExtension.php @@ -22,6 +22,7 @@ use Symfony\Component\HttpKernel\DependencyInjection\Extension; use Symfony\Component\HttpKernel\Kernel; use Translation\Bundle\Model\Configuration as ConfigurationModel; +use Translation\Bundle\Service\StorageService; /** * This is the class that loads and manages your bundle configuration. @@ -83,6 +84,7 @@ public function load(array $configs, ContainerBuilder $container): void } $loader->load('console.yml'); + $loader->load('controllers.yml'); } /** @@ -100,7 +102,7 @@ private function handleConfigNode(ContainerBuilder $container, array $config): v } if (empty($c['project_root'])) { // Add a project root of none is set. - $c['project_root'] = \dirname($container->getParameter('kernel.root_dir')); + $c['project_root'] = \dirname($container->getParameter('kernel.project_dir')); } $c['name'] = $name; $c['locales'] = $config['locales']; @@ -141,6 +143,7 @@ private function handleConfigNode(ContainerBuilder $container, array $config): v if (null !== $first) { // Create some aliases for the default storage $container->setAlias('php_translation.storage', new Alias('php_translation.storage.'.$first, true)); + $container->setAlias(StorageService::class, new Alias('php_translation.storage', true)); if ('default' !== $first) { $container->setAlias('php_translation.storage.default', new Alias('php_translation.storage.'.$first, true)); } @@ -158,11 +161,7 @@ private function enableWebUi(ContainerBuilder $container, array $config): void $path = $config['webui']['file_base_path']; if (null === $path) { - if ($container->hasParameter('kernel.project_dir')) { - $path = $container->getParameter('kernel.project_dir'); - } else { - $path = $container->getParameter('kernel.root_dir').'/..'; - } + $path = $container->getParameter('kernel.project_dir'); } $container->setParameter('php_translation.webui.file_base_path', \rtrim($path, '/').'/'); diff --git a/EventListener/AutoAddMissingTranslations.php b/EventListener/AutoAddMissingTranslations.php index 2b58e536..7db959c8 100644 --- a/EventListener/AutoAddMissingTranslations.php +++ b/EventListener/AutoAddMissingTranslations.php @@ -11,7 +11,8 @@ namespace Translation\Bundle\EventListener; -use Symfony\Component\EventDispatcher\Event; +use Symfony\Component\HttpKernel\Event\PostResponseEvent; +use Symfony\Component\HttpKernel\Event\TerminateEvent; use Symfony\Component\Translation\DataCollectorTranslator; use Translation\Bundle\Service\StorageService; use Translation\Common\Model\Message; @@ -40,8 +41,15 @@ public function __construct(StorageService $storage, DataCollectorTranslator $tr $this->storage = $storage; } - public function onTerminate(Event $event): void + public function onTerminate($event): void { + // FilterResponseEvent have been renamed into ResponseEvent in sf 4.3 + // Use this class to type hint event & remove the following condition once sf ^4.3 become the minimum supported version. + // @see https://github.com/symfony/symfony/blob/master/UPGRADE-4.3.md#httpkernel + if (!$event instanceof PostResponseEvent && !$event instanceof TerminateEvent) { + throw new \InvalidArgumentException('Unknown given event.'); + } + if (null === $this->dataCollector) { return; } diff --git a/EventListener/EditInPlaceResponseListener.php b/EventListener/EditInPlaceResponseListener.php index 25fd820e..26258002 100644 --- a/EventListener/EditInPlaceResponseListener.php +++ b/EventListener/EditInPlaceResponseListener.php @@ -13,6 +13,7 @@ use Symfony\Component\Asset\Packages; use Symfony\Component\HttpKernel\Event\FilterResponseEvent; +use Symfony\Component\HttpKernel\Event\ResponseEvent; use Symfony\Component\Routing\Generator\UrlGeneratorInterface; use Translation\Bundle\EditInPlace\ActivatorInterface; @@ -74,8 +75,15 @@ public function __construct(ActivatorInterface $activator, UrlGeneratorInterface $this->showUntranslatable = $showUntranslatable; } - public function onKernelResponse(FilterResponseEvent $event): void + public function onKernelResponse($event): void { + // FilterResponseEvent have been renamed into ResponseEvent in sf 4.3 + // Use this class to type hint event & remove the following condition once sf ^4.3 become the minimum supported version. + // @see https://github.com/symfony/symfony/blob/master/UPGRADE-4.3.md#httpkernel + if (!$event instanceof FilterResponseEvent && !$event instanceof ResponseEvent) { + throw new \InvalidArgumentException('Unknown given event.'); + } + $request = $event->getRequest(); if (!$this->activator->checkRequest($request)) { diff --git a/Makefile b/Makefile new file mode 100644 index 00000000..c0014216 --- /dev/null +++ b/Makefile @@ -0,0 +1,13 @@ +.PHONY: cs-fix phpstan + +DIR := ${CURDIR} +QA_IMAGE := jakzal/phpqa:php7.3-alpine + +cs-lint: + @docker run --rm -v $(DIR):/project -w /project $(QA_IMAGE) php-cs-fixer fix --diff-format udiff --dry-run -vvv + +cs-fix: + @docker run --rm -v $(DIR):/project -w /project $(QA_IMAGE) php-cs-fixer fix --diff-format udiff -vvv + +phpstan: + @docker run --rm -v $(DIR):/project -w /project $(QA_IMAGE) phpstan analyse diff --git a/Model/Configuration.php b/Model/Configuration.php index 7ebcd162..1945c7bd 100644 --- a/Model/Configuration.php +++ b/Model/Configuration.php @@ -29,7 +29,7 @@ final class Configuration private $locales; /** - * Usually dirname('kernel.root_dir'). + * Usually dirname('kernel.project_dir'). * * @var string */ diff --git a/Resources/config/controllers.yml b/Resources/config/controllers.yml new file mode 100644 index 00000000..66238634 --- /dev/null +++ b/Resources/config/controllers.yml @@ -0,0 +1,25 @@ +services: + Translation\Bundle\Controller\EditInPlaceController: + autowire: true + public: true + tags: ['container.service_subscriber'] + arguments: + - '@Translation\Bundle\Service\StorageManager' + - '@Translation\Bundle\Service\CacheClearer' + - '@Symfony\Component\Validator\Validator\ValidatorInterface' + + Translation\Bundle\Controller\WebUIController: + autowire: true + public: true + tags: ['container.service_subscriber'] + arguments: + - '@Translation\Bundle\Service\ConfigurationManager' + - '@Translation\Bundle\Catalogue\CatalogueFetcher' + - '@Translation\Bundle\Catalogue\CatalogueManager' + - '@Translation\Bundle\Service\StorageManager' + - '@Symfony\Component\Validator\Validator\ValidatorInterface' + - '%php_translation.locales%' + - '%php_translation.webui.enabled%' + - '%php_translation.webui.allow_create%' + - '%php_translation.webui.allow_delete%' + - '%php_translation.webui.file_base_path%' diff --git a/Resources/config/services.yml b/Resources/config/services.yml index 6d374777..4a540ef4 100644 --- a/Resources/config/services.yml +++ b/Resources/config/services.yml @@ -3,6 +3,8 @@ services: public: true class: Translation\Bundle\Catalogue\CatalogueFetcher arguments: ["@translation.loader_or_reader"] + Translation\Bundle\Catalogue\CatalogueFetcher: + alias: php_translation.catalogue_fetcher php_translation.catalogue_writer: public: true @@ -17,6 +19,8 @@ services: php_translation.catalogue_manager: public: true class: Translation\Bundle\Catalogue\CatalogueManager + Translation\Bundle\Catalogue\CatalogueManager: + alias: php_translation.catalogue_manager php_translation.extractor: class: Translation\Extractor\Extractor @@ -24,10 +28,15 @@ services: php_translation.storage_manager: public: true class: Translation\Bundle\Service\StorageManager + Translation\Bundle\Service\StorageManager: + alias: php_translation.storage_manager + public: true php_translation.configuration_manager: public: true class: Translation\Bundle\Service\ConfigurationManager + Translation\Bundle\Service\ConfigurationManager: + alias: php_translation.configuration_manager php_translation.importer: public: true @@ -38,6 +47,9 @@ services: public: true class: Translation\Bundle\Service\CacheClearer arguments: ["%kernel.cache_dir%", "@translator", "@filesystem"] + Translation\Bundle\Service\CacheClearer: + alias: php_translation.cache_clearer + public: true php_translation.local_file_storage.abstract: class: Translation\SymfonyStorage\FileStorage diff --git a/Resources/config/symfony_profiler.yml b/Resources/config/symfony_profiler.yml index 778f438e..71e93e34 100644 --- a/Resources/config/symfony_profiler.yml +++ b/Resources/config/symfony_profiler.yml @@ -4,3 +4,11 @@ services: arguments: [ '@translator.data_collector' ] tags: - { name: 'data_collector', template: "@Translation/SymfonyProfiler/translation.html.twig", id: "translation", priority: 200 } + + Translation\Bundle\Controller\SymfonyProfilerController: + public: true + tags: ['container.service_subscriber'] + arguments: + - '@Translation\Bundle\Service\StorageService' + - '@profiler' + - '%php_translation.toolbar.allow_edit%' diff --git a/Service/CacheClearer.php b/Service/CacheClearer.php index 6c3516ca..9b5b44ef 100644 --- a/Service/CacheClearer.php +++ b/Service/CacheClearer.php @@ -14,7 +14,8 @@ use Symfony\Component\Filesystem\Filesystem; use Symfony\Component\Finder\Finder; use Symfony\Component\HttpKernel\CacheWarmer\WarmableInterface; -use Symfony\Component\Translation\TranslatorInterface; +use Symfony\Component\Translation\TranslatorInterface as LegacyTranslatorInterface; +use Symfony\Contracts\Translation\TranslatorInterface; /** * A service able to read and clear the Symfony Translation cache. @@ -38,8 +39,15 @@ final class CacheClearer */ private $filesystem; - public function __construct(string $kernelCacheDir, TranslatorInterface $translator, Filesystem $filesystem) + public function __construct(string $kernelCacheDir, $translator, Filesystem $filesystem) { + // The TranslatorInterface has been deprecated in favor of Symfony\Contracts\Translation\TranslatorInterface in sf4.2. + // Use this class to type hint event & remove the following condition once sf ^4.2 become the minimum supported version. + // @see https://github.com/symfony/symfony/blob/master/UPGRADE-4.2.md#translation + if (!$translator instanceof LegacyTranslatorInterface && !$translator instanceof TranslatorInterface) { + throw new \InvalidArgumentException('Unable to deal with the given translator.'); + } + $this->kernelCacheDir = $kernelCacheDir; $this->translator = $translator; $this->filesystem = $filesystem; diff --git a/Service/Importer.php b/Service/Importer.php index 7d83057e..3fb8677b 100644 --- a/Service/Importer.php +++ b/Service/Importer.php @@ -132,7 +132,7 @@ private function convertSourceLocationsToMessages(MessageCatalogue $catalogue, S } $key = $sourceLocation->getMessage(); - $catalogue->set($key, null, $domain); + $catalogue->add([$key => null], $domain); $trimLength = 1 + \strlen($this->config['project_root']); $meta = $this->getMetadata($catalogue, $key, $domain); diff --git a/Tests/Functional/BundleInitializationTest.php b/Tests/Functional/BundleInitializationTest.php index 73679848..b28b533e 100644 --- a/Tests/Functional/BundleInitializationTest.php +++ b/Tests/Functional/BundleInitializationTest.php @@ -31,7 +31,7 @@ public function testRegisterBundle(): void $this->assertInstanceOf(ConfigurationManager::class, $config); $default = $config->getConfiguration(); - $root = $container->getParameter('kernel.root_dir'); + $root = $container->getParameter('kernel.project_dir'); $this->assertEquals($root.'/Resources/translations', $default->getOutputDir()); $services = [ diff --git a/Tests/Functional/Command/ExtractCommandTest.php b/Tests/Functional/Command/ExtractCommandTest.php index 57d41e0b..442992c6 100644 --- a/Tests/Functional/Command/ExtractCommandTest.php +++ b/Tests/Functional/Command/ExtractCommandTest.php @@ -13,6 +13,7 @@ use Symfony\Bundle\FrameworkBundle\Console\Application; use Symfony\Component\Console\Tester\CommandTester; +use Symfony\Component\HttpKernel\Kernel; use Translation\Bundle\Model\Metadata; use Translation\Bundle\Tests\Functional\BaseTestCase; @@ -69,11 +70,19 @@ public function testExecute(): void $container = $this->getContainer(); $application->add($container->get('php_translator.console.extract')); + // transchoice tag have been definively removed in sf ^5.0 + // Remove this condition & views_with_transchoice + associated config once sf ^5.0 is the minimum supported version. + if (\version_compare(Kernel::VERSION, 5.0, '<')) { + $configuration = 'app_with_transchoice'; + } else { + $configuration = 'app'; + } + $command = $application->find('translation:extract'); $commandTester = new CommandTester($command); $commandTester->execute([ 'command' => $command->getName(), - 'configuration' => 'app', + 'configuration' => $configuration, 'locale' => 'sv', ]); diff --git a/Tests/Functional/Command/SyncCommandTest.php b/Tests/Functional/Command/SyncCommandTest.php index 25c66e90..b7928a64 100644 --- a/Tests/Functional/Command/SyncCommandTest.php +++ b/Tests/Functional/Command/SyncCommandTest.php @@ -80,7 +80,7 @@ public function testExecute(): void $this->fail('The command should fail when called with an unknown configuration key.'); } catch (\InvalidArgumentException $e) { $this->assertRegExp('|Unknown storage "fail"\.|s', $e->getMessage()); - $this->assertRegExp('|Available storages are "app"\.|s', $e->getMessage()); + $this->assertRegExp('|Available storages are "app"|s', $e->getMessage()); } } } diff --git a/Tests/Functional/app/Controller/TestController.php b/Tests/Functional/app/Controller/TestController.php index eafd3e31..8e08293f 100644 --- a/Tests/Functional/app/Controller/TestController.php +++ b/Tests/Functional/app/Controller/TestController.php @@ -11,13 +11,13 @@ namespace Translation\Bundle\Tests\Functional\app\Controller; -use Symfony\Bundle\FrameworkBundle\Controller\Controller; +use Symfony\Bundle\FrameworkBundle\Controller\AbstractController; use Symfony\Component\HttpFoundation\Response; /** * @author Damien Alexandre */ -class TestController extends Controller +class TestController extends AbstractController { public function translatedAction(): Response { diff --git a/Tests/Functional/app/Resources/views/translated.html.twig b/Tests/Functional/app/Resources/views/translated.html.twig index acb690f2..1e784137 100644 --- a/Tests/Functional/app/Resources/views/translated.html.twig +++ b/Tests/Functional/app/Resources/views/translated.html.twig @@ -5,10 +5,10 @@ {{ 'translated.title'|trans }} -

{{ 'translated.heading'|transchoice(12) }}

+

{{ 'translated.heading'|trans }}

{{ 'translated.paragraph0'|trans }}

{% trans %}translated.paragraph1{% endtrans %}

- {% transchoice 21 %}translated.paragraph2{% endtranschoice %} + {% trans %}translated.paragraph2{% endtrans %} {{ 'localized.email'|trans }}

diff --git a/Tests/Functional/app/Resources/views_with_transchoice/translated.html.twig b/Tests/Functional/app/Resources/views_with_transchoice/translated.html.twig new file mode 100644 index 00000000..acb690f2 --- /dev/null +++ b/Tests/Functional/app/Resources/views_with_transchoice/translated.html.twig @@ -0,0 +1,16 @@ + + + + + {{ 'translated.title'|trans }} + + +

{{ 'translated.heading'|transchoice(12) }}

+

{{ 'translated.paragraph0'|trans }}

{% trans %}translated.paragraph1{% endtrans %}

+

+ {% transchoice 21 %}translated.paragraph2{% endtranschoice %} + {{ 'localized.email'|trans }} +

+
+ + diff --git a/Tests/Functional/app/config/framework.yml b/Tests/Functional/app/config/framework.yml index 15600438..3fb3f675 100644 --- a/Tests/Functional/app/config/framework.yml +++ b/Tests/Functional/app/config/framework.yml @@ -8,10 +8,10 @@ framework: validation: enabled: true router: - resource: "%test.root_dir%/config/routing.yml" + resource: "%test.project_dir%/config/routing.yml" type: 'yaml' twig: strict_variables: "%kernel.debug%" #supresses deprecation notices about the default value TwigBundle pre version 5 paths: - "%test.root_dir%/Resources/views": App + "%test.project_dir%/Resources/views": App diff --git a/Tests/Functional/app/config/normal_config.yml b/Tests/Functional/app/config/normal_config.yml index 01f5a04f..fbc00d2e 100644 --- a/Tests/Functional/app/config/normal_config.yml +++ b/Tests/Functional/app/config/normal_config.yml @@ -6,6 +6,10 @@ translation: enabled: true configs: app: - dirs: ["%test.root_dir%/Resources/views"] - output_dir: "%test.root_dir%/Resources/translations" - project_root: "%test.root_dir%" + dirs: ["%test.project_dir%/Resources/views"] + output_dir: "%test.project_dir%/Resources/translations" + project_root: "%test.project_dir%" + app_with_transchoice: + dirs: ["%test.project_dir%/Resources/views_with_transchoice"] + output_dir: "%test.project_dir%/Resources/translations" + project_root: "%test.project_dir%" diff --git a/Tests/Functional/app/config/parameters.php b/Tests/Functional/app/config/parameters.php index 9716726d..9e1f1c28 100644 --- a/Tests/Functional/app/config/parameters.php +++ b/Tests/Functional/app/config/parameters.php @@ -9,4 +9,4 @@ * file that was distributed with this source code. */ -$container->setParameter('test.root_dir', \dirname(__DIR__)); +$container->setParameter('test.project_dir', \dirname(__DIR__)); diff --git a/Tests/Functional/app/config/services.yml b/Tests/Functional/app/config/services.yml index 7a77ead0..ed0af392 100644 --- a/Tests/Functional/app/config/services.yml +++ b/Tests/Functional/app/config/services.yml @@ -1,4 +1,9 @@ services: + Translation\Bundle\Tests\Functional\app\Controller\TestController: + public: true + autowire: true + tags: ['container.service_subscriber'] + logger: class: Translation\Bundle\Tests\Functional\app\Service\DummyLogger dummy_http_client: diff --git a/Tests/Unit/DependencyInjection/TranslationExtensionTest.php b/Tests/Unit/DependencyInjection/TranslationExtensionTest.php index dfd20d60..e1dc1ebb 100644 --- a/Tests/Unit/DependencyInjection/TranslationExtensionTest.php +++ b/Tests/Unit/DependencyInjection/TranslationExtensionTest.php @@ -23,7 +23,7 @@ class TranslationExtensionTest extends AbstractExtensionTestCase protected function getContainerExtensions(): array { $this->setParameter('kernel.default_locale', 'ar'); - $this->setParameter('kernel.root_dir', __DIR__); + $this->setParameter('kernel.project_dir', __DIR__); $this->setParameter('kernel.debug', true); return [ diff --git a/Tests/Unit/Twig/BaseTwigTestCase.php b/Tests/Unit/Twig/BaseTwigTestCase.php index be9cb761..f404a6d0 100644 --- a/Tests/Unit/Twig/BaseTwigTestCase.php +++ b/Tests/Unit/Twig/BaseTwigTestCase.php @@ -14,7 +14,6 @@ use PHPUnit\Framework\TestCase; use Symfony\Bridge\Twig\Extension\TranslationExtension as SymfonyTranslationExtension; use Symfony\Component\Translation\IdentityTranslator; -use Symfony\Component\Translation\MessageSelector; use Translation\Bundle\Twig\TranslationExtension; use Twig\Environment; use Twig\Loader\ArrayLoader; @@ -33,7 +32,7 @@ final protected function parse(string $file, bool $debug = false): string ? new ArrayLoader() : new \Twig_Loader_Array([]); $env = new Environment($loader); - $env->addExtension(new SymfonyTranslationExtension($translator = new IdentityTranslator(new MessageSelector()))); + $env->addExtension(new SymfonyTranslationExtension($translator = new IdentityTranslator())); $env->addExtension(new TranslationExtension($translator, $debug)); return (string) $env->parse($env->tokenize(new Source($content, '')))->getNode('body'); diff --git a/Tests/Unit/Twig/Fixture/simple_template.html.twig b/Tests/Unit/Twig/Fixture/simple_template.html.twig index 2d56ebef..b15d45af 100644 --- a/Tests/Unit/Twig/Fixture/simple_template.html.twig +++ b/Tests/Unit/Twig/Fixture/simple_template.html.twig @@ -8,14 +8,8 @@ {% trans with {'%name%': 'Johannes'} from "app" %}text.name{% endtrans %} -{% transchoice count with {'%name%': 'Johannes'} from "app" %}text.apple_choice{% endtranschoice %} - {{ "foo.bar" | trans }} -{{ "foo.bar2" | transchoice(5) }} - {{ "foo.bar3" | trans({'%name%': 'Johannes'}, "app") }} -{{ "foo.bar4" | transchoice(5, {'%name%': 'Johannes'}, 'app') }} - -{% trans %}text.default_domain{% endtrans %} \ No newline at end of file +{% trans %}text.default_domain{% endtrans %} diff --git a/Tests/Unit/Twig/Fixture/simple_template_compiled.html.twig b/Tests/Unit/Twig/Fixture/simple_template_compiled.html.twig index 4f262627..3743aaef 100644 --- a/Tests/Unit/Twig/Fixture/simple_template_compiled.html.twig +++ b/Tests/Unit/Twig/Fixture/simple_template_compiled.html.twig @@ -8,14 +8,8 @@ {% trans with {'%name%': 'Johannes'} from "app" %}text.name{% endtrans %} -{% transchoice count with {'%name%': 'Johannes'} from "app" %}text.apple_choice{% endtranschoice %} - {{ "foo.bar" | trans }} -{{ "foo.bar2" | transchoice(5) }} - {{ "foo.bar3" | trans({'%name%': 'Johannes'}, "app") }} -{{ "foo.bar4" | transchoice(5, {'%name%': 'Johannes'}, 'app') }} - -{% trans %}text.default_domain{% endtrans %} \ No newline at end of file +{% trans %}text.default_domain{% endtrans %} diff --git a/Tests/Unit/Twig/Fixture/simple_template_compiled_with_transchoice.html.twig b/Tests/Unit/Twig/Fixture/simple_template_compiled_with_transchoice.html.twig new file mode 100644 index 00000000..4a36b580 --- /dev/null +++ b/Tests/Unit/Twig/Fixture/simple_template_compiled_with_transchoice.html.twig @@ -0,0 +1,21 @@ +{{ "text.foo"|trans }} + +{{ "text.bar"|trans }} + +{{ "text.baz"|trans }} + +{{ "text.foo_bar"|trans({}, "foo") }} + +{% trans with {'%name%': 'Johannes'} from "app" %}text.name{% endtrans %} + +{% transchoice count with {'%name%': 'Johannes'} from "app" %}text.apple_choice{% endtranschoice %} + +{{ "foo.bar" | trans }} + +{{ "foo.bar2" | transchoice(5) }} + +{{ "foo.bar3" | trans({'%name%': 'Johannes'}, "app") }} + +{{ "foo.bar4" | transchoice(5, {'%name%': 'Johannes'}, 'app') }} + +{% trans %}text.default_domain{% endtrans %} diff --git a/Tests/Unit/Twig/Fixture/simple_template_with_transchoice.html.twig b/Tests/Unit/Twig/Fixture/simple_template_with_transchoice.html.twig new file mode 100644 index 00000000..2d56ebef --- /dev/null +++ b/Tests/Unit/Twig/Fixture/simple_template_with_transchoice.html.twig @@ -0,0 +1,21 @@ +{{ "text.foo"|trans|desc("Foo Bar")|meaning("Some Meaning")}} + +{{ "text.bar"|trans|desc("Foo") }} + +{{ "text.baz"|trans|meaning("Bar") }} + +{{ "text.foo_bar"|trans({}, "foo") }} + +{% trans with {'%name%': 'Johannes'} from "app" %}text.name{% endtrans %} + +{% transchoice count with {'%name%': 'Johannes'} from "app" %}text.apple_choice{% endtranschoice %} + +{{ "foo.bar" | trans }} + +{{ "foo.bar2" | transchoice(5) }} + +{{ "foo.bar3" | trans({'%name%': 'Johannes'}, "app") }} + +{{ "foo.bar4" | transchoice(5, {'%name%': 'Johannes'}, 'app') }} + +{% trans %}text.default_domain{% endtrans %} \ No newline at end of file diff --git a/Tests/Unit/Twig/RemovingNodeVisitorTest.php b/Tests/Unit/Twig/RemovingNodeVisitorTest.php index 2618129d..818e6515 100644 --- a/Tests/Unit/Twig/RemovingNodeVisitorTest.php +++ b/Tests/Unit/Twig/RemovingNodeVisitorTest.php @@ -11,6 +11,8 @@ namespace Translation\Bundle\Tests\Unit\Twig; +use Symfony\Component\HttpKernel\Kernel; + /** * @author Johannes M. Schmitt */ @@ -18,8 +20,15 @@ class RemovingNodeVisitorTest extends BaseTwigTestCase { public function testRemovalWithSimpleTemplate(): void { - $expected = $this->parse('simple_template_compiled.html.twig'); - $actual = $this->parse('simple_template.html.twig'); + // transchoice tag have been definively removed in sf ^5.0 + // Remove this condition & *with_transchoice templates once sf ^5.0 is the minimum supported version. + if (\version_compare(Kernel::VERSION, 5.0, '<')) { + $expected = $this->parse('simple_template_compiled_with_transchoice.html.twig'); + $actual = $this->parse('simple_template_with_transchoice.html.twig'); + } else { + $expected = $this->parse('simple_template_compiled.html.twig'); + $actual = $this->parse('simple_template.html.twig'); + } $this->assertEquals($expected, $actual); } diff --git a/Twig/TranslationExtension.php b/Twig/TranslationExtension.php index e886e782..0cfc97ac 100644 --- a/Twig/TranslationExtension.php +++ b/Twig/TranslationExtension.php @@ -12,7 +12,8 @@ namespace Translation\Bundle\Twig; use Symfony\Component\Translation\TranslatorBagInterface; -use Symfony\Component\Translation\TranslatorInterface; +use Symfony\Component\Translation\TranslatorInterface as LegacyTranslatorInterface; +use Symfony\Contracts\Translation\TranslatorInterface; use Translation\Bundle\Twig\Visitor\DefaultApplyingNodeVisitor; use Translation\Bundle\Twig\Visitor\NormalizingNodeVisitor; use Translation\Bundle\Twig\Visitor\RemovingNodeVisitor; @@ -35,8 +36,15 @@ final class TranslationExtension extends AbstractExtension */ private $debug; - public function __construct(TranslatorInterface $translator, bool $debug = false) + public function __construct($translator, bool $debug = false) { + // The TranslatorInterface has been deprecated in favor of Symfony\Contracts\Translation\TranslatorInterface in sf4.2. + // Use this class to type hint event & remove the following condition once sf ^4.2 become the minimum supported version. + // @see https://github.com/symfony/symfony/blob/master/UPGRADE-4.2.md#translation + if (!$translator instanceof LegacyTranslatorInterface && !$translator instanceof TranslatorInterface) { + throw new \InvalidArgumentException('Cannot deal with given translator.'); + } + $this->translator = $translator; $this->debug = $debug; } diff --git a/composer.json b/composer.json index 8707397b..e0772bc6 100644 --- a/composer.json +++ b/composer.json @@ -18,7 +18,6 @@ "symfony/finder": "^3.4 || ^4.3 || ^5.0", "symfony/intl": "^3.4 || ^4.3 || ^5.0", - "php-translation/common": "^1.0", "php-translation/symfony-storage": "^1.0", "php-translation/extractor": "^1.6", "nyholm/nsa": "^1.1", @@ -38,9 +37,12 @@ "matthiasnoback/symfony-dependency-injection-test": "^4.1", "matthiasnoback/symfony-config-test": "^4.1", "nyholm/psr7": "^1.1", - "nyholm/symfony-bundle-test": "^1.6", + "nyholm/symfony-bundle-test": "^1.6.1", "phpunit/phpunit": "^8.4" }, + "conflict": { + "symfony/config": "<3.4.31" + }, "suggest": { "php-http/httplug-bundle": "To easier configure your httplug clients." }, diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon new file mode 100644 index 00000000..aa7eedb5 --- /dev/null +++ b/phpstan-baseline.neon @@ -0,0 +1,191 @@ +parameters: + ignoreErrors: + - + message: "#^Parameter \\$reader of method Translation\\\\Bundle\\\\Catalogue\\\\CatalogueFetcher\\:\\:__construct\\(\\) has invalid typehint type Symfony\\\\Bundle\\\\FrameworkBundle\\\\Translation\\\\TranslationLoader\\.$#" + count: 1 + path: Catalogue/CatalogueFetcher.php + + - + message: "#^Call to an undefined method Symfony\\\\Component\\\\Console\\\\Application\\:\\:getKernel\\(\\)\\.$#" + count: 1 + path: Command/DeleteObsoleteCommand.php + + - + message: "#^Call to an undefined method Symfony\\\\Component\\\\Console\\\\Application\\:\\:getKernel\\(\\)\\.$#" + count: 1 + path: Command/DownloadCommand.php + + - + message: "#^Call to an undefined method Symfony\\\\Component\\\\Console\\\\Application\\:\\:getKernel\\(\\)\\.$#" + count: 1 + path: Command/ExtractCommand.php + + - + message: "#^Call to an undefined method Symfony\\\\Component\\\\Console\\\\Application\\:\\:getKernel\\(\\)\\.$#" + count: 1 + path: Command/StatusCommand.php + + - + message: "#^Call to an undefined static method Symfony\\\\Component\\\\Intl\\\\Intl\\:\\:getLocaleBundle\\(\\)\\.$#" + count: 1 + path: Controller/WebUIController.php + + - + message: "#^Call to an undefined method Symfony\\\\Component\\\\Config\\\\Definition\\\\Builder\\\\TreeBuilder\\:\\:root\\(\\)\\.$#" + count: 1 + path: DependencyInjection/Configuration.php + + - + message: "#^Call to an undefined method Symfony\\\\Component\\\\Config\\\\Definition\\\\Builder\\\\NodeDefinition\\:\\:fixXmlConfig\\(\\)\\.$#" + count: 1 + path: DependencyInjection/Configuration.php + + - + message: "#^Call to an undefined method Symfony\\\\Component\\\\Config\\\\Definition\\\\Builder\\\\NodeParentInterface\\:\\:scalarNode\\(\\)\\.$#" + count: 2 + path: DependencyInjection/Configuration.php + + - + message: "#^Call to an undefined method Symfony\\\\Component\\\\Config\\\\Definition\\\\Builder\\\\NodeParentInterface\\:\\:booleanNode\\(\\)\\.$#" + count: 1 + path: DependencyInjection/Configuration.php + + - + message: "#^Call to method replaceArgument\\(\\) on an unknown class Symfony\\\\Component\\\\DependencyInjection\\\\DefinitionDecorator\\.$#" + count: 2 + path: DependencyInjection/TranslationExtension.php + + - + message: "#^Call to method setPublic\\(\\) on an unknown class Symfony\\\\Component\\\\DependencyInjection\\\\DefinitionDecorator\\.$#" + count: 1 + path: DependencyInjection/TranslationExtension.php + + - + message: "#^Call to method addMethodCall\\(\\) on an unknown class Symfony\\\\Component\\\\DependencyInjection\\\\DefinitionDecorator\\.$#" + count: 2 + path: DependencyInjection/TranslationExtension.php + + - + message: "#^Return typehint of method Translation\\\\Bundle\\\\DependencyInjection\\\\TranslationExtension\\:\\:createChildDefinition\\(\\) has invalid type Symfony\\\\Component\\\\DependencyInjection\\\\DefinitionDecorator\\.$#" + count: 1 + path: DependencyInjection/TranslationExtension.php + + - + message: "#^Instantiated class Symfony\\\\Component\\\\DependencyInjection\\\\DefinitionDecorator not found\\.$#" + count: 1 + path: DependencyInjection/TranslationExtension.php + + - + message: "#^Class Symfony\\\\Component\\\\HttpKernel\\\\Event\\\\PostResponseEvent not found\\.$#" + count: 1 + path: EventListener/AutoAddMissingTranslations.php + + - + message: "#^Class Symfony\\\\Component\\\\HttpKernel\\\\Event\\\\FilterResponseEvent not found\\.$#" + count: 1 + path: EventListener/EditInPlaceResponseListener.php + + - + message: "#^Call to method getRequest\\(\\) on an unknown class Symfony\\\\Component\\\\HttpKernel\\\\Event\\\\FilterResponseEvent\\.$#" + count: 2 + path: EventListener/EditInPlaceResponseListener.php + + - + message: "#^Call to method getResponse\\(\\) on an unknown class Symfony\\\\Component\\\\HttpKernel\\\\Event\\\\FilterResponseEvent\\.$#" + count: 3 + path: EventListener/EditInPlaceResponseListener.php + + - + message: "#^Class Symfony\\\\Component\\\\Translation\\\\TranslatorInterface not found\\.$#" + count: 1 + path: Service/CacheClearer.php + + - + message: "#^Property Translation\\\\Bundle\\\\Translator\\\\EditInPlaceTranslator\\:\\:\\$translator has unknown class Symfony\\\\Component\\\\Translation\\\\TranslatorInterface as its type\\.$#" + count: 1 + path: Translator/EditInPlaceTranslator.php + + - + message: "#^Parameter \\$translator of method Translation\\\\Bundle\\\\Translator\\\\EditInPlaceTranslator\\:\\:__construct\\(\\) has invalid typehint type Symfony\\\\Component\\\\Translation\\\\TranslatorInterface\\.$#" + count: 1 + path: Translator/EditInPlaceTranslator.php + + - + message: "#^Class Symfony\\\\Component\\\\Translation\\\\TranslatorInterface not found\\.$#" + count: 1 + path: Translator/EditInPlaceTranslator.php + + - + message: "#^Call to method getCatalogue\\(\\) on an unknown class Symfony\\\\Component\\\\Translation\\\\TranslatorInterface\\.$#" + count: 1 + path: Translator/EditInPlaceTranslator.php + + - + message: "#^Call to method trans\\(\\) on an unknown class Symfony\\\\Component\\\\Translation\\\\TranslatorInterface\\.$#" + count: 2 + path: Translator/EditInPlaceTranslator.php + + - + message: "#^Call to method getLocale\\(\\) on an unknown class Symfony\\\\Component\\\\Translation\\\\TranslatorInterface\\.$#" + count: 2 + path: Translator/EditInPlaceTranslator.php + + - + message: "#^Call to method transChoice\\(\\) on an unknown class Symfony\\\\Component\\\\Translation\\\\TranslatorInterface\\.$#" + count: 1 + path: Translator/EditInPlaceTranslator.php + + - + message: "#^Call to method setLocale\\(\\) on an unknown class Symfony\\\\Component\\\\Translation\\\\TranslatorInterface\\.$#" + count: 1 + path: Translator/EditInPlaceTranslator.php + + - + message: "#^Property Translation\\\\Bundle\\\\Translator\\\\FallbackTranslator\\:\\:\\$symfonyTranslator has unknown class Symfony\\\\Component\\\\Translation\\\\TranslatorInterface as its type\\.$#" + count: 1 + path: Translator/FallbackTranslator.php + + - + message: "#^Parameter \\$symfonyTranslator of method Translation\\\\Bundle\\\\Translator\\\\FallbackTranslator\\:\\:__construct\\(\\) has invalid typehint type Symfony\\\\Component\\\\Translation\\\\TranslatorInterface\\.$#" + count: 1 + path: Translator/FallbackTranslator.php + + - + message: "#^Class Symfony\\\\Component\\\\Translation\\\\TranslatorInterface not found\\.$#" + count: 1 + path: Translator/FallbackTranslator.php + + - + message: "#^Call to method trans\\(\\) on an unknown class Symfony\\\\Component\\\\Translation\\\\TranslatorInterface\\.$#" + count: 2 + path: Translator/FallbackTranslator.php + + - + message: "#^Call to method transChoice\\(\\) on an unknown class Symfony\\\\Component\\\\Translation\\\\TranslatorInterface\\.$#" + count: 2 + path: Translator/FallbackTranslator.php + + - + message: "#^Call to method setLocale\\(\\) on an unknown class Symfony\\\\Component\\\\Translation\\\\TranslatorInterface\\.$#" + count: 1 + path: Translator/FallbackTranslator.php + + - + message: "#^Call to method getLocale\\(\\) on an unknown class Symfony\\\\Component\\\\Translation\\\\TranslatorInterface\\.$#" + count: 1 + path: Translator/FallbackTranslator.php + + - + message: "#^Call to method getCatalogue\\(\\) on an unknown class Symfony\\\\Component\\\\Translation\\\\TranslatorInterface\\.$#" + count: 1 + path: Translator/FallbackTranslator.php + + - + message: "#^Class Symfony\\\\Component\\\\Translation\\\\TranslatorInterface not found\\.$#" + count: 1 + path: Twig/TranslationExtension.php + + - + message: "#^Call to an undefined method Symfony\\\\Component\\\\Translation\\\\TranslatorBagInterface\\|Symfony\\\\Contracts\\\\Translation\\\\TranslatorInterface\\:\\:transChoice\\(\\)\\.$#" + count: 2 + path: Twig/TranslationExtension.php diff --git a/phpstan.neon.dist b/phpstan.neon.dist index f1aa2a34..cdcc6264 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -1,5 +1,9 @@ +includes: + - phpstan-baseline.neon + parameters: level: 2 + inferPrivatePropertyTypeFromConstructor: true paths: - Catalogue - Command @@ -13,33 +17,3 @@ parameters: - Service - Translator - Twig - - ignoreErrors: - - - message: '#Parameter \$reader of method Translation\\Bundle\\Catalogue\\CatalogueFetcher::__construct\(\) has invalid typehint type Symfony\\Bundle\\FrameworkBundle\\Translation\\TranslationLoader#' - path: %currentWorkingDirectory%/Catalogue/CatalogueFetcher.php - - - - message: '#Return typehint of method Translation\\Bundle\\DependencyInjection\\TranslationExtension::createChildDefinition\(\) has invalid type Symfony\\Component\\DependencyInjection\\DefinitionDecorator#' - path: %currentWorkingDirectory%/DependencyInjection/TranslationExtension.php - - - - comment: 'Symfony 3.3+ BC' - message: '#Symfony\\Component\\DependencyInjection\\DefinitionDecorator#' - path: %currentWorkingDirectory% - - - '#Call to an undefined method Symfony\\Component\\Config\\Definition\\Builder\\Node[a-zA-Z]+()#' - - - - path: %currentWorkingDirectory%/Command - message: '#Call to an undefined method Symfony\\Component\\Console\\Application::getKernel()#' - - - path: %currentWorkingDirectory%/Controller/WebUIController.php - message: '#Call to an undefined static method Symfony\\Component\\Intl\\Intl::getLocaleBundle()#' - - - 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().#' From 435671a448a1568c657e0df9110bc41c6486fe44 Mon Sep 17 00:00:00 2001 From: Olivier Dolbeau Date: Sun, 8 Dec 2019 14:49:18 +0100 Subject: [PATCH 2/6] Use class_exists to deal with next events class --- EventListener/AutoAddMissingTranslations.php | 16 ++++++++-------- EventListener/EditInPlaceResponseListener.php | 16 ++++++++-------- phpstan-baseline.neon | 12 +----------- 3 files changed, 17 insertions(+), 27 deletions(-) diff --git a/EventListener/AutoAddMissingTranslations.php b/EventListener/AutoAddMissingTranslations.php index 7db959c8..b30ab672 100644 --- a/EventListener/AutoAddMissingTranslations.php +++ b/EventListener/AutoAddMissingTranslations.php @@ -41,15 +41,8 @@ public function __construct(StorageService $storage, DataCollectorTranslator $tr $this->storage = $storage; } - public function onTerminate($event): void + public function onTerminate(TerminateEvent $event): void { - // FilterResponseEvent have been renamed into ResponseEvent in sf 4.3 - // Use this class to type hint event & remove the following condition once sf ^4.3 become the minimum supported version. - // @see https://github.com/symfony/symfony/blob/master/UPGRADE-4.3.md#httpkernel - if (!$event instanceof PostResponseEvent && !$event instanceof TerminateEvent) { - throw new \InvalidArgumentException('Unknown given event.'); - } - if (null === $this->dataCollector) { return; } @@ -63,3 +56,10 @@ public function onTerminate($event): void } } } + +// PostResponseEvent have been renamed into ResponseEvent in sf 4.3 +// @see https://github.com/symfony/symfony/blob/master/UPGRADE-4.3.md#httpkernel +// To be removed once sf ^4.3 become the minimum supported version. +if (!\class_exists(TerminateEvent::class) && \class_exists(PostResponseEvent::class)) { + \class_alias(PostResponseEvent::class, TerminateEvent::class); +} diff --git a/EventListener/EditInPlaceResponseListener.php b/EventListener/EditInPlaceResponseListener.php index 26258002..e61c1789 100644 --- a/EventListener/EditInPlaceResponseListener.php +++ b/EventListener/EditInPlaceResponseListener.php @@ -75,15 +75,8 @@ public function __construct(ActivatorInterface $activator, UrlGeneratorInterface $this->showUntranslatable = $showUntranslatable; } - public function onKernelResponse($event): void + public function onKernelResponse(ResponseEvent $event): void { - // FilterResponseEvent have been renamed into ResponseEvent in sf 4.3 - // Use this class to type hint event & remove the following condition once sf ^4.3 become the minimum supported version. - // @see https://github.com/symfony/symfony/blob/master/UPGRADE-4.3.md#httpkernel - if (!$event instanceof FilterResponseEvent && !$event instanceof ResponseEvent) { - throw new \InvalidArgumentException('Unknown given event.'); - } - $request = $event->getRequest(); if (!$this->activator->checkRequest($request)) { @@ -135,3 +128,10 @@ public function onKernelResponse($event): void $event->getResponse()->setContent($content); } } + +// FilterResponseEvent have been renamed into ResponseEvent in sf 4.3 +// @see https://github.com/symfony/symfony/blob/master/UPGRADE-4.3.md#httpkernel +// To be removed once sf ^4.3 become the minimum supported version. +if (!\class_exists(ResponseEvent::class) && \class_exists(FilterResponseEvent::class)) { + \class_alias(FilterResponseEvent::class, ResponseEvent::class); +} diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index aa7eedb5..7319a0e2 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -77,24 +77,14 @@ parameters: - message: "#^Class Symfony\\\\Component\\\\HttpKernel\\\\Event\\\\PostResponseEvent not found\\.$#" - count: 1 + count: 2 path: EventListener/AutoAddMissingTranslations.php - message: "#^Class Symfony\\\\Component\\\\HttpKernel\\\\Event\\\\FilterResponseEvent not found\\.$#" - count: 1 - path: EventListener/EditInPlaceResponseListener.php - - - - message: "#^Call to method getRequest\\(\\) on an unknown class Symfony\\\\Component\\\\HttpKernel\\\\Event\\\\FilterResponseEvent\\.$#" count: 2 path: EventListener/EditInPlaceResponseListener.php - - - message: "#^Call to method getResponse\\(\\) on an unknown class Symfony\\\\Component\\\\HttpKernel\\\\Event\\\\FilterResponseEvent\\.$#" - count: 3 - path: EventListener/EditInPlaceResponseListener.php - - message: "#^Class Symfony\\\\Component\\\\Translation\\\\TranslatorInterface not found\\.$#" count: 1 From d7fb2ccc07f108611350a98ebf4b3c91273dbb58 Mon Sep 17 00:00:00 2001 From: Olivier Dolbeau Date: Sun, 8 Dec 2019 15:24:53 +0100 Subject: [PATCH 3/6] Alaways use ChildDefinition in extension --- DependencyInjection/TranslationExtension.php | 19 ++------------- phpstan-baseline.neon | 25 -------------------- 2 files changed, 2 insertions(+), 42 deletions(-) diff --git a/DependencyInjection/TranslationExtension.php b/DependencyInjection/TranslationExtension.php index 9c82806b..37d209c1 100644 --- a/DependencyInjection/TranslationExtension.php +++ b/DependencyInjection/TranslationExtension.php @@ -15,7 +15,6 @@ use Symfony\Component\DependencyInjection\Alias; use Symfony\Component\DependencyInjection\ChildDefinition; use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\DefinitionDecorator; use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException; use Symfony\Component\DependencyInjection\Loader; use Symfony\Component\DependencyInjection\Reference; @@ -114,7 +113,7 @@ private function handleConfigNode(ContainerBuilder $container, array $config): v /* * Configure storage chain service */ - $storageDefinition = $this->createChildDefinition('php_translation.storage.abstract'); + $storageDefinition = new ChildDefinition('php_translation.storage.abstract'); $storageDefinition->replaceArgument(2, new Reference($configurationServiceId)); $storageDefinition->setPublic(true); $container->setDefinition('php_translation.storage.'.$name, $storageDefinition); @@ -132,7 +131,7 @@ private function handleConfigNode(ContainerBuilder $container, array $config): v continue; } - $def = $this->createChildDefinition($serviceId); + $def = new ChildDefinition($serviceId); $def->replaceArgument(2, [$c['output_dir']]) ->replaceArgument(3, $c['local_file_storage_options']) ->addTag('php_translation.storage', ['type' => 'local', 'name' => $name]); @@ -222,20 +221,6 @@ public function getAlias(): string return 'translation'; } - /** - * To avoid BC break for Symfony 3.3+. - * - * @return ChildDefinition|DefinitionDecorator - */ - private function createChildDefinition(string $parent) - { - if (\class_exists(ChildDefinition::class)) { - return new ChildDefinition($parent); - } - - return new DefinitionDecorator($parent); - } - /** * {@inheritdoc} */ diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 7319a0e2..80518274 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -50,31 +50,6 @@ parameters: count: 1 path: DependencyInjection/Configuration.php - - - message: "#^Call to method replaceArgument\\(\\) on an unknown class Symfony\\\\Component\\\\DependencyInjection\\\\DefinitionDecorator\\.$#" - count: 2 - path: DependencyInjection/TranslationExtension.php - - - - message: "#^Call to method setPublic\\(\\) on an unknown class Symfony\\\\Component\\\\DependencyInjection\\\\DefinitionDecorator\\.$#" - count: 1 - path: DependencyInjection/TranslationExtension.php - - - - message: "#^Call to method addMethodCall\\(\\) on an unknown class Symfony\\\\Component\\\\DependencyInjection\\\\DefinitionDecorator\\.$#" - count: 2 - path: DependencyInjection/TranslationExtension.php - - - - message: "#^Return typehint of method Translation\\\\Bundle\\\\DependencyInjection\\\\TranslationExtension\\:\\:createChildDefinition\\(\\) has invalid type Symfony\\\\Component\\\\DependencyInjection\\\\DefinitionDecorator\\.$#" - count: 1 - path: DependencyInjection/TranslationExtension.php - - - - message: "#^Instantiated class Symfony\\\\Component\\\\DependencyInjection\\\\DefinitionDecorator not found\\.$#" - count: 1 - path: DependencyInjection/TranslationExtension.php - - message: "#^Class Symfony\\\\Component\\\\HttpKernel\\\\Event\\\\PostResponseEvent not found\\.$#" count: 2 From 902b5043c569ac4c04adaeb7b76918e7fa60a242 Mon Sep 17 00:00:00 2001 From: Olivier Dolbeau Date: Sun, 8 Dec 2019 15:28:50 +0100 Subject: [PATCH 4/6] Remove useless PHPDoc --- DependencyInjection/CompilerPass/ExternalTranslatorPass.php | 2 -- DependencyInjection/CompilerPass/SymfonyProfilerPass.php | 2 -- 2 files changed, 4 deletions(-) diff --git a/DependencyInjection/CompilerPass/ExternalTranslatorPass.php b/DependencyInjection/CompilerPass/ExternalTranslatorPass.php index 8f415582..e078ae8f 100644 --- a/DependencyInjection/CompilerPass/ExternalTranslatorPass.php +++ b/DependencyInjection/CompilerPass/ExternalTranslatorPass.php @@ -13,7 +13,6 @@ use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Definition; use Symfony\Component\DependencyInjection\Reference; /** @@ -23,7 +22,6 @@ class ExternalTranslatorPass implements CompilerPassInterface { public function process(ContainerBuilder $container): void { - /* @var Definition $def */ if (!$container->hasDefinition('php_translation.translator_service.external_translator')) { return; } diff --git a/DependencyInjection/CompilerPass/SymfonyProfilerPass.php b/DependencyInjection/CompilerPass/SymfonyProfilerPass.php index a3835086..c4c37b6b 100644 --- a/DependencyInjection/CompilerPass/SymfonyProfilerPass.php +++ b/DependencyInjection/CompilerPass/SymfonyProfilerPass.php @@ -13,7 +13,6 @@ use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Definition; /** * Make sure we have all the dependencies for Symfony Profiler. @@ -24,7 +23,6 @@ class SymfonyProfilerPass implements CompilerPassInterface { public function process(ContainerBuilder $container): void { - /* @var Definition $def */ if (!$container->hasDefinition('php_translation.data_collector')) { return; } From 448adb119bf83c0181469d6b1c056af2d32f0761 Mon Sep 17 00:00:00 2001 From: Olivier Dolbeau Date: Sun, 8 Dec 2019 15:33:51 +0100 Subject: [PATCH 5/6] Get rid of unecessary translation.reader_or_loader service --- .../CompilerPass/LoaderOrReaderPass.php | 38 ------------------- Resources/config/services.yml | 4 +- .../CompilerPass/LoaderOrReaderPassTest.php | 35 ----------------- TranslationBundle.php | 2 - 4 files changed, 2 insertions(+), 77 deletions(-) delete mode 100644 DependencyInjection/CompilerPass/LoaderOrReaderPass.php delete mode 100644 Tests/Unit/DependencyInjection/CompilerPass/LoaderOrReaderPassTest.php diff --git a/DependencyInjection/CompilerPass/LoaderOrReaderPass.php b/DependencyInjection/CompilerPass/LoaderOrReaderPass.php deleted file mode 100644 index 86736c67..00000000 --- a/DependencyInjection/CompilerPass/LoaderOrReaderPass.php +++ /dev/null @@ -1,38 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Translation\Bundle\DependencyInjection\CompilerPass; - -use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; -use Symfony\Component\DependencyInjection\ContainerBuilder; - -/** - * To provide a BC layer for Symfony 2.7 to 3.3 this compiler pass - * registers an alias of whether TranslationReader or TranslationLoader - * to be able to inject it in other services. - */ -class LoaderOrReaderPass implements CompilerPassInterface -{ - public function process(ContainerBuilder $container): void - { - if ($container->has('translation.reader')) { - $container->setAlias('translation.loader_or_reader', 'translation.reader'); - - return; - } - - if ($container->has('translation.loader')) { - $container->setAlias('translation.loader_or_reader', 'translation.loader'); - - return; - } - } -} diff --git a/Resources/config/services.yml b/Resources/config/services.yml index 4a540ef4..95ef5aab 100644 --- a/Resources/config/services.yml +++ b/Resources/config/services.yml @@ -2,7 +2,7 @@ services: php_translation.catalogue_fetcher: public: true class: Translation\Bundle\Catalogue\CatalogueFetcher - arguments: ["@translation.loader_or_reader"] + arguments: ["@translation.reader"] Translation\Bundle\Catalogue\CatalogueFetcher: alias: php_translation.catalogue_fetcher @@ -54,7 +54,7 @@ services: php_translation.local_file_storage.abstract: class: Translation\SymfonyStorage\FileStorage abstract: true - arguments: ["@translation.writer", "@translation.loader_or_reader", ~, []] + arguments: ["@translation.writer", "@translation.reader", ~, []] php_translation.storage.xlf_loader: class: Translation\SymfonyStorage\Loader\XliffLoader diff --git a/Tests/Unit/DependencyInjection/CompilerPass/LoaderOrReaderPassTest.php b/Tests/Unit/DependencyInjection/CompilerPass/LoaderOrReaderPassTest.php deleted file mode 100644 index afb599d2..00000000 --- a/Tests/Unit/DependencyInjection/CompilerPass/LoaderOrReaderPassTest.php +++ /dev/null @@ -1,35 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Translation\Bundle\Tests\Unit\DependencyInjection\CompilerPass; - -use Matthias\SymfonyDependencyInjectionTest\PhpUnit\AbstractCompilerPassTestCase; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\DependencyInjection\Definition; -use Translation\Bundle\DependencyInjection\CompilerPass\LoaderOrReaderPass; - -class LoaderOrReaderPassTest extends AbstractCompilerPassTestCase -{ - protected function registerCompilerPass(ContainerBuilder $container): void - { - $container->addCompilerPass(new LoaderOrReaderPass()); - } - - public function testLoaderOrReader(): void - { - $def = new Definition(); - $this->setDefinition('translation.reader', $def); - - $this->compile(); - - $this->assertContainerBuilderHasAlias('translation.loader_or_reader'); - } -} diff --git a/TranslationBundle.php b/TranslationBundle.php index 5b355437..f81a597a 100644 --- a/TranslationBundle.php +++ b/TranslationBundle.php @@ -17,7 +17,6 @@ use Translation\Bundle\DependencyInjection\CompilerPass\ExternalTranslatorPass; use Translation\Bundle\DependencyInjection\CompilerPass\ExtractorPass; use Translation\Bundle\DependencyInjection\CompilerPass\FileDumperBackupPass; -use Translation\Bundle\DependencyInjection\CompilerPass\LoaderOrReaderPass; use Translation\Bundle\DependencyInjection\CompilerPass\StoragePass; use Translation\Bundle\DependencyInjection\CompilerPass\SymfonyProfilerPass; use Translation\Bundle\DependencyInjection\CompilerPass\ValidatorVisitorPass; @@ -35,7 +34,6 @@ public function build(ContainerBuilder $container): void $container->addCompilerPass(new ExtractorPass()); $container->addCompilerPass(new StoragePass()); $container->addCompilerPass(new EditInPlacePass()); - $container->addCompilerPass(new LoaderOrReaderPass()); $container->addCompilerPass(new FileDumperBackupPass()); } } From fb5b6bad2d755bb80b5993970474d2fb6817ca37 Mon Sep 17 00:00:00 2001 From: Olivier Dolbeau Date: Fri, 20 Dec 2019 15:22:56 +0100 Subject: [PATCH 6/6] Require php-translation/symfony-storage ^2.0 --- Catalogue/CatalogueFetcher.php | 15 +------- Catalogue/CatalogueWriter.php | 15 +------- .../CompilerPass/FileDumperBackupPass.php | 34 ------------------- Makefile | 17 +++++++--- Resources/config/services.yml | 10 ------ Service/StorageService.php | 4 +-- TranslationBundle.php | 2 -- composer.json | 2 +- phpstan-baseline.neon | 5 --- 9 files changed, 17 insertions(+), 87 deletions(-) delete mode 100644 DependencyInjection/CompilerPass/FileDumperBackupPass.php diff --git a/Catalogue/CatalogueFetcher.php b/Catalogue/CatalogueFetcher.php index e06da8f8..0ee5cf00 100644 --- a/Catalogue/CatalogueFetcher.php +++ b/Catalogue/CatalogueFetcher.php @@ -12,12 +12,9 @@ namespace Translation\Bundle\Catalogue; use Nyholm\NSA; -use Symfony\Bundle\FrameworkBundle\Translation\TranslationLoader as SymfonyTranslationLoader; use Symfony\Component\Translation\MessageCatalogue; use Symfony\Component\Translation\Reader\TranslationReaderInterface; use Translation\Bundle\Model\Configuration; -use Translation\SymfonyStorage\LegacyTranslationReader; -use Translation\SymfonyStorage\TranslationLoader; /** * Fetches catalogues from source files. This will only work with local file storage @@ -29,20 +26,10 @@ */ final class CatalogueFetcher { - /** - * @var TranslationReaderInterface - */ private $reader; - /** - * @param SymfonyTranslationLoader|TranslationLoader|TranslationReaderInterface $reader - */ - public function __construct($reader) + public function __construct(TranslationReaderInterface $reader) { - if (!$reader instanceof TranslationReaderInterface) { - $reader = new LegacyTranslationReader($reader); - } - $this->reader = $reader; } diff --git a/Catalogue/CatalogueWriter.php b/Catalogue/CatalogueWriter.php index dd7641ad..9c5bc1ac 100644 --- a/Catalogue/CatalogueWriter.php +++ b/Catalogue/CatalogueWriter.php @@ -12,10 +12,8 @@ namespace Translation\Bundle\Catalogue; use Symfony\Component\Translation\MessageCatalogue; -use Symfony\Component\Translation\Writer\TranslationWriter; use Symfony\Component\Translation\Writer\TranslationWriterInterface; use Translation\Bundle\Model\Configuration; -use Translation\SymfonyStorage\LegacyTranslationWriter; /** * Write catalogues back to disk. @@ -26,22 +24,11 @@ */ final class CatalogueWriter { - /** - * @var TranslationWriterInterface - */ private $writer; - - /** - * @var string - */ private $defaultLocale; - public function __construct(TranslationWriter $writer, string $defaultLocale) + public function __construct(TranslationWriterInterface $writer, string $defaultLocale) { - if (!$writer instanceof TranslationWriterInterface) { - $writer = new LegacyTranslationWriter($writer); - } - $this->writer = $writer; $this->defaultLocale = $defaultLocale; } diff --git a/DependencyInjection/CompilerPass/FileDumperBackupPass.php b/DependencyInjection/CompilerPass/FileDumperBackupPass.php deleted file mode 100644 index ff60a202..00000000 --- a/DependencyInjection/CompilerPass/FileDumperBackupPass.php +++ /dev/null @@ -1,34 +0,0 @@ - - * - * For the full copyright and license information, please view the LICENSE - * file that was distributed with this source code. - */ - -namespace Translation\Bundle\DependencyInjection\CompilerPass; - -use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface; -use Symfony\Component\DependencyInjection\ContainerBuilder; -use Symfony\Component\HttpKernel\Kernel; - -/** - * The FileDumper::setBackup is deprecated since Symfony 4.1. - * This compiler pass assures our service definition remains unchanged for older symfony versions (3 or lower) - * while keeping the latest version clean of deprecation notices. - */ -class FileDumperBackupPass implements CompilerPassInterface -{ - public function process(ContainerBuilder $container): void - { - if (Kernel::MAJOR_VERSION >= 4) { - return; - } - - $definition = $container->getDefinition('php_translation.storage.xlf_dumper'); - $definition->addMethodCall('setBackup', [false]); - } -} diff --git a/Makefile b/Makefile index c0014216..db6bcf45 100644 --- a/Makefile +++ b/Makefile @@ -1,13 +1,20 @@ -.PHONY: cs-fix phpstan +.PHONY: ${TARGETS} DIR := ${CURDIR} QA_IMAGE := jakzal/phpqa:php7.3-alpine -cs-lint: - @docker run --rm -v $(DIR):/project -w /project $(QA_IMAGE) php-cs-fixer fix --diff-format udiff --dry-run -vvv - cs-fix: @docker run --rm -v $(DIR):/project -w /project $(QA_IMAGE) php-cs-fixer fix --diff-format udiff -vvv +cs-diff: + @docker run --rm -v $(DIR):/project -w /project $(QA_IMAGE) php-cs-fixer fix --diff-format udiff --dry-run -vvv + phpstan: - @docker run --rm -v $(DIR):/project -w /project $(QA_IMAGE) phpstan analyse + @docker run --rm -v $(DIR):/project -w /project $(QA_IMAGE) phpstan analyze + +phpunit: + @vendor/bin/phpunit + +static: cs-diff phpstan + +test: static phpunit diff --git a/Resources/config/services.yml b/Resources/config/services.yml index 95ef5aab..104420a8 100644 --- a/Resources/config/services.yml +++ b/Resources/config/services.yml @@ -56,16 +56,6 @@ services: abstract: true arguments: ["@translation.writer", "@translation.reader", ~, []] - php_translation.storage.xlf_loader: - class: Translation\SymfonyStorage\Loader\XliffLoader - tags: - - { name: translation.loader, alias: xlf, legacy-alias: xliff } - - php_translation.storage.xlf_dumper: - class: Translation\SymfonyStorage\Dumper\XliffDumper - tags: - - { name: translation.dumper, alias: xlf, legacy-alias: xliff } - php_translation.catalogue_counter: public: true class: Translation\Bundle\Catalogue\CatalogueCounter diff --git a/Service/StorageService.php b/Service/StorageService.php index 5453664a..03215800 100644 --- a/Service/StorageService.php +++ b/Service/StorageService.php @@ -160,7 +160,7 @@ public function syncAndFetchMessage(string $locale, string $domain, string $key) * local storage and then move on to the remote storages. * {@inheritdoc} */ - public function get($locale, $domain, $key): ?Message + public function get(string $locale, string $domain, string $key): MessageInterface { foreach ([$this->localStorages, $this->remoteStorages] as $storages) { $value = $this->getFromStorages($storages, $locale, $domain, $key); @@ -241,7 +241,7 @@ private function updateStorages(array $storages, MessageInterface $message): voi * * {@inheritdoc} */ - public function delete($locale, $domain, $key): void + public function delete(string $locale, string $domain, string $key): void { foreach ([$this->localStorages, $this->remoteStorages] as $storages) { /** @var Storage $storage */ diff --git a/TranslationBundle.php b/TranslationBundle.php index f81a597a..a9cd7670 100644 --- a/TranslationBundle.php +++ b/TranslationBundle.php @@ -16,7 +16,6 @@ use Translation\Bundle\DependencyInjection\CompilerPass\EditInPlacePass; use Translation\Bundle\DependencyInjection\CompilerPass\ExternalTranslatorPass; use Translation\Bundle\DependencyInjection\CompilerPass\ExtractorPass; -use Translation\Bundle\DependencyInjection\CompilerPass\FileDumperBackupPass; use Translation\Bundle\DependencyInjection\CompilerPass\StoragePass; use Translation\Bundle\DependencyInjection\CompilerPass\SymfonyProfilerPass; use Translation\Bundle\DependencyInjection\CompilerPass\ValidatorVisitorPass; @@ -34,6 +33,5 @@ public function build(ContainerBuilder $container): void $container->addCompilerPass(new ExtractorPass()); $container->addCompilerPass(new StoragePass()); $container->addCompilerPass(new EditInPlacePass()); - $container->addCompilerPass(new FileDumperBackupPass()); } } diff --git a/composer.json b/composer.json index e0772bc6..25cb9e6d 100644 --- a/composer.json +++ b/composer.json @@ -18,7 +18,7 @@ "symfony/finder": "^3.4 || ^4.3 || ^5.0", "symfony/intl": "^3.4 || ^4.3 || ^5.0", - "php-translation/symfony-storage": "^1.0", + "php-translation/symfony-storage": "^2.0", "php-translation/extractor": "^1.6", "nyholm/nsa": "^1.1", "twig/twig": "^1.42 || ^2.11" diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 80518274..f36a783f 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -1,10 +1,5 @@ parameters: ignoreErrors: - - - message: "#^Parameter \\$reader of method Translation\\\\Bundle\\\\Catalogue\\\\CatalogueFetcher\\:\\:__construct\\(\\) has invalid typehint type Symfony\\\\Bundle\\\\FrameworkBundle\\\\Translation\\\\TranslationLoader\\.$#" - count: 1 - path: Catalogue/CatalogueFetcher.php - - message: "#^Call to an undefined method Symfony\\\\Component\\\\Console\\\\Application\\:\\:getKernel\\(\\)\\.$#" count: 1