diff --git a/src/Symfony/Bridge/Twig/Tests/Extension/HttpKernelExtensionTest.php b/src/Symfony/Bridge/Twig/Tests/Extension/HttpKernelExtensionTest.php
index c0dc42d2f35f0..8e5e4d1d4756b 100644
--- a/src/Symfony/Bridge/Twig/Tests/Extension/HttpKernelExtensionTest.php
+++ b/src/Symfony/Bridge/Twig/Tests/Extension/HttpKernelExtensionTest.php
@@ -49,16 +49,8 @@ protected function getFragmentHandler($return)
$strategy->expects($this->once())->method('getName')->will($this->returnValue('inline'));
$strategy->expects($this->once())->method('render')->will($return);
- // simulate a master request
- $event = $this->getMockBuilder('Symfony\Component\HttpKernel\Event\GetResponseEvent')->disableOriginalConstructor()->getMock();
- $event
- ->expects($this->once())
- ->method('getRequest')
- ->will($this->returnValue(Request::create('/')))
- ;
-
$renderer = new FragmentHandler(array($strategy));
- $renderer->onKernelRequest($event);
+ $renderer->setRequest(Request::create('/'));
return $renderer;
}
diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/fragment_renderer.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/fragment_renderer.xml
index cbe3db3257b6e..662f042adeeac 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/fragment_renderer.xml
+++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/fragment_renderer.xml
@@ -14,9 +14,9 @@
-
%kernel.debug%
+
diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/routing.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/routing.xml
index 6d6671b7ae33f..9e21db4519151 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/routing.xml
+++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/routing.xml
@@ -94,6 +94,7 @@
+
diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/services.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/services.xml
index fbddc0e07fbfd..c1c28c0fa0939 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/services.xml
+++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/services.xml
@@ -40,7 +40,7 @@
This service definition only defines the scope of the request.
It is used to check references scope.
-->
-
+
diff --git a/src/Symfony/Bundle/FrameworkBundle/Resources/config/web.xml b/src/Symfony/Bundle/FrameworkBundle/Resources/config/web.xml
index d34ecdf3c3727..177821a5afb24 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Resources/config/web.xml
+++ b/src/Symfony/Bundle/FrameworkBundle/Resources/config/web.xml
@@ -38,6 +38,7 @@
%kernel.default_locale%
+
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/TestBundle/Controller/SubRequestController.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/TestBundle/Controller/SubRequestController.php
new file mode 100644
index 0000000000000..14d002642ba81
--- /dev/null
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/TestBundle/Controller/SubRequestController.php
@@ -0,0 +1,66 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Bundle\FrameworkBundle\Tests\Functional\Bundle\TestBundle\Controller;
+
+use Symfony\Component\HttpFoundation\Request;
+use Symfony\Component\HttpFoundation\Response;
+use Symfony\Component\DependencyInjection\ContainerAware;
+use Symfony\Component\HttpKernel\Controller\ControllerReference;
+
+class SubRequestController extends ContainerAware
+{
+ public function indexAction()
+ {
+ $handler = $this->container->get('fragment.handler');
+
+ $errorUrl = $this->generateUrl('subrequest_fragment_error', array('_locale' => 'fr', '_format' => 'json'));
+ $altUrl = $this->generateUrl('subrequest_fragment', array('_locale' => 'fr', '_format' => 'json'));
+
+ // simulates a failure during the rendering of a fragment...
+ // should render fr/json
+ $content = $handler->render($errorUrl, 'inline', array('alt' => $altUrl));
+
+ // ...to check that the FragmentListener still references the right Request
+ // when rendering another fragment after the error occured
+ // should render en/html instead of fr/json
+ $content .= $handler->render(new ControllerReference('TestBundle:SubRequest:fragment'));
+
+ // forces the LocaleListener to set fr for the locale...
+ // should render fr/json
+ $content .= $handler->render($altUrl);
+
+ // ...and check that after the rendering, the original Request is back
+ // and en is used as a locale
+ // should use en/html instead of fr/json
+ $content .= '--'.$this->generateUrl('subrequest_fragment');
+
+ // The RouterListener is also tested as if it does not keep the right
+ // Request in the context, a 301 would be generated
+
+ return new Response($content);
+ }
+
+ public function fragmentAction(Request $request)
+ {
+ return new Response('--'.$request->getLocale().'/'.$request->getRequestFormat());
+ }
+
+ public function fragmentErrorAction()
+ {
+ throw new \RuntimeException('error');
+ }
+
+ protected function generateUrl($name, $arguments = array())
+ {
+ return $this->container->get('router')->generate($name, $arguments);
+ }
+}
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/TestBundle/Resources/config/routing.yml b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/TestBundle/Resources/config/routing.yml
index d9b380ef8dbd1..6a9f5a8f8be47 100644
--- a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/TestBundle/Resources/config/routing.yml
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/Bundle/TestBundle/Resources/config/routing.yml
@@ -21,3 +21,18 @@ session_showflash:
profiler:
path: /profiler
defaults: { _controller: TestBundle:Profiler:index }
+
+subrequest_index:
+ path: /subrequest/{_locale}.{_format}
+ defaults: { _controller: TestBundle:SubRequest:index, _format: "html" }
+ schemes: [https]
+
+subrequest_fragment_error:
+ path: /subrequest/fragment/error/{_locale}.{_format}
+ defaults: { _controller: TestBundle:SubRequest:fragmentError, _format: "html" }
+ schemes: [http]
+
+subrequest_fragment:
+ path: /subrequest/fragment/{_locale}.{_format}
+ defaults: { _controller: TestBundle:SubRequest:fragment, _format: "html" }
+ schemes: [http]
diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/SubRequestsTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/SubRequestsTest.php
new file mode 100644
index 0000000000000..2676653b1ef6d
--- /dev/null
+++ b/src/Symfony/Bundle/FrameworkBundle/Tests/Functional/SubRequestsTest.php
@@ -0,0 +1,26 @@
+
+ *
+ * For the full copyright and license information, please view the LICENSE
+ * file that was distributed with this source code.
+ */
+
+namespace Symfony\Bundle\FrameworkBundle\Tests\Functional;
+
+/**
+ * @group functional
+ */
+class SubRequestsTest extends WebTestCase
+{
+ public function testStateAfterSubRequest()
+ {
+ $client = $this->createClient(array('test_case' => 'Session', 'root_config' => 'config.yml'));
+ $client->request('GET', 'https://localhost/subrequest/en');
+
+ $this->assertEquals('--fr/json--en/html--fr/json--http://localhost/subrequest/fragment/en', $client->getResponse()->getContent());
+ }
+}
diff --git a/src/Symfony/Component/DependencyInjection/Compiler/ResolveInvalidReferencesPass.php b/src/Symfony/Component/DependencyInjection/Compiler/ResolveInvalidReferencesPass.php
index 6fad9a2841651..93d5806036bde 100644
--- a/src/Symfony/Component/DependencyInjection/Compiler/ResolveInvalidReferencesPass.php
+++ b/src/Symfony/Component/DependencyInjection/Compiler/ResolveInvalidReferencesPass.php
@@ -88,9 +88,7 @@ private function processArguments(array $arguments, $inMethodCall = false)
$exists = $this->container->has($id);
// resolve invalid behavior
- if ($exists && ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE !== $invalidBehavior) {
- $arguments[$k] = new Reference($id, ContainerInterface::EXCEPTION_ON_INVALID_REFERENCE, $argument->isStrict());
- } elseif (!$exists && ContainerInterface::NULL_ON_INVALID_REFERENCE === $invalidBehavior) {
+ if (!$exists && ContainerInterface::NULL_ON_INVALID_REFERENCE === $invalidBehavior) {
$arguments[$k] = null;
} elseif (!$exists && ContainerInterface::IGNORE_ON_INVALID_REFERENCE === $invalidBehavior) {
if ($inMethodCall) {
diff --git a/src/Symfony/Component/DependencyInjection/Container.php b/src/Symfony/Component/DependencyInjection/Container.php
index 8a2c1b3a1ed91..be72e8fc686a5 100644
--- a/src/Symfony/Component/DependencyInjection/Container.php
+++ b/src/Symfony/Component/DependencyInjection/Container.php
@@ -11,6 +11,7 @@
namespace Symfony\Component\DependencyInjection;
+use Symfony\Component\DependencyInjection\Exception\InactiveScopeException;
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException;
@@ -206,6 +207,10 @@ public function set($id, $service, $scope = self::SCOPE_CONTAINER)
}
$this->services[$id] = $service;
+
+ if (method_exists($this, $method = 'synchronize'.strtr($id, array('_' => '', '.' => '_')).'Service')) {
+ $this->$method();
+ }
}
/**
@@ -221,7 +226,7 @@ public function has($id)
{
$id = strtolower($id);
- return isset($this->services[$id]) || method_exists($this, 'get'.strtr($id, array('_' => '', '.' => '_')).'Service');
+ return array_key_exists($id, $this->services) || method_exists($this, 'get'.strtr($id, array('_' => '', '.' => '_')).'Service');
}
/**
@@ -247,7 +252,7 @@ public function get($id, $invalidBehavior = self::EXCEPTION_ON_INVALID_REFERENCE
{
$id = strtolower($id);
- if (isset($this->services[$id])) {
+ if (array_key_exists($id, $this->services)) {
return $this->services[$id];
}
@@ -263,10 +268,14 @@ public function get($id, $invalidBehavior = self::EXCEPTION_ON_INVALID_REFERENCE
} catch (\Exception $e) {
unset($this->loading[$id]);
- if (isset($this->services[$id])) {
+ if (array_key_exists($id, $this->services)) {
unset($this->services[$id]);
}
+ if ($e instanceof InactiveScopeException && self::EXCEPTION_ON_INVALID_REFERENCE !== $invalidBehavior) {
+ return null;
+ }
+
throw $e;
}
@@ -289,7 +298,7 @@ public function get($id, $invalidBehavior = self::EXCEPTION_ON_INVALID_REFERENCE
*/
public function initialized($id)
{
- return isset($this->services[strtolower($id)]);
+ return array_key_exists(strtolower($id), $this->services);
}
/**
@@ -393,8 +402,11 @@ public function leaveScope($name)
$services = $this->scopeStacks[$name]->pop();
$this->scopedServices += $services;
- array_unshift($services, $this->services);
- $this->services = call_user_func_array('array_merge', $services);
+ foreach ($services as $array) {
+ foreach ($array as $id => $service) {
+ $this->set($id, $service, $name);
+ }
+ }
}
}
diff --git a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php
index 5b178714bffee..39c6b0362e5b0 100644
--- a/src/Symfony/Component/DependencyInjection/ContainerBuilder.php
+++ b/src/Symfony/Component/DependencyInjection/ContainerBuilder.php
@@ -46,6 +46,11 @@ class ContainerBuilder extends Container implements TaggedContainerInterface
*/
private $definitions = array();
+ /**
+ * @var Definition[]
+ */
+ private $obsoleteDefinitions = array();
+
/**
* @var Alias[]
*/
@@ -351,14 +356,28 @@ public function set($id, $service, $scope = self::SCOPE_CONTAINER)
if ($this->isFrozen()) {
// setting a synthetic service on a frozen container is alright
- if (!isset($this->definitions[$id]) || !$this->definitions[$id]->isSynthetic()) {
+ if (
+ (!isset($this->definitions[$id]) && !isset($this->obsoleteDefinitions[$id]))
+ ||
+ (isset($this->definitions[$id]) && !$this->definitions[$id]->isSynthetic())
+ ||
+ (isset($this->obsoleteDefinitions[$id]) && !$this->obsoleteDefinitions[$id]->isSynthetic())
+ ) {
throw new BadMethodCallException(sprintf('Setting service "%s" on a frozen container is not allowed.', $id));
}
}
+ if (isset($this->definitions[$id])) {
+ $this->obsoleteDefinitions[$id] = $this->definitions[$id];
+ }
+
unset($this->definitions[$id], $this->aliases[$id]);
parent::set($id, $service, $scope);
+
+ if (isset($this->obsoleteDefinitions[$id]) && $this->obsoleteDefinitions[$id]->isSynchronized()) {
+ $this->synchronize($id);
+ }
}
/**
@@ -885,19 +904,7 @@ private function createService(Definition $definition, $id)
}
foreach ($definition->getMethodCalls() as $call) {
- $services = self::getServiceConditionals($call[1]);
-
- $ok = true;
- foreach ($services as $s) {
- if (!$this->has($s)) {
- $ok = false;
- break;
- }
- }
-
- if ($ok) {
- call_user_func_array(array($service, $call[0]), $this->resolveServices($parameterBag->resolveValue($call[1])));
- }
+ $this->callMethod($service, $call);
}
$properties = $this->resolveServices($parameterBag->resolveValue($definition->getProperties()));
@@ -999,4 +1006,43 @@ public static function getServiceConditionals($value)
return $services;
}
+
+ /**
+ * Synchronizes a service change.
+ *
+ * This method updates all services that depend on the given
+ * service by calling all methods referencing it.
+ *
+ * @param string $id A service id
+ */
+ private function synchronize($id)
+ {
+ foreach ($this->definitions as $definitionId => $definition) {
+ // only check initialized services
+ if (!$this->initialized($definitionId)) {
+ continue;
+ }
+
+ foreach ($definition->getMethodCalls() as $call) {
+ foreach ($call[1] as $argument) {
+ if ($argument instanceof Reference && $id == (string) $argument) {
+ $this->callMethod($this->get($definitionId), $call);
+ }
+ }
+ }
+ }
+ }
+
+ private function callMethod($service, $call)
+ {
+ $services = self::getServiceConditionals($call[1]);
+
+ foreach ($services as $s) {
+ if (!$this->has($s)) {
+ return;
+ }
+ }
+
+ call_user_func_array(array($service, $call[0]), $this->resolveServices($this->getParameterBag()->resolveValue($call[1])));
+ }
}
diff --git a/src/Symfony/Component/DependencyInjection/Definition.php b/src/Symfony/Component/DependencyInjection/Definition.php
index 359553a0bf469..9d52426121874 100644
--- a/src/Symfony/Component/DependencyInjection/Definition.php
+++ b/src/Symfony/Component/DependencyInjection/Definition.php
@@ -36,6 +36,7 @@ class Definition
private $public;
private $synthetic;
private $abstract;
+ private $synchronized;
protected $arguments;
@@ -56,6 +57,7 @@ public function __construct($class = null, array $arguments = array())
$this->tags = array();
$this->public = true;
$this->synthetic = false;
+ $this->synchronized = false;
$this->abstract = false;
$this->properties = array();
}
@@ -569,6 +571,34 @@ public function isPublic()
return $this->public;
}
+ /**
+ * Sets the synchronized flag of this service.
+ *
+ * @param Boolean $boolean
+ *
+ * @return Definition The current instance
+ *
+ * @api
+ */
+ public function setSynchronized($boolean)
+ {
+ $this->synchronized = (Boolean) $boolean;
+
+ return $this;
+ }
+
+ /**
+ * Whether this service is synchronized.
+ *
+ * @return Boolean
+ *
+ * @api
+ */
+ public function isSynchronized()
+ {
+ return $this->synchronized;
+ }
+
/**
* Sets whether this definition is synthetic, that is not constructed by the
* container, but dynamically injected.
diff --git a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php
index 4d66d05c154be..52f80b656d8c8 100644
--- a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php
+++ b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php
@@ -567,7 +567,7 @@ protected function get{$name}Service()
*/
private function addServices()
{
- $publicServices = $privateServices = $aliasServices = '';
+ $publicServices = $privateServices = $aliasServices = $synchronizers = '';
$definitions = $this->container->getDefinitions();
ksort($definitions);
foreach ($definitions as $id => $definition) {
@@ -576,6 +576,8 @@ private function addServices()
} else {
$privateServices .= $this->addService($id, $definition);
}
+
+ $synchronizers .= $this->addServiceSynchronizer($id, $definition);
}
$aliases = $this->container->getAliases();
@@ -584,7 +586,60 @@ private function addServices()
$aliasServices .= $this->addServiceAlias($alias, $id);
}
- return $publicServices.$aliasServices.$privateServices;
+ return $publicServices.$aliasServices.$synchronizers.$privateServices;
+ }
+
+ /**
+ * Adds synchronizer methods.
+ *
+ * @param string $id A service identifier
+ * @param Definition $definition A Definition instance
+ */
+ private function addServiceSynchronizer($id, Definition $definition)
+ {
+ if (!$definition->isSynchronized()) {
+ return;
+ }
+
+ $code = '';
+ foreach ($this->container->getDefinitions() as $definitionId => $definition) {
+ foreach ($definition->getMethodCalls() as $call) {
+ foreach ($call[1] as $argument) {
+ if ($argument instanceof Reference && $id == (string) $argument) {
+ $arguments = array();
+ foreach ($call[1] as $value) {
+ $arguments[] = $this->dumpValue($value);
+ }
+
+ $call = $this->wrapServiceConditionals($call[1], sprintf("\$this->get('%s')->%s(%s);", $definitionId, $call[0], implode(', ', $arguments)));
+
+ $code .= <<initialized('$definitionId')) {
+ $call
+ }
+
+EOF;
+ }
+ }
+ }
+ }
+
+ if (!$code) {
+ return;
+ }
+
+ $name = Container::camelize($id);
+
+ return <<isPublic()) {
$service->setAttribute('public', 'false');
}
+ if ($definition->isSynthetic()) {
+ $service->setAttribute('synthetic', 'true');
+ }
+ if ($definition->isSynchronized()) {
+ $service->setAttribute('synchronized', 'true');
+ }
foreach ($definition->getTags() as $name => $tags) {
foreach ($tags as $attributes) {
@@ -239,6 +245,9 @@ private function convertParameters($parameters, $type, \DOMElement $parent, $key
} elseif ($behaviour == ContainerInterface::IGNORE_ON_INVALID_REFERENCE) {
$element->setAttribute('on-invalid', 'ignore');
}
+ if (!$value->isStrict()) {
+ $element->setAttribute('strict', 'false');
+ }
} elseif ($value instanceof Definition) {
$element->setAttribute('type', 'service');
$this->addService($value, null, $element);
diff --git a/src/Symfony/Component/DependencyInjection/Dumper/YamlDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/YamlDumper.php
index e4e168257e4e6..98903bf77b5db 100644
--- a/src/Symfony/Component/DependencyInjection/Dumper/YamlDumper.php
+++ b/src/Symfony/Component/DependencyInjection/Dumper/YamlDumper.php
@@ -94,6 +94,14 @@ private function addService($id, $definition)
$code .= sprintf(" file: %s\n", $definition->getFile());
}
+ if ($definition->isSynthetic()) {
+ $code .= sprintf(" synthetic: true\n");
+ }
+
+ if ($definition->isSynchronized()) {
+ $code .= sprintf(" synchronized: true\n");
+ }
+
if ($definition->getFactoryMethod()) {
$code .= sprintf(" factory_method: %s\n", $definition->getFactoryMethod());
}
diff --git a/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php b/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php
index f925f78ab27e1..85898d3d3fe86 100644
--- a/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php
+++ b/src/Symfony/Component/DependencyInjection/Loader/XmlFileLoader.php
@@ -148,7 +148,7 @@ private function parseDefinition($id, $service, $file)
$definition = new Definition();
}
- foreach (array('class', 'scope', 'public', 'factory-class', 'factory-method', 'factory-service', 'synthetic', 'abstract') as $key) {
+ foreach (array('class', 'scope', 'public', 'factory-class', 'factory-method', 'factory-service', 'synthetic', 'synchronized', 'abstract') as $key) {
if (isset($service[$key])) {
$method = 'set'.str_replace('-', '', $key);
$definition->$method((string) $service->getAttributeAsPhp($key));
diff --git a/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php b/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php
index 71de4ac6592f6..423ca15d45184 100644
--- a/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php
+++ b/src/Symfony/Component/DependencyInjection/Loader/YamlFileLoader.php
@@ -153,6 +153,10 @@ private function parseDefinition($id, $service, $file)
$definition->setSynthetic($service['synthetic']);
}
+ if (isset($service['synchronized'])) {
+ $definition->setSynchronized($service['synchronized']);
+ }
+
if (isset($service['public'])) {
$definition->setPublic($service['public']);
}
diff --git a/src/Symfony/Component/DependencyInjection/Loader/schema/dic/services/services-1.0.xsd b/src/Symfony/Component/DependencyInjection/Loader/schema/dic/services/services-1.0.xsd
index 316f2d7596870..4d9addcd971f8 100644
--- a/src/Symfony/Component/DependencyInjection/Loader/schema/dic/services/services-1.0.xsd
+++ b/src/Symfony/Component/DependencyInjection/Loader/schema/dic/services/services-1.0.xsd
@@ -86,6 +86,7 @@
+
diff --git a/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php b/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php
index bfd92798dc4c1..af0181ecc1f1b 100644
--- a/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php
+++ b/src/Symfony/Component/DependencyInjection/Tests/ContainerBuilderTest.php
@@ -22,6 +22,7 @@
use Symfony\Component\DependencyInjection\Exception\RuntimeException;
use Symfony\Component\DependencyInjection\Reference;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
+use Symfony\Component\DependencyInjection\Scope;
use Symfony\Component\Config\Resource\FileResource;
class ContainerBuilderTest extends \PHPUnit_Framework_TestCase
@@ -577,6 +578,52 @@ public function testNoExceptionWhenSetSyntheticServiceOnAFrozenContainer()
$this->assertEquals($a, $container->get('a'));
}
+ public function testSetOnSynchronizedService()
+ {
+ $container = new ContainerBuilder();
+ $container->register('baz', 'BazClass')
+ ->setSynchronized(true)
+ ;
+ $container->register('bar', 'BarClass')
+ ->addMethodCall('setBaz', array(new Reference('baz')))
+ ;
+
+ $container->set('baz', $baz = new \BazClass());
+ $this->assertSame($baz, $container->get('bar')->getBaz());
+
+ $container->set('baz', $baz = new \BazClass());
+ $this->assertSame($baz, $container->get('bar')->getBaz());
+ }
+
+ public function testSynchronizedServiceWithScopes()
+ {
+ $container = new ContainerBuilder();
+ $container->addScope(new Scope('foo'));
+ $container->register('baz', 'BazClass')
+ ->setSynthetic(true)
+ ->setSynchronized(true)
+ ->setScope('foo')
+ ;
+ $container->register('bar', 'BarClass')
+ ->addMethodCall('setBaz', array(new Reference('baz', ContainerInterface::NULL_ON_INVALID_REFERENCE, false)))
+ ;
+ $container->compile();
+
+ $container->enterScope('foo');
+ $container->set('baz', $outerBaz = new \BazClass(), 'foo');
+ $this->assertSame($outerBaz, $container->get('bar')->getBaz());
+
+ $container->enterScope('foo');
+ $container->set('baz', $innerBaz = new \BazClass(), 'foo');
+ $this->assertSame($innerBaz, $container->get('bar')->getBaz());
+ $container->leaveScope('foo');
+
+ $this->assertNotSame($innerBaz, $container->get('bar')->getBaz());
+ $this->assertSame($outerBaz, $container->get('bar')->getBaz());
+
+ $container->leaveScope('foo');
+ }
+
/**
* @expectedException BadMethodCallException
*/
diff --git a/src/Symfony/Component/DependencyInjection/Tests/ContainerTest.php b/src/Symfony/Component/DependencyInjection/Tests/ContainerTest.php
index 23c13c5094cb5..726af13904cc7 100644
--- a/src/Symfony/Component/DependencyInjection/Tests/ContainerTest.php
+++ b/src/Symfony/Component/DependencyInjection/Tests/ContainerTest.php
@@ -15,6 +15,7 @@
use Symfony\Component\DependencyInjection\Container;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\DependencyInjection\ParameterBag\ParameterBag;
+use Symfony\Component\DependencyInjection\Exception\InactiveScopeException;
class ContainerTest extends \PHPUnit_Framework_TestCase
{
@@ -98,7 +99,7 @@ public function testGetServiceIds()
$this->assertEquals(array('service_container', 'foo', 'bar'), $sc->getServiceIds(), '->getServiceIds() returns all defined service ids');
$sc = new ProjectServiceContainer();
- $this->assertEquals(array('scoped', 'scoped_foo', 'bar', 'foo_bar', 'foo.baz', 'circular', 'throw_exception', 'throws_exception_on_service_configuration', 'service_container'), $sc->getServiceIds(), '->getServiceIds() returns defined service ids by getXXXService() methods');
+ $this->assertEquals(array('scoped', 'scoped_foo', 'inactive', 'bar', 'foo_bar', 'foo.baz', 'circular', 'throw_exception', 'throws_exception_on_service_configuration', 'service_container'), $sc->getServiceIds(), '->getServiceIds() returns defined service ids by getXXXService() methods');
}
/**
@@ -179,6 +180,15 @@ public function testGetCircularReference()
}
}
+ /**
+ * @covers Symfony\Component\DependencyInjection\Container::get
+ */
+ public function testGetReturnsNullOnInactiveScope()
+ {
+ $sc = new ProjectServiceContainer();
+ $this->assertNull($sc->get('inactive', ContainerInterface::NULL_ON_INVALID_REFERENCE));
+ }
+
/**
* @covers Symfony\Component\DependencyInjection\Container::has
*/
@@ -476,6 +486,11 @@ protected function getScopedFooService()
return $this->services['scoped_foo'] = $this->scopedServices['foo']['scoped_foo'] = new \stdClass();
}
+ protected function getInactiveService()
+ {
+ throw new InactiveScopeException('request', 'request');
+ }
+
protected function getBarService()
{
return $this->__bar;
diff --git a/src/Symfony/Component/DependencyInjection/Tests/DefinitionTest.php b/src/Symfony/Component/DependencyInjection/Tests/DefinitionTest.php
index 89f7ae1ea0ad0..d9a4282efefbc 100644
--- a/src/Symfony/Component/DependencyInjection/Tests/DefinitionTest.php
+++ b/src/Symfony/Component/DependencyInjection/Tests/DefinitionTest.php
@@ -149,7 +149,19 @@ public function testSetIsSynthetic()
$def = new Definition('stdClass');
$this->assertFalse($def->isSynthetic(), '->isSynthetic() returns false by default');
$this->assertSame($def, $def->setSynthetic(true), '->setSynthetic() implements a fluent interface');
- $this->assertTrue($def->isSynthetic(), '->isSynthetic() returns true if the instance must not be public.');
+ $this->assertTrue($def->isSynthetic(), '->isSynthetic() returns true if the service is synthetic.');
+ }
+
+ /**
+ * @covers Symfony\Component\DependencyInjection\Definition::setSynchronized
+ * @covers Symfony\Component\DependencyInjection\Definition::isSynchronized
+ */
+ public function testSetIsSynchronized()
+ {
+ $def = new Definition('stdClass');
+ $this->assertFalse($def->isSynchronized(), '->isSynchronized() returns false by default');
+ $this->assertSame($def, $def->setSynchronized(true), '->setSynchronized() implements a fluent interface');
+ $this->assertTrue($def->isSynchronized(), '->isSynchronized() returns true if the service is synchronized.');
}
/**
diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container9.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container9.php
index 71d29f209bfcb..6ba3ad349d5d8 100644
--- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container9.php
+++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/containers/container9.php
@@ -71,5 +71,14 @@
->register('baz', 'Baz')
->addMethodCall('setFoo', array(new Reference('foo_with_inline')))
;
+$container
+ ->register('request', 'Request')
+ ->setSynthetic(true)
+ ->setSynchronized(true)
+;
+$container
+ ->register('depends_on_request', 'stdClass')
+ ->addMethodCall('setRequest', array(new Reference('request', ContainerInterface::NULL_ON_INVALID_REFERENCE, false)))
+;
return $container;
diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/graphviz/services9.dot b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/graphviz/services9.dot
index 73608e27fc912..cb006641d0b13 100644
--- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/graphviz/services9.dot
+++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/graphviz/services9.dot
@@ -12,6 +12,8 @@ digraph sc {
node_foo_with_inline [label="foo_with_inline\nFoo\n", shape=record, fillcolor="#eeeeee", style="filled"];
node_inlined [label="inlined\nBar\n", shape=record, fillcolor="#eeeeee", style="filled"];
node_baz [label="baz\nBaz\n", shape=record, fillcolor="#eeeeee", style="filled"];
+ node_request [label="request\nRequest\n", shape=record, fillcolor="#eeeeee", style="filled"];
+ node_depends_on_request [label="depends_on_request\nstdClass\n", shape=record, fillcolor="#eeeeee", style="filled"];
node_service_container [label="service_container\nSymfony\\Component\\DependencyInjection\\ContainerBuilder\n", shape=record, fillcolor="#9999ff", style="filled"];
node_foo2 [label="foo2\n\n", shape=record, fillcolor="#ff9999", style="filled"];
node_foo3 [label="foo3\n\n", shape=record, fillcolor="#ff9999", style="filled"];
@@ -28,4 +30,5 @@ digraph sc {
node_foo_with_inline -> node_inlined [label="setBar()" style="dashed"];
node_inlined -> node_baz [label="setBaz()" style="dashed"];
node_baz -> node_foo_with_inline [label="setFoo()" style="dashed"];
+ node_depends_on_request -> node_request [label="setRequest()" style="dashed"];
}
diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/classes.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/classes.php
index fb6d4cf19d5c5..48e1c2c84e12d 100644
--- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/classes.php
+++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/includes/classes.php
@@ -13,6 +13,11 @@ public function setBaz(BazClass $baz)
{
$this->baz = $baz;
}
+
+ public function getBaz()
+ {
+ return $this->baz;
+ }
}
class BazClass
diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9.php
index 324b77f66c7fb..4aad5e6e9e506 100644
--- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9.php
+++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9.php
@@ -60,6 +60,23 @@ protected function getBazService()
return $instance;
}
+ /**
+ * Gets the 'depends_on_request' service.
+ *
+ * This service is shared.
+ * This method always returns the same instance of the service.
+ *
+ * @return stdClass A stdClass instance.
+ */
+ protected function getDependsOnRequestService()
+ {
+ $this->services['depends_on_request'] = $instance = new \stdClass();
+
+ $instance->setRequest($this->get('request', ContainerInterface::NULL_ON_INVALID_REFERENCE));
+
+ return $instance;
+ }
+
/**
* Gets the 'factory_service' service.
*
@@ -168,6 +185,19 @@ protected function getMethodCall1Service()
return $instance;
}
+ /**
+ * Gets the 'request' service.
+ *
+ * This service is shared.
+ * This method always returns the same instance of the service.
+ *
+ * @throws RuntimeException always since this service is expected to be injected dynamically
+ */
+ protected function getRequestService()
+ {
+ throw new RuntimeException('You have requested a synthetic service ("request"). The DIC does not know how to construct this service.');
+ }
+
/**
* Gets the alias_for_foo service alias.
*
@@ -178,6 +208,16 @@ protected function getAliasForFooService()
return $this->get('foo');
}
+ /**
+ * Updates the 'request' service.
+ */
+ protected function synchronizeRequestService()
+ {
+ if ($this->initialized('depends_on_request')) {
+ $this->get('depends_on_request')->setRequest($this->get('request', ContainerInterface::NULL_ON_INVALID_REFERENCE));
+ }
+ }
+
/**
* Gets the 'inlined' service.
*
diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_compiled.php b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_compiled.php
index 5c71db9e66aba..2deea119f47fc 100644
--- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_compiled.php
+++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/php/services9_compiled.php
@@ -69,6 +69,23 @@ protected function getBazService()
return $instance;
}
+ /**
+ * Gets the 'depends_on_request' service.
+ *
+ * This service is shared.
+ * This method always returns the same instance of the service.
+ *
+ * @return stdClass A stdClass instance.
+ */
+ protected function getDependsOnRequestService()
+ {
+ $this->services['depends_on_request'] = $instance = new \stdClass();
+
+ $instance->setRequest($this->get('request', ContainerInterface::NULL_ON_INVALID_REFERENCE));
+
+ return $instance;
+ }
+
/**
* Gets the 'factory_service' service.
*
@@ -174,6 +191,19 @@ protected function getMethodCall1Service()
return $instance;
}
+ /**
+ * Gets the 'request' service.
+ *
+ * This service is shared.
+ * This method always returns the same instance of the service.
+ *
+ * @throws RuntimeException always since this service is expected to be injected dynamically
+ */
+ protected function getRequestService()
+ {
+ throw new RuntimeException('You have requested a synthetic service ("request"). The DIC does not know how to construct this service.');
+ }
+
/**
* Gets the alias_for_foo service alias.
*
@@ -184,6 +214,16 @@ protected function getAliasForFooService()
return $this->get('foo');
}
+ /**
+ * Updates the 'request' service.
+ */
+ protected function synchronizeRequestService()
+ {
+ if ($this->initialized('depends_on_request')) {
+ $this->get('depends_on_request')->setRequest($this->get('request', ContainerInterface::NULL_ON_INVALID_REFERENCE));
+ }
+ }
+
/**
* {@inheritdoc}
*/
diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services6.xml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services6.xml
index 45bc042f61906..4d2aa3d79ae24 100644
--- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services6.xml
+++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services6.xml
@@ -46,5 +46,6 @@
+
diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services9.xml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services9.xml
index 58eb6d79a3c1e..d04d492e8d824 100644
--- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services9.xml
+++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/xml/services9.xml
@@ -67,6 +67,12 @@
+
+
+
+
+
+
diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services6.yml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services6.yml
index eaa52bda62065..820c364a06556 100644
--- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services6.yml
+++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services6.yml
@@ -24,3 +24,7 @@ services:
alias: foo
public: false
factory_service: { class: BazClass, factory_method: getInstance, factory_service: baz_factory }
+ request:
+ class: Request
+ synthetic: true
+ synchronized: true
diff --git a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services9.yml b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services9.yml
index fcbb83f4ae7e1..3d9c6417812f1 100644
--- a/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services9.yml
+++ b/src/Symfony/Component/DependencyInjection/Tests/Fixtures/yaml/services9.yml
@@ -57,4 +57,13 @@ services:
calls:
- [setFoo, ['@foo_with_inline']]
+ request:
+ class: Request
+ synthetic: true
+ synchronized: true
+ depends_on_request:
+ class: stdClass
+ calls:
+ - [setRequest, ['@?request']]
+
alias_for_foo: @foo
diff --git a/src/Symfony/Component/DependencyInjection/Tests/Loader/XmlFileLoaderTest.php b/src/Symfony/Component/DependencyInjection/Tests/Loader/XmlFileLoaderTest.php
index 0287a1b0aa334..b355f0ac215c3 100644
--- a/src/Symfony/Component/DependencyInjection/Tests/Loader/XmlFileLoaderTest.php
+++ b/src/Symfony/Component/DependencyInjection/Tests/Loader/XmlFileLoaderTest.php
@@ -185,6 +185,9 @@ public function testLoadServices()
$this->assertEquals('getInstance', $services['factory_service']->getFactoryMethod());
$this->assertEquals('baz_factory', $services['factory_service']->getFactoryService());
+ $this->assertTrue($services['request']->isSynthetic(), '->load() parses the synthetic flag');
+ $this->assertTrue($services['request']->isSynchronized(), '->load() parses the synchronized flag');
+
$aliases = $container->getAliases();
$this->assertTrue(isset($aliases['alias_for_foo']), '->load() parses elements');
$this->assertEquals('foo', (string) $aliases['alias_for_foo'], '->load() parses aliases');
diff --git a/src/Symfony/Component/DependencyInjection/Tests/Loader/YamlFileLoaderTest.php b/src/Symfony/Component/DependencyInjection/Tests/Loader/YamlFileLoaderTest.php
index e655d3bd8981a..1c700df7b5b9d 100644
--- a/src/Symfony/Component/DependencyInjection/Tests/Loader/YamlFileLoaderTest.php
+++ b/src/Symfony/Component/DependencyInjection/Tests/Loader/YamlFileLoaderTest.php
@@ -128,6 +128,9 @@ public function testLoadServices()
$this->assertEquals(array(array('setBar', array('foo', new Reference('foo'), array(true, false)))), $services['method_call2']->getMethodCalls(), '->load() parses the method_call tag');
$this->assertEquals('baz_factory', $services['factory_service']->getFactoryService());
+ $this->assertTrue($services['request']->isSynthetic(), '->load() parses the synthetic flag');
+ $this->assertTrue($services['request']->isSynchronized(), '->load() parses the synchronized flag');
+
$aliases = $container->getAliases();
$this->assertTrue(isset($aliases['alias_for_foo']), '->load() parses aliases');
$this->assertEquals('foo', (string) $aliases['alias_for_foo'], '->load() parses aliases');
diff --git a/src/Symfony/Component/HttpKernel/DependencyInjection/ContainerAwareHttpKernel.php b/src/Symfony/Component/HttpKernel/DependencyInjection/ContainerAwareHttpKernel.php
index 20b4a5e75e9ad..0aae26b483504 100644
--- a/src/Symfony/Component/HttpKernel/DependencyInjection/ContainerAwareHttpKernel.php
+++ b/src/Symfony/Component/HttpKernel/DependencyInjection/ContainerAwareHttpKernel.php
@@ -56,11 +56,13 @@ public function handle(Request $request, $type = HttpKernelInterface::MASTER_REQ
try {
$response = parent::handle($request, $type, $catch);
} catch (\Exception $e) {
+ $this->container->set('request', null, 'request');
$this->container->leaveScope('request');
throw $e;
}
+ $this->container->set('request', null, 'request');
$this->container->leaveScope('request');
return $response;
diff --git a/src/Symfony/Component/HttpKernel/EventListener/LocaleListener.php b/src/Symfony/Component/HttpKernel/EventListener/LocaleListener.php
index f3cb804832660..0b864c02f2bc4 100644
--- a/src/Symfony/Component/HttpKernel/EventListener/LocaleListener.php
+++ b/src/Symfony/Component/HttpKernel/EventListener/LocaleListener.php
@@ -12,7 +12,6 @@
namespace Symfony\Component\HttpKernel\EventListener;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
-use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
use Symfony\Component\HttpKernel\KernelEvents;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Routing\RequestContextAwareInterface;
@@ -27,7 +26,6 @@ class LocaleListener implements EventSubscriberInterface
{
private $router;
private $defaultLocale;
- private $locales = array();
public function __construct($defaultLocale = 'en', RequestContextAwareInterface $router = null)
{
@@ -35,24 +33,27 @@ public function __construct($defaultLocale = 'en', RequestContextAwareInterface
$this->router = $router;
}
- public function onKernelResponse(FilterResponseEvent $event)
+ public function setRequest(Request $request = null)
{
- array_shift($this->locales);
+ if (null === $request) {
+ return;
+ }
- // setting back the locale to the previous value
- $locale = isset($this->locales[0]) ? $this->locales[0] : $this->defaultLocale;
- $request = $event->getRequest();
- $this->setLocale($request, $locale);
+ if ($locale = $request->attributes->get('_locale')) {
+ $request->setLocale($locale);
+ }
+
+ if (null !== $this->router) {
+ $this->router->getContext()->setParameter('_locale', $request->getLocale());
+ }
}
public function onKernelRequest(GetResponseEvent $event)
{
$request = $event->getRequest();
-
$request->setDefaultLocale($this->defaultLocale);
- $this->setLocale($request, $request->attributes->get('_locale', $this->defaultLocale));
- array_unshift($this->locales, $request->getLocale());
+ $this->setRequest($request);
}
public static function getSubscribedEvents()
@@ -60,16 +61,6 @@ public static function getSubscribedEvents()
return array(
// must be registered after the Router to have access to the _locale
KernelEvents::REQUEST => array(array('onKernelRequest', 16)),
- KernelEvents::RESPONSE => 'onKernelResponse',
);
}
-
- private function setLocale(Request $request, $locale)
- {
- $request->setLocale($locale);
-
- if (null !== $this->router) {
- $this->router->getContext()->setParameter('_locale', $request->getLocale());
- }
- }
}
diff --git a/src/Symfony/Component/HttpKernel/EventListener/RouterListener.php b/src/Symfony/Component/HttpKernel/EventListener/RouterListener.php
index 606b358e72f04..58ea6f0a5436d 100644
--- a/src/Symfony/Component/HttpKernel/EventListener/RouterListener.php
+++ b/src/Symfony/Component/HttpKernel/EventListener/RouterListener.php
@@ -23,6 +23,7 @@
use Symfony\Component\Routing\RequestContext;
use Symfony\Component\Routing\RequestContextAwareInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
+use Symfony\Component\HttpFoundation\Request;
/**
* Initializes the context from the request and sets request attributes based on a matching route.
@@ -59,12 +60,31 @@ public function __construct($matcher, RequestContext $context = null, LoggerInte
$this->logger = $logger;
}
+ /**
+ * Sets the current Request.
+ *
+ * The application should call this method whenever the Request
+ * object changes (entering a Request scope for instance, but
+ * also when leaving a Request scope -- especially when they are
+ * nested).
+ *
+ * @param Request|null $request A Request instance
+ */
+ public function setRequest(Request $request = null)
+ {
+ if (null !== $request) {
+ $this->context->fromRequest($request);
+ }
+ }
+
public function onKernelRequest(GetResponseEvent $event)
{
$request = $event->getRequest();
// initialize the context that is also used by the generator (assuming matcher and generator share the same context instance)
- $this->context->fromRequest($request);
+ // we call setRequest even if most of the time, it has already been done to keep compatibility
+ // with frameworks which do not use the Symfony service container
+ $this->setRequest($request);
if ($request->attributes->has('_controller')) {
// routing is already done
diff --git a/src/Symfony/Component/HttpKernel/Fragment/FragmentHandler.php b/src/Symfony/Component/HttpKernel/Fragment/FragmentHandler.php
index b4f3f9c1eef47..54d0a70b7dbec 100644
--- a/src/Symfony/Component/HttpKernel/Fragment/FragmentHandler.php
+++ b/src/Symfony/Component/HttpKernel/Fragment/FragmentHandler.php
@@ -15,10 +15,6 @@
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\StreamedResponse;
use Symfony\Component\HttpKernel\Controller\ControllerReference;
-use Symfony\Component\HttpKernel\KernelEvents;
-use Symfony\Component\HttpKernel\Event\GetResponseEvent;
-use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
-use Symfony\Component\EventDispatcher\EventSubscriberInterface;
/**
* Renders a URI that represents a resource fragment.
@@ -30,11 +26,11 @@
*
* @see FragmentRendererInterface
*/
-class FragmentHandler implements EventSubscriberInterface
+class FragmentHandler
{
private $debug;
private $renderers;
- private $requests;
+ private $request;
/**
* Constructor.
@@ -49,7 +45,6 @@ public function __construct(array $renderers = array(), $debug = false)
$this->addRenderer($renderer);
}
$this->debug = $debug;
- $this->requests = array();
}
/**
@@ -63,23 +58,13 @@ public function addRenderer(FragmentRendererInterface $renderer)
}
/**
- * Stores the Request object.
+ * Sets the current Request.
*
- * @param GetResponseEvent $event A GetResponseEvent instance
+ * @param Request $request The current Request
*/
- public function onKernelRequest(GetResponseEvent $event)
+ public function setRequest(Request $request = null)
{
- array_unshift($this->requests, $event->getRequest());
- }
-
- /**
- * Removes the most recent Request object.
- *
- * @param FilterResponseEvent $event A FilterResponseEvent instance
- */
- public function onKernelResponse(FilterResponseEvent $event)
- {
- array_shift($this->requests);
+ $this->request = $request;
}
/**
@@ -108,7 +93,11 @@ public function render($uri, $renderer = 'inline', array $options = array())
throw new \InvalidArgumentException(sprintf('The "%s" renderer does not exist.', $renderer));
}
- return $this->deliver($this->renderers[$renderer]->render($uri, $this->requests[0], $options));
+ if (null === $this->request) {
+ throw new \LogicException('Rendering a fragment can only be done when handling a master Request.');
+ }
+
+ return $this->deliver($this->renderers[$renderer]->render($uri, $this->request, $options));
}
/**
@@ -126,7 +115,7 @@ public function render($uri, $renderer = 'inline', array $options = array())
protected function deliver(Response $response)
{
if (!$response->isSuccessful()) {
- throw new \RuntimeException(sprintf('Error when rendering "%s" (Status code is %s).', $this->requests[0]->getUri(), $response->getStatusCode()));
+ throw new \RuntimeException(sprintf('Error when rendering "%s" (Status code is %s).', $this->request->getUri(), $response->getStatusCode()));
}
if (!$response instanceof StreamedResponse) {
@@ -136,14 +125,6 @@ protected function deliver(Response $response)
$response->sendContent();
}
- public static function getSubscribedEvents()
- {
- return array(
- KernelEvents::REQUEST => 'onKernelRequest',
- KernelEvents::RESPONSE => 'onKernelResponse',
- );
- }
-
// to be removed in 2.3
public function fixOptions(array $options)
{
diff --git a/src/Symfony/Component/HttpKernel/Tests/DependencyInjection/ContainerAwareHttpKernelTest.php b/src/Symfony/Component/HttpKernel/Tests/DependencyInjection/ContainerAwareHttpKernelTest.php
index 80d5ffa61a664..6da06c01d1544 100644
--- a/src/Symfony/Component/HttpKernel/Tests/DependencyInjection/ContainerAwareHttpKernelTest.php
+++ b/src/Symfony/Component/HttpKernel/Tests/DependencyInjection/ContainerAwareHttpKernelTest.php
@@ -9,7 +9,7 @@
* file that was distributed with this source code.
*/
-namespace Symfony\Component\HttpKernel\Tests;
+namespace Symfony\Component\HttpKernel\Tests\DependencyInjection;
use Symfony\Component\HttpKernel\HttpKernelInterface;
use Symfony\Component\HttpKernel\DependencyInjection\ContainerAwareHttpKernel;
@@ -54,10 +54,15 @@ public function testHandle($type)
->with($this->equalTo('request'))
;
$container
- ->expects($this->once())
+ ->expects($this->at(1))
->method('set')
->with($this->equalTo('request'), $this->equalTo($request), $this->equalTo('request'))
;
+ $container
+ ->expects($this->at(2))
+ ->method('set')
+ ->with($this->equalTo('request'), $this->equalTo(null), $this->equalTo('request'))
+ ;
$dispatcher = new EventDispatcher();
$resolver = $this->getMock('Symfony\\Component\\HttpKernel\\Controller\\ControllerResolverInterface');
@@ -101,10 +106,15 @@ public function testHandleRestoresThePreviousRequestOnException($type)
->with($this->equalTo('request'))
;
$container
- ->expects($this->once())
+ ->expects($this->at(1))
->method('set')
->with($this->equalTo('request'), $this->equalTo($request), $this->equalTo('request'))
;
+ $container
+ ->expects($this->at(2))
+ ->method('set')
+ ->with($this->equalTo('request'), $this->equalTo(null), $this->equalTo('request'))
+ ;
$dispatcher = new EventDispatcher();
$resolver = $this->getMock('Symfony\\Component\\HttpKernel\\Controller\\ControllerResolverInterface');
diff --git a/src/Symfony/Component/HttpKernel/Tests/Fragment/FragmentHandlerTest.php b/src/Symfony/Component/HttpKernel/Tests/Fragment/FragmentHandlerTest.php
index e0a5b0ad59342..f2a0838a46424 100644
--- a/src/Symfony/Component/HttpKernel/Tests/Fragment/FragmentHandlerTest.php
+++ b/src/Symfony/Component/HttpKernel/Tests/Fragment/FragmentHandlerTest.php
@@ -17,13 +17,6 @@
class FragmentHandlerTest extends \PHPUnit_Framework_TestCase
{
- protected function setUp()
- {
- if (!class_exists('Symfony\Component\EventDispatcher\EventDispatcher')) {
- $this->markTestSkipped('The "EventDispatcher" component is not available');
- }
- }
-
/**
* @expectedException \InvalidArgumentException
*/
@@ -102,14 +95,7 @@ protected function getHandler($returnValue, $arguments = array())
$handler = new FragmentHandler();
$handler->addRenderer($renderer);
-
- $event = $this->getMockBuilder('Symfony\Component\HttpKernel\Event\GetResponseEvent')->disableOriginalConstructor()->getMock();
- $event
- ->expects($this->once())
- ->method('getRequest')
- ->will($this->returnValue(Request::create('/')))
- ;
- $handler->onKernelRequest($event);
+ $handler->setRequest(Request::create('/'));
return $handler;
}