<?php
/**
 * Created by IntelliJ IDEA.
 * User: Miles
 * Date: 1/13/17
 * Time: 4:28 AM
 */

namespace CarbonPHP;

use CarbonPHP\Error\PublicAlert;
use CarbonPHP\Helpers\Files;

/** This pro is in the trait Singleton, but intellij is being dumb and needs some help
 * @property null storage
 */
class Request   // requires carbon::application;
{
    use Singleton; // provides us with the variable $storage which we will call the `set` or group of key => value pairs

    ########################## Manual Input ################################

    /** Adds comma separated parameters to the set
     * @param array ...$argv
     * @return Request
     */
    public function set(...$argv): self
    {
        /** @noinspection PhpUndefinedFieldInspection - this is defined in the singleton */
        $this->storage = $argv;
        return $this;
    }

    ########################## Session Storage #############################

    /** Headers can only be sent and set if output has not already started.
     *  If we attempt to set a header after output has started, store it and
     *  send on the next request.
     * @return void
     */
    public static function sendHeaders(): void
    {
        if (!(SOCKET || headers_sent())) {
            if (isset($_SESSION['Cookies']) && \is_array($_SESSION['Cookies'])) {
                foreach ($_SESSION['Cookies'] as $key => $array) {
                    if ($array[1] ?? false) {
                        static::setCookie($key, $array[0] ?? null, $array[1]);
                    } else {
                        static::setCookie($key, $array[0] ?? null);
                    }
                }
            }

            if (isset($_SESSION['Headers']) && \is_array($_SESSION['Headers'])) {
                foreach ($_SESSION['Headers'] as $value) {
                    static::setHeader($value);
                }
            }
            unset($_SESSION['Cookies'], $_SESSION['Headers']);
        }
    }

    /** Cookies are a pain to set up as they also rely on headers not being sent.
     *  This method makes setting cookies easy with three params.
     * @param string $key the name of the cookie
     * @param mixed $value
     * @param int $time the expiration time of our cookie
     */
    public static function setCookie(string $key, $value = null, int $time = 604800): void // Week?
    {
        if (headers_sent()) {
            $_SESSION['Cookies'][] = [$key => [$value, $time]];
        } else {
            setcookie($key, $value, time() + $time, '/', SITE, HTTPS, true);
        }
    }

    /**
     * Clear all active cookies in the current session
     */
    public function clearCookies(): void
    {
        $all = array_keys(\is_array($_COOKIE) ? $_COOKIE : []);
        foreach ($all as $key => $value) {
            static::setCookie($value);
        }
    }       // Supporting function to setCookie

    /**
     * @param string $string is passed to the php header function
     * @link http://php.net/manual/en/function.header.php
     */
    public static function setHeader(string $string): void
    {
        if (!(\defined('SOCKET') && SOCKET)) {
            if (headers_sent()) {
                /** @noinspection UnsupportedStringOffsetOperationsInspection */
                $_SESSION['Headers'][] = $string;
            } else {
                header($string);
            }
        }
    }

    /** This method requires that PJAX be a loaded JS include in
     * our html page. This does not hard refresh the url, or execute
     * a new instance on the uri's route... It just changes the uri
     * in the browser.
     * @param string $string the new uri location.
     */
    public static function changeURI(string $string): void
    {
        $_SERVER['REQUEST_URI'] = $string;
        static::setHeader('X-PJAX-URL: ' . SITE . $string);
    }

    ########################### Request Data ###############################

    /** Request is a blanket method for other data validation procedures.
     * @param array $argv values should match the keys in the given set
     * @param array $array usually a transfer protocol ($_POST, $_GET, $_COOKIE)
     * @param bool $removeHTML if true htmlspecialchars() will be run on each member of the set
     * @link http://php.net/manual/en/function.htmlspecialchars.php
     * @return Request
     */
    private function request(array $argv, array &$array, bool $removeHTML = false): self
    {
        $this->storage = null;
        $closure = function ($key) use ($removeHTML, &$array) {
            if (array_key_exists($key, $array)) {
                $this->storage[] = $removeHTML ? htmlspecialchars($array[$key]) : $array[$key];
                $array[$key] = null;    // by reference, if we validate it then we should ensure no one uses it
            } else {
                $this->storage[] = false;
            }
        };
        if (\count($argv) === 0 || !array_walk($argv, $closure)) {
            $this->storage = [];
        }
        return $this;
    }

    /** Runs a callable function on every member of the $storage set.
     * If one value is present one value will be returned. If an array
     * is set, and array will be returned.
     * @param callable $closure
     * @return bool|\Closure
     */
    public function closure_array_walk(callable $closure)
    {
        if (empty($this->storage)) {
            return false;
        }

        if (\is_array($this->storage)) {
            array_walk($this->storage, $closure);
        } else {
            $closure($this->storage);
        }

        return function ($array) {
            return \count($array) === 1 ? array_shift($array) : $array;
        };
    }

    /** Filter the $_GET array with the arguments passed in
     * @param array ...$argv
     * @return Request
     */
    public function get(...$argv): self
    {
        return $this->request($argv, $_GET);
    }

    /** Filter the $_POST array with the arguments passed in
     * @param array ...$argv
     * @return Request
     */
    public function post(...$argv): self
    {
        return $this->request($argv, $_POST);
    }

    /** Filter the $_COOKIE array with the arguments passed in
     * @param array ...$argv
     * @return Request
     */
    public function cookie(...$argv): self
    {
        return $this->request($argv, $_COOKIE, true);
    }

    /** Filter the $_FILES array with the arguments passed in
     * @param array ...$argv
     * @return Request
     */
    public function files(...$argv): self
    {
        return $this->request($argv, $_FILES);
    }

    ########################### Store Files   #############################

    /** storeFiles attempts to store files currently in the storage set
     * @param string $location the location to store the files
     * @return array|mixed
     * @throws PublicAlert if the files fail to be stored
     */
    public function storeFiles(string $location = 'Data/Uploads/Temp/')
    {
        $storagePath = array();
        return $this->closure_array_walk(function ($file) use ($location, &$storagePath) {
            $storagePath[] = Files::uploadFile($file, $location);
        })($storagePath);
    }

    ##########################  Storage Shifting  #########################

    /** Attempts to base64 decode all members of our set
     * @return Request
     */
    public function base64_decode(): self
    {
        $array = [];
        $this->closure_array_walk(function ($key) use (&$array) {
            $array[] = base64_decode($key, true);
        });
        return $this;
    }

    /** Checks our set to see if our set contains the key
     * @param string $key
     * @return bool
     */
    public function has(string $key): bool
    {
        return array_key_exists($key, $this->storage);
    }

    /** Removes passed arguments from the set
     * @param array ...$argv
     * @return Request
     */
    public function except(...$argv): self
    {
        array_walk($argv, function ($key) {
            if (array_key_exists($key, $this->storage)) {
                unset($this->storage[$key]);
            }
        });
        return $this;
    }

    ########################## Validating    ##############################

    /** Use a built-in PHP "is_" method on a given set.
     *  If a member of the set is not valid its value will be set to false
     *  Possible options include:
     *      a
     *      array
     *      bool
     *      callable
     *      double
     *      dir
     *      executable
     *      file
     *      finite
     *      float
     *      infinite
     *      int
     *      integer
     *      iterable
     *      link
     *      long
     *      nan
     *      null
     *      numeric
     *      object
     *      readable
     *      real
     *      scalar
     *      soap_fault
     *      string
     *      resource
     *      uploaded_file
     *      is_writeable
     *      is_writable
     *
     * @param string $type
     * @return array|bool|mixed
     * @throws \InvalidArgumentException
     */
    public function is(string $type)
    {
        if (!\function_exists($type = 'is_' . strtolower($type))) {
            throw new \InvalidArgumentException('Function is_$type() could not be found. Please check arguments supplied to is.');
        }

        $array = [];
        return $this->closure_array_walk(function ($key) use ($type, &$array) {
            $array[] = $type($key) ? $key : false;
        })($array);
    }

    /** Preforms a regex expression using preg_match on each member of the set
     * @link http://php.net/manual/en/function.preg-match.php
     * @param string $condition
     * @return array|bool|mixed
     */
    public function regex(string $condition)
    {
        $array = [];
        return $this->closure_array_walk(function ($key) use ($condition, &$array) {
            return $array[] = (preg_match($condition, $key) ? $key : false);
        })($array);
    }

    /**Check for character(s) / array members / representing a hexadecimal digit
     * @link http://php.net/manual/en/function.ctype-xdigit.php
     * @return mixed
     */
    public function hex()
    {
        $array = [];
        return $this->closure_array_walk(function ($key) use (&$array) {
            return $array[] = (ctype_xdigit($key) ? $key : false);
        })($array);
    }

    /** Removes HTML chars from a given set
     * @param bool $complete if set to true than $this
     * will be returned
     * @return array|bool|Request|mixed
     */
    public function noHTML($complete = false)
    {   // Disallow: $, ", ', <, >
        $array = [];
        $fn = $this->closure_array_walk(function ($key) use (&$array) {
            return $array[] = htmlspecialchars($key);
        });

        if ($complete) {
            return $fn($array);
        }

        return $this;
    }

    /** Returns found integers between the given min and max if set. If no max
     * or min is set, just validate integers.
     * @param int|null $min
     * @param int|null $max
     * @return array|bool|mixed
     */
    public function int(int $min = null, int $max = null)   // inclusive max and min
    {
        $array = [];
        return $this->closure_array_walk(function ($key) use (&$array, $min, $max) {
            if (($key = (int)$key) === false) {
                return $array[] = false;
            }
            if ($max !== null) {
                $key = ($key <= $max ? $key : false);
            }
            if ($min !== null) {
                $key = ($key >= $min ? $key : false);
            }
            return $array[] = $key;
        })($array);
    }

    /** Runs a regex expression to find dates matching the pattern
     *         11/12/1995
     * @return array|bool|mixed
     */
    public function date()
    {
        return $this->regex('#^\d{1,2}\/\d{1,2}\/\d{4}$#');
    }

    /** Check for alphanumeric character(s)
     * @link http://php.net/manual/en/function.ctype-alnum.php
     * @return array|bool|mixed
     */
    public function alnum()
    {
        $array = [];
        return $this->closure_array_walk(function ($key) use (&$array) {
            return $array[] = (ctype_alnum($key) ? $key : false);
        })($array);
    }           // One word alpha numeric

    /**
     * Filter text only with regex
     * @return array|bool|mixed
     */
    public function text()
    {
        return $this->regex('/([\w\s])+/');   // Multiple word alpha numeric
    }

    /** Filter single words containing only letters
     * @return array|bool|mixed
     */
    public function word()
    {
        return $this->regex('/^[A-Za-z]+$/');
    }

    public function words()
    {
        return $this->regex('/^[\w]+$/');
    }

    /** Filters phone numbers matching the pattern
     *        #((\(\d{3}\) ?)|(\d{3}-))?\d{3}-\d{4}#
     * @return array|bool|mixed
     */
    public function phone()
    {
        $array = [];
        return $this->closure_array_walk(function ($arg) use (&$array) {
            return $array[] = preg_match('#((\(\d{3}\) ?)|(\d{3}-))?\d{3}-\d{4}#', $arg) ? $this->storage[0] : false;
        })($array);
    }

    /**Checks to see if emails names are given in the set
     * @return array|bool|mixed
     */
    public function email()
    {
        $array = [];
        return $this->closure_array_walk(function ($key) use (&$array) {
            $array[] = filter_var($key, FILTER_VALIDATE_EMAIL);
        })($array);
    }

    /** Checks to see if domain names are given in the set
     * @link http://php.net/manual/en/function.filter-var.php
     * @return array|bool|mixed
     */
    public function website()
    {
        $array = [];
        return $this->closure_array_walk(function ($key) use (&$array) {
            $array[] = filter_var($key, FILTER_VALIDATE_URL);
        })($array);
    }

    /** returns our full current set
     * @return array|bool|mixed
     */
    public function value()
    {
        return \count($this->storage) === 1 ? array_shift($this->storage) : $this->storage;
    }

}


<?php
/**
 * Created by PhpStorm.
 * User: wj008
 * Date: 2017/12/20
 * Time: 0:40
 */

namespace beacon\widget;

use beacon\Field;
use beacon\Form;
use beacon\Request;
use beacon\Utils;
use beacon\View;

class Container extends Hidden
{
    /**
     * 完善字段信息
     * @param Field $field
     * @param Form $form
     * @param string $index
     */
    public static function perfect(Field $field, Form $form, $index = '@@index@@')
    {
        $fields = $form->getFields();
        foreach ($fields as $name => $child) {
            if ($field->dataValDisabled) {
                $child->dataValDisabled = true;
            }
            //当个
            if ($field->mode == 'single') {
                $child->boxId = $field->boxId . '_' . $child->boxId;
                $child->boxName = $field->boxName . '[' . $child->boxName . ']';
                //如果存在拆分的时候
                if ($child->names && is_array($child->names)) {
                    $names = $child->names;
                    foreach ($names as $nKey => $nItem) {
                        if (is_array($nItem) && $nItem['field']) {
                            $nItem['field'] = $field->boxName . '[' . $nItem['field'] . ']';
                        } elseif (is_string($nItem)) {
                            $nItem = $field->boxName . '[' . $nItem . ']';
                        }
                        $names[$nKey] = $nItem;
                    }
                    $child->names = $names;
                }
                //修正动态数据
                if (!empty($child->dynamic)) {
                    $form->createDynamic($child);
                    $dataDynamic = $child->dataDynamic;
                    foreach ($dataDynamic as &$item) {
                        foreach (['show', 'hide', 'off', 'on'] as $key) {
                            if (isset($item[$key])) {
                                if (is_string($item[$key])) {
                                    $item[$key] = explode(',', $item[$key]);
                                }
                                if (is_array($item[$key])) {
                                    foreach ($item[$key] as $idx => $xit) {
                                        $item[$key][$idx] = $field->boxId . '_' . $xit;
                                    }
                                }
                            }
                        }
                    }
                    $child->dataDynamic = $dataDynamic;
                }

            } //多组
            else if ($field->mode == 'multiple') {
                $child->boxId = $field->boxId . '_' . $index . '_' . $child->boxId;
                $child->boxName = $field->boxName . '[' . $index . '][' . $child->boxName . ']';
                //如果存在拆分的时候
                if ($child->names && is_array($child->names)) {
                    $names = $child->names;
                    foreach ($names as $nKey => $nItem) {
                        if (is_array($nItem) && $nItem['field']) {
                            $nItem['field'] = $field->boxName . '[' . $index . '][' . $nItem['field'] . ']';
                        } elseif (is_string($nItem)) {
                            $nItem = $field->boxName . '[' . $index . '][' . $nItem . ']';
                        }
                        $names[$nKey] = $nItem;
                    }
                    $child->names = $names;
                }
                if (!empty($child->dynamic)) {
                    $form->createDynamic($child);
                    $dataDynamic = $child->dataDynamic;
                    foreach ($dataDynamic as &$item) {
                        foreach (['show', 'hide', 'off', 'on'] as $key) {
                            if (isset($item[$key])) {
                                if (is_string($item[$key])) {
                                    $item[$key] = explode(',', $item[$key]);
                                }
                                if (is_array($item[$key])) {
                                    foreach ($item[$key] as $idx => $xit) {
                                        $item[$key][$idx] = $field->boxId . '_' . $index . '_' . $xit;
                                    }
                                }
                            }
                        }
                    }
                    $child->dataDynamic = $dataDynamic;
                }
            }
            $child->dataValOutput = '#' . $field->boxId . '-validation';
        }
    }

    /**
     * 获取插件表单
     * @param Field $field
     * @param string|null $type
     * @return Form
     * @throws \Exception
     */
    public static function plugForm(Field $field, string $type = null)
    {
        $className = $field->plugName;
        if (empty($className) || !class_exists($className)) {
            throw new \Exception('没有找到插件的类 ' . $className);
        }
        if ($type) {
            return new $className($type);
        }
        return new $className($field->getForm()->getType());
    }

    /**
     * 生成代码
     * @param Field $field
     * @param array $attr
     * @return string
     * @throws \Exception
     */
    public function code(Field $field, $attr = [])
    {
        $field->mode = empty($field->mode) ? 'single' : $field->mode;
        #单一模式
        if ($field->mode == 'single') {
            $attr['type'] = '';
            $attr['name'] = '';
            $attr['value'] = '';
            $attr['class'] = '';
            $attr['id'] = 'row_' . $field->boxId;
            $attr = WidgetHelper::mergeAttributes($field, $attr);
            if (empty($field->plugName)) {
                return '

';
            }
            $form = self::plugForm($field);
            if (empty($form->template)) {
                throw new \Exception('插件模板不存在');
            }
            $viewer = new View();
            $viewer->fetch($form->template);
            $wrapFunc = $viewer->getHook('single');
            if ($wrapFunc == null) {
                throw new \Exception('模板中没有找到 {hook fn="single"} 的钩子函数');
            }
            $tinker = $field->getFunc('tinker');
            if ($tinker && is_callable($tinker)) {
                call_user_func($tinker, $form);
            }
            $form->setValues($field->value);
            self::perfect($field, $form);
            $code = $wrapFunc(['field' => $field, 'form' => $form]);
            return '
' . $code . '
';
        } else {
            #多增模式
            if (empty($field->plugName)) {
                return '';
            }
            $form = self::plugForm($field, 'add');
            if (empty($form->template)) {
                throw new \Exception('插件模板不存在');
            }
            $viewer = new View();
            $viewer->fetch($form->template);
            $wrapFunc = $viewer->getHook('multiple-wrap');
            $itemFunc = $viewer->getHook('multiple-item');
            if ($wrapFunc == null) {
                throw new \Exception('模板中没有找到 {hook fn="multiple-wrap"} 的钩子函数');
            }
            if ($itemFunc == null) {
                throw new \Exception('模板中没有找到 {hook fn="multiple-item"} 的钩子函数');
            }
            $out = [];
            $values = $field->value;
            $index = 0;
            $tinker = $field->getFunc('tinker');
            if (!empty($values) && is_array($values)) {
                foreach ($values as $idx => $item) {
                    $pForm = self::plugForm($field, 'edit');
                    if ($tinker && is_callable($tinker)) {
                        call_user_func($tinker, $pForm);
                    }
                    $pForm->setValues($item);
                    self::perfect($field, $pForm, $index);
                    $code = $itemFunc(['field' => $field, 'form' => $pForm, 'index' => 'a' . $index]);
                    $out[] = $code;
                    $index++;
                }
            }
            if ($tinker && is_callable($tinker)) {
                call_user_func($tinker, $form);
            }
            self::perfect($field, $form);
            $code = $itemFunc(['field' => $field, 'form' => $form, 'index' => '@@index@@']);
            $data = [];
            $data[] = 'data-index="' . htmlspecialchars($index) . '"';
            if ($field->dataMinSize) {
                $data[] = 'data-min-size="' . $field->dataMinSize . '"';
            }
            if ($field->dataMaxSize) {
                $data[] = 'data-max-size="' . $field->dataMaxSize . '"';
            }
            if ($field->dataInitSize) {
                $data[] = 'data-init-size="' . $field->dataInitSize . '"';
            }
            return $wrapFunc([
                'field' => $field,
                'form' => $form,
                'body' => join('', $out),
                'source' => base64_encode($code),
                'lastIndex' => $index,
                'attrs' => join(' ', $data)
            ]);
        }
    }

    /**
     * @param Field $field
     * @param array $input
     * @return array|null
     * @throws \Exception
     */
    public function assign(Field $field, array $input)
    {
        $field->mode = empty($field->mode) ? 'single' : $field->mode;
        $boxName = $field->boxName;
        $itemData = Request::input($input, $boxName . ':a', $field->default);
        if (empty($field->plugName)) {
            return $field->value;
        }
        //单个
        if ($field->mode == 'single') {
            $form = self::plugForm($field);
            $tinker = $field->getFunc('tinker');
            if ($tinker && is_callable($tinker)) {
                call_user_func($tinker, $form);
            }
            $childValue = $form->fillComplete($itemData);
            if ($field->dataValDisabled !== true) {
                if (!$form->validation($errors)) {
                    $childError = [];
                    foreach ($errors as $key => $err) {
                        $boxName = $field->boxName . '[' . $key . ']';
                        $childError[$boxName] = $err;
                    }
                    $field->childError = $childError;
                }
            }
            $field->value = $childValue;
            return $field->value;
        }
        //多个
        if ($field->mode == 'multiple') {
            $temp = [];
            $childError = [];
            foreach ($itemData as $idx => $item) {
                $form = self::plugForm($field);
                $tinker = $field->getFunc('tinker');
                if ($tinker && is_callable($tinker)) {
                    call_user_func($tinker, $form);
                }
                $childValue = $form->fillComplete($item);
                if ($field->dataValDisabled !== true) {
                    $errors = [];
                    if (!$form->validation($errors)) {
                        foreach ($errors as $key => $err) {
                            $boxName = $field->boxName . '[' . $idx . '][' . $key . ']';
                            $childError[$boxName] = $err;
                        }
                    }
                }
                $temp[] = $childValue;
            }
            $field->childError = $childError;
            $field->value = $temp;
            return $field->value;
        }
    }

    public function fill(Field $field, array &$values)
    {
        $values[$field->name] = json_encode($field->value, JSON_UNESCAPED_UNICODE);
    }

    public function init(Field $field, array $values)
    {
        $temp = isset($values[$field->name]) ? $values[$field->name] : null;
        $value = null;
        if (is_array($temp)) {
            $value = $temp;
        } else if (is_string($temp) && Utils::isJson($temp)) {
            $value = json_decode($temp, true);
        }
        $field->value = $value;
    }

}


<?php

namespace beacon;

use \PDO as PDO;

/**
 * 数据分页类 of Pagelist
 *
 * @author WJ008
 */
class PageList
{

    private $sql;
    private $page; //当前页面
    private $recordsCount = -1;  //记录数
    private $onlyCount = -1; //仅显示
    private $pageSize; //页面大小
    private $pageCount; //最大页数
    private $key;
    private $args;
    private $info = null;
    /**
     * @var SqlSelector
     */
    private $selector = null;

    /**
     * 数据库分页类

     * (MysqlDB >= 1.0.0, SaMao >= 1.0.0)

     * @param string $sql 要执行的SQL语句
     * @param array $args sql参数数组
     * @param int $size 分页大小
     * @param string $key 分页的URL名称$_GET['?']
     */
    public function __construct($sql, $args = array(), $size = 20, $key = 'page')
    {
        $this->sql = $sql;
        $this->pageSize = intval($size);
        $this->key = $key;
        $this->args = $args;
        $this->page = intval(isset($_REQUEST[$key]) ? $_REQUEST[$key] : '1');
        $this->pageCount = -1;
    }

    /**
     * 直接给定记录数可以提高查询效率
     * @param int $count 记录数
     */
    public function setCount($count)
    {
        $this->recordsCount = $count;
    }

    public function setSelector(SqlSelector $selector)
    {
        $this->selector = $selector;
    }

    /**
     * 设置最大分页行数
     * @param int $count 只显示几条记录
     */
    public function setOnlyCount($count)
    {
        $this->onlyCount = $count;
    }

    private function getPageCount($count, $size)
    {
        if (($count % $size) == 0) {
            $pageCount = ($count / $size);
        } else {
            $pageCount = (int)($count / $size) + 1;
        }
        if ($pageCount == 0) {
            $pageCount = 1;
        }
        return $pageCount;
    }

    /**
     * 获取 分页信息数据
     * array(

     * 'page_key'      ：分页参数名称 如果 page,

     * 'query'         ：本页所附带的连接 即 $_SERVER['REQUEST_URI']
例如 cid=3&keyword=abc&page=3

     * 'other_query'   ：除了page 外的所有 附带参数,
例如 cid=3&keyword=abc 不带页码参数

     * 'page'          ：当前 页码,

     * 'page_count'    ：页数，即最大页数,

     * 'records_count' ：记录数,

     * 'size'          ：分页尺度，即按多少条记录为一页,

     * )
     * @return array|null
     * @throws \Exception
     */
    public function getInfo()
    {
        if ($this->info != null) {
            return $this->info;
        }
        if ($this->recordsCount == -1) {
            if ($this->selector) {
                $this->recordsCount = $this->selector->getCount();
            } else {
                if (strripos($this->sql, ' from ') === stripos($this->sql, ' from ')) {
                    $sql = preg_replace('@^select\s+(distinct\s+[a-z][a-z0-9]+\s*,)?(.*)\s+from\s+@', 'select $1count(1) from ', $this->sql);
                    $row = DB::getRow($sql, $this->args, PDO::FETCH_NUM);
                } else {
                    $row = DB::getRow('select count(1) from (' . $this->sql . ') MyTempTable', $this->args, PDO::FETCH_NUM);
                }
                $this->recordsCount = $row[0];
            }
        }
        if ($this->onlyCount == -1 || $this->onlyCount > $this->recordsCount) {
            $this->onlyCount = $this->recordsCount;
        }
        if ($this->pageCount == -1) {
            $this->pageCount = $this->getPageCount($this->onlyCount, $this->pageSize);
        }
        if ($this->page <= 0) {
            $this->page = 1;
        }
        if ($this->page > $this->pageCount) {
            $this->page = $this->pageCount;
        }
        $this->info = array(
            'keyName' => $this->key,
            'page' => $this->page,
            'pageCount' => $this->pageCount,
            'recordsCount' => $this->recordsCount,
            'onlyCount' => $this->onlyCount,
            'pageSize' => $this->pageSize,
        );
        return $this->info;
    }

    /**
     *  获取 分页后的记录集数据
     * @param null $fetch_style
     * @param null $fetch_argument
     * @param array|null $ctor_args
     * @return array
     * @throws \Exception
     */
    public function getList($fetch_style = null, $fetch_argument = null, array $ctor_args = null)
    {
        $this->getInfo();
        $start = ($this->page - 1) * $this->pageSize;
        if ($start < 0) {
            $start = 0;
        }
        if ($this->selector) {
            $this->selector->limit($start, $this->pageSize);
            return $this->selector->getListByPageList();
        }
        $sql = $this->sql . ' limit ' . $start . ' , ' . $this->pageSize;
        return DB::getList($sql, $this->args, $fetch_style, $fetch_argument, $ctor_args);
    }

    /**
     * 获取所有数据
     * @param null $fetch_style
     * @param null $fetch_argument
     * @param array|null $ctor_args
     * @return array
     * @throws \Exception
     */
    public function getAll($fetch_style = null, $fetch_argument = null, array $ctor_args = null)
    {
        return DB::getList($this->sql, $this->args, $fetch_style, $fetch_argument, $ctor_args);
    }
}


<?php
/**
 * Created by PhpStorm.
 * User: wj008
 * Date: 18-11-15
 * Time: 下午10:17
 */

namespace beacon\widget;

use beacon\Field;
use beacon\Logger;
use beacon\Request;
use beacon\Utils;

class WidgetHelper
{
    /**
     * 根据类型 获取对应的值
     * @param string $varType
     * @param array $input
     * @param string $key
     * @return null
     */
    public static function getValue(string $varType, array $input, string $key)
    {
        switch ($varType) {
            case 'bool':
            case 'boolean':
                return Request::input($input, $key . ':b', false);
            case 'int':
            case 'integer':
                $val = Request::input($input, $key . ':s', '');
                if (preg_match('@[+-]?\d*\.\d+@', $val)) {
                    return Request::input($input, $key . ':f', 0);
                } else {
                    return Request::input($input, $key . ':i', 0);
                }
            case 'double':
            case 'float':
                return Request::input($input, $key . ':f', 0);
            case 'string':
                return Request::input($input, $key . ':s', '');
            case 'array':
                return Request::input($input, $key . ':a', []);
            default :
                return Request::input($input, $key, '');
        }
        return null;
    }

    /**
     * 类型转换
     * @param $value
     * @param $type
     * @return array|bool|int|string
     */
    public static function convertType($value, $type)
    {
        switch ($type) {
            case 'bool':
            case 'boolean':
                if (is_string($value)) {
                    return $value === '1' || $value === 'on' || $value === 'yes' || $value === 'true';
                }
                return !!$value;
            case 'int':
            case 'integer':
                if (is_int($value) || is_float($value) || is_double($value) || is_bool($value)) {
                    return intval($value);
                } else if (is_string($value) && is_numeric($value)) {
                    return intval($value);
                }
                return 0;
            case 'double':
            case 'float':
                if (is_int($value) || is_float($value) || is_double($value) || is_bool($value)) {
                    return $value;
                }
                if (is_string($value) && is_numeric($value)) {
                    return floatval($value);
                }
                return 0;
            case 'array':
                if (is_array($value)) {
                    return $value;
                }
                return [$value];
            default :
                return strval($value);
        }
    }

    /**
     * 合并属性
     * @param Field $field
     * @param array $attrs
     * @return array
     */
    public static function mergeAttributes(Field $field, $attrs = null)
    {
        $attributes = $field->getAttributes();
        if (is_array($attrs)) {
            foreach ($attrs as $key => $val) {
                $key = Utils::camelToAttr($key);
                if ($key[0] == '@') {
                    continue;
                }
                $attributes[$key] = $val;
            }
        }
        $base = [];
        // Logger::log($attributes);
        /*
        if (isset($attributes['data-dynamic'])) {
            if (!isset($attributes['yee-module'])) {
                $attributes['yee-module'] = 'dynamic';
            } else {
                $attributes['yee-module'] .= ' dynamic';
            }
        }*/
        foreach ($attributes as $name => $val) {
            if ($val === null || $val === '') {
                continue;
            }
            if ($name == 'data-val') {
                $name = 'data-v@rule';
            } //验证数据
            else if (preg_match('@^data-val-(.*)$@', $name, $m)) {
                $name = 'data-v@' . $m[1];
            }
            if (is_array($val)) {
                array_push($base, $name . '="' . htmlspecialchars(json_encode($val, JSON_UNESCAPED_UNICODE)) . '"');
            } else if (is_bool($val)) {
                array_push($base, $name . '="' . ($val ? 1 : 0) . '"');
            } else if (is_string($val)) {
                array_push($base, $name . '="' . htmlspecialchars($val) . '"');
            } else {
                array_push($base, $name . '="' . $val . '"');
            }
        }
        return $base;
    }

}


<?php
/**
 * Ongr_Sniffs_ControlStructures_InlineControlStructureSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2014 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Ongr_Sniffs_ControlStructures_InlineIfDeclarationSniff.
 *
 * Tests the spacing of shorthand IF statements.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2014 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Ongr_Sniffs_ControlStructures_InlineIfDeclarationSniff implements PHP_CodeSniffer_Sniff
{

    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return array(T_INLINE_THEN);

    }//end register()

    /**
     * Processes this sniff, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token in the
     *                                        stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        $openBracket  = null;
        $closeBracket = null;
        if (isset($tokens[$stackPtr]['nested_parenthesis']) === true) {
            $parens       = $tokens[$stackPtr]['nested_parenthesis'];
            $openBracket  = array_pop($parens);
            $closeBracket = $tokens[$openBracket]['parenthesis_closer'];
        }

        // Find the beginning of the statement. If we don't find a
        // semicolon (end of statement) or comma (end of array value)
        // then assume the content before the closing parenthesis is the end.
        $else         = $phpcsFile->findNext(T_INLINE_ELSE, ($stackPtr + 1));
        $statementEnd = $phpcsFile->findNext(array(T_SEMICOLON, T_COMMA), ($else + 1), $closeBracket);
        if ($statementEnd === false) {
            $statementEnd = $phpcsFile->findPrevious(T_WHITESPACE, ($closeBracket - 1), null, true);
        }

        // Ongr we allow shorthand IF statements on multiple lines.
//        if ($tokens[$statementEnd]['line'] !== $tokens[$stackPtr]['line']) {
//            $error = 'Inline shorthand IF statement must be declared on a single line';
//            $phpcsFile->addError($error, $stackPtr, 'NotSingleLine');
//            return;
//        }

        // Make sure there are spaces around the question mark.
        $contentBefore = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 1), null, true);
        $contentAfter  = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true);

        //ONGR Brackets are not required.
//        if ($tokens[$contentBefore]['code'] !== T_CLOSE_PARENTHESIS) {
//            $error = 'Inline shorthand IF statement requires brackets around comparison';
//            $phpcsFile->addError($error, $stackPtr, 'NoBrackets');
//            return;
//        }

        $spaceBefore = ($tokens[$stackPtr]['column'] - ($tokens[$contentBefore]['column'] + strlen($tokens[$contentBefore]['content'])));
        if ($spaceBefore !== 1) {
            $error = 'Inline shorthand IF statement requires 1 space before THEN; %s found';
            $data  = array($spaceBefore);
            $phpcsFile->addError($error, $stackPtr, 'SpacingBeforeThen', $data);
        }

        $spaceAfter = (($tokens[$contentAfter]['column']) - ($tokens[$stackPtr]['column'] + 1));
        if ($spaceAfter !== 1) {
            $error = 'Inline shorthand IF statement requires 1 space after THEN; %s found';
            $data  = array($spaceAfter);
            $phpcsFile->addError($error, $stackPtr, 'SpacingAfterThen', $data);
        }

        // Make sure the ELSE has the correct spacing.
        $inlineElse    = $phpcsFile->findNext(T_INLINE_ELSE, ($stackPtr + 1), $statementEnd, false);
        $contentBefore = $phpcsFile->findPrevious(T_WHITESPACE, ($inlineElse - 1), null, true);
        $contentAfter  = $phpcsFile->findNext(T_WHITESPACE, ($inlineElse + 1), null, true);

        $spaceBefore = ($tokens[$inlineElse]['column'] - ($tokens[$contentBefore]['column'] + strlen($tokens[$contentBefore]['content'])));
        if ($spaceBefore !== 1) {
            $error = 'Inline shorthand IF statement requires 1 space before ELSE; %s found';
            $data  = array($spaceBefore);
            $phpcsFile->addError($error, $inlineElse, 'SpacingBeforeElse', $data);
        }

        $spaceAfter = (($tokens[$contentAfter]['column']) - ($tokens[$inlineElse]['column'] + 1));
        if ($spaceAfter !== 1) {
            $error = 'Inline shorthand IF statement requires 1 space after ELSE; %s found';
            $data  = array($spaceAfter);
            $phpcsFile->addError($error, $inlineElse, 'SpacingAfterElse', $data);
        }

    }//end process()

}//end class


<?php

namespace Axllent\Less;

use FilesystemIterator;
use RecursiveDirectoryIterator;
use RecursiveIteratorIterator;
use SilverStripe\Assets\FileNameFilter;
use SilverStripe\Control\Director;
use SilverStripe\Core\Config\Config;
use SilverStripe\Core\Flushable;
use SilverStripe\Core\Injector\Injector;
use SilverStripe\View\Requirements_Backend;
use SilverStripe\Assets\Storage\GeneratedAssetHandler;

/**
 * LESS.php CSS compiler for SilverStripe
 * ======================================
 *
 * Extension to add Less.php CSS compiling to SilverStripe
 *
 * Usage: See README.md
 *
 * License: MIT-style license http://opensource.org/licenses/MIT
 * Authors: Techno Joy development team (www.technojoy.co.nz)
 */

class LessCompiler extends Requirements_Backend implements Flushable
{

    /**
     * @config
     */
    private static $cache_method = 'serialize';

    /**
     * @config
     */
    private static $variables = [];

    private static $already_flushed = false;

    private static $processed_files = [];

    public function __construct()
    {
        $this->config = Config::inst();

        $this->asset_handler = $this->getAssetHandler();

        $this->file_name_filter = FileNameFilter::create();

        $this->is_dev = Director::isDev();
    }

    /**
     * Return cache directory
     * @param Null
     * @return String
     */
    private static function getCacheDir()
    {
        return TEMP_FOLDER . '/less-cache';
    }

    /**
     * Gets the default backend storage for generated files
     *
     * @return GeneratedAssetHandler
     */
    public function getAssetHandler()
    {
        return Injector::inst()->get(GeneratedAssetHandler::class);
    }

    /**
     * Triggered early in the request when a flush is requested
     * Deletes the less.php cache folder and regenerates
     */
    public static function flush()
    {
        if (!self::$already_flushed && file_exists(self::getCacheDir())) {
            $paths = new RecursiveIteratorIterator(
                new RecursiveDirectoryIterator(self::getCacheDir(), FilesystemIterator::SKIP_DOTS),
                RecursiveIteratorIterator::CHILD_FIRST
            );
            foreach ($paths as $path) {
                $path->isDir() && !$path->isLink() ? rmdir($path->getPathname()) : unlink($path->getPathname());
            }
            // make sure we only flush once per request and not for each *.less
            self::$already_flushed = true;
        }
    }

    /**
     * Register the given stylesheet into the list of requirements.
     * Processes *.less files if detected and rewrites URLs
     *
     * @param string $file The CSS file to load, relative to site root
     * @param string $media Comma-separated list of media types to use in the link tag (e.g. 'screen,projector')
     */
    public function css($file, $media = null)
    {
        $css_file = $this->processLessFile($file);
        return parent::css($css_file, $media);
    }

    /**
     * Process any less files and return new filenames
     * @See Requirements_Backend->combineFiles() for options
     */
    public function combineFiles($combinedFileName, $files, $options = array())
    {
        $new_files = [];

        foreach ($files as $file) {
            $new_files[] = $this->processLessFile($file);
        }

        return parent::combineFiles($combinedFileName, $new_files, $options);
    }

    /**
     * Process less file (if detected) and return new URL
     * @param String (original)
     * @return String (new filename)
     */
    public function processLessFile($file)
    {
        if (!preg_match('/\.less$/', $file)) { // Not a less file
            return $file;
        } elseif (!empty(self::$processed_files[$file])) { // already processed
            return self::$processed_files[$file];
        }

        $less_file = $file;

        // return if not a file
        if (!is_file(Director::getAbsFile($less_file))) {
            self::$processed_files[$file] = $file;
            return $file;
        }

        // Generate a new CSS filename that includes the original path to avoid naming conflicts.
        // eg: themes/site/css/file.less becomes themes-site-css-file.css
        $url_friendly_css_name = $this->file_name_filter->filter(
            str_replace('/', '-', preg_replace('/\.less$/i', '', $less_file))
        ) . '.css';

        $css_file = $this->getCombinedFilesFolder() . '/' . $url_friendly_css_name;

        $output_file = $this->asset_handler->getContentURL($css_file);

        if (is_null($output_file) || $this->is_dev) {
            $cache_dir = self::getCacheDir();

            // relative links in css
            $less_base = dirname(Director::baseURL() . $less_file) . '/';

            // Set less options
            $cache_method = $this->config->get('Axllent\\Less\\LessCompiler', 'cache_method');

            $options = [
                'cache_dir' => $cache_dir,
                'cache_method' => $cache_method,
                'compress' => Director::isLive() // compress CSS if live
            ];

            $current_raw_css = $this->asset_handler->getContent($css_file);

            // Generate and return compiled/cached file path
            $variables = $this->config->get('Axllent\\Less\\LessCompiler', 'variables');

            $cached_file = $cache_dir . '/' . \Less_Cache::Get(
                array(Director::getAbsFile($less_file) => $less_base),
                $options,
                $variables
            );

            if (is_null($output_file) || md5($current_raw_css) != md5_file($cached_file)) {
                $this->asset_handler->setContent($css_file, file_get_contents($cached_file));
            }

            $output_file = $this->asset_handler->getContentURL($css_file);
        }

        $parsed_file = Director::makeRelative($output_file);

        self::$processed_files[$file] = $parsed_file;
        self::$processed_files[$parsed_file] = $parsed_file;

        return $parsed_file;
    }
}


<?php

/*
 * This file is part of the Plum package.
 *
 * (c) 2010-2012 Julien Brochet <mewt@madalynn.eu>
 *
 * For the full copyright and license information, please view the LICENSE
 * file that was distributed with this source code.
 */

namespace Plum\Deployer;

use Plum\Server\ServerInterface;

class RsyncDeployer extends AbstractDeployer
{
    /**
     * {@inheritDoc}
     */
    public function doDeploy(ServerInterface $server, array $options, $dryRun)
    {
        $rsyncOptions = isset($options['rsync_options']) ? $options['rsync_options'] : '-azC --force --delete --progress';

        // Exclude file
        $excludeFile = null;
        if (isset($options['rsync_exclude'])) {
            $excludeFile = $options['rsync_exclude'];
            if (false === file_exists($excludeFile)) {
                throw new \InvalidArgumentException(sprintf('The exclude file "%s" does not exist.', $excludeFile));
            }

            $excludeFile = realpath($excludeFile);
        }

        $exclude = '';
        if (null !== $excludeFile) {
            $exclude = sprintf('--exclude-from \'%s\'', $excludeFile);
        }

        $ssh = '';
        if (22 !== $server->getPort()) {
            $ssh = sprintf('-e "ssh -p%d"', $server->getPort());
        }

        $login = sprintf('%s@%s:%s', $server->getUser(), $server->getHost(), $server->getDir());

        $command = sprintf('rsync %s %s %s ./ %s  %s',
                $dryRun ? "--dry-run" : "",
                $rsyncOptions,
                $ssh,
                $login,
                $exclude
        );

        system($command);
    }

    /**
     * {@inheritDoc}
     */
    public function getName()
    {
        return 'rsync';
    }
}


<?php
/**
 * Ongr_Sniffs_Strings_DoubleQuoteUsageSniff.
 *
 * PHP version 5
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2014 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */

/**
 * Ongr_Sniffs_Strings_DoubleQuoteUsageSniff.
 *
 * Makes sure that any use of Double Quotes ("") are warranted.
 *
 * @category  PHP
 * @package   PHP_CodeSniffer
 * @author    Greg Sherwood <gsherwood@squiz.net>
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 * @copyright 2006-2014 Squiz Pty Ltd (ABN 77 084 670 600)
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 * @version   Release: @package_version@
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 */
class Ongr_Sniffs_Strings_DoubleQuoteUsageSniff implements PHP_CodeSniffer_Sniff
{

    /**
     * Returns an array of tokens this test wants to listen for.
     *
     * @return array
     */
    public function register()
    {
        return array(
            T_CONSTANT_ENCAPSED_STRING,
            T_DOUBLE_QUOTED_STRING,
        );

    }//end register()

    /**
     * Processes this test, when one of its tokens is encountered.
     *
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
     * @param int                  $stackPtr  The position of the current token
     *                                        in the stack passed in $tokens.
     *
     * @return void
     */
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
    {
        $tokens = $phpcsFile->getTokens();

        // We are only interested in the first token in a multi-line string.
        if ($tokens[$stackPtr]['code'] === $tokens[($stackPtr - 1)]['code']) {
            return;
        }

        $workingString   = $tokens[$stackPtr]['content'];
        $lastStringToken = $stackPtr;

        $i = ($stackPtr + 1);
        if (isset($tokens[$i]) === true) {
            while ($tokens[$i]['code'] === $tokens[$stackPtr]['code']) {
                $workingString  .= $tokens[$i]['content'];
                $lastStringToken = $i;
                $i++;
            }
        }

        // Check if it's a double quoted string.
        if (strpos($workingString, '"') === false) {
            return;
        }

        // Make sure it's not a part of a string started in a previous line.
        // If it is, then we have already checked it.
        if ($workingString[0] !== '"') {
            return;
        }
        //ONGR variables are allowed in double quoted strings.
//        // The use of variables in double quoted strings is not allowed.
//        if ($tokens[$stackPtr]['code'] === T_DOUBLE_QUOTED_STRING) {
//            $stringTokens = token_get_all('<?php '.$workingString);
//            foreach ($stringTokens as $token) {
//                if (is_array($token) === true && $token[0] === T_VARIABLE) {
//                    $error = 'Variable "%s" not allowed in double quoted string; use concatenation instead';
//                    $data  = array($token[1]);
//                    $phpcsFile->addError($error, $stackPtr, 'ContainsVar', $data);
//                }
//            }
//
//            return;
//        }//end if

        //ONGR We allow '$' char.
        $allowedChars = array(
            '\0',
            '\n',
            '\r',
            '\f',
            '\t',
            '\v',
            '\x',
            '\b',
            '\'',
            '$',
        );

        foreach ($allowedChars as $testChar) {
            if (strpos($workingString, $testChar) !== false) {
                return;
            }
        }

        $error = 'String %s does not require double quotes; use single quotes instead';
        $data  = array(str_replace("\n", '\n', $workingString));
        $fix   = $phpcsFile->addFixableError($error, $stackPtr, 'NotRequired', $data);

        if ($fix === true) {
            $phpcsFile->fixer->beginChangeset();
            $innerContent = substr($workingString, 1, -1);
            $innerContent = str_replace('\"', '"', $innerContent);
            $phpcsFile->fixer->replaceToken($stackPtr, "'$innerContent'");
            while ($lastStringToken !== $stackPtr) {
                $phpcsFile->fixer->replaceToken($lastStringToken, '');
                $lastStringToken--;
            }

            $phpcsFile->fixer->endChangeset();
        }

    }//end process()

}//end class


<?php

namespace beacon;
/**
 * Created by PhpStorm.
 * User: wj008
 * Date: 2017/12/11
 * Time: 20:44
 */
class Request
{

    private static $header = null;

    /**
     * 数据输入格式化
     * @param array $data
     * @param string|null $name
     * @param null $def
     * @return array|bool|float|mixed|null|string
     */
    public static function input(array $data, string $name = null, $def = null)
    {
        if (empty($name)) {
            return $data;
        }
        $type = '';
        if (preg_match('@^(.*):([abfis])@', $name, $m)) {
            $type = $m[2];
            $name = $m[1];
        }
        switch ($type) {
            case 's':
                if (!isset($data[$name])) {
                    if (is_string($def)) {
                        return $def;
                    }
                    return '';
                }
                if (is_string($data[$name])) {
                    return $data[$name];
                }
                return strval($data[$name]);
            case 'b':
                if (!isset($data[$name])) {
                    if (is_bool($def)) {
                        return $def;
                    }
                    if (is_string($def)) {
                        return $def === '1' || $def === 'on' || $def === 'yes' || $def === 'true';
                    }
                    return false;
                }
                return $data[$name] === '1' || $data[$name] === 'on' || $data[$name] === 'yes' || $data[$name] === 'true';
            case 'f':
                if (!isset($data[$name]) || !is_numeric($data[$name])) {
                    if (is_double($def) || is_float($def)) {
                        return $def;
                    }
                    return 0;
                }
                return doubleval($data[$name]);
            case 'i':
                if (!isset($data[$name]) || !is_numeric($data[$name])) {
                    if (is_integer($def)) {
                        return $def;
                    }
                    return 0;
                }
                return intval($data[$name]);
            case 'a':
                if (!isset($data[$name])) {
                    if (is_array($def)) {
                        return $def;
                    }
                    if ($def === null || $def === '') {
                        return [];
                    }
                    return [$def];
                }
                if (is_array($data[$name])) {
                    return $data[$name];
                }
                if (is_string($data[$name]) && Utils::isJson($data[$name])) {
                    return json_decode($data[$name], true);
                }
                //拆分，取值
                if (is_string($data[$name]) && preg_match('@^\d+(,\d+)*$@', $data[$name])) {
                    $retemp = [];
                    $temp = explode(',', $data[$name]);
                    foreach ($temp as $item) {
                        if (is_numeric($item)) {
                            $retemp[] = intval($item);
                        }
                    }
                    return $retemp;
                }
                if ($data[$name] === null || $data[$name] === '') {
                    return [];
                }
                return [$data[$name]];
            default:
                return isset($data[$name]) ? $data[$name] : $def;
        }
    }

    /**
     * get 获取数据 相当于 $_GET
     * @param string|null $name
     * @param null $def
     * @return array|bool|float|mixed|null|string
     */
    public static function get(string $name = null, $def = null)
    {
        return self::input($_GET, $name, $def);
    }

    /**
     * post 获取数据 相当于 $_POST
     * @param string|null $name
     * @param null $def
     * @return array|bool|float|mixed|null|string
     */
    public static function post(string $name = null, $def = null)
    {
        return self::input($_POST, $name, $def);
    }

    /**
     * param 获取数据 相当于 $_REQUEST
     * @param string|null $name
     * @param null $def
     * @return array|bool|float|mixed|null|string
     */
    public static function param(string $name = null, $def = null)
    {
        return self::input($_REQUEST, $name, $def);
    }

    /**
     * 获取 session 相当于 $_SESSION[$name]
     * @param string|null $name
     * @param null $def
     * @return null
     */
    public static function getSession(string $name = null, $def = null)
    {
        if (session_status() !== PHP_SESSION_ACTIVE) {
            session_start();
        }
        if (empty($name)) {
            return $_SESSION;
        }
        return isset($_SESSION[$name]) ? $_SESSION[$name] : $def;
    }

    /**
     * 设置 session
     * @param string $name
     * @param $value
     */
    public static function setSession(string $name, $value)
    {
        if (session_status() !== PHP_SESSION_ACTIVE) {
            session_start();
        }
        $_SESSION[$name] = $value;
    }

    /**
     * 清空session
     */
    public static function delSession()
    {
        if (session_status() !== PHP_SESSION_ACTIVE) {
            session_start();
        }
        session_unset();
        session_destroy();
    }

    /**
     * 获取cookie
     * @param string $name
     * @param null $def
     * @return null
     */
    public static function getCookie(string $name, $def = null)
    {
        return isset($_COOKIE[$name]) ? $_COOKIE[$name] : $def;
    }

    /**
     * 设置cookie
     * @param string $name
     * @param $value
     * @param $options
     * @return bool
     */
    public static function setCookie(string $name, $value, $options)
    {
        if ($options == null) {
            return setcookie($name, $value);
        }
        if (is_integer($options)) {
            return setcookie($name, $value, $options);
        }
        $expire = isset($options['expire']) ? intval($options['expire']) : 0;
        $path = isset($options['path']) ? intval($options['path']) : '';
        $domain = isset($options['domain']) ? intval($options['domain']) : '';
        $secure = isset($options['secure']) ? intval($options['secure']) : false;
        $httponly = isset($options['httponly ']) ? intval($options['httponly ']) : false;
        return setcookie($name, $value, $expire, $path, $domain, $secure, $httponly);
    }

    /**
     * 获取file 相当于 $_FILE[$name]
     * @param string|null $name
     * @return null
     */
    public static function file(string $name = null)
    {
        if (empty($name)) {
            return $_FILES;
        }
        return isset($_FILES[$name]) ? $_FILES[$name] : null;
    }

    /**
     * 获取路由
     * @param string|null $name 支持 ctl:控制器名  act:方法名  app:应用名
     * @param null $def
     * @return null
     */
    public static function route(string $name = null, $def = null)
    {
        $route = Route::get();
        if (empty($name)) {
            return $route;
        }
        if ($route == null) {
            return $def;
        }
        if (isset($route[$name])) {
            return $route[$name];
        }
        return $def;
    }

    /**
     * 获取请求头
     * @param string|null $name
     * @return array|mixed|null|string
     */
    public static function getHeader(string $name = null)
    {
        if (self::$header == null) {
            self::$header = [];
            foreach ($_SERVER as $key => $value) {
                if ('HTTP_' == substr($key, 0, 5)) {
                    $key = strtolower(str_replace('_', '-', substr($key, 5)));
                    self::$header[$key] = $value;
                }
            }
        }
        $list = headers_list();
        foreach ($list as $item) {
            if (preg_match('@^([^:]+):(.*)$@', $item, $mt)) {
                $key = trim($mt[1]);
                $value = trim($mt[2]);
                $key = strtolower(str_replace('_', '-', $key));
                self::$header[$key] = $value;
            }
        }
        if (empty($name)) {
            return self::$header;
        }
        $name = strtolower(str_replace('_', '-', $name));
        return isset(self::$header[$name]) ? self::$header[$name] : '';
    }

    /**
     * 设置请求头
     * @param string $name
     * @param string $value
     * @param bool $replace
     * @param null $http_response_code
     */
    public static function setHeader(string $name, string $value, bool $replace = true, $http_response_code = null)
    {
        $nameTemps = explode('-', $name);
        foreach ($nameTemps as &$n) {
            $n = ucfirst($n);
        }
        $name = join('-', $nameTemps);
        $string = $name . ':' . $value;
        if ($replace) {
            if ($http_response_code == null) {
                @header($string);
            } else {
                @header($string, $replace, $http_response_code);
            }
        } else {
            if ($http_response_code == null) {
                @header($string, false);
            } else {
                @header($string, false, $http_response_code);
            }
        }
    }

    /**
     * 获取ip
     * @param bool $proxy
     * @param bool $forward
     * @return array|mixed|null|string
     */
    public static function getIP(bool $proxy = false, bool $forward = false)
    {
        $ip = '';
        if ($proxy) {
            if ($forward) {
                $forwardIP = self::getHeader('x-forwarded-for');
                if (!empty($forwardIP)) {
                    $temps = explode(',', $forwardIP);
                    foreach ($temps as $item) {
                        $item = trim($item);
                        if (filter_var($item, FILTER_VALIDATE_IP)) {
                            return $item;
                        }
                    }
                }
                $ip = self::getHeader('x-real-ip');
            }
        } else {
            if (isset($_SERVER['REMOTE_ADDR'])) {
                $ip = $_SERVER['REMOTE_ADDR'];
            }
        }
        if (empty($ip)) {
            return '127.0.0.1';
        }
        return $ip;
    }

    /**
     * 获取 内容类型
     * @param bool $whole
     * @return array|mixed|null|string
     */
    public static function getContentType($whole = false)
    {
        $content_type = self::getHeader('content-type');
        if ($whole) {
            return $content_type;
        }
        $temp = explode(';', $content_type);
        return $temp[0];
    }

    /**
     * 设置内容类型
     * @param $type
     * @param string $encoding
     */
    public static function setContentType($type, $encoding = 'utf-8')
    {
        if (strpos($type, '/') === false) {
            $mime_types = [
                'txt' => 'text/plain',
                'htm' => 'text/html',
                'html' => 'text/html',
                'php' => 'text/html',
                'css' => 'text/css',
                'js' => 'application/javascript',
                'json' => 'text/json',
                'xml' => 'application/xml',
                'swf' => 'application/x-shockwave-flash',
                'flv' => 'video/x-flv',
                // images
                'png' => 'image/png',
                'jpe' => 'image/jpeg',
                'jpeg' => 'image/jpeg',
                'jpg' => 'image/jpeg',
                'gif' => 'image/gif',
                'bmp' => 'image/bmp',
                'ico' => 'image/vnd.microsoft.icon',
                'tiff' => 'image/tiff',
                'tif' => 'image/tiff',
                'svg' => 'image/svg+xml',
                'svgz' => 'image/svg+xml',
                // archives
                'zip' => 'application/zip',
                'rar' => 'application/x-rar-compressed',
                'exe' => 'application/x-msdownload',
                'msi' => 'application/x-msdownload',
                'cab' => 'application/vnd.ms-cab-compressed',
                // audio/video
                'mp3' => 'audio/mpeg',
                'qt' => 'video/quicktime',
                'mov' => 'video/quicktime',
                // adobe
                'pdf' => 'application/pdf',
                'psd' => 'image/vnd.adobe.photoshop',
                'ai' => 'application/postscript',
                'eps' => 'application/postscript',
                'ps' => 'application/postscript',
                // ms office
                'doc' => 'application/msword',
                'rtf' => 'application/rtf',
                'xls' => 'application/vnd.ms-excel',
                'ppt' => 'application/vnd.ms-powerpoint',
                // open office
                'odt' => 'application/vnd.oasis.opendocument.text',
                'ods' => 'application/vnd.oasis.opendocument.spreadsheet',
            ];
            $type = isset($mime_types[$type]) ? $mime_types[$type] : 'application/octet-stream';
        }
        $contentType = $type . '; charset=' . $encoding;
        self::setHeader('Content-Type', $contentType);
    }

    /**
     * 获取配置项
     * @param string $name
     * @param null $def
     * @return mixed|string
     */
    public static function config(string $name, $def = null)
    {
        return Config::get($name, $def);
    }

    /**
     * 是否get请求
     * @return bool
     */
    public static function isGet()
    {
        return self::isMethod('get');
    }

    /**
     * 判断请求方式
     * @param string $method
     * @return bool
     */
    public static function isMethod(string $method)
    {
        return strtolower($_SERVER['REQUEST_METHOD']) == strtolower($method) ? true : false;
    }

    /**
     * 获取请求方式
     * @return string
     */
    public static function getMethod()
    {
        return strtolower($_SERVER['REQUEST_METHOD']);
    }

    /**
     * 是否post 请求
     * @return bool
     */
    public static function isPost()
    {
        return self::isMethod('post');
    }

    /**
     * 是否ajax
     * @return bool
     */
    public static function isAjax()
    {
        if (isset($_SERVER['REQUEST_AJAX']) && $_SERVER['REQUEST_AJAX'] == true) {
            return true;
        }
        return strtolower(self::getHeader('x-requested-with')) === 'xmlhttprequest';
    }

    /**
     * 获取来源页
     * @return array|mixed|null|string
     */
    public static function getReferrer()
    {
        $referer = self::getHeader('referer');
        if (empty($referer)) {
            $referer = self::getHeader('referrer');
        }
        return $referer;
    }
}