From c45062b71a033ad70a431b1c4a3a554d80ea2e2a Mon Sep 17 00:00:00 2001 From: Alexander Schranz Date: Sat, 8 Dec 2018 15:55:26 +0000 Subject: [PATCH 01/10] fixed public directory of web server and assets install when configured in composer.json --- .../Command/AssetsInstallCommand.php | 30 ++++++++++++++++++- .../WebServerExtension.php | 23 ++++++++++++++ .../WebServerExtensionTest.php | 9 ++++++ .../Tests/DependencyInjection/composer.json | 6 ++++ 4 files changed, 67 insertions(+), 1 deletion(-) create mode 100644 src/Symfony/Bundle/WebServerBundle/Tests/DependencyInjection/composer.json diff --git a/src/Symfony/Bundle/FrameworkBundle/Command/AssetsInstallCommand.php b/src/Symfony/Bundle/FrameworkBundle/Command/AssetsInstallCommand.php index a52fe67aba..3e5800f9da 100644 --- a/src/Symfony/Bundle/FrameworkBundle/Command/AssetsInstallCommand.php +++ b/src/Symfony/Bundle/FrameworkBundle/Command/AssetsInstallCommand.php @@ -17,6 +17,7 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; use Symfony\Component\Console\Style\SymfonyStyle; +use Symfony\Component\DependencyInjection\ContainerInterface; use Symfony\Component\Filesystem\Exception\IOException; use Symfony\Component\Filesystem\Filesystem; use Symfony\Component\Finder\Finder; @@ -65,7 +66,7 @@ class AssetsInstallCommand extends ContainerAwareCommand { $this ->setDefinition(array( - new InputArgument('target', InputArgument::OPTIONAL, 'The target directory', 'public'), + new InputArgument('target', InputArgument::OPTIONAL, 'The target directory', null), )) ->addOption('symlink', null, InputOption::VALUE_NONE, 'Symlinks the assets instead of copying it') ->addOption('relative', null, InputOption::VALUE_NONE, 'Make relative symlinks') @@ -107,6 +108,10 @@ EOT $kernel = $this->getApplication()->getKernel(); $targetArg = rtrim($input->getArgument('target'), '/'); + if (!$targetArg) { + $targetArg = $this->getPublicDirectory($this->getContainer()); + } + if (!is_dir($targetArg)) { $targetArg = (isset($baseDir) ? $baseDir : $kernel->getContainer()->getParameter('kernel.project_dir')).'/'.$targetArg; @@ -288,4 +293,27 @@ EOT return self::METHOD_COPY; } + + private function getPublicDirectory(ContainerInterface $container) + { + $defaultPublicDir = 'public'; + + if (!$container->hasParameter('kernel.project_dir')) { + return $defaultPublicDir; + } + + $composerFilePath = $container->getParameter('kernel.project_dir').'/composer.json'; + + if (!file_exists($composerFilePath)) { + return $defaultPublicDir; + } + + $composerConfig = json_decode(file_get_contents($composerFilePath), true); + + if (isset($composerConfig['extra']['public-dir'])) { + return $composerConfig['extra']['public-dir']; + } + + return $defaultPublicDir; + } } diff --git a/src/Symfony/Bundle/WebServerBundle/DependencyInjection/WebServerExtension.php b/src/Symfony/Bundle/WebServerBundle/DependencyInjection/WebServerExtension.php index 3dc492dcd1..bf08a2bac9 100644 --- a/src/Symfony/Bundle/WebServerBundle/DependencyInjection/WebServerExtension.php +++ b/src/Symfony/Bundle/WebServerBundle/DependencyInjection/WebServerExtension.php @@ -27,8 +27,31 @@ class WebServerExtension extends Extension $loader = new XmlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config')); $loader->load('webserver.xml'); + $publicDirectory = $this->getPublicDirectory($container); + $container->getDefinition('web_server.command.server_run')->replaceArgument(0, $publicDirectory); + $container->getDefinition('web_server.command.server_start')->replaceArgument(0, $publicDirectory); + if (!class_exists(ConsoleFormatter::class)) { $container->removeDefinition('web_server.command.server_log'); } } + + private function getPublicDirectory(ContainerBuilder $container) + { + $kernelProjectDir = $container->getParameter('kernel.project_dir'); + $publicDir = 'public'; + $composerFilePath = $kernelProjectDir.'/composer.json'; + + if (!file_exists($composerFilePath)) { + return $kernelProjectDir.'/'.$publicDir; + } + + $composerConfig = json_decode(file_get_contents($composerFilePath), true); + + if (isset($composerConfig['extra']['public-dir'])) { + $publicDir = $composerConfig['extra']['public-dir']; + } + + return $kernelProjectDir.'/'.$publicDir; + } } diff --git a/src/Symfony/Bundle/WebServerBundle/Tests/DependencyInjection/WebServerExtensionTest.php b/src/Symfony/Bundle/WebServerBundle/Tests/DependencyInjection/WebServerExtensionTest.php index ebc0c9421f..0d9c2f4bd5 100644 --- a/src/Symfony/Bundle/WebServerBundle/Tests/DependencyInjection/WebServerExtensionTest.php +++ b/src/Symfony/Bundle/WebServerBundle/Tests/DependencyInjection/WebServerExtensionTest.php @@ -21,8 +21,17 @@ class WebServerExtensionTest extends TestCase public function testLoad() { $container = new ContainerBuilder(); + $container->setParameter('kernel.project_dir', __DIR__); (new WebServerExtension())->load(array(), $container); + $this->assertSame( + __DIR__.'/test', + $container->getDefinition('web_server.command.server_run')->getArgument(0) + ); + $this->assertSame( + __DIR__.'/test', + $container->getDefinition('web_server.command.server_start')->getArgument(0) + ); $this->assertTrue($container->hasDefinition('web_server.command.server_run')); $this->assertTrue($container->hasDefinition('web_server.command.server_start')); $this->assertTrue($container->hasDefinition('web_server.command.server_stop')); diff --git a/src/Symfony/Bundle/WebServerBundle/Tests/DependencyInjection/composer.json b/src/Symfony/Bundle/WebServerBundle/Tests/DependencyInjection/composer.json new file mode 100644 index 0000000000..a4652ebdf8 --- /dev/null +++ b/src/Symfony/Bundle/WebServerBundle/Tests/DependencyInjection/composer.json @@ -0,0 +1,6 @@ +{ + "name": "test-composer.json", + "extra": { + "public-dir": "test" + } +} From f58338e2515a5bdaee1bca434c03be5870983459 Mon Sep 17 00:00:00 2001 From: Daniel Wehner Date: Thu, 13 Dec 2018 15:18:21 +0000 Subject: [PATCH 02/10] EventSubscriberInterface isn't a man --- .../Component/EventDispatcher/EventSubscriberInterface.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/EventDispatcher/EventSubscriberInterface.php b/src/Symfony/Component/EventDispatcher/EventSubscriberInterface.php index 8af778919b..6e1976b86a 100644 --- a/src/Symfony/Component/EventDispatcher/EventSubscriberInterface.php +++ b/src/Symfony/Component/EventDispatcher/EventSubscriberInterface.php @@ -12,7 +12,7 @@ namespace Symfony\Component\EventDispatcher; /** - * An EventSubscriber knows himself what events he is interested in. + * An EventSubscriber knows itself what events it is interested in. * If an EventSubscriber is added to an EventDispatcherInterface, the manager invokes * {@link getSubscribedEvents} and registers the subscriber as a listener for all * returned events. From 8caab72f5ec8b587f9d0c73f9a6751a7d41cbb06 Mon Sep 17 00:00:00 2001 From: Daniel Wehner Date: Thu, 13 Dec 2018 16:34:04 +0000 Subject: [PATCH 03/10] Don't use he in docs when its not needed --- .../Component/EventDispatcher/EventDispatcherInterface.php | 2 +- src/Symfony/Component/Form/Extension/Core/Type/ChoiceType.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/EventDispatcher/EventDispatcherInterface.php b/src/Symfony/Component/EventDispatcher/EventDispatcherInterface.php index d3d0cb8a45..8a547da57a 100644 --- a/src/Symfony/Component/EventDispatcher/EventDispatcherInterface.php +++ b/src/Symfony/Component/EventDispatcher/EventDispatcherInterface.php @@ -46,7 +46,7 @@ interface EventDispatcherInterface /** * Adds an event subscriber. * - * The subscriber is asked for all the events he is + * The subscriber is asked for all the events it is * interested in and added as a listener for these events. */ public function addSubscriber(EventSubscriberInterface $subscriber); diff --git a/src/Symfony/Component/Form/Extension/Core/Type/ChoiceType.php b/src/Symfony/Component/Form/Extension/Core/Type/ChoiceType.php index a7e8025a07..00eb88f7c3 100644 --- a/src/Symfony/Component/Form/Extension/Core/Type/ChoiceType.php +++ b/src/Symfony/Component/Form/Extension/Core/Type/ChoiceType.php @@ -396,7 +396,7 @@ class ChoiceType extends AbstractType if ($options['multiple']) { $choiceType = __NAMESPACE__.'\CheckboxType'; // The user can check 0 or more checkboxes. If required - // is true, he is required to check all of them. + // is true, they are required to check all of them. $choiceOpts['required'] = false; } else { $choiceType = __NAMESPACE__.'\RadioType'; From d4e426c46645a0dd30b1b0d16378c0af03fcfc3e Mon Sep 17 00:00:00 2001 From: Frank de Jonge Date: Fri, 14 Dec 2018 10:32:06 +0100 Subject: [PATCH 04/10] Renamed test controller from Controller to TestController so it doesn't show up in the IDE autocomplete. --- src/Symfony/Component/HttpKernel/Tests/HttpKernelTest.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Component/HttpKernel/Tests/HttpKernelTest.php b/src/Symfony/Component/HttpKernel/Tests/HttpKernelTest.php index 4b9ec69d1e..239865a861 100644 --- a/src/Symfony/Component/HttpKernel/Tests/HttpKernelTest.php +++ b/src/Symfony/Component/HttpKernel/Tests/HttpKernelTest.php @@ -200,7 +200,7 @@ class HttpKernelTest extends TestCase public function testHandleWhenTheControllerIsAnObjectWithInvoke() { $dispatcher = new EventDispatcher(); - $kernel = $this->getHttpKernel($dispatcher, new Controller()); + $kernel = $this->getHttpKernel($dispatcher, new TestController()); $this->assertResponseEquals(new Response('foo'), $kernel->handle(new Request())); } @@ -216,7 +216,7 @@ class HttpKernelTest extends TestCase public function testHandleWhenTheControllerIsAnArray() { $dispatcher = new EventDispatcher(); - $kernel = $this->getHttpKernel($dispatcher, array(new Controller(), 'controller')); + $kernel = $this->getHttpKernel($dispatcher, array(new TestController(), 'controller')); $this->assertResponseEquals(new Response('foo'), $kernel->handle(new Request())); } @@ -224,7 +224,7 @@ class HttpKernelTest extends TestCase public function testHandleWhenTheControllerIsAStaticArray() { $dispatcher = new EventDispatcher(); - $kernel = $this->getHttpKernel($dispatcher, array('Symfony\Component\HttpKernel\Tests\Controller', 'staticcontroller')); + $kernel = $this->getHttpKernel($dispatcher, array('Symfony\Component\HttpKernel\Tests\TestController', 'staticcontroller')); $this->assertResponseEquals(new Response('foo'), $kernel->handle(new Request())); } @@ -381,7 +381,7 @@ class HttpKernelTest extends TestCase } } -class Controller +class TestController { public function __invoke() { From 732b86317da09f1c3fffdc827557d06e429c4279 Mon Sep 17 00:00:00 2001 From: Valentin Date: Fri, 14 Dec 2018 13:34:58 +0300 Subject: [PATCH 05/10] [Form] Fixed FormErrorIterator class phpdoc --- src/Symfony/Component/Form/FormErrorIterator.php | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Component/Form/FormErrorIterator.php b/src/Symfony/Component/Form/FormErrorIterator.php index 919b615969..a534918406 100644 --- a/src/Symfony/Component/Form/FormErrorIterator.php +++ b/src/Symfony/Component/Form/FormErrorIterator.php @@ -19,10 +19,9 @@ use Symfony\Component\Validator\ConstraintViolation; /** * Iterates over the errors of a form. * - * Optionally, this class supports recursive iteration. In order to iterate - * recursively, set the constructor argument $deep to true. Now each element - * returned by the iterator is either an instance of {@link FormError} or of - * {@link FormErrorIterator}, in case the errors belong to a sub-form. + * This class supports recursive iteration. In order to iterate recursively, + * pass a structure of {@link FormError} and {@link FormErrorIterator} objects + * to the $errors constructor argument. * * You can also wrap the iterator into a {@link \RecursiveIteratorIterator} to * flatten the recursive structure into a flat list of errors. From 93a0c98cc22100bff372de5d0263b710b7bd840c Mon Sep 17 00:00:00 2001 From: Tri Pham Date: Fri, 14 Dec 2018 14:56:19 +0700 Subject: [PATCH 06/10] Vietnamese translations improvement --- .../Resources/translations/security.vi.xlf | 2 +- .../Resources/translations/validators.vi.xlf | 18 +++++++++--------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/src/Symfony/Component/Security/Core/Resources/translations/security.vi.xlf b/src/Symfony/Component/Security/Core/Resources/translations/security.vi.xlf index b85a43995f..93723bb43e 100644 --- a/src/Symfony/Component/Security/Core/Resources/translations/security.vi.xlf +++ b/src/Symfony/Component/Security/Core/Resources/translations/security.vi.xlf @@ -48,7 +48,7 @@ Username could not be found. - Không tìm thấy tên người dùng username. + Không tìm thấy tên người dùng. Account has expired. diff --git a/src/Symfony/Component/Validator/Resources/translations/validators.vi.xlf b/src/Symfony/Component/Validator/Resources/translations/validators.vi.xlf index e1833c79cb..750a4d91e2 100644 --- a/src/Symfony/Component/Validator/Resources/translations/validators.vi.xlf +++ b/src/Symfony/Component/Validator/Resources/translations/validators.vi.xlf @@ -40,7 +40,7 @@ This field is missing. - Lĩnh vực này là mất tích. + Lĩnh vực này bị thiếu. This value is not a valid date. @@ -132,7 +132,7 @@ This file is not a valid image. - Tập tin không phải là hình ảnh. + Tập tin không phải là hình ảnh hợp lệ. This is not a valid IP address. @@ -148,7 +148,7 @@ This value is not a valid country. - Giá trị không phải là nước hợp lệ. + Giá trị không phải là quốc gia hợp lệ. This value is already used. @@ -180,7 +180,7 @@ This value should have exactly {{ limit }} character.|This value should have exactly {{ limit }} characters. - Giá trị phải có chính xác {{ limit }} kí tự.|Giá trị phải có chính xác {{ limit }} kí tự. + Giá trị này phải có chính xác {{ limit }} kí tự.|Giá trị này phải có chính xác {{ limit }} kí tự. The file was only partially uploaded. @@ -204,11 +204,11 @@ This collection should contain {{ limit }} element or more.|This collection should contain {{ limit }} elements or more. - Danh sách phải chứa {{ limit }} hoặc nhiều hơn thành phần.|Danh sách phải chứa {{ limit }} hoặc nhiều hơn thành phần. + Danh sách phải chứa {{ limit }} thành phần hoặc nhiều hơn.|Danh sách phải chứa {{ limit }} thành phần hoặc nhiều hơn. This collection should contain {{ limit }} element or less.|This collection should contain {{ limit }} elements or less. - Danh sách phải chứa {{ limit }} hoặc ít hơn thành phần.|Danh sách phải chứa {{ limit }} hoặc ít hơn thành phần. + Danh sách phải chứa {{ limit }} thành phần hoặc ít hơn.|Danh sách phải chứa {{ limit }} thành phần hoặc ít hơn. This collection should contain exactly {{ limit }} element.|This collection should contain exactly {{ limit }} elements. @@ -240,11 +240,11 @@ This value is not a valid ISSN. - Giá trị không là ISSN hợp lệ. + Giá trị không phải là ISSN hợp lệ. This value is not a valid currency. - Giá trị không phải là đơn vi tiền tệ hợp lệ. + Giá trị không phải là đơn vị tiền tệ hợp lệ. This value should be equal to {{ compared_value }}. @@ -268,7 +268,7 @@ This value should be less than or equal to {{ compared_value }}. - Giá trị không được phép nhỏ hơn hoặc bằng {{ compared_value }}. + Giá trị phải nhỏ hơn hoặc bằng {{ compared_value }}. This value should not be equal to {{ compared_value }}. From b9359a57ece7e4e1184c798a58e9ce4510ac550e Mon Sep 17 00:00:00 2001 From: Andreas Hasenack Date: Thu, 13 Dec 2018 11:08:50 -0200 Subject: [PATCH 07/10] Adjust tests to work in the armhf architecture. Fixes #29281. --- .../Component/VarDumper/Tests/Caster/SplCasterTest.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Component/VarDumper/Tests/Caster/SplCasterTest.php b/src/Symfony/Component/VarDumper/Tests/Caster/SplCasterTest.php index d3c9ec25f5..1aa8461268 100644 --- a/src/Symfony/Component/VarDumper/Tests/Caster/SplCasterTest.php +++ b/src/Symfony/Component/VarDumper/Tests/Caster/SplCasterTest.php @@ -35,7 +35,7 @@ SplFileInfo { aTime: %s-%s-%d %d:%d:%d mTime: %s-%s-%d %d:%d:%d cTime: %s-%s-%d %d:%d:%d - inode: %d + inode: %i size: %d perms: 0%d owner: %d @@ -85,7 +85,7 @@ SplFileObject { aTime: %s-%s-%d %d:%d:%d mTime: %s-%s-%d %d:%d:%d cTime: %s-%s-%d %d:%d:%d - inode: %d + inode: %i size: %d perms: 0%d owner: %d @@ -105,7 +105,7 @@ SplFileObject { maxLineLen: 0 fstat: array:26 [ "dev" => %d - "ino" => %d + "ino" => %i "nlink" => %d "rdev" => 0 "blksize" => %i From 8e2bd35dcae1f9de728760a9b52cf7f8609bcdde Mon Sep 17 00:00:00 2001 From: Maxime Steinhausser Date: Sat, 15 Dec 2018 11:33:10 +0100 Subject: [PATCH 08/10] [Console] OutputFormatter: move strtolower to createStyleFromString While playing with the href feature that'll be available in 4.3, I spotted href value is lowercased. Which I guess could be an issue on case-sensitive filesystems. This changes nothing for the current branch, but will allow when merging to upper branches to fix the behavior described above, hence keep original case. --- .../Component/Console/Formatter/OutputFormatter.php | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/Symfony/Component/Console/Formatter/OutputFormatter.php b/src/Symfony/Component/Console/Formatter/OutputFormatter.php index 57b95eb140..b9af0b3cca 100644 --- a/src/Symfony/Component/Console/Formatter/OutputFormatter.php +++ b/src/Symfony/Component/Console/Formatter/OutputFormatter.php @@ -157,7 +157,7 @@ class OutputFormatter implements OutputFormatterInterface if (!$open && !$tag) { // $this->styleStack->pop(); - } elseif (false === $style = $this->createStyleFromString(strtolower($tag))) { + } elseif (false === $style = $this->createStyleFromString($tag)) { $output .= $this->applyCurrentStyle($text); } elseif ($open) { $this->styleStack->push($style); @@ -203,13 +203,14 @@ class OutputFormatter implements OutputFormatterInterface $style = new OutputFormatterStyle(); foreach ($matches as $match) { array_shift($match); + $match[0] = strtolower($match[0]); if ('fg' == $match[0]) { - $style->setForeground($match[1]); + $style->setForeground(strtolower($match[1])); } elseif ('bg' == $match[0]) { - $style->setBackground($match[1]); + $style->setBackground(strtolower($match[1])); } elseif ('options' === $match[0]) { - preg_match_all('([^,;]+)', $match[1], $options); + preg_match_all('([^,;]+)', strtolower($match[1]), $options); $options = array_shift($options); foreach ($options as $option) { try { From a8eba803a35994628387678d6d3890f0f4f2bc56 Mon Sep 17 00:00:00 2001 From: Robin Chalas Date: Sat, 15 Dec 2018 11:27:20 +0100 Subject: [PATCH 09/10] [Security] Prefer clone over unserialize(serialize()) for user refreshment --- .../Component/Security/Http/Firewall/ContextListener.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Symfony/Component/Security/Http/Firewall/ContextListener.php b/src/Symfony/Component/Security/Http/Firewall/ContextListener.php index cdaebbca75..fb279791f8 100644 --- a/src/Symfony/Component/Security/Http/Firewall/ContextListener.php +++ b/src/Symfony/Component/Security/Http/Firewall/ContextListener.php @@ -170,7 +170,7 @@ class ContextListener implements ListenerInterface try { $refreshedUser = $provider->refreshUser($user); - $newToken = unserialize(serialize($token)); + $newToken = clone $token; $newToken->setUser($refreshedUser); // tokens can be deauthenticated if the user has been changed. From 2570d6f877538b0cb402b250aac21a6969c03a6d Mon Sep 17 00:00:00 2001 From: Roland Franssen Date: Sat, 1 Dec 2018 18:19:47 +0100 Subject: [PATCH 10/10] [EventDispatcher] Revers event tracing order --- .../Debug/TraceableEventDispatcher.php | 42 ++++++++++++------- .../Debug/TraceableEventDispatcherTest.php | 18 ++++---- 2 files changed, 36 insertions(+), 24 deletions(-) diff --git a/src/Symfony/Component/EventDispatcher/Debug/TraceableEventDispatcher.php b/src/Symfony/Component/EventDispatcher/Debug/TraceableEventDispatcher.php index 967bb9fba1..1696f66b6a 100644 --- a/src/Symfony/Component/EventDispatcher/Debug/TraceableEventDispatcher.php +++ b/src/Symfony/Component/EventDispatcher/Debug/TraceableEventDispatcher.php @@ -29,7 +29,7 @@ class TraceableEventDispatcher implements TraceableEventDispatcherInterface protected $logger; protected $stopwatch; - private $called; + private $callStack; private $dispatcher; private $wrappedListeners; @@ -38,7 +38,6 @@ class TraceableEventDispatcher implements TraceableEventDispatcherInterface $this->dispatcher = $dispatcher; $this->stopwatch = $stopwatch; $this->logger = $logger; - $this->called = array(); $this->wrappedListeners = array(); } @@ -123,6 +122,10 @@ class TraceableEventDispatcher implements TraceableEventDispatcherInterface */ public function dispatch($eventName, Event $event = null) { + if (null === $this->callStack) { + $this->callStack = new \SplObjectStorage(); + } + if (null === $event) { $event = new Event(); } @@ -158,11 +161,15 @@ class TraceableEventDispatcher implements TraceableEventDispatcherInterface */ public function getCalledListeners() { + if (null === $this->callStack) { + return array(); + } + $called = array(); - foreach ($this->called as $eventName => $listeners) { - foreach ($listeners as $listener) { - $called[$eventName.'.'.$listener->getPretty()] = $listener->getInfo($eventName); - } + foreach ($this->callStack as $listener) { + list($eventName) = $this->callStack->getInfo(); + + $called[] = $listener->getInfo($eventName); } return $called; @@ -188,9 +195,9 @@ class TraceableEventDispatcher implements TraceableEventDispatcherInterface foreach ($allListeners as $eventName => $listeners) { foreach ($listeners as $listener) { $called = false; - if (isset($this->called[$eventName])) { - foreach ($this->called[$eventName] as $l) { - if ($l->getWrappedListener() === $listener) { + if (null !== $this->callStack) { + foreach ($this->callStack as $calledListener) { + if ($calledListener->getWrappedListener() === $listener) { $called = true; break; @@ -202,19 +209,19 @@ class TraceableEventDispatcher implements TraceableEventDispatcherInterface if (!$listener instanceof WrappedListener) { $listener = new WrappedListener($listener, null, $this->stopwatch, $this); } - $notCalled[$eventName.'.'.$listener->getPretty()] = $listener->getInfo($eventName); + $notCalled[] = $listener->getInfo($eventName); } } } - uasort($notCalled, array($this, 'sortListenersByPriority')); + uasort($notCalled, array($this, 'sortNotCalledListeners')); return $notCalled; } public function reset() { - $this->called = array(); + $this->callStack = array(); } /** @@ -258,6 +265,7 @@ class TraceableEventDispatcher implements TraceableEventDispatcherInterface $this->wrappedListeners[$eventName][] = $wrappedListener; $this->dispatcher->removeListener($eventName, $listener); $this->dispatcher->addListener($eventName, $wrappedListener, $priority); + $this->callStack->attach($wrappedListener, array($eventName)); } } @@ -286,8 +294,8 @@ class TraceableEventDispatcher implements TraceableEventDispatcherInterface if (!isset($this->called[$eventName])) { $this->called[$eventName] = new \SplObjectStorage(); } - - $this->called[$eventName]->attach($listener); + } else { + $this->callStack->detach($listener); } if (null !== $this->logger && $skipped) { @@ -304,8 +312,12 @@ class TraceableEventDispatcher implements TraceableEventDispatcherInterface } } - private function sortListenersByPriority($a, $b) + private function sortNotCalledListeners(array $a, array $b) { + if (0 !== $cmp = strcmp($a['event'], $b['event'])) { + return $cmp; + } + if (\is_int($a['priority']) && !\is_int($b['priority'])) { return 1; } diff --git a/src/Symfony/Component/EventDispatcher/Tests/Debug/TraceableEventDispatcherTest.php b/src/Symfony/Component/EventDispatcher/Tests/Debug/TraceableEventDispatcherTest.php index d7c5ce18cc..a7efcafa96 100644 --- a/src/Symfony/Component/EventDispatcher/Tests/Debug/TraceableEventDispatcherTest.php +++ b/src/Symfony/Component/EventDispatcher/Tests/Debug/TraceableEventDispatcherTest.php @@ -110,17 +110,17 @@ class TraceableEventDispatcherTest extends TestCase $tdispatcher->addListener('foo', function () {}, 5); $listeners = $tdispatcher->getNotCalledListeners(); - $this->assertArrayHasKey('stub', $listeners['foo.closure']); - unset($listeners['foo.closure']['stub']); + $this->assertArrayHasKey('stub', $listeners[0]); + unset($listeners[0]['stub']); $this->assertEquals(array(), $tdispatcher->getCalledListeners()); - $this->assertEquals(array('foo.closure' => array('event' => 'foo', 'pretty' => 'closure', 'priority' => 5)), $listeners); + $this->assertEquals(array(array('event' => 'foo', 'pretty' => 'closure', 'priority' => 5)), $listeners); $tdispatcher->dispatch('foo'); $listeners = $tdispatcher->getCalledListeners(); - $this->assertArrayHasKey('stub', $listeners['foo.closure']); - unset($listeners['foo.closure']['stub']); - $this->assertEquals(array('foo.closure' => array('event' => 'foo', 'pretty' => 'closure', 'priority' => 5)), $listeners); + $this->assertArrayHasKey('stub', $listeners[0]); + unset($listeners[0]['stub']); + $this->assertEquals(array(array('event' => 'foo', 'pretty' => 'closure', 'priority' => 5)), $listeners); $this->assertEquals(array(), $tdispatcher->getNotCalledListeners()); } @@ -133,10 +133,10 @@ class TraceableEventDispatcherTest extends TestCase $tdispatcher->reset(); $listeners = $tdispatcher->getNotCalledListeners(); - $this->assertArrayHasKey('stub', $listeners['foo.closure']); - unset($listeners['foo.closure']['stub']); + $this->assertArrayHasKey('stub', $listeners[0]); + unset($listeners[0]['stub']); $this->assertEquals(array(), $tdispatcher->getCalledListeners()); - $this->assertEquals(array('foo.closure' => array('event' => 'foo', 'pretty' => 'closure', 'priority' => 5)), $listeners); + $this->assertEquals(array(array('event' => 'foo', 'pretty' => 'closure', 'priority' => 5)), $listeners); } public function testGetCalledListenersNested()