8000 bug #35240 [SecurityBundle] Fix collecting traceable listeners info o… · symfony/symfony@d68a4b0 · GitHub
[go: up one dir, main page]

Skip to content
8000

Commit d68a4b0

Browse files
committed
bug #35240 [SecurityBundle] Fix collecting traceable listeners info on lazy firewalls (chalasr)
This PR was merged into the 4.4 branch. Discussion ---------- [SecurityBundle] Fix collecting traceable listeners info on lazy firewalls | Q | A | ------------- | --- | Branch? | 4.4 | Bug fix? | yes | New feature? | no | Deprecations? | no | Tickets | - | License | MIT | Doc PR | - Before: ![Screenshot 2020-01-07 at 05 17 47](https://user-images.githubusercontent.com/7502063/71869007-cbffd400-3110-11ea-86ad-234da28621c4.png) After: ![Screenshot 2020-01-07 at 05 18 12](https://user-images.githubusercontent.com/7502063/71869014-d9b55980-3110-11ea-8efc-1f1b16b2c372.png) Commits ------- a3a9a0e [SecurityBundle] Fix collecting traceable listeners info using anonymous: lazy
2 parents b0e11e8 + a3a9a0e commit d68a4b0

File tree

4 files changed

+156
-47
lines changed

4 files changed

+156
-47
lines changed

src/Symfony/Bundle/SecurityBundle/Debug/TraceableFirewallListener.php

Lines changed: 40 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,10 @@
1212
namespace Symfony\Bundle\SecurityBundle\Debug;
1313

1414
use Symfony\Bundle\SecurityBundle\EventListener\FirewallListener;
15+
use Symfony\Bundle\SecurityBundle\Security\FirewallContext;
16+
use Symfony\Bundle\SecurityBundle\Security\LazyFirewallContext;
1517
use Symfony\Component\HttpKernel\Event\RequestEvent;
18+
use Symfony\Component\Security\Http\Firewall\AbstractListener;
1619

1720
/**
1821
* Firewall collecting called listeners.
@@ -21,7 +24,7 @@
2124
*/
2225
final class TraceableFirewallListener extends FirewallListener
2326
{
24-
private $wrappedListeners;
27+
private $wrappedListeners = [];
2528

2629
public function getWrappedListeners()
2730
{
@@ -30,14 +33,47 @@ public function getWrappedListeners()
3033

3134
protected function callListeners(RequestEvent $event, iterable $listeners)
3235
{
36+
$wrappedListeners = [];
37+
$wrappedLazyListeners = [];
38+
3339
foreach ($listeners as $listener) {
34-
$wrappedListener = new WrappedListener($listener);
35-
$wrappedListener($event);
36-
$this->wrappedListeners[] = $wrappedListener->getInfo();
40+
if ($listener instanceof LazyFirewallContext) {
41+
\Closure::bind(function () use (&$wrappedLazyListeners, &$wrappedListeners) {
42+
$listeners = [];
43+
foreach ($this->listeners as $listener) {
44+
if ($listener instanceof AbstractListener) {
45+
$listener = new WrappedLazyListener($listener);
46+
$listeners[] = $listener;
47+
$wrappedLazyListeners[] = $listener;
48+
} else {
49+
$listeners[] = function (RequestEvent $event) use ($listener, &$wrappedListeners) {
50+
$wrappedListener = new WrappedListener($listener);
51+
$wrappedListener($event);
52+
$wrappedListeners[] = $wrappedListener->getInfo();
53+
};
54+
}
55+
}
56+
$this->listeners = $listeners;
57+
}, $listener, FirewallContext::class)();
58+
59+
$listener($event);
60+
} else {
61+
$wrappedListener = $listener instanceof AbstractListener ? new WrappedLazyListener($listener) : new WrappedListener($listener);
62+
$wrappedListener($event);
63+
$wrappedListeners[] = $wrappedListener->getInfo();
64+
}
3765

3866
if ($event->hasResponse()) {
3967
break;
4068
}
4169
}
70+
71+
if ($wrappedLazyListeners) {
72+
foreach ($wrappedLazyListeners as $lazyListener) {
73+
$this->wrappedListeners[] = $lazyListener->getInfo();
74+
}
75+
}
76+
77+
$this->wrappedListeners = array_merge($this->wrappedListeners, $wrappedListeners);
4278
}
4379
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
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\Bundle\SecurityBundle\Debug;
13+
14+
use Symfony\Component\Security\Http\Firewall\LegacyListenerTrait;
15+
16+
/**
17+
* @author Robin Chalas <robin.chalas@gmail.com>
18+
*
19+
* @internal
20+
*/
21+
trait TraceableListenerTrait
22+
{
23+
use LegacyListenerTrait;
24+
25+
private $response;
26+
private $listener;
27+
private $time;
28+
private $stub;
29+
30+
/**
31+
* Proxies all method calls to the original listener.
32+
*/
33+
public function __call(string $method, array $arguments)
34+
{
35+
return $this->listener->{$method}(...$arguments);
36+
}
37+
38+
public function getWrappedListener()
39+
{
40+
return $this->listener;
41+
}
42+
}
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
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\Bundle\SecurityBundle\Debug;
13+
14+
use Symfony\Component\HttpFoundation\Request;
15+
use Symfony\Component\HttpKernel\Event\RequestEvent;
16+
use Symfony\Component\Security\Core\Exception\LazyResponseException;
17+
use Symfony\Component\Security\Http\Firewall\AbstractListener;
18+
use Symfony\Component\Security\Http\Firewall\ListenerInterface;
19+
use Symfony\Component\VarDumper\Caster\ClassStub;
20+
21+
/**
22+
* Wraps a lazy security listener.
23+
*
24+
* @author Robin Chalas <robin.chalas@gmail.com>
25+
*
26+
* @internal
27+
*/
28+
final class WrappedLazyListener extends AbstractListener implements ListenerInterface
29+
{
30+
use TraceableListenerTrait;
31+
32+
public function __construct(AbstractListener $listener)
33+
{
34+
$this->listener = $listener;
35+
}
36+
37+
public function supports(Request $request): ?bool
38+
{
39+
return $this->listener->supports($request);
40+
}
41+
42+
/**
43+
* {@inheritdoc}
44+
*/
45+
public function authenticate(RequestEvent $event)
46+
{
47+
$startTime = microtime(true);
48+
49+
try {
50+
$ret = $this->listener->authenticate($event);
51+
} catch (LazyResponseException $e) {
52+
$this->response = $e->getResponse();
53+
54+
throw $e;
55+
} finally {
56+
$this->time = microtime(true) - $startTime;
57+
}
58+
59+
$this->response = $event->getResponse();
60+
61+
return $ret;
62+
}
63+
64+
public function getInfo(): array
65+
{
66+
return [
67+
'response' => $this->response,
68+
'time' => $this->time,
69+
'stub' => $this->stub ?? $this->stub = ClassStub::wrapCallable($this->listener),
70+
];
71+
}
72+
}

src/Symfony/Bundle/SecurityBundle/Debug/WrappedListener.php

Lines changed: 2 additions & 43 deletions
28
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
namespace Symfony\Bundle\SecurityBundle\Debug;
1313

1414
use Symfony\Component\HttpKernel\Event\RequestEvent;
15-
use Symfony\Component\Security\Http\Firewall\LegacyListenerTrait;
1615
use Symfony\Component\Security\Http\Firewall\ListenerInterface;
1716
use Symfony\Component\VarDumper\Caster\ClassStub;
1817

2524
*/
2625
final class WrappedListener implements ListenerInterface
2726
{
-
use LegacyListenerTrait;
29-
30-
private $response;
31-
private $listener;
32-
private $time;
33-
private $stub;
34-
private static $hasVarDumper;
27+
use TraceableListenerTrait;
3528

3629
/**
3730
* @param callable $listener
@@ -57,46 +50,12 @@ public function __invoke(RequestEvent $event)
5750
$this->response = $event->getResponse();
5851
}
5952

60-
/**
61-
* Proxies all method calls to the original listener.
62-
*/
63-
public function __call(string $method, array $arguments)
64-
{
65-
return $this->listener->{$method}(...$arguments);
66-
}
67-
68-
public function getWrappedListener()
69-
{
70-
return $this->listener;
71-
}
72-
7353
public function getInfo(): array
7454
{
75-
if (null !== $this->stub) {
76-
// no-op
77-
} elseif (self::$hasVarDumper ?? self::$hasVarDumper = class_exists(ClassStub::class)) {
78-
$this->stub = ClassStub::wrapCallable($this->listener);
79-
} elseif (\is_array($this->listener)) {
80-
$this->stub = (\is_object($this->listener[0]) ? \get_class($this->listener[0]) : $this->listener[0]).'::'.$this->listener[1];
81-
} elseif ($this->listener instanceof \Closure) {
82-
$r = new \ReflectionFunction($this->listener);
83-
if (false !== strpos($r->name, '{closure}')) {
84-
$this->stub = 'closure';
85-
} elseif ($class = $r->getClosureScopeClass()) {
86-
$this->stub = $class->name.'::'.$r->name;
87-
} else {
88-
$this->stub = $r->name;
89-
}
90-
} elseif (\is_string($this->listener)) {
91-
$this->stub = $this->listener;
92-
} else {
93-
$this->stub = \get_class($this->listener).'::__invoke';
94-
}
95-
9655
return [
9756
'response' => $this->response,
9857
'time' => $this->time,
99-
'stub' => $this->stub,
58+
'stub' => $this->stub ?? $this->stub = ClassStub::wrapCallable($this->listener),
10059
];
10160
}
10261
}

0 commit comments

Comments
 (0)
0