<?php
class Custom extends Buyers
{
    //метод для транслитерации
    public function translit($text)
    {
        $ru = explode('-', "А-а-Б-б-В-в-Ґ-ґ-Г-г-Д-д-Е-е-Ё-ё-Є-є-Ж-ж-З-з-И-и-І-і-Ї-ї-Й-й-К-к-Л-л-М-м-Н-н-О-о-П-п-Р-р-С-с-Т-т-У-у-Ф-ф-Х-х-Ц-ц-Ч-ч-Ш-ш-Щ-щ-Ъ-ъ-Ы-ы-Ь-ь-Э-э-Ю-ю-Я-я");
        $en = explode('-', "a-a-b-b-v-v-g-g-g-g-d-d-e-e-e-e-e-e-zh-zh-z-z-i-i-i-i-i-i-j-j-k-k-l-l-m-m-n-n-o-o-p-p-r-r-s-s-t-t-u-u-f-f-h-h-ts-ts-ch-ch-sh-sh-sch-sch---y-y---e-e-yu-yu-ya-ya");
        $res = str_replace($ru, $en, $text);
        $res = preg_replace("/[\s]+/ui", "-", $res);
        $res = preg_replace("/[\-]+/ui", "-", $res);
        $res = preg_replace("/[^0-9a-z\-]/ui", "", $res);
        $res = strtolower($res);
        return trim($res);
    }

    public function generate_name($max = 10, $ext = false)
    {
        $name = "";
        $symbols = "0123456789abcdefghijklmnopqrstuvwxyz";
        $len = strlen($symbols)-1;
        for($i=0; $i<$max; $i++)
        {
            $s = rand(0,$len);
            $name .= $symbols[$s];
        }

        return $name . ($ext ? ".".$ext : "");
    }

    public function scan_dir($source_dir, $extensions = array())
    {
        $items = new stdClass();

        if(!$content = scandir($source_dir))
            return $items;

        $content = array_diff($content, array('..', '.'));
        foreach($content AS $key => $item)
        {
            if(is_dir($source_dir.$item))
                $items->dirs[] = $item;

            if(in_array(pathinfo($item, PATHINFO_EXTENSION), (array) $extensions))
                $items->files[] = $item;
        }
        return $items;
    }

    //метод для проверки на роботов.
    public function is_bot()
    {
        $minimal_score = 0.5;
        // если чего то нет, то автоматом пропускаем проверку
        if(!$this->settings->secret_key || !$this->settings->site_key)
            return false;

        if(empty($_POST['g-recaptcha-response']))
            return false;

        $url = sprintf('https://www.google.com/recaptcha/api/siteverify?secret=%s&response=%s', $this->settings->secret_key, $_POST['g-recaptcha-response']);
        $response = file_get_contents($url);
        $json = json_decode($response);

        if(!$json->success)
            return true;

        if(isset($json->score) && $json->score > $minimal_score)
            return false;

        return true;
    }

    //определяем город посетителдя по его IP
    public function get_city()
    {
        $ip = $this->request->ip();
        //укажите токен из системы dadata
        $token = "";
        $url = "https://suggestions.dadata.ru/suggestions/api/4_1/rs/iplocate/address";

        $response = file_get_contents($url, false,
            stream_context_create(
                array(
                    'http'=>array(
                        "header"    =>"Content-Type: application/json\r\n"."Accept: application/json\r\n"."Authorization: Token $token",
                        "method"    => "POST",
                        "timeout"    => 2,
                        "content"    => json_encode(array("ip" => $ip))
                    )
                )
            )
        );
        $dadata = json_decode($response);
        return $dadata->location->data->city ?? "NA";
    }

    public function compress($content, $type = "html")
    {
        $level = $this->config->minify[$type];

        //правила только для js.
        if($type == "js")
        {
            if($level != "none")
            {
                $content = preg_replace("~(^|\s{1,})((//(.*?)+(\n|$))|(/\*(.*?)\*/))~ms", " ", $content);
                $content = preg_replace("~(\b)(\n(\s{1,}\b))~m", ";", $content);
                $content = preg_replace("#\s+#", " ", $content);
            }

            //при макс. сжатии убираем пробелы
            if($level == "max")
                $content = preg_replace("#\s?(:|}|{|,|;|!=|!==|===|==|=|\|\||&&)\s?#", "$1", $content);
        }

        //правила только для css
        if($type == "css")
        {
            if($level != "none")
            {
                //многострочные комментарии вида /* comment */
                $content = preg_replace("~(^|\s{1,})(/\*(.*?)\*/)~ms", " ", $content);
                //заменяем путь ../images/test.png на /design/theme/images/test.png
                $content = str_replace("..", "/design/".$this->settings->theme, $content);
                /* удаляем табуляторы, переводы строк и множественные пробелы */
                $content = preg_replace("#\s+#", " ", $content);
            }
            //при макс. сжатии добаваляем ещё правила
            if($level == "max")
            {
                $content = str_replace(array(", .", ";}", "( ", " )"),  array(",.", "}", "(", ")"), $content);
                $content = preg_replace("#\s?(:|;|}|{)\s?#", "$1", $content);
            }
        }

        //правила только для html
        if($type == "html")
        {
            if($level != "none")
            {
                $content = preg_replace("/<!--(.*?)-->/sm", "", $content);
                /* удаляем табуляторы, переводы строк и множественные пробелы */
                $content = preg_replace("#\s+#", " ", $content);
            }
            //при макс. сжатии добаваляем ещё правила
            if($level == "max")
                $content = str_replace(array("> <", " >", "< "), array("><", ">", "<"), $content);
        }
        return trim($content);
    }

    /*
        Получает список файлов в виде массива и возвращает путь до сжатого файла.
        Пример работы в качестве функции на смарти:
        {packer var="css_packed_file" files=$css_files}
    */
    public function packer($files)
    {
        $all_in_one = "";
        //по умолчанию не перепаковываем
        $repack = false;
        //сожмем все файлы
        foreach($files AS $file)
        {
            if(is_readable($file))
            {
                $type = pathinfo($file, PATHINFO_EXTENSION);
                $level = $this->config->minify[$type];

                if($type == "js" || $type == "css")
                {
                    $content = file_get_contents($file);

                    if($level != "none")
                        $content = $this->compress($content, $type);

                    //имя файла показывается только если стоит сжатие
                    $all_in_one .= ($level != "none" ? "/*File: {$file}*/" : "").$content."\n";
                }
                else
                    $all_in_one .= "/*Invalid filetype ({$type})*/\n";
            }
            else
                $all_in_one .= "/*File {$file} not found or unavailable*/\n";
        }

        // Выполняем проверку по дате изменения файлов только если файл уже создан
        $out_file = "cache/".$this->settings->theme.".packed.".$type;
        if(file_exists($out_file))
        {
            foreach($files AS $file)
            {
                // Если дата изменения любого из файлов старше сжатого файла, то перепакуем файл
                if(filemtime($file) > filemtime($out_file))
                    $repack = true;
            }

            // Если было изменение хоть в одном из файлов
            if(md5($all_in_one) <> md5(file_get_contents($out_file)))
                $repack = true;
        }
        else
            $repack = true;

        if($repack)
            file_put_contents($out_file, $all_in_one);

        return $out_file;
    }

    /**
     * Магический метод для обработки вызовов get_*, add_*, update_*, delete_*
     */
    public function __call($name, $arguments)
    {
        if(preg_match('/^(get|add|update|delete)_([a-zA-Z0-9_]+)$/', $name, $matches))
        {
            $action = $matches[1];
            $table = $matches[2];
            $method = $action."_item";

            return $this->$method($table, $arguments);
        }
    }

    /**
     * Получить записи (всегда возвращается массив) *
     */
    protected function get_item($table, $arguments)
    {
        $where = "";
        $filter = $arguments[0];
        //для ассоциативного массива делаем поиск по ключам
        if(is_array($filter) && !array_is_list($filter))
        {
            foreach($filter AS $key => $value)
                $where .= $this->db->placehold(" AND {$key} = ?", $value);
        }
        else
            $where = $this->db->placehold(" AND id IN (?@)", (array) $filter);

        $this->db->query("SELECT * FROM {$table} WHERE 1 {$where}");
        return $this->db->results();
    }

    /**
     * Добавить запись
     */
    protected function add_item($table, $arguments)
    {
        $query = $this->db->placehold("INSERT INTO {$table} SET ?%", $arguments[0]);
        return $this->db->insert_id();
    }

    /**
     * Обновить запись
     */
    protected function update_item($table, $arguments)
    {
        $this->db->query("UPDATE {$table} SET ?% WHERE id = ?", $arguments[1], $arguments[0]);
        return $this->db->affected_rows();
    }

    /**
     * Удалить запись
     */
    protected function delete_item($table, $arguments)
    {
        $id = (array) $arguments[0];
        $this->db->query("DELETE FROM {$table} WHERE id IN (?@) LIMIT ?", $id, count($id));
        return $this->db->affected_rows();
    }
}
