diff --git a/core/lib/Drupal/Core/DependencyInjection/BootstrapContainer.php b/core/lib/Drupal/Core/DependencyInjection/BootstrapContainer.php index 1e9ff04..28674a9 100644 --- a/core/lib/Drupal/Core/DependencyInjection/BootstrapContainer.php +++ b/core/lib/Drupal/Core/DependencyInjection/BootstrapContainer.php @@ -142,7 +142,10 @@ protected function createService($definition, $id) { // Share the service if it is public. if (!isset($definition['public']) || $definition['public'] !== FALSE) { - $this->services[$id] = $service; + // Forward compatibility fix for Symfony 2.8 update. + if (!isset($definition['shared']) || $definition['shared'] !== FALSE) { + $this->services[$id] = $service; + } } if (isset($definition['calls'])) { diff --git a/core/lib/Drupal/Core/DependencyInjection/Container.php b/core/lib/Drupal/Core/DependencyInjection/Container.php index 350d6e1..4fcf980 100644 --- a/core/lib/Drupal/Core/DependencyInjection/Container.php +++ b/core/lib/Drupal/Core/DependencyInjection/Container.php @@ -303,7 +303,10 @@ protected function createService($definition, $id) { // Share the service if it is public. if (!isset($definition['public']) || $definition['public'] !== FALSE) { - $this->services[$id] = $service; + // Forward compatibility fix for Symfony 2.8 update. + if (!isset($definition['shared']) || $definition['shared'] !== FALSE) { + $this->services[$id] = $service; + } } if (isset($definition['calls'])) { diff --git a/core/lib/Drupal/Core/DependencyInjection/Dumper/PhpArrayDumper.php b/core/lib/Drupal/Core/DependencyInjection/Dumper/PhpArrayDumper.php index 9b2a637..541bfa1 100644 --- a/core/lib/Drupal/Core/DependencyInjection/Dumper/PhpArrayDumper.php +++ b/core/lib/Drupal/Core/DependencyInjection/Dumper/PhpArrayDumper.php @@ -212,7 +212,15 @@ protected function getServiceDefinition($definition) { } if (($scope = $definition->getScope()) !== ContainerInterface::SCOPE_CONTAINER) { - throw new InvalidArgumentException("The 'scope' definition is deprecated in Symfony 3.0 and not supported by Drupal 8."); + if ($scope === ContainerInterface::SCOPE_PROTOTYPE) { + // Scope prototype has been replaced with 'shared' => FALSE. + // This is a Symfony 2.8 forward compatibility fix. + // Reference: https://github.com/symfony/symfony/blob/2.8/UPGRADE-2.8.md#dependencyinjection + $service['shared'] = FALSE; + } + else { + throw new InvalidArgumentException("The 'scope' definition is deprecated in Symfony 3.0 and not supported by Drupal 8."); + } } if (($decorated = $definition->getDecoratedService()) !== NULL) { diff --git a/core/tests/Drupal/Tests/Core/DependencyInjection/Dumper/PhpArrayDumperTest.php b/core/tests/Drupal/Tests/Core/DependencyInjection/Dumper/PhpArrayDumperTest.php index 81d26cb..91934c0 100644 --- a/core/tests/Drupal/Tests/Core/DependencyInjection/Dumper/PhpArrayDumperTest.php +++ b/core/tests/Drupal/Tests/Core/DependencyInjection/Dumper/PhpArrayDumperTest.php @@ -223,6 +223,8 @@ public function getDefinitionsDataProvider() { 'arguments_count' => 0, 'properties' => array(), 'calls' => array(), + 'scope' => ContainerInterface::SCOPE_CONTAINER, + 'shared' => TRUE, 'factory' => FALSE, 'configurator' => FALSE, ); @@ -325,6 +327,11 @@ public function getDefinitionsDataProvider() { 'calls' => $calls, ) + $base_service_definition; + $service_definitions[] = array( + 'scope' => ContainerInterface::SCOPE_PROTOTYPE, + 'shared' => FALSE, + ) + $base_service_definition; + // Test factory. $service_definitions[] = array( 'factory' => array(new Reference('bar'), 'factoryMethod'), @@ -363,7 +370,7 @@ public function getDefinitionsDataProvider() { $definition->getArguments()->willReturn($service_definition['arguments']); $definition->getProperties()->willReturn($service_definition['properties']); $definition->getMethodCalls()->willReturn($service_definition['calls']); - $definition->getScope()->willReturn(ContainerInterface::SCOPE_CONTAINER); + $definition->getScope()->willReturn($service_definition['scope']); $definition->getDecoratedService()->willReturn(NULL); $definition->getFactory()->willReturn($service_definition['factory']); $definition->getConfigurator()->willReturn($service_definition['configurator']); @@ -395,6 +402,9 @@ public function getDefinitionsDataProvider() { } } + // Remove any remaining scope. + unset($filtered_service_definition['scope']); + if (isset($filtered_service_definition['public']) && $filtered_service_definition['public'] === FALSE) { $services_provided[] = array( array('foo_service' => $definition->reveal()), diff --git a/core/tests/Drupal/Tests/Core/DependencyInjection/PhpArray/ContainerTest.php b/core/tests/Drupal/Tests/Core/DependencyInjection/PhpArray/ContainerTest.php index 92192e4..54f4267 100644 --- a/core/tests/Drupal/Tests/Core/DependencyInjection/PhpArray/ContainerTest.php +++ b/core/tests/Drupal/Tests/Core/DependencyInjection/PhpArray/ContainerTest.php @@ -119,6 +119,7 @@ public function test_setParameter_frozenContainer() { /** * Tests that Container::get() works properly. + * * @covers ::get * @covers ::createService */ @@ -143,6 +144,19 @@ public function test_get() { $this->assertEquals($service->_someProperty, 'foo', 'Service has added properties.'); } + /** + * Tests that Container::get() for non-shared services works properly. + * + * @covers ::get + * @covers ::createService + */ + public function test_get_nonShared() { + $service = $this->container->get('non_shared_service'); + $service2 = $this->container->get('non_shared_service'); + + $this->assertNotSame($service, $service2, 'Non shared services are always re-instantiated.'); + } + /** * Tests that Container::get() works properly for class from parameters. * @covers ::get @@ -718,6 +732,12 @@ protected function getMockContainerDefinition() { $services['other.service'] = array( 'class' => get_class($fake_service), ); + + $services['non_shared_service'] = array( + 'class' => get_class($fake_service), + 'shared' => FALSE, + ); + $services['other.service_class_from_parameter'] = array( 'class' => $this->getParameterCall('some_parameter_class'), );