<?php

namespace loyalsoft;

/**
 * Description of CommUtil
 * 通用辅助单元
 * 常用的辅助方法都写在这里
 * @author jgao,gwang
 */
class CommUtil {
    //put your code here

    /**
     * 编码 *  data => gzdeflate => base64_encode
     * // RFC 1950 - zlib
     * $compressedData = zlib_encode($uncompressedData, 15);
     * // RFC 1951 - raw deflate
     * $compressedData = zlib_encode($uncompressedData, -15);
     * // RFC 1952 - gzip
     * $compressedData = zlib_encode($uncompressedData, 31);
     * @link http://php.net/manual/en/function.zlib-encode.php 参考
     * @param string $data
     * @return string
     */
    public static function zb64encode($data) {
        return base64_encode(gzdeflate($data));
    }

    /**
     * 解码 * data => base64_decode => gzinflate
     * // RFC 1950 - zlib
     * $compressedData = zlib_encode($uncompressedData, 15);
     * // RFC 1951 - raw deflate
     * $compressedData = zlib_encode($uncompressedData, -15);
     * // RFC 1952 - gzip
     * $compressedData = zlib_encode($uncompressedData, 31);
     * @link http://php.net/manual/en/function.zlib-encode.php 参考
     * @param string $data
     * @return string
     */
    public static function zb64decode($data) {
        return gzinflate(base64_decode($data));
    }

    /**
     *
     * @param int $min
     * @param int $max
     * @return type
     */
    public static function random($min, $max) {
        return rand($min, $max);
    }

    /**
     *  在1到1万之间取一个随机值
     * @return type
     */
    public static function random10K() {
        return self::random(1, 10000);
    }

    /**
     * 直接计算百分比是否落在区间内,相当于骰一次100面骰子,且结果正好小于参数指定的值.
     * @param float $percent 百分之x(精度±0.01%)
     * @return boolean true 本地投筛子成功, false 失败
     */
    public static function randomPercent($percent) {
        return (self::random(1, 10000) / 100) <= $percent;
    }

    /**
     * 对象装箱
     * @param type $surObj 原始obj
     * @param type $desObj 具体obj
     */
    public static function loadObject($surObj, &$desObj) {
        if ($surObj == null || $desObj == null) {
            return;
        }
        foreach ($desObj as $key => $value) {
            if (property_exists($surObj, $key)) {
                $desObj->$key = $surObj->$key;
            }
        }
    }

    /**
     * 方法调用
     * @param type $func
     * @param type $paras
     * @param type $class
     */
    public static function callFunction($func, $paras, $class = "") {
        if ($class == "" || $class == null) {
            call_user_func_array($func, $paras);
        } else {
            call_user_func_array(array($class, $func), $paras);
        }
    }

    /**
     * 浮点数转整形
     * @param type $value
     * @return type
     */
    public static function floatToInt($value) {
        return intval(round($value - 0.49999));
    }

    /**
     * 浮点数转上整形
     * @param type $value
     * @return type
     */
    public static function floatToCeil($value) {
        return round($value + 0.49999);
    }

    /**
     * 解析异常描述信息
     * @param type $e
     * @return type
     */
    public static function getExceptMsg($e) {
        return 'Msg:' . $e->getMessage() . ' Code:' . $e->getCode() . ' File:' . $e->getFile() . ' Line:' . $e->getLine();
    }

    /**
     * 字符串分割
     * @param type $str
     * @param type $char
     * @return type
     */
    public static function split($str, $char) {
        $strArr = explode($char, $str);
        return $strArr;
    }

    /**
     * 属性是否存在
     * @param type $obj
     * @param type $property
     * @return type
     */
    public static function isPropertyExists($obj, $property) {
//        DebugHelper::var_dump($property);
        return property_exists($obj, $property);
    }

    /**
     * 元素是否位于某数组中
     * @param type $array
     * @param type $item
     * @return type
     */
    public static function isInArray($array, $item) {
        return in_array($item, $array);
    }

    /**
     * 统计数组元素数或者对象属性个数
     * @param type $var
     * @return type
     */
    public static function count($var) {
        return count((array) $var);
    }

    /**
     * 兼容数值和字符串两种类型的变量,都可认为是int值. 
     * @param type $var
     * @return boolean
     */
    static function isInt($var) {
        if (is_numeric($var) || is_string($var)) {
            $int = intval($var);
            return (string) $int === (string) $var;
        }
        return false;
    }

    /**
     * 字符串包含判定
     * @param type $string 完整字符串
     * @param type $sub 子串
     * @return type
     */
    public static function isInString($string, $sub) {
        return strpos($string, $sub) >= 0;
    }

    /**
     * 对数组/关联数组进行key=>value模式的遍历
     * @param array $array 原始数组
     * @param callable $callback ($key,$val)
     * @return array 返回callback返回true的item的集合
     */
    public static function arrayKVfilter(array $array, $callback = null) {
        if ($callback == null) {
            $callback = function ($key, $val) {
                return (bool) $val;
            };
        }
        $return = array();
        foreach ($array as $key => $val) {
            if ($callback($key, $val)) {
                $return[$key] = $val;
            }
        }
        return $return;
    }

    /**
     * PHP stdClass Object转array
     * 
     */
    public static function object_array($array) {
        if (is_object($array)) {
            $array = (array) $array;
        }
        if (is_array($array)) {
            foreach ($array as $key => $value) {
                $array[$key] = self::object_array($value);
            }
        }
        return $array;
    }

    /**
     * 数组转对象
     * @param type $arr
     * @return \stdClass
     */
    public static function array2obj($arr) {
        $obj = new \stdClass();
        if (!is_null($arr)) {
            $vars = is_array($arr) ? $arr : (array) $arr;                       # 关联数组
            foreach ($vars as $name => $value) {
                $obj->$name = $value;                                           # 取参数中的或者默认值
            }
        }
        return $obj;
    }

    /**
     * 将转义符"\"增加为"\\"，方便入库
     * * */
    public static function parseBackslash($str) {
        return str_replace("\\\\", "\\\\\\\\", $str);
    }

    /**
     * Zip压缩启用
     */
    public static function output_compress() {
        ini_set("zlib.output_compression", "On");
    }

    /**
     * 将任意编码格式的字符串转换为utf-8编码
     * @param 原始字符串 $str
     * @return 转换后的字符串
     */
    public static function str2UTF8($str) {
        if (false !== mb_detect_encoding($str, 'UTF-8', true)) {
            return $str;
        }
        if (false !== mb_detect_encoding($str, 'gbk', true)) {
            return iconv('gbk', 'UTF-8', $str);
        }
        return iconv(mb_detect_encoding($str), 'UTF-8//IGNORE', $str);
    }

    /**
     * 查找变量/对象的引用名称
     * @param mixed $var 变量/对象
     * @return type
     */
    static function getReference(&$var, $scope = false) {
        if (is_object($var)) {
            $var->___uniqid = uniqid();
        } else {
            $var = serialize($var);
        }
        if (!$scope) {
            $scope = $GLOBALS;
        }
        $name = self::getReference_traverse($var, $scope);
        if (is_object($var)) {
            unset($var->___uniqid);
        } else {
            $var = unserialize($var);
        }
        return "\${$name}";
    }

    private static function getReference_traverse(&$var, $arr) {
        $name = array_search($var, $arr, true);
        if (false !== $name) {
            return "{$name}";
        }
        foreach ($arr as $key => $value) {
            if (is_object($value)) {
                $name = self::getReference_traverse($var, get_object_vars($value));
                if (false !== $name) {
                    return "{$key}->{$name}";
                }
            }
        }
        return "-";
    }

}

/**
 * 仿C#的nameof
 * @param type $var
 * @return type
 */
function nameof(&$var, $scope = false) {
    if (!$scope) {
        $scope = $GLOBALS;
    }
    return CommUtil::getReference($var, $scope);
}

function arr2obj($arr) {
    return CommUtil::array2obj($arr);
}

function obj2arr($obj) {
    return CommUtil::object_array($obj);
}

/**
 *  设定脚本内使用的date函数的时区为中华人民共和国
 */
function default_timezone() {
    date_default_timezone_set("PRC");
}

/**
 * 如果变量为null则取默认值
 * @param type $obj
 * @param type $defaultValue
 */
function my_null_default($obj, $defaultValue) {
    return ($obj === null) ? $defaultValue : $obj;                              # 注意这里必须用===判断
}

/**
 * 确保指定变量不为空(若为空则用stdclass初始化)
 * @param \stdClass $obj
 */
function my_default_Obj(&$obj) {
    if (null == $obj) {
        $obj = new \stdClass();
    }
}

/**
 * 确保指定变量不为空(若为空则用array()初始化)
 * @param \array $arr
 */
function my_default_Arr(&$arr) {
    if (null == $arr) {
        $arr = array();
    }
}

/**
 * 对象初始化
 * @return type
 */
function ObjectInit() {
    return new \stdClass();
}

/**
 * 数组初始化
 * @return type
 */
function ArrayInit() {
    return array();
}

/**
 * 自己写的int判断,相比于系统的要更私人定制化一点,兼容识别字符串类型的变量.(wanggangzero@qq.com)2020年11月24日14:33:02
 * @param type $var
 * @return type
 */
function isInt($var) {
    return CommUtil::isInt($var);
}

/**
 * 是否处于编辑器中,辅助智能感知代码的 gwang(⊙ω⊙)
 * @return bool 是否处于编辑器中
 */
function isEditor() {
    return false;                                                               # 永久性的false就好
}
