nas_docker_compose/kodbox/site/app/function/common.function.php

1656 lines
51 KiB
PHP
Raw Normal View History

2024-08-31 01:03:37 +08:00
<?php
/*
* @link http://kodcloud.com/
* @author warlee | e-mail:kodcloud@qq.com
* @copyright warlee 2014.(Shanghai)Co.,Ltd
* @license http://kodcloud.com/tools/license/license.txt
*/
// 自动类加载路径添加;$addPath为false则不添加
function import($path=false){
static $_autoLoaderPath;
if(empty($_autoLoaderPath)) {
$_autoLoaderPath = array(
MODEL_DIR,
CORER_DIR,
CLASS_DIR,
SDK_DIR,
CORER_DIR.'Cache/',
CORER_DIR.'DB/',
CORER_DIR.'IO/',
CORER_DIR.'Task/',
CORER_DIR.'Backup/',
);
if(!is_dir(MODEL_DIR)){
$_autoLoaderPath = array(CLASS_DIR,SDK_DIR);
}
}
if($path){
if(is_dir($path)){
$_autoLoaderPath[] = rtrim($path,'/').'/';
}else if( is_file($path) ){
include_once $path;
return array();
}
}
return $_autoLoaderPath;
}
// 类自动加载通过autoLoaderPath的路径
import(SDK_DIR.'archiveLib/');
function myAutoloader($name) {
static $_cacheError = array();
if(isset($_cacheError[$name])){
return $_cacheError[$name];
}
$find = import();
$result = false;
foreach ($find as $path) {
$result = classPathAuto($path,$name);
if($result) break;
}
if($result){
include_once ($result);
return true;
}
$_cacheError[$name] = false;
// write_log(array($name,$result,$find),'test');
return false;
}
spl_autoload_register('myAutoloader', true, true);
// 自动获取类文件名兼容文件路径大小写敏感的情况linux环境
function classPathAuto($path,$name,$fileLast = '.class.php'){
$path = rtrim($path,'/').'/';
$nameUpper = strtoupper(substr($name,0,1)).substr($name,1);
$nameLower = strtolower($name);
$result = false;
// pr($path.$name.$fileLast);
if(file_exists($path.$name.$fileLast)){
$result = $path.$name.$fileLast;
}else if(file_exists($path.$nameLower.$fileLast)){
$result = $path.$nameLower.$fileLast;
}else if(file_exists($path.$nameUpper.$fileLast)){
$result = $path.$nameUpper.$fileLast;
}
return $result;
}
// 是否为控制台模式(控制台执行,或者curl请求)
function is_cli(){
static $isFirst = true;
static $isCli = false;
if($isFirst){
$isFirst = false;
$isCli = stristr(php_sapi_name(),'cli') ? true : false;
if(strstr($_SERVER['HTTP_USER_AGENT'],'curl/')){$isCli = true;}
}
return $isCli;
}
/**
* 文本字符串转换
*/
function mystr($str){
$from = array("\r\n", " ");
$to = array("<br/>", "&nbsp");
return str_replace($from, $to, $str);
}
// 清除多余空格和回车字符
function strip($str){
return preg_replace('!\s+!', '', $str);
}
function timeFloat(){
return microtime(true);
}
// 删除字符串两端的字符串
function str_trim($str,$remove){
return str_rtrim(str_ltrim($str,$remove),$remove);
}
function str_ltrim($str,$remove){
if(!$str || !$remove) return $str;
while(substr($str,0,strlen($remove)) == $remove){
$str = substr($str,strlen($remove));
}
return $str;
}
function str_rtrim($str,$remove){
if(!$str || !$remove) return $str;
while(substr($str,-strlen($remove)) == $remove){
$str = substr($str,0,-strlen($remove));
}
return $str;
}
/**
* 根据id获取短标识;
* 加入时间戳避免猜测;id不可逆
*
* eg: 234==>4JdQ9Lgw; 100000000=>4LyUC2xQ
*/
function short_id($id){
$id = intval($id) + microtime(true)*10000;
$id = pack('H*',base_convert($id,10,16));
$base64 = base64_encode($id);
$replace = array('/'=>'_','+'=>'-','='=>'');
return strtr($base64, $replace);
}
/**
* 获取精确时间
*/
function mtime(){
$t= explode(' ',microtime());
$time = $t[0]+$t[1];
return $time;
}
function guid(){
return md5(microtime(true).rand_string(20));
}
/**
* 过滤HTML
*
* eg: </script><script>alert(1234)</script>
* 允许url中字符;
*/
function clear_html($html, $br = true){
$html = $html === null ? "" : $html;
$replace = array('<','>','"',"'");
$replaceTo = array('&lt;','&gt;','&quot;','&#39;');
return str_replace($replace,$replaceTo,$html);
}
function clear_quote($html){
$html = $html === null ? "" : $html;
$replace = array('"',"'",'</script');
$replaceTo = array('\\"',"\\'","<\/script");
return str_ireplace($replace,$replaceTo,$html);
}
// 反序列化攻击防护,不允许类对象;
function unserialize_safe($str){
if(!$str) return false;
if(preg_match("/O:(\d+):/",$str,$match)) return false;
return unserialize($str);
}
/**
* 过滤js、css等
*/
function filter_html($html){
$find = array(
"/<(\/?)(script|i?frame|style|html|body|title|link|meta|\?|\%)([^>]*?)>/isU",
"/(<[^>]*)on[a-zA-Z]+\s*=([^>]*>)/isU",
"/javascript\s*:/isU",
);
$replace = array("\\1\\2\\3","\\1\\2","");
return preg_replace($find,$replace,$html);
}
function equal_not_case($str,$str2) {
return strtolower($str) === strtolower($str2);
}
function in_array_not_case($needle, $haystack) {
return in_array(strtolower($needle),array_map('strtolower',$haystack));
}
/**
* 将obj深度转化成array
*
* @param $obj 要转换的数据 可能是数组 也可能是个对象 还可能是一般数据类型
* @return array || 一般数据类型
*/
function obj2array($obj){
if (is_array($obj)) {
foreach($obj as &$value) {
$value = obj2array($value);
};unset($value);
return $obj;
} elseif (is_object($obj)) {
$obj = get_object_vars($obj);
return obj2array($obj);
} else {
return $obj;
}
}
// 主动输出内容维持检测;(用户最终show_json情况; 文件下载情况不适用);
// 没有输出时,php-fpm情况下,connection_aborted判断不准确
function check_abort_echo(){
static $lastTime = 0;
if(isset($GLOBALS['ignore_abort']) && $GLOBALS['ignore_abort'] == 1) return;
// 每秒输出2次;
if(timeFloat() - $lastTime >= 0.5){
ob_end_flush();echo str_pad('',1024*5);flush();
$lastTime = timeFloat();
}
// write_log(connection_aborted().';'.connection_status(),'check_abort');
if(connection_aborted()){write_log(get_caller_msg(),'abort');exit;}
}
function check_abort(){
if(isset($GLOBALS['ignore_abort']) && $GLOBALS['ignore_abort'] == 1) return;
if(connection_aborted()){write_log(get_caller_msg(),'abort');exit;}
}
function check_aborted(){
// connection_aborted();
exit;
}
function ignore_timeout(){
$GLOBALS['ignore_abort'] = 1;
@ignore_user_abort(true);
set_timeout();
}
// 48 * 60 * 60
function set_timeout($timeout=172800){
static $firstRun = false;
if($firstRun) return; //避免重复调用; 5000次100ms;
$firstRun = true;
@ini_set("max_execution_time",$timeout);
@ini_set('request_terminate_timeout',$timeout);
@set_time_limit($timeout);
@ini_set('memory_limit', '4000M');//4G;
}
function check_code($code){
ob_clean();
header("Content-type: image/png");
$width = 70;$height=27;
$fontsize = 18;$len = strlen($code);
$im = @imagecreatetruecolor($width, $height) or die("create image error!");
$background_color = imagecolorallocate($im,255, 255, 255);
imagefill($im, 0, 0, $background_color);
for ($i = 0; $i < 2000; $i++) {//获取随机淡色
$line_color = imagecolorallocate($im, mt_rand(180,255),mt_rand(160, 255),mt_rand(100, 255));
imageline($im,mt_rand(0,$width),mt_rand(0,$height), //画直线
mt_rand(0,$width), mt_rand(0,$height),$line_color);
imagearc($im,mt_rand(0,$width),mt_rand(0,$height), //画弧线
mt_rand(0,$width), mt_rand(0,$height), $height, $width,$line_color);
}
$border_color = imagecolorallocate($im, 160, 160, 160);
imagerectangle($im, 0, 0, $width-1, $height-1, $border_color);//画矩形边框颜色200,200,200
for ($i = 0; $i < $len; $i++) {//写入随机字串
$text_color = imagecolorallocate($im,mt_rand(30, 140),mt_rand(30,140),mt_rand(30,140));
imagechar($im,10,$i*$fontsize+6,rand(1,$height/3),$code[$i],$text_color);
}
imagejpeg($im);//显示图
imagedestroy($im);//销毁图片
}
// 立即输出内容到页面; $replace 为true代表替换输出; 支持cli模式及cli下的curl请求;
function echoLog($log,$replace=false){
static $isFirst = true;
static $timeBefore = false;
static $logOutBefore = '';
static $replaceID = '';
if($isFirst){
ignore_timeout();
@ob_end_clean();
@header('X-Accel-Buffering: no');
$isFirst = false;
}
$timeDelay = 0.05;// 临时替换的输出内容, 50ms内只输出一次;
$timeAt = timeFloat();
if($timeBefore && $replace && ($timeAt - $timeBefore) < $timeDelay){return;}
$timeBefore = $timeAt;
$timeFloat = explode(".",mtime());
$timeNow = date("H:i:s.",time()).sprintf("%03d",substr($timeFloat[1],0,3));
if(is_cli()){
// \b输出光标回退一个字符(并不清空,需要自行覆盖);\r输出光标回到行首; "\r\033[k";
$chrPad = "\x01";$chrBack = "\x08";//$chrPad = "\x01" "\x06" "\x1b","\x18",""
$padLen = $logOutBefore ? strlen(trim($logOutBefore,$chrPad)) : 0;
$charReplace = array('<br/>'=>"\n",'&nbsp;'=>' ',"&quot;"=>'"');$append = "\n";
if($replace){$charReplace = array('<br/>'=>"_|",'&nbsp;'=>' ',"&quot;"=>'"');$append = str_repeat($chrPad,2000);}
$output = $timeNow.": ".str_replace(array_keys($charReplace),array_values($charReplace),$log);
$padLenBefore = $padLen - strlen($output);// 填充到前一次长度,清除所有显示字符(比前一行短,前一行超出部分会出现残留)
$output = $output.str_pad("",$padLenBefore <= 0 ? 0 : $padLenBefore);
$logOutBefore = $replace ? $output:'';
// 最前面追加\r 兼容部分终端没有回退的情况;
@ob_end_flush();echo "\r".str_repeat($chrBack,$padLen).$output.$append;@flush();
return;
}
$replaceIdBefore = $replaceID;
if(!$replace){$replaceID = '';}
if($replace){$replaceID = $replaceID ? $replaceID:rand_string(10);}
if(!strstr($log,'<')){$log = str_replace(array(" "),array("&nbsp;"),$log);} // 没有html标签时替换空格
$log = str_replace(array('`',"\n"),array('`',"<br/>"),$log);
$timeStyle = '<span style="display:inline-block;width:100px;font-size:14px;color:#888;font-family:monospace;padding-right:10px;">';
$textStyle = '<span style="display:inline-block;font-size:14px;color:#0084fe;font-family:monospace;">';
$logNow = $timeStyle.$timeNow."</span>".$textStyle.$log.'</span>';
$logOut = "<div class='line' ".($replaceID ? 'id="line-'.$replaceID.'"':'').">".$logNow."</div>";
// 替换输出: 针对上一次输出行进行替换; 当前不是替换输出且前一次为替换输出则移除前一行; 不干扰其他echo等输出的内容;
if($replace){
$script = 'var line=document.getElementById("line-'.$replaceID.'");';
$script = $script.'if(!line){document.write(`'.$logOut.'`);}else{line.innerHTML=`'.$logNow.'`;}';
$logOut = '<script>{'.$script.'}</script>';
}else if(!$replace && $replaceIdBefore){
$script = 'var line=document.getElementById("line-'.$replaceIdBefore.'");if(line){line.remove();}';
$logOut = $logOut.'<script>{'.$script.'}</script>';
}
@ob_end_flush();echo $logOut.str_pad('',1024*2);flush();
}
/**
* 计算N次方根
* @param $num
* @param $root
*/
function croot($num, $root = 3){
$root = intval($root);
if (!$root) {
return $num;
}
return exp(log($num) / $root);
}
function add_magic_quotes($array){
foreach ((array) $array as $k => $v) {
if (is_array($v)) {
$array[$k] = add_magic_quotes($v);
} else {
$array[$k] = addslashes($v);
}
}
return $array;
}
// 字符串加转义
function add_slashes($string){
if (!$GLOBALS['magic_quotes_gpc']) {
if (is_array($string)) {
foreach($string as $key => $val) {
$string[$key] = add_slashes($val);
}
} else {
$string = addslashes($string);
}
}
return $string;
}
/**
* hex to binary
*/
if (!function_exists('hex2bin')) {
function hex2bin($hexdata) {
return pack('H*', $hexdata);
}
}
if (!function_exists('gzdecode')) {
function gzdecode($data){
return gzinflate(substr($data,10,-8));
}
}
function xml2json($decodeXml){
$data = simplexml_load_string($decodeXml,'SimpleXMLElement', LIBXML_NOCDATA);
return json_decode(json_encode($data),true);
}
/**
* XML编码
* @param mixed $data 数据
* @param string $root 根节点名
* @param string $item 数字索引的子节点名
* @param string $attr 根节点属性
* @param string $id 数字索引子节点key转换的属性名
* @param string $encoding 数据编码
* @return string
*/
function xml_encode($data, $root = 'think', $item = 'item', $attr = '', $id = 'id', $encoding = 'utf-8') {
if (is_array($attr)) {
$_attr = array();
foreach ($attr as $key => $value) {
$_attr[] = "{$key}=\"{$value}\"";
}
$attr = implode(' ', $_attr);
}
$attr = trim($attr);
$attr = empty($attr) ? '' : " {$attr}";
$xml = "<?xml version=\"1.0\" encoding=\"{$encoding}\"?>";
$xml .= "<{$root}{$attr}>";
$xml .= data_to_xml($data, $item, $id);
$xml .= "</{$root}>";
return $xml;
}
/**
* 数据XML编码
* @param mixed $data 数据
* @param string $item 数字索引时的节点名称
* @param string $id 数字索引key转换为的属性名
* @return string
*/
function data_to_xml($data, $item = 'item', $id = 'id') {
$xml = $attr = '';
foreach ($data as $key => $val) {
if (is_numeric($key)) {
$id && $attr = " {$id}=\"{$key}\"";
$key = $item;
}
$xml .= "<{$key}{$attr}>";
$xml .= (is_array($val) || is_object($val)) ? data_to_xml($val, $item, $id) : $val;
$xml .= "</{$key}>";
}
return $xml;
}
/**
* 数组key连接的值设置
* $arr data.list.order <==> $arr['data']['list']['order']
*/
function array_set_value(&$array,$key,$value){
if(!is_array($array)) {
$array = array();
}
$keyArr = explode(".",$key);
$tempArr = &$array;
$count = count($keyArr);
for ($i=0; $i < $count; $i++) {
$k = $keyArr[$i];
if($i+1 == $count ){
$tempArr[$k] = $value;
return true;
}
if(!isset($tempArr[$k])){
$tempArr[$k] = array();
}
$tempArr = &$tempArr[$k];
if(!is_array($tempArr)){//有值并且不是数组的情况
return false;
}
}
return false;
}
function _get($array,$key,$default=null){
return array_get_value($array,$key,$default);
}
/**
* 数组key连接的值获取
* $arr data.list.order <==> $arr['data']['list']['order']
*/
function array_get_value(&$array,$key,$default=null){
if(!is_array($array)) return $default;
if(isset($array[$key])) return $array[$key];
if(strpos($key,'.') === false){
return isset($array[$key]) ? $array[$key] : $default;
}
$keyArr = explode(".",$key);
$tempArr = $array;
$total = count($keyArr);
for ($i=0; $i < $total; $i++) {
$k = $keyArr[$i];
if(!isset($tempArr[$k])) return $default;
if( $i+1 == $total ){
return $tempArr[$k];
}
$tempArr = $tempArr[$k];
}
return $default;
}
// 数组按照keyArr保持顺序;
function array_sort_keep($array,$key,$keyArr){
$result = array();
$arrayNew = array_to_keyvalue($array,$key);
foreach ($keyArr as $key){
if(!isset($arrayNew[$key.''])){continue;}
$result[] = $arrayNew[$key.''];
}
return $result;
}
/**
* 二维数组按照指定的键值进行排序,默认升序
*
* @param $field 排序字段; 为空时按一维数组排序;
* @param $type 升序降序 默认升序
* @param $fieldDefault 额外排序字段($field相等时的第二个排序字段)
*
* @return array
* $array = array(
* array('name'=>'手机','brand'=>'诺基亚','price'=>1050),
* array('name'=>'手表','brand'=>'卡西欧','price'=>960)
* );
* $out = array_sort_by($array,'price');
* $out = array_sort_by($array,'info.count');
*/
function array_sort_by($records, $field='', $orderDesc=false,$fieldMore=false){
if(!is_array($records) || !$records) return array();
if($fieldMore && $fieldMore == $field){$fieldMore = false;}
if(count($records) == 1) return $records;
$order = $orderDesc ? SORT_DESC : SORT_ASC;
$flag = SORT_NATURAL | SORT_FLAG_CASE;//SORT_REGULAR; SORT_NATURAL | SORT_FLAG_CASE
$sortBy1 = array();$sortBy2 = array();
if(!$field){array_multisort($records,$order,$flag,$records);return $records;}
foreach ($records as $item){
$sortBy1[] = isset($item[$field]) ? $item[$field]: _get($item,$field,'');
if($fieldMore){$sortBy2[] = isset($item[$fieldMore]) ? $item[$fieldMore]: _get($item,$fieldMore,'');}
}
if($fieldMore){ array_multisort($sortBy1,$order,$flag,$sortBy2,$order,$flag,$records);}
if(!$fieldMore){array_multisort($sortBy1,$order,$flag,$records);}
return $records;
}
if (!function_exists('array_column')) {
function array_column($array, $columnKey, $indexKey = null) {
$result = array();
foreach ($array as $subArray) {
if (is_null($indexKey) && array_key_exists($columnKey, $subArray)) {
$result[] = is_object($subArray)?$subArray->$columnKey: $subArray[$columnKey];
} elseif (array_key_exists($indexKey, $subArray)) {
if (is_null($columnKey)) {
$index = is_object($subArray)?$subArray->$indexKey: $subArray[$indexKey];
$result[$index] = $subArray;
} elseif (array_key_exists($columnKey, $subArray)) {
$index = is_object($subArray)?$subArray->$indexKey: $subArray[$indexKey];
$result[$index] = is_object($subArray)?$subArray->$columnKey: $subArray[$columnKey];
}
}
}
return $result;
}
}
/**
* 遍历数组,对每个元素调用 $callback假如返回值不为假值则直接返回该返回值
* 假如每次 $callback 都返回假值,最终返回 false
*
* @param $array
* @param $callback
* @return mixed
*/
function array_try($array, $callback){
if (!$array || !$callback) {
return false;
}
$args = func_get_args();
array_shift($args);
array_shift($args);
if (!$args) {
$args = array();
}
foreach($array as $v) {
$params = $args;
array_unshift($params, $v);
$x = call_user_func_array($callback, $params);
if ($x) {
return $x;
}
}
return false;
}
// 取出数组中第n项
function array_get_index($array,$index){
foreach($array as $k=>$v){
$index--;
if($index<0) return array($k,$v);
}
}
/**
* 根据数组子项去重
*/
function array_unique_by_key($array,$key){
$array = array_to_keyvalue($array,$key);
return array_values($array);
}
// 多条数组筛选子元素:获取多条数组中项的某个字段构成值数组
function array_field_values($array,$field){
$result = array();
if(!is_array($array) || !$array) return $result;
foreach ($array as $val) {
if(is_array($val) && isset($val[$field])){
$result[] = $val[$field];
}
}
return $result;
}
// 单条数据筛选key只筛选返回数组中指定key的部分
function array_field_key($array,$field){
$result = array();
if(!is_array($array) || !$array) return $result;
foreach ($field as $val) {
if(isset($array[$val])){
$result[$val] = $array[$val];
}
}
return $result;
}
// 多条数组筛选筛选项中key为$field,值为$field的部分
function array_filter_by_field($array,$field,$value){
$result = array();
if(!is_array($array) || !$array) return $result;
foreach ($array as $key => $val){
if($val[$field] != $value) continue;
if(is_int($key)){
$result[] = $val;
}else{
$result[$key] = $val;
}
}
return $result;
}
function array_remove_by_field($array,$field,$value){
$result = array();
if(!is_array($array) || !$array) return $result;
foreach ($array as $key => $val) {
if($val[$field] == $value) continue;
if(is_int($key)){
$result[] = $val;
}else{
$result[$key] = $val;
}
}
return $result;
}
function array_find_by_field($array,$field,$value){
if(!is_array($array) || !$array) return null;
foreach ($array as $val) {
if($val[$field] == $value) return $val;
}
return null;
}
function array_page_split($array,$page=false,$pageNum=false){
$page = intval($pageNum ? $pageNum : $GLOBALS['in']['page']);
$page = $page <= 1 ? 1 : $page;
$pageMax = 5000;
$pageNum = intval($pageNum ? $pageNum : $GLOBALS['in']['pageNum']);
$pageNum = $pageNum <= 5 ? 5 : ($pageNum > $pageMax ? $pageMax: $pageNum);
$array = is_array($array) ? $array :array();
$pageTotal = ceil(count($array) / $pageNum);
$page = $page <= 1 ? 1 : ($page >= $pageTotal ? $pageTotal : $page);
$result = array(
'pageInfo' => array(
'totalNum' => count($array),
'pageNum' => $pageNum,
'page' => $page,
'pageTotal' => $pageTotal,
),
'list' => array_slice($array,($page-1) * $pageNum,$pageNum)
);
return $result;
}
/**
* 删除数组子项的特定key的数据
* $keyArray 单个key字符串或多个key组成的数组
* eg: [{a:1,b:2},{a:33,b:44}] ==> [{a:1},{a:33}]
*/
function array_remove_key(&$array, $keyArray){
if(!is_array($array) || !$array) return array();
if(!is_array($keyArray)) $keyArray = array($keyArray);
foreach ($array as &$item) {
foreach ($keyArray as $key) {
if(isset($item[$key])){
unset($item[$key]);
}
}
};unset($item);
return $array;
}
// 删除数组某个值
function array_remove_value($array, $value){
if(!is_array($array) || !$array) return array();
$isNumericArray = true;
foreach ($array as $key => $item) {
if ($item === $value) {
if (!is_int($key)) {
$isNumericArray = false;
}
unset($array[$key]);
}
}
if ($isNumericArray) {
$array = array_values($array);
}
return $array;
}
// 获取数组key最大的值
function array_key_max($array){
if(count($array)==0){
return 1;
}
$idArr = array_keys($array);
rsort($idArr,SORT_NUMERIC);//id从高到底
return intval($idArr[0]);
}
/**
* 将纯数组的元素的某个key作为key生成新的数组
* [{"id":34,"name":"dd"},{"id":78,"name":"dd"}]
* (arr,'id')=>{34:{"id":34,"name":"dd"},78:{"id":78,"name":"dd"}} //用元素key的值作为新数组的key
* (arr,'id','name')=>{34:"dd",78:"name"} //用元素key的值作为新数组的key只取对应$contentKey的值作为内容
* (arr,'','name')=>["dd","name"] //只取数组元素的特定项构成新的数组
*/
function array_to_keyvalue($array,$key='',$contentKey=false,$hasSub=false){
$result = array();
if(!is_array($array) || !$array) return $result;
if(!$key){return array_column($array,$contentKey);}
$contentKey = $contentKey ? $contentKey : null;
if(!$hasSub){return array_column($array,$contentKey,$key);}
// 支持取值的下层;
foreach ($array as $item) {
$theValue = $contentKey ? _get($item,$contentKey):$item;
if($key){
$theKey = _get($item,$key).'';
$result[$theKey] = $theValue;
}elseif(!is_null($theValue)){
$result[] = $theValue;
}
}
return $result;
}
/**
* 根据parentid获取家谱树列表
* @param [type] $array
* @param [type] $id
* @param string $idKey // id名称
* @param string $pidKey // pid名称
* @return void
*/
function array_tree($array, $id, $idKey = 'id', $pidKey = 'parentid'){
$tree = array();
while($id != '0'){
foreach ($array as $v) {
if(!isset($v[$pidKey])) $v[$pidKey] = '0';
if($v[$idKey] == $id){
$tree[] = $v;
$id = $v[$pidKey];
break;
}
}
}
return $tree;
}
/**
* 迭代获取子孙树——必须要有根部门pid=空)
* @param [type] $rows
* @param string $pid
* @return void
*/
function array_sub_tree($rows, $pid = 'parentid', $id = 'id') {
$rows = array_column ( $rows, null, $id );
foreach ( $rows as $key => $val ) {
if ( $val[$pid] ) {
if ( isset ( $rows[$val[$pid]] )) {
$rows[$val[$pid]]['children'][$val[$id]] = &$rows[$key];
}
}
}
foreach ( $rows as $key => $val ) {
if ( $val[$pid] ) unset ( $rows[$key] ); // 根元素的parentid需为空以此删除其他项
}
return $rows;
}
/**
* 将数组的元素的某个key作为key生成新的数组;值为数组形式;
* [{"id":34,"type":1},{"id":78,"type":2},{"id":45,"type":1}]
* (arr,'type')=>{1:[{"id":34,"name":"dd"},{"id":45,"type":1}],2:[{"id":78,"name":"dd"}]}
* (arr,'name','name')=>{1:[34,45],2:[78]} //保留对应可以的内容
*/
function array_to_keyvalue_group($array,$key='',$contentKey=false){
$result = array();
if(!is_array($array) || !$array) return $result;
foreach ($array as $item) {
$theValue = $item;
if($contentKey){
$theValue = $item[$contentKey];
}
if(!isset($result[$item[$key]])){
$result[$item[$key]] = array();
}
$result[$item[$key]][] = $theValue;
}
return $result;
}
/**
* 合并两个数组,保留索引信息;
*/
function array_merge_index($array,$array2){
$result = $array;
if(!is_array($array) || !$array) return $result;
foreach ($array2 as $key => $value) {
$result[$key] = $value;
}
return $result;
}
/**
* 二维数组,根据键值向前、后移动
* @param string $swap prev next
* @return void
*/
function array_swap_keyvalue($array, $key, $value, $swap = 'next'){
foreach ($array as $idx => $item) {
if(isset($item[$key]) && $item[$key] == $value){
$index = $idx;
break;
}
}
if(!isset($index)) return $array;
$swap == 'prev' && $index = $index -1;
$before = array_slice($array,0,$index);
$middle = array_reverse(array_slice($array,$index,2));
$after = array_slice($array,$index + 2);
return array_merge($before,$middle,$after);
}
//set_error_handler('errorHandler',E_ERROR|E_PARSE|E_CORE_ERROR|E_COMPILE_ERROR|E_USER_ERROR);
register_shutdown_function('fatalErrorHandler');
function errorHandler($err_type,$errstr,$errfile,$errline){
if (($err_type & E_WARNING) === 0 && ($err_type & E_NOTICE) === 0) {
return false;
}
$arr = array(
$err_type,
$errstr,
//" in [".$errfile.']',
" in [".get_path_this(get_path_father($errfile)).'/'.get_path_this($errfile).']',
'line:'.$errline,
);
$str = implode(" ",$arr)."<br/>";
show_tips($str);
}
//捕获fatalError
function fatalErrorHandler(){
$e = error_get_last();
if(!$e) return;
switch($e['type']){
case E_ERROR:
case E_PARSE:
case E_CORE_ERROR:
case E_COMPILE_ERROR:
case E_USER_ERROR:
errorHandler($e['type'],$e['message'],$e['file'],$e['line']);
break;
case E_NOTICE:break;
default:break;
}
}
function show_tips($message,$url= '', $time = 3,$title = ''){
$res = Hook::trigger("show_tips",$message,$url,$time,$title);
if (!empty($res) && is_array($res)) {
$vars = array('message', 'url', 'time', 'title');
foreach ($vars as $key) {
if (isset($res[$key])) $$key = $res[$key];
}
}
ob_get_clean();
header('Content-Type: text/html; charset=utf-8');
$goto = "content='$time;url=$url'";
$info = "{$time}s 后自动跳转, <a href='$url'>立即跳转</a>";
if ($url == "") {//是否自动跳转
$goto = "";$info = "";
}
if($title == ''){$title = "出错了! (warning!)";}
//移动端;报错输出
if(isset($_REQUEST['HTTP_X_PLATFORM'])){
show_json($message,false);
}
if(is_array($message) || is_object($message)){
$message = json_encode_force($message);
$message = htmlspecialchars($message);
$message = str_replace(array('\n','\/'),array("<br/>",'/'),stripslashes($message));
$message = "<pre>".$message.'</pre>';
}else{
$message = filter_html(nl2br($message));
}
$template = TEMPLATE.'common/showTips.html';
if(file_exists($template)){
include($template);exit;
}
echo<<<END
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no, viewport-fit=cover, shrink-to-fit=no" />
<meta http-equiv='refresh' $goto charset="utf-8">
<style>
body{background: #f6f6f6;padding:0;margin:0; display:flex;align-items: center;justify-content: center;
position: absolute;left: 0;right: 0;bottom: 0;top: 0;}
#msgbox{box-shadow: 0px 10px 40px rgba(0, 0, 0, 0.1);border-radius: 5px;border-radius: 5px;background: #fff;
font-family: "Lantinghei SC","Hiragino Sans GB","Microsoft Yahei",Helvetica,arial,sans-serif;line-height: 1.5em;
color:888;margin:0 auto;margin-top:10px;margin-bottom:10px;width:500px;font-size:13px;color:#666;word-wrap: break-word;word-break: break-all;max-width: 90%;box-sizing: border-box;max-height: 90%;overflow: auto;padding:30px 30px;}
#msgbox #info{margin-top: 10px;color:#aaa;}
#msgbox #title{color: #333;border-bottom: 1px solid #eee;padding: 10px 0;margin:0 0 15px;font-size:22px;font-weight:200;}
#msgbox #info a{color: #64b8fb;text-decoration: none;padding: 2px 0px;border-bottom: 1px solid;}
#msgbox a{text-decoration:none;color:#2196F3;}
#msgbox a:hover{color:#f60;border-bottom:1px solid}
#msgbox .desc{color:#f60;font-weight: 600;padding: 10px 0 10px;}
#msgbox pre{word-break: break-all;word-wrap: break-word;white-space: pre-wrap;
background: #002b36;padding:1em;color: #839496;border-left: 6px solid #8e8e8e;border-radius: 3px;}
</style>
</head>
<body>
<div id="msgbox">
<div id="title">$title</div>
<div id="message">$message</div>
<div id="info">$info</div>
</div>
</body>
</html>
END;
exit;
}
function get_caller_trace($trace,$needArgs = true) {
$trace = is_array($trace) ? $trace : array();
$traceText = array();
$maxLoad = 50; //数据过多自动丢失后面内容;
if(count($trace) > $maxLoad){
$trace = array_slice($trace,count($trace) - $maxLoad);
}
$trace = array_reverse($trace);
$ignoreMethod = array('get_caller_info','think_exception','think_trace');
$keepArgs = array('Action','ActionApply','ActionCall');
foreach($trace as $i => $call){
$method = $call['function'] ? $call['function'] : '';
if(in_array($method,$ignoreMethod)) continue;
if(isset($call['class']) && $call['class'] == 'ClassBaseCall') continue;
if(isset($call['object']) && is_object($call['object'])) {
$call['object'] = get_class_name($call['object']);
}else if(isset($call['class'])){
$call['object'] = $call['class'];
}
$file = isset($call['file']) ? get_path_this(get_path_father($call['file'])).'/'.get_path_this($call['file']) : '';
$traceText[$i] = isset($call['line']) ? $file.'['.$call['line'].'] ' : $file;
$traceText[$i].= empty($call['object'])? '': $call['object'].$call['type'];
if( $method =='show_json' || $method =='think_trace'){
$traceText[$i].= $method.'(args)';
}else{
$temp = (isset($call['args']) && is_array($call['args'])) ? array_values($call['args']) : array();
$args = array(); // 深拷贝,避免引用传参被修改
$maxLength = 200;//参数最长长度
foreach($temp as $j=>$value){
if(!$needArgs && !in_array($method,$keepArgs)){
$param = (is_string($value) || is_numeric($value) || !$value) ? $value.'':'[obj]';
if(strlen($param) > $maxLength){$param = mb_substr($param,0,$maxLength).'...';}
$args[] = '"'.$param.'"';continue;
}
$value = @json_decode(@json_encode($value));
$param = json_encode(array_parse_deep($value));
$param = str_replace(array('\\/','\/','\\\\/','\"'),array('/','/','/',"'"),$param);
if(substr($param,0,1) == '['){$param = substr($param,1,-1);}
if(strlen($param) > $maxLength){$param = mb_substr($param,0,$maxLength).'...';}
$args[] = $param;
}
$traceText[$i] .= $method ? $method.'('.implode(',',$args).')' : '';
}
}
return array_values($traceText);
}
function get_caller_info($needArgs = true) {
$trace = debug_backtrace();
return get_caller_trace($trace,$needArgs);
}
function get_caller_msg($trace = false) {
return get_caller_msg_parse(get_caller_info(),$trace);
}
function get_caller_msg_parse($msg,$trace = false) {
$msg = array_slice($msg,0,count($msg) - 1);
$msg['memory'] = sprintf("%.3fM",memory_get_usage()/(1024*1024));
if($trace){
$msg['trace'] = think_trace('[trace]');
}
$msg = json_encode_force($msg);
$msg = str_replace(array('\\/','\/','\\\\/','\"'),array('/','/','/','"'),$msg);
return $msg;
}
// 去除json中注释部分; json允许注释
// 支持 // 和 /*...*/注释
function json_comment_clear($str){
$result = '';
$inComment = false;
$commentType = '//';// /*,//
$quoteCount = 0;
$str = str_replace(array('\"',"\r"),array("\\\0","\n"),$str);
for ($i=0; $i < strlen($str); $i++) {
$char = $str[$i];
if($inComment){
if($commentType == '//' && $char == "\n"){
$result .= "\n";
$inComment = false;
}else if($commentType == '/*' && $char == '*' && $str[$i+1] == '/'){
$i++;
$inComment = false;
}
}else{
if($str[$i] == '/'){
if($quoteCount % 2 != 0){//成对匹配,则当前不在字符串内
$result .= $char;
continue;
}
if($str[$i+1] == '*'){
$inComment = true;
$commentType = '/*';
$i++;
continue;
}else if($str[$i+1] == '/'){
$inComment = true;
$commentType = '//';
$i++;
continue;
}
}else if($str[$i] == '"'){
$quoteCount++;
}
$result .= $char;
}
}
$result = str_replace("\\\0",'\"',$result);
$result = str_replace("\n\n","\n",$result);
return $result;
}
function json_space_clear($str){
$result = '';
$quoteCount = 0;
$str = str_replace(array('\"',"\r"),array("\\\0","\n"),$str);
for ($i=0; $i < strlen($str); $i++) {
$char = $str[$i];
//忽略不在字符串中的空格 tab 和换行
if( $quoteCount % 2 == 0 &&
($char == ' ' || $char == ' ' || $char == "\n") ){
continue;
}
if($char == '"'){
$quoteCount ++;
}
$result .= $char;
}
$result = str_replace("\\\0",'\"',$result);
return $result;
}
function json_decode_force($str){
$str = trim($str,'');
$str = json_comment_clear($str);
$str = json_space_clear($str);
//允许最后一个多余逗号(todo:字符串内)
$str = str_replace(array(',}',',]',"\n","\t"),array('}',']','',' '),$str);
$result = json_decode($str,true);
if(!$result){
//show_json($result,false);
}
return $result;
}
function json_encode_force($json){
if(defined('JSON_PRETTY_PRINT')){
$jsonStr = json_encode($json,JSON_UNESCAPED_UNICODE|JSON_PRETTY_PRINT);
}else{
$jsonStr = json_encode($json);
}
if($jsonStr === false){
$json = array_parse_deep($json);
$parse = new Services_JSON();
$jsonStr = $parse->encode($json);
}
return $jsonStr;
}
function array_parse_deep($arr){
if(!is_array($arr)) return $arr;
foreach ($arr as $key => $obj) {
if(is_resource($obj) || is_object($obj)){ // 资源无法json_encode;
$arr[$key] = get_class_name($obj);
}else if(is_array($obj)){
$arr[$key] = array_parse_deep($obj);
}
}
return $arr;
}
function get_class_name($obj){
if(is_resource($obj)){ // 资源无法json_encode;
ob_start();echo $obj;$id = ob_get_clean();
$id = str_replace('Resource id #','',$id);
$result = '{'.$id."}@".get_resource_type($obj);
}else if(is_object($obj)){
$id = substr(md5(spl_object_hash($obj)),0,3);
$result = '{'.$id."}#".get_class($obj);
}
return $result;
}
/**
* 打包返回AJAX请求的数据
* @params {int} 返回状态码, 通常0表示正常
* @params {array} 返回的数据集合
*/
function show_json($data=false,$code = true,$info='',$infoMore=''){
if(!isset($GLOBALS['showJsonTimeStart'])){
$GLOBALS['showJsonTimeStart'] = TIME_FLOAT;
}
$result = array(
'code' => $code,
'timeUse' => sprintf('%.4f',mtime() - $GLOBALS['showJsonTimeStart']),
'timeNow' => sprintf('%.4f',mtime()),
'data' => $data
);
if($info !== ''){$result['info'] = $info;}
if($infoMore !== ''){$result['infoMore'] = $infoMore;}
// 有值且为true则返回清空输出并返回数据结果
if(isset($GLOBALS['SHOW_JSON_NOT_EXIT']) && $GLOBALS['SHOW_JSON_NOT_EXIT']){
// 保留第一个show_json调用输出;ob_get_clean 后该次置空;
if(isset($GLOBALS['SHOW_JSON_NOT_EXIT_DONE']) && $GLOBALS['SHOW_JSON_NOT_EXIT_DONE']){return;}
$GLOBALS['SHOW_JSON_NOT_EXIT_DONE'] = 1;
write_log(array('SHOW_JSON_NOT_EXIT',$result,'call'=>get_caller_info()));
if(!ob_get_length()){echo json_encode_force($result);}
return;
}
// 处理输出数据调用;
if($GLOBALS['SHOW_JSON_RESULT_PARSE']){
$resultNew = $GLOBALS['SHOW_JSON_RESULT_PARSE']($result);
$result = is_array($resultNew) ? $resultNew:$result;
$GLOBALS['SHOW_JSON_RESULT_PARSE'] = false;
}
$temp = Hook::trigger("show_json",$result);
if(is_array($temp)){$result = $temp;}
if(defined("GLOBAL_DEBUG") && GLOBAL_DEBUG==1){
// $result['in'] = $GLOBALS['in'];
$result['memory'] = sprintf("%.3fM",memory_get_usage()/(1024*1024));
$result['call'] = get_caller_info();
$result['trace'] = think_trace('[trace]');
}
check_abort(); // hook之后检测处理; task缓存保持;
@ob_get_clean();
if( isset($_SERVER['HTTP_ACCEPT_ENCODING']) &&
strstr($_SERVER['HTTP_ACCEPT_ENCODING'],'gzip')){
@ob_start('ob_gzhandler');// 自动开启gzip;
}
if(!headers_sent()){
header("X-Powered-By: kodbox.");
header('Content-Type: application/json; charset=utf-8');
if(!$code){header("X-Request-Error: 1");}
}
$json = json_encode_force($result);
if( isset($_GET['callback']) && $GLOBALS['config']['jsonpAllow'] ){
if(!preg_match("/^[0-9a-zA-Z_.]+$/",$_GET['callback'])){
die("calllback error!");
}
echo $_GET['callback'].'('.$json.');';
}else{
echo $json;
}
exit;
}
function show_trace(){
echo '<pre>';
echo json_encode_force(get_caller_info());
echo '</pre>';
exit;
}
function file_sub_str($file,$start=0,$len=0){
$size = filesize_64($file);
if($start < 0 ){
$start = $size + $start;
$len = $size - $start;
}
if($len <= 0) return '';
$fp = fopen($file,'r');
fseek_64($fp,$start);
$res = fread($fp,$len);
fclose($fp);
return $res;
}
function str2hex($string){
$hex='';
for($i=0;$i<strlen($string);$i++){
$hex .= sprintf('%02s ',dechex(ord($string[$i])));
}
$hex = strtoupper($hex);
return $hex;
}
function hex2str($hex){
$hex = str_replace(" ",'',$hex);
$string='';
for ($i=0; $i < strlen($hex)-1; $i+=2){
$string .= chr(hexdec($hex[$i].$hex[$i+1]));
}
return $string;
}
// if(!function_exists('json_encode')){
// function json_encode($data){
// $json = new Services_JSON();
// return $json->encode($data);
// }
// function json_decode($json_data,$toarray =false) {
// $json = new Services_JSON();
// $array = $json->decode($json_data);
// if ($toarray) {
// $array = obj2array($array);
// }
// return $array;
// }
// }
/**
* 去掉HTML代码中的HTML标签返回纯文本
* @param string $document 待处理的字符串
* @return string
*/
function html2txtClear($document){
$search = array ("'<script[^>]*?>.*?</>'si", // 去掉 javascript
"'<[\/\!]*?[^<>]*?>'si", // 去掉 HTML 标记
"'([\r\n])[\s]+'", // 去掉空白字符
"'&(quot|#34);'i", // 替换 HTML 实体
"'&(amp|#38);'i",
"'&(lt|#60);'i",
"'&(gt|#62);'i",
"'&(nbsp|#160);'i",
"'&(iexcl|#161);'i",
"'&(cent|#162);'i",
"'&(pound|#163);'i",
"'&(copy|#169);'i",
// "'&#(\d+);'e");
"'&#(\d+);'"); // 作为 PHP 代码运行
$replace = array ("",
"",
"",
"\"",
"&",
"<",
">",
" ",
chr(161),
chr(162),
chr(163),
chr(169),
"chr(\\1)");
$text = preg_replace_callback ($search, function(){return $replace;}, $document);
return $text;
}
function html2txt($str){
$str = preg_replace("/<style .*?<\/style>/is", "", $str);$str = preg_replace("/<script .*?<\/script>/is", "", $str);
$str = preg_replace("/<br \s*\/?\/>/i", "\n", $str);
$str = preg_replace("/<\/?p>/i", "\n\n", $str);
$str = preg_replace("/<\/?td>/i", "\n", $str);
$str = preg_replace("/<\/?div>/i", "\n", $str);
$str = preg_replace("/<\/?blockquote>/i", "\n", $str);
$str = preg_replace("/<\/?li>/i", "\n", $str);
$str = preg_replace("/\&nbsp\;/i", " ", $str);
$str = preg_replace("/\&nbsp/i", " ", $str);
$str = preg_replace("/\&amp\;/i", "&", $str);
$str = preg_replace("/\&amp/i", "&", $str);
$str = preg_replace("/\&lt\;/i", "<", $str);
$str = preg_replace("/\&lt/i", "<", $str);
$str = preg_replace("/\&ldquo\;/i", '"', $str);
$str = preg_replace("/\&ldquo/i", '"', $str);
$str = preg_replace("/\&lsquo\;/i", "'", $str);
$str = preg_replace("/\&lsquo/i", "'", $str);
$str = preg_replace("/\&rsquo\;/i", "'", $str);
$str = preg_replace("/\&rsquo/i", "'", $str);
$str = preg_replace("/\&gt\;/i", ">", $str);
$str = preg_replace("/\&gt/i", ">", $str);
$str = preg_replace("/\&rdquo\;/i", '"', $str);
$str = preg_replace("/\&rdquo/i", '"', $str);
$str = strip_tags($str);
$str = html_entity_decode($str, ENT_QUOTES, $encode);
$str = preg_replace("/\&\#.*?\;/i", "", $str);
return $str;
}
// 获取内容第一条
function match_text($content, $preg){
$preg = "/" . $preg . "/isU";
preg_match($preg, $content, $result);
return is_array($result) ? $result[1]:false;
}
// 获取内容,获取一个页面若干信息.结果在 1,2,3……中
function match_all($content, $preg){
$preg = "/" . $preg . "/isU";
preg_match_all($preg, $content, $result);
return $result;
}
if(!function_exists('mb_substr')){
function mb_substr($str,$start,$len,$charset='') {
return preg_replace('#^(?:[\x00-\x7F]|[\xC0-\xFF][\x80-\xBF]+){0,'.$start.'}'.
'((?:[\x00-\x7F]|[\xC0-\xFF][\x80-\xBF]+){0,'.$len.'}).*#s','$1',$str);
}
}
if(!function_exists('mb_strlen')){
function mb_strlen($str,$charset='') {
preg_match_all("/./u", $str, $ar);
return count($ar[0]);
}
}
/**
* 字符串截取自动修复;(仅utf8 字符串); 去除前后不足一个字符的字节
* 截取多余部分用replace替换;
* 只处理头和尾;
*
* $str = substr("我的中国心",1,-2);
* $str = utf8Repair($str);
*
* 1 1-128
* 2 192-223, 128-191
* 3 224-239, 128-191, 128-191
* 4 240-247, 128-191, 128-191, 128-191
*/
function utf8Repair($str,$replace=''){
$start = 0;$char = ord($str[$start]);
while($char >= 128 && $char <= 191 && $start <= 5){
$start ++;$char = ord($str[$start]);
}
$length = strlen($str);$charByte = 0;
$endFrom = $length - 5 > 0 ? $length - 5 : 0;
for($end = $endFrom; $end < $length; $end++){
$char = ord($str[$end]);
if ($char <= 128 || ($char >= 128 && $char <= 191)) continue;
if ($char > 239) {$charByte = 4;}
else if ($char > 223) {$charByte = 3;}
else if ($char > 191) {$charByte = 2;}
else {return $str;}
if ($end + $charByte - 1 == $length - 1){$end = $length - 1;break;} // 头占用一个字节,需减去;
if ($end + $charByte - 1 > $length - 1){$end = $end - 1;break;}
$end = $end + $charByte - 2;// -1,因为上面+1;
}
$charStart = '';$charEnd = '';$strLen = $end - $start + 1;
if($start == 0 && $end == $length - 1) return $str;
if($strLen <= 0) return $replace ? str_repeat($replace,$length) : '';
if($replace && $start){$charStart = str_repeat($replace,$start);}
if($replace && $end != $length){$charEnd = str_repeat($replace,$length - $end + 1);}
// pr($start,$end,$length,$charStart,$charEnd);exit;
return $charStart.substr($str,$start,$end - $start + 1).$charEnd;
}
/**
* 字符串截取,支持中文和其他编码
*
* @param string $str 需要转换的字符串
* @param string $start 开始位置
* @param string $length 截取长度
* @param string $charset 编码格式
* @param string $suffix 截断显示字符
* @return string
*/
function msubstr($str, $start = 0, $length, $charset = "utf-8", $suffix = true){
if (function_exists("mb_substr")) {
$i_str_len = mb_strlen($str);
$s_sub_str = mb_substr($str, $start, $length, $charset);
if ($length >= $i_str_len) {
return $s_sub_str;
}
return $s_sub_str . '...';
} elseif (function_exists('iconv_substr')) {
return iconv_substr($str, $start, $length, $charset);
}
$re['utf-8'] = "/[\x01-\x7f]|[\xc2-\xdf][\x80-\xbf]|[\xe0-\xef][\x80-\xbf]{2}|[\xf0-\xff][\x80-\xbf]{3}/";
$re['gb2312'] = "/[\x01-\x7f]|[\xb0-\xf7][\xa0-\xfe]/";
$re['gbk'] = "/[\x01-\x7f]|[\x81-\xfe][\x40-\xfe]/";
$re['big5'] = "/[\x01-\x7f]|[\x81-\xfe]([\x40-\x7e]|\xa1-\xfe])/";
preg_match_all($re[$charset], $str, $match);
$slice = join("", array_slice($match[0], $start, $length));
if ($suffix) return $slice . "";
return $slice;
}
// -----------------变量调试-------------------
/**
* 格式化输出变量,或者对象
*
* @param args;
* 默认自动退出最后一个参数为false时不退出
*/
function pr_replace_callback($matches){
return "\n".str_repeat(" ",strlen($matches[1])*2).$matches[2];
}
function pr_trace(){
$result = func_get_args();
$result['memory'] = sprintf("%.3fM",memory_get_usage()/(1024*1024));
$result['call'] = get_caller_info();
$result['trace'] = think_trace('[trace]');
call_user_func('pr',$result);
}
function pr_trace_exit(){pr_trace();exit;}
function pr(){
static $hasStyle = false;
$arg = func_get_args();
$num = func_num_args();
if( !isset($GLOBALS['debugLastTime']) ){
$time = mtime() - TIME_FLOAT;
}else{
$time = mtime() - $GLOBALS['debugLastTime'];
}
$GLOBALS['debugLastTime'] = mtime();
if($num == 0 || ($num== 1 && is_null($arg[0]))) return;
ob_start();
$style = '<style>
pre.debug{margin:2px 0;font-size:14px;color:#222;font-family:Consolas ;line-height:1.2em;background:#f6f6f6;
border-left:5px solid #444;padding:5px;width:95%;word-break:break-all;white-space:pre-wrap;word-wrap: break-word;}
pre.debug b{font-weight:400;}
.debug .debug_keywords{font-weight:200;color:#888;}
.debug .debug_tag{color:#222 !important;}
.debug .debug_var{color:#f60;}
.debug .debug_var_str,.debug #debug_var_str .debug_keywords{color:#f44336;}
.debug .debug_set{color:#0C9CAE;}</style>';
$trace = debug_backtrace();
ob_start();
$callFile = $trace[0];$callAt = $trace[1];
if(isset($trace[2]) && $trace[2]['function'] == 'pr_trace'){
$callFile = $trace[2];$callAt = $trace[3];
}
$method = $callAt['function'];
if(isset($callAt['class'])){
$method = $callAt['class'].'->'.$callAt['function'];
}
$fileInfo = get_path_this($callFile['file']).'; '.$method.'()';
$time = sprintf("%.5fs",$time);
$logInfo = "<i class='debug_keywords'>".$fileInfo.";[line-".$callFile['line']."];{$time}</i><br/>";
for ($i=0; $i < $num; $i++) {
var_dump($arg[$i]);
}
$out = ob_get_clean(); //缓冲输出给$out 变量
$out = preg_replace('/=\>\n\s+/',' => ',$out); //高亮=>后面的值
$out = preg_replace_callback('/\n(\s*)([\}\[])/','pr_replace_callback',$out); //高亮=>后面的值
if(is_cli()){echo $time.': '.$fileInfo.";[line-".$callFile['line']."] ".strip_tags($out);return;}
$out = preg_replace('/"(.*)"/','<b class="debug_var_str">"\\1"</b>', $logInfo.$out); //高亮字符串变量
$out = preg_replace('/\[(.*)\]/','<b class="debug_tag">[</b><b class="debug_var">\\1</b><b class="debug_tag">]</b>', $out); //高亮变量
$out = str_replace(array('=>',"\n\n"), array('<b id="debug_set">=></b>',"\n"), $out);
$keywords = array('array','int','string','object','null','float','bool'); //关键字高亮
$keywords_to = $keywords;
foreach($keywords as $key => $val) {
$keywords_to[$key] = '<b class="debug_keywords">' . $val . '</b>';
}
$out = str_replace($keywords, $keywords_to, $out);
// $out = stripslashes($out);
$out = str_replace(array('\n','\/'),array("<br/>",'/'),$out);
if($hasStyle){$style = "";}
if(!$hasStyle){$hasStyle = true;}
echo $style.'<pre class="debug">'.$out.'</pre>';
}
function dump(){call_user_func('pr',func_get_args());}
function debug_out(){call_user_func('pr',func_get_args());}
/**
* $from~$to范围内的随机数,包含$from,$to;
*/
function rand_from_to($from, $to){
return mt_rand($from,$to);
// return $from + mt_rand(0, $to - $from);
}
/**
* 产生随机字串,可用来自动生成密码 默认长度6位 字母和数字混合
*
* @param string $len 长度
* @param string $type 字串类型0 字母 1 数字 2 大写字母 3 小写字母 4 中文
* 其他为数字字母混合(去掉了 容易混淆的字符oOLl和数字01)
* @param string $addChars 额外字符
* @return string
*/
function rand_string($len = 4, $type='checkCode'){
$str = '';
switch ($type) {
case 1://数字
$chars = '0123456789';
break;
case 2://大写字母
$chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
break;
case 3://小写字母
$chars = 'abcdefghijklmnopqrstuvwxyz';
break;
case 4://大小写中英文
$chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
break;
default:
// 默认去掉了容易混淆的字符oOLl和数字01要添加请使用addChars参数
$chars = 'ABCDEFGHIJKMNPQRSTUVWXYZabcdefghijkmnpqrstuvwxyz23456789';
break;
}
if ($len > 10) { // 位数过长重复字符串一定次数
$chars = $type == 1 ? str_repeat($chars, $len) : str_repeat($chars, 5);
}
if ($type != 4) {
$chars = str_shuffle($chars);
$str = substr($chars, 0, $len);
} else {
// 中文随机字
for($i = 0; $i < $len; $i ++) {
$str .= msubstr($chars, floor(mt_rand(0, mb_strlen($chars, 'utf-8') - 1)), 1);
}
}
return $str;
}
/**
* 生成自动密码
*/
function make_password(){
$temp = '0123456789abcdefghijklmnopqrstuvwxyz'.
'ABCDEFGHIJKMNPQRSTUVWXYZ~!@#$^*)_+}{}[]|":;,.'.time();
for($i=0;$i<10;$i++){
$temp = str_shuffle($temp.substr($temp,-5));
}
return md5($temp);
}
/**
* php DES解密函数
*
* @param string $key 密钥
* @param string $encrypted 加密字符串
* @return string
*/
function des_decode($key, $encrypted){
$encrypted = base64_decode($encrypted);
$td = mcrypt_module_open(MCRYPT_DES, '', MCRYPT_MODE_CBC, ''); //使用MCRYPT_DES算法,cbc模式
$iv = mcrypt_create_iv(mcrypt_enc_get_iv_size($td), MCRYPT_RAND);
$ks = mcrypt_enc_get_key_size($td);
mcrypt_generic_init($td, $key, $key); //初始处理
$decrypted = mdecrypt_generic($td, $encrypted); //解密
mcrypt_generic_deinit($td); //结束
mcrypt_module_close($td);
return pkcs5_unpad($decrypted);
}
/**
* php DES加密函数
*
* @param string $key 密钥
* @param string $text 字符串
* @return string
*/
function des_encode($key, $text){
$y = pkcs5_pad($text);
$td = mcrypt_module_open(MCRYPT_DES, '', MCRYPT_MODE_CBC, ''); //使用MCRYPT_DES算法,cbc模式
$ks = mcrypt_enc_get_key_size($td);
mcrypt_generic_init($td, $key, $key); //初始处理
$encrypted = mcrypt_generic($td, $y); //解密
mcrypt_generic_deinit($td); //结束
mcrypt_module_close($td);
return base64_encode($encrypted);
}
function pkcs5_unpad($text){
$pad = ord($text[strlen($text)-1]);
if ($pad > strlen($text)) return $text;
if (strspn($text, chr($pad), strlen($text) - $pad) != $pad) return $text;
return substr($text, 0, -1 * $pad);
}
function pkcs5_pad($text, $block = 8){
$pad = $block - (strlen($text) % $block);
return $text . str_repeat(chr($pad), $pad);
}
// 检测语言,只分中文、英语
function check_lang($word){
$language = 'zh-cn';
if (!preg_match('/^[a-z]{2}(?:_[a-zA-Z]{2})?$/', $word)) {
$language = 'en';
}
return $language;
}