helpers.php.bak 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528
  1. <?php
  2. /**
  3. * This file is part of webman.
  4. *
  5. * Licensed under The MIT License
  6. * For full copyright and license information, please see the MIT-LICENSE.txt
  7. * Redistributions of files must retain the above copyright notice.
  8. *
  9. * @author walkor<walkor@workerman.net>
  10. * @copyright walkor<walkor@workerman.net>
  11. * @link http://www.workerman.net/
  12. * @license http://www.opensource.org/licenses/mit-license.php MIT License
  13. */
  14. use support\Container;
  15. use support\Request;
  16. use support\Response;
  17. use support\Translation;
  18. use support\view\Blade;
  19. use support\view\Raw;
  20. use support\view\ThinkPHP;
  21. use support\view\Twig;
  22. use Twig\Error\LoaderError;
  23. use Twig\Error\RuntimeError;
  24. use Twig\Error\SyntaxError;
  25. use Webman\App;
  26. use Webman\Config;
  27. use Webman\Route;
  28. use Workerman\Protocols\Http\Session;
  29. use Workerman\Worker;
  30. // Project base path
  31. define('BASE_PATH', dirname(__DIR__));
  32. /**
  33. * return the program execute directory
  34. * @param string $path
  35. * @return string
  36. */
  37. function run_path(string $path = ''): string
  38. {
  39. static $runPath = '';
  40. if (!$runPath) {
  41. $runPath = is_phar() ? dirname(Phar::running(false)) : BASE_PATH;
  42. }
  43. return path_combine($runPath, $path);
  44. }
  45. /**
  46. * if the param $path equal false,will return this program current execute directory
  47. * @param string|false $path
  48. * @return string
  49. */
  50. function base_path($path = ''): string
  51. {
  52. if (false === $path) {
  53. return run_path();
  54. }
  55. return path_combine(BASE_PATH, $path);
  56. }
  57. /**
  58. * App path
  59. * @param string $path
  60. * @return string
  61. */
  62. function app_path(string $path = ''): string
  63. {
  64. return path_combine(BASE_PATH . DIRECTORY_SEPARATOR . 'app', $path);
  65. }
  66. /**
  67. * Public path
  68. * @param string $path
  69. * @return string
  70. */
  71. function public_path(string $path = ''): string
  72. {
  73. static $publicPath = '';
  74. if (!$publicPath) {
  75. $publicPath = \config('app.public_path') ?: run_path('public');
  76. }
  77. return path_combine($publicPath, $path);
  78. }
  79. /**
  80. * Config path
  81. * @param string $path
  82. * @return string
  83. */
  84. function config_path(string $path = ''): string
  85. {
  86. return path_combine(BASE_PATH . DIRECTORY_SEPARATOR . 'config', $path);
  87. }
  88. /**
  89. * Runtime path
  90. * @param string $path
  91. * @return string
  92. */
  93. function runtime_path(string $path = ''): string
  94. {
  95. static $runtimePath = '';
  96. if (!$runtimePath) {
  97. $runtimePath = \config('app.runtime_path') ?: run_path('runtime');
  98. }
  99. return path_combine($runtimePath, $path);
  100. }
  101. /**
  102. * Generate paths based on given information
  103. * @param string $front
  104. * @param string $back
  105. * @return string
  106. */
  107. function path_combine(string $front, string $back): string
  108. {
  109. return $front . ($back ? (DIRECTORY_SEPARATOR . ltrim($back, DIRECTORY_SEPARATOR)) : $back);
  110. }
  111. /**
  112. * Response
  113. * @param int $status
  114. * @param array $headers
  115. * @param string $body
  116. * @return Response
  117. */
  118. function response(string $body = '', int $status = 200, array $headers = []): Response
  119. {
  120. return new Response($status, $headers, $body);
  121. }
  122. /**
  123. * Json response
  124. * @param $data
  125. * @param int $options
  126. * @return Response
  127. */
  128. function json($data, int $options = JSON_UNESCAPED_UNICODE): Response
  129. {
  130. return new Response(200, ['Content-Type' => 'application/json'], json_encode($data, $options));
  131. }
  132. /**
  133. * Xml response
  134. * @param $xml
  135. * @return Response
  136. */
  137. function xml($xml): Response
  138. {
  139. if ($xml instanceof SimpleXMLElement) {
  140. $xml = $xml->asXML();
  141. }
  142. return new Response(200, ['Content-Type' => 'text/xml'], $xml);
  143. }
  144. /**
  145. * Jsonp response
  146. * @param $data
  147. * @param string $callbackName
  148. * @return Response
  149. */
  150. function jsonp($data, string $callbackName = 'callback'): Response
  151. {
  152. if (!is_scalar($data) && null !== $data) {
  153. $data = json_encode($data);
  154. }
  155. return new Response(200, [], "$callbackName($data)");
  156. }
  157. /**
  158. * Redirect response
  159. * @param string $location
  160. * @param int $status
  161. * @param array $headers
  162. * @return Response
  163. */
  164. function redirect(string $location, int $status = 302, array $headers = []): Response
  165. {
  166. $response = new Response($status, ['Location' => $location]);
  167. if (!empty($headers)) {
  168. $response->withHeaders($headers);
  169. }
  170. return $response;
  171. }
  172. /**
  173. * View response
  174. * @param string $template
  175. * @param array $vars
  176. * @param string|null $app
  177. * @param string|null $plugin
  178. * @return Response
  179. */
  180. function view(string $template, array $vars = [], string $app = null, string $plugin = null): Response
  181. {
  182. $request = \request();
  183. $plugin = $plugin === null ? ($request->plugin ?? '') : $plugin;
  184. $handler = \config($plugin ? "plugin.$plugin.view.handler" : 'view.handler');
  185. return new Response(200, [], $handler::render($template, $vars, $app, $plugin));
  186. }
  187. /**
  188. * Raw view response
  189. * @param string $template
  190. * @param array $vars
  191. * @param string|null $app
  192. * @return Response
  193. * @throws Throwable
  194. */
  195. function raw_view(string $template, array $vars = [], string $app = null): Response
  196. {
  197. return new Response(200, [], Raw::render($template, $vars, $app));
  198. }
  199. /**
  200. * Blade view response
  201. * @param string $template
  202. * @param array $vars
  203. * @param string|null $app
  204. * @return Response
  205. */
  206. function blade_view(string $template, array $vars = [], string $app = null): Response
  207. {
  208. return new Response(200, [], Blade::render($template, $vars, $app));
  209. }
  210. /**
  211. * Think view response
  212. * @param string $template
  213. * @param array $vars
  214. * @param string|null $app
  215. * @return Response
  216. */
  217. function think_view(string $template, array $vars = [], string $app = null): Response
  218. {
  219. return new Response(200, [], ThinkPHP::render($template, $vars, $app));
  220. }
  221. /**
  222. * Twig view response
  223. * @param string $template
  224. * @param array $vars
  225. * @param string|null $app
  226. * @return Response
  227. * @throws LoaderError
  228. * @throws RuntimeError
  229. * @throws SyntaxError
  230. */
  231. function twig_view(string $template, array $vars = [], string $app = null): Response
  232. {
  233. return new Response(200, [], Twig::render($template, $vars, $app));
  234. }
  235. /**
  236. * Get request
  237. * @return \Webman\Http\Request|Request|null
  238. */
  239. function request()
  240. {
  241. return App::request();
  242. }
  243. /**
  244. * Get config
  245. * @param string|null $key
  246. * @param $default
  247. * @return array|mixed|null
  248. */
  249. function config(string $key = null, $default = null)
  250. {
  251. return Config::get($key, $default);
  252. }
  253. /**
  254. * Create url
  255. * @param string $name
  256. * @param ...$parameters
  257. * @return string
  258. */
  259. function route(string $name, ...$parameters): string
  260. {
  261. $route = Route::getByName($name);
  262. if (!$route) {
  263. return '';
  264. }
  265. if (!$parameters) {
  266. return $route->url();
  267. }
  268. if (is_array(current($parameters))) {
  269. $parameters = current($parameters);
  270. }
  271. return $route->url($parameters);
  272. }
  273. /**
  274. * Session
  275. * @param mixed $key
  276. * @param mixed $default
  277. * @return mixed|bool|Session
  278. */
  279. function session($key = null, $default = null)
  280. {
  281. $session = \request()->session();
  282. if (null === $key) {
  283. return $session;
  284. }
  285. if (is_array($key)) {
  286. $session->put($key);
  287. return null;
  288. }
  289. if (strpos($key, '.')) {
  290. $keyArray = explode('.', $key);
  291. $value = $session->all();
  292. foreach ($keyArray as $index) {
  293. if (!isset($value[$index])) {
  294. return $default;
  295. }
  296. $value = $value[$index];
  297. }
  298. return $value;
  299. }
  300. return $session->get($key, $default);
  301. }
  302. /**
  303. * Translation
  304. * @param string $id
  305. * @param array $parameters
  306. * @param string|null $domain
  307. * @param string|null $locale
  308. * @return string
  309. */
  310. function trans(string $id, array $parameters = [], string $domain = null, string $locale = null): string
  311. {
  312. $res = Translation::trans($id, $parameters, $domain, $locale);
  313. return $res === '' ? $id : $res;
  314. }
  315. /**
  316. * Locale
  317. * @param string|null $locale
  318. * @return string
  319. */
  320. function locale(string $locale = null): string
  321. {
  322. if (!$locale) {
  323. return Translation::getLocale();
  324. }
  325. Translation::setLocale($locale);
  326. return $locale;
  327. }
  328. /**
  329. * 404 not found
  330. * @return Response
  331. */
  332. function not_found(): Response
  333. {
  334. return new Response(404, [], file_get_contents(public_path() . '/404.html'));
  335. }
  336. /**
  337. * Copy dir
  338. * @param string $source
  339. * @param string $dest
  340. * @param bool $overwrite
  341. * @return void
  342. */
  343. function copy_dir(string $source, string $dest, bool $overwrite = false)
  344. {
  345. if (is_dir($source)) {
  346. if (!is_dir($dest)) {
  347. mkdir($dest);
  348. }
  349. $files = scandir($source);
  350. foreach ($files as $file) {
  351. if ($file !== "." && $file !== "..") {
  352. copy_dir("$source/$file", "$dest/$file", $overwrite);
  353. }
  354. }
  355. } else if (file_exists($source) && ($overwrite || !file_exists($dest))) {
  356. copy($source, $dest);
  357. }
  358. }
  359. /**
  360. * Remove dir
  361. * @param string $dir
  362. * @return bool
  363. */
  364. function remove_dir(string $dir): bool
  365. {
  366. if (is_link($dir) || is_file($dir)) {
  367. return unlink($dir);
  368. }
  369. $files = array_diff(scandir($dir), array('.', '..'));
  370. foreach ($files as $file) {
  371. (is_dir("$dir/$file") && !is_link($dir)) ? remove_dir("$dir/$file") : unlink("$dir/$file");
  372. }
  373. return rmdir($dir);
  374. }
  375. /**
  376. * Bind worker
  377. * @param $worker
  378. * @param $class
  379. */
  380. function worker_bind($worker, $class)
  381. {
  382. $callbackMap = [
  383. 'onConnect',
  384. 'onMessage',
  385. 'onClose',
  386. 'onError',
  387. 'onBufferFull',
  388. 'onBufferDrain',
  389. 'onWorkerStop',
  390. 'onWebSocketConnect',
  391. 'onWorkerReload'
  392. ];
  393. foreach ($callbackMap as $name) {
  394. if (method_exists($class, $name)) {
  395. $worker->$name = [$class, $name];
  396. }
  397. }
  398. if (method_exists($class, 'onWorkerStart')) {
  399. call_user_func([$class, 'onWorkerStart'], $worker);
  400. }
  401. }
  402. /**
  403. * Start worker
  404. * @param $processName
  405. * @param $config
  406. * @return void
  407. */
  408. function worker_start($processName, $config)
  409. {
  410. $worker = new Worker($config['listen'] ?? null, $config['context'] ?? []);
  411. $propertyMap = [
  412. 'count',
  413. 'user',
  414. 'group',
  415. 'reloadable',
  416. 'reusePort',
  417. 'transport',
  418. 'protocol',
  419. ];
  420. $worker->name = $processName;
  421. foreach ($propertyMap as $property) {
  422. if (isset($config[$property])) {
  423. $worker->$property = $config[$property];
  424. }
  425. }
  426. $worker->onWorkerStart = function ($worker) use ($config) {
  427. require_once base_path('/support/bootstrap.php');
  428. if (isset($config['handler'])) {
  429. if (!class_exists($config['handler'])) {
  430. echo "process error: class {$config['handler']} not exists\r\n";
  431. return;
  432. }
  433. $instance = Container::make($config['handler'], $config['constructor'] ?? []);
  434. worker_bind($worker, $instance);
  435. }
  436. };
  437. }
  438. /**
  439. * Get realpath
  440. * @param string $filePath
  441. * @return string
  442. */
  443. function get_realpath(string $filePath): string
  444. {
  445. if (strpos($filePath, 'phar://') === 0) {
  446. return $filePath;
  447. } else {
  448. return realpath($filePath);
  449. }
  450. }
  451. /**
  452. * Is phar
  453. * @return bool
  454. */
  455. function is_phar(): bool
  456. {
  457. return class_exists(Phar::class, false) && Phar::running();
  458. }
  459. /**
  460. * Get cpu count
  461. * @return int
  462. */
  463. function cpu_count(): int
  464. {
  465. // Windows does not support the number of processes setting.
  466. if (DIRECTORY_SEPARATOR === '\\') {
  467. return 1;
  468. }
  469. $count = 4;
  470. if (is_callable('shell_exec')) {
  471. if (strtolower(PHP_OS) === 'darwin') {
  472. $count = (int)shell_exec('sysctl -n machdep.cpu.core_count');
  473. } else {
  474. $count = (int)shell_exec('nproc');
  475. }
  476. }
  477. return $count > 0 ? $count : 4;
  478. }
  479. /**
  480. * Get request parameters, if no parameter name is passed, an array of all values is returned, default values is supported
  481. * @param string|null $param param's name
  482. * @param mixed|null $default default value
  483. * @return mixed|null
  484. */
  485. function input(string $param = null, $default = null)
  486. {
  487. return is_null($param) ? request()->all() : request()->input($param, $default);
  488. }