66use SlopeIt \BreadcrumbBundle \Model \ProcessedBreadcrumbItem ;
77use Symfony \Component \HttpFoundation \RequestStack ;
88use Symfony \Component \PropertyAccess \PropertyAccessorInterface ;
9- use Symfony \Component \Routing \RouterInterface ;
9+ use Symfony \Component \Routing \Generator \ UrlGeneratorInterface ;
1010use Symfony \Contracts \Translation \TranslatorInterface ;
1111
1212/**
@@ -26,9 +26,9 @@ class BreadcrumbItemProcessor
2626 private $ requestStack ;
2727
2828 /**
29- * @var RouterInterface
29+ * @var UrlGeneratorInterface
3030 */
31- private $ router ;
31+ private $ urlGenerator ;
3232
3333 /**
3434 * @var TranslatorInterface
@@ -38,19 +38,55 @@ class BreadcrumbItemProcessor
3838 public function __construct (
3939 PropertyAccessorInterface $ propertyAccessor ,
4040 TranslatorInterface $ translator ,
41- RouterInterface $ router ,
41+ UrlGeneratorInterface $ urlGenerator ,
4242 RequestStack $ requestStack
4343 ) {
4444 $ this ->propertyAccessor = $ propertyAccessor ;
4545 $ this ->translator = $ translator ;
46- $ this ->router = $ router ;
46+ $ this ->urlGenerator = $ urlGenerator ;
4747 $ this ->requestStack = $ requestStack ;
4848 }
4949
5050 /**
51+ * @param BreadcrumbItem[] $items
5152 * @param array<string, mixed> $variables
53+ * @return ProcessedBreadcrumbItem[]
5254 */
53- public function process (BreadcrumbItem $ item , array $ variables ): ProcessedBreadcrumbItem
55+ public function process (array $ items , array $ variables ): array
56+ {
57+ $ requestContext = $ this ->urlGenerator ->getContext ();
58+
59+ // Save original parameters of the request context, so they can be re-applied after url generation is done.
60+ $ originalRequestContextParameters = $ requestContext ->getParameters ();
61+
62+ // Use the request context to pre-set parameters that are already present as attributes of the current request.
63+ // This allows for URL generation using parameters already present in the request path without having to
64+ // re-specify them all the time. These parameters won't be added unnecessarily if they are not needed for the
65+ // route being generated.
66+ foreach ($ this ->requestStack ->getCurrentRequest ()->attributes as $ key => $ value ) {
67+ if ($ key [0 ] !== '_ ' ) {
68+ $ requestContext ->setParameter ($ key , $ value );
69+ }
70+ }
71+
72+ // Process items with our own "modified" request context
73+ $ processedItems = array_map (
74+ function (BreadcrumbItem $ item ) use ($ variables ) {
75+ return $ this ->processItem ($ item , $ variables );
76+ },
77+ $ items
78+ );
79+
80+ // Restore parameters originally present in the context so that this method doesn't have any side effects.
81+ $ this ->urlGenerator ->getContext ()->setParameters ($ originalRequestContextParameters );
82+
83+ return $ processedItems ;
84+ }
85+
86+ /**
87+ * @param array<string, mixed> $variables
88+ */
89+ private function processItem (BreadcrumbItem $ item , array $ variables ): ProcessedBreadcrumbItem
5490 {
5591 // Process the label
5692 if ($ item ->getLabel () && $ item ->getLabel ()[0 ] === '$ ' ) {
@@ -62,23 +98,17 @@ public function process(BreadcrumbItem $item, array $variables): ProcessedBreadc
6298 }
6399
64100 // Process the route
65- // TODO: cache parameters extracted from current request
66- $ params = [];
67- foreach ($ this ->requestStack ->getCurrentRequest ()->attributes as $ key => $ value ) {
68- if ($ key [0 ] !== '_ ' ) {
69- $ params [$ key ] = $ value ;
70- }
71- }
72- foreach ($ item ->getRouteParams () ?: [] as $ key => $ value ) {
73- if (is_string ($ value ) && $ value [0 ] === '$ ' ) {
74- $ params [$ key ] = $ this ->parseValue ($ value , $ variables );
75- } else {
76- $ params [$ key ] = $ value ;
101+ if ($ item ->getRoute () !== null ) {
102+ $ params = [];
103+ foreach ($ item ->getRouteParams () ?: [] as $ key => $ value ) {
104+ if (is_string ($ value ) && $ value [0 ] === '$ ' ) {
105+ $ params [$ key ] = $ this ->parseValue ($ value , $ variables );
106+ } else {
107+ $ params [$ key ] = $ value ;
108+ }
77109 }
78- }
79110
80- if ($ item ->getRoute () !== null ) {
81- $ processedUrl = $ this ->router ->generate ($ item ->getRoute (), $ params );
111+ $ processedUrl = $ this ->urlGenerator ->generate ($ item ->getRoute (), $ params );
82112 } else {
83113 $ processedUrl = null ;
84114 }
0 commit comments