@@ -21,21 +21,23 @@ class Sort extends LookupRefValidations
2121 * Both $sortIndex and $sortOrder can be arrays, to provide multi-level sorting.
2222 *
2323 * @param mixed $sortArray The range of cells being sorted
24- * @param mixed $sortIndex Whether the uniqueness should be determined by row ( the default) or by column
24+ * @param mixed $sortIndex The column or row number within the sortArray to sort on
2525 * @param mixed $sortOrder Flag indicating whether to sort ascending or descending
2626 * Ascending = 1 (self::ORDER_ASCENDING)
2727 * Descending = -1 (self::ORDER_DESCENDING)
2828 * @param mixed $byColumn Whether the sort should be determined by row (the default) or by column
2929 *
3030 * @return mixed The sorted values from the sort range
3131 */
32- public static function sort ($ sortArray , $ sortIndex = [ 1 ] , $ sortOrder = self ::ORDER_ASCENDING , $ byColumn = false )
32+ public static function sort ($ sortArray , $ sortIndex = 1 , $ sortOrder = self ::ORDER_ASCENDING , $ byColumn = false )
3333 {
3434 if (!is_array ($ sortArray )) {
3535 // Scalars are always returned "as is"
3636 return $ sortArray ;
3737 }
3838
39+ $ sortArray = self ::enumerateArrayKeys ($ sortArray );
40+
3941 $ byColumn = (bool ) $ byColumn ;
4042 $ lookupIndexSize = $ byColumn ? count ($ sortArray ) : count ($ sortArray [0 ]);
4143
@@ -68,6 +70,12 @@ public static function sort($sortArray, $sortIndex = [1], $sortOrder = self::ORD
6870 *
6971 * @param mixed $sortArray The range of cells being sorted
7072 * @param mixed $args
73+ * At least one additional argument must be provided, The vector or range to sort on
74+ * After that, arguments are passed as pairs:
75+ * sort order: ascending or descending
76+ * Ascending = 1 (self::ORDER_ASCENDING)
77+ * Descending = -1 (self::ORDER_DESCENDING)
78+ * additional arrays or ranges for multi-level sorting
7179 *
7280 * @return mixed The sorted values from the sort range
7381 */
@@ -78,6 +86,8 @@ public static function sortBy($sortArray, ...$args)
7886 return $ sortArray ;
7987 }
8088
89+ $ sortArray = self ::enumerateArrayKeys ($ sortArray );
90+
8191 $ lookupArraySize = count ($ sortArray );
8292 $ argumentCount = count ($ args );
8393
@@ -94,19 +104,33 @@ public static function sortBy($sortArray, ...$args)
94104 return self ::processSortBy ($ sortArray , $ sortBy , $ sortOrder );
95105 }
96106
107+ private static function enumerateArrayKeys (array $ sortArray ): array
108+ {
109+ array_walk (
110+ $ sortArray ,
111+ function (&$ columns ): void {
112+ if (is_array ($ columns )) {
113+ $ columns = array_values ($ columns );
114+ }
115+ }
116+ );
117+
118+ return array_values ($ sortArray );
119+ }
120+
97121 /**
98122 * @param mixed $sortIndex
99123 * @param mixed $sortOrder
100124 */
101- private static function validateScalarArgumentsForSort (&$ sortIndex , &$ sortOrder , int $ lookupIndexSize ): void
125+ private static function validateScalarArgumentsForSort (&$ sortIndex , &$ sortOrder , int $ sortArraySize ): void
102126 {
103127 if (is_array ($ sortIndex ) || is_array ($ sortOrder )) {
104128 throw new Exception (ExcelError::VALUE ());
105129 }
106130
107131 $ sortIndex = self ::validatePositiveInt ($ sortIndex , false );
108132
109- if ($ sortIndex > $ lookupIndexSize ) {
133+ if ($ sortIndex > $ sortArraySize ) {
110134 throw new Exception (ExcelError::VALUE ());
111135 }
112136
@@ -116,15 +140,15 @@ private static function validateScalarArgumentsForSort(&$sortIndex, &$sortOrder,
116140 /**
117141 * @param mixed $sortVector
118142 */
119- private static function validateSortVector ($ sortVector , int $ lookupArraySize ): array
143+ private static function validateSortVector ($ sortVector , int $ sortArraySize ): array
120144 {
121145 if (!is_array ($ sortVector )) {
122146 throw new Exception (ExcelError::VALUE ());
123147 }
124148
125149 // It doesn't matter if it's a row or a column vectors, it works either way
126150 $ sortVector = Functions::flattenArray ($ sortVector );
127- if (count ($ sortVector ) !== $ lookupArraySize ) {
151+ if (count ($ sortVector ) !== $ sortArraySize ) {
128152 throw new Exception (ExcelError::VALUE ());
129153 }
130154
@@ -148,14 +172,14 @@ private static function validateSortOrder($sortOrder): int
148172 * @param array $sortIndex
149173 * @param mixed $sortOrder
150174 */
151- private static function validateArrayArgumentsForSort (&$ sortIndex , &$ sortOrder , int $ lookupIndexSize ): void
175+ private static function validateArrayArgumentsForSort (&$ sortIndex , &$ sortOrder , int $ sortArraySize ): void
152176 {
153177 // It doesn't matter if they're row or column vectors, it works either way
154178 $ sortIndex = Functions::flattenArray ($ sortIndex );
155179 $ sortOrder = Functions::flattenArray ($ sortOrder );
156180
157181 if (
158- count ($ sortOrder ) === 0 || count ($ sortOrder ) > $ lookupIndexSize ||
182+ count ($ sortOrder ) === 0 || count ($ sortOrder ) > $ sortArraySize ||
159183 (count ($ sortOrder ) > count ($ sortIndex ))
160184 ) {
161185 throw new Exception (ExcelError::VALUE ());
@@ -170,7 +194,7 @@ private static function validateArrayArgumentsForSort(&$sortIndex, &$sortOrder,
170194 }
171195
172196 foreach ($ sortIndex as $ key => &$ value ) {
173- self ::validateScalarArgumentsForSort ($ value , $ sortOrder [$ key ], $ lookupIndexSize );
197+ self ::validateScalarArgumentsForSort ($ value , $ sortOrder [$ key ], $ sortArraySize );
174198 }
175199 }
176200
@@ -195,7 +219,7 @@ function ($value) {
195219 * @param array[] $sortIndex
196220 * @param int[] $sortOrder
197221 */
198- private static function processSortBy (array $ lookupArray , array $ sortIndex , $ sortOrder ): array
222+ private static function processSortBy (array $ sortArray , array $ sortIndex , $ sortOrder ): array
199223 {
200224 $ sortArguments = [];
201225 $ sortData = [];
@@ -204,32 +228,32 @@ private static function processSortBy(array $lookupArray, array $sortIndex, $sor
204228 $ sortArguments [] = self ::prepareSortVectorValues ($ sortValues );
205229 $ sortArguments [] = $ sortOrder [$ index ] === self ::ORDER_ASCENDING ? SORT_ASC : SORT_DESC ;
206230 }
207- $ sortArguments = self ::applyPHP7Patch ($ lookupArray , $ sortArguments );
231+ $ sortArguments = self ::applyPHP7Patch ($ sortArray , $ sortArguments );
208232
209233 $ sortVector = self ::executeVectorSortQuery ($ sortData , $ sortArguments );
210234
211- return self ::sortLookupArrayFromVector ($ lookupArray , $ sortVector );
235+ return self ::sortLookupArrayFromVector ($ sortArray , $ sortVector );
212236 }
213237
214238 /**
215239 * @param int[] $sortIndex
216240 * @param int[] $sortOrder
217241 */
218- private static function sortByRow (array $ lookupArray , array $ sortIndex , array $ sortOrder ): array
242+ private static function sortByRow (array $ sortArray , array $ sortIndex , array $ sortOrder ): array
219243 {
220- $ sortVector = self ::buildVectorForSort ($ lookupArray , $ sortIndex , $ sortOrder );
244+ $ sortVector = self ::buildVectorForSort ($ sortArray , $ sortIndex , $ sortOrder );
221245
222- return self ::sortLookupArrayFromVector ($ lookupArray , $ sortVector );
246+ return self ::sortLookupArrayFromVector ($ sortArray , $ sortVector );
223247 }
224248
225249 /**
226250 * @param int[] $sortIndex
227251 * @param int[] $sortOrder
228252 */
229- private static function sortByColumn (array $ lookupArray , array $ sortIndex , array $ sortOrder ): array
253+ private static function sortByColumn (array $ sortArray , array $ sortIndex , array $ sortOrder ): array
230254 {
231- $ lookupArray = Matrix::transpose ($ lookupArray );
232- $ result = self ::sortByRow ($ lookupArray , $ sortIndex , $ sortOrder );
255+ $ sortArray = Matrix::transpose ($ sortArray );
256+ $ result = self ::sortByRow ($ sortArray , $ sortIndex , $ sortOrder );
233257
234258 return Matrix::transpose ($ result );
235259 }
@@ -238,17 +262,17 @@ private static function sortByColumn(array $lookupArray, array $sortIndex, array
238262 * @param int[] $sortIndex
239263 * @param int[] $sortOrder
240264 */
241- private static function buildVectorForSort (array $ lookupArray , array $ sortIndex , array $ sortOrder ): array
265+ private static function buildVectorForSort (array $ sortArray , array $ sortIndex , array $ sortOrder ): array
242266 {
243267 $ sortArguments = [];
244268 $ sortData = [];
245269 foreach ($ sortIndex as $ index => $ sortIndexValue ) {
246- $ sortValues = array_column ($ lookupArray , $ sortIndexValue - 1 );
270+ $ sortValues = array_column ($ sortArray , $ sortIndexValue - 1 );
247271 $ sortData [] = $ sortValues ;
248272 $ sortArguments [] = self ::prepareSortVectorValues ($ sortValues );
249273 $ sortArguments [] = $ sortOrder [$ index ] === self ::ORDER_ASCENDING ? SORT_ASC : SORT_DESC ;
250274 }
251- $ sortArguments = self ::applyPHP7Patch ($ lookupArray , $ sortArguments );
275+ $ sortArguments = self ::applyPHP7Patch ($ sortArray , $ sortArguments );
252276
253277 $ sortData = self ::executeVectorSortQuery ($ sortData , $ sortArguments );
254278
@@ -279,12 +303,12 @@ private static function executeVectorSortQuery(array $sortData, array $sortArgum
279303 return $ sortedData ;
280304 }
281305
282- private static function sortLookupArrayFromVector (array $ lookupArray , array $ sortVector ): array
306+ private static function sortLookupArrayFromVector (array $ sortArray , array $ sortVector ): array
283307 {
284308 // Building a new array in the correct (sorted) order works; but may be memory heavy for larger arrays
285309 $ sortedArray = [];
286310 foreach ($ sortVector as $ index ) {
287- $ sortedArray [] = $ lookupArray [$ index ];
311+ $ sortedArray [] = $ sortArray [$ index ];
288312 }
289313
290314 return $ sortedArray ;
@@ -306,10 +330,10 @@ private static function sortLookupArrayFromVector(array $lookupArray, array $sor
306330 * MS Excel replicates the PHP 8.0.0 behaviour, retaining the original order of matching elements.
307331 * To replicate that behaviour with PHP 7, we add an extra sort based on the row index.
308332 */
309- private static function applyPHP7Patch (array $ lookupArray , array $ sortArguments ): array
333+ private static function applyPHP7Patch (array $ sortArray , array $ sortArguments ): array
310334 {
311335 if (PHP_VERSION_ID < 80000 ) {
312- $ sortArguments [] = range (1 , count ($ lookupArray ));
336+ $ sortArguments [] = range (1 , count ($ sortArray ));
313337 $ sortArguments [] = SORT_ASC ;
314338 }
315339
0 commit comments