Skip to content

Commit 3b1a977

Browse files
committed
[WebProfilerBundle] Try to display the most useful panel by default
1 parent 2b71c6f commit 3b1a977

File tree

3 files changed

+120
-5
lines changed

3 files changed

+120
-5
lines changed

src/Symfony/Bundle/WebProfilerBundle/Controller/ProfilerController.php

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
use Symfony\Component\HttpFoundation\Request;
1818
use Symfony\Component\HttpFoundation\Response;
1919
use Symfony\Component\HttpFoundation\Session\Flash\AutoExpireFlashBag;
20+
use Symfony\Component\HttpKernel\DataCollector\DumpDataCollector;
21+
use Symfony\Component\HttpKernel\DataCollector\ExceptionDataCollector;
2022
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
2123
use Symfony\Component\HttpKernel\Profiler\Profiler;
2224
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
@@ -78,7 +80,7 @@ public function panelAction(Request $request, $token)
7880
$this->cspHandler->disableCsp();
7981
}
8082

81-
$panel = $request->query->get('panel', 'request');
83+
$panel = $request->query->get('panel');
8284
$page = $request->query->get('page', 'home');
8385

8486
if ('latest' === $token && $latest = current($this->profiler->find(null, null, 1, null, null, null))) {
@@ -89,6 +91,22 @@ public function panelAction(Request $request, $token)
8991
return new Response($this->twig->render('@WebProfiler/Profiler/info.html.twig', ['about' => 'no_token', 'token' => $token, 'request' => $request]), 200, ['Content-Type' => 'text/html']);
9092
}
9193

94+
if (null === $panel) {
95+
$panel = 'request';
96+
97+
foreach ($profile->getCollectors() as $collector) {
98+
if ($collector instanceof ExceptionDataCollector && $collector->hasException()) {
99+
$panel = $collector->getName();
100+
101+
break;
102+
}
103+
104+
if ($collector instanceof DumpDataCollector && $collector->getDumpsCount() > 0) {
105+
$panel = $collector->getName();
106+
}
107+
}
108+
}
109+
92110
if (!$profile->hasCollector($panel)) {
93111
throw new NotFoundHttpException(sprintf('Panel "%s" is not available for token "%s".', $panel, $token));
94112
}

src/Symfony/Bundle/WebProfilerBundle/Resources/views/Profiler/base_js.html.twig

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -267,7 +267,7 @@
267267
if (request.profilerUrl) {
268268
profilerCell.textContent = '';
269269
var profilerLink = document.createElement('a');
270-
profilerLink.setAttribute('href', request.statusCode < 400 ? request.profilerUrl : request.profilerUrl + '?panel=exception');
270+
profilerLink.setAttribute('href', request.profilerUrl);
271271
profilerLink.textContent = request.profile;
272272
profilerCell.appendChild(profilerLink);
273273
}

src/Symfony/Bundle/WebProfilerBundle/Tests/Controller/ProfilerControllerTest.php

Lines changed: 100 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,17 @@
1515
use Symfony\Bundle\WebProfilerBundle\Controller\ProfilerController;
1616
use Symfony\Bundle\WebProfilerBundle\Csp\ContentSecurityPolicyHandler;
1717
use Symfony\Component\HttpFoundation\Request;
18+
use Symfony\Component\HttpFoundation\Response;
19+
use Symfony\Component\HttpKernel\DataCollector\DumpDataCollector;
20+
use Symfony\Component\HttpKernel\DataCollector\ExceptionDataCollector;
21+
use Symfony\Component\HttpKernel\DataCollector\RequestDataCollector;
1822
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
1923
use Symfony\Component\HttpKernel\Profiler\Profile;
24+
use Symfony\Component\HttpKernel\Profiler\Profiler;
25+
use Twig\Environment;
26+
use Twig\Loader\LoaderInterface;
27+
use Twig\Loader\SourceContextLoaderInterface;
28+
use Twig\Source;
2029

2130
class ProfilerControllerTest extends TestCase
2231
{
@@ -185,17 +194,105 @@ public function provideCspVariants()
185194
];
186195
}
187196

188-
private function createController($profiler, $twig, $withCSP): ProfilerController
197+
/**
198+
* @dataProvider defaultPanelProvider
199+
*/
200+
public function testDefaultPanel(string $expectedPanel, Profile $profile)
201+
{
202+
$profiler = $this->createMock(Profiler::class);
203+
$profiler
204+
->expects($this->atLeastOnce())
205+
->method('loadProfile')
206+
->with($profile->getToken())
207+
->willReturn($profile);
208+
209+
$profiler
210+
->expects($this->atLeastOnce())
211+
->method('has')
212+
->with($this->logicalXor($collectorsNames = array_keys($profile->getCollectors())))
213+
->willReturn(true);
214+
215+
if (Environment::MAJOR_VERSION > 1) {
216+
$loader = $this->createMock(LoaderInterface::class);
217+
$loader
218+
->expects($this->atLeastOnce())
219+
->method('exists')
220+
->with($this->logicalXor($expectedTemplate = 'expected_template.html.twig', 'other_template.html.twig'))
221+
->willReturn(true);
222+
} else {
223+
$loader = $this->createMock(SourceContextLoaderInterface::class);
224+
}
225+
226+
$twig = $this->createMock(Environment::class);
227+
$twig
228+
->expects($this->atLeastOnce())
229+
->method('getLoader')
230+
->willReturn($loader);
231+
$twig
232+
->expects($this->once())
233+
->method('render')
234+
->with($expectedTemplate);
235+
236+
$this
237+
->createController($profiler, $twig, false, array_map(function (string $collectorName) use ($expectedPanel, $expectedTemplate): array {
238+
if ($collectorName === $expectedPanel) {
239+
return [$expectedPanel, $expectedTemplate];
240+
}
241+
242+
return [$collectorName, 'other_template.html.twig'];
243+
}, $collectorsNames))
244+
->panelAction(new Request(), $profile->getToken());
245+
}
246+
247+
public function defaultPanelProvider(): \Generator
248+
{
249+
// Test default behavior
250+
$profile = new Profile('xxxxxx');
251+
$profile->addCollector($requestDataCollector = new RequestDataCollector());
252+
yield [$requestDataCollector->getName(), $profile];
253+
254+
// Test exception
255+
$profile = new Profile('xxxxxx');
256+
$profile->addCollector($exceptionDataCollector = new ExceptionDataCollector());
257+
$exceptionDataCollector->collect(new Request(), new Response(), new \DomainException());
258+
yield [$exceptionDataCollector->getName(), $profile];
259+
260+
// Test exception priority
261+
$dumpDataCollector = $this->createMock(DumpDataCollector::class);
262+
$dumpDataCollector
263+
->expects($this->atLeastOnce())
264+
->method('getName')
265+
->willReturn('dump');
266+
$dumpDataCollector
267+
->expects($this->atLeastOnce())
268+
->method('getDumpsCount')
269+
->willReturn(1);
270+
$profile = new Profile('xxxxxx');
271+
$profile->setCollectors([$exceptionDataCollector, $dumpDataCollector]);
272+
yield [$exceptionDataCollector->getName(), $profile];
273+
274+
// Test exception priority when defined afterwards
275+
$profile = new Profile('xxxxxx');
276+
$profile->setCollectors([$dumpDataCollector, $exceptionDataCollector]);
277+
yield [$exceptionDataCollector->getName(), $profile];
278+
279+
// Test dump
280+
$profile = new Profile('xxxxxx');
281+
$profile->addCollector($dumpDataCollector);
282+
yield [$dumpDataCollector->getName(), $profile];
283+
}
284+
285+
private function createController($profiler, $twig, $withCSP, array $templates = []): ProfilerController
189286
{
190287
$urlGenerator = $this->getMockBuilder('Symfony\Component\Routing\Generator\UrlGeneratorInterface')->getMock();
191288

192289
if ($withCSP) {
193290
$nonceGenerator = $this->getMockBuilder('Symfony\Bundle\WebProfilerBundle\Csp\NonceGenerator')->getMock();
194291
$nonceGenerator->method('generate')->willReturn('dummy_nonce');
195292

196-
return new ProfilerController($urlGenerator, $profiler, $twig, [], new ContentSecurityPolicyHandler($nonceGenerator));
293+
return new ProfilerController($urlGenerator, $profiler, $twig, $templates, new ContentSecurityPolicyHandler($nonceGenerator));
197294
}
198295

199-
return new ProfilerController($urlGenerator, $profiler, $twig, []);
296+
return new ProfilerController($urlGenerator, $profiler, $twig, $templates);
200297
}
201298
}

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy