| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644 |
- <?php
- /**
- * ZenTaoPHP的baseHelper类。
- * The baseHelper class file of ZenTaoPHP framework.
- *
- * @package framework
- *
- * The author disclaims copyright to this source code. In place of
- * a legal notice, here is a blessing:
- *
- * May you do good and not evil.
- * May you find forgiveness for yourself and forgive others.
- * May you share freely, never taking more than you give.
- */
- class baseHelper
- {
- /**
- * 已加载的目录.
- * The loaded directories.
- *
- * @static
- * @var array
- * @access public
- */
- static $loadedDirs = array();
- /**
- * 已经包含的文件.
- * The included files.
- *
- * @static
- * @var array
- * @access public
- */
- static $includedFiles = array();
- /**
- * 设置一个对象的成员变量。
- * Set the member's value of one object.
- * <code>
- * <?php
- * $lang->db->user = 'wwccss';
- * helper::setMember('lang', 'db.user', 'chunsheng.wang');
- * ?>
- * </code>
- * @param string $objName the var name of the object.
- * @param string $key the key of the member, can be parent.child.
- * @param mixed $value the value to be set.
- * @static
- * @access public
- * @return bool
- */
- static public function setMember($objName, $key, $value)
- {
- global ${$objName};
- if(!is_object(${$objName}) or empty($key)) return false;
- $key = str_replace('.', '->', $key);
- $value = serialize($value);
- $code = ("\${$objName}->{$key}=unserialize(<<<EOT\n$value\nEOT\n);");
- eval($code);
- return true;
- }
- /**
- * 生成一个模块方法的链接。control类的createLink实际上调用的是这个方法。
- * Create a link to a module's method, mapped in control class to call conveniently.
- *
- * <code>
- * <?php
- * helper::createLink('hello', 'index', 'var1=value1&var2=value2');
- * helper::createLink('hello', 'index', array('var1' => 'value1', 'var2' => 'value2');
- * ?>
- * </code>
- * @param string $moduleName module name, can pass appName like app.module.
- * @param string $methodName method name
- * @param string|array $vars the params passed to the method, can be array('key' => 'value') or key1=value1&key2=value2) or key1=value1&key2=value2
- * @param string $viewType the view type
- * @param bool $onlyBody pass onlyBody=yes to the link thus the app can control the header and footer hide or show..
- * @static
- * @access public
- * @return string the link string.
- */
- static public function createLink($moduleName, $methodName = 'index', $vars = '', $viewType = '', $onlyBody = false)
- {
- $link = null;
- /* 设置$appName和$moduleName。Set appName and moduleName. */
- global $app, $config;
- if(strpos($moduleName, '.') !== false)
- {
- [$appName, $moduleName] = explode('.', $moduleName);
- }
- else
- {
- $appName = $app->getAppName();
- }
- if(!empty($appName)) $appName .= '/';
- /* 处理$viewType和$vars。Set $viewType and $vars. */
- if(empty($viewType)) $viewType = $app->getViewType();
- if(!is_array($vars))
- {
- /* Prevent + from converting to spaces. */
- $vars = str_replace('+', '%2B', $vars);
- parse_str($vars, $vars);
- }
- /* 生成url链接的开始部分。Set the begin parts of the link. */
- if($config->requestType == 'PATH_INFO2')
- {
- $link = '/';
- }
- elseif($config->requestType == 'PATH_INFO')
- {
- $link = $config->webRoot . $appName;
- }
- elseif($app->apiVersion)
- {
- $link = $config->webRoot . 'index.php';
- }
- else
- {
- $link = $config->webRoot . $appName . basename((string) $_SERVER['SCRIPT_NAME']);
- }
- /**
- * #1: RequestType为GET。When the requestType is GET.
- * Input: moduleName=article&methodName=index&var1=value1. Output: ?m=article&f=index&var1=value1.
- *
- */
- if($config->requestType == 'GET')
- {
- $link .= "?{$config->moduleVar}=$moduleName&{$config->methodVar}=$methodName";
- if($viewType != 'html') $link .= "&{$config->viewVar}=" . $viewType;
- foreach($vars as $key => $value) $link .= "&$key=$value";
- return static::processOnlyBodyParam($link, $onlyBody);
- }
- /**
- * #2: 方法名不是默认值或者是默认值,但有传参。MethodName equals the default method or vars not empty.
- * Input: moduleName=article&methodName=view. Output: article-view.html
- * Input: moduleName=article&methodName=view. Output: article-index-abc.html
- *
- */
- if($methodName != $config->default->method or !empty($vars))
- {
- $link .= "$moduleName{$config->requestFix}$methodName";
- foreach($vars as $value) $link .= "{$config->requestFix}$value";
- $link .= '.' . $viewType;
- return static::processOnlyBodyParam($link, $onlyBody);
- }
- /**
- * #3: 方法名为默认值且没有传参且模块名为默认值。MethodName is the default and moduleName is default and vars empty.
- * Input: moduleName=index&methodName=index. Output: index.html
- *
- */
- if($moduleName == $config->default->module)
- {
- $link .= $config->default->method . '.' . $viewType;
- return static::processOnlyBodyParam($link, $onlyBody);
- }
- /**
- * #4: 方法名为默认值且没有传参且模块名不为默认值,viewType和app指定的相等。MethodName is default but moduleName not and viewType equal app's viewType..
- * Input: moduleName=article&methodName=index&viewType=html. Output: /article/
- *
- */
- if($viewType == $app->getViewType())
- {
- $link .= $moduleName . '.' . $viewType;
- return static::processOnlyBodyParam($link, $onlyBody);
- }
- /**
- * #5: 方法名为默认值且没有传参且模块名不为默认值,viewType有另外指定。MethodName is default but moduleName not and viewType no equls app's viewType.
- * Input: moduleName=article&methodName=index&viewType=json. Output: /article.json
- *
- */
- $link .= $moduleName . '.' . $viewType;
- return static::processOnlyBodyParam($link, $onlyBody);
- }
- /**
- * 处理onlyBody 参数。
- * Process the onlyBody param in url.
- *
- * 如果传参的时候设定了$onlyBody为真,或者当前页面请求中包含了onlybody=yes,在生成链接的时候继续追加。
- * If $onlyBody set to true or onlybody=yes in the url, append onlyBody param to the link.
- *
- * @param string $link
- * @param bool $onlyBody
- * @static
- * @access public
- * @return string
- */
- public static function processOnlyBodyParam($link, $onlyBody = false)
- {
- global $config;
- $sign = strpos($link, '?') === false ? "?" : "&";
- $appendString = '';
- if($onlyBody or (static::inOnlyBodyMode() && !static::isAjaxRequest('modal'))) $appendString = $sign . "onlybody=yes";
- if(static::isWithTID() and strpos($link, 'tid=') === false) $appendString .= empty($appendString) ? "{$sign}tid={$_GET['tid']}" : "&tid={$_GET['tid']}";
- return $link . $appendString;
- }
- /**
- * 检查是否是onlybody模式。
- * Check in only body mode or not.
- *
- * @access public
- * @return bool
- */
- public static function inOnlyBodyMode()
- {
- return (isset($_GET['onlybody']) and $_GET['onlybody'] == 'yes');
- }
- /**
- * Is with tid.
- *
- * @static
- * @access public
- * @return bool
- */
- public static function isWithTID()
- {
- global $config;
- return (!empty($config->tabSession) and isset($_GET['tid']));
- }
- /**
- * 使用helper::import()来引入文件,不要直接使用include或者require.
- * Using helper::import() to import a file, instead of include or require.
- *
- * @param string $file the file to be imported.
- * @static
- * @access public
- * @return bool
- */
- static public function import($file)
- {
- $file = realpath($file);
- if($file === false) return false;
- if(isset(static::$includedFiles[$file])) return true;
- if(!is_file($file)) return false;
- include $file;
- static::$includedFiles[$file] = true;
- return true;
- }
- /**
- * 使用helper::importControl()来引入Control文件,不要直接使用include或者require.
- * Using helper::importControl() to import a file, instead of include or require.
- *
- * @param string $moduleName.
- * @static
- * @access public
- * @return bool
- */
- static public function importControl($moduleName)
- {
- global $app;
- return helper::import($app->getModulePath('', $moduleName) . 'control.php');
- }
- /**
- * 转义 'order by' 之后下一个关键字之前的SQL语句。Wrap partial sql after 'order by' keyword and before the next keyword such as 'limit'.
- * 将部分MySQL保留字用反引号包裹起来。Wrap some reserved word of MySQL in backticks.
- * 例如/example: 'order_desc' -> '`order` desc', 'order_asc' -> '`order` asc'
- * @see https://dev.mysql.com/doc/refman/en/identifiers.html
- * @see https://dev.mysql.com/doc/refman/en/keywords.html
- * @param string $sql
- * @return string
- */
- static public function wrapSqlAfterOrderBy($sql)
- {
- $sql = trim($sql);
- $sql = preg_replace('/_(asc|desc)$/i', ' $1', $sql);
- if(empty($sql)) return '';
- if(strpos($sql, ' ') === false and strpos($sql, ',') === false) return '`' . $sql . '`';
- $reservedWords = ['asc', 'desc', 'order', 'limit'];
- $sqlParts = explode(',', $sql);
- $wrappedParts = [];
- foreach ($sqlParts as $part)
- {
- if(in_array($part, $reservedWords))
- {
- $wrappedParts[] = '`' . $part . '`';
- }
- else
- {
- if(strpos($part, ' ') !== false)
- {
- $part = preg_replace('/([0-9,a-z,A-Z$_]+) (asc|desc)/i', '`$1` $2', $part);
- $wrappedParts[] = $part;
- }
- else
- {
- $wrappedParts[] = '`' . $part . '`';
- }
- }
- }
- return implode(',', $wrappedParts);
- }
- /**
- * 将数组或者列表转化成 IN( 'a', 'b') 的形式。
- * Convert a list to IN('a', 'b') string.
- *
- * @param string|array $idList 列表,可以是数组或者用逗号隔开的列表。The id lists, can be a array or a string joined with comma.
- * @static
- * @access public
- * @return string the string like IN('a', 'b').
- */
- static public function dbIN($idList)
- {
- if(is_array($idList))
- {
- foreach($idList as $key=>$value) $idList[$key] = addslashes((string) $value);
- $idCount = count($idList);
- if($idCount == 0) return "= NULL";
- if($idCount == 1) return "= '" . current($idList) . "'";
- return "IN ('" . join("','", $idList) . "')";
- }
- if(is_null($idList)) return '=NULL';
- if(!is_string($idList)) $idList = json_encode($idList);
- $idList = str_replace(',', "','", str_replace(' ', '', addslashes($idList)));
- if(substr_count($idList, ',') != 0) return "IN ('" . $idList . "')";
- return $idList == '' ? '= NULL' : "= '$idList'";
- }
- /**
- * 安全的Base64编码,框架对'/'字符比较敏感,转换为'.'。
- * Create safe base64 encoded string for the framework.
- *
- * @param string $string the string to encode.
- * @static
- * @access public
- * @return string encoded string.
- */
- static public function safe64Encode($string)
- {
- return strtr(base64_encode($string), '/', '.');
- }
- /**
- * 解码base64,先将之前的'.' 转换回'/'
- * Decode the string encoded by safe64Encode.
- *
- * @param string $string the string to decode
- * @static
- * @access public
- * @return string decoded string.
- */
- static public function safe64Decode($string)
- {
- return base64_decode(strtr($string, '.', '/'));
- }
- /**
- * JSON编码,自动处理转义的问题。
- * JSON encode, process the slashes.
- *
- * @param mixed $data the object to encode
- * @static
- * @access public
- * @return string decoded string.
- */
- static public function jsonEncode($data)
- {
- return json_encode($data, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES | JSON_PRESERVE_ZERO_FRACTION);
- }
- /**
- * Encrypt password.
- *
- * @param string $password
- * @static
- * @access public
- * @return string
- */
- public static function encryptPassword($password)
- {
- global $config;
- $encrypted = '';
- if(!empty($config->encryptSecret) and $password)
- {
- $secret = $config->encryptSecret;
- $iv = str_repeat("\0", 8);
- if(function_exists('mcrypt_encrypt'))
- {
- $encrypted = base64_encode((string) mcrypt_encrypt(MCRYPT_DES, substr((string) $secret, 0, 8), $password, MCRYPT_MODE_CBC, $iv));
- }
- elseif(function_exists('openssl_encrypt'))
- {
- /* Set password length to multiple of 8. For compatible mcrypt_encrypt function. */
- $oversize = strlen($password) % 8;
- if($oversize != 0) $password .= str_repeat("\0", 8 - $oversize);
- $encrypted = openssl_encrypt($password, 'DES-CBC', substr((string) $secret, 0, 8), OPENSSL_ZERO_PADDING, $iv);
- }
- }
- if(empty($encrypted)) $encrypted = $password;
- return $encrypted;
- }
- /**
- * Decrypt password.
- *
- * @param string $password
- * @static
- * @access public
- * @return string
- */
- public static function decryptPassword($password)
- {
- global $config;
- $decryptedPassword = '';
- if(!empty($config->encryptSecret) and $password)
- {
- $secret = $config->encryptSecret;
- $iv = str_repeat("\0", 8);
- if(function_exists('mcrypt_decrypt'))
- {
- $decryptedPassword = trim((string) mcrypt_decrypt(MCRYPT_DES, substr((string) $secret, 0, 8), base64_decode($password), MCRYPT_MODE_CBC, $iv));
- }
- elseif(function_exists('openssl_decrypt'))
- {
- $decryptedPassword = trim(openssl_decrypt($password, 'DES-CBC', substr((string) $secret, 0, 8), OPENSSL_ZERO_PADDING, $iv));
- }
- /* Check decrypted password. Judge whether there is garbled code. */
- $jsoned = json_encode($decryptedPassword);
- if($jsoned === 'null' or empty($jsoned)) $decryptedPassword = '';
- }
- if(empty($decryptedPassword)) $decryptedPassword = $password;
- $decryptedPassword = trim($decryptedPassword);
- return $decryptedPassword;
- }
- /**
- * 判断是否是utf8编码
- * Judge a string is utf-8 or not.
- *
- * @author hmdker@gmail.com
- * @param string $string
- * @see http://php.net/manual/en/function.mb-detect-encoding.php
- * @static
- * @access public
- * @return bool
- */
- static public function isUTF8($string)
- {
- $c = 0;
- $b = 0;
- $bits = 0;
- $len = strlen($string);
- for($i=0; $i<$len; $i++)
- {
- $c = ord($string[$i]);
- if($c > 128)
- {
- if(($c >= 254)) return false;
- elseif($c >= 252) $bits=6;
- elseif($c >= 248) $bits=5;
- elseif($c >= 240) $bits=4;
- elseif($c >= 224) $bits=3;
- elseif($c >= 192) $bits=2;
- else return false;
- if(($i+$bits) > $len) return false;
- while($bits > 1)
- {
- $i++;
- $b=ord($string[$i]);
- if($b < 128 || $b > 191) return false;
- $bits--;
- }
- }
- }
- return true;
- }
- /**
- * 去掉UTF-8 Bom头。
- * Remove UTF-8 Bom.
- *
- * @param string|false $string
- * @access public
- * @return string
- */
- public static function removeUTF8Bom($string)
- {
- /* The ob_get_clean() will return false if output buffering isn't active. */
- if(!is_string($string)) return '';
- if(substr($string, 0, 3) == pack('CCC', 239, 187, 191)) return substr($string, 3);
- return $string;
- }
- /**
- * 增强substr方法:支持多字节语言,比如中文。
- * Enhanced substr version: support multibyte languages like Chinese.
- *
- * @param string $string
- * @param int $length
- * @param string $append
- * @return string
- */
- public static function substr($string, $length, $append = '')
- {
- $rawString = $string;
- if(function_exists('mb_substr')) $string = mb_substr($string, 0, $length, 'utf-8');
- preg_match_all("/./su", $string, $data);
- $string = implode("", array_slice($data[0], 0, $length));
- return ($string != $rawString) ? $string . $append : $string;
- }
- /**
- * Get browser name and version.
- *
- * @access public
- * @return array
- */
- public static function getBrowser()
- {
- $browser = array('name'=>'unknown', 'version'=>'unknown');
- if(empty($_SERVER['HTTP_USER_AGENT'])) return $browser;
- $agent = $_SERVER["HTTP_USER_AGENT"];
- /* Chrome should check before safari.*/
- if(strpos((string) $agent, 'Firefox') !== false) $browser['name'] = "firefox";
- if(strpos((string) $agent, 'Opera') !== false) $browser['name'] = 'opera';
- if(strpos((string) $agent, 'Safari') !== false) $browser['name'] = 'safari';
- if(strpos((string) $agent, 'Chrome') !== false) $browser['name'] = "chrome";
- // Check the name of browser
- if(strpos((string) $agent, 'MSIE') !== false || strpos((string) $agent, 'rv:11.0')) $browser['name'] = 'ie';
- if(strpos((string) $agent, 'Edge') !== false) $browser['name'] = 'edge';
- // Check the version of browser
- if(preg_match('/MSIE\s(\d+)\..*/i', (string) $agent, $regs)) $browser['version'] = $regs[1];
- if(preg_match('/FireFox\/(\d+)\..*/i', (string) $agent, $regs)) $browser['version'] = $regs[1];
- if(preg_match('/Opera[\s|\/](\d+)\..*/i', (string) $agent, $regs)) $browser['version'] = $regs[1];
- if(preg_match('/Chrome\/(\d+)\..*/i', (string) $agent, $regs)) $browser['version'] = $regs[1];
- if((strpos((string) $agent, 'Chrome') === false) && preg_match('/Safari\/(\d+)\..*$/i', (string) $agent, $regs)) $browser['version'] = $regs[1];
- if(preg_match('/rv:(\d+)\..*/i', (string) $agent, $regs)) $browser['version'] = $regs[1];
- if(preg_match('/Edge\/(\d+)\..*/i', (string) $agent, $regs)) $browser['version'] = $regs[1];
- return $browser;
- }
- /**
- * Get client os from agent info.
- *
- * @static
- * @access public
- * @return string
- */
- public static function getOS()
- {
- if(empty($_SERVER['HTTP_USER_AGENT'])) return 'unknow';
- $osList = array();
- $osList['/windows nt 10/i'] = 'Windows 10';
- $osList['/windows nt 6.3/i'] = 'Windows 8.1';
- $osList['/windows nt 6.2/i'] = 'Windows 8';
- $osList['/windows nt 6.1/i'] = 'Windows 7';
- $osList['/windows nt 6.0/i'] = 'Windows Vista';
- $osList['/windows nt 5.2/i'] = 'Windows Server 2003/XP x64';
- $osList['/windows nt 5.1/i'] = 'Windows XP';
- $osList['/windows xp/i'] = 'Windows XP';
- $osList['/windows nt 5.0/i'] = 'Windows 2000';
- $osList['/windows me/i'] = 'Windows ME';
- $osList['/win98/i'] = 'Windows 98';
- $osList['/win95/i'] = 'Windows 95';
- $osList['/win16/i'] = 'Windows 3.11';
- $osList['/macintosh|mac os x/i'] = 'Mac OS X';
- $osList['/mac_powerpc/i'] = 'Mac OS 9';
- $osList['/linux/i'] = 'Linux';
- $osList['/ubuntu/i'] = 'Ubuntu';
- $osList['/iphone/i'] = 'iPhone';
- $osList['/ipod/i'] = 'iPod';
- $osList['/ipad/i'] = 'iPad';
- $osList['/android/i'] = 'Android';
- $osList['/blackberry/i'] = 'BlackBerry';
- $osList['/webos/i'] = 'Mobile';
- foreach ($osList as $regex => $value)
- {
- if(preg_match($regex, (string) $_SERVER['HTTP_USER_AGENT'])) return $value;
- }
- return 'unknown';
- }
- /**
- * 计算两个日期相差的天数,取整。
- * Compute the diff days of two date.
- *
- * @param string $date1 the first date.
- * @param string $date2 the second date.
- * @access public
- * @return int the diff of the two days.
- */
- static public function diffDate($date1, $date2)
- {
- if(empty($date1) or empty($date2)) return 0;
- /* Get the timestamp in the current operating system. */
- $date1 = new DateTime($date1);
- $date2 = new DateTime($date2);
- $date1 = date_format($date1, "U"); /* Seconds since the Unix Epoch (January 1 1970 00:00:00 GMT). */
- $date2 = date_format($date2, "U");
- return (int)round(($date1 - $date2) / 86400, 0);
- }
- /**
- * 获取当前时间,使用common语言文件定义的DT_DATETIME1常量。
- * Get now time use the DT_DATETIME1 constant defined in the lang file.
- *
- * @access public
- * @return string now
- */
- static public function now()
- {
- return date(DT_DATETIME1);
- }
- /**
- * 获取当前日期,使用common语言文件定义的DT_DATE1常量。
- * Get today according to the DT_DATE1 constant defined in the lang file.
- *
- * @access public
- * @return string today
- */
- static public function today()
- {
- return date(DT_DATE1);
- }
- /**
- * 获取当前日期,使用common语言文件定义的DT_TIME1常量。
- * Get now time use the DT_TIME1 constant defined in the lang file.
- *
- * @access public
- * @return string today
- */
- static public function time()
- {
- return date(DT_TIME1);
- }
- /**
- * 判断日期是不是零。
- * Judge a date is zero or not.
- *
- * @access public
- * @return bool
- */
- static public function isZeroDate($date)
- {
- return (empty($date) or substr($date, 0, 4) <= '1970');
- }
- /**
- * 列出目录中符合该正则表达式的文件。
- * Get files match the pattern under a directory.
- *
- * @access public
- * @return array the files match the pattern
- */
- static public function ls($dir, $pattern = '')
- {
- if(empty($dir)) return array();
- if(isset(static::$loadedDirs[$dir][$pattern])) return static::$loadedDirs[$dir][$pattern];
- $files = array();
- $dir = realpath($dir);
- if($dir === false) return array();
- if(is_dir($dir)) $files = glob($dir . DIRECTORY_SEPARATOR . '*' . $pattern);
- static::$loadedDirs[$dir][$pattern] = $files ?: array();
- return static::$loadedDirs[$dir][$pattern];
- }
- /**
- * 切换目录。第一次调用的时候记录当前的路径,再次调用的时候切换回之前的路径。
- * Change directory: first call, save the $cwd, second call, change to $cwd.
- *
- * @param string $path
- * @static
- * @access public
- * @return void
- */
- static public function cd($path = '')
- {
- static $cwd = '';
- if($path) $cwd = getcwd();
- !empty($path) ? chdir($path) : chdir($cwd);
- }
- /**
- * 通过域名获取站点代号。
- * Get siteCode for a domain.
- *
- * www.xirang.com => xirang
- * xirang.com => xirang
- * xirang.com.cn => xirang
- * xirang.cn => xirang
- * xirang => xirang
- *
- * @param string $domain
- * @return string $siteCode
- **/
- public static function parseSiteCode($domain)
- {
- global $config;
- /* 去除域名中的端口部分。Remove the port part of the domain. */
- if(strpos($domain, ':') !== false) $domain = substr($domain, 0, strpos($domain, ':'));
- $domain = strtolower($domain);
- /* $config里面有定义或者是localhost,直接返回。 Return directly if defined in $config or is localhost. */
- if(isset($config->siteCodeList[$domain])) return $config->siteCodeList[$domain];
- if($domain == 'localhost') return $domain;
- /* 将域名中的-改为_。Replace '-' with '_' in the domain. */
- $domain = str_replace('-', '_', $domain);
- $items = explode('.', $domain);
- /* 类似a.com的形式。 Domain like a.com. */
- $postfix = str_replace($items[0] . '.', '', $domain);
- if(isset($config->domainPostfix) and strpos((string) $config->domainPostfix, "|$postfix|") !== false) return $items[0];
- /* 类似www.a.com的形式。 Domain like www.a.com. */
- $postfix = str_replace($items[0] . '.' . $items[1] . '.', '', $domain);
- if(isset($config->domainPostfix) and strpos((string) $config->domainPostfix, "|$postfix|") !== false) return $items[1];
- /* 类似xxx.sub.a.com的形式。 Domain like xxx.sub.a.com. */
- $postfix = str_replace($items[0] . '.' . $items[1] . '.' . $items[2] . '.', '', $domain);
- if(isset($config->domainPostfix) and strpos((string) $config->domainPostfix, "|$postfix|") !== false) return $items[0];
- return '';
- }
- /**
- * 检查是否是AJAX请求。
- * Check is ajax request.
- *
- * @param ?string $type zin|modal|fetch
- * @static
- * @access public
- * @return bool
- */
- public static function isAjaxRequest($type = null)
- {
- $isAjax = (isset($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH'] === 'XMLHttpRequest') || (isset($_GET['HTTP_X_REQUESTED_WITH']) && $_GET['HTTP_X_REQUESTED_WITH'] === 'XMLHttpRequest');
- if($isAjax === false) return false;
- if($type === 'zin') return array_key_exists('HTTP_X_ZIN_OPTIONS', $_SERVER);
- if($type === 'modal') return isset($_SERVER['HTTP_X_ZUI_MODAL']) && $_SERVER['HTTP_X_ZUI_MODAL'] == true;
- if($type === 'fetch') return !array_key_exists('HTTP_X_ZIN_OPTIONS', $_SERVER) && !(isset($_SERVER['HTTP_X_ZUI_MODAL']) && $_SERVER['HTTP_X_ZUI_MODAL'] == true);
- return $isAjax;
- }
- /**
- * 301跳转。
- * Header 301 Moved Permanently.
- *
- * @param string $locate
- * @access public
- * @return void
- */
- public static function header301($locate)
- {
- helper::setStatus(301);
- helper::header('location', $locate);
- helper::end();
- }
- /**
- * 获取远程IP。
- * Get remote ip.
- *
- * @param bool $proxy
- * @param bool $single
- * @access public
- * @return string
- */
- public static function getRemoteIp($proxy = true, $single = true)
- {
- $ip = '';
- if(!empty($_SERVER["REMOTE_ADDR"])) $ip = $_SERVER["REMOTE_ADDR"];
- if($proxy)
- {
- if(!empty($_SERVER["HTTP_X_FORWARDED_FOR"])) $ip = $_SERVER["HTTP_X_FORWARDED_FOR"];
- if(!empty($_SERVER['HTTP_CLIENT_IP'])) $ip = $_SERVER['HTTP_CLIENT_IP'];
- /* The Proxy Server like CDN will change the HTTP_X_FORWARDED_FOR header with value 'realIP, proxyIP'. */
- if($single && strpos($ip, ',') !== false) $ip = trim(explode(',', $ip)[0]);
- }
- return $ip;
- }
- /**
- * Restart session.
- *
- * @param string $sessionID
- * @static
- * @access public
- * @return void
- */
- public static function restartSession($sessionID = '')
- {
- if(!preg_match('/^\w+$/', $sessionID)) $sessionID = '';
- if(empty($sessionID)) $sessionID = sha1((string)mt_rand(0, mt_getrandmax()));
- session_write_close();
- if(ini_get('session.save_handler') == 'user') // Once enable the custom session handler in baseRouter, session.save_handler becomes user.
- {
- $ztSessionHandler = new ztSessionHandler();
- session_set_save_handler($ztSessionHandler, true);
- }
- session_id($sessionID);
- session_start();
- global $app;
- if($app && isset($_SESSION['user'])) $app->user = $_SESSION['user'];
- if($app && !isset($_SESSION['user'])) unset($app->user);
- }
- /**
- * Check DB to repair table.
- *
- * @param object $exception
- * @static
- * @access public
- * @return string
- */
- public static function checkDB2Repair($exception)
- {
- global $config, $lang;
- $repairCode = '|1034|1035|1194|1195|1459|';
- $errorInfo = $exception->errorInfo;
- $errorCode = zget($errorInfo, 1, 0);
- $errorMsg = zget($errorInfo, 2, '');
- $message = $exception->getMessage();
- if(strpos($repairCode, "|$errorCode|") !== false or ($errorCode == '1016' and strpos((string) $errorMsg, 'errno: 145') !== false) or strpos((string) $message, 'repair') !== false)
- {
- if(isset($config->framework->autoRepairTable) and $config->framework->autoRepairTable)
- {
- helper::header('location', $config->webRoot . 'checktable.php');
- helper::end();
- }
- return $lang->repairTable;
- }
- return null;
- }
- /**
- * Send a cookie.
- *
- * @param string $name
- * @param string|int|bool $value
- * @param int|null $expire
- * @param string|null $path
- * @param string $domain
- * @param bool|null $secure
- * @param bool $httponly
- * @static
- * @access public
- * @return bool
- */
- public static function setcookie($name, $value = '', $expire = null, $path = null, $domain = '', $secure = null, $httponly = true)
- {
- if(defined('RUN_MODE') && RUN_MODE == 'test')
- {
- $_COOKIE[$name] = (string)$value;
- return;
- }
- global $config, $app;
- if($expire === null) $expire = $config->cookieLife;
- if($path === null) $path = $config->webRoot;
- if($secure === null) $secure = $config->cookieSecure;
- $value = (string)$value;
- $_COOKIE[$name] = $value;
- if(isset($app->worker))
- {
- $app->worker->response->setCookie($name, $value, $expire, $path, $domain, $secure, $httponly);
- }
- else
- {
- return setcookie($name, $value, $expire, $path, $domain, $secure, $httponly);
- }
- }
- /**
- * 设置状态码。
- * Set status code.
- *
- * @param int $code
- * @static
- * @access public
- * @return void
- */
- static public function setStatus($code)
- {
- global $app;
- if(isset($app->worker))
- {
- $app->worker->response->setStatus($code);
- }
- else
- {
- $PHRASES = array(
- 100 => 'Continue', 101 => 'Switching Protocols', 102 => 'Processing',
- 200 => 'OK', 201 => 'Created', 202 => 'Accepted', 203 => 'Non-Authoritative Information', 204 => 'No Content', 205 => 'Reset Content', 206 => 'Partial Content', 207 => 'Multi-status', 208 => 'Already Reported',
- 300 => 'Multiple Choices', 301 => 'Moved Permanently', 302 => 'Found', 303 => 'See Other', 304 => 'Not Modified', 305 => 'Use Proxy', 306 => 'Switch Proxy', 307 => 'Temporary Redirect',
- 400 => 'Bad Request', 401 => 'Unauthorized', 402 => 'Payment Required', 403 => 'Forbidden', 404 => 'Not Found', 405 => 'Method Not Allowed', 406 => 'Not Acceptable', 407 => 'Proxy Authentication Required', 408 => 'Request Time-out', 409 => 'Conflict', 410 => 'Gone', 411 => 'Length Required', 412 => 'Precondition Failed', 413 => 'Request Entity Too Large', 414 => 'Request-URI Too Large', 415 => 'Unsupported Media Type', 416 => 'Requested range not satisfiable', 417 => 'Expectation Failed', 418 => 'I\'m a teapot', 422 => 'Unprocessable Entity', 423 => 'Locked', 424 => 'Failed Dependency', 425 => 'Unordered Collection', 426 => 'Upgrade Required', 428 => 'Precondition Required', 429 => 'Too Many Requests', 431 => 'Request Header Fields Too Large', 451 => 'Unavailable For Legal Reasons',
- 500 => 'Internal Server Error', 501 => 'Not Implemented', 502 => 'Bad Gateway', 503 => 'Service Unavailable', 504 => 'Gateway Time-out', 505 => 'HTTP Version not supported', 506 => 'Variant Also Negotiates', 507 => 'Insufficient Storage', 508 => 'Loop Detected', 511 => 'Network Authentication Required',
- );
- header('HTTP/1.1 ' . (string)$code . ' ' . $PHRASES[$code], true, $code);
- }
- }
- /**
- * 发送HTTP头信息。
- * Send http header.
- *
- * @param string $key
- * @param string $value
- * @param bool $replace
- * @param int $response_code
- * @static
- * @access public
- * @return void
- */
- static public function header($key, $value, $replace = true, $response_code = 0)
- {
- global $app;
- if(isset($app->worker))
- {
- $key = trim(strtolower($key));
- $app->worker->response->setHeader($key, $value);
- if($key == 'location')
- {
- $app->worker->response->setStatus(302);
- helper::end();
- }
- }
- else
- {
- header($key . ': ' . $value, $replace, $response_code);
- }
- }
- /**
- * Generate rand string.
- *
- * @param int $length
- * @access public
- * @return string
- */
- static public function randStr($length = 4)
- {
- $seeds = str_shuffle('abcdefghijklmnpqrstuvwxyzABCDEFGHIJKLMNPQRSTUVWXYZ123456789');
- return substr($seeds, 0, $length);
- }
- /**
- * 获取二维数组中的某一列。
- * Get array column to array.
- *
- * @param array $input
- * @param int|string|null $columnKey
- * @param int|string|null $indexKey
- * @static
- * @access public
- * @return array
- */
- public static function arrayColumn($input, $columnKey, $indexKey = null)
- {
- /* If php version greater than 7, calling system functions returns. */
- if(defined('PHP_VERSION_ID') && PHP_VERSION_ID >= 70000) return \array_column($input, $columnKey, $indexKey);
- $output = array();
- foreach($input as $row)
- {
- $key = $value = null;
- $keySet = $valueSet = false;
- if($indexKey !== null && array_key_exists($indexKey, (array) $row))
- {
- $keySet = true;
- $key = \is_object($row) ? (string) $row->$indexKey : (string) $row[$indexKey];
- }
- if(null === $columnKey)
- {
- $valueSet = true;
- $value = $row;
- }
- elseif(\is_array($row) && \array_key_exists($columnKey, $row))
- {
- $valueSet = true;
- $value = $row[$columnKey];
- }
- elseif(\is_object($row) && \property_exists($row, $columnKey))
- {
- $valueSet = true;
- $value = $row->$columnKey;
- }
- if($valueSet)
- {
- if($keySet)
- {
- $output[$key] = $value;
- }
- else
- {
- $output[] = $value;
- }
- }
- }
- return $output;
- }
- /**
- * 在本地语言没有中文的环境下解析pathinfo.
- * pathinfo of utf-8.
- *
- * @param string $filepath
- * @access public
- * @return array
- */
- public static function mbPathinfo($filepath)
- {
- $ret = array('dirname' => '', 'basename' => '', 'extension' => '', 'filename' => '');
- preg_match('%^(.*?)[\\\\/]*(([^/\\\\]*?)(\.([^\.\\\\/]+?)|))[\\\\/\.]*$%im',$filepath,$m);
- $ret['dirname'] = !empty($m[1]) ? $m[1] : '';
- $ret['basename'] = !empty($m[2]) ? $m[2] : '';
- $ret['extension'] = !empty($m[5]) ? $m[5] : '';
- $ret['filename'] = !empty($m[3]) ? $m[3] : '';
- return $ret;
- }
- /**
- * 代替 die、exit 函数终止并输出。
- * Instead of die, exit function to terminate and output.
- *
- * @param string $content
- * @return never
- * @throws EndResponseException
- */
- public static function end($content = '')
- {
- throw EndResponseException::create($content);
- }
- /**
- * 连接 Redis 服务器。
- * Connect to Redis server.
- *
- * @param object $setting
- * @static
- * @access public
- * @return object
- */
- public static function connectRedis($setting)
- {
- if(!class_exists('Redis')) throw new Exception('The Redis extension is not installed.');
- try
- {
- $redis = new Redis();
- $version = phpversion('redis');
- $password = !empty($setting->password) ? htmlspecialchars_decode($setting->password) : null;
- if(version_compare($version, '5.3.0', 'ge'))
- {
- $redis->connect($setting->host, (int)$setting->port, 1, null, 0, 0, ['auth' => [$setting->username ?: null, $password]]);
- }
- else
- {
- $redis->connect($setting->host, (int)$setting->port, 1, null, 0, 0);
- $redis->auth($password);
- }
- if(!$redis->ping()) throw new Exception('Can not connect to Redis server.');
- $databases = $redis->config('GET', 'databases');
- if($setting->database >= $databases['databases']) throw new Exception("The database number is out of range. Your Redis server's max database number is " . ($databases['databases'] - 1) . '.');
- return $redis;
- }
- catch(RedisException $e)
- {
- throw new Exception('Can not connect to Redis server. The error message is: ' . $e->getMessage());
- }
- }
- /**
- * 转换类型。
- * Convert the type.
- *
- * @param mixed $value
- * @param string $type
- * @static
- * @access public
- * @return array|bool|float|int|object|string
- */
- public static function convertType($value, $type)
- {
- switch($type)
- {
- case 'int':
- return (int)$value;
- case 'float':
- return (float)$value;
- case 'bool':
- return (bool)filter_var($value, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE);
- case 'array':
- return array_filter((array)$value, function($var){return ($var === '0' || !empty($var));});
- case 'object':
- return (object)$value;
- case 'datetime':
- case 'date':
- return $value ? trim((string)$value) : null;
- case 'string':
- default:
- return trim((string)$value);
- }
- }
- /**
- * 将科学计数法展示的工时转换为字符串。
- * Convert scientific notation of hours to string.
- *
- * @param string|float $hours
- * @access public
- * @return string
- */
- public static function formatHours($hours = '', $decimals = 2, $characters = '.')
- {
- return rtrim(rtrim(number_format((float)$hours, $decimals, $characters, ''), '0'), $characters);
- }
- /**
- * 判断当前页面是否需要进行htmlspecialchars_decode解码。
- * Check if current page need to decode with htmlspecialchars_decode.
- *
- * @access public
- * @return bool
- */
- public static function needDecodeHtmlSpecialChars()
- {
- /* API模式下,所有页面都需要解码。In API mode, all pages need to be decoded. */
- if(defined('RUN_MODE') && RUN_MODE == 'api') return true;
- global $app, $config;
- /* baseRouter 构造函数中会调用此方法,此时 $app 还未初始化完成。The baseRouter constructor will call this method, at this time $app is not initialized yet. */
- if(is_null($app)) return false;
- /* 当前请求已经判断过,直接返回结果。 The current request has been judged, return the result directly. */
- if(!is_null($app->needDecodeHtmlSpecialChars)) return $app->needDecodeHtmlSpecialChars;
- /* 如果是旧页面,则不需要解码。 If it is an old page, no need to decode. */
- $moduleName = $app->getModuleName();
- $methodName = $app->getMethodName();
- if(!isset($config->index->oldPages)) $app->loadConfig('index');
- $app->needDecodeHtmlSpecialChars = !in_array("{$moduleName}-{$methodName}", $config->index->oldPages);
- return $app->needDecodeHtmlSpecialChars;
- }
- /**
- * 对数据对象或数组中的标题字段进行htmlspecialchars_decode解码。
- * Decode the title field in data object or array with htmlspecialchars_decode.
- *
- * @param string $table
- * @param object|array $data
- * @access public
- * @return bool|object|array
- */
- public static function decodeHtmlSpecialChars($table, $data)
- {
- if(empty($data)) return $data;
- if(!is_object($data) && !is_array($data)) return $data;
- if(!self::needDecodeHtmlSpecialChars()) return $data;
- global $app, $config;
- $objectType = str_replace(['`', $config->db->prefix], '', $table);
- if(in_array($objectType, array('config', 'user'))) return $data;
- if(!isset($config->action->objectNameFields)) $app->loadConfig('action');
- $titleField = $config->action->objectNameFields[$objectType] ?? '';
- if(!$titleField) return $data;
- if(is_object($data))
- {
- if(isset($data->$titleField)) $data->$titleField = htmlspecialchars_decode((string)$data->$titleField, ENT_QUOTES);
- return $data;
- }
- foreach($data as $key => $row)
- {
- if(is_object($row) && isset($row->$titleField)) $row->$titleField = htmlspecialchars_decode((string)$row->$titleField, ENT_QUOTES);
- if(is_array($row) && isset($row[$titleField])) $row[$titleField] = htmlspecialchars_decode((string)$row[$titleField], ENT_QUOTES);
- $data[$key] = $row;
- }
- return $data;
- }
- }
- //------------------------------- 常用函数。Some tool functions.-------------------------------//
- /**
- * helper::createLink()的别名,方便创建本模块方法的链接。
- * The short alias of helper::createLink() method to create link to control method of current module.
- *
- * @param string $methodName the method name
- * @param string|array $vars the params passed to the method, can be array('key' => 'value') or key1=value1&key2=value2)
- * @param string $viewType
- * @return string the link string.
- */
- function inLink($methodName = 'index', $vars = '', $viewType = '', $onlybody = false)
- {
- global $app;
- return helper::createLink($app->getModuleName(), $methodName, $vars, $viewType, $onlybody);
- }
- /**
- * 通过一个静态游标,可以遍历数组。
- * Static cycle a array.
- *
- * @param array $items the array to be cycled.
- * @return mixed
- */
- function cycle($items)
- {
- static $i = 0;
- if(!is_array($items)) $items = explode(',', $items);
- if(!isset($items[$i])) $i = 0;
- $result = $items[$i];
- $i++;
- return $result;
- }
- /**
- * 获取当前时间的Unix时间戳,精确到微妙。
- * Get current microtime.
- *
- * @access public
- * @return float current time.
- */
- function getTime()
- {
- [$usec, $sec] = explode(" ", microtime());
- return ((float)$usec + (float)$sec);
- }
- /**
- * 打印变量的信息,支持传入多个变量信息。
- * dump a var, support multi vars.
- *
- * @access public
- * @param mixed ...$vars the vars to be dumped.
- * @return int return the count of vars.
- */
- function a()
- {
- $vars = func_get_args();
- foreach($vars as $var)
- {
- echo "<pre style='background:#eee;border:1px solid #aaa;padding:0.4em 0.8em;font-size:12px;overflow:auto;color:#000;margin:12px 0'><code>";
- print_r($var);
- echo "</code></pre>";
- }
- return count($vars);
- }
- /**
- * 判断是否内外IP。
- * Judge the server ip is local or not.
- *
- * @access public
- * @return bool
- */
- function isLocalIP()
- {
- if(PHP_SAPI == 'cli' || php_sapi_name() == 'cli') return true;
- global $config;
- if(isset($config->isLocalIP)) return $config->isLocalIP;
- $serverIP = $_SERVER['SERVER_ADDR'];
- if($serverIP == '127.0.0.1' or $serverIP == '::1') return true;
- if(strpos((string) $serverIP, '10.70') !== false) return false;
- return !filter_var($serverIP, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE);
- }
- /**
- * 获取webRoot。
- * Get web root.
- *
- * @access public
- * @return string
- */
- function getWebRoot($full = false)
- {
- $envWebRoot = (string)getenv('ZT_WEB_ROOT');
- if($envWebRoot) $envWebRoot = '/' . trim($envWebRoot, '/') . '/';
- if(!$full && $envWebRoot) return $envWebRoot;
- $path = $_SERVER['SCRIPT_NAME'];
- if(PHP_SAPI == 'cli')
- {
- if(isset($_SERVER['argv'][1]))
- {
- $url = parse_url((string) $_SERVER['argv'][1]);
- $path = empty($url['path']) ? '/' : rtrim($url['path'], '/');
- }
- $path = empty($path) ? '/' : preg_replace('/\/www$/', '/www/', (string) $path);
- }
- if($full)
- {
- $http = isHttps() ? 'https://' : 'http://';
- return $http . $_SERVER['HTTP_HOST'] . substr((string) $path, 0, (strrpos((string) $path, '/') + 1)) . trim($envWebRoot, '/');
- }
- $pos = strrpos((string) $path, '/');
- if($pos === false) return '';
- $path = substr((string) $path, 0, ($pos + 1));
- $path = str_replace('\\', '/', $path);
- return $path;
- }
- /**
- * 当数组/对象变量$var存在$key项时,返回存在的对应值或设定值,否则返回$key或不存在的设定值。
- * When the $var has the $key, return it, else result one default value.
- *
- * @param array|object $var
- * @param mixed $valueWhenNone value when the key not exits.
- * @param mixed $valueWhenExists value when the key exits.
- * @access public
- * @return mixed
- */
- function zget($var, $key, $valueWhenNone = false, $valueWhenExists = false)
- {
- if(!is_array($var) and !is_object($var)) return false;
- $type = is_array($var) ? 'array' : 'object';
- $checkExists = $type == 'array' ? isset($var[$key]) : isset($var->$key);
- if($checkExists)
- {
- if($valueWhenExists !== false) return $valueWhenExists;
- return $type == 'array' ? $var[$key] : $var->$key;
- }
- if($valueWhenNone !== false) return $valueWhenNone;
- return $key;
- }
- /**
- * Is https.
- *
- * @access public
- * @return bool
- */
- function isHttps()
- {
- if(!empty($_SERVER['HTTPS']) && strtolower((string) $_SERVER['HTTPS']) !== 'off') return true;
- if(isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https') return true;
- if(!empty($_SERVER['HTTP_FRONT_END_HTTPS']) && strtolower((string) $_SERVER['HTTP_FRONT_END_HTTPS']) !== 'off') return true;
- return false;
- }
- /**
- * Compatibility for htmlspecialchars.
- *
- * @param string $string
- * @param int $flags
- * @param string $encoding
- * @access public
- * @return string
- */
- function htmlSpecialString($string, $flags = '', $encoding = 'UTF-8')
- {
- if(!$flags) $flags = defined('ENT_SUBSTITUTE') ? ENT_QUOTES | ENT_SUBSTITUTE | ENT_HTML401 : ENT_QUOTES;
- return htmlspecialchars((string)$string, $flags, $encoding);
- }
- /**
- * 获取环境变量。
- * Get environment variable.
- *
- * @param string $name
- * @param string $default
- * @param string $format
- * @access public
- * @return mixed
- */
- function getEnvData($name, $default = '', $format = 'string')
- {
- $value = getenv($name);
- if($value === false) $value = $default;
- return helper::convertType($value, $format);
- }
- if(!function_exists('array_column'))
- {
- function array_column($input, $columnKey, $indexKey = null)
- {
- $output = array();
- foreach($input as $row)
- {
- $key = $value = null;
- $keySet = $valueSet = false;
- if(null !== $indexKey && array_key_exists($indexKey, $row))
- {
- $keySet = true;
- $key = (string) $row[$indexKey];
- }
- if(null === $columnKey)
- {
- $valueSet = true;
- $value = $row;
- }
- elseif(\is_array($row) && \array_key_exists($columnKey, $row))
- {
- $valueSet = true;
- $value = $row[$columnKey];
- }
- elseif(\is_object($row) && \property_exists($row, $columnKey))
- {
- $valueSet = true;
- $value = $row->$columnKey;
- }
- if($valueSet)
- {
- if($keySet)
- {
- $output[$key] = $value;
- }
- else
- {
- $output[] = $value;
- }
- }
- }
- return $output;
- }
- }
- if(!function_exists('getallheaders'))
- {
- function getallheaders()
- {
- $headers = array();
- foreach($_SERVER as $name => $value)
- {
- if(strncmp($name, 'HTTP_', strlen('HTTP_')) === 0)
- {
- $headers[str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', substr($name, 5)))))] = $value;
- }
- }
- return $headers;
- }
- }
- /*
- * 兼容json扩展不存在的情况。
- * Initialization without JSON extension.
- */
- if(!interface_exists('JsonSerializable'))
- {
- interface JsonSerializable
- {
- /**
- * @return mixed
- */
- public function jsonSerialize();
- }
- function json_encode($data, $flags = 0, $depth = 512)
- {
- return $data;
- }
- function json_decode($data, $associative = null, $depth = 512, $flags = 0)
- {
- return $data;
- }
- }
- /**
- * 把一个或多个数组附加到第一个数组,用于替换数组 + 运算符。
- * Append one or more arrays to the first array, used to replace the array + operator.
- *
- * reference: https://www.php.net/manual/en/language.operators.array.php.
- *
- * @param array ...$args
- * @return array
- */
- function arrayUnion(...$args)
- {
- $args = array_filter($args, function($arg){return is_array($arg);});
- $count = count($args);
- if($count == 0) return [];
- if($count == 1) return reset($args);
- $result = array_shift($args);
- foreach($args as $arg)
- {
- foreach($arg as $key => $value)
- {
- if(!isset($result[$key])) $result[$key] = $value;
- }
- }
- return $result;
- }
- /**
- * 压缩 ID 列表。
- * Compress ID list.
- *
- * @param string|array $idList
- * @access public
- * @return string
- */
- function compress($idList)
- {
- if(is_string($idList)) $idList = array_filter(explode(',', $idList));
- if(!is_array($idList)) return $idList;
- $firstID = reset($idList);
- if(!is_numeric($firstID) || (float)$firstID != $firstID) return $idList; // If the first ID is not numeric, return the original array.
- $idList = array_values($idList);
- asort($idList);
- $count = count($idList);
- $encoded = [$idList[0]];
- for($i = 1; $i < $count; $i++) $encoded[] = $idList[$i] - $idList[$i-1];
- return gzcompress(implode(',', $encoded));
- }
- /**
- * 解压缩 ID 列表。
- * Uncompress ID list.
- *
- * @param string $encoded
- * @access public
- * @return array
- */
- function uncompress($encoded)
- {
- $decoded = explode(',', gzuncompress($encoded));
- for($i = 1; $i < count($decoded); $i++) $decoded[$i] += $decoded[$i-1];
- return $decoded;
- }
- /**
- * 将字符串及数组转为Int数组
- * Convert string array to int array.
- *
- * @param array|string $strArray
- * @access public
- * @return array
- */
- function toIntArray($strArray)
- {
- if(is_string($strArray)) $strArray = explode(',', $strArray);
- $intArray = [];
- foreach($strArray as $val)
- {
- if($val === '') continue;
- $intArray[] = (int)$val;
- }
- return $intArray;
- }
|