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

559 lines
16 KiB
PHP
Raw Normal View History

<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien.potencier@symfony-project.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\DelegatingLoader;
use Symfony\Component\DependencyInjection\Loader\LoaderResolver;
use Symfony\Component\DependencyInjection\Loader\LoaderInterface;
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;
/**
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.potencier@symfony-project.org>
*/
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;
const VERSION = '2.0.0-DEV';
/**
* Constructor.
*
* @param string $environment The environment
* @param Boolean $debug Whether to enable debugging or not
*/
public function __construct($environment, $debug)
{
$this->environment = $environment;
$this->debug = (Boolean) $debug;
$this->booted = false;
$this->rootDir = realpath($this->registerRootDir());
2011-01-25 16:07:37 +00:00
$this->name = preg_replace('/[^a-zA-Z0-9_]+/', '', basename($this->rootDir));
if ($this->debug) {
ini_set('display_errors', 1);
error_reporting(-1);
$this->startTime = microtime(true);
} 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.
*/
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->bundles 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.
*/
public function shutdown()
{
$this->booted = false;
foreach ($this->bundles as $bundle) {
2010-08-10 15:59:12 +01:00
$bundle->shutdown();
$bundle->setContainer(null);
}
$this->container = null;
}
/**
* {@inheritdoc}
*/
public function handle(Request $request, $type = HttpKernelInterface::MASTER_REQUEST, $catch = true)
{
if (false === $this->booted) {
$this->boot();
}
return $this->container->get('http_kernel')->handle($request, $type, $catch);
}
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
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
*/
public function isClassInActiveBundle($class)
{
foreach ($this->bundles as $bundle) {
$bundleClass = get_class($bundle);
if (0 === strpos($class, substr($bundleClass, 0, strrpos($bundleClass, '\\')))) {
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
/**
* Returns a bundle by its name.
*
* @param string $name Bundle name
* @param Boolean $first Whether to return the first bundle or all bundles matching this name
*
* @return BundleInterface A BundleInterface instance
*
* @throws \InvalidArgumentException when the bundle is not enabled
*/
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.', $name));
}
if (true === $first) {
return $this->bundleMap[$name][0];
} elseif (false === $first) {
return $this->bundleMap[$name];
}
}
/**
* 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
*
* 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,
* this method will look for a file named:
*
* $dir/BundleName/path/without/Resources
*
* @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 characters
*/
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));
}
$name = substr($name, 1);
list($bundle, $path) = explode('/', $name, 2);
$isResource = 0 === strpos($path, 'Resources');
$files = array();
if (true === $isResource && null !== $dir && file_exists($file = $dir.'/'.$bundle.'/'.substr($path, 10))) {
if ($first) {
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 $file;
}
$files[] = $file;
}
foreach ($this->getBundle($bundle, false) as $bundle) {
if (file_exists($file = $bundle->getPath().'/'.$path)) {
if ($first) {
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;
}
}
if ($files) {
return $files;
}
throw new \InvalidArgumentException(sprintf('Unable to find file "@%s".', $name));
}
public function getName()
{
return $this->name;
}
2011-01-17 19:41:55 +00:00
/**
* Gets the environment.
*
* @return string The current environment
*/
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
*/
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
*/
public function getRootDir()
{
return $this->rootDir;
}
2011-01-17 19:41:55 +00:00
/**
* Gets the current container.
*
* @return ContainerInterface A ContainerInterface instance
*/
public function getContainer()
{
return $this->container;
}
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
*/
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
*/
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
*/
public function getLogDir()
{
return $this->rootDir.'/logs';
}
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();
2011-01-23 13:10:12 +00:00
$this->bundleMap = 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();
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 (!isset($this->bundleMap[$name])) {
$this->bundleMap[$name] = array();
}
$this->bundleMap[$name][] = $bundle;
}
// inheritance
$extended = array();
foreach ($this->bundles as $name => $bundle) {
$parent = $bundle;
$first = true;
while ($parentName = $parent->getParent()) {
if (!isset($this->bundles[$parentName])) {
throw new \LogicException(sprintf('Bundle "%s" extends bundle "%s", which is not registered.', $name, $parentName));
}
if ($first && isset($extended[$parentName])) {
throw new \LogicException(sprintf('Bundle "%s" is directly extended by two bundles "%s" and "%s".', $parentName, $name, $extended[$parentName]));
}
$first = false;
$parent = $this->bundles[$parentName];
$extended[$parentName] = $name;
array_unshift($this->bundleMap[$parentName], $bundle);
}
}
}
protected function initializeContainer()
{
2011-01-25 16:07:37 +00:00
$class = $this->name.ucfirst($this->environment).($this->debug ? 'Debug' : '').'ProjectContainer';
$location = $this->getCacheDir().'/'.$class;
$reload = $this->debug ? $this->needsReload($class, $location) : false;
$fresh = false;
if ($reload || !file_exists($location.'.php')) {
$container = $this->buildContainer();
$this->dumpContainer($container, $class, $location.'.php');
$fresh = true;
}
require_once $location.'.php';
2011-01-20 10:38:17 +00:00
$this->container = new $class();
$this->container->set('kernel', $this);
if ($fresh && 'cli' !== php_sapi_name()) {
$this->container->get('cache_warmer')->warmUp($this->container->getParameter('kernel.cache_dir'));
}
}
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(
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
'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',
),
$this->getEnvParameters()
);
}
protected function getEnvParameters()
{
$parameters = array();
foreach ($_SERVER as $key => $value) {
if ('SYMFONY__' === substr($key, 0, 9)) {
$parameters[strtolower(str_replace('__', '.', substr($key, 9)))] = $value;
}
}
return $parameters;
}
protected function needsReload($class, $location)
{
if (!file_exists($location.'.meta') || !file_exists($location.'.php')) {
return true;
}
$meta = unserialize(file_get_contents($location.'.meta'));
$time = filemtime($location.'.php');
foreach ($meta as $resource) {
if (!$resource->isUptodate($time)) {
return true;
}
}
return false;
}
protected function buildContainer()
{
$parameterBag = new ParameterBag($this->getKernelParameters());
$container = new ContainerBuilder($parameterBag);
foreach ($this->bundles as $bundle) {
$bundle->registerExtensions($container);
if ($this->debug) {
$container->addObjectResource($bundle);
}
}
if (null !== $cont = $this->registerContainerConfiguration($this->getContainerLoader($container))) {
$container->merge($cont);
}
$container->compile();
return $container;
}
protected function dumpContainer(ContainerBuilder $container, $class, $file)
{
foreach (array('cache', 'logs') as $name) {
$dir = $container->getParameter(sprintf('kernel.%s_dir', $name));
if (!is_dir($dir)) {
if (false === @mkdir($dir, 0777, true)) {
die(sprintf('Unable to create the %s directory (%s)', $name, dirname($dir)));
}
} elseif (!is_writable($dir)) {
die(sprintf('Unable to write in the %s directory (%s)', $name, $dir));
}
}
// cache the container
$dumper = new PhpDumper($container);
$content = $dumper->dump(array('class' => $class));
if (!$this->debug) {
$content = self::stripComments($content);
}
$this->writeCacheFile($file, $content);
if ($this->debug) {
$container->addObjectResource($this);
// save the resources
$this->writeCacheFile($this->getCacheDir().'/'.$class.'.meta', serialize($container->getResources()));
}
}
protected function getContainerLoader(ContainerInterface $container)
{
$resolver = new LoaderResolver(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
new XmlFileLoader($container),
new YamlFileLoader($container),
new IniFileLoader($container),
new PhpFileLoader($container),
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
*/
static public 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;
}
protected function writeCacheFile($file, $content)
{
$tmpFile = tempnam(dirname($file), basename($file));
2010-08-12 20:58:19 +01:00
if (false !== @file_put_contents($tmpFile, $content) && @rename($tmpFile, $file)) {
chmod($file, 0644);
2010-08-12 20:58:19 +01:00
return;
}
2010-08-12 20:58:19 +01:00
throw new \RuntimeException(sprintf('Failed to write cache file "%s".', $file));
}
public function serialize()
{
return serialize(array($this->environment, $this->debug));
}
public function unserialize($data)
{
list($environment, $debug) = unserialize($data);
$this->__construct($environment, $debug);
}
}