helper.class.php 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447
  1. <?php /**
  2. * ZenTaoAPI的helper类。
  3. * The helper class file of ZenTao API.
  4. *
  5. * The author disclaims copyright to this source code. In place of
  6. * a legal notice, here is a blessing:
  7. *
  8. * May you do good and not evil.
  9. * May you find forgiveness for yourself and forgive others.
  10. * May you share freely, never taking more than you give.
  11. */
  12. include dirname(__FILE__, 2) . '/base/helper.class.php';
  13. class helper extends baseHelper
  14. {
  15. /**
  16. * @param bool $source
  17. */
  18. public static function getViewType($source = false)
  19. {
  20. global $config, $app;
  21. if($config->requestType != 'GET')
  22. {
  23. $pathInfo = $app->getPathInfo();
  24. if(!empty($pathInfo))
  25. {
  26. $dotPos = strrpos((string) $pathInfo, '.');
  27. if($dotPos)
  28. {
  29. $viewType = substr((string) $pathInfo, $dotPos + 1);
  30. }
  31. else
  32. {
  33. $config->default->view = $config->default->view == 'mhtml' ? 'html' : $config->default->view;
  34. }
  35. }
  36. }
  37. elseif($config->requestType == 'GET')
  38. {
  39. if(isset($_GET[$config->viewVar]))
  40. {
  41. $viewType = $_GET[$config->viewVar];
  42. }
  43. else
  44. {
  45. /* Set default view when url has not module name. such as only domain. */
  46. $config->default->view = ($config->default->view == 'mhtml' and isset($_GET[$config->moduleVar])) ? 'html' : $config->default->view;
  47. }
  48. }
  49. if($source and isset($viewType)) return $viewType;
  50. if(isset($viewType) and strpos((string) $config->views, ',' . $viewType . ',') === false) $viewType = $config->default->view;
  51. return $viewType ?? $config->default->view;
  52. }
  53. /**
  54. * Verify that the system has opened on the feature.
  55. *
  56. * @param string $feature scrum_risk | risk | scrum
  57. * @static
  58. * @access public
  59. * @return bool
  60. */
  61. public static function hasFeature($feature)
  62. {
  63. global $config;
  64. if(strpos($feature, '_') !== false)
  65. {
  66. $code = explode('_', $feature);
  67. $code = $code[0] . ucfirst($code[1]);
  68. return strpos(",$config->disabledFeatures,", ",{$code},") === false;
  69. }
  70. else
  71. {
  72. if(in_array($feature, array('scrum', 'waterfall', 'agileplus', 'waterfallplus'))) return strpos(",$config->disabledFeatures,", ",{$feature},") === false;
  73. $hasFeature = false;
  74. $canConfigFeature = false;
  75. foreach($config->featureGroup as $group => $modules)
  76. {
  77. foreach($modules as $module)
  78. {
  79. if($feature == $group or $feature == $module)
  80. {
  81. $canConfigFeature = true;
  82. if(in_array($group, array('scrum', 'waterfall', 'agileplus', 'waterfallplus')))
  83. {
  84. if(helper::hasFeature("{$group}") and helper::hasFeature("{$group}_{$module}")) $hasFeature = true;
  85. }
  86. else
  87. {
  88. if(helper::hasFeature("{$group}_{$module}")) $hasFeature = true;
  89. }
  90. }
  91. }
  92. }
  93. return !$canConfigFeature or ($hasFeature && strpos(",$config->disabledFeatures,", ",{$feature},") === false);
  94. }
  95. }
  96. /**
  97. * Encode json for $.parseJSON
  98. *
  99. * @param array $data
  100. * @param int $options
  101. * @static
  102. * @access public
  103. * @return string
  104. */
  105. public static function jsonEncode4Parse($data, $options = 0)
  106. {
  107. $json = json_encode($data);
  108. if($options) $json = str_replace(array("'", '"'), array('\u0027', '\u0022'), $json);
  109. $escapers = array("\\", "/", "\"", "'", "\n", "\r", "\t", "\x08", "\x0c", "\\\\u");
  110. $replacements = array("\\\\", "\\/", "\\\"", "\'", "\\n", "\\r", "\\t", "\\f", "\\b", "\\u");
  111. return str_replace($escapers, $replacements, $json);
  112. }
  113. /**
  114. * Convert encoding.
  115. *
  116. * @param string $string
  117. * @param string $fromEncoding
  118. * @param string $toEncoding
  119. * @static
  120. * @access public
  121. * @return string
  122. */
  123. public static function convertEncoding($string, $fromEncoding, $toEncoding = 'utf-8')
  124. {
  125. $toEncoding = str_replace('utf8', 'utf-8', $toEncoding);
  126. if(function_exists('mb_convert_encoding'))
  127. {
  128. /* Remove like utf-8//TRANSLIT. */
  129. $position = strpos($toEncoding, '//');
  130. if($position !== false) $toEncoding = substr($toEncoding, 0, $position);
  131. /* Check string encoding. */
  132. $encodings = array_merge(array('GB2312', 'GBK', 'BIG5'), mb_list_encodings());
  133. $encoding = strtolower(mb_detect_encoding($string, $encodings));
  134. if($encoding == $toEncoding) return $string;
  135. return mb_convert_encoding($string, $toEncoding, $encoding);
  136. }
  137. elseif(function_exists('iconv'))
  138. {
  139. if($fromEncoding == $toEncoding) return $string;
  140. $convertString = @iconv($fromEncoding, $toEncoding, $string);
  141. /* iconv error then return original. */
  142. if(!$convertString) return $string;
  143. return $convertString;
  144. }
  145. return $string;
  146. }
  147. /**
  148. * Calculate two working days.
  149. *
  150. * @param string $begin
  151. * @param string $end
  152. * @return bool|float
  153. */
  154. public static function workDays($begin, $end)
  155. {
  156. $begin = strtotime($begin);
  157. $end = strtotime($end);
  158. if($end < $begin) return false;
  159. $double = floor(($end - $begin) / (7 * 24 * 3600));
  160. $begin = date('w', $begin);
  161. $end = date('w', $end);
  162. $end = $begin > $end ? $end + 5 : $end;
  163. return $double * 5 + $end - $begin;
  164. }
  165. /**
  166. * Unify string to standard chars.
  167. *
  168. * @param string $string
  169. * @param string $to
  170. * @static
  171. * @access public
  172. * @return string
  173. */
  174. public static function unify($string, $to = ',')
  175. {
  176. $labels = array('_', '、', ' ', '-', '?', '@', '&', '%', '~', '`', '+', '*', '/', '\\', ',', '。');
  177. $string = str_replace($labels, $to, $string);
  178. return preg_replace("/[{$to}]+/", $to, trim($string, $to));
  179. }
  180. /**
  181. * Create url of issue.
  182. *
  183. * @param string $moduleName
  184. * @param string $methodName
  185. * @param string|array $vars
  186. * @param string $viewType
  187. * @param bool $onlyBody
  188. * @static
  189. * @access public
  190. * @return string
  191. */
  192. public static function createLink($moduleName, $methodName = 'index', $vars = '', $viewType = 'json', $onlyBody = false)
  193. {
  194. global $config;
  195. $link = parent::createLink($moduleName, $methodName, $vars, $viewType);
  196. /* The requestTypes are: GET, PATH_INFO2, PATH_INFO */
  197. if($config->requestType == 'GET')
  198. {
  199. $link = $config->webRoot . (string) substr($link, 1);
  200. }
  201. elseif($config->requestType == 'PATH_INFO2')
  202. {
  203. $link = substr((string) $link, $pos + 4);
  204. }
  205. return $link;
  206. }
  207. /**
  208. * 是否是内网。
  209. * Check is intranet.
  210. *
  211. * @return bool
  212. */
  213. public static function isIntranet()
  214. {
  215. return !defined('USE_INTRANET') ? false : USE_INTRANET;
  216. }
  217. /**
  218. * 转换类型。
  219. * Convert the type.
  220. *
  221. * @param mixed $value
  222. * @param string $type
  223. * @static
  224. * @access public
  225. * @return array|bool|float|int|object|string
  226. */
  227. public static function convertType($value, $type)
  228. {
  229. switch($type)
  230. {
  231. case 'int':
  232. return (int)$value;
  233. case 'float':
  234. return (float)$value;
  235. case 'bool':
  236. return (bool)$value;
  237. case 'array':
  238. return (array)$value;
  239. case 'object':
  240. return (object)$value;
  241. case 'datetime':
  242. case 'date':
  243. return $value ? (string)$value : null;
  244. case 'string':
  245. default:
  246. return (string)$value;
  247. }
  248. }
  249. /**
  250. * 检查是否启用缓存。
  251. * Check is enable cache.
  252. *
  253. * @return bool
  254. */
  255. public static function isCacheEnabled()
  256. {
  257. if(isset($_GET['_nocache']) || isset($_SERVER['HTTP_X_ZT_REFRESH'])) return false;
  258. global $config;
  259. return $config->cache->enable;
  260. }
  261. /**
  262. * 发送请求的响应数据
  263. * Send response data
  264. *
  265. * @param mixed $data
  266. * @param int $code
  267. * @access public
  268. * @return string
  269. */
  270. static public function send($data = '', $code = 200)
  271. {
  272. self::end(self::response($data, $code));
  273. }
  274. /**
  275. * 发送请求的响应数据
  276. * Send response data
  277. *
  278. * @param mixed $data
  279. * @param int $code
  280. * @access public
  281. * @return string
  282. */
  283. static public function response($data = '', $code = 200)
  284. {
  285. $statusCode = array(
  286. 100 => "100 Continue",
  287. 101 => "101 Switching Protocols",
  288. 102 => "102 Processing",
  289. 200 => "200 OK",
  290. 201 => "201 Created",
  291. 202 => "202 Accepted",
  292. 203 => "203 Non-Authoritative Information",
  293. 204 => "204 No Content",
  294. 205 => "205 Reset Content",
  295. 206 => "206 Partial Content",
  296. 207 => "207 Multi-Status",
  297. 300 => "300 Multiple Choices",
  298. 301 => "301 Moved Permanently",
  299. 302 => "302 Found",
  300. 303 => "303 See Other",
  301. 304 => "304 Not Modified",
  302. 305 => "305 Use Proxy",
  303. 307 => "307 Temporary Redirect",
  304. 400 => "400 Bad Request",
  305. 401 => "401 Authorization Required",
  306. 402 => "402 Payment Required",
  307. 403 => "403 Forbidden",
  308. 404 => "404 Not Found",
  309. 405 => "405 Method Not Allowed",
  310. 406 => "406 Not Acceptable",
  311. 407 => "407 Proxy Authentication Required",
  312. 408 => "408 Request Time-out",
  313. 409 => "409 Conflict",
  314. 410 => "410 Gone",
  315. 411 => "411 Length Required",
  316. 412 => "412 Precondition Failed",
  317. 413 => "413 Request Entity Too Large",
  318. 414 => "414 Request-URI Too Large",
  319. 415 => "415 Unsupported Media Type",
  320. 416 => "416 Requested Range Not Satisfiable",
  321. 417 => "417 Expectation Failed",
  322. 422 => "422 Unprocessable Entity",
  323. 423 => "423 Locked",
  324. 424 => "424 Failed Dependency",
  325. 426 => "426 Upgrade Required",
  326. );
  327. header("Access-Control-Allow-Origin: *");
  328. header("Access-Control-Allow-Credentials: true");
  329. header("Access-Control-Allow-Headers: Origin,X-Requested-With,Content-Type,Accept,Authorization,Token,Referer,User-Agent");
  330. header('Access-Control-Allow-Methods: GET,POST,PUT,DELETE,OPTIONS,PATCH');
  331. header("Content-type: application/json");
  332. header("HTTP/1.1 {$statusCode[$code]}");
  333. return !empty($data) ? json_encode($data, JSON_HEX_TAG) : '';
  334. }
  335. }
  336. /**
  337. * 检查是否是onlybody模式。
  338. * Check exist onlybody param.
  339. *
  340. * @access public
  341. * @return bool
  342. */
  343. function isonlybody()
  344. {
  345. return helper::inOnlyBodyMode();
  346. }
  347. /**
  348. * 检查页面是否是弹窗中。
  349. * Check page is modal.
  350. *
  351. * @access public
  352. * @return bool
  353. */
  354. function isInModal()
  355. {
  356. return helper::isAjaxRequest('modal');
  357. }
  358. /**
  359. * Format time.
  360. *
  361. * @param string|null $time
  362. * @param string $format
  363. * @access public
  364. * @return string
  365. */
  366. function formatTime($time, $format = '')
  367. {
  368. if($time === null) return '';
  369. $time = str_replace('0000-00-00', '', $time);
  370. $time = str_replace('00:00:00', '', $time);
  371. if(trim($time) == '') return '';
  372. if($format) return date($format, strtotime($time));
  373. return trim($time);
  374. }
  375. /**
  376. * 生成随机数。
  377. * Generate random number.
  378. *
  379. * @access public
  380. * @return int
  381. */
  382. function updateSessionRandom()
  383. {
  384. $random = mt_rand();
  385. $_SESSION['rand'] = $random;
  386. return $random;
  387. }
  388. /**
  389. * 获取可用的界面列表。
  390. * Get available vision list.
  391. *
  392. * @access public
  393. * @return array
  394. */
  395. function getVisions()
  396. {
  397. global $config, $lang;
  398. $visions = array_flip(array_unique(array_filter(explode(',', trim($config->visions, ',')))));
  399. $visionList = $lang->visionList;
  400. return array_intersect_key($visionList, $visions);
  401. }
  402. /**
  403. * Fix for session error.
  404. *
  405. * @param string $class
  406. * @access protected
  407. * @return void
  408. */
  409. function autoloader($class)
  410. {
  411. if(!class_exists($class))
  412. {
  413. if($class == 'post_max_size' or $class == 'max_input_vars') eval('class ' . $class . ' {};');
  414. }
  415. }
  416. spl_autoload_register('autoloader');