14
14
use Symfony \Component \HttpFoundation \Request ;
15
15
use InvalidArgumentException ;
16
16
use RuntimeException ;
17
+ use Symfony \Contracts \Translation \TranslatorInterface ;
17
18
18
19
class BreadcrumbListener
19
20
{
@@ -22,17 +23,20 @@ class BreadcrumbListener
22
23
private BreadcrumbTrail $ breadcrumbTrail ;
23
24
private Request $ request ;
24
25
private EntityManagerInterface $ manager ;
26
+ private TranslatorInterface $ translator ;
25
27
26
28
public function __construct (
27
29
RouterInterface $ router ,
28
30
PropertyAccessorInterface $ propertyAccess ,
29
31
BreadcrumbTrail $ breadcrumbTrail ,
30
- EntityManagerInterface $ manager
32
+ EntityManagerInterface $ manager ,
33
+ TranslatorInterface $ translator
31
34
) {
32
35
$ this ->router = $ router ;
33
36
$ this ->propertyAccess = $ propertyAccess ;
34
37
$ this ->breadcrumbTrail = $ breadcrumbTrail ;
35
38
$ this ->manager = $ manager ;
39
+ $ this ->translator = $ translator ;
36
40
}
37
41
38
42
public function onKernelController (KernelEvent $ event ): void
@@ -104,6 +108,7 @@ private function generateBreadcrumb(
104
108
\Reflectionmethod $ method
105
109
): Breadcrumb {
106
110
$ title = $ breadcrumb ->getTitle ();
111
+ $ parameters = $ breadcrumb ->getParameters ();
107
112
108
113
// We're dealing with an expression, e.g. {item.name}
109
114
if ($ title [0 ] === '{ ' && $ title [-1 ] === '} ' ) {
@@ -171,6 +176,60 @@ private function generateBreadcrumb(
171
176
);
172
177
}
173
178
179
+ if (count ($ parameters )) {
180
+ foreach ($ parameters as $ key => $ parameterValue ) {
181
+ if (str_contains ($ parameterValue , '. ' )) {
182
+ $ split = explode ('. ' , $ parameterValue , 2 );
183
+ $ attributeName = $ split [0 ];
184
+ $ propertyPath = $ split [1 ];
185
+ } else {
186
+ $ attributeName = $ parameterValue ;
187
+ }
188
+
189
+ if (!$ this ->request ->attributes ->has ($ attributeName )) {
190
+ throw new RuntimeException (
191
+ 'You tried to use { ' . $ attributeName . '} as a breadcrumb parameter, but there is no ' .
192
+ 'parameter with that name in the route. '
193
+ );
194
+ }
195
+
196
+ $ attributeId = $ this ->request ->attributes ->get ($ attributeName );
197
+
198
+ $ name = null ;
199
+ foreach ($ method ->getParameters () as $ parameter ) {
200
+ if ($ parameter ->name === $ attributeName ) {
201
+ $ name = $ parameter ->getType ()->getName ();
202
+ }
203
+ }
204
+
205
+ if ($ name === null ) {
206
+ throw new RuntimeException (
207
+ 'You tried to use { ' . $ attributeName . '} as a breadcrumb parameter, but there is no ' .
208
+ 'parameter with that name in the route. '
209
+ );
210
+ }
211
+
212
+ $ attribute = $ this ->manager ->getRepository ($ name )->find ($ attributeId );
213
+
214
+ if (!is_object ($ attribute )) {
215
+ throw new RuntimeException (
216
+ 'Could not resolve entity ' . $ name . ' with ID ' . $ attributeId
217
+ );
218
+ }
219
+
220
+ if (!isset ($ propertyPath )) {
221
+ throw new RuntimeException (
222
+ 'When using objects in a breadcrumb, you have to specify which method to read. ' .
223
+ ' E.g. {object.name} '
224
+ );
225
+ }
226
+
227
+ $ parameters [$ key ] = $ this ->propertyAccess ->getValue ($ attribute , $ propertyPath );
228
+ }
229
+
230
+ $ title = $ this ->translator ->trans ($ title , $ parameters );
231
+ }
232
+
174
233
// Just a simple string
175
234
return new Breadcrumb ($ title );
176
235
}
0 commit comments