From 52d8676399117dde482cc7e30a0474c02d5438a9 Mon Sep 17 00:00:00 2001 From: Douglas Greenshields Date: Wed, 24 Jul 2013 15:40:20 +0100 Subject: [PATCH 1/9] [Intl] made RegionBundle and LanguageBundle merge fallback data when using a country-specific locale --- .../Component/Intl/ResourceBundle/LanguageBundle.php | 6 +++--- .../Component/Intl/ResourceBundle/RegionBundle.php | 4 ++-- .../Intl/Tests/ResourceBundle/RegionBundleTest.php | 4 ++-- .../Tests/Constraints/CountryValidatorTest.php | 10 ++++++++++ .../Tests/Constraints/LanguageValidatorTest.php | 12 ++++++++++++ 5 files changed, 29 insertions(+), 7 deletions(-) diff --git a/src/Symfony/Component/Intl/ResourceBundle/LanguageBundle.php b/src/Symfony/Component/Intl/ResourceBundle/LanguageBundle.php index c449f9c199..6b98a29e39 100644 --- a/src/Symfony/Component/Intl/ResourceBundle/LanguageBundle.php +++ b/src/Symfony/Component/Intl/ResourceBundle/LanguageBundle.php @@ -27,7 +27,7 @@ class LanguageBundle extends AbstractBundle implements LanguageBundleInterface $locale = \Locale::getDefault(); } - if (null === ($languages = $this->readEntry($locale, array('Languages')))) { + if (null === ($languages = $this->readEntry($locale, array('Languages'), true))) { return null; } @@ -49,7 +49,7 @@ class LanguageBundle extends AbstractBundle implements LanguageBundleInterface $locale = \Locale::getDefault(); } - if (null === ($languages = $this->readEntry($locale, array('Languages')))) { + if (null === ($languages = $this->readEntry($locale, array('Languages'), true))) { return array(); } @@ -102,7 +102,7 @@ class LanguageBundle extends AbstractBundle implements LanguageBundleInterface $locale = \Locale::getDefault(); } - if (null === ($scripts = $this->readEntry($locale, array('Scripts')))) { + if (null === ($scripts = $this->readEntry($locale, array('Scripts'), true))) { return array(); } diff --git a/src/Symfony/Component/Intl/ResourceBundle/RegionBundle.php b/src/Symfony/Component/Intl/ResourceBundle/RegionBundle.php index a3cd9bd39a..bbfbedeed9 100644 --- a/src/Symfony/Component/Intl/ResourceBundle/RegionBundle.php +++ b/src/Symfony/Component/Intl/ResourceBundle/RegionBundle.php @@ -27,7 +27,7 @@ class RegionBundle extends AbstractBundle implements RegionBundleInterface $locale = \Locale::getDefault(); } - return $this->readEntry($locale, array('Countries', $country)); + return $this->readEntry($locale, array('Countries', $country), true); } /** @@ -39,7 +39,7 @@ class RegionBundle extends AbstractBundle implements RegionBundleInterface $locale = \Locale::getDefault(); } - if (null === ($countries = $this->readEntry($locale, array('Countries')))) { + if (null === ($countries = $this->readEntry($locale, array('Countries'), true))) { return array(); } diff --git a/src/Symfony/Component/Intl/Tests/ResourceBundle/RegionBundleTest.php b/src/Symfony/Component/Intl/Tests/ResourceBundle/RegionBundleTest.php index ccdf904c91..8155040806 100644 --- a/src/Symfony/Component/Intl/Tests/ResourceBundle/RegionBundleTest.php +++ b/src/Symfony/Component/Intl/Tests/ResourceBundle/RegionBundleTest.php @@ -40,7 +40,7 @@ class RegionBundleTest extends \PHPUnit_Framework_TestCase { $this->reader->expects($this->once()) ->method('readEntry') - ->with(self::RES_DIR, 'en', array('Countries', 'AT')) + ->with(self::RES_DIR, 'en', array('Countries', 'AT'), true) ->will($this->returnValue('Austria')); $this->assertSame('Austria', $this->bundle->getCountryName('AT', 'en')); @@ -55,7 +55,7 @@ class RegionBundleTest extends \PHPUnit_Framework_TestCase $this->reader->expects($this->once()) ->method('readEntry') - ->with(self::RES_DIR, 'en', array('Countries')) + ->with(self::RES_DIR, 'en', array('Countries'), true) ->will($this->returnValue($sortedCountries)); $this->assertSame($sortedCountries, $this->bundle->getCountryNames('en')); diff --git a/src/Symfony/Component/Validator/Tests/Constraints/CountryValidatorTest.php b/src/Symfony/Component/Validator/Tests/Constraints/CountryValidatorTest.php index 3eedaa3264..95851e8097 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/CountryValidatorTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/CountryValidatorTest.php @@ -104,4 +104,14 @@ class CountryValidatorTest extends \PHPUnit_Framework_TestCase array('EN'), ); } + + public function testValidateUsingCountrySpecificLocale() + { + \Locale::setDefault('en_GB'); + $existingCountry = 'GB'; + $this->context->expects($this->never()) + ->method('addViolation'); + + $this->validator->validate($existingCountry, new Country()); + } } diff --git a/src/Symfony/Component/Validator/Tests/Constraints/LanguageValidatorTest.php b/src/Symfony/Component/Validator/Tests/Constraints/LanguageValidatorTest.php index 1230e3f322..3588887d74 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/LanguageValidatorTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/LanguageValidatorTest.php @@ -104,4 +104,16 @@ class LanguageValidatorTest extends \PHPUnit_Framework_TestCase array('foobar'), ); } + + public function testValidateUsingCountrySpecificLocale() + { + \Locale::setDefault('fr_FR'); + $existingLanguage = 'en'; + $this->context->expects($this->never()) + ->method('addViolation'); + + $this->validator->validate($existingLanguage, new Language(array( + 'message' => 'aMessage' + ))); + } } From 19fef77d0d1ccb75cbba98ca26c69274e28e2d13 Mon Sep 17 00:00:00 2001 From: Romain Neutron Date: Wed, 11 Sep 2013 14:13:56 +0200 Subject: [PATCH 2/9] [Process] Fix process merge in 2.3 Handles should be read and closed after `proc_close` is called. --- src/Symfony/Component/Process/Process.php | 25 +++++++++++------------ 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/src/Symfony/Component/Process/Process.php b/src/Symfony/Component/Process/Process.php index 98d2bbdf5b..f8edbf75cd 100644 --- a/src/Symfony/Component/Process/Process.php +++ b/src/Symfony/Component/Process/Process.php @@ -303,18 +303,6 @@ class Process } $this->updateStatus(false); - while ($this->processPipes->hasOpenHandles()) { - usleep(100); - foreach ($this->processPipes->readAndCloseHandles(true) as $type => $data) { - if (3 == $type) { - $this->fallbackExitcode = (int) $data; - } else { - call_user_func($this->callback, $type === self::STDOUT ? self::OUT : self::ERR, $data); - } - } - } - $this->close(); - if ($this->processInformation['signaled']) { if ($this->isSigchildEnabled()) { throw new RuntimeException('The process has been signaled.'); @@ -1062,13 +1050,24 @@ class Process */ private function close() { - $this->processPipes->close(); $exitcode = -1; if (is_resource($this->process)) { $exitcode = proc_close($this->process); } + while ($this->processPipes->hasOpenHandles()) { + usleep(100); + foreach ($this->processPipes->readAndCloseHandles(true) as $type => $data) { + if (3 == $type) { + $this->fallbackExitcode = (int) $data; + } else { + call_user_func($this->callback, $type === self::STDOUT ? self::OUT : self::ERR, $data); + } + } + } + $this->processPipes->close(); + $this->exitcode = $this->exitcode !== null ? $this->exitcode : -1; $this->exitcode = -1 != $exitcode ? $exitcode : $this->exitcode; From 37102dcc7c7c81e1b7e714626fafe528727f3434 Mon Sep 17 00:00:00 2001 From: Romain Neutron Date: Wed, 11 Sep 2013 21:09:08 +0200 Subject: [PATCH 3/9] [Process] Close unix pipes before calling `proc_close` to avoid a deadlock see http://php.net/manual/en/function.proc-close.php --- src/Symfony/Component/Process/Process.php | 5 +++++ .../Component/Process/ProcessPipes.php | 20 ++++++++++++++----- 2 files changed, 20 insertions(+), 5 deletions(-) diff --git a/src/Symfony/Component/Process/Process.php b/src/Symfony/Component/Process/Process.php index c0bc715d69..c9224d5e4c 100644 --- a/src/Symfony/Component/Process/Process.php +++ b/src/Symfony/Component/Process/Process.php @@ -310,8 +310,13 @@ class Process } $this->updateStatus(false); + // Unix pipes must be closed before calling proc_close to void deadlock + // see manual http://php.net/manual/en/function.proc-close.php + $this->processPipes->closeUnixPipes(); $exitcode = proc_close($this->process); + // Windows only : when using file handles, some activity may occur after + // calling proc_close while($this->processPipes->hasOpenHandles()) { usleep(100); foreach ($this->processPipes->readAndCloseHandles(true) as $type => $data) { diff --git a/src/Symfony/Component/Process/ProcessPipes.php b/src/Symfony/Component/Process/ProcessPipes.php index 3b29ae9e51..a0fe71c8c1 100644 --- a/src/Symfony/Component/Process/ProcessPipes.php +++ b/src/Symfony/Component/Process/ProcessPipes.php @@ -77,14 +77,24 @@ class ProcessPipes */ public function close() { - foreach ($this->pipes as $offset => $pipe) { - fclose($pipe); - } - + $this->closeUnixPipes(); foreach ($this->fileHandles as $offset => $handle) { fclose($handle); } - $this->fileHandles = $this->pipes = array(); + $this->fileHandles = array(); + } + + /** + * Closes unix pipes. + * + * Nothing happens in case file handles are used. + */ + public function closeUnixPipes() + { + foreach ($this->pipes as $pipe) { + fclose($pipe); + } + $this->pipes = array(); } /** From 610301d5e0b8abf4644b1bc904a3e8f3a6283330 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Thu, 12 Sep 2013 06:41:55 +0200 Subject: [PATCH 4/9] [FrameworkBundle] removed obsolete code --- .../DependencyInjection/FrameworkExtensionTest.php | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php index 00c0098a0d..a7bfb149e7 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/FrameworkExtensionTest.php @@ -296,13 +296,12 @@ abstract class FrameworkExtensionTest extends TestCase protected function createContainer(array $data = array()) { return new ContainerBuilder(new ParameterBag(array_merge(array( - 'kernel.bundles' => array('FrameworkBundle' => 'Symfony\\Bundle\\FrameworkBundle\\FrameworkBundle'), - 'kernel.cache_dir' => __DIR__, - 'kernel.compiled_classes' => array(), - 'kernel.debug' => false, - 'kernel.environment' => 'test', - 'kernel.name' => 'kernel', - 'kernel.root_dir' => __DIR__, + 'kernel.bundles' => array('FrameworkBundle' => 'Symfony\\Bundle\\FrameworkBundle\\FrameworkBundle'), + 'kernel.cache_dir' => __DIR__, + 'kernel.debug' => false, + 'kernel.environment' => 'test', + 'kernel.name' => 'kernel', + 'kernel.root_dir' => __DIR__, ), $data))); } From 2747bdca761c61f0a05c976aa05267034f73e602 Mon Sep 17 00:00:00 2001 From: Bernhard Schussek Date: Thu, 12 Sep 2013 09:25:54 +0200 Subject: [PATCH 5/9] [Form] Fixed regression in BooleanToStringTransformer from ed83752 --- .../Core/DataTransformer/BooleanToStringTransformer.php | 4 ++++ .../DataTransformer/BooleanToStringTransformerTest.php | 8 +++----- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/Symfony/Component/Form/Extension/Core/DataTransformer/BooleanToStringTransformer.php b/src/Symfony/Component/Form/Extension/Core/DataTransformer/BooleanToStringTransformer.php index f8e3b5bfcb..4f6b12275b 100644 --- a/src/Symfony/Component/Form/Extension/Core/DataTransformer/BooleanToStringTransformer.php +++ b/src/Symfony/Component/Form/Extension/Core/DataTransformer/BooleanToStringTransformer.php @@ -49,6 +49,10 @@ class BooleanToStringTransformer implements DataTransformerInterface */ public function transform($value) { + if (null === $value) { + return null; + } + if (!is_bool($value)) { throw new TransformationFailedException('Expected a Boolean.'); } diff --git a/src/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/BooleanToStringTransformerTest.php b/src/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/BooleanToStringTransformerTest.php index 4f6238aee0..a1217783d1 100644 --- a/src/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/BooleanToStringTransformerTest.php +++ b/src/Symfony/Component/Form/Tests/Extension/Core/DataTransformer/BooleanToStringTransformerTest.php @@ -38,12 +38,10 @@ class BooleanToStringTransformerTest extends \PHPUnit_Framework_TestCase $this->assertNull($this->transformer->transform(false)); } - /** - * @expectedException \Symfony\Component\Form\Exception\TransformationFailedException - */ - public function testTransformFailsIfNull() + // https://github.com/symfony/symfony/issues/8989 + public function testTransformAcceptsNull() { - $this->transformer->transform(null); + $this->assertNull($this->transformer->transform(null)); } /** From ce7de37f1623f7edde972cdbc7ad3c4d733e7bae Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Thu, 12 Sep 2013 08:52:33 +0200 Subject: [PATCH 6/9] [DependencyInjection] fixed a non-detected circular reference in PhpDumper (closes #8425) This circular reference cannot be detected by the compiler pass as we don't check for method arguments there. The Container itself already detects such circular references at runtime. So this fix is about circular references that are not detected at compile time, and are not even detected at runtime because the code that would cause the detection is never run (generated after a return statement.) --- .../DependencyInjection/Dumper/PhpDumper.php | 6 ++++++ .../Tests/Dumper/PhpDumperTest.php | 15 +++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php index 31be3f416b..37f29e8a88 100644 --- a/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php +++ b/src/Symfony/Component/DependencyInjection/Dumper/PhpDumper.php @@ -387,6 +387,12 @@ class PhpDumper extends Dumper continue; } + // if the instance is simple, the return statement has already been generated + // so, the only possible way to get there is because of a circular reference + if ($this->isSimpleInstance($id, $definition)) { + throw new ServiceCircularReferenceException($id, array($id)); + } + $name = (string) $this->definitionVariables->offsetGet($iDefinition); $code .= $this->addServiceMethodCalls(null, $iDefinition, $name); $code .= $this->addServiceProperties(null, $iDefinition, $name); diff --git a/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php b/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php index 369ac81bbe..44043268d3 100644 --- a/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php +++ b/src/Symfony/Component/DependencyInjection/Tests/Dumper/PhpDumperTest.php @@ -155,4 +155,19 @@ class PhpDumperTest extends \PHPUnit_Framework_TestCase $this->assertSame($bar, $container->get('foo')->bar, '->set() overrides an already defined service'); } + + /** + * @expectedException \Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException + */ + public function testCircularReference() + { + $container = new ContainerBuilder(); + $container->register('foo', 'stdClass')->addArgument(new Reference('bar')); + $container->register('bar', 'stdClass')->setPublic(false)->addMethodCall('setA', array(new Reference('baz'))); + $container->register('baz', 'stdClass')->addMethodCall('setA', array(new Reference('foo'))); + $container->compile(); + + $dumper = new PhpDumper($container); + $dumper->dump(); + } } From 867b81af5a8c699324526f9c2c8c286c88b61532 Mon Sep 17 00:00:00 2001 From: Bernhard Schussek Date: Thu, 12 Sep 2013 10:13:57 +0200 Subject: [PATCH 7/9] [Form] Fixed regression causing invalid "WHERE id IN ()" statements --- .../Form/ChoiceList/EntityChoiceList.php | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/Symfony/Bridge/Doctrine/Form/ChoiceList/EntityChoiceList.php b/src/Symfony/Bridge/Doctrine/Form/ChoiceList/EntityChoiceList.php index c3510515c5..189a90fa94 100644 --- a/src/Symfony/Bridge/Doctrine/Form/ChoiceList/EntityChoiceList.php +++ b/src/Symfony/Bridge/Doctrine/Form/ChoiceList/EntityChoiceList.php @@ -204,6 +204,16 @@ class EntityChoiceList extends ObjectChoiceList */ public function getChoicesForValues(array $values) { + // Performance optimization + // Also prevents the generation of "WHERE id IN ()" queries through the + // entity loader. At least with MySQL and on the development machine + // this was tested on, no exception was thrown for such invalid + // statements, consequently no test fails when this code is removed. + // https://github.com/symfony/symfony/pull/8981#issuecomment-24230557 + if (empty($values)) { + return array(); + } + if (!$this->loaded) { // Optimize performance in case we have an entity loader and // a single-field identifier @@ -247,6 +257,11 @@ class EntityChoiceList extends ObjectChoiceList */ public function getValuesForChoices(array $entities) { + // Performance optimization + if (empty($entities)) { + return array(); + } + if (!$this->loaded) { // Optimize performance for single-field identifiers. We already // know that the IDs are used as values @@ -282,6 +297,11 @@ class EntityChoiceList extends ObjectChoiceList */ public function getIndicesForChoices(array $entities) { + // Performance optimization + if (empty($entities)) { + return array(); + } + if (!$this->loaded) { // Optimize performance for single-field identifiers. We already // know that the IDs are used as indices @@ -317,6 +337,11 @@ class EntityChoiceList extends ObjectChoiceList */ public function getIndicesForValues(array $values) { + // Performance optimization + if (empty($values)) { + return array(); + } + if (!$this->loaded) { // Optimize performance for single-field identifiers. From 427ee19195315d65327cdbd7415e1649ff34e146 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Thu, 12 Sep 2013 14:08:32 +0200 Subject: [PATCH 8/9] [FrameworkBundle] fixed registration of the register listener pass --- src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php b/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php index 2919146d10..745bbb91f0 100644 --- a/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php +++ b/src/Symfony/Bundle/FrameworkBundle/FrameworkBundle.php @@ -60,7 +60,9 @@ class FrameworkBundle extends Bundle $container->addCompilerPass(new RoutingResolverPass()); $container->addCompilerPass(new ProfilerPass()); - $container->addCompilerPass(new RegisterKernelListenersPass(), PassConfig::TYPE_AFTER_REMOVING); + // must be registered before removing private services as some might be listeners/subscribers + // but as late as possible to get resolved parameters + $container->addCompilerPass(new RegisterKernelListenersPass(), PassConfig::TYPE_BEFORE_REMOVING); $container->addCompilerPass(new TemplatingPass()); $container->addCompilerPass(new AddConstraintValidatorsPass()); $container->addCompilerPass(new AddValidatorInitializersPass()); From 84443392dfe364e4ac31cd64e822c6fd6154bcb1 Mon Sep 17 00:00:00 2001 From: Fabien Potencier Date: Thu, 12 Sep 2013 14:09:39 +0200 Subject: [PATCH 9/9] [HttpKernel] added a check for private event listeners/subscribers --- .../Compiler/RegisterKernelListenersPass.php | 12 ++++++- .../RegisterKernelListenersPassTest.php | 34 +++++++++++++++++++ 2 files changed, 45 insertions(+), 1 deletion(-) diff --git a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/RegisterKernelListenersPass.php b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/RegisterKernelListenersPass.php index ad406eb6a3..4a152f575e 100644 --- a/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/RegisterKernelListenersPass.php +++ b/src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/RegisterKernelListenersPass.php @@ -25,6 +25,11 @@ class RegisterKernelListenersPass implements CompilerPassInterface $definition = $container->getDefinition('event_dispatcher'); foreach ($container->findTaggedServiceIds('kernel.event_listener') as $id => $events) { + $def = $container->getDefinition($id); + if (!$def->isPublic()) { + throw new \InvalidArgumentException(sprintf('The service "%s" must be public as event listeners are lazy-loaded.', $id)); + } + foreach ($events as $event) { $priority = isset($event['priority']) ? $event['priority'] : 0; @@ -45,8 +50,13 @@ class RegisterKernelListenersPass implements CompilerPassInterface } foreach ($container->findTaggedServiceIds('kernel.event_subscriber') as $id => $attributes) { + $def = $container->getDefinition($id); + if (!$def->isPublic()) { + throw new \InvalidArgumentException(sprintf('The service "%s" must be public as event subscribers are lazy-loaded.', $id)); + } + // We must assume that the class value has been correctly filled, even if the service is created by a factory - $class = $container->getDefinition($id)->getClass(); + $class = $def->getClass(); $refClass = new \ReflectionClass($class); $interface = 'Symfony\Component\EventDispatcher\EventSubscriberInterface'; diff --git a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/RegisterKernelListenersPassTest.php b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/RegisterKernelListenersPassTest.php index 670052fe1b..a0bbcdc3d8 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/RegisterKernelListenersPassTest.php +++ b/src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/RegisterKernelListenersPassTest.php @@ -31,6 +31,9 @@ class RegisterKernelListenersPassTest extends \PHPUnit_Framework_TestCase ); $definition = $this->getMock('Symfony\Component\DependencyInjection\Definition'); + $definition->expects($this->atLeastOnce()) + ->method('isPublic') + ->will($this->returnValue(true)); $definition->expects($this->atLeastOnce()) ->method('getClass') ->will($this->returnValue('stdClass')); @@ -60,6 +63,9 @@ class RegisterKernelListenersPassTest extends \PHPUnit_Framework_TestCase ); $definition = $this->getMock('Symfony\Component\DependencyInjection\Definition'); + $definition->expects($this->atLeastOnce()) + ->method('isPublic') + ->will($this->returnValue(true)); $definition->expects($this->atLeastOnce()) ->method('getClass') ->will($this->returnValue('Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\Compiler\SubscriberService')); @@ -81,6 +87,34 @@ class RegisterKernelListenersPassTest extends \PHPUnit_Framework_TestCase $registerListenersPass = new RegisterKernelListenersPass(); $registerListenersPass->process($builder); } + + /** + * @expectedException \InvalidArgumentException + * @expectedExceptionMessage The service "foo" must be public as event listeners are lazy-loaded. + */ + public function testPrivateEventListener() + { + $container = new ContainerBuilder(); + $container->register('foo', 'stdClass')->setPublic(false)->addTag('kernel.event_listener', array()); + $container->register('event_dispatcher', 'stdClass'); + + $registerListenersPass = new RegisterKernelListenersPass(); + $registerListenersPass->process($container); + } + + /** + * @expectedException \InvalidArgumentException + * @expectedExceptionMessage The service "foo" must be public as event subscribers are lazy-loaded. + */ + public function testPrivateEventSubscriber() + { + $container = new ContainerBuilder(); + $container->register('foo', 'stdClass')->setPublic(false)->addTag('kernel.event_subscriber', array()); + $container->register('event_dispatcher', 'stdClass'); + + $registerListenersPass = new RegisterKernelListenersPass(); + $registerListenersPass->process($container); + } } class SubscriberService implements \Symfony\Component\EventDispatcher\EventSubscriberInterface