99namespace Ibexa \DesignSystemTwig \Twig \Components ;
1010
1111use InvalidArgumentException ;
12+ use Symfony \Component \OptionsResolver \Options ;
1213use Symfony \Component \OptionsResolver \OptionsResolver ;
1314use Symfony \UX \TwigComponent \Attribute \AsTwigComponent ;
1415use Symfony \UX \TwigComponent \Attribute \ExposeInTemplate ;
1718#[AsTwigComponent('ibexa:overflow_list ' )]
1819final class OverflowList
1920{
20- /**
21- * @var list<array>
22- */
21+ /** @var list<array> */
2322 public array $ items = [];
2423
25- /**
26- * @var array<string>
27- */
24+ /** @var list<string> */
2825 public array $ itemTemplateProps = [];
2926
3027 /**
@@ -41,31 +38,12 @@ public function validate(array $props): array
4138 ->define ('items ' )
4239 ->allowedTypes ('array ' )
4340 ->default ([])
44- ->normalize (static function ($ options , $ value ): array {
45- if (!is_array ($ value ) || !array_is_list ($ value )) {
46- throw new InvalidArgumentException ('Property "items" must be a list (sequential array). ' );
47- }
48-
49- foreach ($ value as $ i => $ item ) {
50- if (!is_array ($ item )) {
51- throw new InvalidArgumentException (sprintf ('items[%d] must be an array, %s given. ' , $ i , get_debug_type ($ item )));
52- }
53- foreach (array_keys ($ item ) as $ key ) {
54- if (!is_string ($ key )) {
55- throw new InvalidArgumentException (sprintf ('items[%d] must use string keys. ' , $ i ));
56- }
57- if (!preg_match ('/^[A-Za-z_][A-Za-z0-9_]*$/ ' , $ key )) {
58- throw new InvalidArgumentException (sprintf ('Invalid key "%s" in items[%d]. ' , $ key , $ i ));
59- }
60- }
61- }
62-
63- return $ value ;
64- });
41+ ->normalize (self ::normalizeItems (...));
6542 $ resolver
6643 ->define ('itemTemplateProps ' )
6744 ->allowedTypes ('array ' )
68- ->default ([]);
45+ ->default ([])
46+ ->normalize (self ::normalizeItemTemplateProps (...));
6947
7048 return $ resolver ->resolve ($ props ) + $ props ;
7149 }
@@ -76,20 +54,66 @@ public function validate(array $props): array
7654 #[ExposeInTemplate('item_template_props ' )]
7755 public function getItemTemplateProps (): array
7856 {
79- if (empty ($ this ->items )) {
57+ if (empty ($ this ->itemTemplateProps )) {
8058 return [];
8159 }
8260
83- $ allKeys = [];
84- foreach ($ this ->items as $ item ) {
85- $ allKeys = array_unique ([...$ allKeys , ...array_keys ($ item )]);
86- }
87-
8861 $ props = [];
89- foreach ($ allKeys as $ name ) {
62+ foreach ($ this -> itemTemplateProps as $ name ) {
9063 $ props [$ name ] = '{{ ' . $ name . ' }} ' ;
9164 }
9265
9366 return $ props ;
9467 }
68+
69+ /**
70+ * @param Options<array<string, mixed>> $options
71+ * @param array<int, mixed> $value
72+ *
73+ * @return list<array<string, mixed>>
74+ */
75+ private static function normalizeItems (Options $ options , array $ value ): array
76+ {
77+ if (!array_is_list ($ value )) {
78+ throw new InvalidArgumentException ('Property "items" must be a list (sequential array). ' );
79+ }
80+
81+ foreach ($ value as $ i => $ item ) {
82+ if (!is_array ($ item )) {
83+ throw new InvalidArgumentException (sprintf ('items[%d] must be an array, %s given. ' , $ i , get_debug_type ($ item )));
84+ }
85+ foreach (array_keys ($ item ) as $ key ) {
86+ if (!is_string ($ key )) {
87+ throw new InvalidArgumentException (sprintf ('items[%d] must use string keys. ' , $ i ));
88+ }
89+ if (!preg_match ('/^[A-Za-z_][A-Za-z0-9_]*$/ ' , $ key )) {
90+ throw new InvalidArgumentException (sprintf ('Invalid key "%s" in items[%d]. ' , $ key , $ i ));
91+ }
92+ }
93+ }
94+
95+ return $ value ;
96+ }
97+
98+ /**
99+ * @param Options<array<string, mixed>> $options
100+ * @param array<int|string, mixed> $value
101+ *
102+ * @return array<int, string>
103+ */
104+ private static function normalizeItemTemplateProps (Options $ options , array $ value ): array
105+ {
106+ foreach ($ value as $ key => $ prop ) {
107+ if (!is_string ($ prop )) {
108+ $ index = is_int ($ key ) ? (string ) $ key : sprintf ('"%s" ' , $ key );
109+ throw new InvalidArgumentException (sprintf ('itemTemplateProps[%s] must be a string, %s given. ' , $ index , get_debug_type ($ prop )));
110+ }
111+
112+ if (!preg_match ('/^[A-Za-z_][A-Za-z0-9_]*$/ ' , $ prop )) {
113+ throw new InvalidArgumentException (sprintf ('Invalid itemTemplateProps value "%s". ' , $ prop ));
114+ }
115+ }
116+
117+ return array_values ($ value );
118+ }
95119}
0 commit comments