Skip to content

Commit ee5bd54

Browse files
committed
Adding a MicroKernel that has a few special powers:
1) Services can be configured 2) Bundles can be registered using a method that also allows them to be immediately configured
1 parent 7b358a1 commit ee5bd54

File tree

4 files changed

+435
-0
lines changed

4 files changed

+435
-0
lines changed
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Bundle\FrameworkBundle\Kernel;
13+
14+
use Symfony\Component\Config\Loader\LoaderInterface;
15+
use Symfony\Component\Config\Loader\LoaderResolverInterface;
16+
use Symfony\Component\DependencyInjection\ContainerBuilder;
17+
18+
/**
19+
* Configuration loader that holds the ContainerBuilder inside.
20+
*
21+
* It can be useful to pass this to KernelInterface::registerContainerConfiguration()
22+
* instead of a normal Loader if that method will need the ContainerBuilder.
23+
*
24+
* @author Ryan Weaver <ryan@knpuniversity.com>
25+
*/
26+
class ContainerBuilderAwareLoader implements LoaderInterface
27+
{
28+
/**
29+
* @var ContainerBuilder
30+
*/
31+
private $containerBuilder;
32+
33+
/**
34+
* @var LoaderInterface
35+
*/
36+
private $resourceLoader;
37+
38+
public function __construct(ContainerBuilder $builder, LoaderInterface $resourceLoader)
39+
{
40+
$this->containerBuilder = $builder;
41+
$this->resourceLoader = $resourceLoader;
42+
}
43+
44+
public function getContainerBuilder()
45+
{
46+
return $this->containerBuilder;
47+
}
48+
49+
public function getResourceLoader()
50+
{
51+
return $this->resourceLoader;
52+
}
53+
54+
/**
55+
* @see LoaderInterface
56+
*/
57+
public function load($resource, $type = null)
58+
{
59+
return $this->resourceLoader->load($resource, $type);
60+
}
61+
62+
/**
63+
* @see LoaderInterface
64+
*/
65+
public function supports($resource, $type = null)
66+
{
67+
return $this->resourceLoader->supports($resource, $type);
68+
}
69+
70+
/**
71+
* @see LoaderInterface
72+
*/
73+
public function getResolver()
74+
{
75+
return $this->resourceLoader->getResolver();
76+
}
77+
78+
/**
79+
* @see LoaderInterface
80+
*/
81+
public function setResolver(LoaderResolverInterface $resolver)
82+
{
83+
return $this->resourceLoader->setResolver($resolver);
84+
}
85+
}
Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Bundle\FrameworkBundle\Kernel;
13+
14+
use Symfony\Component\Config\Loader\Loader;
15+
use Symfony\Component\Config\Loader\LoaderInterface;
16+
use Symfony\Component\DependencyInjection\ContainerBuilder;
17+
use Symfony\Component\DependencyInjection\ContainerInterface;
18+
use Symfony\Component\HttpKernel\Bundle\BundleInterface;
19+
use Symfony\Component\HttpKernel\Kernel;
20+
21+
/**
22+
* A Kernel that allows you to configure services.
23+
*
24+
* @author Ryan Weaver <ryan@knpuniversity.com>
25+
*/
26+
abstract class MicroKernel extends Kernel
27+
{
28+
private $bundlesRegistered = false;
29+
30+
/**
31+
* @var BundleInterface[]
32+
*/
33+
private $bundlesToRegister = array();
34+
35+
/**
36+
* An associative array of bundle names and their configuration arrays.
37+
*
38+
* @var array
39+
*/
40+
private $bundleConfiguration = array();
41+
42+
/**
43+
* Call $this->addBundle() to add (and optionally configure) your bundles.
44+
*/
45+
abstract protected function configureBundles();
46+
47+
/**
48+
* Add any service definitions to your container.
49+
*
50+
* @param ContainerBuilder $c
51+
* @param LoaderInterface $loader
52+
*/
53+
abstract protected function configureServices(ContainerBuilder $c, LoaderInterface $loader);
54+
55+
/**
56+
* Adds a bundle to the kernel, which can optionally be configured.
57+
*
58+
* @param BundleInterface $bundle
59+
* @param array $configuration Configuration for this bundle
60+
*
61+
* @return $this
62+
*/
63+
protected function addBundle(BundleInterface $bundle, $configuration = array())
64+
{
65+
if ($this->bundlesRegistered) {
66+
throw new \LogicException('addBundle() cannot be called after configureBundles() is called!');
67+
}
68+
69+
$this->bundlesToRegister[$bundle->getName()] = $bundle;
70+
71+
if ($configuration) {
72+
$this->bundleConfiguration[$bundle->getName()] = $configuration;
73+
}
74+
75+
return $this;
76+
}
77+
78+
/**
79+
* {@inheritdoc}
80+
*/
81+
public function registerBundles()
82+
{
83+
$this->configureBundles();
84+
$this->bundlesRegistered = true;
85+
86+
return array_values($this->bundlesToRegister);
87+
}
88+
89+
/**
90+
* Applies the bundle configuration and calls configureServices() for continued building.
91+
*
92+
* @param LoaderInterface $loader
93+
*/
94+
public function registerContainerConfiguration(LoaderInterface $loader)
95+
{
96+
if (!$loader instanceof ContainerBuilderAwareLoader) {
97+
throw new \LogicException('registerContainerConfiguration requires the LoaderInterface to be a ContainerBuilderAwareLoader.');
98+
}
99+
100+
/* @var ContainerBuilderAwareLoader $loader */
101+
$builder = $loader->getContainerBuilder();
102+
$loader = $loader->getResourceLoader();
103+
104+
// load the bundle configuration
105+
foreach ($this->bundleConfiguration as $bundleName => $configuration) {
106+
$extension = $this->bundlesToRegister[$bundleName]->getContainerExtension();
107+
if (!$extension) {
108+
throw new \LogicException('Bundle "%s" does not have an extension that can be configured.');
109+
}
110+
111+
$alias = $extension->getAlias();
112+
$builder->loadFromExtension($alias, $configuration);
113+
}
114+
115+
// allow the kernel to configure its services
116+
$this->configureServices(
117+
$builder,
118+
$loader
119+
);
120+
}
121+
122+
/**
123+
* Returns a loader with the ContainerBuilder embedded inside of it.
124+
*
125+
* @param ContainerInterface $container
126+
*
127+
* @return ContainerBuilderAwareLoader
128+
*/
129+
protected function getContainerLoader(ContainerInterface $container)
130+
{
131+
if (!$container instanceof ContainerBuilder) {
132+
throw new \LogicException('Only ContainerBuilder instances are supported.');
133+
}
134+
135+
$loader = parent::getContainerLoader($container);
136+
137+
return new ContainerBuilderAwareLoader($container, $loader);
138+
}
139+
}
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Bundle\FrameworkBundle\Tests\Fixtures\Kernel;
13+
14+
use Symfony\Bundle\FrameworkBundle\Kernel\MicroKernel;
15+
use Symfony\Component\Config\Loader\LoaderInterface;
16+
use Symfony\Component\DependencyInjection\ContainerBuilder;
17+
use Symfony\Component\DependencyInjection\ContainerInterface;
18+
use Symfony\Component\HttpKernel\Bundle\BundleInterface;
19+
20+
class MicroKernelForTest extends MicroKernel
21+
{
22+
private $configureBundlesCalled = false;
23+
24+
private $configureServicesCalled = false;
25+
26+
public function addBundleExternally(BundleInterface $bundle, $configuration = array())
27+
{
28+
$this->addBundle($bundle, $configuration);
29+
}
30+
31+
public function configureBundleExternally($bundleName, array $configuration)
32+
{
33+
$this->configureBundle($bundleName, $configuration);
34+
}
35+
36+
public function getContainerLoaderExternally(ContainerInterface $container)
37+
{
38+
return $this->getContainerLoader($container);
39+
}
40+
41+
protected function configureBundles()
42+
{
43+
$this->configureBundlesCalled = true;
44+
}
45+
46+
protected function configureServices(ContainerBuilder $c, LoaderInterface $loader)
47+
{
48+
$this->configureServicesCalled = true;
49+
}
50+
51+
public function wasConfigureBundlesCalled()
52+
{
53+
return $this->configureBundlesCalled;
54+
}
55+
56+
public function wasConfigureServicesCalled()
57+
{
58+
return $this->configureServicesCalled;
59+
}
60+
}

0 commit comments

Comments
 (0)