<?php
/**
 * Класс-обертка для обращения к переменным _GET, _POST, _FILES, _COOKIE
 */
class Request extends Buyers
{
    /**
     * Конструктор, чистка слешей
     */
    public function __construct()
    {
        $_GET = $this->stripslashes_array($_GET);
        $_POST = $this->stripslashes_array($_POST);
        $_COOKIE = $this->stripslashes_array($_COOKIE);
    }

    /**
    * Определение request-метода обращения к странице (GET, POST)
    * Если задан аргумент функции (название метода, в любом регистре), возвращает true или false
    * Если аргумент не задан, возвращает имя метода
    * Пример:
    *
    *    if($this->request->method('post'))
    *        print 'Request method is POST';
    *
    */
    public function method($method = null)
    {
        if(!empty($method))
            return strtolower($_SERVER['REQUEST_METHOD']) == strtolower($method);

        return $_SERVER['REQUEST_METHOD'];
    }

    /**
    * Фильтрация получаемых данных
    */
    public function filter($val, $type = false)
    {
        //если не указан тип данных, то возвращаем как есть
        if(!$type)
            return $val;

        return match($type)
        {
            "email"   => filter_var($val, FILTER_VALIDATE_EMAIL),
            "string"  => trim(strval(preg_replace('/[^\p{L}\p{Nd}\d\s_@\-\:\.,\%\s]/ui', '', $val))),
            "phone"   => strval(preg_replace('/[^\d\+\(\)\s\-]/ui', '', $val)),
            "integer" => intval($val),
            "float"   => floatval($val),
            "boolean" => !empty($val),
            "null"    => empty($val) ? null : $val
            //"null"    => ($val == '' || $val == 0 || $val == false) ? null : $val
        };
    }

    /**
    * Возвращает переменную _GET, отфильтрованную по заданному типу, если во втором параметре указан тип фильтра
    * Если $type не задан, возвращает переменную как есть
    */
    public function get($name, $type = null)
    {
        $val = '';
        if(isset($_GET[$name]))
            $val = $_GET[$name];

        if(!empty($type) && is_array($val))
            $val = reset($val);
        //фильтруем переменную по тем типам данных которые у нас есть
        $val = $this->filter($val, $type);
        return $val;
    }

    /**
    * Возвращает переменную _COOKIE, отфильтрованную по заданному типу, если во втором параметре указан тип фильтра
    * Если $type не задан, возвращает переменную как есть
    */
    public function cookie($name, $type = null)
    {
        $val = '';
        if(isset($_COOKIE[$name]))
            $val = $this->filter($_COOKIE[$name], $type);
        return $val;
    }

    /**
    * Возвращает переменную _POST, отфильтрованную по заданному типу, если во втором параметре указан тип фильтра
    * Если $type не задан, возвращает переменную в чистом виде
    */
    public function post($name = null, $type = null)
    {
        $val = '';
        if(!empty($name) && isset($_POST[$name]))
            $val = $_POST[$name];
        elseif(empty($name))
            $val = file_get_contents('php://input');
        //фильтруем переменную по тем типам данных которые у нас есть
        $val = $this->filter($val, $type);
        return $val;
    }

    /**
    * Возвращает переменную _FILES
    * Обычно переменные _FILES являются двухмерными массивами, поэтому можно указать второй параметр,
    * например, чтобы получить имя загруженного файла: $filename = $buyers->request->files('myfile', 'name');
    */
    public function files($name, $name2 = null)
    {
        if(!empty($name2) && !empty($_FILES[$name][$name2]))
            return $_FILES[$name][$name2];
        elseif(empty($name2) && !empty($_FILES[$name]))
            return $_FILES[$name];
        else
            return null;
    }

    /**
     * Рекурсивная чистка магических слешей
     */
    private function stripslashes_array($array)
    {
        return is_array($array) ? array_map($this->stripslashes_array, $array) : stripslashes($array);
    }

    /**
     * Получение ип адреса пользователя
     */
    public function ip()
    {
        return filter_var($_SERVER['HTTP_CLIENT_IP'] ?? ($_SERVER['HTTP_X_FORWARDED_FOR'] ?? $_SERVER['REMOTE_ADDR']), FILTER_VALIDATE_IP);
    }

    /**
     * Переадресация пользователя
     */
    public function redirect($url)
    {
        if(is_array($url))
            $url = $this->url($url);

        header("Location: ".$url);
        exit();
    }


    public function url($params = array())
    {
        $anchor = '';
        if(!empty($params['#']))
        {
            $anchor = '#'.$params['#'];
            unset($params['#']);
        }

        $url = parse_url($_SERVER["REQUEST_URI"]);
        $result = $url['path'];

        if($params = array_filter($params))
            $result .= '?'.http_build_query($params);

        return $result . $anchor;
    }

    /**
     * Установка заголовков для страницы по типам данных
     */
    public function set_header($type)
    {
        $contentType = match ($type) {
            'json'  => 'application/json; charset=UTF-8',
            'image' => 'image/jpeg',
            'text'  => 'text/plain; charset=UTF-8',
            'html'  => 'text/html; charset=UTF-8',
            'xml'   => 'text/xml; charset=UTF-8',
            default => 'text/html; charset=UTF-8',
        };

        header("Content-type: {$contentType}");
        header("Cache-Control: must-revalidate");
        header("Pragma: no-cache");
        header("Expires: -1");
    }
}
