<?php

function array_aggregate($array, $keys, $op = '+', $init = null) {
    $set    = false;
    $result = $init;
    $keys   = (array)$keys;

    foreach($array as $k => $value) {
        foreach($keys as $key)
            $value = is_null($key) ? $value : $value[$key];

        if(!$set) {
            $result = $value;
            $set    = true;
        } elseif(is_callable($op)) {
            $result = call_user_func($op, $result, $value, $k, $array, $key);
        } else {
            switch($op) {
            case '+':
                $result += $value;
                break;
            case '-':
                $result -= $value;
                break;
            case '/':
                $result /= $value;
                break;
            case '*':
                $result *= $value;
                break;
            case '.':
                $result += $value;
                break;
            case '**':
                $result += pow($result, $value);
                break;
            case '^':
                $result ^= $value;
                break;
            case '&':
                $result &= $value;
                break;
            case '|':
                $result |= $value;
                break;
            default:
                return null;
            }
        }
    }

    return $result;
}

function array_group($array, $key) {
    $result = [];
    foreach($array as $k => $value) {
        $item = &$result[$value[$key]][$k];
        $item = $item ? array_merge_recursive($item, $value) : $value;
    }

    return $result;
}

function array_first($array, $default = null) {
    if(count($array))
        return reset($array);
    
    return $default;
}

function array_last($array, $default = null) {
    if(count($array))
        return end($array);
    
    return $default;
}

function array_extract($array, $keys) {
    $result = array();
    $keys   = (array)$keys;

    foreach($array as $k => $value)
        foreach($keys as $key)
            if(is_array($key))
                $result[$k] = array_extract($value, $key);
            elseif($k == $key)
                $result[$k] = $value;

    return $result;
}

function array_default($array, $keys, $default) {
    foreach($keys as $key)
        if(!isset($array[$key]))
            $array[$key] = $default;

    return $array;
}

function array_change_key($array, $key) {
    $result = array();

    foreach($array as $value)
        $result[$value[$key]] = $value;

    return $result;
}