This repository has been archived on 2023-08-20. You can view files and clone it, but cannot push or open issues or pull requests.
symfony/src/Symfony/Component/HttpKernel/Kernel.php

742 lines
22 KiB
PHP
Raw Normal View History

<?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.
*/
removed Symfony\Framework Things have been moved to Symfony\Component\HttpKernel and Symfony\Bundle\FrameworkBundle The kernel configuration namespace was removed and merged with the main web configuration namespace (kernel:config => web:config, kernel:test => web:test, and kernel:session => web:session): Before: <kernel:config charset="UTF-8" error_handler="null" /> <web:config csrf-secret="xxxxxxxxxx"> <web:router resource="%kernel.root_dir%/config/routing.xml" /> <web:validation enabled="true" annotations="true" /> </web:config> After: <web:config csrf-secret="xxxxxxxxxx" charset="UTF-8" error-handler="null"> <web:router resource="%kernel.root_dir%/config/routing.xml" /> <web:validation enabled="true" annotations="true" /> </web:config> Renamed classes: Symfony\{Framework => Bundle\FrameworkBundle}\Cache\Cache Symfony\{Framework => Bundle\FrameworkBundle}\Client Symfony\{Framework => Bundle\FrameworkBundle}\Debug\EventDispatcher Symfony\{Framework => Bundle\FrameworkBundle}\Debug\EventDispatcherTraceableInterface Symfony\{Framework => Bundle\FrameworkBundle}\EventDispatcher Symfony\{Framework => Component\HttpFoundation}\UniversalClassLoader Symfony\{Framework => Component\HttpKernel}\Bundle\Bundle Symfony\{Framework => Component\HttpKernel}\Bundle\BundleInterface Symfony\{Framework => Component\HttpKernel}\ClassCollectionLoader Symfony\{Framework => Component\HttpKernel}\Debug\ErrorException Symfony\{Framework => Component\HttpKernel}\Debug\ErrorHandler Symfony\{Bundle\FrameworkBundle => Component\HttpKernel}\Debug\ExceptionListener Symfony\{Framework => Component\HttpKernel}\Kernel
2010-09-15 19:49:16 +01:00
namespace Symfony\Component\HttpKernel;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Dumper\PhpDumper;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
use Symfony\Component\DependencyInjection\Loader\XmlFileLoader;
use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
use Symfony\Component\DependencyInjection\Loader\IniFileLoader;
use Symfony\Component\DependencyInjection\Loader\PhpFileLoader;
use Symfony\Component\DependencyInjection\Loader\ClosureLoader;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\HttpKernelInterface;
refactored bundle management Before I explain the changes, let's talk about the current state. Before this patch, the registerBundleDirs() method returned an ordered (for resource overloading) list of namespace prefixes and the path to their location. Here are some problems with this approach: * The paths set by this method and the paths configured for the autoloader can be disconnected (leading to unexpected behaviors); * A bundle outside these paths worked, but unexpected behavior can occur; * Choosing a bundle namespace was limited to the registered namespace prefixes, and their number should stay low enough (for performance reasons) -- moreover the current Bundle\ and Application\ top namespaces does not respect the standard rules for namespaces (first segment should be the vendor name); * Developers must understand the concept of "namespace prefixes" to understand the overloading mechanism, which is one more thing to learn, which is Symfony specific; * Each time you want to get a resource that can be overloaded (a template for instance), Symfony would have tried all namespace prefixes one after the other until if finds a matching file. But that can be computed in advance to reduce the overhead. Another topic which was not really well addressed is how you can reference a file/resource from a bundle (and take into account the possibility of overloading). For instance, in the routing, you can import a file from a bundle like this: <import resource="FrameworkBundle/Resources/config/internal.xml" /> Again, this works only because we have a limited number of possible namespace prefixes. This patch addresses these problems and some more. First, the registerBundleDirs() method has been removed. It means that you are now free to use any namespace for your bundles. No need to have specific prefixes anymore. You are also free to store them anywhere, in as many directories as you want. You just need to be sure that they are autoloaded correctly. The bundle "name" is now always the short name of the bundle class (like FrameworkBundle or SensioCasBundle). As the best practice is to prefix the bundle name with the vendor name, it's up to the vendor to ensure that each bundle name is unique. I insist that a bundle name must be unique. This was the opposite before as two bundles with the same name was how Symfony2 found inheritance. A new getParent() method has been added to BundleInterface. It returns the bundle name that the bundle overrides (this is optional of course). That way, there is no ordering problem anymore as the inheritance tree is explicitely defined by the bundle themselves. So, with this system, we can easily have an inheritance tree like the following: FooBundle < MyFooBundle < MyCustomFooBundle MyCustomFooBundle returns MyFooBundle for the getParent() method, and MyFooBundle returns FooBundle. If two bundles override the same bundle, an exception is thrown. Based on the bundle name, you can now reference any resource with this notation: @FooBundle/Resources/config/routing.xml @FooBundle/Controller/FooController.php This notation is the input of the Kernel::locateResource() method, which returns the location of the file (and of course it takes into account overloading). So, in the routing, you can now use the following: <import resource="@FrameworkBundle/Resources/config/internal.xml" /> The template loading mechanism also use this method under the hood. As a bonus, all the code that converts from internal notations to file names (controller names: ControllerNameParser, template names: TemplateNameParser, resource paths, ...) is now contained in several well-defined classes. The same goes for the code that look for templates (TemplateLocator), routing files (FileLocator), ... As a side note, it is really easy to also support multiple-inheritance for a bundle (for instance if a bundle returns an array of bundle names it extends). However, this is not implemented in this patch as I'm not sure we want to support that. How to upgrade: * Each bundle must now implement two new mandatory methods: getPath() and getNamespace(), and optionally the getParent() method if the bundle extends another one. Here is a common implementation for these methods: /** * {@inheritdoc} */ public function getParent() { return 'MyFrameworkBundle'; } /** * {@inheritdoc} */ public function getNamespace() { return __NAMESPACE__; } /** * {@inheritdoc} */ public function getPath() { return strtr(__DIR__, '\\', '/'); } * The registerBundleDirs() can be removed from your Kernel class; * If your code relies on getBundleDirs() or the kernel.bundle_dirs parameter, it should be upgraded to use the new interface (see Doctrine commands for many example of such a change); * When referencing a bundle, you must now always use its name (no more \ or / in bundle names) -- this transition was already done for most things before, and now applies to the routing as well; * Imports in routing files must be changed: Before: <import resource="Sensio/CasBundle/Resources/config/internal.xml" /> After: <import resource="@SensioCasBundle/Resources/config/internal.xml" />
2011-01-18 09:23:49 +00:00
use Symfony\Component\HttpKernel\Bundle\BundleInterface;
use Symfony\Component\HttpKernel\Config\FileLocator;
use Symfony\Component\HttpKernel\DependencyInjection\MergeExtensionConfigurationPass;
use Symfony\Component\HttpKernel\DependencyInjection\AddClassesToCachePass;
use Symfony\Component\HttpKernel\Debug\ErrorHandler;
use Symfony\Component\HttpKernel\Debug\ExceptionHandler;
use Symfony\Component\Config\Loader\LoaderResolver;
use Symfony\Component\Config\Loader\DelegatingLoader;
use Symfony\Component\Config\ConfigCache;
use Symfony\Component\ClassLoader\ClassCollectionLoader;
use Symfony\Component\ClassLoader\DebugUniversalClassLoader;
/**
2011-01-23 12:17:50 +00:00
* The Kernel is the heart of the Symfony system.
*
* It manages an environment made of bundles.
*
* @author Fabien Potencier <fabien@symfony.com>
2011-07-20 09:14:31 +01:00
*
* @api
*/
2011-01-25 16:07:37 +00:00
abstract class Kernel implements KernelInterface
{
protected $bundles;
refactored bundle management Before I explain the changes, let's talk about the current state. Before this patch, the registerBundleDirs() method returned an ordered (for resource overloading) list of namespace prefixes and the path to their location. Here are some problems with this approach: * The paths set by this method and the paths configured for the autoloader can be disconnected (leading to unexpected behaviors); * A bundle outside these paths worked, but unexpected behavior can occur; * Choosing a bundle namespace was limited to the registered namespace prefixes, and their number should stay low enough (for performance reasons) -- moreover the current Bundle\ and Application\ top namespaces does not respect the standard rules for namespaces (first segment should be the vendor name); * Developers must understand the concept of "namespace prefixes" to understand the overloading mechanism, which is one more thing to learn, which is Symfony specific; * Each time you want to get a resource that can be overloaded (a template for instance), Symfony would have tried all namespace prefixes one after the other until if finds a matching file. But that can be computed in advance to reduce the overhead. Another topic which was not really well addressed is how you can reference a file/resource from a bundle (and take into account the possibility of overloading). For instance, in the routing, you can import a file from a bundle like this: <import resource="FrameworkBundle/Resources/config/internal.xml" /> Again, this works only because we have a limited number of possible namespace prefixes. This patch addresses these problems and some more. First, the registerBundleDirs() method has been removed. It means that you are now free to use any namespace for your bundles. No need to have specific prefixes anymore. You are also free to store them anywhere, in as many directories as you want. You just need to be sure that they are autoloaded correctly. The bundle "name" is now always the short name of the bundle class (like FrameworkBundle or SensioCasBundle). As the best practice is to prefix the bundle name with the vendor name, it's up to the vendor to ensure that each bundle name is unique. I insist that a bundle name must be unique. This was the opposite before as two bundles with the same name was how Symfony2 found inheritance. A new getParent() method has been added to BundleInterface. It returns the bundle name that the bundle overrides (this is optional of course). That way, there is no ordering problem anymore as the inheritance tree is explicitely defined by the bundle themselves. So, with this system, we can easily have an inheritance tree like the following: FooBundle < MyFooBundle < MyCustomFooBundle MyCustomFooBundle returns MyFooBundle for the getParent() method, and MyFooBundle returns FooBundle. If two bundles override the same bundle, an exception is thrown. Based on the bundle name, you can now reference any resource with this notation: @FooBundle/Resources/config/routing.xml @FooBundle/Controller/FooController.php This notation is the input of the Kernel::locateResource() method, which returns the location of the file (and of course it takes into account overloading). So, in the routing, you can now use the following: <import resource="@FrameworkBundle/Resources/config/internal.xml" /> The template loading mechanism also use this method under the hood. As a bonus, all the code that converts from internal notations to file names (controller names: ControllerNameParser, template names: TemplateNameParser, resource paths, ...) is now contained in several well-defined classes. The same goes for the code that look for templates (TemplateLocator), routing files (FileLocator), ... As a side note, it is really easy to also support multiple-inheritance for a bundle (for instance if a bundle returns an array of bundle names it extends). However, this is not implemented in this patch as I'm not sure we want to support that. How to upgrade: * Each bundle must now implement two new mandatory methods: getPath() and getNamespace(), and optionally the getParent() method if the bundle extends another one. Here is a common implementation for these methods: /** * {@inheritdoc} */ public function getParent() { return 'MyFrameworkBundle'; } /** * {@inheritdoc} */ public function getNamespace() { return __NAMESPACE__; } /** * {@inheritdoc} */ public function getPath() { return strtr(__DIR__, '\\', '/'); } * The registerBundleDirs() can be removed from your Kernel class; * If your code relies on getBundleDirs() or the kernel.bundle_dirs parameter, it should be upgraded to use the new interface (see Doctrine commands for many example of such a change); * When referencing a bundle, you must now always use its name (no more \ or / in bundle names) -- this transition was already done for most things before, and now applies to the routing as well; * Imports in routing files must be changed: Before: <import resource="Sensio/CasBundle/Resources/config/internal.xml" /> After: <import resource="@SensioCasBundle/Resources/config/internal.xml" />
2011-01-18 09:23:49 +00:00
protected $bundleMap;
protected $container;
protected $rootDir;
protected $environment;
protected $debug;
protected $booted;
protected $name;
protected $startTime;
protected $classes;
2012-08-28 08:05:44 +01:00
const VERSION = '2.0.17';
2012-07-11 19:25:42 +01:00
const VERSION_ID = '20017';
const MAJOR_VERSION = '2';
const MINOR_VERSION = '0';
2012-07-11 19:25:42 +01:00
const RELEASE_VERSION = '17';
2012-08-28 08:05:44 +01:00
const EXTRA_VERSION = '';
/**
* Constructor.
*
* @param string $environment The environment
* @param Boolean $debug Whether to enable debugging or not
2011-07-20 09:14:31 +01:00
*
* @api
*/
public function __construct($environment, $debug)
{
$this->environment = $environment;
$this->debug = (Boolean) $debug;
$this->booted = false;
$this->rootDir = $this->getRootDir();
$this->name = preg_replace('/[^a-zA-Z0-9_]+/', '', basename($this->rootDir));
$this->classes = array();
if ($this->debug) {
$this->startTime = microtime(true);
}
$this->init();
}
public function init()
{
if ($this->debug) {
ini_set('display_errors', 1);
error_reporting(-1);
DebugUniversalClassLoader::enable();
ErrorHandler::register();
if ('cli' !== php_sapi_name()) {
ExceptionHandler::register();
}
} else {
ini_set('display_errors', 0);
}
}
2010-06-10 16:54:39 +01:00
public function __clone()
{
if ($this->debug) {
$this->startTime = microtime(true);
}
$this->booted = false;
$this->container = null;
}
/**
* Boots the current kernel.
2011-07-20 09:14:31 +01:00
*
* @api
*/
public function boot()
{
if (true === $this->booted) {
2011-01-23 12:17:50 +00:00
return;
}
refactored bundle management Before I explain the changes, let's talk about the current state. Before this patch, the registerBundleDirs() method returned an ordered (for resource overloading) list of namespace prefixes and the path to their location. Here are some problems with this approach: * The paths set by this method and the paths configured for the autoloader can be disconnected (leading to unexpected behaviors); * A bundle outside these paths worked, but unexpected behavior can occur; * Choosing a bundle namespace was limited to the registered namespace prefixes, and their number should stay low enough (for performance reasons) -- moreover the current Bundle\ and Application\ top namespaces does not respect the standard rules for namespaces (first segment should be the vendor name); * Developers must understand the concept of "namespace prefixes" to understand the overloading mechanism, which is one more thing to learn, which is Symfony specific; * Each time you want to get a resource that can be overloaded (a template for instance), Symfony would have tried all namespace prefixes one after the other until if finds a matching file. But that can be computed in advance to reduce the overhead. Another topic which was not really well addressed is how you can reference a file/resource from a bundle (and take into account the possibility of overloading). For instance, in the routing, you can import a file from a bundle like this: <import resource="FrameworkBundle/Resources/config/internal.xml" /> Again, this works only because we have a limited number of possible namespace prefixes. This patch addresses these problems and some more. First, the registerBundleDirs() method has been removed. It means that you are now free to use any namespace for your bundles. No need to have specific prefixes anymore. You are also free to store them anywhere, in as many directories as you want. You just need to be sure that they are autoloaded correctly. The bundle "name" is now always the short name of the bundle class (like FrameworkBundle or SensioCasBundle). As the best practice is to prefix the bundle name with the vendor name, it's up to the vendor to ensure that each bundle name is unique. I insist that a bundle name must be unique. This was the opposite before as two bundles with the same name was how Symfony2 found inheritance. A new getParent() method has been added to BundleInterface. It returns the bundle name that the bundle overrides (this is optional of course). That way, there is no ordering problem anymore as the inheritance tree is explicitely defined by the bundle themselves. So, with this system, we can easily have an inheritance tree like the following: FooBundle < MyFooBundle < MyCustomFooBundle MyCustomFooBundle returns MyFooBundle for the getParent() method, and MyFooBundle returns FooBundle. If two bundles override the same bundle, an exception is thrown. Based on the bundle name, you can now reference any resource with this notation: @FooBundle/Resources/config/routing.xml @FooBundle/Controller/FooController.php This notation is the input of the Kernel::locateResource() method, which returns the location of the file (and of course it takes into account overloading). So, in the routing, you can now use the following: <import resource="@FrameworkBundle/Resources/config/internal.xml" /> The template loading mechanism also use this method under the hood. As a bonus, all the code that converts from internal notations to file names (controller names: ControllerNameParser, template names: TemplateNameParser, resource paths, ...) is now contained in several well-defined classes. The same goes for the code that look for templates (TemplateLocator), routing files (FileLocator), ... As a side note, it is really easy to also support multiple-inheritance for a bundle (for instance if a bundle returns an array of bundle names it extends). However, this is not implemented in this patch as I'm not sure we want to support that. How to upgrade: * Each bundle must now implement two new mandatory methods: getPath() and getNamespace(), and optionally the getParent() method if the bundle extends another one. Here is a common implementation for these methods: /** * {@inheritdoc} */ public function getParent() { return 'MyFrameworkBundle'; } /** * {@inheritdoc} */ public function getNamespace() { return __NAMESPACE__; } /** * {@inheritdoc} */ public function getPath() { return strtr(__DIR__, '\\', '/'); } * The registerBundleDirs() can be removed from your Kernel class; * If your code relies on getBundleDirs() or the kernel.bundle_dirs parameter, it should be upgraded to use the new interface (see Doctrine commands for many example of such a change); * When referencing a bundle, you must now always use its name (no more \ or / in bundle names) -- this transition was already done for most things before, and now applies to the routing as well; * Imports in routing files must be changed: Before: <import resource="Sensio/CasBundle/Resources/config/internal.xml" /> After: <import resource="@SensioCasBundle/Resources/config/internal.xml" />
2011-01-18 09:23:49 +00:00
// init bundles
$this->initializeBundles();
2011-01-20 10:38:17 +00:00
refactored bundle management Before I explain the changes, let's talk about the current state. Before this patch, the registerBundleDirs() method returned an ordered (for resource overloading) list of namespace prefixes and the path to their location. Here are some problems with this approach: * The paths set by this method and the paths configured for the autoloader can be disconnected (leading to unexpected behaviors); * A bundle outside these paths worked, but unexpected behavior can occur; * Choosing a bundle namespace was limited to the registered namespace prefixes, and their number should stay low enough (for performance reasons) -- moreover the current Bundle\ and Application\ top namespaces does not respect the standard rules for namespaces (first segment should be the vendor name); * Developers must understand the concept of "namespace prefixes" to understand the overloading mechanism, which is one more thing to learn, which is Symfony specific; * Each time you want to get a resource that can be overloaded (a template for instance), Symfony would have tried all namespace prefixes one after the other until if finds a matching file. But that can be computed in advance to reduce the overhead. Another topic which was not really well addressed is how you can reference a file/resource from a bundle (and take into account the possibility of overloading). For instance, in the routing, you can import a file from a bundle like this: <import resource="FrameworkBundle/Resources/config/internal.xml" /> Again, this works only because we have a limited number of possible namespace prefixes. This patch addresses these problems and some more. First, the registerBundleDirs() method has been removed. It means that you are now free to use any namespace for your bundles. No need to have specific prefixes anymore. You are also free to store them anywhere, in as many directories as you want. You just need to be sure that they are autoloaded correctly. The bundle "name" is now always the short name of the bundle class (like FrameworkBundle or SensioCasBundle). As the best practice is to prefix the bundle name with the vendor name, it's up to the vendor to ensure that each bundle name is unique. I insist that a bundle name must be unique. This was the opposite before as two bundles with the same name was how Symfony2 found inheritance. A new getParent() method has been added to BundleInterface. It returns the bundle name that the bundle overrides (this is optional of course). That way, there is no ordering problem anymore as the inheritance tree is explicitely defined by the bundle themselves. So, with this system, we can easily have an inheritance tree like the following: FooBundle < MyFooBundle < MyCustomFooBundle MyCustomFooBundle returns MyFooBundle for the getParent() method, and MyFooBundle returns FooBundle. If two bundles override the same bundle, an exception is thrown. Based on the bundle name, you can now reference any resource with this notation: @FooBundle/Resources/config/routing.xml @FooBundle/Controller/FooController.php This notation is the input of the Kernel::locateResource() method, which returns the location of the file (and of course it takes into account overloading). So, in the routing, you can now use the following: <import resource="@FrameworkBundle/Resources/config/internal.xml" /> The template loading mechanism also use this method under the hood. As a bonus, all the code that converts from internal notations to file names (controller names: ControllerNameParser, template names: TemplateNameParser, resource paths, ...) is now contained in several well-defined classes. The same goes for the code that look for templates (TemplateLocator), routing files (FileLocator), ... As a side note, it is really easy to also support multiple-inheritance for a bundle (for instance if a bundle returns an array of bundle names it extends). However, this is not implemented in this patch as I'm not sure we want to support that. How to upgrade: * Each bundle must now implement two new mandatory methods: getPath() and getNamespace(), and optionally the getParent() method if the bundle extends another one. Here is a common implementation for these methods: /** * {@inheritdoc} */ public function getParent() { return 'MyFrameworkBundle'; } /** * {@inheritdoc} */ public function getNamespace() { return __NAMESPACE__; } /** * {@inheritdoc} */ public function getPath() { return strtr(__DIR__, '\\', '/'); } * The registerBundleDirs() can be removed from your Kernel class; * If your code relies on getBundleDirs() or the kernel.bundle_dirs parameter, it should be upgraded to use the new interface (see Doctrine commands for many example of such a change); * When referencing a bundle, you must now always use its name (no more \ or / in bundle names) -- this transition was already done for most things before, and now applies to the routing as well; * Imports in routing files must be changed: Before: <import resource="Sensio/CasBundle/Resources/config/internal.xml" /> After: <import resource="@SensioCasBundle/Resources/config/internal.xml" />
2011-01-18 09:23:49 +00:00
// init container
2011-01-20 10:38:17 +00:00
$this->initializeContainer();
foreach ($this->getBundles() as $bundle) {
2010-08-10 15:59:12 +01:00
$bundle->setContainer($this->container);
$bundle->boot();
}
$this->booted = true;
}
/**
* Shutdowns the kernel.
*
* This method is mainly useful when doing functional testing.
2011-07-20 09:14:31 +01:00
*
* @api
*/
public function shutdown()
{
if (false === $this->booted) {
return;
}
$this->booted = false;
foreach ($this->getBundles() as $bundle) {
2010-08-10 15:59:12 +01:00
$bundle->shutdown();
$bundle->setContainer(null);
}
$this->container = null;
}
/**
* {@inheritdoc}
2011-07-20 09:14:31 +01:00
*
* @api
*/
public function handle(Request $request, $type = HttpKernelInterface::MASTER_REQUEST, $catch = true)
{
if (false === $this->booted) {
$this->boot();
}
return $this->getHttpKernel()->handle($request, $type, $catch);
}
/**
* Gets a http kernel from the container
*
* @return HttpKernel
*/
protected function getHttpKernel()
{
return $this->container->get('http_kernel');
}
2010-05-19 09:24:36 +01:00
/**
refactored bundle management Before I explain the changes, let's talk about the current state. Before this patch, the registerBundleDirs() method returned an ordered (for resource overloading) list of namespace prefixes and the path to their location. Here are some problems with this approach: * The paths set by this method and the paths configured for the autoloader can be disconnected (leading to unexpected behaviors); * A bundle outside these paths worked, but unexpected behavior can occur; * Choosing a bundle namespace was limited to the registered namespace prefixes, and their number should stay low enough (for performance reasons) -- moreover the current Bundle\ and Application\ top namespaces does not respect the standard rules for namespaces (first segment should be the vendor name); * Developers must understand the concept of "namespace prefixes" to understand the overloading mechanism, which is one more thing to learn, which is Symfony specific; * Each time you want to get a resource that can be overloaded (a template for instance), Symfony would have tried all namespace prefixes one after the other until if finds a matching file. But that can be computed in advance to reduce the overhead. Another topic which was not really well addressed is how you can reference a file/resource from a bundle (and take into account the possibility of overloading). For instance, in the routing, you can import a file from a bundle like this: <import resource="FrameworkBundle/Resources/config/internal.xml" /> Again, this works only because we have a limited number of possible namespace prefixes. This patch addresses these problems and some more. First, the registerBundleDirs() method has been removed. It means that you are now free to use any namespace for your bundles. No need to have specific prefixes anymore. You are also free to store them anywhere, in as many directories as you want. You just need to be sure that they are autoloaded correctly. The bundle "name" is now always the short name of the bundle class (like FrameworkBundle or SensioCasBundle). As the best practice is to prefix the bundle name with the vendor name, it's up to the vendor to ensure that each bundle name is unique. I insist that a bundle name must be unique. This was the opposite before as two bundles with the same name was how Symfony2 found inheritance. A new getParent() method has been added to BundleInterface. It returns the bundle name that the bundle overrides (this is optional of course). That way, there is no ordering problem anymore as the inheritance tree is explicitely defined by the bundle themselves. So, with this system, we can easily have an inheritance tree like the following: FooBundle < MyFooBundle < MyCustomFooBundle MyCustomFooBundle returns MyFooBundle for the getParent() method, and MyFooBundle returns FooBundle. If two bundles override the same bundle, an exception is thrown. Based on the bundle name, you can now reference any resource with this notation: @FooBundle/Resources/config/routing.xml @FooBundle/Controller/FooController.php This notation is the input of the Kernel::locateResource() method, which returns the location of the file (and of course it takes into account overloading). So, in the routing, you can now use the following: <import resource="@FrameworkBundle/Resources/config/internal.xml" /> The template loading mechanism also use this method under the hood. As a bonus, all the code that converts from internal notations to file names (controller names: ControllerNameParser, template names: TemplateNameParser, resource paths, ...) is now contained in several well-defined classes. The same goes for the code that look for templates (TemplateLocator), routing files (FileLocator), ... As a side note, it is really easy to also support multiple-inheritance for a bundle (for instance if a bundle returns an array of bundle names it extends). However, this is not implemented in this patch as I'm not sure we want to support that. How to upgrade: * Each bundle must now implement two new mandatory methods: getPath() and getNamespace(), and optionally the getParent() method if the bundle extends another one. Here is a common implementation for these methods: /** * {@inheritdoc} */ public function getParent() { return 'MyFrameworkBundle'; } /** * {@inheritdoc} */ public function getNamespace() { return __NAMESPACE__; } /** * {@inheritdoc} */ public function getPath() { return strtr(__DIR__, '\\', '/'); } * The registerBundleDirs() can be removed from your Kernel class; * If your code relies on getBundleDirs() or the kernel.bundle_dirs parameter, it should be upgraded to use the new interface (see Doctrine commands for many example of such a change); * When referencing a bundle, you must now always use its name (no more \ or / in bundle names) -- this transition was already done for most things before, and now applies to the routing as well; * Imports in routing files must be changed: Before: <import resource="Sensio/CasBundle/Resources/config/internal.xml" /> After: <import resource="@SensioCasBundle/Resources/config/internal.xml" />
2011-01-18 09:23:49 +00:00
* Gets the registered bundle instances.
2010-05-19 09:24:36 +01:00
*
refactored bundle management Before I explain the changes, let's talk about the current state. Before this patch, the registerBundleDirs() method returned an ordered (for resource overloading) list of namespace prefixes and the path to their location. Here are some problems with this approach: * The paths set by this method and the paths configured for the autoloader can be disconnected (leading to unexpected behaviors); * A bundle outside these paths worked, but unexpected behavior can occur; * Choosing a bundle namespace was limited to the registered namespace prefixes, and their number should stay low enough (for performance reasons) -- moreover the current Bundle\ and Application\ top namespaces does not respect the standard rules for namespaces (first segment should be the vendor name); * Developers must understand the concept of "namespace prefixes" to understand the overloading mechanism, which is one more thing to learn, which is Symfony specific; * Each time you want to get a resource that can be overloaded (a template for instance), Symfony would have tried all namespace prefixes one after the other until if finds a matching file. But that can be computed in advance to reduce the overhead. Another topic which was not really well addressed is how you can reference a file/resource from a bundle (and take into account the possibility of overloading). For instance, in the routing, you can import a file from a bundle like this: <import resource="FrameworkBundle/Resources/config/internal.xml" /> Again, this works only because we have a limited number of possible namespace prefixes. This patch addresses these problems and some more. First, the registerBundleDirs() method has been removed. It means that you are now free to use any namespace for your bundles. No need to have specific prefixes anymore. You are also free to store them anywhere, in as many directories as you want. You just need to be sure that they are autoloaded correctly. The bundle "name" is now always the short name of the bundle class (like FrameworkBundle or SensioCasBundle). As the best practice is to prefix the bundle name with the vendor name, it's up to the vendor to ensure that each bundle name is unique. I insist that a bundle name must be unique. This was the opposite before as two bundles with the same name was how Symfony2 found inheritance. A new getParent() method has been added to BundleInterface. It returns the bundle name that the bundle overrides (this is optional of course). That way, there is no ordering problem anymore as the inheritance tree is explicitely defined by the bundle themselves. So, with this system, we can easily have an inheritance tree like the following: FooBundle < MyFooBundle < MyCustomFooBundle MyCustomFooBundle returns MyFooBundle for the getParent() method, and MyFooBundle returns FooBundle. If two bundles override the same bundle, an exception is thrown. Based on the bundle name, you can now reference any resource with this notation: @FooBundle/Resources/config/routing.xml @FooBundle/Controller/FooController.php This notation is the input of the Kernel::locateResource() method, which returns the location of the file (and of course it takes into account overloading). So, in the routing, you can now use the following: <import resource="@FrameworkBundle/Resources/config/internal.xml" /> The template loading mechanism also use this method under the hood. As a bonus, all the code that converts from internal notations to file names (controller names: ControllerNameParser, template names: TemplateNameParser, resource paths, ...) is now contained in several well-defined classes. The same goes for the code that look for templates (TemplateLocator), routing files (FileLocator), ... As a side note, it is really easy to also support multiple-inheritance for a bundle (for instance if a bundle returns an array of bundle names it extends). However, this is not implemented in this patch as I'm not sure we want to support that. How to upgrade: * Each bundle must now implement two new mandatory methods: getPath() and getNamespace(), and optionally the getParent() method if the bundle extends another one. Here is a common implementation for these methods: /** * {@inheritdoc} */ public function getParent() { return 'MyFrameworkBundle'; } /** * {@inheritdoc} */ public function getNamespace() { return __NAMESPACE__; } /** * {@inheritdoc} */ public function getPath() { return strtr(__DIR__, '\\', '/'); } * The registerBundleDirs() can be removed from your Kernel class; * If your code relies on getBundleDirs() or the kernel.bundle_dirs parameter, it should be upgraded to use the new interface (see Doctrine commands for many example of such a change); * When referencing a bundle, you must now always use its name (no more \ or / in bundle names) -- this transition was already done for most things before, and now applies to the routing as well; * Imports in routing files must be changed: Before: <import resource="Sensio/CasBundle/Resources/config/internal.xml" /> After: <import resource="@SensioCasBundle/Resources/config/internal.xml" />
2011-01-18 09:23:49 +00:00
* @return array An array of registered bundle instances
2011-07-20 09:14:31 +01:00
*
* @api
2010-05-19 09:24:36 +01:00
*/
public function getBundles()
{
return $this->bundles;
}
/**
* Checks if a given class name belongs to an active bundle.
*
* @param string $class A class name
*
* @return Boolean true if the class belongs to an active bundle, false otherwise
2011-07-20 09:14:31 +01:00
*
* @api
*/
public function isClassInActiveBundle($class)
{
foreach ($this->getBundles() as $bundle) {
2011-02-08 16:00:13 +00:00
if (0 === strpos($class, $bundle->getNamespace())) {
return true;
}
}
return false;
}
refactored bundle management Before I explain the changes, let's talk about the current state. Before this patch, the registerBundleDirs() method returned an ordered (for resource overloading) list of namespace prefixes and the path to their location. Here are some problems with this approach: * The paths set by this method and the paths configured for the autoloader can be disconnected (leading to unexpected behaviors); * A bundle outside these paths worked, but unexpected behavior can occur; * Choosing a bundle namespace was limited to the registered namespace prefixes, and their number should stay low enough (for performance reasons) -- moreover the current Bundle\ and Application\ top namespaces does not respect the standard rules for namespaces (first segment should be the vendor name); * Developers must understand the concept of "namespace prefixes" to understand the overloading mechanism, which is one more thing to learn, which is Symfony specific; * Each time you want to get a resource that can be overloaded (a template for instance), Symfony would have tried all namespace prefixes one after the other until if finds a matching file. But that can be computed in advance to reduce the overhead. Another topic which was not really well addressed is how you can reference a file/resource from a bundle (and take into account the possibility of overloading). For instance, in the routing, you can import a file from a bundle like this: <import resource="FrameworkBundle/Resources/config/internal.xml" /> Again, this works only because we have a limited number of possible namespace prefixes. This patch addresses these problems and some more. First, the registerBundleDirs() method has been removed. It means that you are now free to use any namespace for your bundles. No need to have specific prefixes anymore. You are also free to store them anywhere, in as many directories as you want. You just need to be sure that they are autoloaded correctly. The bundle "name" is now always the short name of the bundle class (like FrameworkBundle or SensioCasBundle). As the best practice is to prefix the bundle name with the vendor name, it's up to the vendor to ensure that each bundle name is unique. I insist that a bundle name must be unique. This was the opposite before as two bundles with the same name was how Symfony2 found inheritance. A new getParent() method has been added to BundleInterface. It returns the bundle name that the bundle overrides (this is optional of course). That way, there is no ordering problem anymore as the inheritance tree is explicitely defined by the bundle themselves. So, with this system, we can easily have an inheritance tree like the following: FooBundle < MyFooBundle < MyCustomFooBundle MyCustomFooBundle returns MyFooBundle for the getParent() method, and MyFooBundle returns FooBundle. If two bundles override the same bundle, an exception is thrown. Based on the bundle name, you can now reference any resource with this notation: @FooBundle/Resources/config/routing.xml @FooBundle/Controller/FooController.php This notation is the input of the Kernel::locateResource() method, which returns the location of the file (and of course it takes into account overloading). So, in the routing, you can now use the following: <import resource="@FrameworkBundle/Resources/config/internal.xml" /> The template loading mechanism also use this method under the hood. As a bonus, all the code that converts from internal notations to file names (controller names: ControllerNameParser, template names: TemplateNameParser, resource paths, ...) is now contained in several well-defined classes. The same goes for the code that look for templates (TemplateLocator), routing files (FileLocator), ... As a side note, it is really easy to also support multiple-inheritance for a bundle (for instance if a bundle returns an array of bundle names it extends). However, this is not implemented in this patch as I'm not sure we want to support that. How to upgrade: * Each bundle must now implement two new mandatory methods: getPath() and getNamespace(), and optionally the getParent() method if the bundle extends another one. Here is a common implementation for these methods: /** * {@inheritdoc} */ public function getParent() { return 'MyFrameworkBundle'; } /** * {@inheritdoc} */ public function getNamespace() { return __NAMESPACE__; } /** * {@inheritdoc} */ public function getPath() { return strtr(__DIR__, '\\', '/'); } * The registerBundleDirs() can be removed from your Kernel class; * If your code relies on getBundleDirs() or the kernel.bundle_dirs parameter, it should be upgraded to use the new interface (see Doctrine commands for many example of such a change); * When referencing a bundle, you must now always use its name (no more \ or / in bundle names) -- this transition was already done for most things before, and now applies to the routing as well; * Imports in routing files must be changed: Before: <import resource="Sensio/CasBundle/Resources/config/internal.xml" /> After: <import resource="@SensioCasBundle/Resources/config/internal.xml" />
2011-01-18 09:23:49 +00:00
/**
2011-01-28 20:55:43 +00:00
* Returns a bundle and optionally its descendants by its name.
refactored bundle management Before I explain the changes, let's talk about the current state. Before this patch, the registerBundleDirs() method returned an ordered (for resource overloading) list of namespace prefixes and the path to their location. Here are some problems with this approach: * The paths set by this method and the paths configured for the autoloader can be disconnected (leading to unexpected behaviors); * A bundle outside these paths worked, but unexpected behavior can occur; * Choosing a bundle namespace was limited to the registered namespace prefixes, and their number should stay low enough (for performance reasons) -- moreover the current Bundle\ and Application\ top namespaces does not respect the standard rules for namespaces (first segment should be the vendor name); * Developers must understand the concept of "namespace prefixes" to understand the overloading mechanism, which is one more thing to learn, which is Symfony specific; * Each time you want to get a resource that can be overloaded (a template for instance), Symfony would have tried all namespace prefixes one after the other until if finds a matching file. But that can be computed in advance to reduce the overhead. Another topic which was not really well addressed is how you can reference a file/resource from a bundle (and take into account the possibility of overloading). For instance, in the routing, you can import a file from a bundle like this: <import resource="FrameworkBundle/Resources/config/internal.xml" /> Again, this works only because we have a limited number of possible namespace prefixes. This patch addresses these problems and some more. First, the registerBundleDirs() method has been removed. It means that you are now free to use any namespace for your bundles. No need to have specific prefixes anymore. You are also free to store them anywhere, in as many directories as you want. You just need to be sure that they are autoloaded correctly. The bundle "name" is now always the short name of the bundle class (like FrameworkBundle or SensioCasBundle). As the best practice is to prefix the bundle name with the vendor name, it's up to the vendor to ensure that each bundle name is unique. I insist that a bundle name must be unique. This was the opposite before as two bundles with the same name was how Symfony2 found inheritance. A new getParent() method has been added to BundleInterface. It returns the bundle name that the bundle overrides (this is optional of course). That way, there is no ordering problem anymore as the inheritance tree is explicitely defined by the bundle themselves. So, with this system, we can easily have an inheritance tree like the following: FooBundle < MyFooBundle < MyCustomFooBundle MyCustomFooBundle returns MyFooBundle for the getParent() method, and MyFooBundle returns FooBundle. If two bundles override the same bundle, an exception is thrown. Based on the bundle name, you can now reference any resource with this notation: @FooBundle/Resources/config/routing.xml @FooBundle/Controller/FooController.php This notation is the input of the Kernel::locateResource() method, which returns the location of the file (and of course it takes into account overloading). So, in the routing, you can now use the following: <import resource="@FrameworkBundle/Resources/config/internal.xml" /> The template loading mechanism also use this method under the hood. As a bonus, all the code that converts from internal notations to file names (controller names: ControllerNameParser, template names: TemplateNameParser, resource paths, ...) is now contained in several well-defined classes. The same goes for the code that look for templates (TemplateLocator), routing files (FileLocator), ... As a side note, it is really easy to also support multiple-inheritance for a bundle (for instance if a bundle returns an array of bundle names it extends). However, this is not implemented in this patch as I'm not sure we want to support that. How to upgrade: * Each bundle must now implement two new mandatory methods: getPath() and getNamespace(), and optionally the getParent() method if the bundle extends another one. Here is a common implementation for these methods: /** * {@inheritdoc} */ public function getParent() { return 'MyFrameworkBundle'; } /** * {@inheritdoc} */ public function getNamespace() { return __NAMESPACE__; } /** * {@inheritdoc} */ public function getPath() { return strtr(__DIR__, '\\', '/'); } * The registerBundleDirs() can be removed from your Kernel class; * If your code relies on getBundleDirs() or the kernel.bundle_dirs parameter, it should be upgraded to use the new interface (see Doctrine commands for many example of such a change); * When referencing a bundle, you must now always use its name (no more \ or / in bundle names) -- this transition was already done for most things before, and now applies to the routing as well; * Imports in routing files must be changed: Before: <import resource="Sensio/CasBundle/Resources/config/internal.xml" /> After: <import resource="@SensioCasBundle/Resources/config/internal.xml" />
2011-01-18 09:23:49 +00:00
*
* @param string $name Bundle name
2011-01-28 20:55:43 +00:00
* @param Boolean $first Whether to return the first bundle only or together with its descendants
refactored bundle management Before I explain the changes, let's talk about the current state. Before this patch, the registerBundleDirs() method returned an ordered (for resource overloading) list of namespace prefixes and the path to their location. Here are some problems with this approach: * The paths set by this method and the paths configured for the autoloader can be disconnected (leading to unexpected behaviors); * A bundle outside these paths worked, but unexpected behavior can occur; * Choosing a bundle namespace was limited to the registered namespace prefixes, and their number should stay low enough (for performance reasons) -- moreover the current Bundle\ and Application\ top namespaces does not respect the standard rules for namespaces (first segment should be the vendor name); * Developers must understand the concept of "namespace prefixes" to understand the overloading mechanism, which is one more thing to learn, which is Symfony specific; * Each time you want to get a resource that can be overloaded (a template for instance), Symfony would have tried all namespace prefixes one after the other until if finds a matching file. But that can be computed in advance to reduce the overhead. Another topic which was not really well addressed is how you can reference a file/resource from a bundle (and take into account the possibility of overloading). For instance, in the routing, you can import a file from a bundle like this: <import resource="FrameworkBundle/Resources/config/internal.xml" /> Again, this works only because we have a limited number of possible namespace prefixes. This patch addresses these problems and some more. First, the registerBundleDirs() method has been removed. It means that you are now free to use any namespace for your bundles. No need to have specific prefixes anymore. You are also free to store them anywhere, in as many directories as you want. You just need to be sure that they are autoloaded correctly. The bundle "name" is now always the short name of the bundle class (like FrameworkBundle or SensioCasBundle). As the best practice is to prefix the bundle name with the vendor name, it's up to the vendor to ensure that each bundle name is unique. I insist that a bundle name must be unique. This was the opposite before as two bundles with the same name was how Symfony2 found inheritance. A new getParent() method has been added to BundleInterface. It returns the bundle name that the bundle overrides (this is optional of course). That way, there is no ordering problem anymore as the inheritance tree is explicitely defined by the bundle themselves. So, with this system, we can easily have an inheritance tree like the following: FooBundle < MyFooBundle < MyCustomFooBundle MyCustomFooBundle returns MyFooBundle for the getParent() method, and MyFooBundle returns FooBundle. If two bundles override the same bundle, an exception is thrown. Based on the bundle name, you can now reference any resource with this notation: @FooBundle/Resources/config/routing.xml @FooBundle/Controller/FooController.php This notation is the input of the Kernel::locateResource() method, which returns the location of the file (and of course it takes into account overloading). So, in the routing, you can now use the following: <import resource="@FrameworkBundle/Resources/config/internal.xml" /> The template loading mechanism also use this method under the hood. As a bonus, all the code that converts from internal notations to file names (controller names: ControllerNameParser, template names: TemplateNameParser, resource paths, ...) is now contained in several well-defined classes. The same goes for the code that look for templates (TemplateLocator), routing files (FileLocator), ... As a side note, it is really easy to also support multiple-inheritance for a bundle (for instance if a bundle returns an array of bundle names it extends). However, this is not implemented in this patch as I'm not sure we want to support that. How to upgrade: * Each bundle must now implement two new mandatory methods: getPath() and getNamespace(), and optionally the getParent() method if the bundle extends another one. Here is a common implementation for these methods: /** * {@inheritdoc} */ public function getParent() { return 'MyFrameworkBundle'; } /** * {@inheritdoc} */ public function getNamespace() { return __NAMESPACE__; } /** * {@inheritdoc} */ public function getPath() { return strtr(__DIR__, '\\', '/'); } * The registerBundleDirs() can be removed from your Kernel class; * If your code relies on getBundleDirs() or the kernel.bundle_dirs parameter, it should be upgraded to use the new interface (see Doctrine commands for many example of such a change); * When referencing a bundle, you must now always use its name (no more \ or / in bundle names) -- this transition was already done for most things before, and now applies to the routing as well; * Imports in routing files must be changed: Before: <import resource="Sensio/CasBundle/Resources/config/internal.xml" /> After: <import resource="@SensioCasBundle/Resources/config/internal.xml" />
2011-01-18 09:23:49 +00:00
*
2011-01-28 20:55:43 +00:00
* @return BundleInterface|Array A BundleInterface instance or an array of BundleInterface instances if $first is false
refactored bundle management Before I explain the changes, let's talk about the current state. Before this patch, the registerBundleDirs() method returned an ordered (for resource overloading) list of namespace prefixes and the path to their location. Here are some problems with this approach: * The paths set by this method and the paths configured for the autoloader can be disconnected (leading to unexpected behaviors); * A bundle outside these paths worked, but unexpected behavior can occur; * Choosing a bundle namespace was limited to the registered namespace prefixes, and their number should stay low enough (for performance reasons) -- moreover the current Bundle\ and Application\ top namespaces does not respect the standard rules for namespaces (first segment should be the vendor name); * Developers must understand the concept of "namespace prefixes" to understand the overloading mechanism, which is one more thing to learn, which is Symfony specific; * Each time you want to get a resource that can be overloaded (a template for instance), Symfony would have tried all namespace prefixes one after the other until if finds a matching file. But that can be computed in advance to reduce the overhead. Another topic which was not really well addressed is how you can reference a file/resource from a bundle (and take into account the possibility of overloading). For instance, in the routing, you can import a file from a bundle like this: <import resource="FrameworkBundle/Resources/config/internal.xml" /> Again, this works only because we have a limited number of possible namespace prefixes. This patch addresses these problems and some more. First, the registerBundleDirs() method has been removed. It means that you are now free to use any namespace for your bundles. No need to have specific prefixes anymore. You are also free to store them anywhere, in as many directories as you want. You just need to be sure that they are autoloaded correctly. The bundle "name" is now always the short name of the bundle class (like FrameworkBundle or SensioCasBundle). As the best practice is to prefix the bundle name with the vendor name, it's up to the vendor to ensure that each bundle name is unique. I insist that a bundle name must be unique. This was the opposite before as two bundles with the same name was how Symfony2 found inheritance. A new getParent() method has been added to BundleInterface. It returns the bundle name that the bundle overrides (this is optional of course). That way, there is no ordering problem anymore as the inheritance tree is explicitely defined by the bundle themselves. So, with this system, we can easily have an inheritance tree like the following: FooBundle < MyFooBundle < MyCustomFooBundle MyCustomFooBundle returns MyFooBundle for the getParent() method, and MyFooBundle returns FooBundle. If two bundles override the same bundle, an exception is thrown. Based on the bundle name, you can now reference any resource with this notation: @FooBundle/Resources/config/routing.xml @FooBundle/Controller/FooController.php This notation is the input of the Kernel::locateResource() method, which returns the location of the file (and of course it takes into account overloading). So, in the routing, you can now use the following: <import resource="@FrameworkBundle/Resources/config/internal.xml" /> The template loading mechanism also use this method under the hood. As a bonus, all the code that converts from internal notations to file names (controller names: ControllerNameParser, template names: TemplateNameParser, resource paths, ...) is now contained in several well-defined classes. The same goes for the code that look for templates (TemplateLocator), routing files (FileLocator), ... As a side note, it is really easy to also support multiple-inheritance for a bundle (for instance if a bundle returns an array of bundle names it extends). However, this is not implemented in this patch as I'm not sure we want to support that. How to upgrade: * Each bundle must now implement two new mandatory methods: getPath() and getNamespace(), and optionally the getParent() method if the bundle extends another one. Here is a common implementation for these methods: /** * {@inheritdoc} */ public function getParent() { return 'MyFrameworkBundle'; } /** * {@inheritdoc} */ public function getNamespace() { return __NAMESPACE__; } /** * {@inheritdoc} */ public function getPath() { return strtr(__DIR__, '\\', '/'); } * The registerBundleDirs() can be removed from your Kernel class; * If your code relies on getBundleDirs() or the kernel.bundle_dirs parameter, it should be upgraded to use the new interface (see Doctrine commands for many example of such a change); * When referencing a bundle, you must now always use its name (no more \ or / in bundle names) -- this transition was already done for most things before, and now applies to the routing as well; * Imports in routing files must be changed: Before: <import resource="Sensio/CasBundle/Resources/config/internal.xml" /> After: <import resource="@SensioCasBundle/Resources/config/internal.xml" />
2011-01-18 09:23:49 +00:00
*
* @throws \InvalidArgumentException when the bundle is not enabled
2011-07-20 09:14:31 +01:00
*
* @api
refactored bundle management Before I explain the changes, let's talk about the current state. Before this patch, the registerBundleDirs() method returned an ordered (for resource overloading) list of namespace prefixes and the path to their location. Here are some problems with this approach: * The paths set by this method and the paths configured for the autoloader can be disconnected (leading to unexpected behaviors); * A bundle outside these paths worked, but unexpected behavior can occur; * Choosing a bundle namespace was limited to the registered namespace prefixes, and their number should stay low enough (for performance reasons) -- moreover the current Bundle\ and Application\ top namespaces does not respect the standard rules for namespaces (first segment should be the vendor name); * Developers must understand the concept of "namespace prefixes" to understand the overloading mechanism, which is one more thing to learn, which is Symfony specific; * Each time you want to get a resource that can be overloaded (a template for instance), Symfony would have tried all namespace prefixes one after the other until if finds a matching file. But that can be computed in advance to reduce the overhead. Another topic which was not really well addressed is how you can reference a file/resource from a bundle (and take into account the possibility of overloading). For instance, in the routing, you can import a file from a bundle like this: <import resource="FrameworkBundle/Resources/config/internal.xml" /> Again, this works only because we have a limited number of possible namespace prefixes. This patch addresses these problems and some more. First, the registerBundleDirs() method has been removed. It means that you are now free to use any namespace for your bundles. No need to have specific prefixes anymore. You are also free to store them anywhere, in as many directories as you want. You just need to be sure that they are autoloaded correctly. The bundle "name" is now always the short name of the bundle class (like FrameworkBundle or SensioCasBundle). As the best practice is to prefix the bundle name with the vendor name, it's up to the vendor to ensure that each bundle name is unique. I insist that a bundle name must be unique. This was the opposite before as two bundles with the same name was how Symfony2 found inheritance. A new getParent() method has been added to BundleInterface. It returns the bundle name that the bundle overrides (this is optional of course). That way, there is no ordering problem anymore as the inheritance tree is explicitely defined by the bundle themselves. So, with this system, we can easily have an inheritance tree like the following: FooBundle < MyFooBundle < MyCustomFooBundle MyCustomFooBundle returns MyFooBundle for the getParent() method, and MyFooBundle returns FooBundle. If two bundles override the same bundle, an exception is thrown. Based on the bundle name, you can now reference any resource with this notation: @FooBundle/Resources/config/routing.xml @FooBundle/Controller/FooController.php This notation is the input of the Kernel::locateResource() method, which returns the location of the file (and of course it takes into account overloading). So, in the routing, you can now use the following: <import resource="@FrameworkBundle/Resources/config/internal.xml" /> The template loading mechanism also use this method under the hood. As a bonus, all the code that converts from internal notations to file names (controller names: ControllerNameParser, template names: TemplateNameParser, resource paths, ...) is now contained in several well-defined classes. The same goes for the code that look for templates (TemplateLocator), routing files (FileLocator), ... As a side note, it is really easy to also support multiple-inheritance for a bundle (for instance if a bundle returns an array of bundle names it extends). However, this is not implemented in this patch as I'm not sure we want to support that. How to upgrade: * Each bundle must now implement two new mandatory methods: getPath() and getNamespace(), and optionally the getParent() method if the bundle extends another one. Here is a common implementation for these methods: /** * {@inheritdoc} */ public function getParent() { return 'MyFrameworkBundle'; } /** * {@inheritdoc} */ public function getNamespace() { return __NAMESPACE__; } /** * {@inheritdoc} */ public function getPath() { return strtr(__DIR__, '\\', '/'); } * The registerBundleDirs() can be removed from your Kernel class; * If your code relies on getBundleDirs() or the kernel.bundle_dirs parameter, it should be upgraded to use the new interface (see Doctrine commands for many example of such a change); * When referencing a bundle, you must now always use its name (no more \ or / in bundle names) -- this transition was already done for most things before, and now applies to the routing as well; * Imports in routing files must be changed: Before: <import resource="Sensio/CasBundle/Resources/config/internal.xml" /> After: <import resource="@SensioCasBundle/Resources/config/internal.xml" />
2011-01-18 09:23:49 +00:00
*/
public function getBundle($name, $first = true)
{
if (!isset($this->bundleMap[$name])) {
throw new \InvalidArgumentException(sprintf('Bundle "%s" does not exist or it is not enabled. Maybe you forgot to add it in the registerBundles() function of your %s.php file?', $name, get_class($this)));
refactored bundle management Before I explain the changes, let's talk about the current state. Before this patch, the registerBundleDirs() method returned an ordered (for resource overloading) list of namespace prefixes and the path to their location. Here are some problems with this approach: * The paths set by this method and the paths configured for the autoloader can be disconnected (leading to unexpected behaviors); * A bundle outside these paths worked, but unexpected behavior can occur; * Choosing a bundle namespace was limited to the registered namespace prefixes, and their number should stay low enough (for performance reasons) -- moreover the current Bundle\ and Application\ top namespaces does not respect the standard rules for namespaces (first segment should be the vendor name); * Developers must understand the concept of "namespace prefixes" to understand the overloading mechanism, which is one more thing to learn, which is Symfony specific; * Each time you want to get a resource that can be overloaded (a template for instance), Symfony would have tried all namespace prefixes one after the other until if finds a matching file. But that can be computed in advance to reduce the overhead. Another topic which was not really well addressed is how you can reference a file/resource from a bundle (and take into account the possibility of overloading). For instance, in the routing, you can import a file from a bundle like this: <import resource="FrameworkBundle/Resources/config/internal.xml" /> Again, this works only because we have a limited number of possible namespace prefixes. This patch addresses these problems and some more. First, the registerBundleDirs() method has been removed. It means that you are now free to use any namespace for your bundles. No need to have specific prefixes anymore. You are also free to store them anywhere, in as many directories as you want. You just need to be sure that they are autoloaded correctly. The bundle "name" is now always the short name of the bundle class (like FrameworkBundle or SensioCasBundle). As the best practice is to prefix the bundle name with the vendor name, it's up to the vendor to ensure that each bundle name is unique. I insist that a bundle name must be unique. This was the opposite before as two bundles with the same name was how Symfony2 found inheritance. A new getParent() method has been added to BundleInterface. It returns the bundle name that the bundle overrides (this is optional of course). That way, there is no ordering problem anymore as the inheritance tree is explicitely defined by the bundle themselves. So, with this system, we can easily have an inheritance tree like the following: FooBundle < MyFooBundle < MyCustomFooBundle MyCustomFooBundle returns MyFooBundle for the getParent() method, and MyFooBundle returns FooBundle. If two bundles override the same bundle, an exception is thrown. Based on the bundle name, you can now reference any resource with this notation: @FooBundle/Resources/config/routing.xml @FooBundle/Controller/FooController.php This notation is the input of the Kernel::locateResource() method, which returns the location of the file (and of course it takes into account overloading). So, in the routing, you can now use the following: <import resource="@FrameworkBundle/Resources/config/internal.xml" /> The template loading mechanism also use this method under the hood. As a bonus, all the code that converts from internal notations to file names (controller names: ControllerNameParser, template names: TemplateNameParser, resource paths, ...) is now contained in several well-defined classes. The same goes for the code that look for templates (TemplateLocator), routing files (FileLocator), ... As a side note, it is really easy to also support multiple-inheritance for a bundle (for instance if a bundle returns an array of bundle names it extends). However, this is not implemented in this patch as I'm not sure we want to support that. How to upgrade: * Each bundle must now implement two new mandatory methods: getPath() and getNamespace(), and optionally the getParent() method if the bundle extends another one. Here is a common implementation for these methods: /** * {@inheritdoc} */ public function getParent() { return 'MyFrameworkBundle'; } /** * {@inheritdoc} */ public function getNamespace() { return __NAMESPACE__; } /** * {@inheritdoc} */ public function getPath() { return strtr(__DIR__, '\\', '/'); } * The registerBundleDirs() can be removed from your Kernel class; * If your code relies on getBundleDirs() or the kernel.bundle_dirs parameter, it should be upgraded to use the new interface (see Doctrine commands for many example of such a change); * When referencing a bundle, you must now always use its name (no more \ or / in bundle names) -- this transition was already done for most things before, and now applies to the routing as well; * Imports in routing files must be changed: Before: <import resource="Sensio/CasBundle/Resources/config/internal.xml" /> After: <import resource="@SensioCasBundle/Resources/config/internal.xml" />
2011-01-18 09:23:49 +00:00
}
if (true === $first) {
return $this->bundleMap[$name][0];
}
2011-04-13 22:18:28 +01:00
return $this->bundleMap[$name];
refactored bundle management Before I explain the changes, let's talk about the current state. Before this patch, the registerBundleDirs() method returned an ordered (for resource overloading) list of namespace prefixes and the path to their location. Here are some problems with this approach: * The paths set by this method and the paths configured for the autoloader can be disconnected (leading to unexpected behaviors); * A bundle outside these paths worked, but unexpected behavior can occur; * Choosing a bundle namespace was limited to the registered namespace prefixes, and their number should stay low enough (for performance reasons) -- moreover the current Bundle\ and Application\ top namespaces does not respect the standard rules for namespaces (first segment should be the vendor name); * Developers must understand the concept of "namespace prefixes" to understand the overloading mechanism, which is one more thing to learn, which is Symfony specific; * Each time you want to get a resource that can be overloaded (a template for instance), Symfony would have tried all namespace prefixes one after the other until if finds a matching file. But that can be computed in advance to reduce the overhead. Another topic which was not really well addressed is how you can reference a file/resource from a bundle (and take into account the possibility of overloading). For instance, in the routing, you can import a file from a bundle like this: <import resource="FrameworkBundle/Resources/config/internal.xml" /> Again, this works only because we have a limited number of possible namespace prefixes. This patch addresses these problems and some more. First, the registerBundleDirs() method has been removed. It means that you are now free to use any namespace for your bundles. No need to have specific prefixes anymore. You are also free to store them anywhere, in as many directories as you want. You just need to be sure that they are autoloaded correctly. The bundle "name" is now always the short name of the bundle class (like FrameworkBundle or SensioCasBundle). As the best practice is to prefix the bundle name with the vendor name, it's up to the vendor to ensure that each bundle name is unique. I insist that a bundle name must be unique. This was the opposite before as two bundles with the same name was how Symfony2 found inheritance. A new getParent() method has been added to BundleInterface. It returns the bundle name that the bundle overrides (this is optional of course). That way, there is no ordering problem anymore as the inheritance tree is explicitely defined by the bundle themselves. So, with this system, we can easily have an inheritance tree like the following: FooBundle < MyFooBundle < MyCustomFooBundle MyCustomFooBundle returns MyFooBundle for the getParent() method, and MyFooBundle returns FooBundle. If two bundles override the same bundle, an exception is thrown. Based on the bundle name, you can now reference any resource with this notation: @FooBundle/Resources/config/routing.xml @FooBundle/Controller/FooController.php This notation is the input of the Kernel::locateResource() method, which returns the location of the file (and of course it takes into account overloading). So, in the routing, you can now use the following: <import resource="@FrameworkBundle/Resources/config/internal.xml" /> The template loading mechanism also use this method under the hood. As a bonus, all the code that converts from internal notations to file names (controller names: ControllerNameParser, template names: TemplateNameParser, resource paths, ...) is now contained in several well-defined classes. The same goes for the code that look for templates (TemplateLocator), routing files (FileLocator), ... As a side note, it is really easy to also support multiple-inheritance for a bundle (for instance if a bundle returns an array of bundle names it extends). However, this is not implemented in this patch as I'm not sure we want to support that. How to upgrade: * Each bundle must now implement two new mandatory methods: getPath() and getNamespace(), and optionally the getParent() method if the bundle extends another one. Here is a common implementation for these methods: /** * {@inheritdoc} */ public function getParent() { return 'MyFrameworkBundle'; } /** * {@inheritdoc} */ public function getNamespace() { return __NAMESPACE__; } /** * {@inheritdoc} */ public function getPath() { return strtr(__DIR__, '\\', '/'); } * The registerBundleDirs() can be removed from your Kernel class; * If your code relies on getBundleDirs() or the kernel.bundle_dirs parameter, it should be upgraded to use the new interface (see Doctrine commands for many example of such a change); * When referencing a bundle, you must now always use its name (no more \ or / in bundle names) -- this transition was already done for most things before, and now applies to the routing as well; * Imports in routing files must be changed: Before: <import resource="Sensio/CasBundle/Resources/config/internal.xml" /> After: <import resource="@SensioCasBundle/Resources/config/internal.xml" />
2011-01-18 09:23:49 +00:00
}
/**
* Returns the file path for a given resource.
*
* A Resource can be a file or a directory.
*
refactored bundle management Before I explain the changes, let's talk about the current state. Before this patch, the registerBundleDirs() method returned an ordered (for resource overloading) list of namespace prefixes and the path to their location. Here are some problems with this approach: * The paths set by this method and the paths configured for the autoloader can be disconnected (leading to unexpected behaviors); * A bundle outside these paths worked, but unexpected behavior can occur; * Choosing a bundle namespace was limited to the registered namespace prefixes, and their number should stay low enough (for performance reasons) -- moreover the current Bundle\ and Application\ top namespaces does not respect the standard rules for namespaces (first segment should be the vendor name); * Developers must understand the concept of "namespace prefixes" to understand the overloading mechanism, which is one more thing to learn, which is Symfony specific; * Each time you want to get a resource that can be overloaded (a template for instance), Symfony would have tried all namespace prefixes one after the other until if finds a matching file. But that can be computed in advance to reduce the overhead. Another topic which was not really well addressed is how you can reference a file/resource from a bundle (and take into account the possibility of overloading). For instance, in the routing, you can import a file from a bundle like this: <import resource="FrameworkBundle/Resources/config/internal.xml" /> Again, this works only because we have a limited number of possible namespace prefixes. This patch addresses these problems and some more. First, the registerBundleDirs() method has been removed. It means that you are now free to use any namespace for your bundles. No need to have specific prefixes anymore. You are also free to store them anywhere, in as many directories as you want. You just need to be sure that they are autoloaded correctly. The bundle "name" is now always the short name of the bundle class (like FrameworkBundle or SensioCasBundle). As the best practice is to prefix the bundle name with the vendor name, it's up to the vendor to ensure that each bundle name is unique. I insist that a bundle name must be unique. This was the opposite before as two bundles with the same name was how Symfony2 found inheritance. A new getParent() method has been added to BundleInterface. It returns the bundle name that the bundle overrides (this is optional of course). That way, there is no ordering problem anymore as the inheritance tree is explicitely defined by the bundle themselves. So, with this system, we can easily have an inheritance tree like the following: FooBundle < MyFooBundle < MyCustomFooBundle MyCustomFooBundle returns MyFooBundle for the getParent() method, and MyFooBundle returns FooBundle. If two bundles override the same bundle, an exception is thrown. Based on the bundle name, you can now reference any resource with this notation: @FooBundle/Resources/config/routing.xml @FooBundle/Controller/FooController.php This notation is the input of the Kernel::locateResource() method, which returns the location of the file (and of course it takes into account overloading). So, in the routing, you can now use the following: <import resource="@FrameworkBundle/Resources/config/internal.xml" /> The template loading mechanism also use this method under the hood. As a bonus, all the code that converts from internal notations to file names (controller names: ControllerNameParser, template names: TemplateNameParser, resource paths, ...) is now contained in several well-defined classes. The same goes for the code that look for templates (TemplateLocator), routing files (FileLocator), ... As a side note, it is really easy to also support multiple-inheritance for a bundle (for instance if a bundle returns an array of bundle names it extends). However, this is not implemented in this patch as I'm not sure we want to support that. How to upgrade: * Each bundle must now implement two new mandatory methods: getPath() and getNamespace(), and optionally the getParent() method if the bundle extends another one. Here is a common implementation for these methods: /** * {@inheritdoc} */ public function getParent() { return 'MyFrameworkBundle'; } /** * {@inheritdoc} */ public function getNamespace() { return __NAMESPACE__; } /** * {@inheritdoc} */ public function getPath() { return strtr(__DIR__, '\\', '/'); } * The registerBundleDirs() can be removed from your Kernel class; * If your code relies on getBundleDirs() or the kernel.bundle_dirs parameter, it should be upgraded to use the new interface (see Doctrine commands for many example of such a change); * When referencing a bundle, you must now always use its name (no more \ or / in bundle names) -- this transition was already done for most things before, and now applies to the routing as well; * Imports in routing files must be changed: Before: <import resource="Sensio/CasBundle/Resources/config/internal.xml" /> After: <import resource="@SensioCasBundle/Resources/config/internal.xml" />
2011-01-18 09:23:49 +00:00
* The resource name must follow the following pattern:
*
* @<BundleName>/path/to/a/file.something
refactored bundle management Before I explain the changes, let's talk about the current state. Before this patch, the registerBundleDirs() method returned an ordered (for resource overloading) list of namespace prefixes and the path to their location. Here are some problems with this approach: * The paths set by this method and the paths configured for the autoloader can be disconnected (leading to unexpected behaviors); * A bundle outside these paths worked, but unexpected behavior can occur; * Choosing a bundle namespace was limited to the registered namespace prefixes, and their number should stay low enough (for performance reasons) -- moreover the current Bundle\ and Application\ top namespaces does not respect the standard rules for namespaces (first segment should be the vendor name); * Developers must understand the concept of "namespace prefixes" to understand the overloading mechanism, which is one more thing to learn, which is Symfony specific; * Each time you want to get a resource that can be overloaded (a template for instance), Symfony would have tried all namespace prefixes one after the other until if finds a matching file. But that can be computed in advance to reduce the overhead. Another topic which was not really well addressed is how you can reference a file/resource from a bundle (and take into account the possibility of overloading). For instance, in the routing, you can import a file from a bundle like this: <import resource="FrameworkBundle/Resources/config/internal.xml" /> Again, this works only because we have a limited number of possible namespace prefixes. This patch addresses these problems and some more. First, the registerBundleDirs() method has been removed. It means that you are now free to use any namespace for your bundles. No need to have specific prefixes anymore. You are also free to store them anywhere, in as many directories as you want. You just need to be sure that they are autoloaded correctly. The bundle "name" is now always the short name of the bundle class (like FrameworkBundle or SensioCasBundle). As the best practice is to prefix the bundle name with the vendor name, it's up to the vendor to ensure that each bundle name is unique. I insist that a bundle name must be unique. This was the opposite before as two bundles with the same name was how Symfony2 found inheritance. A new getParent() method has been added to BundleInterface. It returns the bundle name that the bundle overrides (this is optional of course). That way, there is no ordering problem anymore as the inheritance tree is explicitely defined by the bundle themselves. So, with this system, we can easily have an inheritance tree like the following: FooBundle < MyFooBundle < MyCustomFooBundle MyCustomFooBundle returns MyFooBundle for the getParent() method, and MyFooBundle returns FooBundle. If two bundles override the same bundle, an exception is thrown. Based on the bundle name, you can now reference any resource with this notation: @FooBundle/Resources/config/routing.xml @FooBundle/Controller/FooController.php This notation is the input of the Kernel::locateResource() method, which returns the location of the file (and of course it takes into account overloading). So, in the routing, you can now use the following: <import resource="@FrameworkBundle/Resources/config/internal.xml" /> The template loading mechanism also use this method under the hood. As a bonus, all the code that converts from internal notations to file names (controller names: ControllerNameParser, template names: TemplateNameParser, resource paths, ...) is now contained in several well-defined classes. The same goes for the code that look for templates (TemplateLocator), routing files (FileLocator), ... As a side note, it is really easy to also support multiple-inheritance for a bundle (for instance if a bundle returns an array of bundle names it extends). However, this is not implemented in this patch as I'm not sure we want to support that. How to upgrade: * Each bundle must now implement two new mandatory methods: getPath() and getNamespace(), and optionally the getParent() method if the bundle extends another one. Here is a common implementation for these methods: /** * {@inheritdoc} */ public function getParent() { return 'MyFrameworkBundle'; } /** * {@inheritdoc} */ public function getNamespace() { return __NAMESPACE__; } /** * {@inheritdoc} */ public function getPath() { return strtr(__DIR__, '\\', '/'); } * The registerBundleDirs() can be removed from your Kernel class; * If your code relies on getBundleDirs() or the kernel.bundle_dirs parameter, it should be upgraded to use the new interface (see Doctrine commands for many example of such a change); * When referencing a bundle, you must now always use its name (no more \ or / in bundle names) -- this transition was already done for most things before, and now applies to the routing as well; * Imports in routing files must be changed: Before: <import resource="Sensio/CasBundle/Resources/config/internal.xml" /> After: <import resource="@SensioCasBundle/Resources/config/internal.xml" />
2011-01-18 09:23:49 +00:00
*
* where BundleName is the name of the bundle
* and the remaining part is the relative path in the bundle.
*
* If $dir is passed, and the first segment of the path is "Resources",
refactored bundle management Before I explain the changes, let's talk about the current state. Before this patch, the registerBundleDirs() method returned an ordered (for resource overloading) list of namespace prefixes and the path to their location. Here are some problems with this approach: * The paths set by this method and the paths configured for the autoloader can be disconnected (leading to unexpected behaviors); * A bundle outside these paths worked, but unexpected behavior can occur; * Choosing a bundle namespace was limited to the registered namespace prefixes, and their number should stay low enough (for performance reasons) -- moreover the current Bundle\ and Application\ top namespaces does not respect the standard rules for namespaces (first segment should be the vendor name); * Developers must understand the concept of "namespace prefixes" to understand the overloading mechanism, which is one more thing to learn, which is Symfony specific; * Each time you want to get a resource that can be overloaded (a template for instance), Symfony would have tried all namespace prefixes one after the other until if finds a matching file. But that can be computed in advance to reduce the overhead. Another topic which was not really well addressed is how you can reference a file/resource from a bundle (and take into account the possibility of overloading). For instance, in the routing, you can import a file from a bundle like this: <import resource="FrameworkBundle/Resources/config/internal.xml" /> Again, this works only because we have a limited number of possible namespace prefixes. This patch addresses these problems and some more. First, the registerBundleDirs() method has been removed. It means that you are now free to use any namespace for your bundles. No need to have specific prefixes anymore. You are also free to store them anywhere, in as many directories as you want. You just need to be sure that they are autoloaded correctly. The bundle "name" is now always the short name of the bundle class (like FrameworkBundle or SensioCasBundle). As the best practice is to prefix the bundle name with the vendor name, it's up to the vendor to ensure that each bundle name is unique. I insist that a bundle name must be unique. This was the opposite before as two bundles with the same name was how Symfony2 found inheritance. A new getParent() method has been added to BundleInterface. It returns the bundle name that the bundle overrides (this is optional of course). That way, there is no ordering problem anymore as the inheritance tree is explicitely defined by the bundle themselves. So, with this system, we can easily have an inheritance tree like the following: FooBundle < MyFooBundle < MyCustomFooBundle MyCustomFooBundle returns MyFooBundle for the getParent() method, and MyFooBundle returns FooBundle. If two bundles override the same bundle, an exception is thrown. Based on the bundle name, you can now reference any resource with this notation: @FooBundle/Resources/config/routing.xml @FooBundle/Controller/FooController.php This notation is the input of the Kernel::locateResource() method, which returns the location of the file (and of course it takes into account overloading). So, in the routing, you can now use the following: <import resource="@FrameworkBundle/Resources/config/internal.xml" /> The template loading mechanism also use this method under the hood. As a bonus, all the code that converts from internal notations to file names (controller names: ControllerNameParser, template names: TemplateNameParser, resource paths, ...) is now contained in several well-defined classes. The same goes for the code that look for templates (TemplateLocator), routing files (FileLocator), ... As a side note, it is really easy to also support multiple-inheritance for a bundle (for instance if a bundle returns an array of bundle names it extends). However, this is not implemented in this patch as I'm not sure we want to support that. How to upgrade: * Each bundle must now implement two new mandatory methods: getPath() and getNamespace(), and optionally the getParent() method if the bundle extends another one. Here is a common implementation for these methods: /** * {@inheritdoc} */ public function getParent() { return 'MyFrameworkBundle'; } /** * {@inheritdoc} */ public function getNamespace() { return __NAMESPACE__; } /** * {@inheritdoc} */ public function getPath() { return strtr(__DIR__, '\\', '/'); } * The registerBundleDirs() can be removed from your Kernel class; * If your code relies on getBundleDirs() or the kernel.bundle_dirs parameter, it should be upgraded to use the new interface (see Doctrine commands for many example of such a change); * When referencing a bundle, you must now always use its name (no more \ or / in bundle names) -- this transition was already done for most things before, and now applies to the routing as well; * Imports in routing files must be changed: Before: <import resource="Sensio/CasBundle/Resources/config/internal.xml" /> After: <import resource="@SensioCasBundle/Resources/config/internal.xml" />
2011-01-18 09:23:49 +00:00
* this method will look for a file named:
*
* $dir/<BundleName>/path/without/Resources
*
* before looking in the bundle resource folder.
refactored bundle management Before I explain the changes, let's talk about the current state. Before this patch, the registerBundleDirs() method returned an ordered (for resource overloading) list of namespace prefixes and the path to their location. Here are some problems with this approach: * The paths set by this method and the paths configured for the autoloader can be disconnected (leading to unexpected behaviors); * A bundle outside these paths worked, but unexpected behavior can occur; * Choosing a bundle namespace was limited to the registered namespace prefixes, and their number should stay low enough (for performance reasons) -- moreover the current Bundle\ and Application\ top namespaces does not respect the standard rules for namespaces (first segment should be the vendor name); * Developers must understand the concept of "namespace prefixes" to understand the overloading mechanism, which is one more thing to learn, which is Symfony specific; * Each time you want to get a resource that can be overloaded (a template for instance), Symfony would have tried all namespace prefixes one after the other until if finds a matching file. But that can be computed in advance to reduce the overhead. Another topic which was not really well addressed is how you can reference a file/resource from a bundle (and take into account the possibility of overloading). For instance, in the routing, you can import a file from a bundle like this: <import resource="FrameworkBundle/Resources/config/internal.xml" /> Again, this works only because we have a limited number of possible namespace prefixes. This patch addresses these problems and some more. First, the registerBundleDirs() method has been removed. It means that you are now free to use any namespace for your bundles. No need to have specific prefixes anymore. You are also free to store them anywhere, in as many directories as you want. You just need to be sure that they are autoloaded correctly. The bundle "name" is now always the short name of the bundle class (like FrameworkBundle or SensioCasBundle). As the best practice is to prefix the bundle name with the vendor name, it's up to the vendor to ensure that each bundle name is unique. I insist that a bundle name must be unique. This was the opposite before as two bundles with the same name was how Symfony2 found inheritance. A new getParent() method has been added to BundleInterface. It returns the bundle name that the bundle overrides (this is optional of course). That way, there is no ordering problem anymore as the inheritance tree is explicitely defined by the bundle themselves. So, with this system, we can easily have an inheritance tree like the following: FooBundle < MyFooBundle < MyCustomFooBundle MyCustomFooBundle returns MyFooBundle for the getParent() method, and MyFooBundle returns FooBundle. If two bundles override the same bundle, an exception is thrown. Based on the bundle name, you can now reference any resource with this notation: @FooBundle/Resources/config/routing.xml @FooBundle/Controller/FooController.php This notation is the input of the Kernel::locateResource() method, which returns the location of the file (and of course it takes into account overloading). So, in the routing, you can now use the following: <import resource="@FrameworkBundle/Resources/config/internal.xml" /> The template loading mechanism also use this method under the hood. As a bonus, all the code that converts from internal notations to file names (controller names: ControllerNameParser, template names: TemplateNameParser, resource paths, ...) is now contained in several well-defined classes. The same goes for the code that look for templates (TemplateLocator), routing files (FileLocator), ... As a side note, it is really easy to also support multiple-inheritance for a bundle (for instance if a bundle returns an array of bundle names it extends). However, this is not implemented in this patch as I'm not sure we want to support that. How to upgrade: * Each bundle must now implement two new mandatory methods: getPath() and getNamespace(), and optionally the getParent() method if the bundle extends another one. Here is a common implementation for these methods: /** * {@inheritdoc} */ public function getParent() { return 'MyFrameworkBundle'; } /** * {@inheritdoc} */ public function getNamespace() { return __NAMESPACE__; } /** * {@inheritdoc} */ public function getPath() { return strtr(__DIR__, '\\', '/'); } * The registerBundleDirs() can be removed from your Kernel class; * If your code relies on getBundleDirs() or the kernel.bundle_dirs parameter, it should be upgraded to use the new interface (see Doctrine commands for many example of such a change); * When referencing a bundle, you must now always use its name (no more \ or / in bundle names) -- this transition was already done for most things before, and now applies to the routing as well; * Imports in routing files must be changed: Before: <import resource="Sensio/CasBundle/Resources/config/internal.xml" /> After: <import resource="@SensioCasBundle/Resources/config/internal.xml" />
2011-01-18 09:23:49 +00:00
*
* @param string $name A resource name to locate
* @param string $dir A directory where to look for the resource first
* @param Boolean $first Whether to return the first path or paths for all matching bundles
*
* @return string|array The absolute path of the resource or an array if $first is false
*
* @throws \InvalidArgumentException if the file cannot be found or the name is not valid
* @throws \RuntimeException if the name contains invalid/unsafe
* @throws \RuntimeException if a custom resource is hidden by a resource in a derived bundle
2011-07-20 09:14:31 +01:00
*
* @api
refactored bundle management Before I explain the changes, let's talk about the current state. Before this patch, the registerBundleDirs() method returned an ordered (for resource overloading) list of namespace prefixes and the path to their location. Here are some problems with this approach: * The paths set by this method and the paths configured for the autoloader can be disconnected (leading to unexpected behaviors); * A bundle outside these paths worked, but unexpected behavior can occur; * Choosing a bundle namespace was limited to the registered namespace prefixes, and their number should stay low enough (for performance reasons) -- moreover the current Bundle\ and Application\ top namespaces does not respect the standard rules for namespaces (first segment should be the vendor name); * Developers must understand the concept of "namespace prefixes" to understand the overloading mechanism, which is one more thing to learn, which is Symfony specific; * Each time you want to get a resource that can be overloaded (a template for instance), Symfony would have tried all namespace prefixes one after the other until if finds a matching file. But that can be computed in advance to reduce the overhead. Another topic which was not really well addressed is how you can reference a file/resource from a bundle (and take into account the possibility of overloading). For instance, in the routing, you can import a file from a bundle like this: <import resource="FrameworkBundle/Resources/config/internal.xml" /> Again, this works only because we have a limited number of possible namespace prefixes. This patch addresses these problems and some more. First, the registerBundleDirs() method has been removed. It means that you are now free to use any namespace for your bundles. No need to have specific prefixes anymore. You are also free to store them anywhere, in as many directories as you want. You just need to be sure that they are autoloaded correctly. The bundle "name" is now always the short name of the bundle class (like FrameworkBundle or SensioCasBundle). As the best practice is to prefix the bundle name with the vendor name, it's up to the vendor to ensure that each bundle name is unique. I insist that a bundle name must be unique. This was the opposite before as two bundles with the same name was how Symfony2 found inheritance. A new getParent() method has been added to BundleInterface. It returns the bundle name that the bundle overrides (this is optional of course). That way, there is no ordering problem anymore as the inheritance tree is explicitely defined by the bundle themselves. So, with this system, we can easily have an inheritance tree like the following: FooBundle < MyFooBundle < MyCustomFooBundle MyCustomFooBundle returns MyFooBundle for the getParent() method, and MyFooBundle returns FooBundle. If two bundles override the same bundle, an exception is thrown. Based on the bundle name, you can now reference any resource with this notation: @FooBundle/Resources/config/routing.xml @FooBundle/Controller/FooController.php This notation is the input of the Kernel::locateResource() method, which returns the location of the file (and of course it takes into account overloading). So, in the routing, you can now use the following: <import resource="@FrameworkBundle/Resources/config/internal.xml" /> The template loading mechanism also use this method under the hood. As a bonus, all the code that converts from internal notations to file names (controller names: ControllerNameParser, template names: TemplateNameParser, resource paths, ...) is now contained in several well-defined classes. The same goes for the code that look for templates (TemplateLocator), routing files (FileLocator), ... As a side note, it is really easy to also support multiple-inheritance for a bundle (for instance if a bundle returns an array of bundle names it extends). However, this is not implemented in this patch as I'm not sure we want to support that. How to upgrade: * Each bundle must now implement two new mandatory methods: getPath() and getNamespace(), and optionally the getParent() method if the bundle extends another one. Here is a common implementation for these methods: /** * {@inheritdoc} */ public function getParent() { return 'MyFrameworkBundle'; } /** * {@inheritdoc} */ public function getNamespace() { return __NAMESPACE__; } /** * {@inheritdoc} */ public function getPath() { return strtr(__DIR__, '\\', '/'); } * The registerBundleDirs() can be removed from your Kernel class; * If your code relies on getBundleDirs() or the kernel.bundle_dirs parameter, it should be upgraded to use the new interface (see Doctrine commands for many example of such a change); * When referencing a bundle, you must now always use its name (no more \ or / in bundle names) -- this transition was already done for most things before, and now applies to the routing as well; * Imports in routing files must be changed: Before: <import resource="Sensio/CasBundle/Resources/config/internal.xml" /> After: <import resource="@SensioCasBundle/Resources/config/internal.xml" />
2011-01-18 09:23:49 +00:00
*/
public function locateResource($name, $dir = null, $first = true)
{
if ('@' !== $name[0]) {
throw new \InvalidArgumentException(sprintf('A resource name must start with @ ("%s" given).', $name));
}
if (false !== strpos($name, '..')) {
throw new \RuntimeException(sprintf('File name "%s" contains invalid characters (..).', $name));
}
2011-05-03 12:55:00 +01:00
$bundleName = substr($name, 1);
$path = '';
if (false !== strpos($bundleName, '/')) {
list($bundleName, $path) = explode('/', $bundleName, 2);
}
refactored bundle management Before I explain the changes, let's talk about the current state. Before this patch, the registerBundleDirs() method returned an ordered (for resource overloading) list of namespace prefixes and the path to their location. Here are some problems with this approach: * The paths set by this method and the paths configured for the autoloader can be disconnected (leading to unexpected behaviors); * A bundle outside these paths worked, but unexpected behavior can occur; * Choosing a bundle namespace was limited to the registered namespace prefixes, and their number should stay low enough (for performance reasons) -- moreover the current Bundle\ and Application\ top namespaces does not respect the standard rules for namespaces (first segment should be the vendor name); * Developers must understand the concept of "namespace prefixes" to understand the overloading mechanism, which is one more thing to learn, which is Symfony specific; * Each time you want to get a resource that can be overloaded (a template for instance), Symfony would have tried all namespace prefixes one after the other until if finds a matching file. But that can be computed in advance to reduce the overhead. Another topic which was not really well addressed is how you can reference a file/resource from a bundle (and take into account the possibility of overloading). For instance, in the routing, you can import a file from a bundle like this: <import resource="FrameworkBundle/Resources/config/internal.xml" /> Again, this works only because we have a limited number of possible namespace prefixes. This patch addresses these problems and some more. First, the registerBundleDirs() method has been removed. It means that you are now free to use any namespace for your bundles. No need to have specific prefixes anymore. You are also free to store them anywhere, in as many directories as you want. You just need to be sure that they are autoloaded correctly. The bundle "name" is now always the short name of the bundle class (like FrameworkBundle or SensioCasBundle). As the best practice is to prefix the bundle name with the vendor name, it's up to the vendor to ensure that each bundle name is unique. I insist that a bundle name must be unique. This was the opposite before as two bundles with the same name was how Symfony2 found inheritance. A new getParent() method has been added to BundleInterface. It returns the bundle name that the bundle overrides (this is optional of course). That way, there is no ordering problem anymore as the inheritance tree is explicitely defined by the bundle themselves. So, with this system, we can easily have an inheritance tree like the following: FooBundle < MyFooBundle < MyCustomFooBundle MyCustomFooBundle returns MyFooBundle for the getParent() method, and MyFooBundle returns FooBundle. If two bundles override the same bundle, an exception is thrown. Based on the bundle name, you can now reference any resource with this notation: @FooBundle/Resources/config/routing.xml @FooBundle/Controller/FooController.php This notation is the input of the Kernel::locateResource() method, which returns the location of the file (and of course it takes into account overloading). So, in the routing, you can now use the following: <import resource="@FrameworkBundle/Resources/config/internal.xml" /> The template loading mechanism also use this method under the hood. As a bonus, all the code that converts from internal notations to file names (controller names: ControllerNameParser, template names: TemplateNameParser, resource paths, ...) is now contained in several well-defined classes. The same goes for the code that look for templates (TemplateLocator), routing files (FileLocator), ... As a side note, it is really easy to also support multiple-inheritance for a bundle (for instance if a bundle returns an array of bundle names it extends). However, this is not implemented in this patch as I'm not sure we want to support that. How to upgrade: * Each bundle must now implement two new mandatory methods: getPath() and getNamespace(), and optionally the getParent() method if the bundle extends another one. Here is a common implementation for these methods: /** * {@inheritdoc} */ public function getParent() { return 'MyFrameworkBundle'; } /** * {@inheritdoc} */ public function getNamespace() { return __NAMESPACE__; } /** * {@inheritdoc} */ public function getPath() { return strtr(__DIR__, '\\', '/'); } * The registerBundleDirs() can be removed from your Kernel class; * If your code relies on getBundleDirs() or the kernel.bundle_dirs parameter, it should be upgraded to use the new interface (see Doctrine commands for many example of such a change); * When referencing a bundle, you must now always use its name (no more \ or / in bundle names) -- this transition was already done for most things before, and now applies to the routing as well; * Imports in routing files must be changed: Before: <import resource="Sensio/CasBundle/Resources/config/internal.xml" /> After: <import resource="@SensioCasBundle/Resources/config/internal.xml" />
2011-01-18 09:23:49 +00:00
$isResource = 0 === strpos($path, 'Resources') && null !== $dir;
$overridePath = substr($path, 9);
$resourceBundle = null;
$bundles = $this->getBundle($bundleName, false);
$files = array();
2011-04-05 08:48:36 +01:00
foreach ($bundles as $bundle) {
if ($isResource && file_exists($file = $dir.'/'.$bundle->getName().$overridePath)) {
if (null !== $resourceBundle) {
2011-04-05 08:48:36 +01:00
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;
refactored bundle management Before I explain the changes, let's talk about the current state. Before this patch, the registerBundleDirs() method returned an ordered (for resource overloading) list of namespace prefixes and the path to their location. Here are some problems with this approach: * The paths set by this method and the paths configured for the autoloader can be disconnected (leading to unexpected behaviors); * A bundle outside these paths worked, but unexpected behavior can occur; * Choosing a bundle namespace was limited to the registered namespace prefixes, and their number should stay low enough (for performance reasons) -- moreover the current Bundle\ and Application\ top namespaces does not respect the standard rules for namespaces (first segment should be the vendor name); * Developers must understand the concept of "namespace prefixes" to understand the overloading mechanism, which is one more thing to learn, which is Symfony specific; * Each time you want to get a resource that can be overloaded (a template for instance), Symfony would have tried all namespace prefixes one after the other until if finds a matching file. But that can be computed in advance to reduce the overhead. Another topic which was not really well addressed is how you can reference a file/resource from a bundle (and take into account the possibility of overloading). For instance, in the routing, you can import a file from a bundle like this: <import resource="FrameworkBundle/Resources/config/internal.xml" /> Again, this works only because we have a limited number of possible namespace prefixes. This patch addresses these problems and some more. First, the registerBundleDirs() method has been removed. It means that you are now free to use any namespace for your bundles. No need to have specific prefixes anymore. You are also free to store them anywhere, in as many directories as you want. You just need to be sure that they are autoloaded correctly. The bundle "name" is now always the short name of the bundle class (like FrameworkBundle or SensioCasBundle). As the best practice is to prefix the bundle name with the vendor name, it's up to the vendor to ensure that each bundle name is unique. I insist that a bundle name must be unique. This was the opposite before as two bundles with the same name was how Symfony2 found inheritance. A new getParent() method has been added to BundleInterface. It returns the bundle name that the bundle overrides (this is optional of course). That way, there is no ordering problem anymore as the inheritance tree is explicitely defined by the bundle themselves. So, with this system, we can easily have an inheritance tree like the following: FooBundle < MyFooBundle < MyCustomFooBundle MyCustomFooBundle returns MyFooBundle for the getParent() method, and MyFooBundle returns FooBundle. If two bundles override the same bundle, an exception is thrown. Based on the bundle name, you can now reference any resource with this notation: @FooBundle/Resources/config/routing.xml @FooBundle/Controller/FooController.php This notation is the input of the Kernel::locateResource() method, which returns the location of the file (and of course it takes into account overloading). So, in the routing, you can now use the following: <import resource="@FrameworkBundle/Resources/config/internal.xml" /> The template loading mechanism also use this method under the hood. As a bonus, all the code that converts from internal notations to file names (controller names: ControllerNameParser, template names: TemplateNameParser, resource paths, ...) is now contained in several well-defined classes. The same goes for the code that look for templates (TemplateLocator), routing files (FileLocator), ... As a side note, it is really easy to also support multiple-inheritance for a bundle (for instance if a bundle returns an array of bundle names it extends). However, this is not implemented in this patch as I'm not sure we want to support that. How to upgrade: * Each bundle must now implement two new mandatory methods: getPath() and getNamespace(), and optionally the getParent() method if the bundle extends another one. Here is a common implementation for these methods: /** * {@inheritdoc} */ public function getParent() { return 'MyFrameworkBundle'; } /** * {@inheritdoc} */ public function getNamespace() { return __NAMESPACE__; } /** * {@inheritdoc} */ public function getPath() { return strtr(__DIR__, '\\', '/'); } * The registerBundleDirs() can be removed from your Kernel class; * If your code relies on getBundleDirs() or the kernel.bundle_dirs parameter, it should be upgraded to use the new interface (see Doctrine commands for many example of such a change); * When referencing a bundle, you must now always use its name (no more \ or / in bundle names) -- this transition was already done for most things before, and now applies to the routing as well; * Imports in routing files must be changed: Before: <import resource="Sensio/CasBundle/Resources/config/internal.xml" /> After: <import resource="@SensioCasBundle/Resources/config/internal.xml" />
2011-01-18 09:23:49 +00:00
}
if (file_exists($file = $bundle->getPath().'/'.$path)) {
if ($first && !$isResource) {
return $file;
}
refactored bundle management Before I explain the changes, let's talk about the current state. Before this patch, the registerBundleDirs() method returned an ordered (for resource overloading) list of namespace prefixes and the path to their location. Here are some problems with this approach: * The paths set by this method and the paths configured for the autoloader can be disconnected (leading to unexpected behaviors); * A bundle outside these paths worked, but unexpected behavior can occur; * Choosing a bundle namespace was limited to the registered namespace prefixes, and their number should stay low enough (for performance reasons) -- moreover the current Bundle\ and Application\ top namespaces does not respect the standard rules for namespaces (first segment should be the vendor name); * Developers must understand the concept of "namespace prefixes" to understand the overloading mechanism, which is one more thing to learn, which is Symfony specific; * Each time you want to get a resource that can be overloaded (a template for instance), Symfony would have tried all namespace prefixes one after the other until if finds a matching file. But that can be computed in advance to reduce the overhead. Another topic which was not really well addressed is how you can reference a file/resource from a bundle (and take into account the possibility of overloading). For instance, in the routing, you can import a file from a bundle like this: <import resource="FrameworkBundle/Resources/config/internal.xml" /> Again, this works only because we have a limited number of possible namespace prefixes. This patch addresses these problems and some more. First, the registerBundleDirs() method has been removed. It means that you are now free to use any namespace for your bundles. No need to have specific prefixes anymore. You are also free to store them anywhere, in as many directories as you want. You just need to be sure that they are autoloaded correctly. The bundle "name" is now always the short name of the bundle class (like FrameworkBundle or SensioCasBundle). As the best practice is to prefix the bundle name with the vendor name, it's up to the vendor to ensure that each bundle name is unique. I insist that a bundle name must be unique. This was the opposite before as two bundles with the same name was how Symfony2 found inheritance. A new getParent() method has been added to BundleInterface. It returns the bundle name that the bundle overrides (this is optional of course). That way, there is no ordering problem anymore as the inheritance tree is explicitely defined by the bundle themselves. So, with this system, we can easily have an inheritance tree like the following: FooBundle < MyFooBundle < MyCustomFooBundle MyCustomFooBundle returns MyFooBundle for the getParent() method, and MyFooBundle returns FooBundle. If two bundles override the same bundle, an exception is thrown. Based on the bundle name, you can now reference any resource with this notation: @FooBundle/Resources/config/routing.xml @FooBundle/Controller/FooController.php This notation is the input of the Kernel::locateResource() method, which returns the location of the file (and of course it takes into account overloading). So, in the routing, you can now use the following: <import resource="@FrameworkBundle/Resources/config/internal.xml" /> The template loading mechanism also use this method under the hood. As a bonus, all the code that converts from internal notations to file names (controller names: ControllerNameParser, template names: TemplateNameParser, resource paths, ...) is now contained in several well-defined classes. The same goes for the code that look for templates (TemplateLocator), routing files (FileLocator), ... As a side note, it is really easy to also support multiple-inheritance for a bundle (for instance if a bundle returns an array of bundle names it extends). However, this is not implemented in this patch as I'm not sure we want to support that. How to upgrade: * Each bundle must now implement two new mandatory methods: getPath() and getNamespace(), and optionally the getParent() method if the bundle extends another one. Here is a common implementation for these methods: /** * {@inheritdoc} */ public function getParent() { return 'MyFrameworkBundle'; } /** * {@inheritdoc} */ public function getNamespace() { return __NAMESPACE__; } /** * {@inheritdoc} */ public function getPath() { return strtr(__DIR__, '\\', '/'); } * The registerBundleDirs() can be removed from your Kernel class; * If your code relies on getBundleDirs() or the kernel.bundle_dirs parameter, it should be upgraded to use the new interface (see Doctrine commands for many example of such a change); * When referencing a bundle, you must now always use its name (no more \ or / in bundle names) -- this transition was already done for most things before, and now applies to the routing as well; * Imports in routing files must be changed: Before: <import resource="Sensio/CasBundle/Resources/config/internal.xml" /> After: <import resource="@SensioCasBundle/Resources/config/internal.xml" />
2011-01-18 09:23:49 +00:00
$files[] = $file;
$resourceBundle = $bundle->getName();
refactored bundle management Before I explain the changes, let's talk about the current state. Before this patch, the registerBundleDirs() method returned an ordered (for resource overloading) list of namespace prefixes and the path to their location. Here are some problems with this approach: * The paths set by this method and the paths configured for the autoloader can be disconnected (leading to unexpected behaviors); * A bundle outside these paths worked, but unexpected behavior can occur; * Choosing a bundle namespace was limited to the registered namespace prefixes, and their number should stay low enough (for performance reasons) -- moreover the current Bundle\ and Application\ top namespaces does not respect the standard rules for namespaces (first segment should be the vendor name); * Developers must understand the concept of "namespace prefixes" to understand the overloading mechanism, which is one more thing to learn, which is Symfony specific; * Each time you want to get a resource that can be overloaded (a template for instance), Symfony would have tried all namespace prefixes one after the other until if finds a matching file. But that can be computed in advance to reduce the overhead. Another topic which was not really well addressed is how you can reference a file/resource from a bundle (and take into account the possibility of overloading). For instance, in the routing, you can import a file from a bundle like this: <import resource="FrameworkBundle/Resources/config/internal.xml" /> Again, this works only because we have a limited number of possible namespace prefixes. This patch addresses these problems and some more. First, the registerBundleDirs() method has been removed. It means that you are now free to use any namespace for your bundles. No need to have specific prefixes anymore. You are also free to store them anywhere, in as many directories as you want. You just need to be sure that they are autoloaded correctly. The bundle "name" is now always the short name of the bundle class (like FrameworkBundle or SensioCasBundle). As the best practice is to prefix the bundle name with the vendor name, it's up to the vendor to ensure that each bundle name is unique. I insist that a bundle name must be unique. This was the opposite before as two bundles with the same name was how Symfony2 found inheritance. A new getParent() method has been added to BundleInterface. It returns the bundle name that the bundle overrides (this is optional of course). That way, there is no ordering problem anymore as the inheritance tree is explicitely defined by the bundle themselves. So, with this system, we can easily have an inheritance tree like the following: FooBundle < MyFooBundle < MyCustomFooBundle MyCustomFooBundle returns MyFooBundle for the getParent() method, and MyFooBundle returns FooBundle. If two bundles override the same bundle, an exception is thrown. Based on the bundle name, you can now reference any resource with this notation: @FooBundle/Resources/config/routing.xml @FooBundle/Controller/FooController.php This notation is the input of the Kernel::locateResource() method, which returns the location of the file (and of course it takes into account overloading). So, in the routing, you can now use the following: <import resource="@FrameworkBundle/Resources/config/internal.xml" /> The template loading mechanism also use this method under the hood. As a bonus, all the code that converts from internal notations to file names (controller names: ControllerNameParser, template names: TemplateNameParser, resource paths, ...) is now contained in several well-defined classes. The same goes for the code that look for templates (TemplateLocator), routing files (FileLocator), ... As a side note, it is really easy to also support multiple-inheritance for a bundle (for instance if a bundle returns an array of bundle names it extends). However, this is not implemented in this patch as I'm not sure we want to support that. How to upgrade: * Each bundle must now implement two new mandatory methods: getPath() and getNamespace(), and optionally the getParent() method if the bundle extends another one. Here is a common implementation for these methods: /** * {@inheritdoc} */ public function getParent() { return 'MyFrameworkBundle'; } /** * {@inheritdoc} */ public function getNamespace() { return __NAMESPACE__; } /** * {@inheritdoc} */ public function getPath() { return strtr(__DIR__, '\\', '/'); } * The registerBundleDirs() can be removed from your Kernel class; * If your code relies on getBundleDirs() or the kernel.bundle_dirs parameter, it should be upgraded to use the new interface (see Doctrine commands for many example of such a change); * When referencing a bundle, you must now always use its name (no more \ or / in bundle names) -- this transition was already done for most things before, and now applies to the routing as well; * Imports in routing files must be changed: Before: <import resource="Sensio/CasBundle/Resources/config/internal.xml" /> After: <import resource="@SensioCasBundle/Resources/config/internal.xml" />
2011-01-18 09:23:49 +00:00
}
}
if (count($files) > 0) {
return $first && $isResource ? $files[0] : $files;
refactored bundle management Before I explain the changes, let's talk about the current state. Before this patch, the registerBundleDirs() method returned an ordered (for resource overloading) list of namespace prefixes and the path to their location. Here are some problems with this approach: * The paths set by this method and the paths configured for the autoloader can be disconnected (leading to unexpected behaviors); * A bundle outside these paths worked, but unexpected behavior can occur; * Choosing a bundle namespace was limited to the registered namespace prefixes, and their number should stay low enough (for performance reasons) -- moreover the current Bundle\ and Application\ top namespaces does not respect the standard rules for namespaces (first segment should be the vendor name); * Developers must understand the concept of "namespace prefixes" to understand the overloading mechanism, which is one more thing to learn, which is Symfony specific; * Each time you want to get a resource that can be overloaded (a template for instance), Symfony would have tried all namespace prefixes one after the other until if finds a matching file. But that can be computed in advance to reduce the overhead. Another topic which was not really well addressed is how you can reference a file/resource from a bundle (and take into account the possibility of overloading). For instance, in the routing, you can import a file from a bundle like this: <import resource="FrameworkBundle/Resources/config/internal.xml" /> Again, this works only because we have a limited number of possible namespace prefixes. This patch addresses these problems and some more. First, the registerBundleDirs() method has been removed. It means that you are now free to use any namespace for your bundles. No need to have specific prefixes anymore. You are also free to store them anywhere, in as many directories as you want. You just need to be sure that they are autoloaded correctly. The bundle "name" is now always the short name of the bundle class (like FrameworkBundle or SensioCasBundle). As the best practice is to prefix the bundle name with the vendor name, it's up to the vendor to ensure that each bundle name is unique. I insist that a bundle name must be unique. This was the opposite before as two bundles with the same name was how Symfony2 found inheritance. A new getParent() method has been added to BundleInterface. It returns the bundle name that the bundle overrides (this is optional of course). That way, there is no ordering problem anymore as the inheritance tree is explicitely defined by the bundle themselves. So, with this system, we can easily have an inheritance tree like the following: FooBundle < MyFooBundle < MyCustomFooBundle MyCustomFooBundle returns MyFooBundle for the getParent() method, and MyFooBundle returns FooBundle. If two bundles override the same bundle, an exception is thrown. Based on the bundle name, you can now reference any resource with this notation: @FooBundle/Resources/config/routing.xml @FooBundle/Controller/FooController.php This notation is the input of the Kernel::locateResource() method, which returns the location of the file (and of course it takes into account overloading). So, in the routing, you can now use the following: <import resource="@FrameworkBundle/Resources/config/internal.xml" /> The template loading mechanism also use this method under the hood. As a bonus, all the code that converts from internal notations to file names (controller names: ControllerNameParser, template names: TemplateNameParser, resource paths, ...) is now contained in several well-defined classes. The same goes for the code that look for templates (TemplateLocator), routing files (FileLocator), ... As a side note, it is really easy to also support multiple-inheritance for a bundle (for instance if a bundle returns an array of bundle names it extends). However, this is not implemented in this patch as I'm not sure we want to support that. How to upgrade: * Each bundle must now implement two new mandatory methods: getPath() and getNamespace(), and optionally the getParent() method if the bundle extends another one. Here is a common implementation for these methods: /** * {@inheritdoc} */ public function getParent() { return 'MyFrameworkBundle'; } /** * {@inheritdoc} */ public function getNamespace() { return __NAMESPACE__; } /** * {@inheritdoc} */ public function getPath() { return strtr(__DIR__, '\\', '/'); } * The registerBundleDirs() can be removed from your Kernel class; * If your code relies on getBundleDirs() or the kernel.bundle_dirs parameter, it should be upgraded to use the new interface (see Doctrine commands for many example of such a change); * When referencing a bundle, you must now always use its name (no more \ or / in bundle names) -- this transition was already done for most things before, and now applies to the routing as well; * Imports in routing files must be changed: Before: <import resource="Sensio/CasBundle/Resources/config/internal.xml" /> After: <import resource="@SensioCasBundle/Resources/config/internal.xml" />
2011-01-18 09:23:49 +00:00
}
2011-05-03 12:55:00 +01:00
throw new \InvalidArgumentException(sprintf('Unable to find file "%s".', $name));
refactored bundle management Before I explain the changes, let's talk about the current state. Before this patch, the registerBundleDirs() method returned an ordered (for resource overloading) list of namespace prefixes and the path to their location. Here are some problems with this approach: * The paths set by this method and the paths configured for the autoloader can be disconnected (leading to unexpected behaviors); * A bundle outside these paths worked, but unexpected behavior can occur; * Choosing a bundle namespace was limited to the registered namespace prefixes, and their number should stay low enough (for performance reasons) -- moreover the current Bundle\ and Application\ top namespaces does not respect the standard rules for namespaces (first segment should be the vendor name); * Developers must understand the concept of "namespace prefixes" to understand the overloading mechanism, which is one more thing to learn, which is Symfony specific; * Each time you want to get a resource that can be overloaded (a template for instance), Symfony would have tried all namespace prefixes one after the other until if finds a matching file. But that can be computed in advance to reduce the overhead. Another topic which was not really well addressed is how you can reference a file/resource from a bundle (and take into account the possibility of overloading). For instance, in the routing, you can import a file from a bundle like this: <import resource="FrameworkBundle/Resources/config/internal.xml" /> Again, this works only because we have a limited number of possible namespace prefixes. This patch addresses these problems and some more. First, the registerBundleDirs() method has been removed. It means that you are now free to use any namespace for your bundles. No need to have specific prefixes anymore. You are also free to store them anywhere, in as many directories as you want. You just need to be sure that they are autoloaded correctly. The bundle "name" is now always the short name of the bundle class (like FrameworkBundle or SensioCasBundle). As the best practice is to prefix the bundle name with the vendor name, it's up to the vendor to ensure that each bundle name is unique. I insist that a bundle name must be unique. This was the opposite before as two bundles with the same name was how Symfony2 found inheritance. A new getParent() method has been added to BundleInterface. It returns the bundle name that the bundle overrides (this is optional of course). That way, there is no ordering problem anymore as the inheritance tree is explicitely defined by the bundle themselves. So, with this system, we can easily have an inheritance tree like the following: FooBundle < MyFooBundle < MyCustomFooBundle MyCustomFooBundle returns MyFooBundle for the getParent() method, and MyFooBundle returns FooBundle. If two bundles override the same bundle, an exception is thrown. Based on the bundle name, you can now reference any resource with this notation: @FooBundle/Resources/config/routing.xml @FooBundle/Controller/FooController.php This notation is the input of the Kernel::locateResource() method, which returns the location of the file (and of course it takes into account overloading). So, in the routing, you can now use the following: <import resource="@FrameworkBundle/Resources/config/internal.xml" /> The template loading mechanism also use this method under the hood. As a bonus, all the code that converts from internal notations to file names (controller names: ControllerNameParser, template names: TemplateNameParser, resource paths, ...) is now contained in several well-defined classes. The same goes for the code that look for templates (TemplateLocator), routing files (FileLocator), ... As a side note, it is really easy to also support multiple-inheritance for a bundle (for instance if a bundle returns an array of bundle names it extends). However, this is not implemented in this patch as I'm not sure we want to support that. How to upgrade: * Each bundle must now implement two new mandatory methods: getPath() and getNamespace(), and optionally the getParent() method if the bundle extends another one. Here is a common implementation for these methods: /** * {@inheritdoc} */ public function getParent() { return 'MyFrameworkBundle'; } /** * {@inheritdoc} */ public function getNamespace() { return __NAMESPACE__; } /** * {@inheritdoc} */ public function getPath() { return strtr(__DIR__, '\\', '/'); } * The registerBundleDirs() can be removed from your Kernel class; * If your code relies on getBundleDirs() or the kernel.bundle_dirs parameter, it should be upgraded to use the new interface (see Doctrine commands for many example of such a change); * When referencing a bundle, you must now always use its name (no more \ or / in bundle names) -- this transition was already done for most things before, and now applies to the routing as well; * Imports in routing files must be changed: Before: <import resource="Sensio/CasBundle/Resources/config/internal.xml" /> After: <import resource="@SensioCasBundle/Resources/config/internal.xml" />
2011-01-18 09:23:49 +00:00
}
/**
* Gets the name of the kernel
*
* @return string The kernel name
2011-07-20 09:14:31 +01:00
*
* @api
*/
public function getName()
{
return $this->name;
}
2011-01-17 19:41:55 +00:00
/**
* Gets the environment.
*
* @return string The current environment
2011-07-20 09:14:31 +01:00
*
* @api
2011-01-17 19:41:55 +00:00
*/
public function getEnvironment()
{
return $this->environment;
}
2011-01-17 19:41:55 +00:00
/**
* Checks if debug mode is enabled.
*
* @return Boolean true if debug mode is enabled, false otherwise
2011-07-20 09:14:31 +01:00
*
* @api
2011-01-17 19:41:55 +00:00
*/
public function isDebug()
{
return $this->debug;
}
2011-01-17 19:41:55 +00:00
/**
* Gets the application root dir.
*
* @return string The application root dir
2011-07-20 09:14:31 +01:00
*
* @api
2011-01-17 19:41:55 +00:00
*/
public function getRootDir()
{
if (null === $this->rootDir) {
$r = new \ReflectionObject($this);
$this->rootDir = str_replace('\\', '/', dirname($r->getFileName()));
}
return $this->rootDir;
}
2011-01-17 19:41:55 +00:00
/**
* Gets the current container.
*
* @return ContainerInterface A ContainerInterface instance
2011-07-20 09:14:31 +01:00
*
* @api
2011-01-17 19:41:55 +00:00
*/
public function getContainer()
{
return $this->container;
}
/**
* Loads the PHP class cache.
*
2012-05-15 17:56:32 +01:00
* @param string $name The cache name prefix
* @param string $extension File extension of the resulting file
*/
public function loadClassCache($name = 'classes', $extension = '.php')
{
if (!$this->booted && file_exists($this->getCacheDir().'/classes.map')) {
ClassCollectionLoader::load(include($this->getCacheDir().'/classes.map'), $this->getCacheDir(), $name, $this->debug, false, $extension);
}
}
/**
* Used internally.
*/
public function setClassCache(array $classes)
{
file_put_contents($this->getCacheDir().'/classes.map', sprintf('<?php return %s;', var_export($classes, true)));
}
2011-01-17 19:41:55 +00:00
/**
* Gets the request start time (not available if debug is disabled).
*
* @return integer The request start timestamp
2011-07-20 09:14:31 +01:00
*
* @api
2011-01-17 19:41:55 +00:00
*/
public function getStartTime()
{
return $this->debug ? $this->startTime : -INF;
}
2011-01-17 19:41:55 +00:00
/**
* Gets the cache directory.
*
* @return string The cache directory
2011-07-20 09:14:31 +01:00
*
* @api
2011-01-17 19:41:55 +00:00
*/
public function getCacheDir()
{
return $this->rootDir.'/cache/'.$this->environment;
}
2011-01-17 19:41:55 +00:00
/**
* Gets the log directory.
*
* @return string The log directory
2011-07-20 09:14:31 +01:00
*
* @api
2011-01-17 19:41:55 +00:00
*/
public function getLogDir()
{
return $this->rootDir.'/logs';
}
2011-01-28 20:55:43 +00:00
/**
2011-03-16 20:35:00 +00:00
* Initializes the data structures related to the bundle management.
*
2011-02-08 16:00:13 +00:00
* - 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).
2011-01-28 20:55:43 +00:00
*
* @throws \LogicException if two bundles share a common name
* @throws \LogicException if a bundle tries to extend a non-registered bundle
2011-04-06 06:46:08 +01:00
* @throws \LogicException if a bundle tries to extend itself
2011-01-28 20:55:43 +00:00
* @throws \LogicException if two bundles extend the same ancestor
*/
refactored bundle management Before I explain the changes, let's talk about the current state. Before this patch, the registerBundleDirs() method returned an ordered (for resource overloading) list of namespace prefixes and the path to their location. Here are some problems with this approach: * The paths set by this method and the paths configured for the autoloader can be disconnected (leading to unexpected behaviors); * A bundle outside these paths worked, but unexpected behavior can occur; * Choosing a bundle namespace was limited to the registered namespace prefixes, and their number should stay low enough (for performance reasons) -- moreover the current Bundle\ and Application\ top namespaces does not respect the standard rules for namespaces (first segment should be the vendor name); * Developers must understand the concept of "namespace prefixes" to understand the overloading mechanism, which is one more thing to learn, which is Symfony specific; * Each time you want to get a resource that can be overloaded (a template for instance), Symfony would have tried all namespace prefixes one after the other until if finds a matching file. But that can be computed in advance to reduce the overhead. Another topic which was not really well addressed is how you can reference a file/resource from a bundle (and take into account the possibility of overloading). For instance, in the routing, you can import a file from a bundle like this: <import resource="FrameworkBundle/Resources/config/internal.xml" /> Again, this works only because we have a limited number of possible namespace prefixes. This patch addresses these problems and some more. First, the registerBundleDirs() method has been removed. It means that you are now free to use any namespace for your bundles. No need to have specific prefixes anymore. You are also free to store them anywhere, in as many directories as you want. You just need to be sure that they are autoloaded correctly. The bundle "name" is now always the short name of the bundle class (like FrameworkBundle or SensioCasBundle). As the best practice is to prefix the bundle name with the vendor name, it's up to the vendor to ensure that each bundle name is unique. I insist that a bundle name must be unique. This was the opposite before as two bundles with the same name was how Symfony2 found inheritance. A new getParent() method has been added to BundleInterface. It returns the bundle name that the bundle overrides (this is optional of course). That way, there is no ordering problem anymore as the inheritance tree is explicitely defined by the bundle themselves. So, with this system, we can easily have an inheritance tree like the following: FooBundle < MyFooBundle < MyCustomFooBundle MyCustomFooBundle returns MyFooBundle for the getParent() method, and MyFooBundle returns FooBundle. If two bundles override the same bundle, an exception is thrown. Based on the bundle name, you can now reference any resource with this notation: @FooBundle/Resources/config/routing.xml @FooBundle/Controller/FooController.php This notation is the input of the Kernel::locateResource() method, which returns the location of the file (and of course it takes into account overloading). So, in the routing, you can now use the following: <import resource="@FrameworkBundle/Resources/config/internal.xml" /> The template loading mechanism also use this method under the hood. As a bonus, all the code that converts from internal notations to file names (controller names: ControllerNameParser, template names: TemplateNameParser, resource paths, ...) is now contained in several well-defined classes. The same goes for the code that look for templates (TemplateLocator), routing files (FileLocator), ... As a side note, it is really easy to also support multiple-inheritance for a bundle (for instance if a bundle returns an array of bundle names it extends). However, this is not implemented in this patch as I'm not sure we want to support that. How to upgrade: * Each bundle must now implement two new mandatory methods: getPath() and getNamespace(), and optionally the getParent() method if the bundle extends another one. Here is a common implementation for these methods: /** * {@inheritdoc} */ public function getParent() { return 'MyFrameworkBundle'; } /** * {@inheritdoc} */ public function getNamespace() { return __NAMESPACE__; } /** * {@inheritdoc} */ public function getPath() { return strtr(__DIR__, '\\', '/'); } * The registerBundleDirs() can be removed from your Kernel class; * If your code relies on getBundleDirs() or the kernel.bundle_dirs parameter, it should be upgraded to use the new interface (see Doctrine commands for many example of such a change); * When referencing a bundle, you must now always use its name (no more \ or / in bundle names) -- this transition was already done for most things before, and now applies to the routing as well; * Imports in routing files must be changed: Before: <import resource="Sensio/CasBundle/Resources/config/internal.xml" /> After: <import resource="@SensioCasBundle/Resources/config/internal.xml" />
2011-01-18 09:23:49 +00:00
protected function initializeBundles()
{
// init bundles
$this->bundles = array();
$topMostBundles = array();
$directChildren = array();
refactored bundle management Before I explain the changes, let's talk about the current state. Before this patch, the registerBundleDirs() method returned an ordered (for resource overloading) list of namespace prefixes and the path to their location. Here are some problems with this approach: * The paths set by this method and the paths configured for the autoloader can be disconnected (leading to unexpected behaviors); * A bundle outside these paths worked, but unexpected behavior can occur; * Choosing a bundle namespace was limited to the registered namespace prefixes, and their number should stay low enough (for performance reasons) -- moreover the current Bundle\ and Application\ top namespaces does not respect the standard rules for namespaces (first segment should be the vendor name); * Developers must understand the concept of "namespace prefixes" to understand the overloading mechanism, which is one more thing to learn, which is Symfony specific; * Each time you want to get a resource that can be overloaded (a template for instance), Symfony would have tried all namespace prefixes one after the other until if finds a matching file. But that can be computed in advance to reduce the overhead. Another topic which was not really well addressed is how you can reference a file/resource from a bundle (and take into account the possibility of overloading). For instance, in the routing, you can import a file from a bundle like this: <import resource="FrameworkBundle/Resources/config/internal.xml" /> Again, this works only because we have a limited number of possible namespace prefixes. This patch addresses these problems and some more. First, the registerBundleDirs() method has been removed. It means that you are now free to use any namespace for your bundles. No need to have specific prefixes anymore. You are also free to store them anywhere, in as many directories as you want. You just need to be sure that they are autoloaded correctly. The bundle "name" is now always the short name of the bundle class (like FrameworkBundle or SensioCasBundle). As the best practice is to prefix the bundle name with the vendor name, it's up to the vendor to ensure that each bundle name is unique. I insist that a bundle name must be unique. This was the opposite before as two bundles with the same name was how Symfony2 found inheritance. A new getParent() method has been added to BundleInterface. It returns the bundle name that the bundle overrides (this is optional of course). That way, there is no ordering problem anymore as the inheritance tree is explicitely defined by the bundle themselves. So, with this system, we can easily have an inheritance tree like the following: FooBundle < MyFooBundle < MyCustomFooBundle MyCustomFooBundle returns MyFooBundle for the getParent() method, and MyFooBundle returns FooBundle. If two bundles override the same bundle, an exception is thrown. Based on the bundle name, you can now reference any resource with this notation: @FooBundle/Resources/config/routing.xml @FooBundle/Controller/FooController.php This notation is the input of the Kernel::locateResource() method, which returns the location of the file (and of course it takes into account overloading). So, in the routing, you can now use the following: <import resource="@FrameworkBundle/Resources/config/internal.xml" /> The template loading mechanism also use this method under the hood. As a bonus, all the code that converts from internal notations to file names (controller names: ControllerNameParser, template names: TemplateNameParser, resource paths, ...) is now contained in several well-defined classes. The same goes for the code that look for templates (TemplateLocator), routing files (FileLocator), ... As a side note, it is really easy to also support multiple-inheritance for a bundle (for instance if a bundle returns an array of bundle names it extends). However, this is not implemented in this patch as I'm not sure we want to support that. How to upgrade: * Each bundle must now implement two new mandatory methods: getPath() and getNamespace(), and optionally the getParent() method if the bundle extends another one. Here is a common implementation for these methods: /** * {@inheritdoc} */ public function getParent() { return 'MyFrameworkBundle'; } /** * {@inheritdoc} */ public function getNamespace() { return __NAMESPACE__; } /** * {@inheritdoc} */ public function getPath() { return strtr(__DIR__, '\\', '/'); } * The registerBundleDirs() can be removed from your Kernel class; * If your code relies on getBundleDirs() or the kernel.bundle_dirs parameter, it should be upgraded to use the new interface (see Doctrine commands for many example of such a change); * When referencing a bundle, you must now always use its name (no more \ or / in bundle names) -- this transition was already done for most things before, and now applies to the routing as well; * Imports in routing files must be changed: Before: <import resource="Sensio/CasBundle/Resources/config/internal.xml" /> After: <import resource="@SensioCasBundle/Resources/config/internal.xml" />
2011-01-18 09:23:49 +00:00
foreach ($this->registerBundles() as $bundle) {
$name = $bundle->getName();
2011-01-28 20:55:43 +00:00
if (isset($this->bundles[$name])) {
throw new \LogicException(sprintf('Trying to register two bundles with the same name "%s"', $name));
}
refactored bundle management Before I explain the changes, let's talk about the current state. Before this patch, the registerBundleDirs() method returned an ordered (for resource overloading) list of namespace prefixes and the path to their location. Here are some problems with this approach: * The paths set by this method and the paths configured for the autoloader can be disconnected (leading to unexpected behaviors); * A bundle outside these paths worked, but unexpected behavior can occur; * Choosing a bundle namespace was limited to the registered namespace prefixes, and their number should stay low enough (for performance reasons) -- moreover the current Bundle\ and Application\ top namespaces does not respect the standard rules for namespaces (first segment should be the vendor name); * Developers must understand the concept of "namespace prefixes" to understand the overloading mechanism, which is one more thing to learn, which is Symfony specific; * Each time you want to get a resource that can be overloaded (a template for instance), Symfony would have tried all namespace prefixes one after the other until if finds a matching file. But that can be computed in advance to reduce the overhead. Another topic which was not really well addressed is how you can reference a file/resource from a bundle (and take into account the possibility of overloading). For instance, in the routing, you can import a file from a bundle like this: <import resource="FrameworkBundle/Resources/config/internal.xml" /> Again, this works only because we have a limited number of possible namespace prefixes. This patch addresses these problems and some more. First, the registerBundleDirs() method has been removed. It means that you are now free to use any namespace for your bundles. No need to have specific prefixes anymore. You are also free to store them anywhere, in as many directories as you want. You just need to be sure that they are autoloaded correctly. The bundle "name" is now always the short name of the bundle class (like FrameworkBundle or SensioCasBundle). As the best practice is to prefix the bundle name with the vendor name, it's up to the vendor to ensure that each bundle name is unique. I insist that a bundle name must be unique. This was the opposite before as two bundles with the same name was how Symfony2 found inheritance. A new getParent() method has been added to BundleInterface. It returns the bundle name that the bundle overrides (this is optional of course). That way, there is no ordering problem anymore as the inheritance tree is explicitely defined by the bundle themselves. So, with this system, we can easily have an inheritance tree like the following: FooBundle < MyFooBundle < MyCustomFooBundle MyCustomFooBundle returns MyFooBundle for the getParent() method, and MyFooBundle returns FooBundle. If two bundles override the same bundle, an exception is thrown. Based on the bundle name, you can now reference any resource with this notation: @FooBundle/Resources/config/routing.xml @FooBundle/Controller/FooController.php This notation is the input of the Kernel::locateResource() method, which returns the location of the file (and of course it takes into account overloading). So, in the routing, you can now use the following: <import resource="@FrameworkBundle/Resources/config/internal.xml" /> The template loading mechanism also use this method under the hood. As a bonus, all the code that converts from internal notations to file names (controller names: ControllerNameParser, template names: TemplateNameParser, resource paths, ...) is now contained in several well-defined classes. The same goes for the code that look for templates (TemplateLocator), routing files (FileLocator), ... As a side note, it is really easy to also support multiple-inheritance for a bundle (for instance if a bundle returns an array of bundle names it extends). However, this is not implemented in this patch as I'm not sure we want to support that. How to upgrade: * Each bundle must now implement two new mandatory methods: getPath() and getNamespace(), and optionally the getParent() method if the bundle extends another one. Here is a common implementation for these methods: /** * {@inheritdoc} */ public function getParent() { return 'MyFrameworkBundle'; } /** * {@inheritdoc} */ public function getNamespace() { return __NAMESPACE__; } /** * {@inheritdoc} */ public function getPath() { return strtr(__DIR__, '\\', '/'); } * The registerBundleDirs() can be removed from your Kernel class; * If your code relies on getBundleDirs() or the kernel.bundle_dirs parameter, it should be upgraded to use the new interface (see Doctrine commands for many example of such a change); * When referencing a bundle, you must now always use its name (no more \ or / in bundle names) -- this transition was already done for most things before, and now applies to the routing as well; * Imports in routing files must be changed: Before: <import resource="Sensio/CasBundle/Resources/config/internal.xml" /> After: <import resource="@SensioCasBundle/Resources/config/internal.xml" />
2011-01-18 09:23:49 +00:00
$this->bundles[$name] = $bundle;
if ($parentName = $bundle->getParent()) {
if (isset($directChildren[$parentName])) {
throw new \LogicException(sprintf('Bundle "%s" is directly extended by two bundles "%s" and "%s".', $parentName, $name, $directChildren[$parentName]));
refactored bundle management Before I explain the changes, let's talk about the current state. Before this patch, the registerBundleDirs() method returned an ordered (for resource overloading) list of namespace prefixes and the path to their location. Here are some problems with this approach: * The paths set by this method and the paths configured for the autoloader can be disconnected (leading to unexpected behaviors); * A bundle outside these paths worked, but unexpected behavior can occur; * Choosing a bundle namespace was limited to the registered namespace prefixes, and their number should stay low enough (for performance reasons) -- moreover the current Bundle\ and Application\ top namespaces does not respect the standard rules for namespaces (first segment should be the vendor name); * Developers must understand the concept of "namespace prefixes" to understand the overloading mechanism, which is one more thing to learn, which is Symfony specific; * Each time you want to get a resource that can be overloaded (a template for instance), Symfony would have tried all namespace prefixes one after the other until if finds a matching file. But that can be computed in advance to reduce the overhead. Another topic which was not really well addressed is how you can reference a file/resource from a bundle (and take into account the possibility of overloading). For instance, in the routing, you can import a file from a bundle like this: <import resource="FrameworkBundle/Resources/config/internal.xml" /> Again, this works only because we have a limited number of possible namespace prefixes. This patch addresses these problems and some more. First, the registerBundleDirs() method has been removed. It means that you are now free to use any namespace for your bundles. No need to have specific prefixes anymore. You are also free to store them anywhere, in as many directories as you want. You just need to be sure that they are autoloaded correctly. The bundle "name" is now always the short name of the bundle class (like FrameworkBundle or SensioCasBundle). As the best practice is to prefix the bundle name with the vendor name, it's up to the vendor to ensure that each bundle name is unique. I insist that a bundle name must be unique. This was the opposite before as two bundles with the same name was how Symfony2 found inheritance. A new getParent() method has been added to BundleInterface. It returns the bundle name that the bundle overrides (this is optional of course). That way, there is no ordering problem anymore as the inheritance tree is explicitely defined by the bundle themselves. So, with this system, we can easily have an inheritance tree like the following: FooBundle < MyFooBundle < MyCustomFooBundle MyCustomFooBundle returns MyFooBundle for the getParent() method, and MyFooBundle returns FooBundle. If two bundles override the same bundle, an exception is thrown. Based on the bundle name, you can now reference any resource with this notation: @FooBundle/Resources/config/routing.xml @FooBundle/Controller/FooController.php This notation is the input of the Kernel::locateResource() method, which returns the location of the file (and of course it takes into account overloading). So, in the routing, you can now use the following: <import resource="@FrameworkBundle/Resources/config/internal.xml" /> The template loading mechanism also use this method under the hood. As a bonus, all the code that converts from internal notations to file names (controller names: ControllerNameParser, template names: TemplateNameParser, resource paths, ...) is now contained in several well-defined classes. The same goes for the code that look for templates (TemplateLocator), routing files (FileLocator), ... As a side note, it is really easy to also support multiple-inheritance for a bundle (for instance if a bundle returns an array of bundle names it extends). However, this is not implemented in this patch as I'm not sure we want to support that. How to upgrade: * Each bundle must now implement two new mandatory methods: getPath() and getNamespace(), and optionally the getParent() method if the bundle extends another one. Here is a common implementation for these methods: /** * {@inheritdoc} */ public function getParent() { return 'MyFrameworkBundle'; } /** * {@inheritdoc} */ public function getNamespace() { return __NAMESPACE__; } /** * {@inheritdoc} */ public function getPath() { return strtr(__DIR__, '\\', '/'); } * The registerBundleDirs() can be removed from your Kernel class; * If your code relies on getBundleDirs() or the kernel.bundle_dirs parameter, it should be upgraded to use the new interface (see Doctrine commands for many example of such a change); * When referencing a bundle, you must now always use its name (no more \ or / in bundle names) -- this transition was already done for most things before, and now applies to the routing as well; * Imports in routing files must be changed: Before: <import resource="Sensio/CasBundle/Resources/config/internal.xml" /> After: <import resource="@SensioCasBundle/Resources/config/internal.xml" />
2011-01-18 09:23:49 +00:00
}
2011-04-06 06:46:08 +01:00
if ($parentName == $name) {
throw new \LogicException(sprintf('Bundle "%s" can not extend itself.', $name));
}
$directChildren[$parentName] = $name;
} else {
$topMostBundles[$name] = $bundle;
}
}
refactored bundle management Before I explain the changes, let's talk about the current state. Before this patch, the registerBundleDirs() method returned an ordered (for resource overloading) list of namespace prefixes and the path to their location. Here are some problems with this approach: * The paths set by this method and the paths configured for the autoloader can be disconnected (leading to unexpected behaviors); * A bundle outside these paths worked, but unexpected behavior can occur; * Choosing a bundle namespace was limited to the registered namespace prefixes, and their number should stay low enough (for performance reasons) -- moreover the current Bundle\ and Application\ top namespaces does not respect the standard rules for namespaces (first segment should be the vendor name); * Developers must understand the concept of "namespace prefixes" to understand the overloading mechanism, which is one more thing to learn, which is Symfony specific; * Each time you want to get a resource that can be overloaded (a template for instance), Symfony would have tried all namespace prefixes one after the other until if finds a matching file. But that can be computed in advance to reduce the overhead. Another topic which was not really well addressed is how you can reference a file/resource from a bundle (and take into account the possibility of overloading). For instance, in the routing, you can import a file from a bundle like this: <import resource="FrameworkBundle/Resources/config/internal.xml" /> Again, this works only because we have a limited number of possible namespace prefixes. This patch addresses these problems and some more. First, the registerBundleDirs() method has been removed. It means that you are now free to use any namespace for your bundles. No need to have specific prefixes anymore. You are also free to store them anywhere, in as many directories as you want. You just need to be sure that they are autoloaded correctly. The bundle "name" is now always the short name of the bundle class (like FrameworkBundle or SensioCasBundle). As the best practice is to prefix the bundle name with the vendor name, it's up to the vendor to ensure that each bundle name is unique. I insist that a bundle name must be unique. This was the opposite before as two bundles with the same name was how Symfony2 found inheritance. A new getParent() method has been added to BundleInterface. It returns the bundle name that the bundle overrides (this is optional of course). That way, there is no ordering problem anymore as the inheritance tree is explicitely defined by the bundle themselves. So, with this system, we can easily have an inheritance tree like the following: FooBundle < MyFooBundle < MyCustomFooBundle MyCustomFooBundle returns MyFooBundle for the getParent() method, and MyFooBundle returns FooBundle. If two bundles override the same bundle, an exception is thrown. Based on the bundle name, you can now reference any resource with this notation: @FooBundle/Resources/config/routing.xml @FooBundle/Controller/FooController.php This notation is the input of the Kernel::locateResource() method, which returns the location of the file (and of course it takes into account overloading). So, in the routing, you can now use the following: <import resource="@FrameworkBundle/Resources/config/internal.xml" /> The template loading mechanism also use this method under the hood. As a bonus, all the code that converts from internal notations to file names (controller names: ControllerNameParser, template names: TemplateNameParser, resource paths, ...) is now contained in several well-defined classes. The same goes for the code that look for templates (TemplateLocator), routing files (FileLocator), ... As a side note, it is really easy to also support multiple-inheritance for a bundle (for instance if a bundle returns an array of bundle names it extends). However, this is not implemented in this patch as I'm not sure we want to support that. How to upgrade: * Each bundle must now implement two new mandatory methods: getPath() and getNamespace(), and optionally the getParent() method if the bundle extends another one. Here is a common implementation for these methods: /** * {@inheritdoc} */ public function getParent() { return 'MyFrameworkBundle'; } /** * {@inheritdoc} */ public function getNamespace() { return __NAMESPACE__; } /** * {@inheritdoc} */ public function getPath() { return strtr(__DIR__, '\\', '/'); } * The registerBundleDirs() can be removed from your Kernel class; * If your code relies on getBundleDirs() or the kernel.bundle_dirs parameter, it should be upgraded to use the new interface (see Doctrine commands for many example of such a change); * When referencing a bundle, you must now always use its name (no more \ or / in bundle names) -- this transition was already done for most things before, and now applies to the routing as well; * Imports in routing files must be changed: Before: <import resource="Sensio/CasBundle/Resources/config/internal.xml" /> After: <import resource="@SensioCasBundle/Resources/config/internal.xml" />
2011-01-18 09:23:49 +00:00
// look for orphans
2011-02-06 20:39:06 +00:00
if (count($diff = array_values(array_diff(array_keys($directChildren), array_keys($this->bundles))))) {
throw new \LogicException(sprintf('Bundle "%s" extends bundle "%s", which is not registered.', $directChildren[$diff[0]], $diff[0]));
}
refactored bundle management Before I explain the changes, let's talk about the current state. Before this patch, the registerBundleDirs() method returned an ordered (for resource overloading) list of namespace prefixes and the path to their location. Here are some problems with this approach: * The paths set by this method and the paths configured for the autoloader can be disconnected (leading to unexpected behaviors); * A bundle outside these paths worked, but unexpected behavior can occur; * Choosing a bundle namespace was limited to the registered namespace prefixes, and their number should stay low enough (for performance reasons) -- moreover the current Bundle\ and Application\ top namespaces does not respect the standard rules for namespaces (first segment should be the vendor name); * Developers must understand the concept of "namespace prefixes" to understand the overloading mechanism, which is one more thing to learn, which is Symfony specific; * Each time you want to get a resource that can be overloaded (a template for instance), Symfony would have tried all namespace prefixes one after the other until if finds a matching file. But that can be computed in advance to reduce the overhead. Another topic which was not really well addressed is how you can reference a file/resource from a bundle (and take into account the possibility of overloading). For instance, in the routing, you can import a file from a bundle like this: <import resource="FrameworkBundle/Resources/config/internal.xml" /> Again, this works only because we have a limited number of possible namespace prefixes. This patch addresses these problems and some more. First, the registerBundleDirs() method has been removed. It means that you are now free to use any namespace for your bundles. No need to have specific prefixes anymore. You are also free to store them anywhere, in as many directories as you want. You just need to be sure that they are autoloaded correctly. The bundle "name" is now always the short name of the bundle class (like FrameworkBundle or SensioCasBundle). As the best practice is to prefix the bundle name with the vendor name, it's up to the vendor to ensure that each bundle name is unique. I insist that a bundle name must be unique. This was the opposite before as two bundles with the same name was how Symfony2 found inheritance. A new getParent() method has been added to BundleInterface. It returns the bundle name that the bundle overrides (this is optional of course). That way, there is no ordering problem anymore as the inheritance tree is explicitely defined by the bundle themselves. So, with this system, we can easily have an inheritance tree like the following: FooBundle < MyFooBundle < MyCustomFooBundle MyCustomFooBundle returns MyFooBundle for the getParent() method, and MyFooBundle returns FooBundle. If two bundles override the same bundle, an exception is thrown. Based on the bundle name, you can now reference any resource with this notation: @FooBundle/Resources/config/routing.xml @FooBundle/Controller/FooController.php This notation is the input of the Kernel::locateResource() method, which returns the location of the file (and of course it takes into account overloading). So, in the routing, you can now use the following: <import resource="@FrameworkBundle/Resources/config/internal.xml" /> The template loading mechanism also use this method under the hood. As a bonus, all the code that converts from internal notations to file names (controller names: ControllerNameParser, template names: TemplateNameParser, resource paths, ...) is now contained in several well-defined classes. The same goes for the code that look for templates (TemplateLocator), routing files (FileLocator), ... As a side note, it is really easy to also support multiple-inheritance for a bundle (for instance if a bundle returns an array of bundle names it extends). However, this is not implemented in this patch as I'm not sure we want to support that. How to upgrade: * Each bundle must now implement two new mandatory methods: getPath() and getNamespace(), and optionally the getParent() method if the bundle extends another one. Here is a common implementation for these methods: /** * {@inheritdoc} */ public function getParent() { return 'MyFrameworkBundle'; } /** * {@inheritdoc} */ public function getNamespace() { return __NAMESPACE__; } /** * {@inheritdoc} */ public function getPath() { return strtr(__DIR__, '\\', '/'); } * The registerBundleDirs() can be removed from your Kernel class; * If your code relies on getBundleDirs() or the kernel.bundle_dirs parameter, it should be upgraded to use the new interface (see Doctrine commands for many example of such a change); * When referencing a bundle, you must now always use its name (no more \ or / in bundle names) -- this transition was already done for most things before, and now applies to the routing as well; * Imports in routing files must be changed: Before: <import resource="Sensio/CasBundle/Resources/config/internal.xml" /> After: <import resource="@SensioCasBundle/Resources/config/internal.xml" />
2011-01-18 09:23:49 +00:00
// 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 $bundle) {
$this->bundleMap[$bundle] = $bundleMap;
array_pop($bundleMap);
refactored bundle management Before I explain the changes, let's talk about the current state. Before this patch, the registerBundleDirs() method returned an ordered (for resource overloading) list of namespace prefixes and the path to their location. Here are some problems with this approach: * The paths set by this method and the paths configured for the autoloader can be disconnected (leading to unexpected behaviors); * A bundle outside these paths worked, but unexpected behavior can occur; * Choosing a bundle namespace was limited to the registered namespace prefixes, and their number should stay low enough (for performance reasons) -- moreover the current Bundle\ and Application\ top namespaces does not respect the standard rules for namespaces (first segment should be the vendor name); * Developers must understand the concept of "namespace prefixes" to understand the overloading mechanism, which is one more thing to learn, which is Symfony specific; * Each time you want to get a resource that can be overloaded (a template for instance), Symfony would have tried all namespace prefixes one after the other until if finds a matching file. But that can be computed in advance to reduce the overhead. Another topic which was not really well addressed is how you can reference a file/resource from a bundle (and take into account the possibility of overloading). For instance, in the routing, you can import a file from a bundle like this: <import resource="FrameworkBundle/Resources/config/internal.xml" /> Again, this works only because we have a limited number of possible namespace prefixes. This patch addresses these problems and some more. First, the registerBundleDirs() method has been removed. It means that you are now free to use any namespace for your bundles. No need to have specific prefixes anymore. You are also free to store them anywhere, in as many directories as you want. You just need to be sure that they are autoloaded correctly. The bundle "name" is now always the short name of the bundle class (like FrameworkBundle or SensioCasBundle). As the best practice is to prefix the bundle name with the vendor name, it's up to the vendor to ensure that each bundle name is unique. I insist that a bundle name must be unique. This was the opposite before as two bundles with the same name was how Symfony2 found inheritance. A new getParent() method has been added to BundleInterface. It returns the bundle name that the bundle overrides (this is optional of course). That way, there is no ordering problem anymore as the inheritance tree is explicitely defined by the bundle themselves. So, with this system, we can easily have an inheritance tree like the following: FooBundle < MyFooBundle < MyCustomFooBundle MyCustomFooBundle returns MyFooBundle for the getParent() method, and MyFooBundle returns FooBundle. If two bundles override the same bundle, an exception is thrown. Based on the bundle name, you can now reference any resource with this notation: @FooBundle/Resources/config/routing.xml @FooBundle/Controller/FooController.php This notation is the input of the Kernel::locateResource() method, which returns the location of the file (and of course it takes into account overloading). So, in the routing, you can now use the following: <import resource="@FrameworkBundle/Resources/config/internal.xml" /> The template loading mechanism also use this method under the hood. As a bonus, all the code that converts from internal notations to file names (controller names: ControllerNameParser, template names: TemplateNameParser, resource paths, ...) is now contained in several well-defined classes. The same goes for the code that look for templates (TemplateLocator), routing files (FileLocator), ... As a side note, it is really easy to also support multiple-inheritance for a bundle (for instance if a bundle returns an array of bundle names it extends). However, this is not implemented in this patch as I'm not sure we want to support that. How to upgrade: * Each bundle must now implement two new mandatory methods: getPath() and getNamespace(), and optionally the getParent() method if the bundle extends another one. Here is a common implementation for these methods: /** * {@inheritdoc} */ public function getParent() { return 'MyFrameworkBundle'; } /** * {@inheritdoc} */ public function getNamespace() { return __NAMESPACE__; } /** * {@inheritdoc} */ public function getPath() { return strtr(__DIR__, '\\', '/'); } * The registerBundleDirs() can be removed from your Kernel class; * If your code relies on getBundleDirs() or the kernel.bundle_dirs parameter, it should be upgraded to use the new interface (see Doctrine commands for many example of such a change); * When referencing a bundle, you must now always use its name (no more \ or / in bundle names) -- this transition was already done for most things before, and now applies to the routing as well; * Imports in routing files must be changed: Before: <import resource="Sensio/CasBundle/Resources/config/internal.xml" /> After: <import resource="@SensioCasBundle/Resources/config/internal.xml" />
2011-01-18 09:23:49 +00:00
}
}
refactored bundle management Before I explain the changes, let's talk about the current state. Before this patch, the registerBundleDirs() method returned an ordered (for resource overloading) list of namespace prefixes and the path to their location. Here are some problems with this approach: * The paths set by this method and the paths configured for the autoloader can be disconnected (leading to unexpected behaviors); * A bundle outside these paths worked, but unexpected behavior can occur; * Choosing a bundle namespace was limited to the registered namespace prefixes, and their number should stay low enough (for performance reasons) -- moreover the current Bundle\ and Application\ top namespaces does not respect the standard rules for namespaces (first segment should be the vendor name); * Developers must understand the concept of "namespace prefixes" to understand the overloading mechanism, which is one more thing to learn, which is Symfony specific; * Each time you want to get a resource that can be overloaded (a template for instance), Symfony would have tried all namespace prefixes one after the other until if finds a matching file. But that can be computed in advance to reduce the overhead. Another topic which was not really well addressed is how you can reference a file/resource from a bundle (and take into account the possibility of overloading). For instance, in the routing, you can import a file from a bundle like this: <import resource="FrameworkBundle/Resources/config/internal.xml" /> Again, this works only because we have a limited number of possible namespace prefixes. This patch addresses these problems and some more. First, the registerBundleDirs() method has been removed. It means that you are now free to use any namespace for your bundles. No need to have specific prefixes anymore. You are also free to store them anywhere, in as many directories as you want. You just need to be sure that they are autoloaded correctly. The bundle "name" is now always the short name of the bundle class (like FrameworkBundle or SensioCasBundle). As the best practice is to prefix the bundle name with the vendor name, it's up to the vendor to ensure that each bundle name is unique. I insist that a bundle name must be unique. This was the opposite before as two bundles with the same name was how Symfony2 found inheritance. A new getParent() method has been added to BundleInterface. It returns the bundle name that the bundle overrides (this is optional of course). That way, there is no ordering problem anymore as the inheritance tree is explicitely defined by the bundle themselves. So, with this system, we can easily have an inheritance tree like the following: FooBundle < MyFooBundle < MyCustomFooBundle MyCustomFooBundle returns MyFooBundle for the getParent() method, and MyFooBundle returns FooBundle. If two bundles override the same bundle, an exception is thrown. Based on the bundle name, you can now reference any resource with this notation: @FooBundle/Resources/config/routing.xml @FooBundle/Controller/FooController.php This notation is the input of the Kernel::locateResource() method, which returns the location of the file (and of course it takes into account overloading). So, in the routing, you can now use the following: <import resource="@FrameworkBundle/Resources/config/internal.xml" /> The template loading mechanism also use this method under the hood. As a bonus, all the code that converts from internal notations to file names (controller names: ControllerNameParser, template names: TemplateNameParser, resource paths, ...) is now contained in several well-defined classes. The same goes for the code that look for templates (TemplateLocator), routing files (FileLocator), ... As a side note, it is really easy to also support multiple-inheritance for a bundle (for instance if a bundle returns an array of bundle names it extends). However, this is not implemented in this patch as I'm not sure we want to support that. How to upgrade: * Each bundle must now implement two new mandatory methods: getPath() and getNamespace(), and optionally the getParent() method if the bundle extends another one. Here is a common implementation for these methods: /** * {@inheritdoc} */ public function getParent() { return 'MyFrameworkBundle'; } /** * {@inheritdoc} */ public function getNamespace() { return __NAMESPACE__; } /** * {@inheritdoc} */ public function getPath() { return strtr(__DIR__, '\\', '/'); } * The registerBundleDirs() can be removed from your Kernel class; * If your code relies on getBundleDirs() or the kernel.bundle_dirs parameter, it should be upgraded to use the new interface (see Doctrine commands for many example of such a change); * When referencing a bundle, you must now always use its name (no more \ or / in bundle names) -- this transition was already done for most things before, and now applies to the routing as well; * Imports in routing files must be changed: Before: <import resource="Sensio/CasBundle/Resources/config/internal.xml" /> After: <import resource="@SensioCasBundle/Resources/config/internal.xml" />
2011-01-18 09:23:49 +00:00
}
/**
* Gets the container class.
*
* @return string The container class
*/
protected function getContainerClass()
{
return $this->name.ucfirst($this->environment).($this->debug ? 'Debug' : '').'ProjectContainer';
}
/**
* Gets the container's base class.
*
* All names except Container must be fully qualified.
*
* @return string
*/
protected function getContainerBaseClass()
{
return 'Container';
}
/**
2011-03-16 20:35:00 +00:00
* Initializes the service container.
*
2011-03-16 20:35:00 +00:00
* The cached version of the service container is used when fresh, otherwise the
* container is built.
*/
protected function initializeContainer()
{
$class = $this->getContainerClass();
$cache = new ConfigCache($this->getCacheDir().'/'.$class.'.php', $this->debug);
2011-03-18 10:17:56 +00:00
$fresh = true;
if (!$cache->isFresh()) {
$container = $this->buildContainer();
$this->dumpContainer($cache, $container, $class, $this->getContainerBaseClass());
2011-03-18 10:17:56 +00:00
$fresh = false;
}
require_once $cache;
2011-01-20 10:38:17 +00:00
$this->container = new $class();
$this->container->set('kernel', $this);
if (!$fresh && $this->container->has('cache_warmer')) {
$this->container->get('cache_warmer')->warmUp($this->container->getParameter('kernel.cache_dir'));
}
}
/**
2011-03-16 20:35:00 +00:00
* Returns the kernel parameters.
*
* @return array An array of kernel parameters
*/
2011-01-25 16:07:37 +00:00
protected function getKernelParameters()
{
$bundles = array();
refactored bundle management Before I explain the changes, let's talk about the current state. Before this patch, the registerBundleDirs() method returned an ordered (for resource overloading) list of namespace prefixes and the path to their location. Here are some problems with this approach: * The paths set by this method and the paths configured for the autoloader can be disconnected (leading to unexpected behaviors); * A bundle outside these paths worked, but unexpected behavior can occur; * Choosing a bundle namespace was limited to the registered namespace prefixes, and their number should stay low enough (for performance reasons) -- moreover the current Bundle\ and Application\ top namespaces does not respect the standard rules for namespaces (first segment should be the vendor name); * Developers must understand the concept of "namespace prefixes" to understand the overloading mechanism, which is one more thing to learn, which is Symfony specific; * Each time you want to get a resource that can be overloaded (a template for instance), Symfony would have tried all namespace prefixes one after the other until if finds a matching file. But that can be computed in advance to reduce the overhead. Another topic which was not really well addressed is how you can reference a file/resource from a bundle (and take into account the possibility of overloading). For instance, in the routing, you can import a file from a bundle like this: <import resource="FrameworkBundle/Resources/config/internal.xml" /> Again, this works only because we have a limited number of possible namespace prefixes. This patch addresses these problems and some more. First, the registerBundleDirs() method has been removed. It means that you are now free to use any namespace for your bundles. No need to have specific prefixes anymore. You are also free to store them anywhere, in as many directories as you want. You just need to be sure that they are autoloaded correctly. The bundle "name" is now always the short name of the bundle class (like FrameworkBundle or SensioCasBundle). As the best practice is to prefix the bundle name with the vendor name, it's up to the vendor to ensure that each bundle name is unique. I insist that a bundle name must be unique. This was the opposite before as two bundles with the same name was how Symfony2 found inheritance. A new getParent() method has been added to BundleInterface. It returns the bundle name that the bundle overrides (this is optional of course). That way, there is no ordering problem anymore as the inheritance tree is explicitely defined by the bundle themselves. So, with this system, we can easily have an inheritance tree like the following: FooBundle < MyFooBundle < MyCustomFooBundle MyCustomFooBundle returns MyFooBundle for the getParent() method, and MyFooBundle returns FooBundle. If two bundles override the same bundle, an exception is thrown. Based on the bundle name, you can now reference any resource with this notation: @FooBundle/Resources/config/routing.xml @FooBundle/Controller/FooController.php This notation is the input of the Kernel::locateResource() method, which returns the location of the file (and of course it takes into account overloading). So, in the routing, you can now use the following: <import resource="@FrameworkBundle/Resources/config/internal.xml" /> The template loading mechanism also use this method under the hood. As a bonus, all the code that converts from internal notations to file names (controller names: ControllerNameParser, template names: TemplateNameParser, resource paths, ...) is now contained in several well-defined classes. The same goes for the code that look for templates (TemplateLocator), routing files (FileLocator), ... As a side note, it is really easy to also support multiple-inheritance for a bundle (for instance if a bundle returns an array of bundle names it extends). However, this is not implemented in this patch as I'm not sure we want to support that. How to upgrade: * Each bundle must now implement two new mandatory methods: getPath() and getNamespace(), and optionally the getParent() method if the bundle extends another one. Here is a common implementation for these methods: /** * {@inheritdoc} */ public function getParent() { return 'MyFrameworkBundle'; } /** * {@inheritdoc} */ public function getNamespace() { return __NAMESPACE__; } /** * {@inheritdoc} */ public function getPath() { return strtr(__DIR__, '\\', '/'); } * The registerBundleDirs() can be removed from your Kernel class; * If your code relies on getBundleDirs() or the kernel.bundle_dirs parameter, it should be upgraded to use the new interface (see Doctrine commands for many example of such a change); * When referencing a bundle, you must now always use its name (no more \ or / in bundle names) -- this transition was already done for most things before, and now applies to the routing as well; * Imports in routing files must be changed: Before: <import resource="Sensio/CasBundle/Resources/config/internal.xml" /> After: <import resource="@SensioCasBundle/Resources/config/internal.xml" />
2011-01-18 09:23:49 +00:00
foreach ($this->bundles as $name => $bundle) {
$bundles[$name] = get_class($bundle);
}
return array_merge(
array(
'kernel.root_dir' => $this->rootDir,
'kernel.environment' => $this->environment,
'kernel.debug' => $this->debug,
'kernel.name' => $this->name,
'kernel.cache_dir' => $this->getCacheDir(),
'kernel.logs_dir' => $this->getLogDir(),
'kernel.bundles' => $bundles,
'kernel.charset' => 'UTF-8',
'kernel.container_class' => $this->getContainerClass(),
),
$this->getEnvParameters()
);
}
/**
2011-03-16 20:35:00 +00:00
* Gets the environment parameters.
*
2011-03-16 20:35:00 +00:00
* Only the parameters starting with "SYMFONY__" are considered.
*
* @return array An array of parameters
*/
protected function getEnvParameters()
{
$parameters = array();
foreach ($_SERVER as $key => $value) {
if (0 === strpos($key, 'SYMFONY__')) {
$parameters[strtolower(str_replace('__', '.', substr($key, 9)))] = $value;
}
}
return $parameters;
}
/**
2011-03-16 20:35:00 +00:00
* Builds the service container.
*
2011-03-16 20:35:00 +00:00
* @return ContainerBuilder The compiled service container
*/
protected function buildContainer()
{
foreach (array('cache' => $this->getCacheDir(), 'logs' => $this->getLogDir()) as $name => $dir) {
if (!is_dir($dir)) {
if (false === @mkdir($dir, 0777, true)) {
throw new \RuntimeException(sprintf("Unable to create the %s directory (%s)\n", $name, $dir));
}
} elseif (!is_writable($dir)) {
throw new \RuntimeException(sprintf("Unable to write in the %s directory (%s)\n", $name, $dir));
}
}
$container = new ContainerBuilder(new ParameterBag($this->getKernelParameters()));
$extensions = array();
foreach ($this->bundles as $bundle) {
$bundle->build($container);
if ($extension = $bundle->getContainerExtension()) {
$container->registerExtension($extension);
$extensions[] = $extension->getAlias();
}
if ($this->debug) {
$container->addObjectResource($bundle);
}
}
$container->addObjectResource($this);
// ensure these extensions are implicitly loaded
$container->getCompilerPassConfig()->setMergePass(new MergeExtensionConfigurationPass($extensions));
if (null !== $cont = $this->registerContainerConfiguration($this->getContainerLoader($container))) {
$container->merge($cont);
}
$container->addCompilerPass(new AddClassesToCachePass($this));
$container->compile();
return $container;
}
/**
2011-03-16 20:35:00 +00:00
* Dumps the service container to PHP code in the cache.
*
2011-04-23 16:05:44 +01:00
* @param ConfigCache $cache The config cache
* @param ContainerBuilder $container The service container
* @param string $class The name of the class to generate
* @param string $baseClass The name of the container's base class
*/
protected function dumpContainer(ConfigCache $cache, ContainerBuilder $container, $class, $baseClass)
{
// cache the container
$dumper = new PhpDumper($container);
$content = $dumper->dump(array('class' => $class, 'base_class' => $baseClass));
if (!$this->debug) {
$content = self::stripComments($content);
}
$cache->write($content, $container->getResources());
}
/**
2011-03-16 20:35:00 +00:00
* Returns a loader for the container.
*
* @param ContainerInterface $container The service container
*
* @return DelegatingLoader The loader
*/
protected function getContainerLoader(ContainerInterface $container)
{
$locator = new FileLocator($this);
$resolver = new LoaderResolver(array(
new XmlFileLoader($container, $locator),
new YamlFileLoader($container, $locator),
new IniFileLoader($container, $locator),
new PhpFileLoader($container, $locator),
new ClosureLoader($container),
));
return new DelegatingLoader($resolver);
}
/**
* Removes comments from a PHP source string.
*
* We don't use the PHP php_strip_whitespace() function
* as we want the content to be readable and well-formatted.
*
* @param string $source A PHP string
*
* @return string The PHP string with the comments removed
*/
2012-07-09 13:38:28 +01:00
public static function stripComments($source)
{
if (!function_exists('token_get_all')) {
return $source;
}
$output = '';
foreach (token_get_all($source) as $token) {
if (is_string($token)) {
$output .= $token;
} elseif (!in_array($token[0], array(T_COMMENT, T_DOC_COMMENT))) {
$output .= $token[1];
}
}
// replace multiple new lines with a single newline
$output = preg_replace(array('/\s+$/Sm', '/\n+/S'), "\n", $output);
return $output;
}
public function serialize()
{
return serialize(array($this->environment, $this->debug));
}
public function unserialize($data)
{
list($environment, $debug) = unserialize($data);
$this->__construct($environment, $debug);
}
}