@@ -29,14 +29,15 @@ public function getFilters(): array
2929 {
3030 return [
3131 new TwigFilter ('data_uri ' , [$ this , 'dataUri ' ]),
32+ new TwigFilter ('attr_merge ' , 'twig_attr_merge ' ),
3233 ];
3334 }
3435
3536 public function getFunctions (): array
3637 {
3738 return [
3839 new TwigFunction ('html_classes ' , 'twig_html_classes ' ),
39- new TwigFunction ('attr ' , [ $ this , ' attr ' ] , ['needs_environment ' => true , 'is_safe ' => ['html ' ]]),
40+ new TwigFunction ('attr ' , ' twig_attr ' , ['needs_environment ' => true , 'is_safe ' => ['html ' ]]),
4041 ];
4142 }
4243
@@ -81,65 +82,11 @@ public function dataUri(string $data, string $mime = null, array $parameters = [
8182
8283 return $ repr ;
8384 }
84-
85- public function attr (Environment $ env , ...$ args ): string
86- {
87- $ class = '' ;
88- $ style = '' ;
89- $ attr = [];
90-
91- foreach ($ args as $ attrs ) {
92- if (!$ attrs ) {
93- continue ;
94- }
95-
96- $ attrs = (array ) $ attrs ;
97-
98- if (isset ($ attrs ['class ' ])) {
99- $ class .= implode (' ' , (array ) $ attrs ['class ' ]) . ' ' ;
100- unset($ attrs ['class ' ]);
101- }
102-
103- if (isset ($ attrs ['style ' ])) {
104- foreach ((array ) $ attrs ['style ' ] as $ name => $ value ) {
105- if (is_numeric ($ name )) {
106- $ style .= $ value . '; ' ;
107- } else {
108- $ style .= $ name .': ' .$ value .'; ' ;
109- }
110- }
111- unset($ attrs ['style ' ]);
112- }
113-
114- if (isset ($ attrs ['data ' ])) {
115- foreach ($ attrs ['data ' ] as $ name => $ value ) {
116- $ attrs ['data- ' .$ name ] = $ value ;
117- }
118- unset($ attrs ['data ' ]);
119- }
120-
121- $ attr = array_merge ($ attr , $ attrs );
122- }
123-
124- if ($ class ) {
125- $ attr ['class ' ] = trim ($ class );
126- }
127-
128- if ($ style ) {
129- $ attr ['style ' ] = trim ($ style );
130- }
131-
132- $ result = '' ;
133- foreach ($ attr as $ name => $ value ) {
134- $ result .= twig_escape_filter ($ env , $ name , 'html_attr ' ).'=" ' .htmlspecialchars ($ value ).'" ' ;
135- }
136-
137- return trim ($ result );
138- }
13985}
14086}
14187
14288namespace {
89+ use Twig \Environment ;
14390use Twig \Error \RuntimeError ;
14491
14592function twig_html_classes (...$ args ): string
@@ -165,4 +112,75 @@ function twig_html_classes(...$args): string
165112
166113 return implode (' ' , array_unique ($ classes ));
167114}
115+
116+ function twig_attr_merge (...$ arrays ): array
117+ {
118+ $ result = [];
119+
120+ foreach ($ arrays as $ argNumber => $ array ) {
121+ if (!$ array ) {
122+ continue ;
123+ }
124+
125+ if (!twig_test_iterable ($ array )) {
126+ throw new RuntimeError (sprintf ('The attr_merge filter only works with arrays or "Traversable", got "%s" for argument %d. ' , \gettype ($ array ), $ argNumber + 1 ));
127+ }
128+
129+ $ array = twig_to_array ($ array );
130+
131+ foreach (['class ' , 'style ' , 'data ' ] as $ deepMergeKey ) {
132+ if (isset ($ array [$ deepMergeKey ])) {
133+ $ value = $ array [$ deepMergeKey ];
134+ unset($ array [$ deepMergeKey ]);
135+
136+ if (!twig_test_iterable ($ value )) {
137+ $ value = (array ) $ value ;
138+ }
139+
140+ $ value = twig_to_array ($ value );
141+
142+ $ result [$ deepMergeKey ] = array_merge ($ result [$ deepMergeKey ] ?? [], $ value );
143+ }
144+ }
145+
146+ $ result = array_merge ($ result , $ array );
147+ }
148+
149+ return $ result ;
150+ }
151+
152+ function twig_attr (Environment $ env , ...$ args ): string
153+ {
154+ $ attr = twig_attr_merge (...$ args );
155+
156+ if (isset ($ attr ['class ' ])) {
157+ $ attr ['class ' ] = trim (implode (' ' , array_values ($ attr ['class ' ])));
158+ }
159+
160+ if (isset ($ attr ['style ' ])) {
161+ $ style = '' ;
162+ foreach ($ attr ['style ' ] as $ name => $ value ) {
163+ if (is_numeric ($ name )) {
164+ $ style .= $ value .'; ' ;
165+ } else {
166+ $ style .= $ name .': ' .$ value .'; ' ;
167+ }
168+ }
169+ $ attr ['style ' ] = trim ($ style );
170+ }
171+
172+ if (isset ($ attr ['data ' ])) {
173+ foreach ($ attr ['data ' ] as $ name => $ value ) {
174+ $ attr ['data- ' .$ name ] = $ value ;
175+ }
176+ unset($ attr ['data ' ]);
177+ }
178+
179+ $ result = '' ;
180+ foreach ($ attr as $ name => $ value ) {
181+ $ result .= twig_escape_filter ($ env , $ name , 'html_attr ' ).'=" ' .htmlspecialchars ($ value ).'" ' ;
182+ }
183+
184+ return trim ($ result );
185+ }
168186}
0 commit comments