@@ -65,6 +65,108 @@ public static function wash(iterable $with): array
6565 return array_filter (self ::uniqueRecursive (self ::toArray ($ with )));
6666 }
6767
68+ /**
69+ * @param array<mixed> $array
70+ * @param string $prepend
71+ * @return array<mixed>
72+ */
73+ public static function flatDot (array $ array , string $ prepend = '' ): array
74+ {
75+ return self ::flattenDot ($ array , $ prepend , uniqid ('self- ' , false ));
76+ }
77+
78+ /**
79+ * @param array<mixed> $array
80+ * @param string $prepend
81+ * @param string $saveKey
82+ * @return array<mixed>
83+ */
84+ private static function flattenDot (array $ array , string $ prepend , string $ saveKey ): array
85+ {
86+ $ array = self ::undot ($ array , $ saveKey );
87+
88+ $ results = [];
89+
90+ foreach ($ array as $ key => $ value ) {
91+ if (is_array ($ value ) && !empty ($ value )) {
92+ foreach (self ::flattenDot ($ value , $ prepend ? "$ prepend. $ key " : $ key , $ saveKey ) as $ itemKey => $ item ) {
93+ $ results [str_replace (". $ saveKey " , '' , $ itemKey )] = $ item ;
94+ }
95+ } elseif ($ key === $ saveKey ) {
96+ $ results [$ prepend ] = $ value ;
97+ } else {
98+ $ results [$ prepend ? "$ prepend. $ key " : $ key ] = $ value ;
99+ }
100+ }
101+
102+ return $ results ;
103+ }
104+
105+ /**
106+ * @param array<mixed> $array
107+ * @param string|null $saveKey
108+ * @return array<mixed>
109+ */
110+ public static function undot (array $ array , string $ saveKey = null ): array
111+ {
112+ $ results = [];
113+
114+ ksort ($ array );
115+
116+ foreach ($ array as $ key => $ value ) {
117+ $ value = is_array ($ value ) ? self ::undot ($ value , $ saveKey ) : $ value ;
118+
119+ self ::apply ($ results , $ key , $ value , $ saveKey );
120+ }
121+
122+ return $ results ;
123+ }
124+
125+ /**
126+ * @param array<mixed> $array
127+ * @param string $path
128+ * @param mixed $value
129+ * @param string|null $saveKey
130+ * @return mixed
131+ */
132+ public static function apply (array &$ array , string $ path , mixed $ value , string $ saveKey = null ): mixed
133+ {
134+ if (is_null ($ path )) {
135+ return $ array = $ value ;
136+ }
137+
138+ $ keys = explode ('. ' , $ path );
139+
140+ $ keysCount = count ($ keys );
141+
142+ foreach ($ keys as $ i => $ key ) {
143+ if ($ keysCount === 1 ) {
144+ break ;
145+ }
146+
147+ $ keysCount --;
148+ unset($ keys [$ i ]);
149+
150+ // If the key doesn't exist at this depth, we will just create an empty array
151+ // to hold the next value, allowing us to create the arrays to hold final
152+ // values at the correct depth. Then we'll keep digging into the array.
153+ if (!isset ($ array [$ key ])) {
154+ $ array [$ key ] = [];
155+ }
156+ if (!is_array ($ array [$ key ])) {
157+ $ array [$ key ] = $ saveKey
158+ ? [$ saveKey => $ array [$ key ]]
159+ : [];
160+ }
161+
162+ $ array = &$ array [$ key ];
163+ }
164+
165+ $ array [array_shift ($ keys )] = $ value ;
166+
167+ return $ array ;
168+ }
169+
68170 /**
69171 * @template TKey as array-key
70172 * @template TValue
0 commit comments