Skip to content

Commit 986a0a2

Browse files
committed
[FrameworkBundle] Allow to leverage autoconfiguration for DataCollectors with template
1 parent 31c194f commit 986a0a2

File tree

5 files changed

+135
-3
lines changed

5 files changed

+135
-3
lines changed

src/Symfony/Bundle/FrameworkBundle/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ CHANGELOG
88
* Added `framework.trusted_proxies` and `framework.trusted_headers` configuration options
99
* Deprecated the public `form.factory`, `form.type.file`, `translator`, `security.csrf.token_manager`, `serializer`,
1010
`cache_clearer`, `filesystem` and `validator` services to private.
11+
* Added `TemplateAwareDataCollectorInterface` and `AbstractDataCollector` to simplify custom data collector creation and leverage autoconfiguration
1112

1213
5.1.0
1314
-----
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
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\FrameworkBundle\DataCollector;
13+
14+
/**
15+
* @author Laurent VOULLEMIER <laurent.voullemier@gmail.com>
16+
*/
17+
abstract class AbstractDataCollector implements TemplateAwareDataCollectorInterface
18+
{
19+
/**
20+
* @var array
21+
*/
22+
protected $data = [];
23+
24+
public function getName(): string
25+
{
26+
return static::class;
27+
}
28+
29+
public function reset(): void
30+
{
31+
$this->data = [];
32+
}
33+
34+
public static function getTemplate(): ?string
35+
{
36+
return null;
37+
}
38+
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
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\FrameworkBundle\DataCollector;
13+
14+
use Symfony\Component\HttpKernel\DataCollector\DataCollectorInterface;
15+
16+
/**
17+
* @author Laurent VOULLEMIER <laurent.voullemier@gmail.com>
18+
*/
19+
interface TemplateAwareDataCollectorInterface extends DataCollectorInterface
20+
{
21+
public static function getTemplate(): ?string;
22+
}

src/Symfony/Bundle/FrameworkBundle/DependencyInjection/Compiler/ProfilerPass.php

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
namespace Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler;
1313

14+
use Symfony\Bundle\FrameworkBundle\DataCollector\TemplateAwareDataCollectorInterface;
1415
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
1516
use Symfony\Component\DependencyInjection\ContainerBuilder;
1617
use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
@@ -37,11 +38,14 @@ public function process(ContainerBuilder $container)
3738
$priority = isset($attributes[0]['priority']) ? $attributes[0]['priority'] : 0;
3839
$template = null;
3940

40-
if (isset($attributes[0]['template'])) {
41-
if (!isset($attributes[0]['id'])) {
41+
$collectorClass = $container->findDefinition($id)->getClass();
42+
$isTemplateAware = is_subclass_of($collectorClass, TemplateAwareDataCollectorInterface::class);
43+
if (isset($attributes[0]['template']) || $isTemplateAware) {
44+
$idForTemplate = $attributes[0]['id'] ?? $collectorClass;
45+
if (!$idForTemplate) {
4246
throw new InvalidArgumentException(sprintf('Data collector service "%s" must have an id attribute in order to specify a template.', $id));
4347
}
44-
$template = [$attributes[0]['id'], $attributes[0]['template']];
48+
$template = [$idForTemplate, $attributes[0]['template'] ?? $collectorClass::getTemplate()];
4549
}
4650

4751
$collectors->insert([$id, $template], [$priority, --$order]);

src/Symfony/Bundle/FrameworkBundle/Tests/DependencyInjection/Compiler/ProfilerPassTest.php

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,15 @@
1212
namespace Symfony\Bundle\FrameworkBundle\Tests\DependencyInjection\Compiler;
1313

1414
use PHPUnit\Framework\TestCase;
15+
use Symfony\Bundle\FrameworkBundle\DataCollector\AbstractDataCollector;
16+
use Symfony\Bundle\FrameworkBundle\DataCollector\TemplateAwareDataCollectorInterface;
1517
use Symfony\Bundle\FrameworkBundle\DependencyInjection\Compiler\ProfilerPass;
18+
use Symfony\Component\DependencyInjection\Compiler\ResolveChildDefinitionsPass;
19+
use Symfony\Component\DependencyInjection\Compiler\ResolveInstanceofConditionalsPass;
1620
use Symfony\Component\DependencyInjection\ContainerBuilder;
21+
use Symfony\Component\HttpFoundation\Request;
22+
use Symfony\Component\HttpFoundation\Response;
23+
use Symfony\Component\HttpKernel\DataCollector\DataCollectorInterface;
1724

1825
class ProfilerPassTest extends TestCase
1926
{
@@ -54,4 +61,64 @@ public function testValidCollector()
5461
$this->assertCount(1, $methodCalls);
5562
$this->assertEquals('add', $methodCalls[0][0]); // grab the method part of the first call
5663
}
64+
65+
public function provideValidCollectorWithTemplateUsingAutoconfigure(): \Generator
66+
{
67+
yield [new class() implements TemplateAwareDataCollectorInterface {
68+
public function collect(Request $request, Response $response, \Throwable $exception = null)
69+
{
70+
}
71+
72+
public function getName(): string
73+
{
74+
return static::class;
75+
}
76+
77+
public function reset()
78+
{
79+
}
80+
81+
public static function getTemplate(): string
82+
{
83+
return 'foo';
84+
}
85+
}];
86+
87+
yield [new class() extends AbstractDataCollector {
88+
public function collect(Request $request, Response $response, \Throwable $exception = null)
89+
{
90+
}
91+
92+
public static function getTemplate(): string
93+
{
94+
return 'foo';
95+
}
96+
}];
97+
}
98+
99+
/**
100+
* @dataProvider provideValidCollectorWithTemplateUsingAutoconfigure
101+
*/
102+
public function testValidCollectorWithTemplateUsingAutoconfigure(TemplateAwareDataCollectorInterface $dataCollector)
103+
{
104+
$container = new ContainerBuilder();
105+
$profilerDefinition = $container->register('profiler', 'ProfilerClass');
106+
107+
$container->registerForAutoconfiguration(DataCollectorInterface::class)->addTag('data_collector');
108+
$container->register('mydatacollector', \get_class($dataCollector))->setAutoconfigured(true);
109+
110+
(new ResolveInstanceofConditionalsPass())->process($container);
111+
(new ProfilerPass())->process($container);
112+
113+
$idForTemplate = \get_class($dataCollector);
114+
$this->assertSame(['mydatacollector' => [$idForTemplate, 'foo']], $container->getParameter('data_collector.templates'));
115+
116+
// grab the method calls off of the "profiler" definition
117+
$methodCalls = $profilerDefinition->getMethodCalls();
118+
$this->assertCount(1, $methodCalls);
119+
$this->assertEquals('add', $methodCalls[0][0]); // grab the method part of the first call
120+
121+
(new ResolveChildDefinitionsPass())->process($container);
122+
$this->assertSame($idForTemplate, $container->get('mydatacollector')->getName());
123+
}
57124
}

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