8000 feature #10200 [EventDispatcher] simplified code for TraceableEventDi… · symfony/symfony@fe86efd · GitHub
[go: up one dir, main page]

Skip to content
.hEHvLI{min-width:0;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;}/*!sc*/ .bmcJak{min-width:0;}/*!sc*/ .fyKNMY[data-size="medium"]{color:var(--fgColor-default,var(--color-fg-default,#1F2328));}/*!sc*/ .gUkoLg{-webkit-box-pack:center;-webkit-justify-content:center;-ms-flex-pack:center;justify-content:center;}/*!sc*/ .dpBUfI{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row;-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;}/*!sc*/ @media screen and (min-width:544px){.dpBUfI{-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;}}/*!sc*/ @media screen and (min-width:768px){.dpBUfI{-webkit-flex-wrap:wrap;-ms-flex-wrap:wrap;flex-wrap:wrap;}}/*!sc*/ @media screen and (min-width:1012px){.dpBUfI{-webkit-flex-wrap:nowrap;-ms-flex-wrap:nowrap;flex-wrap:nowrap;}}/*!sc*/ .hKWjvQ{display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;-webkit-flex-direction:row;-ms-flex-direction:row;flex-direction:row;-webkit-align-items:center;-webkit-box-align:center;-ms-flex-align:center;align-items:center;}/*!sc*/ .cvdqJW{width:20px;height:20px;margin-right:8px;margin-top:-1px;margin-left:1px;}/*!sc*/ .dkaFxu{font-weight:600;white-space:nowrap;color:var(--fgColor-default,var(--color-fg-default,#1F2328));}/*!sc*/ .dkaFxu:hover{color:var(--fgColor-default,var(--color-fg-default,#1F2328));-webkit-text-decoration:underline;text-decoration:underline;}/*!sc*/ .irPhWZ{width:60px;}/*!sc*/ .dNbsEP{width:62px;}/*!sc*/ .kHfwUD{width:60px;height:22px;}/*!sc*/ .bHLmSv{position:absolute;inset:0 -2px;cursor:col-resize;background-color:transparent;-webkit-transition-delay:0.1s;transition-delay:0.1s;}/*!sc*/ .bHLmSv:hover{background-color:var(--bgColor-neutral-muted,var(--color-neutral-muted,rgba(175,184,193,0.2)));}/*!sc*/ .hqtbbn{bottom:0 !important;-webkit-clip:rect(1px,1px,1px,1px);clip:rect(1px,1px,1px,1px);-webkit-clip-path:inset(50%);clip-path:inset(50%);height:84px;position:absolute;width:320px;}/*!sc*/ data-styled.g1[id="Box-sc-g0xbh4-0"]{content:"hEHvLI,bmcJak,fyKNMY,gUkoLg,dpBUfI,hKWjvQ,cvdqJW,dkaFxu,irPhWZ,dNbsEP,kHfwUD,bHLmSv,hqtbbn,"}/*!sc*/ .brGdpi{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;-webkit-clip:rect(0,0,0,0);clip:rect(0,0,0,0);white-space:nowrap;border-width:0;}/*!sc*/ data-styled.g4[id="_VisuallyHidden__VisuallyHidden-sc-11jhm7a-0"]{content:"brGdpi,"}/*!sc*/ .jjwhNb{position:relative;display:inline-block;display:-webkit-box;display:-webkit-flex;display:-ms-flexbox;display:flex;}/*!sc*/ .jjwhNb::after{position:absolute;z-index:1000000;display:none;padding:0.5em 0.75em;font:normal normal 11px/1.5 -apple-system,BlinkMacSystemFont,"Segoe UI","Noto Sans",Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji";-webkit-font-smoothing:subpixel-antialiased;color:var(--tooltip-fgColor,var(--fgColor-onEmphasis,var(--color-fg-on-emphasis,#ffffff)));text-align:center;-webkit-text-decoration:none;text-decoration:none;text-shadow:none;text-transform:none;-webkit-letter-spacing:normal;-moz-letter-spacing:normal;-ms-letter-spacing:normal;letter-spacing:normal;word-wrap:break-word;white-space:pre;pointer-events:none;content:attr(aria-label);background:var(--tooltip-bgColor,var(--bgColor-emphasis,var(--color-neutral-emphasis-plus,#24292f)));border-radius:6px;opacity:0;}/*!sc*/ @-webkit-keyframes tooltip-appear{from{opacity:0;}to{opacity:1;}}/*!sc*/ @keyframes tooltip-appear{from{opacity:0;}to{opacity:1;}}/*!sc*/ .jjwhNb:hover::after,.jjwhNb:active::after,.jjwhNb:focus::after,.jjwhNb:focus-within::after{display:inline-block;-webkit-text-decoration:none;text-decoration:none;-webkit-animation-name:tooltip-appear;animation-name:tooltip-appear;-webkit-animation-duration:0.1s;animation-duration:0.1s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in;-webkit-animation-delay:0s;animation-delay:0s;}/*!sc*/ .jjwhNb.tooltipped-no-delay:hover::after,.jjwhNb.tooltipped-no-delay:active::after,.jjwhNb.tooltipped-no-delay:focus::after,.jjwhNb.tooltipped-no-delay:focus-within::after{-webkit-animation-delay:0s;animation-delay:0s;}/*!sc*/ .jjwhNb.tooltipped-multiline:hover::after,.jjwhNb.tooltipped-multiline:active::after,.jjwhNb.tooltipped-multiline:focus::after,.jjwhNb.tooltipped-multiline:focus-within::after{display:table-cell;}/*!sc*/ .jjwhNb.tooltipped-s::after,.jjwhNb.tooltipped-se::after,.jjwhNb.tooltipped-sw::after{top:100%;right:50%;margin-top:6px;}/*!sc*/ .jjwhNb.tooltipped-se::after{right:auto;left:50%;margin-left:-16px;}/*!sc*/ .jjwhNb.tooltipped-sw::after{margin-right:-16px;}/*!sc*/ .jjwhNb.tooltipped-n::after,.jjwhNb.tooltipped-ne::after,.jjwhNb.tooltipped-nw::after{right:50%;bottom:100%;margin-bottom:6px;}/*!sc*/ .jjwhNb.tooltipped-ne::after{right:auto;left:50%;margin-left:-16px;}/*!sc*/ .jjwhNb.tooltipped-nw::after{margin-right:-16px;}/*!sc*/ .jjwhNb.tooltipped-s::after,.jjwhNb.tooltipped-n::after{-webkit-transform:translateX(50%);-ms-transform:translateX(50%);transform:translateX(50%);}/*!sc*/ .jjwhNb.tooltipped-w::after{right:100%;bottom:50%;margin-right:6px;-webkit-transform:translateY(50%);-ms-transform:translateY(50%);transform:translateY(50%);}/*!sc*/ .jjwhNb.tooltipped-e::after{bottom:50%;left:100%;margin-left:6px;-webkit-transform:translateY(50%);-ms-transform:translateY(50%);transform:translateY(50%);}/*!sc*/ .jjwhNb.tooltipped-multiline::after{width:-webkit-max-content;width:-moz-max-content;width:max-content;max-width:250px;word-wrap:break-word;white-space:pre-line;border-collapse:separate;}/*!sc*/ .jjwhNb.tooltipped-multiline.tooltipped-s::after,.jjwhNb.tooltipped-multiline.tooltipped-n::after{right:auto;left:50%;-webkit-transform:translateX(-50%);-ms-transform:translateX(-50%);transform:translateX(-50%);}/*!sc*/ .jjwhNb.tooltipped-multiline.tooltipped-w::after,.jjwhNb.tooltipped-multiline.tooltipped-e::after{right:100%;}/*!sc*/ .jjwhNb.tooltipped-align-right-2::after{right:0;margin-right:0;}/*!sc*/ .jjwhNb.tooltipped-align-left-2::after{left:0;margin-left:0;}/*!sc*/ .hWlpPn{position:relative;display:inline-block;}/*!sc*/ .hWlpPn::after{position:absolute;z-index:1000000;display:none;padding:0.5em 0.75em;font:normal normal 11px/1.5 -apple-system,BlinkMacSystemFont,"Segoe UI","Noto Sans",Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji";-webkit-font-smoothing:subpixel-antialiased;color:var(--tooltip-fgColor,var(--fgColor-onEmphasis,var(--color-fg-on-emphasis,#ffffff)));text-align:center;-webkit-text-decoration:none;text-decoration:none;text-shadow:none;text-transform:none;-webkit-letter-spacing:normal;-moz-letter-spacing:normal;-ms-letter-spacing:normal;letter-spacing:normal;word-wrap:break-word;white-space:pre;pointer-events:none;content:attr(aria-label);background:var(--tooltip-bgColor,var(--bgColor-emphasis,var(--color-neutral-emphasis-plus,#24292f)));border-radius:6px;opacity:0;}/*!sc*/ @-webkit-keyframes tooltip-appear{from{opacity:0;}to{opacity:1;}}/*!sc*/ @keyframes tooltip-appear{from{opacity:0;}to{opacity:1;}}/*!sc*/ .hWlpPn:hover::after,.hWlpPn:active::after,.hWlpPn:focus::after,.hWlpPn:focus-within::after{display:inline-block;-webkit-text-decoration:none;text-decoration:none;-webkit-animation-name:tooltip-appear;animation-name:tooltip-appear;-webkit-animation-duration:0.1s;animation-duration:0.1s;-webkit-animation-fill-mode:forwards;animation-fill-mode:forwards;-webkit-animation-timing-function:ease-in;animation-timing-function:ease-in;-webkit-animation-delay:0s;animation-delay:0s;}/*!sc*/ .hWlpPn.tooltipped-no-delay:hover::after,.hWlpPn.tooltipped-no-delay:active::after,.hWlpPn.tooltipped-no-delay:focus::after,.hWlpPn.tooltipped-no-delay:focus-within::after{-webkit-animation-delay:0s;animation-delay:0s;}/*!sc*/ .hWlpPn.tooltipped-multiline:hover::after,.hWlpPn.tooltipped-multiline:active::after,.hWlpPn.tooltipped-multiline:focus::after,.hWlpPn.tooltipped-multiline:focus-within::after{display:table-cell;}/*!sc*/ .hWlpPn.tooltipped-s::after,.hWlpPn.tooltipped-se::after,.hWlpPn.tooltipped-sw::after{top:100%;right:50%;margin-top:6px;}/*!sc*/ .hWlpPn.tooltipped-se::after{right:auto;left:50%;margin-left:-16px;}/*!sc*/ .hWlpPn.tooltipped-sw::after{margin-right:-16px;}/*!sc*/ .hWlpPn.tooltipped-n::after,.hWlpPn.tooltipped-ne::after,.hWlpPn.tooltipped-nw::after{right:50%;bottom:100%;margin-bottom:6px;}/*!sc*/ .hWlpPn.tooltipped-ne::after{right:auto;left:50%;margin-left:-16px;}/*!sc*/ .hWlpPn.tooltipped-nw::after{margin-right:-16px;}/*!sc*/ .hWlpPn.tooltipped-s::after,.hWlpPn.tooltipped-n::after{-webkit-transform:translateX(50%);-ms-transform:translateX(50%);transform:translateX(50%);}/*!sc*/ .hWlpPn.tooltipped-w::after{right:100%;bottom:50%;margin-right:6px;-webkit-transform:translateY(50%);-ms-transform:translateY(50%);transform:translateY(50%);}/*!sc*/ .hWlpPn.tooltipped-e::after{bottom:50%;left:100%;margin-left:6px;-webkit-transform:translateY(50%);-ms-transform:translateY(50%);transform:translateY(50%);}/*!sc*/ .hWlpPn.tooltipped-multiline::after{width:-webkit-max-content;width:-moz-max-content;width:max-content;max-width:250px;word-wrap:break-word;white-space:pre-line;border-collapse:separate;}/*!sc*/ .hWlpPn.tooltipped-multiline.tooltipped-s::after,.hWlpPn.tooltipped-multiline.tooltipped-n::after{right:auto;left:50%;-webkit-transform:translateX(-50%);-ms-transform:translateX(-50%);transform:translateX(-50%);}/*!sc*/ .hWlpPn.tooltipped-multiline.tooltipped-w::after,.hWlpPn.tooltipped-multiline.tooltipped-e::after{right:100%;}/*!sc*/ .hWlpPn.tooltipped-align-right-2::after{right:0;margin-right:0;}/*!sc*/ .hWlpPn.tooltipped-align-left-2::after{left:0;margin-left:0;}/*!sc*/ data-styled.g5[id="Tooltip__TooltipBase-sc-17tf59c-0"]{content:"jjwhNb,hWlpPn,"}/*!sc*/ .irithh{position:relative;overflow:hidden;-webkit-mask-image:radial-gradient(white,black);mask-image:radial-gradient(white,black);background-color:var(--bgColor-neutral-muted,var(--color-neutral-subtle,rgba(234,238,242,0.5)));border-radius:3px;display:block;height:1.2em;width:60px;}/*!sc*/ .irithh::after{-webkit-animation:crVFvv 1.5s infinite linear;animation:crVFvv 1.5s infinite linear;background:linear-gradient(90deg,transparent,var(--bgColor-neutral-muted,var(--color-neutral-subtle,rgba(234,238,242,0.5))),transparent);content:'';position:absolute;-webkit-transform:translateX(-100%);-ms-transform:translateX(-100%);transform:translateX(-100%);bottom:0;left:0;right:0;top:0;}/*!sc*/ .ihfxfT{position:relative;overflow:hidden;-webkit-mask-image:radial-gradient(white,black);mask-image:radial-gradient(white,black);background-color:var(--bgColor-neutral-muted,var(--color-neutral-subtle,rgba(234,238,242,0.5)));border-radius:3px;display:block;height:1.2em;width:62px;}/*!sc*/ .ihfxfT::after{-webkit-animation:crVFvv 1.5s infinite linear;animation:crVFvv 1.5s infinite linear;background:linear-gradient(90deg,transparent,var(--bgColor-neutral-muted,var(--color-neutral-subtle,rgba(234,238,242,0.5))),transparent);content:'';position:absolute;-webkit-transform:translateX(-100%);-ms-transform:translateX(-100%);transform:translateX(-100%);bottom:0;left:0;right:0;top:0;}/*!sc*/ .kRBfod{position:relative;overflow:hidden;-webkit-mask-image:radial-gradient(white,black);mask-image:radial-gradient(white,black);background-color:var(--bgColor-neutral-muted,var(--color-neutral-subtle,rgba(234,238,242,0.5)));border-radius:3px;display:block;height:1.2em;width:60px;height:22px;}/*!sc*/ .kRBfod::after{-webkit-animation:crVFvv 1.5s infinite linear;animation:crVFvv 1.5s infinite linear;background:linear-gradient(90deg,transparent,var(--bgColor-neutral-muted,var(--color-neutral-subtle,rgba(234,238,242,0.5))),transparent);content:'';position:absolute;-webkit-transform:translateX(-100%);-ms-transform:translateX(-100%);transform:translateX(-100%);bottom:0;left:0;right:0;top:0;}/*!sc*/ data-styled.g27[id="LoadingSkeleton-sc-695d630a-0"]{content:"irithh,ihfxfT,kRBfod,"}/*!sc*/ @-webkit-keyframes crVFvv{0%{-webkit-transform:translateX(-100%);-ms-transform:translateX(-100%);transform:translateX(-100%);}50%{-webkit-transform:translateX(100%);-ms-transform:translateX(100%);transform:translateX(100%);}100%{-webkit-transform:translateX(100%);-ms-transform:translateX(100%);transform:translateX(100%);}}/*!sc*/ @keyframes crVFvv{0%{-webkit-transform:translateX(-100%);-ms-transform:translateX(-100%);transform:translateX(-100%);}50%{-webkit-transform:translateX(100%);-ms-transform:translateX(100%);transform:translateX(100%);}100%{-webkit-transform:translateX(100%);-ms-transform:translateX(100%);transform:translateX(100%);}}/*!sc*/ data-styled.g53[id="sc-keyframes-crVFvv"]{content:"crVFvv,"}/*!sc*/

Commit fe86efd

Browse files
committed
feature #10200 [EventDispatcher] simplified code for TraceableEventDispatcher (fabpot)
This PR was merged into the 2.5-dev branch. Discussion ---------- [EventDispatcher] simplified code for TraceableEventDispatcher | Q | A | ------------- | --- | Bug fix? | no | New feature? | no | BC breaks? | no | Deprecations? | no | Tests pass? | yes | Fixed tickets | n/a | License | MIT | Doc PR | n/a Commits ------- 42e4c7b [EventDispatcher] simplified code for TraceableEventDispatcher
2 parents 6dfdb97 + 42e4c7b commit fe86efd

File tree

3 files changed

+146
-147
lines changed

3 files changed

+146
-147
lines changed

src/Symfony/Component/EventDispatcher/Debug/TraceableEventDispatcher.php

Lines changed: 77 additions & 143 deletions
Original file line numberDiff line numberDiff line change
@@ -28,11 +28,9 @@ class TraceableEventDispatcher implements TraceableEventDispatcherInterface
2828
{
2929
protected $logger;
3030
protected $stopwatch;
31-
private $called = array();
31+
32+
private $called;
3233
private $dispatcher;
33-
private $wrappedListeners = array();
34-
private $firstCalledEvent = array();
35-
private $lastEventId = 0;
3634

3735
/**
3836
* Constructor.
@@ -46,6 +44,7 @@ public function __construct(EventDispatcherInterface $dispatcher, Stopwatch $sto
4644
$this->dispatcher = $dispatcher;
4745
$this->stopwatch = $stopwatch;
4846
$this->logger = $logger;
47+
$this->called = array();
4948
}
5049

5150
/**
@@ -105,47 +104,19 @@ public function dispatch($eventName, Event $event = null)
105104
$event = new Event();
106105
}
107106

108-
$eventId = ++$this->lastEventId;
109-
110-
// Wrap all listeners before they are called
111-
$this->wrappedListeners[$eventId] = new \SplObjectStorage();
112-
113-
$listeners = $this->dispatcher->getListeners($eventName);
114-
115-
foreach ($listeners as $listener) {
116-
$this->dispatcher->removeListener($eventName, $listener);
117-
$wrapped = $this->wrapListener($eventName, $eventId, $listener);
118-
$this->wrappedListeners[$eventId][$wrapped] = $listener;
119-
$this->dispatcher->addListener($eventName, $wrapped);
120-
}
121-
107+
$this->preProcess($eventName);
122108
$this->preDispatch($eventName, $event);
123109

124110
$e = $this->stopwatch->start($eventName, 'section');
125111

126-
$this->firstCalledEvent[$eventName] = $this->stopwatch->start($eventName.'.loading', 'event_listener_loading');
127-
128-
if (!$this->dispatcher->hasListeners($eventName)) {
129-
$this->firstCalledEvent[$eventName]->stop();
130-
}
131-
132112
$this->dispatcher->dispatch($eventName, $event);
133113

134-
unset($this->firstCalledEvent[$eventName]);
135-
136114
if ($e->isStarted()) {
137115
$e->stop();
138116
}
139117

140118
$this->postDispatch($eventName, $event);
141-
142-
// Unwrap all listeners after they are called
143-
foreach ($this->wrappedListeners[$eventId] as $wrapped) {
144-
$this->dispatcher->removeListener($eventName, $wrapped);
145-
$this->dispatcher->addListener($eventName, $this->wrappedListeners[$eventId][$wrapped]);
146-
}
147-
148-
unset($this->wrappedListeners[$eventId]);
119+
$this->postProcess($eventName);
149120

150121
return $event;
151122
}
@@ -155,7 +126,15 @@ public function dispatch($eventName, Event $event = null)
155126
*/
156127
public function getCalledListeners()
157128
{
158-
return $this->called;
129+
$called = array();
130+
foreach ($this->called as $eventName => $listeners) {
131+
foreach ($listeners as $listener) {
132+
$info = $this->getListenerInfo($listener->getWrappedListener(), $eventName);
133+
$called[$eventName.'.'.$info['pretty']] = $info;
134+
}
135+
}
136+
137+
return $called;
159138
}
160139

161140
/**
@@ -164,12 +143,22 @@ public function getCalledListeners()
164143
public function getNotCalledListeners()
165144
{
166145
$notCalled = array();
167-
168-
foreach ($this->getListeners() as $name => $listeners) {
146+
foreach ($this->getListeners() as $eventName => $listeners) {
169147
foreach ($listeners as $listener) {
170-
$info = $this->getListenerInfo($listener, $name, null);
171-
if (!isset($this->called[$name.'.'.$info['pretty']])) {
172-
$notCalled[$name.'.'.$info['pretty']] = $info;
148+
$called = false;
149+
if (isset($this->called[$eventName])) {
150+
foreach ($this->called[$eventName] as $l) {
151+
if ($l->getWrappedListener() === $listener) {
152+
$called = true;
153+
154+
break;
155+
}
156+
}
157+
}
158+
159+
if (!$called) {
160+
$info = $this->getListenerInfo($listener, $eventName);
161+
$notCalled[$eventName.'.'.$info['pretty']] = $info;
173162
}
174163
}
175164
}
@@ -191,64 +180,68 @@ public function __call($method, $arguments)
191180
}
192181

193182
/**
194-
* This is a private method and must not be used.
183+
* Called before dispatching the event.
195184
*
196-
* This method is public because it is used in a closure.
197-
* Whenever Symfony will require PHP 5.4, this could be changed
198-
* to a proper private method.
185+
* @param string $eventName The event name
186+
* @param Event $event The event
199187
*/
200-
public function logSkippedListeners($eventName, $eventId, Event $event, $listener)
188+
protected function preDispatch($eventName, Event $event)
201189
{
202-
if (null === $this->logger) {
203-
return;
204-
}
205-
206-
$info = $this->getListenerInfo($listener, $eventName, $eventId);
207-
208-
$this->logger->debug(sprintf('Listener "%s" stopped propagation of the event "%s".', $info['pretty'], $eventName));
209-
210-
$skippedListeners = $this->getListeners($eventName);
211-
$skipped = false;
212-
213-
foreach ($skippedListeners as $skippedListener) {
214-
$skippedListener = $this->unwrapListener($skippedListener, $eventId);
215-
216-
if ($skipped) {
217-
$info = $this->getListenerInfo($skippedListener, $eventName, $eventId);
218-
$this->logger->debug(sprintf('Listener "%s" was not called for event "%s".', $info['pretty'], $eventName));
219-
}
220-
221-
if ($skippedListener === $listener) {
222-
$skipped = true;
223-
}
224-
}
225190
}
226191

227192
/**
228-
* This is a private method.
193+
* Called after dispatching the event.
229194
*
230-
* This method is public because it is used in a closure.
231-
* Whenever Symfony will require PHP 5.4, this could be changed
232-
* to a proper private method.
195+
* @param string $eventName The event name
196+
* @param Event $event The event
233197
*/
234-
public function preListenerCall($eventName, $eventId, $listener)
198+
protected function postDispatch($eventName, Event $event)
235199
{
236-
// is it the first called listener?
237-
if (isset($this->firstCalledEvent[$eventName])) {
238-
$this->firstCalledEvent[$eventName]->stop();
200+
}
239201

240-
unset($this->firstCalledEvent[$eventName]);
202+
private function preProcess($eventName)
203+
{
204+
foreach ($this->dispatcher->getListeners($eventName) as $listener) {
205+
$this->dispatcher->removeListener($eventName, $listener);
206+
$info = $this->getListenerInfo($listener, $eventName);
207+
$name = isset($info['class']) ? $info['class'] : $info['type'];
208+
$this->dispatcher->addListener($eventName, new WrappedListener($listener, $name, $this->stopwatch));
241209
}
210+
}
242211

243-
$info = $this->getListenerInfo($listener, $eventName, $eventId);
212+
private function postProcess($eventName)
213+
{
214+
$skipped = false;
215+
foreach ($this->dispatcher->getListeners($eventName) as $listener) {
216+
// Unwrap listener
217+
$this->dispatcher->removeListener($eventName, $listener);
218+
$this->dispatcher->addListener($eventName, $listener->getWrappedListener());
244219

245-
if (null !== $this->logger) {
246-
$this->logger->debug(sprintf('Notified event "%s" to listener "%s".', $eventName, $info['pretty']));
247-
}
220+
$info = $this->getListenerInfo($listener->getWrappedListener(), $eventName);
221+
if ($listener->wasCalled()) {
222+
if (null !== $this->logger) {
223+
$this->logger->debug(sprintf('Notified event "%s" to listener "%s".', $eventName, $info['pretty']));
224+
}
225+
226+
if (!isset($this->called[$eventName])) {
227+
$this->called[$eventName] = new \SplObjectStorage();
228+
}
248229

249-
$this->called[$eventName.'.'.$info['pretty']] = $info;
230+
$this->called[$eventName]->attach($listener);
231+
}
232+
233+
if (null !== $this->logger && $skipped) {
234+
$this->logger->debug(sprintf('Listener "%s" was not called for event "%s".', $info['pretty'], $eventName));
235+
}
250236

251-
return $this->stopwatch->start(isset($info['class']) ? $info['class'] : $info['type'], 'event_listener');
237+
if ($listener->stoppedPropagation()) {
238+
if (null !== $this->logger) {
239+
$this->logger->debug(sprintf('Listener "%s" stopped propagation of the event "%s".', $info['pretty'], $eventName));
240+
}
241+
242+
$skipped = true;
243+
}
244+
}
252245
}
253246

254247
/**
@@ -259,10 +252,8 @@ public function preListenerCall($eventName, $eventId, $listener)
259252
*
260253
* @return array Information about the listener
261254
*/
262-
private function getListenerInfo($listener, $eventName, $eventId)
255+
private function getListenerInfo($listener, $eventName)
263256
{
264-
$listener = $this->unwrapListener($listener, $eventId);
265-
266257
$info = array(
267258
'event' => $eventName,
268259
);
@@ -312,61 +303,4 @@ private function getListenerInfo($listener, $eventName, $eventId)
312303

313304
return $info;
314305
}
315-
316-
/**
317-
* Called before dispatching the event.
318-
*
319-
* @param string $eventName The event name
320-
* @param Event $event The event
321-
*/
322-
protected function preDispatch($eventName, Event $event)
323-
{
324-
}
325-
326-
/**
327-
* Called after dispatching the event.
328-
*
329-
* @param string $eventName The event name
330-
* @param Event $event The event
331-
*/
332-
protected function postDispatch($eventName, Event $event)
333-
{
334-
}
335-
336-
private function wrapListener($eventName, $eventId, $listener)
337-
{
338-
$self = $this;
339-
340-
return function (Event $event) use ($self, $eventName, $eventId, $listener) {
341-
$e = $self->preListenerCall($eventName, $eventId, $listener);
342-
343-
call_user_func($listener, $event, $eventName, $self);
344-
345-
if ($e->isStarted()) {
346-
$e->stop();
347-
}
348-
349-
if ($event->isPropagationStopped()) {
350-
$self->logSkippedListeners($eventName, $eventId, $event, $listener);
351-
}
352-
};
353-
}
354-
355-
private function unwrapListener($listener, $eventId)
356-
{
357-
// get the original listener
358-
if (is_object($listener)) {
359-
if (null === $eventId) {
360-
foreach (array_keys($this->wrappedListeners) as $eventId) {
361-
if (isset($this->wrappedListeners[$eventId][$listener])) {
362-
return $this->wrappedListeners[$eventId][$listener];
363-
}
364-
}
365-
} elseif (isset($this->wrappedListeners[$eventId][$listener])) {
366-
return $this->wrappedListeners[$eventId][$listener];
367-
}
368-
}
369-
370-
return $listener;
371-
}
372306
}
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Symfony package.
5+
*
6+
* (c) Fabien Potencier <fabien@symfony.com>
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
namespace Symfony\Component\EventDispatcher\Debug;
13+
14+
use Symfony\Component\Stopwatch\Stopwatch;
15+
use Symfony\Component\EventDispatcher\Event;
16+
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
17+
18+
/**
19+
* @author Fabien Potencier <fabien@symfony.com>
20+
*/
21+
class WrappedListener
22+
{
23+
private $listener;
24+
private $name;
25+
private $called;
26+
private $stoppedPropagation;
27+
private $stopwatch;
28+
29+
public function __construct($listener, $name, Stopwatch $stopwatch)
30+
{
31+
$this->listener = $listener;
32+
$this->name = $name;
33+
$this->stopwatch = $stopwatch;
34+
$this->called = false;
35+
$this->stoppedPropagation = false;
36+
}
37+
38+
public function getWrappedListener()
39+
{
40+
return $this->listener;
41+
}
42+
43+
public function wasCalled()
44+
{
45+
return $this->called;
46+
}
47+
48+
public function stoppedPropagation()
49+
{
50+
return $this->stoppedPropagation;
51+
}
52+
53+
public function __invoke(Event $event, $eventName, EventDispatcherInterface $dispatcher)
54+
{
55+
$this->called = true;
56+
57+
$e = $this->stopwatch->start($this->name, 'event_listener');
58+
59+
call_user_func($this->listener, $event, $eventName, $dispatcher);
60+
61+
if ($e->isStarted()) {
62+
$e->stop();
63+
}
64+
65+
if ($event->isPropagationStopped()) {
66+
$this->stoppedPropagation = true;
67+
}
68+
}
69+
}

src/Symfony/Component/HttpKernel/Tests/Debug/TraceableEventDispatcherTest.php

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,14 +32,10 @@ public function testStopwatchSections()
3232
$this->assertEquals(array(
3333
'__section__',
3434
'kernel.request',
35-
'kernel.request.loading',
3635
'kernel.controller',
37-
'kernel.controller.loading',
3836
'controller',
3937
'kernel.response',
40-
'kernel.response.loading',
4138
'kernel.terminate',
42-
'kernel.terminate.loading',
4339
), array_keys($events));
4440
}
4541

0 commit comments

Comments
 (0)
0