<?php
class Files extends Buyers
{
    //постоянная папка
    public $files_dir = "files/docs/";
    //временная папка
    public $temp_files_dir = "cache/tmp/";

    public $allowed_extensions = array(
        "jpg"  => "ffd8ff",
        "png"  => "89504e",
        "webp" => "524946",
        "gif"  => "474946",
        "psd"  => "384250",
        "avi"  => "524946",
        "mkv"  => "1a45df",
        "mov"  => "000000",
        "mp4"  => "000000",
        "mp3"  => "494433",
        "pdf"  => "255044",
        "xls"  => "d0cf11",
        "doc"  => "d0cf11",
        "docx" => "504b03",
        "xlsx" => "504b03",
        "rar"  => "526172",
        "zip"  => "504b03",
    );

    public function __construct()
    {
        if(!is_dir($this->config->root_dir.$this->files_dir))
            mkdir($this->config->root_dir.$this->files_dir, 0755);

        if(!is_dir($this->config->root_dir.$this->temp_files_dir))
            mkdir($this->config->root_dir.$this->temp_files_dir, 0755);
    }

    public function add_file($file)
    {
        $this->db->query("INSERT INTO files SET ?%", $file);
        return $this->db->insert_id();
    }

    public function get_files($filter = array())
    {
        $filter_relation = '';
        $filter_relation_id = '';

        if(isset($filter['relation']))
            $filter_relation = $this->db->placehold('AND relation = ?', $filter['relation']);

        if(isset($filter['relation_id']))
            $filter_relation_id = $this->db->placehold('AND relation_id IN(?@)', (array)$filter['relation_id']);

        $query = "SELECT * FROM files WHERE 1 $filter_relation $filter_relation_id ORDER BY position ASC";
        $this->db->query($query);

        return $this->db->results();
    }

    public function update_file($id, $file)
    {
        $query = $this->db->placehold("UPDATE files SET ?% WHERE id=? LIMIT 1", $file, intval($id));
        $this->db->query($query);
        return $this->db->affected_rows();
    }

    public function update_files($page_id, $relation = 'pages')
    {
        //если изменили описание у файлов или обновили позиции
        if($files = $this->request->post('files'))
        foreach($files['id'] AS $key => $id)
            $this->files->update_file($id, array("position" => $key, "name" => $files['name'][$key]));

        //если переданы id для удаления
        $this->delete_files();

        //если есть что закачивать (перемещать из временной папки в постоянную)
        if($uploads = $this->request->post('upload'))
        foreach($uploads AS $u)
        {
            //данные по файлу которые сформировались на момент закачки файла на сервер
            $attach = json_decode($u);
            $attach->added = date("Y-m-d H:i:s");
            $attach->relation = $relation;
            $attach->relation_id = $page_id;
            $attach->position = isset($key) ? ++$key : 0;
            $attach->filepath = $this->files_dir . $attach->filename;

            rename($this->temp_files_dir . $attach->filename, $attach->filepath);
            chmod($attach->filepath, 0644);
            $this->files->add_file($attach);
        }
    }

    public function delete_files()
    {
        if($delete_files = $this->request->post('delete_files'))
        foreach($delete_files AS $file_id)
        {
            $this->db->query("SELECT filepath FROM files WHERE id = ? LIMIT 1", $file_id);
            if($filepath = $this->db->result('filepath'))
            {
                if(strpos($filepath, $this->files_dir) === 0)
                {
                    unlink($filepath);
                    $this->db->query("DELETE FROM files WHERE id = ?", $file_id);
                }
            }
        }
    }

    public function upload_file($post_filename)
    {
        //часть файла
        $chunk = file_get_contents("php://input");

        //если сессии нет, то закачка только началась
        if(!$tmpfile = $this->sessions->post_filename)
        {
            //тип файла который был передан в имени файла
            $type = strtolower(pathinfo($post_filename, PATHINFO_EXTENSION));
            //сформируем уникальное имя закачиваемому файлу сохранив расширение файла
            $tmpfile = $this->temp_files_dir . $this->custom->generate_name(7, $type);
            $this->sessions->post_filename = $tmpfile;
        }

        //идёт загрузка
        if(!empty($chunk))
            file_put_contents($tmpfile, base64_decode($chunk), FILE_APPEND);

        if($this->request->get('finished'))
        {
            unset($this->sessions->post_filename);

            //фактический тип файла
            if(!$type = $this->get_extension($tmpfile, $post_filename))
                exit('Unknown filetype');

            return array('name' => $post_filename, 'filename' => basename($tmpfile), 'filesize' => filesize($tmpfile), 'filetype' => $type);
        }
    }

    public function get_extension($tmpfile, $post_filename)
    {
        //тип файла переданный в запросе
        $type = strtolower(pathinfo($post_filename, PATHINFO_EXTENSION));

        //получаем первые 3 байта закачиваемого файла
        $handle = fopen($tmpfile, "r");
        $file_bytes = bin2hex(fread($handle, 3));
        fclose($handle);

        //если такого типа файла нет в белом списке
        if(!$this->allowed_extensions[$type])
            return false;

        //равен ли тип передаваемого файла фактическому
        if($this->allowed_extensions[$type] !== $file_bytes)
            return false;

        return $type;
    }
}
