feature #24161 [HttpKernel] Remove bundle inheritance (fabpot)

This PR was merged into the 4.0-dev branch.

Discussion
----------

[HttpKernel] Remove bundle inheritance

| Q             | A
| ------------- | ---
| Branch?       | master
| Bug fix?      | no
| New feature?  | yes
| BC breaks?    | yes
| Deprecations? | no
| Tests pass?   | yes
| Fixed tickets | n/a
| License       | MIT
| Doc PR        | n/a

Blocked by symfony/symfony#24160

Commits
-------

a8a0a21049 [HttpKernel] removed bundle inheritance
This commit is contained in:
Fabien Potencier 2017-09-26 16:11:51 -07:00
commit 92d5134369
14 changed files with 50 additions and 481 deletions

View File

@ -52,47 +52,32 @@ class ControllerNameParser
}
$originalController = $controller;
list($bundle, $controller, $action) = $parts;
list($bundleName, $controller, $action) = $parts;
$controller = str_replace('/', '\\', $controller);
$bundles = array();
try {
// this throws an exception if there is no such bundle
$allBundles = $this->kernel->getBundle($bundle, false, true);
$bundle = $this->kernel->getBundle($bundleName);
} catch (\InvalidArgumentException $e) {
$message = sprintf(
'The "%s" (from the _controller value "%s") does not exist or is not enabled in your kernel!',
$bundle,
$bundleName,
$originalController
);
if ($alternative = $this->findAlternative($bundle)) {
if ($alternative = $this->findAlternative($bundleName)) {
$message .= sprintf(' Did you mean "%s:%s:%s"?', $alternative, $controller, $action);
}
throw new \InvalidArgumentException($message, 0, $e);
}
if (!is_array($allBundles)) {
// happens when HttpKernel is version 4+
$allBundles = array($allBundles);
$try = $bundle->getNamespace().'\\Controller\\'.$controller.'Controller';
if (class_exists($try)) {
return $try.'::'.$action.'Action';
}
foreach ($allBundles as $b) {
$try = $b->getNamespace().'\\Controller\\'.$controller.'Controller';
if (class_exists($try)) {
return $try.'::'.$action.'Action';
}
$bundles[] = $b->getName();
$msg = sprintf('The _controller value "%s:%s:%s" maps to a "%s" class, but this class was not found. Create this class or check the spelling of the class and its namespace.', $bundle, $controller, $action, $try);
}
if (count($bundles) > 1) {
$msg = sprintf('Unable to find controller "%s:%s" in bundles %s.', $bundle, $controller, implode(', ', $bundles));
}
throw new \InvalidArgumentException($msg);
throw new \InvalidArgumentException(sprintf('The _controller value "%s:%s:%s" maps to a "%s" class, but this class was not found. Create this class or check the spelling of the class and its namespace.', $bundleName, $controller, $action, $try));
}
/**

View File

@ -40,7 +40,6 @@ class ControllerNameParserTest extends TestCase
$this->assertEquals('TestBundle\FooBundle\Controller\DefaultController::indexAction', $parser->parse('FooBundle:Default:index'), '->parse() converts a short a:b:c notation string to a class::method string');
$this->assertEquals('TestBundle\FooBundle\Controller\Sub\DefaultController::indexAction', $parser->parse('FooBundle:Sub\Default:index'), '->parse() converts a short a:b:c notation string to a class::method string');
$this->assertEquals('TestBundle\Fabpot\FooBundle\Controller\DefaultController::indexAction', $parser->parse('SensioFooBundle:Default:index'), '->parse() converts a short a:b:c notation string to a class::method string');
$this->assertEquals('TestBundle\Sensio\Cms\FooBundle\Controller\DefaultController::indexAction', $parser->parse('SensioCmsFooBundle:Default:index'), '->parse() converts a short a:b:c notation string to a class::method string');
$this->assertEquals('TestBundle\FooBundle\Controller\Test\DefaultController::indexAction', $parser->parse('FooBundle:Test\\Default:index'), '->parse() converts a short a:b:c notation string to a class::method string');
$this->assertEquals('TestBundle\FooBundle\Controller\Test\DefaultController::indexAction', $parser->parse('FooBundle:Test/Default:index'), '->parse() converts a short a:b:c notation string to a class::method string');
@ -138,7 +137,6 @@ class ControllerNameParserTest extends TestCase
{
return array(
'Alternative will be found using levenshtein' => array('FoodBundle:Default:index', 'FooBundle:Default:index'),
'Alternative will be found using partial match' => array('FabpotFooBund:Default:index', 'FabpotFooBundle:Default:index'),
'Bundle does not exist at all' => array('CrazyBundle:Default:index', false),
);
}
@ -146,10 +144,8 @@ class ControllerNameParserTest extends TestCase
private function createParser()
{
$bundles = array(
'SensioFooBundle' => array($this->getBundle('TestBundle\Fabpot\FooBundle', 'FabpotFooBundle'), $this->getBundle('TestBundle\Sensio\FooBundle', 'SensioFooBundle')),
'SensioCmsFooBundle' => array($this->getBundle('TestBundle\Sensio\Cms\FooBundle', 'SensioCmsFooBundle')),
'FooBundle' => array($this->getBundle('TestBundle\FooBundle', 'FooBundle')),
'FabpotFooBundle' => array($this->getBundle('TestBundle\Fabpot\FooBundle', 'FabpotFooBundle'), $this->getBundle('TestBundle\Sensio\FooBundle', 'SensioFooBundle')),
'SensioCmsFooBundle' => $this->getBundle('TestBundle\Sensio\Cms\FooBundle', 'SensioCmsFooBundle'),
'FooBundle' => $this->getBundle('TestBundle\FooBundle', 'FooBundle'),
);
$kernel = $this->getMockBuilder('Symfony\Component\HttpKernel\KernelInterface')->getMock();
@ -166,11 +162,9 @@ class ControllerNameParserTest extends TestCase
;
$bundles = array(
'SensioFooBundle' => $this->getBundle('TestBundle\Fabpot\FooBundle', 'FabpotFooBundle'),
'SensioCmsFooBundle' => $this->getBundle('TestBundle\Sensio\Cms\FooBundle', 'SensioCmsFooBundle'),
'FoooooBundle' => $this->getBundle('TestBundle\FooBundle', 'FoooooBundle'),
'FooBundle' => $this->getBundle('TestBundle\FooBundle', 'FooBundle'),
'FabpotFooBundle' => $this->getBundle('TestBundle\Fabpot\FooBundle', 'FabpotFooBundle'),
);
$kernel
->expects($this->any())

View File

@ -605,7 +605,7 @@ abstract class FrameworkExtensionTest extends TestCase
$container = $this->createContainerFromFile('validation_annotations', array(
'kernel.bundles' => array('TestBundle' => 'Symfony\\Bundle\\FrameworkBundle\\Tests\\TestBundle'),
'kernel.bundles_metadata' => array('TestBundle' => array('namespace' => 'Symfony\\Bundle\\FrameworkBundle\\Tests', 'parent' => null, 'path' => __DIR__.'/Fixtures/TestBundle')),
'kernel.bundles_metadata' => array('TestBundle' => array('namespace' => 'Symfony\\Bundle\\FrameworkBundle\\Tests', 'path' => __DIR__.'/Fixtures/TestBundle')),
));
$calls = $container->getDefinition('validator.builder')->getMethodCalls();
@ -641,7 +641,7 @@ abstract class FrameworkExtensionTest extends TestCase
$container = $this->createContainerFromFile('validation_annotations', array(
'kernel.bundles' => array('CustomPathBundle' => 'Symfony\\Bundle\\FrameworkBundle\\Tests\\CustomPathBundle'),
'kernel.bundles_metadata' => array('TestBundle' => array('namespace' => 'Symfony\\Bundle\\FrameworkBundle\\Tests', 'parent' => null, 'path' => __DIR__.'/Fixtures/CustomPathBundle')),
'kernel.bundles_metadata' => array('TestBundle' => array('namespace' => 'Symfony\\Bundle\\FrameworkBundle\\Tests', 'path' => __DIR__.'/Fixtures/CustomPathBundle')),
));
$calls = $container->getDefinition('validator.builder')->getMethodCalls();
@ -848,7 +848,7 @@ abstract class FrameworkExtensionTest extends TestCase
public function testSerializerMapping()
{
$container = $this->createContainerFromFile('serializer_mapping', array('kernel.bundles_metadata' => array('TestBundle' => array('namespace' => 'Symfony\\Bundle\\FrameworkBundle\\Tests', 'path' => __DIR__.'/Fixtures/TestBundle', 'parent' => null))));
$container = $this->createContainerFromFile('serializer_mapping', array('kernel.bundles_metadata' => array('TestBundle' => array('namespace' => 'Symfony\\Bundle\\FrameworkBundle\\Tests', 'path' => __DIR__.'/Fixtures/TestBundle'))));
$configDir = __DIR__.'/Fixtures/TestBundle/Resources/config';
$expectedLoaders = array(
new Definition(AnnotationLoader::class, array(new Reference('annotation_reader'))),
@ -980,7 +980,7 @@ abstract class FrameworkExtensionTest extends TestCase
{
return new ContainerBuilder(new ParameterBag(array_merge(array(
'kernel.bundles' => array('FrameworkBundle' => 'Symfony\\Bundle\\FrameworkBundle\\FrameworkBundle'),
'kernel.bundles_metadata' => array('FrameworkBundle' => array('namespace' => 'Symfony\\Bundle\\FrameworkBundle', 'path' => __DIR__.'/../..', 'parent' => null)),
'kernel.bundles_metadata' => array('FrameworkBundle' => array('namespace' => 'Symfony\\Bundle\\FrameworkBundle', 'path' => __DIR__.'/../..')),
'kernel.cache_dir' => __DIR__,
'kernel.project_dir' => __DIR__,
'kernel.debug' => false,

View File

@ -109,18 +109,9 @@ class TwigExtension extends Extension
$container->getDefinition('twig.cache_warmer')->replaceArgument(2, $config['paths']);
$container->getDefinition('twig.template_iterator')->replaceArgument(2, $config['paths']);
$bundleHierarchy = $this->getBundleHierarchy($container, $config);
foreach ($bundleHierarchy as $name => $bundle) {
foreach ($this->getBundleTemplatePaths($container, $config) as $name => $paths) {
$namespace = $this->normalizeBundleName($name);
foreach ($bundle['children'] as $child) {
foreach ($bundleHierarchy[$child]['paths'] as $path) {
$twigFilesystemLoaderDefinition->addMethodCall('addPath', array($path, $namespace));
}
}
foreach ($bundle['paths'] as $path) {
foreach ($paths as $path) {
$twigFilesystemLoaderDefinition->addMethodCall('addPath', array($path, $namespace));
}
}
@ -166,58 +157,24 @@ class TwigExtension extends Extension
$container->registerForAutoconfiguration(RuntimeExtensionInterface::class)->addTag('twig.runtime');
}
private function getBundleHierarchy(ContainerBuilder $container, array $config)
private function getBundleTemplatePaths(ContainerBuilder $container, array $config)
{
$bundleHierarchy = array();
foreach ($container->getParameter('kernel.bundles_metadata') as $name => $bundle) {
if (!array_key_exists($name, $bundleHierarchy)) {
$bundleHierarchy[$name] = array(
'paths' => array(),
'parents' => array(),
'children' => array(),
);
}
if (file_exists($dir = $container->getParameter('kernel.root_dir').'/Resources/'.$name.'/views')) {
$bundleHierarchy[$name]['paths'][] = $dir;
$bundleHierarchy[$name][] = $dir;
}
$container->addResource(new FileExistenceResource($dir));
if (file_exists($dir = $container->getParameterBag()->resolveValue($config['default_path']).'/bundles/'.$name)) {
$bundleHierarchy[$name]['paths'][] = $dir;
$bundleHierarchy[$name][] = $dir;
}
$container->addResource(new FileExistenceResource($dir));
if (file_exists($dir = $bundle['path'].'/Resources/views')) {
$bundleHierarchy[$name]['paths'][] = $dir;
$bundleHierarchy[$name][] = $dir;
}
$container->addResource(new FileExistenceResource($dir));
if (!isset($bundle['parent']) || null === $bundle['parent']) {
continue;
}
$bundleHierarchy[$name]['parents'][] = $bundle['parent'];
if (!array_key_exists($bundle['parent'], $bundleHierarchy)) {
$bundleHierarchy[$bundle['parent']] = array(
'paths' => array(),
'parents' => array(),
'children' => array(),
);
}
$bundleHierarchy[$bundle['parent']]['children'] = array_merge($bundleHierarchy[$name]['children'], array($name), $bundleHierarchy[$bundle['parent']]['children']);
foreach ($bundleHierarchy[$bundle['parent']]['parents'] as $parent) {
$bundleHierarchy[$name]['parents'][] = $parent;
$bundleHierarchy[$parent]['children'] = array_merge($bundleHierarchy[$name]['children'], array($name), $bundleHierarchy[$parent]['children']);
}
foreach ($bundleHierarchy[$name]['children'] as $child) {
$bundleHierarchy[$child]['parents'] = array_merge($bundleHierarchy[$child]['parents'], $bundleHierarchy[$name]['parents']);
}
}
return $bundleHierarchy;

View File

@ -188,23 +188,9 @@ class TwigExtensionTest extends TestCase
array('namespaced_path1', 'namespace1'),
array('namespaced_path2', 'namespace2'),
array('namespaced_path3', 'namespace3'),
array(__DIR__.'/Fixtures/Bundle/ChildChildChildChildTwigBundle/Resources/views', 'ChildChildChildChildTwig'),
array(__DIR__.'/Fixtures/Bundle/ChildChildChildChildTwigBundle/Resources/views', 'ChildChildChildTwig'),
array(__DIR__.'/Fixtures/Bundle/ChildChildChildTwigBundle/Resources/views', 'ChildChildChildTwig'),
array(__DIR__.'/Fixtures/Bundle/ChildChildChildChildTwigBundle/Resources/views', 'Twig'),
array(__DIR__.'/Fixtures/Bundle/ChildChildChildTwigBundle/Resources/views', 'Twig'),
array(__DIR__.'/Fixtures/Bundle/ChildChildTwigBundle/Resources/views', 'Twig'),
array(__DIR__.'/Fixtures/Bundle/ChildTwigBundle/Resources/views', 'Twig'),
array(__DIR__.'/Fixtures/Resources/TwigBundle/views', 'Twig'),
array(__DIR__.'/Fixtures/templates/bundles/TwigBundle', 'Twig'),
array(realpath(__DIR__.'/../..').'/Resources/views', 'Twig'),
array(__DIR__.'/Fixtures/Bundle/ChildChildChildChildTwigBundle/Resources/views', 'ChildTwig'),
array(__DIR__.'/Fixtures/Bundle/ChildChildChildTwigBundle/Resources/views', 'ChildTwig'),
array(__DIR__.'/Fixtures/Bundle/ChildChildTwigBundle/Resources/views', 'ChildTwig'),
array(__DIR__.'/Fixtures/Bundle/ChildTwigBundle/Resources/views', 'ChildTwig'),
array(__DIR__.'/Fixtures/Bundle/ChildChildChildChildTwigBundle/Resources/views', 'ChildChildTwig'),
array(__DIR__.'/Fixtures/Bundle/ChildChildChildTwigBundle/Resources/views', 'ChildChildTwig'),
array(__DIR__.'/Fixtures/Bundle/ChildChildTwigBundle/Resources/views', 'ChildChildTwig'),
array(__DIR__.'/Fixtures/Resources/views'),
array(__DIR__.'/Fixtures/templates'),
), $paths);
@ -284,37 +270,12 @@ class TwigExtensionTest extends TestCase
'kernel.debug' => false,
'kernel.bundles' => array(
'TwigBundle' => 'Symfony\\Bundle\\TwigBundle\\TwigBundle',
'ChildTwigBundle' => 'Symfony\\Bundle\\TwigBundle\\Tests\\DependencyInjection\\Fixtures\\Bundle\\ChildTwigBundle\\ChildTwigBundle',
'ChildChildTwigBundle' => 'Symfony\\Bundle\\TwigBundle\\Tests\\DependencyInjection\\Fixtures\\Bundle\\ChildChildTwigBundle\\ChildChildTwigBundle',
'ChildChildChildTwigBundle' => 'Symfony\\Bundle\\TwigBundle\\Tests\\DependencyInjection\\Fixtures\\Bundle\\ChildChildChildTwigBundle\\ChildChildChildTwigBundle',
'ChildChildChildChildTwigBundle' => 'Symfony\\Bundle\\TwigBundle\\Tests\\DependencyInjection\\Fixtures\\Bundle\\ChildChildChildChildTwigBundle\\ChildChildChildChildTwigBundle',
),
'kernel.bundles_metadata' => array(
'ChildChildChildChildTwigBundle' => array(
'namespace' => 'Symfony\\Bundle\\TwigBundle\\Tests\\DependencyInjection\\Fixtures\\Bundle\\ChildChildChildChildTwigBundle\\ChildChildChildChildTwigBundle',
'parent' => 'ChildChildChildTwigBundle',
'path' => __DIR__.'/Fixtures/Bundle/ChildChildChildChildTwigBundle',
),
'TwigBundle' => array(
'namespace' => 'Symfony\\Bundle\\TwigBundle',
'parent' => null,
'path' => realpath(__DIR__.'/../..'),
),
'ChildTwigBundle' => array(
'namespace' => 'Symfony\\Bundle\\TwigBundle\\Tests\\DependencyInjection\\Fixtures\\Bundle\\ChildTwigBundle\\ChildTwigBundle',
'parent' => 'TwigBundle',
'path' => __DIR__.'/Fixtures/Bundle/ChildTwigBundle',
),
'ChildChildChildTwigBundle' => array(
'namespace' => 'Symfony\\Bundle\\TwigBundle\\Tests\\DependencyInjection\\Fixtures\\Bundle\\ChildChildChildTwigBundle\\ChildChildChildTwigBundle',
'parent' => 'ChildChildTwigBundle',
'path' => __DIR__.'/Fixtures/Bundle/ChildChildChildTwigBundle',
),
'ChildChildTwigBundle' => array(
'namespace' => 'Symfony\\Bundle\\TwigBundle\\Tests\\DependencyInjection\\Fixtures\\Bundle\\ChildChildTwigBundle\\ChildChildTwigBundle',
'parent' => 'ChildTwigBundle',
'path' => __DIR__.'/Fixtures/Bundle/ChildChildTwigBundle',
),
),
)));

View File

@ -128,15 +128,6 @@ abstract class Bundle implements BundleInterface
return $this->path;
}
/**
* Returns the bundle parent name.
*
* @return string|null The Bundle parent name it overrides or null if no parent
*/
public function getParent()
{
}
/**
* Returns the bundle name (the class short name).
*

View File

@ -48,19 +48,6 @@ interface BundleInterface extends ContainerAwareInterface
*/
public function getContainerExtension();
/**
* Returns the bundle name that this bundle overrides.
*
* Despite its name, this method does not imply any parent/child relationship
* between the bundles, just a way to extend and override an existing
* bundle.
*
* @return string The Bundle name it overrides or null if no parent
*
* @deprecated This method is deprecated as of 3.4 and will be removed in 4.0.
*/
public function getParent();
/**
* Returns the bundle name (the class short name).
*

View File

@ -50,7 +50,6 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl
*/
protected $bundles = array();
protected $bundleMap;
protected $container;
protected $rootDir;
protected $environment;
@ -199,26 +198,13 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl
/**
* {@inheritdoc}
*/
public function getBundle($name, $first = true/*, $noDeprecation = false */)
public function getBundle($name)
{
$noDeprecation = false;
if (func_num_args() >= 3) {
$noDeprecation = func_get_arg(2);
}
if (!$first && !$noDeprecation) {
@trigger_error(sprintf('Passing "false" as the second argument to %s() is deprecated as of 3.4 and will be removed in 4.0.', __METHOD__), E_USER_DEPRECATED);
}
if (!isset($this->bundleMap[$name])) {
if (!isset($this->bundles[$name])) {
throw new \InvalidArgumentException(sprintf('Bundle "%s" does not exist or it is not enabled. Maybe you forgot to add it in the registerBundles() method of your %s.php file?', $name, get_class($this)));
}
if (true === $first) {
return $this->bundleMap[$name][0];
}
return $this->bundleMap[$name];
return $this->bundles[$name];
}
/**
@ -245,32 +231,27 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl
$isResource = 0 === strpos($path, 'Resources') && null !== $dir;
$overridePath = substr($path, 9);
$resourceBundle = null;
$bundles = $this->getBundle($bundleName, false, true);
$bundle = $this->getBundle($bundleName);
$files = array();
foreach ($bundles as $bundle) {
if ($isResource && file_exists($file = $dir.'/'.$bundle->getName().$overridePath)) {
if (null !== $resourceBundle) {
throw new \RuntimeException(sprintf('"%s" resource is hidden by a resource from the "%s" derived bundle. Create a "%s" file to override the bundle resource.',
$file,
$resourceBundle,
$dir.'/'.$bundles[0]->getName().$overridePath
));
}
if ($first) {
return $file;
}
$files[] = $file;
if ($isResource && file_exists($file = $dir.'/'.$bundle->getName().$overridePath)) {
if (null !== $resourceBundle) {
throw new \RuntimeException(sprintf('"%s" resource is hidden by a resource from the "%s" derived bundle. Create a "%s" file to override the bundle resource.',
$file,
$resourceBundle,
$dir.'/'.$bundles[0]->getName().$overridePath
));
}
if (file_exists($file = $bundle->getPath().'/'.$path)) {
if ($first && !$isResource) {
return $file;
}
$files[] = $file;
$resourceBundle = $bundle->getName();
$files[] = $file;
}
if (file_exists($file = $bundle->getPath().'/'.$path)) {
if ($first && !$isResource) {
return $file;
}
$files[] = $file;
$resourceBundle = $bundle->getName();
}
if (count($files) > 0) {
@ -395,68 +376,20 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl
}
/**
* Initializes the data structures related to the bundle management.
*
* - the bundles property maps a bundle name to the bundle instance,
* - the bundleMap property maps a bundle name to the bundle inheritance hierarchy (most derived bundle first).
* Initializes bundles.
*
* @throws \LogicException if two bundles share a common name
* @throws \LogicException if a bundle tries to extend a non-registered bundle
* @throws \LogicException if a bundle tries to extend itself
* @throws \LogicException if two bundles extend the same ancestor
*/
protected function initializeBundles()
{
// init bundles
$this->bundles = array();
$topMostBundles = array();
$directChildren = array();
foreach ($this->registerBundles() as $bundle) {
$name = $bundle->getName();
if (isset($this->bundles[$name])) {
throw new \LogicException(sprintf('Trying to register two bundles with the same name "%s"', $name));
}
$this->bundles[$name] = $bundle;
if ($parentName = $bundle->getParent()) {
@trigger_error('Bundle inheritance is deprecated as of 3.4 and will be removed in 4.0.', E_USER_DEPRECATED);
if (isset($directChildren[$parentName])) {
throw new \LogicException(sprintf('Bundle "%s" is directly extended by two bundles "%s" and "%s".', $parentName, $name, $directChildren[$parentName]));
}
if ($parentName == $name) {
throw new \LogicException(sprintf('Bundle "%s" can not extend itself.', $name));
}
$directChildren[$parentName] = $name;
} else {
$topMostBundles[$name] = $bundle;
}
}
// look for orphans
if (!empty($directChildren) && count($diff = array_diff_key($directChildren, $this->bundles))) {
$diff = array_keys($diff);
throw new \LogicException(sprintf('Bundle "%s" extends bundle "%s", which is not registered.', $directChildren[$diff[0]], $diff[0]));
}
// inheritance
$this->bundleMap = array();
foreach ($topMostBundles as $name => $bundle) {
$bundleMap = array($bundle);
$hierarchy = array($name);
while (isset($directChildren[$name])) {
$name = $directChildren[$name];
array_unshift($bundleMap, $this->bundles[$name]);
$hierarchy[] = $name;
}
foreach ($hierarchy as $hierarchyBundle) {
$this->bundleMap[$hierarchyBundle] = $bundleMap;
array_pop($bundleMap);
}
}
}
@ -588,7 +521,6 @@ abstract class Kernel implements KernelInterface, RebootableInterface, Terminabl
foreach ($this->bundles as $name => $bundle) {
$bundles[$name] = get_class($bundle);
$bundlesMetadata[$name] = array(
'parent' => $bundle->getParent(),
'path' => $bundle->getPath(),
'namespace' => $bundle->getNamespace(),
);

View File

@ -58,19 +58,15 @@ interface KernelInterface extends HttpKernelInterface, \Serializable
public function getBundles();
/**
* Returns a bundle and optionally its descendants by its name.
* Returns a bundle.
*
* The second argument is deprecated as of 3.4 and will be removed in 4.0. This method
* will always return an instance of BundleInterface in 4.0.
* @param string $name Bundle name
*
* @param string $name Bundle name
* @param bool $first Whether to return the first bundle only or together with its descendants
*
* @return BundleInterface|BundleInterface[] A BundleInterface instance or an array of BundleInterface instances if $first is false
* @return BundleInterface A BundleInterface instance
*
* @throws \InvalidArgumentException when the bundle is not enabled
*/
public function getBundle($name, $first = true);
public function getBundle($name);
/**
* Returns the file path for a given resource.

View File

@ -331,7 +331,7 @@ EOF;
$kernel
->expects($this->once())
->method('getBundle')
->will($this->returnValue(array($this->getBundle(__DIR__.'/Fixtures/Bundle1Bundle'))))
->will($this->returnValue($this->getBundle(__DIR__.'/Fixtures/Bundle1Bundle')))
;
$kernel->locateResource('@Bundle1Bundle/config/routing.xml');
@ -343,80 +343,19 @@ EOF;
$kernel
->expects($this->once())
->method('getBundle')
->will($this->returnValue(array($this->getBundle(__DIR__.'/Fixtures/Bundle1Bundle'))))
->will($this->returnValue($this->getBundle(__DIR__.'/Fixtures/Bundle1Bundle')))
;
$this->assertEquals(__DIR__.'/Fixtures/Bundle1Bundle/foo.txt', $kernel->locateResource('@Bundle1Bundle/foo.txt'));
}
/**
* @group legacy
*/
public function testLocateResourceReturnsTheFirstThatMatchesWithParent()
{
$parent = $this->getBundle(__DIR__.'/Fixtures/Bundle1Bundle');
$child = $this->getBundle(__DIR__.'/Fixtures/Bundle2Bundle');
$kernel = $this->getKernel(array('getBundle'));
$kernel
->expects($this->exactly(2))
->method('getBundle')
->will($this->returnValue(array($child, $parent)))
;
$this->assertEquals(__DIR__.'/Fixtures/Bundle2Bundle/foo.txt', $kernel->locateResource('@ParentAABundle/foo.txt'));
$this->assertEquals(__DIR__.'/Fixtures/Bundle1Bundle/bar.txt', $kernel->locateResource('@ParentAABundle/bar.txt'));
}
/**
* @group legacy
*/
public function testLocateResourceReturnsAllMatches()
{
$parent = $this->getBundle(__DIR__.'/Fixtures/Bundle1Bundle');
$child = $this->getBundle(__DIR__.'/Fixtures/Bundle2Bundle');
$kernel = $this->getKernel(array('getBundle'));
$kernel
->expects($this->once())
->method('getBundle')
->will($this->returnValue(array($child, $parent)))
;
$this->assertEquals(array(
__DIR__.'/Fixtures/Bundle2Bundle/foo.txt',
__DIR__.'/Fixtures/Bundle1Bundle/foo.txt', ),
$kernel->locateResource('@Bundle1Bundle/foo.txt', null, false));
}
/**
* @group legacy
*/
public function testLocateResourceReturnsAllMatchesBis()
{
$kernel = $this->getKernel(array('getBundle'));
$kernel
->expects($this->once())
->method('getBundle')
->will($this->returnValue(array(
$this->getBundle(__DIR__.'/Fixtures/Bundle1Bundle'),
$this->getBundle(__DIR__.'/Foobar'),
)))
;
$this->assertEquals(
array(__DIR__.'/Fixtures/Bundle1Bundle/foo.txt'),
$kernel->locateResource('@Bundle1Bundle/foo.txt', null, false)
);
}
public function testLocateResourceIgnoresDirOnNonResource()
{
$kernel = $this->getKernel(array('getBundle'));
$kernel
->expects($this->once())
->method('getBundle')
->will($this->returnValue(array($this->getBundle(__DIR__.'/Fixtures/Bundle1Bundle'))))
->will($this->returnValue($this->getBundle(__DIR__.'/Fixtures/Bundle1Bundle')))
;
$this->assertEquals(
@ -431,7 +370,7 @@ EOF;
$kernel
->expects($this->once())
->method('getBundle')
->will($this->returnValue(array($this->getBundle(__DIR__.'/Fixtures/FooBundle', null, null, 'FooBundle'))))
->will($this->returnValue($this->getBundle(__DIR__.'/Fixtures/FooBundle', null, null, 'FooBundle')))
;
$this->assertEquals(
@ -440,73 +379,13 @@ EOF;
);
}
/**
* @group legacy
*/
public function testLocateResourceReturnsTheDirOneForResourcesAndBundleOnes()
{
$kernel = $this->getKernel(array('getBundle'));
$kernel
->expects($this->once())
->method('getBundle')
->will($this->returnValue(array($this->getBundle(__DIR__.'/Fixtures/Bundle1Bundle', null, null, 'Bundle1Bundle'))))
;
$this->assertEquals(array(
__DIR__.'/Fixtures/Resources/Bundle1Bundle/foo.txt',
__DIR__.'/Fixtures/Bundle1Bundle/Resources/foo.txt', ),
$kernel->locateResource('@Bundle1Bundle/Resources/foo.txt', __DIR__.'/Fixtures/Resources', false)
);
}
/**
* @group legacy
*/
public function testLocateResourceOverrideBundleAndResourcesFolders()
{
$parent = $this->getBundle(__DIR__.'/Fixtures/BaseBundle', null, 'BaseBundle', 'BaseBundle');
$child = $this->getBundle(__DIR__.'/Fixtures/ChildBundle', 'ParentBundle', 'ChildBundle', 'ChildBundle');
$kernel = $this->getKernel(array('getBundle'));
$kernel
->expects($this->exactly(4))
->method('getBundle')
->will($this->returnValue(array($child, $parent)))
;
$this->assertEquals(array(
__DIR__.'/Fixtures/Resources/ChildBundle/foo.txt',
__DIR__.'/Fixtures/ChildBundle/Resources/foo.txt',
__DIR__.'/Fixtures/BaseBundle/Resources/foo.txt',
),
$kernel->locateResource('@BaseBundle/Resources/foo.txt', __DIR__.'/Fixtures/Resources', false)
);
$this->assertEquals(
__DIR__.'/Fixtures/Resources/ChildBundle/foo.txt',
$kernel->locateResource('@BaseBundle/Resources/foo.txt', __DIR__.'/Fixtures/Resources')
);
try {
$kernel->locateResource('@BaseBundle/Resources/hide.txt', __DIR__.'/Fixtures/Resources', false);
$this->fail('Hidden resources should raise an exception when returning an array of matching paths');
} catch (\RuntimeException $e) {
}
try {
$kernel->locateResource('@BaseBundle/Resources/hide.txt', __DIR__.'/Fixtures/Resources', true);
$this->fail('Hidden resources should raise an exception when returning the first matching path');
} catch (\RuntimeException $e) {
}
}
public function testLocateResourceOnDirectories()
{
$kernel = $this->getKernel(array('getBundle'));
$kernel
->expects($this->exactly(2))
->method('getBundle')
->will($this->returnValue(array($this->getBundle(__DIR__.'/Fixtures/FooBundle', null, null, 'FooBundle'))))
->will($this->returnValue($this->getBundle(__DIR__.'/Fixtures/FooBundle', null, null, 'FooBundle')))
;
$this->assertEquals(
@ -522,7 +401,7 @@ EOF;
$kernel
->expects($this->exactly(2))
->method('getBundle')
->will($this->returnValue(array($this->getBundle(__DIR__.'/Fixtures/Bundle1Bundle', null, null, 'Bundle1Bundle'))))
->will($this->returnValue($this->getBundle(__DIR__.'/Fixtures/Bundle1Bundle', null, null, 'Bundle1Bundle')))
;
$this->assertEquals(
@ -535,102 +414,6 @@ EOF;
);
}
/**
* @group legacy
*/
public function testInitializeBundles()
{
$parent = $this->getBundle(null, null, 'ParentABundle');
$child = $this->getBundle(null, 'ParentABundle', 'ChildABundle');
// use test kernel so we can access getBundleMap()
$kernel = $this->getKernelForTest(array('registerBundles'));
$kernel
->expects($this->once())
->method('registerBundles')
->will($this->returnValue(array($parent, $child)))
;
$kernel->boot();
$map = $kernel->getBundleMap();
$this->assertEquals(array($child, $parent), $map['ParentABundle']);
}
/**
* @group legacy
*/
public function testInitializeBundlesSupportInheritanceCascade()
{
$grandparent = $this->getBundle(null, null, 'GrandParentBBundle');
$parent = $this->getBundle(null, 'GrandParentBBundle', 'ParentBBundle');
$child = $this->getBundle(null, 'ParentBBundle', 'ChildBBundle');
// use test kernel so we can access getBundleMap()
$kernel = $this->getKernelForTest(array('registerBundles'));
$kernel
->expects($this->once())
->method('registerBundles')
->will($this->returnValue(array($grandparent, $parent, $child)))
;
$kernel->boot();
$map = $kernel->getBundleMap();
$this->assertEquals(array($child, $parent, $grandparent), $map['GrandParentBBundle']);
$this->assertEquals(array($child, $parent), $map['ParentBBundle']);
$this->assertEquals(array($child), $map['ChildBBundle']);
}
/**
* @group legacy
* @expectedException \LogicException
* @expectedExceptionMessage Bundle "ChildCBundle" extends bundle "FooBar", which is not registered.
*/
public function testInitializeBundlesThrowsExceptionWhenAParentDoesNotExists()
{
$child = $this->getBundle(null, 'FooBar', 'ChildCBundle');
$kernel = $this->getKernel(array(), array($child));
$kernel->boot();
}
/**
* @group legacy
*/
public function testInitializeBundlesSupportsArbitraryBundleRegistrationOrder()
{
$grandparent = $this->getBundle(null, null, 'GrandParentCBundle');
$parent = $this->getBundle(null, 'GrandParentCBundle', 'ParentCBundle');
$child = $this->getBundle(null, 'ParentCBundle', 'ChildCBundle');
// use test kernel so we can access getBundleMap()
$kernel = $this->getKernelForTest(array('registerBundles'));
$kernel
->expects($this->once())
->method('registerBundles')
->will($this->returnValue(array($parent, $grandparent, $child)))
;
$kernel->boot();
$map = $kernel->getBundleMap();
$this->assertEquals(array($child, $parent, $grandparent), $map['GrandParentCBundle']);
$this->assertEquals(array($child, $parent), $map['ParentCBundle']);
$this->assertEquals(array($child), $map['ChildCBundle']);
}
/**
* @group legacy
* @expectedException \LogicException
* @expectedExceptionMessage Bundle "ParentCBundle" is directly extended by two bundles "ChildC2Bundle" and "ChildC1Bundle".
*/
public function testInitializeBundlesThrowsExceptionWhenABundleIsDirectlyExtendedByTwoBundles()
{
$parent = $this->getBundle(null, null, 'ParentCBundle');
$child1 = $this->getBundle(null, 'ParentCBundle', 'ChildC1Bundle');
$child2 = $this->getBundle(null, 'ParentCBundle', 'ChildC2Bundle');
$kernel = $this->getKernel(array(), array($parent, $child1, $child2));
$kernel->boot();
}
/**
* @group legacy
* @expectedException \LogicException
@ -645,19 +428,6 @@ EOF;
$kernel->boot();
}
/**
* @group legacy
* @expectedException \LogicException
* @expectedExceptionMessage Bundle "CircularRefBundle" can not extend itself.
*/
public function testInitializeBundleThrowsExceptionWhenABundleExtendsItself()
{
$circularRef = $this->getBundle(null, 'CircularRefBundle', 'CircularRefBundle');
$kernel = $this->getKernel(array(), array($circularRef));
$kernel->boot();
}
public function testTerminateReturnsSilentlyIfKernelIsNotBooted()
{
$kernel = $this->getKernel(array('getHttpKernel'));