<?php

//------    CONVERTIR NUMEROS A LETRAS         ---------------
//------    Máxima cifra soportada: 18 dígitos con 2 decimales
//------    999,999,999,999,999,999.99
// NOVECIENTOS NOVENTA Y NUEVE MIL NOVECIENTOS NOVENTA Y NUEVE BILLONES
// NOVECIENTOS NOVENTA Y NUEVE MIL NOVECIENTOS NOVENTA Y NUEVE MILLONES
// NOVECIENTOS NOVENTA Y NUEVE MIL NOVECIENTOS NOVENTA Y NUEVE PESOS 99/100 M.N.
//------    Creada por:                        ---------------
//------             ULTIMINIO RAMOS GALÁN     ---------------
//------            uramos@gmail.com           ---------------
//------    10 de junio de 2009. México, D.F.  ---------------
//------    PHP Version 4.3.1 o mayores

function numtoletras($xcifra)
{
    $xarray = array(
        0 => "Cero",
        1 => "UN", "DOS", "TRES", "CUATRO", "CINCO", "SEIS", "SIETE", "OCHO", "NUEVE", "DIEZ", "ONCE", "DOCE", "TRECE", "CATORCE", "QUINCE", "DIECISEIS", "DIECISIETE", "DIECIOCHO", "DIECINUEVE", "VEINTI",
        30 => "TREINTA",
        40 => "CUARENTA",
        50 => "CINCUENTA",
        60 => "SESENTA",
        70 => "SETENTA",
        80 => "OCHENTA",
        90 => "NOVENTA",
        100 => "CIENTO",
        200 => "DOSCIENTOS",
        300 => "TRESCIENTOS",
        400 => "CUATROCIENTOS",
        500 => "QUINIENTOS",
        600 => "SEISCIENTOS",
        700 => "SETECIENTOS",
        800 => "OCHOCIENTOS",
        900 => "NOVECIENTOS"
    );

    $xcifra = trim($xcifra);
    $xlength = strlen($xcifra);
    $xpos_punto = strpos($xcifra, ".");
    $xaux_int = $xcifra;
    $xdecimales = "00";
    if (!($xpos_punto === false)) {
        if ($xpos_punto == 0) {
            $xcifra = "0" . $xcifra;
            $xpos_punto = strpos($xcifra, ".");
        }
        $xaux_int = substr($xcifra, 0, $xpos_punto); // obtengo el entero de la cifra a covertir
        $xdecimales = substr($xcifra . "00", $xpos_punto + 1, 2); // obtengo los valores decimales
    }

    $XAUX = str_pad($xaux_int, 18, " ", STR_PAD_LEFT); // ajusto la longitud de la cifra, para que sea divisible por centenas de miles (grupos de 6)
    $xcadena = "";
    for ($xz = 0; $xz < 3; $xz++) {
        $xaux = substr($XAUX, $xz * 6, 6);
        $xi = 0;
        $xlimite = 6; // inicializo el contador de centenas xi y establezco el límite a 6 dígitos en la parte entera
        $xexit = true; // bandera para controlar el ciclo del While
        while ($xexit) {
            if ($xi == $xlimite) { // si ya llegó al límite máximo de enteros
                break; // termina el ciclo
            }

            $x3digitos = ($xlimite - $xi) * -1; // comienzo con los tres primeros digitos de la cifra, comenzando por la izquierda
            $xaux = substr($xaux, $x3digitos, abs($x3digitos)); // obtengo la centena (los tres dígitos)
            for ($xy = 1; $xy < 4; $xy++) { // ciclo para revisar centenas, decenas y unidades, en ese orden
                switch ($xy) {

                    case 1: // checa las centenas
                        if (substr($xaux, 0, 3) < 100) { // si el grupo de tres dígitos es menor a una centena ( < 99) no hace nada y pasa a revisar las decenas

                        } else {
                            $key = (int)substr($xaux, 0, 3);
                            if (true === array_key_exists($key, $xarray)) {  // busco si la centena es número redondo (100, 200, 300, 400, etc..)
                                $xseek = $xarray[$key];
                                $xsub = subfijo($xaux); // devuelve el subfijo correspondiente (Millón, Millones, Mil o nada)
                                if (substr($xaux, 0, 3) == 100)
                                    $xcadena = " " . $xcadena . " CIEN " . $xsub;
                                else
                                    $xcadena = " " . $xcadena . " " . $xseek . " " . $xsub;
                                $xy = 3; // la centena fue redonda, entonces termino el ciclo del for y ya no reviso decenas ni unidades
                            } else { // entra aquí si la centena no fue numero redondo (101, 253, 120, 980, etc.)
                                $key = (int)substr($xaux, 0, 1) * 100;
                                $xseek = $xarray[$key]; // toma el primer caracter de la centena y lo multiplica por cien y lo busca en el arreglo (para que busque 100,200,300, etc)
                                $xcadena = " " . $xcadena . " " . $xseek;
                            } // ENDIF ($xseek)
                        } // ENDIF (substr($xaux, 0, 3) < 100)
                        break;

                    case 2: // checa las decenas (con la misma lógica que las centenas)
                        if (substr($xaux, 1, 2) < 10) {

                        } else {
                            $key = (int)substr($xaux, 1, 2);
                            if (true === array_key_exists($key, $xarray)) {
                                $xseek = $xarray[$key];
                                $xsub = subfijo($xaux);
                                if (substr($xaux, 1, 2) == 20)
                                    $xcadena = " " . $xcadena . " VEINTE " . $xsub;
                                else
                                    $xcadena = " " . $xcadena . " " . $xseek . " " . $xsub;
                                $xy = 3;
                            } else {
                                $key = (int)substr($xaux, 1, 1) * 10;
                                $xseek = $xarray[$key];
                                if (20 == substr($xaux, 1, 1) * 10)
                                    $xcadena = " " . $xcadena . " " . $xseek;
                                else
                                    $xcadena = " " . $xcadena . " " . $xseek . " Y ";
                            } // ENDIF ($xseek)
                        } // ENDIF (substr($xaux, 1, 2) < 10)
                        break;
                    case 3: // checa las unidades
                        if (substr($xaux, 2, 1) < 1) { // si la unidad es cero, ya no hace nada

                        } else {
                            $key = (int)substr($xaux, 2, 1);
                            $xseek = $xarray[$key]; // obtengo directamente el valor de la unidad (del uno al nueve)
                            $xsub = subfijo($xaux);
                            $xcadena = " " . $xcadena . " " . $xseek . " " . $xsub;
                        } // ENDIF (substr($xaux, 2, 1) < 1)
                        break;
                } // END SWITCH
            } // END FOR
            $xi = $xi + 3;
        } // ENDDO

        if (substr(trim($xcadena), -5, 5) == "ILLON") // si la cadena obtenida termina en MILLON o BILLON, entonces le agrega al final la conjuncion DE
        $xcadena .= " DE";

        if (substr(trim($xcadena), -7, 7) == "ILLONES") // si la cadena obtenida en MILLONES o BILLONES, entoncea le agrega al final la conjuncion DE
        $xcadena .= " DE";

        // ----------- esta línea la puedes cambiar de acuerdo a tus necesidades o a tu país -------
        if (trim($xaux) != "") {
            switch ($xz) {
                case 0:
                    if (trim(substr($XAUX, $xz * 6, 6)) == "1")
                        $xcadena .= "UN BILLON ";
                    else
                        $xcadena .= " BILLONES ";
                    break;
                case 1:
                    if (trim(substr($XAUX, $xz * 6, 6)) == "1")
                        $xcadena .= "UN MILLON ";
                    else
                        $xcadena .= " MILLONES ";
                    break;
                case 2:
                    if ($xcifra < 1) {
                        $xcadena = "CERO $xdecimales/100 ";
                    }
                    if ($xcifra >= 1 && $xcifra < 2) {
                        $xcadena = "UN SOL Y $xdecimales/100 ";
                    }
                    if ($xcifra >= 2) {
                        $xcadena .= " Y $xdecimales/100 "; //
                    }
                    break;
            } // endswitch ($xz)
        } // ENDIF (trim($xaux) != "")
        // ------------------      en este caso, para México se usa esta leyenda     ----------------
        $xcadena = str_replace("VEINTI ", "VEINTI", $xcadena); // quito el espacio para el VEINTI, para que quede: VEINTICUATRO, VEINTIUN, VEINTIDOS, etc
        $xcadena = str_replace("  ", " ", $xcadena); // quito espacios dobles
        $xcadena = str_replace("UN UN", "UN", $xcadena); // quito la duplicidad
        $xcadena = str_replace("  ", " ", $xcadena); // quito espacios dobles
        $xcadena = str_replace("BILLON DE MILLONES", "BILLON DE", $xcadena); // corrigo la leyenda
        $xcadena = str_replace("BILLONES DE MILLONES", "BILLONES DE", $xcadena); // corrigo la leyenda
        $xcadena = str_replace("DE UN", "UN", $xcadena); // corrigo la leyenda
    } // ENDFOR ($xz)

    return trim($xcadena);

}
// END FUNCTION

function subfijo($xx)
{ // esta función regresa un subfijo para la cifra
    $xx = trim($xx);
    $xstrlen = strlen($xx);
    if ($xstrlen == 1 || $xstrlen == 2 || $xstrlen == 3)
        $xsub = "";
    //
    if ($xstrlen == 4 || $xstrlen == 5 || $xstrlen == 6)
        $xsub = "MIL";
    //
    return $xsub;
}
// END FUNCTION

//RANDPOM STRING
function randomstring($len)
{
    $string = "";
    $chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
    for ($i = 0; $i < $len; $i++)
        $string .= substr($chars, rand(0, strlen($chars)), 1);
    return $string;
}
/************************ KENY PONTE - 11/06/2020**************************** */
function replace_invalid_caracters($cadena) {
    $cadena = str_replace("'", "", $cadena);
    $cadena = str_replace("#", "", $cadena);
    $cadena = str_replace("$", "", $cadena);
    $cadena = str_replace("%", "", $cadena);
    $cadena = str_replace("&", "", $cadena);
    $cadena = str_replace("'", "", $cadena);
    $cadena = str_replace("(", "", $cadena);
    $cadena = str_replace(")", "", $cadena);
    $cadena = str_replace("*", "", $cadena);
    $cadena = str_replace("+", "", $cadena);
    $cadena = str_replace("-", "", $cadena);
    $cadena = str_replace(".", "", $cadena);
    $cadena = str_replace("/", "", $cadena);
    $cadena = str_replace("<", "", $cadena);
    $cadena = str_replace("=", "", $cadena);
    $cadena = str_replace(">", "", $cadena);
    $cadena = str_replace("?", "", $cadena);
    $cadena = str_replace("@", "", $cadena);
    $cadena = str_replace("[", "", $cadena);
    $cadena = str_replace("\\", "", $cadena);
    $cadena = str_replace("]", "", $cadena);
    $cadena = str_replace("^", "", $cadena);
    $cadena = str_replace("_", "", $cadena);
    $cadena = str_replace("`", "", $cadena);
    $cadena = str_replace("{", "", $cadena);
    $cadena = str_replace("|", "", $cadena);
    $cadena = str_replace("}", "", $cadena);
    $cadena = str_replace("~", "", $cadena);
    $cadena = str_replace("¡", "", $cadena);
    $cadena = str_replace("¢", "", $cadena);
    $cadena = str_replace("£", "", $cadena);
    $cadena = str_replace("¤", "", $cadena);
    $cadena = str_replace("¥", "", $cadena);
    $cadena = str_replace("¦", "", $cadena);
    $cadena = str_replace("§", "", $cadena);
    $cadena = str_replace("¨", "", $cadena);
    $cadena = str_replace("©", "", $cadena);
    $cadena = str_replace("ª", "", $cadena);
    $cadena = str_replace("«", "", $cadena);
    $cadena = str_replace("¬", "", $cadena);
    $cadena = str_replace("®", "", $cadena);
    $cadena = str_replace("°", "", $cadena);
    $cadena = str_replace("±", "", $cadena);
    $cadena = str_replace("²", "", $cadena);
    $cadena = str_replace("³", "", $cadena);
    $cadena = str_replace("´", "", $cadena);
    $cadena = str_replace("µ", "", $cadena);
    $cadena = str_replace("¶", "", $cadena);
    $cadena = str_replace("·", "", $cadena);
    $cadena = str_replace("¸", "", $cadena);
    $cadena = str_replace("¹", "", $cadena);
    $cadena = str_replace("º", "", $cadena);
    $cadena = str_replace("»", "", $cadena);
    $cadena = str_replace("¼", "", $cadena);
    $cadena = str_replace("½", "", $cadena);
    $cadena = str_replace("¾", "", $cadena);
    $cadena = str_replace("¿", "", $cadena);
    $cadena = str_replace("À", "A", $cadena);
    $cadena = str_replace("Á", "A", $cadena);
    $cadena = str_replace("Â", "A", $cadena);
    $cadena = str_replace("Ã", "A", $cadena);
    $cadena = str_replace("Ä", "A", $cadena);
    $cadena = str_replace("Å", "A", $cadena);
    $cadena = str_replace("Æ", "", $cadena);
    $cadena = str_replace("Ç", "", $cadena);
    $cadena = str_replace("È", "E", $cadena);
    $cadena = str_replace("É", "E", $cadena);
    $cadena = str_replace("Ê", "E", $cadena);
    $cadena = str_replace("Ë", "E", $cadena);
    $cadena = str_replace("Ì", "I", $cadena);
    $cadena = str_replace("Í", "I", $cadena);
    $cadena = str_replace("Î", "I", $cadena);
    $cadena = str_replace("Ï", "I", $cadena);
    $cadena = str_replace("Ð", "", $cadena);
    $cadena = str_replace("Ñ", "N", $cadena);
    $cadena = str_replace("Ò", "O", $cadena);
    $cadena = str_replace("Ó", "O", $cadena);
    $cadena = str_replace("Ô", "O", $cadena);
    $cadena = str_replace("Õ", "O", $cadena);
    $cadena = str_replace("Ö", "O", $cadena);
    $cadena = str_replace("×", "", $cadena);
    $cadena = str_replace("Ø", "", $cadena);
    $cadena = str_replace("Ù", "U", $cadena);
    $cadena = str_replace("Ú", "U", $cadena);
    $cadena = str_replace("Û", "U", $cadena);
    $cadena = str_replace("Ü", "U", $cadena);
    $cadena = str_replace("Ý", "Y", $cadena);
    $cadena = str_replace("Þ", "", $cadena);
    $cadena = str_replace("ß", "", $cadena);
    $cadena = str_replace("à", "a", $cadena);
    $cadena = str_replace("á", "a", $cadena);
    $cadena = str_replace("â", "a", $cadena);
    $cadena = str_replace("ã", "a", $cadena);
    $cadena = str_replace("ä", "a", $cadena);
    $cadena = str_replace("å", "a", $cadena);
    $cadena = str_replace("æ", "", $cadena);
    $cadena = str_replace("ç", "", $cadena);
    $cadena = str_replace("è", "e", $cadena);
    $cadena = str_replace("é", "e", $cadena);
    $cadena = str_replace("ê", "e", $cadena);
    $cadena = str_replace("ë", "e", $cadena);
    $cadena = str_replace("ì", "i", $cadena);
    $cadena = str_replace("í", "i", $cadena);
    $cadena = str_replace("î", "i", $cadena);
    $cadena = str_replace("ï", "i", $cadena);
    $cadena = str_replace("ð", "o", $cadena);
    $cadena = str_replace("ñ", "n", $cadena);
    $cadena = str_replace("ò", "o", $cadena);
    $cadena = str_replace("ó", "o", $cadena);
    $cadena = str_replace("ô", "o", $cadena);
    $cadena = str_replace("õ", "o", $cadena);
    $cadena = str_replace("ö", "o", $cadena);
    $cadena = str_replace("÷", "", $cadena);
    $cadena = str_replace("ø", "", $cadena);
    $cadena = str_replace("ù", "u", $cadena);
    $cadena = str_replace("ú", "u", $cadena);
    $cadena = str_replace("û", "u", $cadena);
    $cadena = str_replace("ü", "u", $cadena);
    $cadena = str_replace("ý", "y", $cadena);
    $cadena = str_replace("þ", "", $cadena);
    $cadena = str_replace("ÿ", "", $cadena);
    $cadena = str_replace("Œ", "", $cadena);
    $cadena = str_replace("œ", "", $cadena);
    $cadena = str_replace("Š", "", $cadena);
    $cadena = str_replace("š", "", $cadena);
    $cadena = str_replace("Ÿ", "", $cadena);
    $cadena = str_replace("ƒ", "", $cadena);
    $cadena = str_replace("–", "", $cadena);
    $cadena = str_replace("—", "", $cadena);
    $cadena = str_replace("‘", "", $cadena);
    $cadena = str_replace("’", "", $cadena);
    $cadena = str_replace("‚", "", $cadena);
    $cadena = str_replace("“", "", $cadena);
    $cadena = str_replace("”", "", $cadena);
    $cadena = str_replace("„", "", $cadena);
    $cadena = str_replace("†", "", $cadena);
    $cadena = str_replace("‡", "", $cadena);
    $cadena = str_replace("•", "", $cadena);
    $cadena = str_replace("…", "", $cadena);
    $cadena = str_replace("‰", "", $cadena);
    $cadena = str_replace("€", "", $cadena);
    $cadena = str_replace("™", "", $cadena);

    return $cadena;
}
/********************KENY PONTE - 11/06/2020*********************** */

function array_group_by(array $arr, $key)  {
    if (!is_string($key) && !is_int($key) && !is_float($key) && !is_callable($key)) {
        trigger_error('array_group_by(): The key should be a string, an integer, a float, or a function', E_USER_ERROR);
    }

    $isFunction = !is_string($key) && is_callable($key);

    // Load the new array, splitting by the target key
    $grouped = [];
    foreach ($arr as $value) {
        $groupKey = null;

        if ($isFunction) {
            $groupKey = $key($value);
        } else if (is_object($value)) {
            $groupKey = $value->{$key};
        } else {
            $groupKey = $value[$key];
        }

        $grouped[$groupKey][] = $value;
    }

    // Recursively build a nested grouping if more parameters are supplied
    // Each grouped array value is grouped according to the next sequential key
    if (func_num_args() > 2) {
        $args = func_get_args();

        foreach ($grouped as $groupKey => $value) {
            $params = array_merge([$value], array_slice($args, 2, func_num_args()));
            $grouped[$groupKey] = call_user_func_array('array_group_by', $params);
        }
    }

    return $grouped;
}
?>