1212namespace Symfony \UX \Autocomplete ;
1313
1414use Doctrine \ORM \Tools \Pagination \Paginator ;
15+ use Symfony \Component \PropertyAccess \Exception \UnexpectedTypeException ;
16+ use Symfony \Component \PropertyAccess \PropertyAccessorInterface ;
17+ use Symfony \Component \PropertyAccess \PropertyPath ;
18+ use Symfony \Component \PropertyAccess \PropertyPathInterface ;
1519use Symfony \Component \Security \Core \Exception \AccessDeniedException ;
1620use Symfony \Component \Security \Core \Security ;
1721use Symfony \UX \Autocomplete \Doctrine \DoctrineRegistryWrapper ;
@@ -25,7 +29,8 @@ final class AutocompleteResultsExecutor
2529{
2630 public function __construct (
2731 private DoctrineRegistryWrapper $ managerRegistry ,
28- private ?Security $ security = null
32+ private PropertyAccessorInterface $ propertyAccessor ,
33+ private ?Security $ security = null ,
2934 ) {
3035 }
3136
@@ -53,14 +58,56 @@ public function fetchResults(EntityAutocompleterInterface $autocompleter, string
5358
5459 $ nbPages = (int ) ceil ($ paginator ->count () / $ queryBuilder ->getMaxResults ());
5560
56- $ results = [];
57- foreach ($ paginator as $ entity ) {
58- $ results [] = [
59- 'value ' => $ autocompleter ->getValue ($ entity ),
60- 'text ' => $ autocompleter ->getLabel ($ entity ),
61- ];
61+ $ options = [];
62+ $ optgroups = [];
63+
64+ if (null !== $ groupBy = $ autocompleter ->getGroupBy ()) {
65+ if (\is_string ($ groupBy )) {
66+ $ groupBy = new PropertyPath ($ groupBy );
67+ }
68+
69+ if ($ groupBy instanceof PropertyPathInterface) {
70+ $ accessor = $ this ->propertyAccessor ;
71+ $ groupBy = function ($ choice ) use ($ accessor , $ groupBy ) {
72+ try {
73+ return $ accessor ->getValue ($ choice , $ groupBy );
74+ } catch (UnexpectedTypeException ) {
75+ return null ;
76+ }
77+ };
78+ }
79+ }
80+
81+ if (\is_callable ($ groupBy )) {
82+ $ optgroupLabels = [];
83+
84+ foreach ($ paginator as $ entity ) {
85+ $ option = [
86+ 'value ' => $ autocompleter ->getValue ($ entity ),
87+ 'text ' => $ autocompleter ->getLabel ($ entity ),
88+ ];
89+
90+ $ groupLabels = $ groupBy ($ entity , $ option ['value ' ], $ option ['text ' ]);
91+
92+ if (null !== $ groupLabels ) {
93+ $ groupLabels = \is_array ($ groupLabels ) ? array_map ('strval ' , $ groupLabels ) : [(string ) $ groupLabels ];
94+ $ option ['group_by ' ] = $ groupLabels ;
95+ $ optgroupLabels = array_merge ($ optgroupLabels , $ groupLabels );
96+ }
97+
98+ $ options [] = $ option ;
99+ }
100+
101+ $ optgroups = array_map (fn (string $ label ) => ['value ' => $ label , 'label ' => $ label ], array_unique ($ optgroupLabels ));
102+ } else {
103+ foreach ($ paginator as $ entity ) {
104+ $ options [] = [
105+ 'value ' => $ autocompleter ->getValue ($ entity ),
106+ 'text ' => $ autocompleter ->getLabel ($ entity ),
107+ ];
108+ }
62109 }
63110
64- return new AutocompleteResults ($ results , $ page < $ nbPages );
111+ return new AutocompleteResults ($ options , $ optgroups , $ page < $ nbPages );
65112 }
66113}
0 commit comments