<?php

defined('GX_LIB') or die('Direct Access Not Allowed!');

class Typo
{
    public static function cleanX($c)
    {
        $val = self::strip_tags_content($c, '<script>', true);
        $val = preg_replace_callback(
            '#\<pre\>(.+?)\<\/pre\>#s',
            function ($matches) {
                return "<pre>" . str_replace('"', '&quot;', $matches[1]) . "</pre>";
            },
            $val
        );
        $val = self::filterXss($val);
        $val = htmlspecialchars($val, ENT_QUOTES | ENT_HTML5, 'UTF-8');
        $val = str_replace('\\', "\\\\", $val);
        return $val;
    }

    public static function Xclean($vars)
    {
        $var = htmlspecialchars_decode($vars, ENT_QUOTES | ENT_HTML5);
        $var = str_replace('\\\\', '\\', $var);
        return $var;
    }

    public static function slugify($text)
    {
        $text = strip_tags($text);
        $text = preg_replace('~[^\\pL\d]+~u', '-', $text);
        $text = trim($text, '-');
        if (function_exists('iconv')) {
            $text = iconv('UTF-8', 'ASCII//TRANSLIT//IGNORE', $text);
        }
        $text = strtolower($text);
        $text = preg_replace('~[^-\w]+~', '', $text);
        return empty($text) ? 'n-a' : $text;
    }

    public static function strip($text, $tags = '', $invert = false)
    {
        preg_match_all('/<(.+?)[\s]*\/?[\s]*>/si', trim($tags), $tags);
        $tags = array_unique($tags[1]);

        if (is_array($tags) && count($tags) > 0) {
            if (!$invert) {
                $text = preg_replace('@<(?!(?:' . implode('|', $tags) . ')\b)(\w+)\b.*?>@si', '', $text);
                $text = preg_replace('@</(?!(?:' . implode('|', $tags) . ')\b)(\w+)\b.*?>@si', '', $text);
            } else {
                $text = preg_replace('@<(' . implode('|', $tags) . ')\b.*?>@si', '', $text);
                $text = preg_replace('@</(' . implode('|', $tags) . ')\b.*?>@si', '', $text);
            }
        } elseif (!$invert) {
            $text = preg_replace('@<(\w+)\b.*?>@si', '', $text);
            $text = preg_replace('@</(\w+)\b.*?>@si', '', $text);
        }

        return $text;
    }

    public static function strip_tags_content($text, $tags = '', $invert = false)
    {
        preg_match_all('/<(.+?)[\s]*\/?[\s]*>/si', trim($tags), $tags);
        $tags = array_unique($tags[1]);

        if (is_array($tags) && count($tags) > 0) {
            if (!$invert) {
                return preg_replace('@<(?!(?:' . implode('|', $tags) . ')\b)(\w+)\b.*?>.*?</\1>@si', '', $text);
            } else {
                return preg_replace('@<(' . implode('|', $tags) . ')\b.*?>.*?</\1>@si', '', $text);
            }
        } elseif (!$invert) {
            return preg_replace('@<(\w+)\b.*?>.*?</\1>@si', '', $text);
        }

        return $text;
    }

    public static function crypto_rand_secure($min, $max)
    {
        $range = $max - $min;
        if ($range < 0) return $min;
        $log = log($range, 2);
        $bytes = (int) ($log / 8) + 1;
        $bits = (int) $log + 1;
        $filter = (1 << $bits) - 1;
        do {
            $rnd = hexdec(bin2hex(openssl_random_pseudo_bytes($bytes)));
            $rnd = $rnd & $filter;
        } while ($rnd >= $range);

        return $min + $rnd;
    }

    public static function getToken($length)
    {
        $token = '';
        $codeAlphabet = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
        $max = strlen($codeAlphabet) - 1;
        for ($i = 0; $i < $length; ++$i) {
            $token .= $codeAlphabet[self::crypto_rand_secure(0, $max)];
        }
        return $token;
    }

    public static function int($var)
    {
        return (int) $var;
    }

    public static function float($var)
    {
        return number_format((float)$var, 2, '.', '');
    }

    public static function escape($vars)
    {
        return Db::escape($vars);
    }

    public static function nl2p($string, $line_breaks = true, $xml = true)
    {
        $string = str_replace(['<p>', '</p>', '<br>', '<br />'], '', $string);
        if ($line_breaks) {
            return '<p>' . preg_replace(
                ["/([\n]{2,})/i", "/([^>])\n([^<])/i"],
                ["</p>\n<p>", '$1<br' . ($xml ? ' /' : '') . '>$2'],
                trim($string)
            ) . '</p>';
        } else {
            return '<p>' . preg_replace(
                ["/([\n]{2,})/i", "/([\r\n]{3,})/i", "/([^>])\n([^<])/i"],
                ["</p>\n<p>", "</p>\n<p>", '$1<br' . ($xml ? ' /' : '') . '>$2'],
                trim($string)
            ) . '</p>';
        }
    }

    public static function url2link($text)
    {
        return preg_replace(
            '@((https?://)([^\s<>]+))@i',
            '<a href="$1" target="_blank" rel="nofollow">$1</a>',
            $text
        );
    }

    public static function p2nl($string)
    {
        return str_replace(['<p>', '</p>', '<br>', '<br />'], ["", "\n", "", ""], $string);
    }

    public static function p2br($string)
    {
        return str_replace(['<p>', '</p>'], ['', '<br />'], $string);
    }

    public static function jsonFormat($var)
    {
        $var = str_replace(["\r\n", "\r"], "\n", $var);
        $var = str_replace("\n", '\\n', $var);
        $var = str_replace("'", '\\u0027', $var);
        $var = preg_replace_callback('/<([^<>]+)>/', fn($m) => str_replace('"', '\"', $m[0]), $var);
        $var = str_replace('/>', ' />', $var);
        $var = str_replace('</', '<\/', $var);
        $var = self::cleanX($var);
        return str_replace('\&', '&', $var);
    }

    public static function jsonDeFormat($var)
    {
        return utf8_decode($var);
    }

    public static function validateEmail($email)
    {
        return filter_var($email, FILTER_VALIDATE_EMAIL) !== false;
    }

    public static function filterXss($str)
    {
        return preg_replace([
            '#(onload|onerror|onblur|onchange|onscroll|oninput|onfocus|onbeforescriptexecute|ontoggle|onratechange|onreadystatechange|onpropertychange|onqt_error|onpageshow|onclick|onmouseover|onunload|event|formaction|actiontype|background|oncut)=("|\')(.*?)("|\')#is',
            '#javascript:#i'
        ], '', $str);
    }
}
