<?php 
 
/** 
 * This file is part of the CodeIgniter 4 framework. 
 * 
 * (c) CodeIgniter Foundation <[email protected]> 
 * 
 * For the full copyright and license information, please view the LICENSE 
 * file that was distributed with this source code. 
 */ 
 
/** 
 * CodeIgniter Array Helpers 
 */ 
 
if (! function_exists('dot_array_search')) 
{ 
    /** 
     * Searches an array through dot syntax. Supports 
     * wildcard searches, like foo.*.bar 
     * 
     * @param string $index 
     * @param array  $array 
     * 
     * @return mixed|null 
     */ 
    function dot_array_search(string $index, array $array) 
    { 
        $segments = explode('.', rtrim(rtrim($index, '* '), '.')); 
 
        return _array_search_dot($segments, $array); 
    } 
} 
 
if (! function_exists('_array_search_dot')) 
{ 
    /** 
     * Used by dot_array_search to recursively search the 
     * array with wildcards. 
     * 
     * @param array $indexes 
     * @param array $array 
     * 
     * @return mixed|null 
     */ 
    function _array_search_dot(array $indexes, array $array) 
    { 
        // Grab the current index 
        $currentIndex = $indexes 
            ? array_shift($indexes) 
            : null; 
 
        if ((empty($currentIndex) && (int) $currentIndex !== 0) || (! isset($array[$currentIndex]) && $currentIndex !== '*')) 
        { 
            return null; 
        } 
 
        // Handle Wildcard (*) 
        if ($currentIndex === '*') 
        { 
            // If $array has more than 1 item, we have to loop over each. 
            foreach ($array as $value) 
            { 
                $answer = _array_search_dot($indexes, $value); 
 
                if ($answer !== null) 
                { 
                    return $answer; 
                } 
            } 
 
            // Still here after searching all child nodes? 
            return null; 
        } 
 
        // If this is the last index, make sure to return it now, 
        // and not try to recurse through things. 
        if (empty($indexes)) 
        { 
            return $array[$currentIndex]; 
        } 
 
        // Do we need to recursively search this value? 
        if (is_array($array[$currentIndex]) && $array[$currentIndex]) 
        { 
            return _array_search_dot($indexes, $array[$currentIndex]); 
        } 
 
        // Otherwise we've found our match! 
        return $array[$currentIndex]; 
    } 
} 
 
if (! function_exists('array_deep_search')) 
{ 
    /** 
     * Returns the value of an element at a key in an array of uncertain depth. 
     * 
     * @param mixed $key 
     * @param array $array 
     * 
     * @return mixed|null 
     */ 
    function array_deep_search($key, array $array) 
    { 
        if (isset($array[$key])) 
        { 
            return $array[$key]; 
        } 
 
        foreach ($array as $value) 
        { 
            if (is_array($value)) 
            { 
                if ($result = array_deep_search($key, $value)) 
                { 
                    return $result; 
                } 
            } 
        } 
 
        return null; 
    } 
} 
 
if (! function_exists('array_sort_by_multiple_keys')) 
{ 
    /** 
     * Sorts a multidimensional array by its elements values. The array 
     * columns to be used for sorting are passed as an associative 
     * array of key names and sorting flags. 
     * 
     * Both arrays of objects and arrays of array can be sorted. 
     * 
     * Example: 
     *     array_sort_by_multiple_keys($players, [ 
     *         'team.hierarchy' => SORT_ASC, 
     *         'position'       => SORT_ASC, 
     *         'name'           => SORT_STRING, 
     *     ]); 
     * 
     * The '.' dot operator in the column name indicates a deeper array or 
     * object level. In principle, any number of sublevels could be used, 
     * as long as the level and column exist in every array element. 
     * 
     * For information on multi-level array sorting, refer to Example #3 here: 
     * https://www.php.net/manual/de/function.array-multisort.php 
     * 
     * @param array $array       the reference of the array to be sorted 
     * @param array $sortColumns an associative array of columns to sort 
     *                           after and their sorting flags 
     * 
     * @return boolean 
     */ 
    function array_sort_by_multiple_keys(array &$array, array $sortColumns): bool 
    { 
        // Check if there really are columns to sort after 
        if (empty($sortColumns) || empty($array)) 
        { 
            return false; 
        } 
 
        // Group sorting indexes and data 
        $tempArray = []; 
        foreach ($sortColumns as $key => $sortFlag) 
        { 
            // Get sorting values 
            $carry = $array; 
 
            // The '.' operator separates nested elements 
            foreach (explode('.', $key) as $keySegment) 
            { 
                // Loop elements if they are objects 
                if (is_object(reset($carry))) 
                { 
                    // Extract the object attribute 
                    foreach ($carry as $index => $object) 
                    { 
                        $carry[$index] = $object->$keySegment; 
                    } 
 
                    continue; 
                } 
 
                // Extract the target column if elements are arrays 
                $carry = array_column($carry, $keySegment); 
            } 
 
            // Store the collected sorting parameters 
            $tempArray[] = $carry; 
            $tempArray[] = $sortFlag; 
        } 
 
        // Append the array as reference 
        $tempArray[] = &$array; 
 
        // Pass sorting arrays and flags as an argument list. 
        return array_multisort(...$tempArray); 
    } 
} 
 
if (! function_exists('array_flatten_with_dots')) 
{ 
    /** 
     * Flatten a multidimensional array using dots as separators. 
     * 
     * @param iterable $array The multi-dimensional array 
     * @param string   $id    Something to initially prepend to the flattened keys 
     * 
     * @return array The flattened array 
     */ 
    function array_flatten_with_dots(iterable $array, string $id = ''): array 
    { 
        $flattened = []; 
 
        foreach ($array as $key => $value) 
        { 
            $newKey = $id . $key; 
 
            if (is_array($value)) 
            { 
                $flattened = array_merge($flattened, array_flatten_with_dots($value, $newKey . '.')); 
            } 
            else 
            { 
                $flattened[$newKey] = $value; 
            } 
        } 
 
        return $flattened; 
    } 
} 
 
 |