From 6996e1cbe2fed324e758e6d1aae5b61eade85bf5 Mon Sep 17 00:00:00 2001 From: Yonel Ceruto Date: Wed, 31 Jul 2019 22:33:32 -0400 Subject: [PATCH] [HttpKernel][FrameworkBundle] Add alternative convention for bundle directories --- UPGRADE-4.4.md | 28 ++++++- UPGRADE-5.0.md | 27 +++++- .../CompilerPass/DoctrineValidationPass.php | 7 +- .../Command/AssetsInstallCommand.php | 8 +- .../Command/TranslationDebugCommand.php | 10 ++- .../Command/TranslationUpdateCommand.php | 5 +- .../FrameworkExtension.php | 22 ++--- .../LegacyBundle/Entity/LegacyPerson.php | 24 ++++++ .../Bundle/LegacyBundle/LegacyBundle.php | 18 ++++ .../Resources/config/serialization.yaml | 4 + .../Resources/config/validation.yaml | 5 ++ .../LegacyBundle/Resources/public/legacy.css | 0 .../Resources/translations/legacy.en.yaml | 1 + .../Resources/views/index.html.twig | 1 + .../ModernBundle/config/serialization.yaml | 4 + .../ModernBundle/config/validation.yaml | 5 ++ .../Bundle/ModernBundle/public/modern.css | 0 .../ModernBundle/src/Entity/ModernPerson.php | 24 ++++++ .../Bundle/ModernBundle/src/ModernBundle.php | 22 +++++ .../ModernBundle/templates/index.html.twig | 1 + .../ModernBundle/translations/modern.en.yaml | 1 + .../Tests/Functional/BundlePathsTest.php | 84 +++++++++++++++++++ .../Functional/app/BundlePaths/bundles.php | 22 +++++ .../Functional/app/BundlePaths/config.yml | 11 +++ .../DependencyInjection/TwigExtension.php | 2 +- .../Bundle/TwigBundle/TemplateIterator.php | 4 +- .../Component/HttpKernel/Bundle/Bundle.php | 5 -- .../HttpKernel/Bundle/BundleInterface.php | 2 - src/Symfony/Component/HttpKernel/CHANGELOG.md | 3 +- 29 files changed, 308 insertions(+), 42 deletions(-) create mode 100644 src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/LegacyBundle/Entity/LegacyPerson.php create mode 100644 src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/LegacyBundle/LegacyBundle.php create mode 100644 src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/LegacyBundle/Resources/config/serialization.yaml create mode 100644 src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/LegacyBundle/Resources/config/validation.yaml create mode 100644 src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/LegacyBundle/Resources/public/legacy.css create mode 100644 src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/LegacyBundle/Resources/translations/legacy.en.yaml create mode 100644 src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/LegacyBundle/Resources/views/index.html.twig create mode 100644 src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/ModernBundle/config/serialization.yaml create mode 100644 src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/ModernBundle/config/validation.yaml create mode 100644 src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/ModernBundle/public/modern.css create mode 100644 src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/ModernBundle/src/Entity/ModernPerson.php create mode 100644 src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/ModernBundle/src/ModernBundle.php create mode 100644 src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/ModernBundle/templates/index.html.twig create mode 100644 src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/ModernBundle/translations/modern.en.yaml create mode 100644 src/Symfony/Bundle/FrameworkBundle/Tests/Functional/BundlePathsTest.php create mode 100644 src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/BundlePaths/bundles.php create mode 100644 src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/BundlePaths/config.yml diff --git a/UPGRADE-4.4.md b/UPGRADE-4.4.md index c3b9ad8688616..de27e3c1cb7f6 100644 --- a/UPGRADE-4.4.md +++ b/UPGRADE-4.4.md @@ -108,9 +108,33 @@ HttpFoundation HttpKernel ---------- - * Implementing the `BundleInterface` without implementing the `getPublicDir()` method is deprecated. - This method will be added to the interface in 5.0. * The `DebugHandlersListener` class has been marked as `final` + * Added new Bundle directory convention consistent with standard skeletons: + + ``` + └── MyBundle/ + ├── config/ + ├── public/ + ├── src/ + │ └── MyBundle.php + ├── templates/ + └── translations/ + ``` + + To make this work properly, it is necessary to change the root path of the bundle: + + ```php + class MyBundle extends Bundle + { + public function getPath(): string + { + return \dirname(__DIR__); + } + } + ``` + + As many bundles must be compatible with a range of Symfony versions, the current + directory convention is not deprecated yet, but it will be in the future. Lock ---- diff --git a/UPGRADE-5.0.md b/UPGRADE-5.0.md index 284e942c9aec3..9dbdca5993c7e 100644 --- a/UPGRADE-5.0.md +++ b/UPGRADE-5.0.md @@ -286,7 +286,6 @@ HttpFoundation HttpKernel ---------- - * The `getPublicDir()` method has been added to the `BundleInterface`. * Removed `Client`, use `HttpKernelBrowser` instead * The `Kernel::getRootDir()` and the `kernel.root_dir` parameter have been removed * The `KernelInterface::getName()` and the `kernel.name` parameter have been removed @@ -303,6 +302,32 @@ HttpKernel * Removed `TranslatorListener` in favor of `LocaleAwareListener` * The `DebugHandlersListener` class has been made `final` * Removed `SaveSessionListener` in favor of `AbstractSessionListener` + * Added new Bundle directory convention consistent with standard skeletons: + + ``` + └── MyBundle/ + ├── config/ + ├── public/ + ├── src/ + │ └── MyBundle.php + ├── templates/ + └── translations/ + ``` + + To make this work properly, it is necessary to change the root path of the bundle: + + ```php + class MyBundle extends Bundle + { + public function getPath(): string + { + return \dirname(__DIR__); + } + } + ``` + + As many bundles must be compatible with a range of Symfony versions, the current + directory convention is not deprecated yet, but it will be in the future. Intl ---- diff --git a/src/Symfony/Bridge/Doctrine/DependencyInjection/CompilerPass/DoctrineValidationPass.php b/src/Symfony/Bridge/Doctrine/DependencyInjection/CompilerPass/DoctrineValidationPass.php index b0db71c929366..25776641796fe 100644 --- a/src/Symfony/Bridge/Doctrine/DependencyInjection/CompilerPass/DoctrineValidationPass.php +++ b/src/Symfony/Bridge/Doctrine/DependencyInjection/CompilerPass/DoctrineValidationPass.php @@ -48,11 +48,10 @@ private function updateValidatorMappingFiles(ContainerBuilder $container, string } $files = $container->getParameter('validator.mapping.loader.'.$mapping.'_files_loader.mapping_files'); - $validationPath = 'Resources/config/validation.'.$this->managerType.'.'.$extension; + $validationPath = '/config/validation.'.$this->managerType.'.'.$extension; - foreach ($container->getParameter('kernel.bundles') as $bundle) { - $reflection = new \ReflectionClass($bundle); - if ($container->fileExists($file = \dirname($reflection->getFileName()).'/'.$validationPath)) { + foreach ($container->getParameter('kernel.bundles_metadata') as $bundle) { + if ($container->fileExists($file = $bundle['path'].'/Resources'.$validationPath) || $container->fileExists($file = $bundle['path'].$validationPath)) { $files[] = $file; } } diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/AssetsInstallCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/AssetsInstallCommand.php index ff7352790cef3..111ed815c73a3 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/AssetsInstallCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/AssetsInstallCommand.php @@ -137,13 +137,7 @@ protected function execute(InputInterface $input, OutputInterface $output) $validAssetDirs = []; /** @var BundleInterface $bundle */ foreach ($kernel->getBundles() as $bundle) { - if (!method_exists($bundle, 'getPublicDir')) { - @trigger_error(sprintf('Not defining "getPublicDir()" method in the "%s" class is deprecated since Symfony 4.4 and will not be supported in 5.0.', \get_class($bundle)), E_USER_DEPRECATED); - $publicDir = 'Resources/public'; - } else { - $publicDir = ltrim($bundle->getPublicDir(), '\\/'); - } - if (!is_dir($originDir = $bundle->getPath().\DIRECTORY_SEPARATOR.$publicDir)) { + if (!is_dir($originDir = $bundle->getPath().'/Resources/public') && !is_dir($originDir = $bundle->getPath().'/public')) { continue; } diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/TranslationDebugCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/TranslationDebugCommand.php index 7058730388a03..85c1e52905758 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/TranslationDebugCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/TranslationDebugCommand.php @@ -162,7 +162,9 @@ protected function execute(InputInterface $input, OutputInterface $output) if (null !== $input->getArgument('bundle')) { try { $bundle = $kernel->getBundle($input->getArgument('bundle')); - $transPaths = [$bundle->getPath().'/Resources/translations']; + $bundleDir = $bundle->getPath(); + $transPaths = [is_dir($bundleDir.'/Resources/translations') ? $bundleDir.'/Resources/translations' : $bundleDir.'/translations']; + $viewsPaths = [is_dir($bundleDir.'/Resources/views') ? $bundleDir.'/Resources/views' : $bundleDir.'/templates']; if ($this->defaultTransPath) { $transPaths[] = $this->defaultTransPath; } @@ -171,7 +173,6 @@ protected function execute(InputInterface $input, OutputInterface $output) $notice = sprintf('Storing translations files for "%s" in the "%s" directory is deprecated since Symfony 4.2, ', $dir, $bundle->getName()); @trigger_error($notice.($this->defaultTransPath ? sprintf('use the "%s" directory instead.', $this->defaultTransPath) : 'configure and use "framework.translator.default_path" instead.'), E_USER_DEPRECATED); } - $viewsPaths = [$bundle->getPath().'/Resources/views']; if ($this->defaultViewsPath) { $viewsPaths[] = $this->defaultViewsPath; } @@ -206,13 +207,14 @@ protected function execute(InputInterface $input, OutputInterface $output) } } elseif ($input->getOption('all')) { foreach ($kernel->getBundles() as $bundle) { - $transPaths[] = $bundle->getPath().'/Resources/translations'; + $bundleDir = $bundle->getPath(); + $transPaths[] = is_dir($bundleDir.'/Resources/translations') ? $bundleDir.'/Resources/translations' : $bundle->getPath().'/translations'; + $viewsPaths[] = is_dir($bundleDir.'/Resources/views') ? $bundleDir.'/Resources/views' : $bundle->getPath().'/templates'; if (is_dir($deprecatedPath = sprintf('%s/Resources/%s/translations', $rootDir, $bundle->getName()))) { $transPaths[] = $deprecatedPath; $notice = sprintf('Storing translations files for "%s" in the "%s" directory is deprecated since Symfony 4.2, ', $bundle->getName(), $deprecatedPath); @trigger_error($notice.($this->defaultTransPath ? sprintf('use the "%s" directory instead.', $this->defaultTransPath) : 'configure and use "framework.translator.default_path" instead.'), E_USER_DEPRECATED); } - $viewsPaths[] = $bundle->getPath().'/Resources/views'; if (is_dir($deprecatedPath = sprintf('%s/Resources/%s/views', $rootDir, $bundle->getName()))) { $viewsPaths[] = $deprecatedPath; $notice = sprintf('Loading Twig templates for "%s" from the "%s" directory is deprecated since Symfony 4.2, ', $bundle->getName(), $deprecatedPath); diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/TranslationUpdateCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/TranslationUpdateCommand.php index ded71fd60e4bb..25bd9c1e2939b 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/TranslationUpdateCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/TranslationUpdateCommand.php @@ -154,7 +154,9 @@ protected function execute(InputInterface $input, OutputInterface $output) if (null !== $input->getArgument('bundle')) { try { $foundBundle = $kernel->getBundle($input->getArgument('bundle')); - $transPaths = [$foundBundle->getPath().'/Resources/translations']; + $bundleDir = $foundBundle->getPath(); + $transPaths = [is_dir($bundleDir.'/Resources/translations') ? $bundleDir.'/Resources/translations' : $bundleDir.'/translations']; + $viewsPaths = [is_dir($bundleDir.'/Resources/views') ? $bundleDir.'/Resources/views' : $bundleDir.'/templates']; if ($this->defaultTransPath) { $transPaths[] = $this->defaultTransPath; } @@ -163,7 +165,6 @@ protected function execute(InputInterface $input, OutputInterface $output) $notice = sprintf('Storing translations files for "%s" in the "%s" directory is deprecated since Symfony 4.2, ', $foundBundle->getName(), $dir); @trigger_error($notice.($this->defaultTransPath ? sprintf('use the "%s" directory instead.', $this->defaultTransPath) : 'configure and use "framework.translator.default_path" instead.'), E_USER_DEPRECATED); } - $viewsPaths = [$foundBundle->getPath().'/Resources/views']; if ($this->defaultViewsPath) { $viewsPaths[] = $this->defaultViewsPath; } diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php index 158c329fa38ad..f0b4bf00e3e12 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php @@ -1152,7 +1152,7 @@ private function registerTranslatorConfiguration(array $config, ContainerBuilder $defaultDir = $container->getParameterBag()->resolveValue($config['default_path']); $rootDir = $container->getParameter('kernel.root_dir'); foreach ($container->getParameter('kernel.bundles_metadata') as $name => $bundle) { - if ($container->fileExists($dir = $bundle['path'].'/Resources/translations')) { + if ($container->fileExists($dir = $bundle['path'].'/Resources/translations') || $container->fileExists($dir = $bundle['path'].'/translations')) { $dirs[] = $dir; } else { $nonExistingDirs[] = $dir; @@ -1314,20 +1314,20 @@ private function registerValidatorMapping(ContainerBuilder $container, array $co } foreach ($container->getParameter('kernel.bundles_metadata') as $bundle) { - $dirname = $bundle['path']; + $configDir = is_dir($bundle['path'].'/Resources/config') ? $bundle['path'].'/Resources/config' : $bundle['path'].'/config'; if ( - $container->fileExists($file = $dirname.'/Resources/config/validation.yaml', false) || - $container->fileExists($file = $dirname.'/Resources/config/validation.yml', false) + $container->fileExists($file = $configDir.'/validation.yaml', false) || + $container->fileExists($file = $configDir.'/validation.yml', false) ) { $fileRecorder('yml', $file); } - if ($container->fileExists($file = $dirname.'/Resources/config/validation.xml', false)) { + if ($container->fileExists($file = $configDir.'/validation.xml', false)) { $fileRecorder('xml', $file); } - if ($container->fileExists($dir = $dirname.'/Resources/config/validation', '/^$/')) { + if ($container->fileExists($dir = $configDir.'/validation', '/^$/')) { $this->registerMappingFilesFromDir($dir, $fileRecorder); } } @@ -1508,20 +1508,20 @@ private function registerSerializerConfiguration(array $config, ContainerBuilder }; foreach ($container->getParameter('kernel.bundles_metadata') as $bundle) { - $dirname = $bundle['path']; + $configDir = is_dir($bundle['path'].'/Resources/config') ? $bundle['path'].'/Resources/config' : $bundle['path'].'/config'; - if ($container->fileExists($file = $dirname.'/Resources/config/serialization.xml', false)) { + if ($container->fileExists($file = $configDir.'/serialization.xml', false)) { $fileRecorder('xml', $file); } if ( - $container->fileExists($file = $dirname.'/Resources/config/serialization.yaml', false) || - $container->fileExists($file = $dirname.'/Resources/config/serialization.yml', false) + $container->fileExists($file = $configDir.'/serialization.yaml', false) || + $container->fileExists($file = $configDir.'/serialization.yml', false) ) { $fileRecorder('yml', $file); } - if ($container->fileExists($dir = $dirname.'/Resources/config/serialization', '/^$/')) { + if ($container->fileExists($dir = $configDir.'/serialization', '/^$/')) { $this->registerMappingFilesFromDir($dir, $fileRecorder); } } diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/LegacyBundle/Entity/LegacyPerson.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/LegacyBundle/Entity/LegacyPerson.php new file mode 100644 index 0000000000000..8135e95e89c02 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/LegacyBundle/Entity/LegacyPerson.php @@ -0,0 +1,24 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\LegacyBundle\Entity; + +class LegacyPerson +{ + public $name; + public $age; + + public function __construct(string $name, string $age) + { + $this->name = $name; + $this->age = $age; + } +} diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/LegacyBundle/LegacyBundle.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/LegacyBundle/LegacyBundle.php new file mode 100644 index 0000000000000..e38e38824b324 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/LegacyBundle/LegacyBundle.php @@ -0,0 +1,18 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\LegacyBundle; + +use Symfony\Component\HttpKernel\Bundle\Bundle; + +class LegacyBundle extends Bundle +{ +} diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/LegacyBundle/Resources/config/serialization.yaml b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/LegacyBundle/Resources/config/serialization.yaml new file mode 100644 index 0000000000000..c878793ea9a2a --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/LegacyBundle/Resources/config/serialization.yaml @@ -0,0 +1,4 @@ +Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\LegacyBundle\Entity\LegacyPerson: + attributes: + name: + serialized_name: 'full_name' diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/LegacyBundle/Resources/config/validation.yaml b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/LegacyBundle/Resources/config/validation.yaml new file mode 100644 index 0000000000000..c59b8cb168bb2 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/LegacyBundle/Resources/config/validation.yaml @@ -0,0 +1,5 @@ +Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\LegacyBundle\Entity\LegacyPerson: + properties: + age: + - GreaterThan: + value: 18 diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/LegacyBundle/Resources/public/legacy.css b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/LegacyBundle/Resources/public/legacy.css new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/LegacyBundle/Resources/translations/legacy.en.yaml b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/LegacyBundle/Resources/translations/legacy.en.yaml new file mode 100644 index 0000000000000..1860a9d6340b6 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/LegacyBundle/Resources/translations/legacy.en.yaml @@ -0,0 +1 @@ +ok_label: OK diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/LegacyBundle/Resources/views/index.html.twig b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/LegacyBundle/Resources/views/index.html.twig new file mode 100644 index 0000000000000..d86bac9de59ab --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/LegacyBundle/Resources/views/index.html.twig @@ -0,0 +1 @@ +OK diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/ModernBundle/config/serialization.yaml b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/ModernBundle/config/serialization.yaml new file mode 100644 index 0000000000000..d83e457f0a2ec --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/ModernBundle/config/serialization.yaml @@ -0,0 +1,4 @@ +Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\ModernBundle\src\Entity\ModernPerson: + attributes: + name: + serialized_name: 'full_name' diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/ModernBundle/config/validation.yaml b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/ModernBundle/config/validation.yaml new file mode 100644 index 0000000000000..f3044c3b19edb --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/ModernBundle/config/validation.yaml @@ -0,0 +1,5 @@ +Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\ModernBundle\src\Entity\ModernPerson: + properties: + age: + - GreaterThan: + value: 18 diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/ModernBundle/public/modern.css b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/ModernBundle/public/modern.css new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/ModernBundle/src/Entity/ModernPerson.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/ModernBundle/src/Entity/ModernPerson.php new file mode 100644 index 0000000000000..6c22925d65eb0 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/ModernBundle/src/Entity/ModernPerson.php @@ -0,0 +1,24 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\ModernBundle\src\Entity; + +class ModernPerson +{ + public $name; + public $age; + + public function __construct(string $name, string $age) + { + $this->name = $name; + $this->age = $age; + } +} diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/ModernBundle/src/ModernBundle.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/ModernBundle/src/ModernBundle.php new file mode 100644 index 0000000000000..cc29f998ee964 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/ModernBundle/src/ModernBundle.php @@ -0,0 +1,22 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\ModernBundle\src; + +use Symfony\Component\HttpKernel\Bundle\Bundle; + +class ModernBundle extends Bundle +{ + public function getPath(): string + { + return \dirname(__DIR__); + } +} diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/ModernBundle/templates/index.html.twig b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/ModernBundle/templates/index.html.twig new file mode 100644 index 0000000000000..d86bac9de59ab --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/ModernBundle/templates/index.html.twig @@ -0,0 +1 @@ +OK diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/ModernBundle/translations/modern.en.yaml b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/ModernBundle/translations/modern.en.yaml new file mode 100644 index 0000000000000..1860a9d6340b6 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/ModernBundle/translations/modern.en.yaml @@ -0,0 +1 @@ +ok_label: OK diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/BundlePathsTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/BundlePathsTest.php new file mode 100644 index 0000000000000..f447300c2c69c --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/BundlePathsTest.php @@ -0,0 +1,84 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +namespace Symfony\Bundle\FrameworkBundle\Tests\Functional; + +use Symfony\Bundle\FrameworkBundle\Command\AssetsInstallCommand; +use Symfony\Bundle\FrameworkBundle\Console\Application; +use Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\LegacyBundle\Entity\LegacyPerson; +use Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\ModernBundle\src\Entity\ModernPerson; +use Symfony\Component\Console\Tester\CommandTester; +use Symfony\Component\Filesystem\Filesystem; + +class BundlePathsTest extends AbstractWebTestCase +{ + public function testBundlePublicDir() + { + $kernel = static::bootKernel(['test_case' => 'BundlePaths']); + $projectDir = sys_get_temp_dir().'/'.uniqid('sf_bundle_paths', true); + + $fs = new Filesystem(); + $fs->mkdir($projectDir.'/public'); + $command = (new Application($kernel))->add(new AssetsInstallCommand($fs, $projectDir)); + $exitCode = (new CommandTester($command))->execute(['target' => $projectDir.'/public']); + + $this->assertSame(0, $exitCode); + $this->assertFileExists($projectDir.'/public/bundles/modern/modern.css'); + $this->assertFileExists($projectDir.'/public/bundles/legacy/legacy.css'); + + $fs->remove($projectDir); + } + + public function testBundleTwigTemplatesDir() + { + static::bootKernel(['test_case' => 'BundlePaths']); + $twig = static::$container->get('twig'); + $bundlesMetadata = static::$container->getParameter('kernel.bundles_metadata'); + + $this->assertSame([$bundlesMetadata['LegacyBundle']['path'].'/Resources/views'], $twig->getLoader()->getPaths('Legacy')); + $this->assertSame("OK\n", $twig->render('@Legacy/index.html.twig')); + + $this->assertSame([$bundlesMetadata['ModernBundle']['path'].'/templates'], $twig->getLoader()->getPaths('Modern')); + $this->assertSame("OK\n", $twig->render('@Modern/index.html.twig')); + } + + public function testBundleTranslationsDir() + { + static::bootKernel(['test_case' => 'BundlePaths']); + $translator = static::$container->get('translator'); + + $this->assertSame('OK', $translator->trans('ok_label', [], 'legacy')); + $this->assertSame('OK', $translator->trans('ok_label', [], 'modern')); + } + + public function testBundleValidationConfigDir() + { + static::bootKernel(['test_case' => 'BundlePaths']); + $validator = static::$container->get('validator'); + + $this->assertTrue($validator->hasMetadataFor(LegacyPerson::class)); + $this->assertCount(1, $constraintViolationList = $validator->validate(new LegacyPerson('john', 5))); + $this->assertSame('This value should be greater than 18.', $constraintViolationList->get(0)->getMessage()); + + $this->assertTrue($validator->hasMetadataFor(ModernPerson::class)); + $this->assertCount(1, $constraintViolationList = $validator->validate(new ModernPerson('john', 5))); + $this->assertSame('This value should be greater than 18.', $constraintViolationList->get(0)->getMessage()); + } + + public function testBundleSerializationConfigDir() + { + static::bootKernel(['test_case' => 'BundlePaths']); + $serializer = static::$container->get('serializer'); + + $this->assertEquals(['full_name' => 'john', 'age' => 5], $serializer->normalize(new LegacyPerson('john', 5), 'json')); + $this->assertEquals(['full_name' => 'john', 'age' => 5], $serializer->normalize(new ModernPerson('john', 5), 'json')); + } +} diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/BundlePaths/bundles.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/BundlePaths/bundles.php new file mode 100644 index 0000000000000..7e01199ea7909 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/BundlePaths/bundles.php @@ -0,0 +1,22 @@ + + * + * For the full copyright and license information, please view the LICENSE + * file that was distributed with this source code. + */ + +use Symfony\Bundle\FrameworkBundle\FrameworkBundle; +use Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\LegacyBundle\LegacyBundle; +use Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\ModernBundle\src\ModernBundle; +use Symfony\Bundle\TwigBundle\TwigBundle; + +return [ + new FrameworkBundle(), + new TwigBundle(), + new ModernBundle(), + new LegacyBundle(), +]; diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/BundlePaths/config.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/BundlePaths/config.yml new file mode 100644 index 0000000000000..4a2d4c57ef6a4 --- /dev/null +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/app/BundlePaths/config.yml @@ -0,0 +1,11 @@ +imports: + - { resource: ../config/default.yml } + +framework: + translator: true + validation: true + serializer: true + +twig: + strict_variables: '%kernel.debug%' + exception_controller: ~ diff --git a/src/Symfony/Bundle/TwigBundle/DependencyInjection/TwigExtension.php b/src/Symfony/Bundle/TwigBundle/DependencyInjection/TwigExtension.php index e21b60b002081..b15516d465c1e 100644 --- a/src/Symfony/Bundle/TwigBundle/DependencyInjection/TwigExtension.php +++ b/src/Symfony/Bundle/TwigBundle/DependencyInjection/TwigExtension.php @@ -188,7 +188,7 @@ private function getBundleTemplatePaths(ContainerBuilder $container, array $conf } $container->addResource(new FileExistenceResource($defaultOverrideBundlePath)); - if (file_exists($dir = $bundle['path'].'/Resources/views')) { + if (file_exists($dir = $bundle['path'].'/Resources/views') || file_exists($dir = $bundle['path'].'/templates')) { $bundleHierarchy[$name][] = $dir; } $container->addResource(new FileExistenceResource($dir)); diff --git a/src/Symfony/Bundle/TwigBundle/TemplateIterator.php b/src/Symfony/Bundle/TwigBundle/TemplateIterator.php index 4d4d835dfeb25..b96a18318bf48 100644 --- a/src/Symfony/Bundle/TwigBundle/TemplateIterator.php +++ b/src/Symfony/Bundle/TwigBundle/TemplateIterator.php @@ -65,9 +65,11 @@ public function getIterator() $name = substr($name, 0, -6); } + $bundleTemplatesDir = is_dir($bundle->getPath().'/Resources/views') ? $bundle->getPath().'/Resources/views' : $bundle->getPath().'/templates'; + $templates = array_merge( $templates, - $this->findTemplatesInDirectory($bundle->getPath().'/Resources/views', $name), + $this->findTemplatesInDirectory($bundleTemplatesDir, $name), $this->findTemplatesInDirectory($this->rootDir.'/Resources/'.$bundle->getName().'/views', $name) ); if (null !== $this->defaultPath) { diff --git a/src/Symfony/Component/HttpKernel/Bundle/Bundle.php b/src/Symfony/Component/HttpKernel/Bundle/Bundle.php index ca190ee69543e..26dea9b205193 100644 --- a/src/Symfony/Component/HttpKernel/Bundle/Bundle.php +++ b/src/Symfony/Component/HttpKernel/Bundle/Bundle.php @@ -135,11 +135,6 @@ public function registerCommands(Application $application) { } - public function getPublicDir(): string - { - return 'Resources/public'; - } - /** * Returns the bundle's container extension class. * diff --git a/src/Symfony/Component/HttpKernel/Bundle/BundleInterface.php b/src/Symfony/Component/HttpKernel/Bundle/BundleInterface.php index c45754b3ee1e0..88a95d8332942 100644 --- a/src/Symfony/Component/HttpKernel/Bundle/BundleInterface.php +++ b/src/Symfony/Component/HttpKernel/Bundle/BundleInterface.php @@ -19,8 +19,6 @@ * BundleInterface. * * @author Fabien Potencier - * - * @method string getPublicDir() Returns relative path for the public assets directory */ interface BundleInterface extends ContainerAwareInterface { diff --git a/src/Symfony/Component/HttpKernel/CHANGELOG.md b/src/Symfony/Component/HttpKernel/CHANGELOG.md index feae351734b69..4087d4f66a9a2 100644 --- a/src/Symfony/Component/HttpKernel/CHANGELOG.md +++ b/src/Symfony/Component/HttpKernel/CHANGELOG.md @@ -4,9 +4,8 @@ CHANGELOG 4.4.0 ----- - * Implementing the `BundleInterface` without implementing the `getPublicDir()` method is deprecated. - This method will be added to the interface in 5.0. * The `DebugHandlersListener` class has been marked as `final` + * Added new Bundle directory convention consistent with standard skeletons 4.3.0 ----- pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy