Skip to content

Commit 59e3840

Browse files
authored
Merge pull request #1825 from antograssiot/datacollector-improvement
Enhance Api Platform Profiler
2 parents c550dbe + 95e4f30 commit 59e3840

File tree

3 files changed

+63
-113
lines changed

3 files changed

+63
-113
lines changed

src/Bridge/Symfony/Bundle/DataCollector/RequestDataCollector.php

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
namespace ApiPlatform\Core\Bridge\Symfony\Bundle\DataCollector;
1515

1616
use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface;
17+
use ApiPlatform\Core\Util\RequestAttributesExtractor;
1718
use Symfony\Component\HttpFoundation\Request;
1819
use Symfony\Component\HttpFoundation\Response;
1920
use Symfony\Component\HttpKernel\DataCollector\DataCollector;
@@ -40,17 +41,12 @@ public function collect(Request $request, Response $response, \Exception $except
4041

4142
$this->data = [
4243
'resource_class' => $resourceClass,
43-
'resource_metadata' => $resourceMetadata,
44-
'method' => $request->getMethod(),
44+
'resource_metadata' => $resourceMetadata ? $this->cloneVar($resourceMetadata) : null,
4545
'acceptable_content_types' => $request->getAcceptableContentTypes(),
46+
'request_attributes' => RequestAttributesExtractor::extractAttributes($request),
4647
];
4748
}
4849

49-
public function getMethod(): string
50-
{
51-
return $this->data['method'] ?? '';
52-
}
53-
5450
public function getAcceptableContentTypes(): array
5551
{
5652
return $this->data['acceptable_content_types'] ?? [];
@@ -66,6 +62,11 @@ public function getResourceMetadata()
6662
return $this->data['resource_metadata'] ?? null;
6763
}
6864

65+
public function getRequestAttributes(): array
66+
{
67+
return $this->data['request_attributes'] ?? [];
68+
}
69+
6970
/**
7071
* {@inheritdoc}
7172
*/
Lines changed: 43 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,9 @@
11
{% extends '@WebProfiler/Profiler/layout.html.twig' %}
22

3-
{% macro operationLine(itemOrCollection, key, operation) %}
3+
{% macro operationLine(key, operation, actualOperationName) %}
44
<tr>
5-
<td>
6-
{{ key }}
7-
</td>
8-
<td>
9-
{% if operation['method'] is defined %}
10-
<em>Method:</em> {{ operation['method'] }}
11-
{% elseif operation['route_name'] is defined %}
12-
<em>Route name:</em> {{ operation['route_name'] }}
13-
{% endif %}
14-
</td>
15-
<td>
16-
<a
17-
href="#"
18-
class="sf-toggle link-inverse sf-toggle-on"
19-
data-toggle-selector="#api-platform-line-{{ itemOrCollection }}-{{ key }}"
20-
data-toggle-alt-content="Hide"
21-
data-toggle-original-content="Show"
22-
>
23-
Show
24-
</a>
25-
</td>
26-
</tr>
27-
<tr id="api-platform-line-{{ itemOrCollection }}-{{ key }}">
28-
<td colspan="3">
29-
{{- dump(operation) -}}
30-
</td>
5+
<th scope="row"{% if key == actualOperationName %} class="status-success"{% endif %}>{{ key }}</th>
6+
<td{% if key == actualOperationName %} class="status-success"{% endif %}>{{- profiler_dump(operation, 1) -}}</td>
317
</tr>
328
{% endmacro %}
339

@@ -38,19 +14,14 @@
3814
{{ include('@ApiPlatform/DataCollector/api-platform.svg') }}
3915
{% endset %}
4016

41-
{{ include('@WebProfiler/Profiler/toolbar_item.html.twig', { 'link': true }) }}
42-
{% endblock %}
43-
44-
{% block head %}
45-
{# Optional. Here you can link to or define your own CSS and JS contents. #}
46-
{# Use {{ parent() }} to extend the default styles instead of overriding them. #}
47-
{{ parent() }}
17+
{% set text %}
18+
<div class="sf-toolbar-info-piece">
19+
<b>Resource Class</b>
20+
<span>{{ collector.resourceClass|default('Not an API Platform resource') }}</span>
21+
</div>
22+
{% endset %}
4823

49-
<style>
50-
tr.sf-toggle-content.sf-toggle-visible {
51-
display: table-row;
52-
}
53-
</style>
24+
{{ include('@WebProfiler/Profiler/toolbar_item.html.twig', { 'link': true }) }}
5425
{% endblock %}
5526

5627
{% block menu %}
@@ -64,84 +35,50 @@
6435
{% endblock %}
6536

6637
{% block panel %}
67-
{# Optional, for showing the most details. #}
68-
<h2>Acceptable Content Types</h2>
69-
<table>
70-
<thead>
71-
<tr>
72-
<th>Content Type</th>
73-
</tr>
74-
</thead>
75-
76-
<tbody>
77-
{% for type in collector.acceptableContentTypes %}
78-
<tr>
79-
<td>{{ type }}</td>
80-
</tr>
81-
{% endfor %}
82-
</tbody>
83-
</table>
84-
<table>
85-
<thead>
86-
<tr>
87-
<th>
88-
Resource class
89-
</th>
90-
</tr>
91-
</thead>
92-
93-
<tbody>
94-
<tr>
95-
<td>
96-
{{ collector.resourceClass|default('Not an API Platform resource') }}
97-
</td>
98-
<tr>
99-
</tbody>
100-
</table>
38+
<div class="metrics">
39+
<div class="metric">
40+
<span class="value">{{ collector.resourceClass|default('Not an API Platform resource') }}</span>
41+
<span class="label">Resource class</span>
42+
</div>
43+
</div>
10144

10245
{% if collector.resourceMetadata %}
10346
<h2>Metadata</h2>
10447
<h3>Short name: "{{ collector.resourceMetadata.shortName }}"</h3>
10548
<table>
10649
<thead>
10750
<tr>
108-
<th>
51+
<th scope="col" class="key">
10952
Item operations
11053
</th>
111-
<th>
112-
Method / Route name
113-
</th>
114-
<th>
54+
<th scope="col">
11555
Attributes
11656
</th>
11757
</tr>
11858
</thead>
11959

12060
<tbody>
12161
{% for key, itemOperation in collector.resourceMetadata.itemOperations %}
122-
{{ apiPlatform.operationLine('item', key, itemOperation) }}
62+
{{ apiPlatform.operationLine(key, itemOperation, collector.requestAttributes.item_operation_name) }}
12363
{% endfor %}
12464
</tbody>
12565
</table>
12666

12767
<table>
12868
<thead>
12969
<tr>
130-
<th>
70+
<th scope="col" class="key">
13171
Collection operations
13272
</th>
133-
<th>
134-
Method / Route name
135-
</th>
136-
<th>
73+
<th scope="col">
13774
Attributes
13875
</th>
13976
</tr>
14077
</thead>
14178

14279
<tbody>
14380
{% for key, collectionOperation in collector.resourceMetadata.collectionOperations %}
144-
{{ apiPlatform.operationLine('collection', key, collectionOperation) }}
81+
{{ apiPlatform.operationLine(key, collectionOperation, collector.requestAttributes.collection_operation_name) }}
14582
{% endfor %}
14683
</tbody>
14784
</table>
@@ -171,26 +108,41 @@
171108
<table>
172109
<thead>
173110
<tr>
174-
<th colspan="100%">
111+
<th scope="col" class="key">
175112
Attributes
176113
</th>
114+
<th scope="col" ></th>
177115
</tr>
178116
</thead>
179117

180118
<tbody>
181119
{% for key, value in collector.resourceMetadata.attributes if key != 'filters' %}
182120
<tr>
183-
<td>
121+
<th scope="row">
184122
{{ key }}
185-
</td>
123+
</th>
186124
<td>
187-
<pre>
188-
{{- dump(value) -}}
189-
</pre>
125+
{{- profiler_dump(value, 2) -}}
190126
</td>
191127
</tr>
192128
{% endfor %}
193129
</tbody>
194130
</table>
131+
<h2>Acceptable Content Types</h2>
132+
<table>
133+
<thead>
134+
<tr>
135+
<th>Content Type</th>
136+
</tr>
137+
</thead>
138+
139+
<tbody>
140+
{% for type in collector.acceptableContentTypes %}
141+
<tr>
142+
<td>{{ type }}</td>
143+
</tr>
144+
{% endfor %}
145+
</tbody>
146+
</table>
195147
{% endif %}
196148
{% endblock %}

tests/Bridge/Symfony/Bundle/DataCollector/RequestDataCollectorTest.php

Lines changed: 12 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
use Symfony\Component\HttpFoundation\ParameterBag;
2222
use Symfony\Component\HttpFoundation\Request;
2323
use Symfony\Component\HttpFoundation\Response;
24+
use Symfony\Component\VarDumper\Cloner\Data;
2425

2526
/**
2627
* @author Julien DENIAU <[email protected]>
@@ -51,10 +52,6 @@ public function setUp()
5152
public function testNoResourceClass()
5253
{
5354
$this->apiResourceClassWillReturn(null);
54-
$this->request
55-
->getMethod()
56-
->shouldBeCalled()
57-
->willReturn('GET');
5855

5956
$dataCollector = new RequestDataCollector(
6057
$this->metadataFactory->reveal()
@@ -65,7 +62,7 @@ public function testNoResourceClass()
6562
$this->response
6663
);
6764

68-
$this->assertEquals($dataCollector->getMethod(), 'GET');
65+
$this->assertEquals($dataCollector->getRequestAttributes(), []);
6966
$this->assertEquals($dataCollector->getAcceptableContentTypes(), ['foo', 'bar']);
7067
$this->assertNull($dataCollector->getResourceClass());
7168
$this->assertNull($dataCollector->getResourceMetadata());
@@ -80,7 +77,7 @@ public function testNotCallingCollect()
8077
$this->metadataFactory->reveal()
8178
);
8279

83-
$this->assertEquals($dataCollector->getMethod(), '');
80+
$this->assertEquals($dataCollector->getRequestAttributes(), []);
8481
$this->assertEquals($dataCollector->getAcceptableContentTypes(), []);
8582
$this->assertNull($dataCollector->getResourceClass());
8683
$this->assertNull($dataCollector->getResourceMetadata());
@@ -89,10 +86,10 @@ public function testNotCallingCollect()
8986
public function testWithRessource()
9087
{
9188
$this->apiResourceClassWillReturn(DummyEntity::class);
92-
$this->request
93-
->getMethod()
94-
->shouldBeCalled()
95-
->willReturn('GET');
89+
$this->attributes->has('_api_item_operation_name')->shouldBeCalled()->willReturn(true);
90+
$this->attributes->get('_api_item_operation_name')->shouldBeCalled()->willReturn('get');
91+
$this->attributes->get('_api_receive')->shouldBeCalled()->willReturn(true);
92+
$this->request->attributes = $this->attributes->reveal();
9693

9794
$dataCollector = new RequestDataCollector(
9895
$this->metadataFactory->reveal()
@@ -103,17 +100,17 @@ public function testWithRessource()
103100
$this->response
104101
);
105102

106-
$this->assertEquals($dataCollector->getMethod(), 'GET');
103+
$this->assertEquals(['resource_class' => DummyEntity::class, 'item_operation_name' => 'get', 'receive' => true], $dataCollector->getRequestAttributes());
107104
$this->assertEquals($dataCollector->getAcceptableContentTypes(), ['foo', 'bar']);
108105
$this->assertEquals($dataCollector->getResourceClass(), DummyEntity::class);
109-
$this->assertInstanceOf(ResourceMetadata::class, $dataCollector->getResourceMetadata());
106+
$this->assertInstanceOf(Data::class, $dataCollector->getResourceMetadata());
107+
$this->assertSame(ResourceMetadata::class, $dataCollector->getResourceMetadata()->getType());
110108
}
111109

112110
private function apiResourceClassWillReturn($data)
113111
{
114-
$this->attributes->get('_api_resource_class')
115-
->shouldBeCalled()
116-
->willReturn($data);
112+
$this->attributes->get('_api_resource_class')->shouldBeCalled()->willReturn($data);
113+
$this->attributes->get('_api_subresource_context')->shouldBeCalled()->willReturn(null);
117114
$this->request->attributes = $this->attributes->reveal();
118115

119116
if (!$data) {

0 commit comments

Comments
 (0)