[HttpKernel][FrameworkBundle] Add alternative convention for bundle directories
This commit is contained in:
parent
6723bb9cdf
commit
6996e1cbe2
@ -108,9 +108,33 @@ HttpFoundation
|
|||||||
HttpKernel
|
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`
|
* 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
|
Lock
|
||||||
----
|
----
|
||||||
|
@ -286,7 +286,6 @@ HttpFoundation
|
|||||||
HttpKernel
|
HttpKernel
|
||||||
----------
|
----------
|
||||||
|
|
||||||
* The `getPublicDir()` method has been added to the `BundleInterface`.
|
|
||||||
* Removed `Client`, use `HttpKernelBrowser` instead
|
* Removed `Client`, use `HttpKernelBrowser` instead
|
||||||
* The `Kernel::getRootDir()` and the `kernel.root_dir` parameter have been removed
|
* The `Kernel::getRootDir()` and the `kernel.root_dir` parameter have been removed
|
||||||
* The `KernelInterface::getName()` and the `kernel.name` 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`
|
* Removed `TranslatorListener` in favor of `LocaleAwareListener`
|
||||||
* The `DebugHandlersListener` class has been made `final`
|
* The `DebugHandlersListener` class has been made `final`
|
||||||
* Removed `SaveSessionListener` in favor of `AbstractSessionListener`
|
* 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
|
Intl
|
||||||
----
|
----
|
||||||
|
@ -48,11 +48,10 @@ class DoctrineValidationPass implements CompilerPassInterface
|
|||||||
}
|
}
|
||||||
|
|
||||||
$files = $container->getParameter('validator.mapping.loader.'.$mapping.'_files_loader.mapping_files');
|
$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) {
|
foreach ($container->getParameter('kernel.bundles_metadata') as $bundle) {
|
||||||
$reflection = new \ReflectionClass($bundle);
|
if ($container->fileExists($file = $bundle['path'].'/Resources'.$validationPath) || $container->fileExists($file = $bundle['path'].$validationPath)) {
|
||||||
if ($container->fileExists($file = \dirname($reflection->getFileName()).'/'.$validationPath)) {
|
|
||||||
$files[] = $file;
|
$files[] = $file;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -137,13 +137,7 @@ EOT
|
|||||||
$validAssetDirs = [];
|
$validAssetDirs = [];
|
||||||
/** @var BundleInterface $bundle */
|
/** @var BundleInterface $bundle */
|
||||||
foreach ($kernel->getBundles() as $bundle) {
|
foreach ($kernel->getBundles() as $bundle) {
|
||||||
if (!method_exists($bundle, 'getPublicDir')) {
|
if (!is_dir($originDir = $bundle->getPath().'/Resources/public') && !is_dir($originDir = $bundle->getPath().'/public')) {
|
||||||
@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)) {
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -162,7 +162,9 @@ EOF
|
|||||||
if (null !== $input->getArgument('bundle')) {
|
if (null !== $input->getArgument('bundle')) {
|
||||||
try {
|
try {
|
||||||
$bundle = $kernel->getBundle($input->getArgument('bundle'));
|
$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) {
|
if ($this->defaultTransPath) {
|
||||||
$transPaths[] = $this->defaultTransPath;
|
$transPaths[] = $this->defaultTransPath;
|
||||||
}
|
}
|
||||||
@ -171,7 +173,6 @@ EOF
|
|||||||
$notice = sprintf('Storing translations files for "%s" in the "%s" directory is deprecated since Symfony 4.2, ', $dir, $bundle->getName());
|
$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);
|
@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) {
|
if ($this->defaultViewsPath) {
|
||||||
$viewsPaths[] = $this->defaultViewsPath;
|
$viewsPaths[] = $this->defaultViewsPath;
|
||||||
}
|
}
|
||||||
@ -206,13 +207,14 @@ EOF
|
|||||||
}
|
}
|
||||||
} elseif ($input->getOption('all')) {
|
} elseif ($input->getOption('all')) {
|
||||||
foreach ($kernel->getBundles() as $bundle) {
|
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()))) {
|
if (is_dir($deprecatedPath = sprintf('%s/Resources/%s/translations', $rootDir, $bundle->getName()))) {
|
||||||
$transPaths[] = $deprecatedPath;
|
$transPaths[] = $deprecatedPath;
|
||||||
$notice = sprintf('Storing translations files for "%s" in the "%s" directory is deprecated since Symfony 4.2, ', $bundle->getName(), $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);
|
@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()))) {
|
if (is_dir($deprecatedPath = sprintf('%s/Resources/%s/views', $rootDir, $bundle->getName()))) {
|
||||||
$viewsPaths[] = $deprecatedPath;
|
$viewsPaths[] = $deprecatedPath;
|
||||||
$notice = sprintf('Loading Twig templates for "%s" from the "%s" directory is deprecated since Symfony 4.2, ', $bundle->getName(), $deprecatedPath);
|
$notice = sprintf('Loading Twig templates for "%s" from the "%s" directory is deprecated since Symfony 4.2, ', $bundle->getName(), $deprecatedPath);
|
||||||
|
@ -154,7 +154,9 @@ EOF
|
|||||||
if (null !== $input->getArgument('bundle')) {
|
if (null !== $input->getArgument('bundle')) {
|
||||||
try {
|
try {
|
||||||
$foundBundle = $kernel->getBundle($input->getArgument('bundle'));
|
$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) {
|
if ($this->defaultTransPath) {
|
||||||
$transPaths[] = $this->defaultTransPath;
|
$transPaths[] = $this->defaultTransPath;
|
||||||
}
|
}
|
||||||
@ -163,7 +165,6 @@ EOF
|
|||||||
$notice = sprintf('Storing translations files for "%s" in the "%s" directory is deprecated since Symfony 4.2, ', $foundBundle->getName(), $dir);
|
$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);
|
@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) {
|
if ($this->defaultViewsPath) {
|
||||||
$viewsPaths[] = $this->defaultViewsPath;
|
$viewsPaths[] = $this->defaultViewsPath;
|
||||||
}
|
}
|
||||||
|
@ -1152,7 +1152,7 @@ class FrameworkExtension extends Extension
|
|||||||
$defaultDir = $container->getParameterBag()->resolveValue($config['default_path']);
|
$defaultDir = $container->getParameterBag()->resolveValue($config['default_path']);
|
||||||
$rootDir = $container->getParameter('kernel.root_dir');
|
$rootDir = $container->getParameter('kernel.root_dir');
|
||||||
foreach ($container->getParameter('kernel.bundles_metadata') as $name => $bundle) {
|
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;
|
$dirs[] = $dir;
|
||||||
} else {
|
} else {
|
||||||
$nonExistingDirs[] = $dir;
|
$nonExistingDirs[] = $dir;
|
||||||
@ -1314,20 +1314,20 @@ class FrameworkExtension extends Extension
|
|||||||
}
|
}
|
||||||
|
|
||||||
foreach ($container->getParameter('kernel.bundles_metadata') as $bundle) {
|
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 (
|
if (
|
||||||
$container->fileExists($file = $dirname.'/Resources/config/validation.yaml', false) ||
|
$container->fileExists($file = $configDir.'/validation.yaml', false) ||
|
||||||
$container->fileExists($file = $dirname.'/Resources/config/validation.yml', false)
|
$container->fileExists($file = $configDir.'/validation.yml', false)
|
||||||
) {
|
) {
|
||||||
$fileRecorder('yml', $file);
|
$fileRecorder('yml', $file);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($container->fileExists($file = $dirname.'/Resources/config/validation.xml', false)) {
|
if ($container->fileExists($file = $configDir.'/validation.xml', false)) {
|
||||||
$fileRecorder('xml', $file);
|
$fileRecorder('xml', $file);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($container->fileExists($dir = $dirname.'/Resources/config/validation', '/^$/')) {
|
if ($container->fileExists($dir = $configDir.'/validation', '/^$/')) {
|
||||||
$this->registerMappingFilesFromDir($dir, $fileRecorder);
|
$this->registerMappingFilesFromDir($dir, $fileRecorder);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1508,20 +1508,20 @@ class FrameworkExtension extends Extension
|
|||||||
};
|
};
|
||||||
|
|
||||||
foreach ($container->getParameter('kernel.bundles_metadata') as $bundle) {
|
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);
|
$fileRecorder('xml', $file);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (
|
if (
|
||||||
$container->fileExists($file = $dirname.'/Resources/config/serialization.yaml', false) ||
|
$container->fileExists($file = $configDir.'/serialization.yaml', false) ||
|
||||||
$container->fileExists($file = $dirname.'/Resources/config/serialization.yml', false)
|
$container->fileExists($file = $configDir.'/serialization.yml', false)
|
||||||
) {
|
) {
|
||||||
$fileRecorder('yml', $file);
|
$fileRecorder('yml', $file);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($container->fileExists($dir = $dirname.'/Resources/config/serialization', '/^$/')) {
|
if ($container->fileExists($dir = $configDir.'/serialization', '/^$/')) {
|
||||||
$this->registerMappingFilesFromDir($dir, $fileRecorder);
|
$this->registerMappingFilesFromDir($dir, $fileRecorder);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,24 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* 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;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,18 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
{
|
||||||
|
}
|
@ -0,0 +1,4 @@
|
|||||||
|
Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\LegacyBundle\Entity\LegacyPerson:
|
||||||
|
attributes:
|
||||||
|
name:
|
||||||
|
serialized_name: 'full_name'
|
@ -0,0 +1,5 @@
|
|||||||
|
Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\LegacyBundle\Entity\LegacyPerson:
|
||||||
|
properties:
|
||||||
|
age:
|
||||||
|
- GreaterThan:
|
||||||
|
value: 18
|
@ -0,0 +1 @@
|
|||||||
|
ok_label: OK
|
@ -0,0 +1 @@
|
|||||||
|
OK
|
@ -0,0 +1,4 @@
|
|||||||
|
Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\ModernBundle\src\Entity\ModernPerson:
|
||||||
|
attributes:
|
||||||
|
name:
|
||||||
|
serialized_name: 'full_name'
|
@ -0,0 +1,5 @@
|
|||||||
|
Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\ModernBundle\src\Entity\ModernPerson:
|
||||||
|
properties:
|
||||||
|
age:
|
||||||
|
- GreaterThan:
|
||||||
|
value: 18
|
@ -0,0 +1,24 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* 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;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,22 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* 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__);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1 @@
|
|||||||
|
OK
|
@ -0,0 +1 @@
|
|||||||
|
ok_label: OK
|
@ -0,0 +1,84 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* 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'));
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,22 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of the Symfony package.
|
||||||
|
*
|
||||||
|
* (c) Fabien Potencier <fabien@symfony.com>
|
||||||
|
*
|
||||||
|
* 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(),
|
||||||
|
];
|
@ -0,0 +1,11 @@
|
|||||||
|
imports:
|
||||||
|
- { resource: ../config/default.yml }
|
||||||
|
|
||||||
|
framework:
|
||||||
|
translator: true
|
||||||
|
validation: true
|
||||||
|
serializer: true
|
||||||
|
|
||||||
|
twig:
|
||||||
|
strict_variables: '%kernel.debug%'
|
||||||
|
exception_controller: ~
|
@ -188,7 +188,7 @@ class TwigExtension extends Extension
|
|||||||
}
|
}
|
||||||
$container->addResource(new FileExistenceResource($defaultOverrideBundlePath));
|
$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;
|
$bundleHierarchy[$name][] = $dir;
|
||||||
}
|
}
|
||||||
$container->addResource(new FileExistenceResource($dir));
|
$container->addResource(new FileExistenceResource($dir));
|
||||||
|
@ -65,9 +65,11 @@ class TemplateIterator implements \IteratorAggregate
|
|||||||
$name = substr($name, 0, -6);
|
$name = substr($name, 0, -6);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$bundleTemplatesDir = is_dir($bundle->getPath().'/Resources/views') ? $bundle->getPath().'/Resources/views' : $bundle->getPath().'/templates';
|
||||||
|
|
||||||
$templates = array_merge(
|
$templates = array_merge(
|
||||||
$templates,
|
$templates,
|
||||||
$this->findTemplatesInDirectory($bundle->getPath().'/Resources/views', $name),
|
$this->findTemplatesInDirectory($bundleTemplatesDir, $name),
|
||||||
$this->findTemplatesInDirectory($this->rootDir.'/Resources/'.$bundle->getName().'/views', $name)
|
$this->findTemplatesInDirectory($this->rootDir.'/Resources/'.$bundle->getName().'/views', $name)
|
||||||
);
|
);
|
||||||
if (null !== $this->defaultPath) {
|
if (null !== $this->defaultPath) {
|
||||||
|
@ -135,11 +135,6 @@ abstract class Bundle implements BundleInterface
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getPublicDir(): string
|
|
||||||
{
|
|
||||||
return 'Resources/public';
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the bundle's container extension class.
|
* Returns the bundle's container extension class.
|
||||||
*
|
*
|
||||||
|
@ -19,8 +19,6 @@ use Symfony\Component\DependencyInjection\Extension\ExtensionInterface;
|
|||||||
* BundleInterface.
|
* BundleInterface.
|
||||||
*
|
*
|
||||||
* @author Fabien Potencier <fabien@symfony.com>
|
* @author Fabien Potencier <fabien@symfony.com>
|
||||||
*
|
|
||||||
* @method string getPublicDir() Returns relative path for the public assets directory
|
|
||||||
*/
|
*/
|
||||||
interface BundleInterface extends ContainerAwareInterface
|
interface BundleInterface extends ContainerAwareInterface
|
||||||
{
|
{
|
||||||
|
@ -4,9 +4,8 @@ CHANGELOG
|
|||||||
4.4.0
|
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`
|
* The `DebugHandlersListener` class has been marked as `final`
|
||||||
|
* Added new Bundle directory convention consistent with standard skeletons
|
||||||
|
|
||||||
4.3.0
|
4.3.0
|
||||||
-----
|
-----
|
||||||
|
Reference in New Issue
Block a user