Skip to content

Commit 32e0a25

Browse files
feature #32845 [HttpKernel][FrameworkBundle] Add alternative convention for bundle directories (yceruto)
This PR was squashed before being merged into the 4.4 branch (closes #32845). Discussion ---------- [HttpKernel][FrameworkBundle] Add alternative convention for bundle directories | Q | A | ------------- | --- | Branch? | 4.4 | Bug fix? | no | New feature? | yes | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | #32453 | License | MIT | Doc PR | TODO We already know that bundles must be compatible with many Symfony's versions, so it is very likely that current bundles won't be able to use this feature soon, unless they create symbolic links to support both structures. The point is that this is already happening, so in the future when our bundles stop to support <=4.3 then you'll be sure to change the current directory structure. We have recently added the `getPublicDir()` method in #31975, here I'm removing it in favor of hardcoding a new convention. I've added some functional tests in which I've changed everything to this structure: ``` -- ModernBundle |-- config/ |-- public/ |-- src/ |-- ModernBundle.php |-- templates/ |-- translations/ ``` WDYT? Commits ------- 6996e1c [HttpKernel][FrameworkBundle] Add alternative convention for bundle directories
2 parents d6773bc + 6996e1c commit 32e0a25

File tree

29 files changed

+308
-42
lines changed

29 files changed

+308
-42
lines changed

UPGRADE-4.4.md

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -113,9 +113,33 @@ HttpFoundation
113113
HttpKernel
114114
----------
115115

116-
* Implementing the `BundleInterface` without implementing the `getPublicDir()` method is deprecated.
117-
This method will be added to the interface in 5.0.
118116
* The `DebugHandlersListener` class has been marked as `final`
117+
* Added new Bundle directory convention consistent with standard skeletons:
118+
119+
```
120+
└── MyBundle/
121+
├── config/
122+
├── public/
123+
├── src/
124+
│ └── MyBundle.php
125+
├── templates/
126+
└── translations/
127+
```
128+
129+
To make this work properly, it is necessary to change the root path of the bundle:
130+
131+
```php
132+
class MyBundle extends Bundle
133+
{
134+
public function getPath(): string
135+
{
136+
return \dirname(__DIR__);
137+
}
138+
}
139+
```
140+
141+
As many bundles must be compatible with a range of Symfony versions, the current
142+
directory convention is not deprecated yet, but it will be in the future.
119143

120144
Lock
121145
----

UPGRADE-5.0.md

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -291,7 +291,6 @@ HttpFoundation
291291
HttpKernel
292292
----------
293293

294-
* The `getPublicDir()` method has been added to the `BundleInterface`.
295294
* Removed `Client`, use `HttpKernelBrowser` instead
296295
* The `Kernel::getRootDir()` and the `kernel.root_dir` parameter have been removed
297296
* The `KernelInterface::getName()` and the `kernel.name` parameter have been removed
@@ -308,6 +307,32 @@ HttpKernel
308307
* Removed `TranslatorListener` in favor of `LocaleAwareListener`
309308
* The `DebugHandlersListener` class has been made `final`
310309
* Removed `SaveSessionListener` in favor of `AbstractSessionListener`
310+
* Added new Bundle directory convention consistent with standard skeletons:
311+
312+
```
313+
└── MyBundle/
314+
├── config/
315+
├── public/
316+
├── src/
317+
│ └── MyBundle.php
318+
├── templates/
319+
└── translations/
320+
```
321+
322+
To make this work properly, it is necessary to change the root path of the bundle:
323+
324+
```php
325+
class MyBundle extends Bundle
326+
{
327+
public function getPath(): string
328+
{
329+
return \dirname(__DIR__);
330+
}
331+
}
332+
```
333+
334+
As many bundles must be compatible with a range of Symfony versions, the current
335+
directory convention is not deprecated yet, but it will be in the future.
311336

312337
Intl
313338
----

src/Symfony/Bridge/Doctrine/DependencyInjection/CompilerPass/DoctrineValidationPass.php

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -48,11 +48,10 @@ private function updateValidatorMappingFiles(ContainerBuilder $container, string
4848
}
4949

5050
$files = $container->getParameter('validator.mapping.loader.'.$mapping.'_files_loader.mapping_files');
51-
$validationPath = 'Resources/config/validation.'.$this->managerType.'.'.$extension;
51+
$validationPath = '/config/validation.'.$this->managerType.'.'.$extension;
5252

53-
foreach ($container->getParameter('kernel.bundles') as $bundle) {
54-
$reflection = new \ReflectionClass($bundle);
55-
if ($container->fileExists($file = \dirname($reflection->getFileName()).'/'.$validationPath)) {
53+
foreach ($container->getParameter('kernel.bundles_metadata') as $bundle) {
54+
if ($container->fileExists($file = $bundle['path'].'/Resources'.$validationPath) || $container->fileExists($file = $bundle['path'].$validationPath)) {
5655
$files[] = $file;
5756
}
5857
}

src/Symfony/Bundle/FrameworkBundle/Command/AssetsInstallCommand.php

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -137,13 +137,7 @@ protected function execute(InputInterface $input, OutputInterface $output)
137137
$validAssetDirs = [];
138138
/** @var BundleInterface $bundle */
139139
foreach ($kernel->getBundles() as $bundle) {
140-
if (!method_exists($bundle, 'getPublicDir')) {
141-
@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);
142-
$publicDir = 'Resources/public';
143-
} else {
144-
$publicDir = ltrim($bundle->getPublicDir(), '\\/');
145-
}
146-
if (!is_dir($originDir = $bundle->getPath().\DIRECTORY_SEPARATOR.$publicDir)) {
140+
if (!is_dir($originDir = $bundle->getPath().'/Resources/public') && !is_dir($originDir = $bundle->getPath().'/public')) {
147141
continue;
148142
}
149143

src/Symfony/Bundle/FrameworkBundle/Command/TranslationDebugCommand.php

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,9 @@ protected function execute(InputInterface $input, OutputInterface $output)
162162
if (null !== $input->getArgument('bundle')) {
163163
try {
164164
$bundle = $kernel->getBundle($input->getArgument('bundle'));
165-
$transPaths = [$bundle->getPath().'/Resources/translations'];
165+
$bundleDir = $bundle->getPath();
166+
$transPaths = [is_dir($bundleDir.'/Resources/translations') ? $bundleDir.'/Resources/translations' : $bundleDir.'/translations'];
167+
$viewsPaths = [is_dir($bundleDir.'/Resources/views') ? $bundleDir.'/Resources/views' : $bundleDir.'/templates'];
166168
if ($this->defaultTransPath) {
167169
$transPaths[] = $this->defaultTransPath;
168170
}
@@ -171,7 +173,6 @@ protected function execute(InputInterface $input, OutputInterface $output)
171173
$notice = sprintf('Storing translations files for "%s" in the "%s" directory is deprecated since Symfony 4.2, ', $dir, $bundle->getName());
172174
@trigger_error($notice.($this->defaultTransPath ? sprintf('use the "%s" directory instead.', $this->defaultTransPath) : 'configure and use "framework.translator.default_path" instead.'), E_USER_DEPRECATED);
173175
}
174-
$viewsPaths = [$bundle->getPath().'/Resources/views'];
175176
if ($this->defaultViewsPath) {
176177
$viewsPaths[] = $this->defaultViewsPath;
177178
}
@@ -206,13 +207,14 @@ protected function execute(InputInterface $input, OutputInterface $output)
206207
}
207208
} elseif ($input->getOption('all')) {
208209
foreach ($kernel->getBundles() as $bundle) {
209-
$transPaths[] = $bundle->getPath().'/Resources/translations';
210+
$bundleDir = $bundle->getPath();
211+
$transPaths[] = is_dir($bundleDir.'/Resources/translations') ? $bundleDir.'/Resources/translations' : $bundle->getPath().'/translations';
212+
$viewsPaths[] = is_dir($bundleDir.'/Resources/views') ? $bundleDir.'/Resources/views' : $bundle->getPath().'/templates';
210213
if (is_dir($deprecatedPath = sprintf('%s/Resources/%s/translations', $rootDir, $bundle->getName()))) {
211214
$transPaths[] = $deprecatedPath;
212215
$notice = sprintf('Storing translations files for "%s" in the "%s" directory is deprecated since Symfony 4.2, ', $bundle->getName(), $deprecatedPath);
213216
@trigger_error($notice.($this->defaultTransPath ? sprintf('use the "%s" directory instead.', $this->defaultTransPath) : 'configure and use "framework.translator.default_path" instead.'), E_USER_DEPRECATED);
214217
}
215-
$viewsPaths[] = $bundle->getPath().'/Resources/views';
216218
if (is_dir($deprecatedPath = sprintf('%s/Resources/%s/views', $rootDir, $bundle->getName()))) {
217219
$viewsPaths[] = $deprecatedPath;
218220
$notice = sprintf('Loading Twig templates for "%s" from the "%s" directory is deprecated since Symfony 4.2, ', $bundle->getName(), $deprecatedPath);

src/Symfony/Bundle/FrameworkBundle/Command/TranslationUpdateCommand.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,9 @@ protected function execute(InputInterface $input, OutputInterface $output)
154154
if (null !== $input->getArgument('bundle')) {
155155
try {
156156
$foundBundle = $kernel->getBundle($input->getArgument('bundle'));
157-
$transPaths = [$foundBundle->getPath().'/Resources/translations'];
157+
$bundleDir = $foundBundle->getPath();
158+
$transPaths = [is_dir($bundleDir.'/Resources/translations') ? $bundleDir.'/Resources/translations' : $bundleDir.'/translations'];
159+
$viewsPaths = [is_dir($bundleDir.'/Resources/views') ? $bundleDir.'/Resources/views' : $bundleDir.'/templates'];
158160
if ($this->defaultTransPath) {
159161
$transPaths[] = $this->defaultTransPath;
160162
}
@@ -163,7 +165,6 @@ protected function execute(InputInterface $input, OutputInterface $output)
163165
$notice = sprintf('Storing translations files for "%s" in the "%s" directory is deprecated since Symfony 4.2, ', $foundBundle->getName(), $dir);
164166
@trigger_error($notice.($this->defaultTransPath ? sprintf('use the "%s" directory instead.', $this->defaultTransPath) : 'configure and use "framework.translator.default_path" instead.'), E_USER_DEPRECATED);
165167
}
166-
$viewsPaths = [$foundBundle->getPath().'/Resources/views'];
167168
if ($this->defaultViewsPath) {
168169
$viewsPaths[] = $this->defaultViewsPath;
169170
}

src/Symfony/Bundle/FrameworkBundle/DependencyInjection/FrameworkExtension.php

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1156,7 +1156,7 @@ private function registerTranslatorConfiguration(array $config, ContainerBuilder
11561156
$defaultDir = $container->getParameterBag()->resolveValue($config['default_path']);
11571157
$rootDir = $container->getParameter('kernel.root_dir');
11581158
foreach ($container->getParameter('kernel.bundles_metadata') as $name => $bundle) {
1159-
if ($container->fileExists($dir = $bundle['path'].'/Resources/translations')) {
1159+
if ($container->fileExists($dir = $bundle['path'].'/Resources/translations') || $container->fileExists($dir = $bundle['path'].'/translations')) {
11601160
$dirs[] = $dir;
11611161
} else {
11621162
$nonExistingDirs[] = $dir;
@@ -1318,20 +1318,20 @@ private function registerValidatorMapping(ContainerBuilder $container, array $co
13181318
}
13191319

13201320
foreach ($container->getParameter('kernel.bundles_metadata') as $bundle) {
1321-
$dirname = $bundle['path'];
1321+
$configDir = is_dir($bundle['path'].'/Resources/config') ? $bundle['path'].'/Resources/config' : $bundle['path'].'/config';
13221322

13231323
if (
1324-
$container->fileExists($file = $dirname.'/Resources/config/validation.yaml', false) ||
1325-
$container->fileExists($file = $dirname.'/Resources/config/validation.yml', false)
1324+
$container->fileExists($file = $configDir.'/validation.yaml', false) ||
1325+
$container->fileExists($file = $configDir.'/validation.yml', false)
13261326
) {
13271327
$fileRecorder('yml', $file);
13281328
}
13291329

1330-
if ($container->fileExists($file = $dirname.'/Resources/config/validation.xml', false)) {
1330+
if ($container->fileExists($file = $configDir.'/validation.xml', false)) {
13311331
$fileRecorder('xml', $file);
13321332
}
13331333

1334-
if ($container->fileExists($dir = $dirname.'/Resources/config/validation', '/^$/')) {
1334+
if ($container->fileExists($dir = $configDir.'/validation', '/^$/')) {
13351335
$this->registerMappingFilesFromDir($dir, $fileRecorder);
13361336
}
13371337
}
@@ -1512,20 +1512,20 @@ private function registerSerializerConfiguration(array $config, ContainerBuilder
15121512
};
15131513

15141514
foreach ($container->getParameter('kernel.bundles_metadata') as $bundle) {
1515-
$dirname = $bundle['path'];
1515+
$configDir = is_dir($bundle['path'].'/Resources/config') ? $bundle['path'].'/Resources/config' : $bundle['path'].'/config';
15161516

1517-
if ($container->fileExists($file = $dirname.'/Resources/config/serialization.xml', false)) {
1517+
if ($container->fileExists($file = $configDir.'/serialization.xml', false)) {
15181518
$fileRecorder('xml', $file);
15191519
}
15201520

15211521
if (
1522-
$container->fileExists($file = $dirname.'/Resources/config/serialization.yaml', false) ||
1523-
$container->fileExists($file = $dirname.'/Resources/config/serialization.yml', false)
1522+
$container->fileExists($file = $configDir.'/serialization.yaml', false) ||
1523+
$container->fileExists($file = $configDir.'/serialization.yml', false)
15241524
) {
15251525
$fileRecorder('yml', $file);
15261526
}
15271527

1528-
if ($container->fileExists($dir = $dirname.'/Resources/config/serialization', '/^$/')) {
1528+
if ($container->fileExists($dir = $configDir.'/serialization', '/^$/')) {
15291529
$this->registerMappingFilesFromDir($dir, $fileRecorder);
15301530
}
15311531
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\LegacyBundle\Entity;
13+
14+
class LegacyPerson
15+
{
16+
public $name;
17+
public $age;
18+
19+
public function __construct(string $name, string $age)
20+
{
21+
$this->name = $name;
22+
$this->age = $age;
23+
}
24+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\LegacyBundle;
13+
14+
use Symfony\Component\HttpKernel\Bundle\Bundle;
15+
16+
class LegacyBundle extends Bundle
17+
{
18+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\LegacyBundle\Entity\LegacyPerson:
2+
attributes:
3+
name:
4+
serialized_name: 'full_name'

0 commit comments

Comments
 (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