国内流行的内容管理系统(CMS)多端全媒体解决方案 https://www.dedebiz.com
Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

395 linhas
11KB

  1. <?php
  2. if (!defined('DEDEINC')) exit('dedebiz');
  3. //Copyright 2020 The DedeBiz Authors. All rights reserved.
  4. //license that can be found in the LICENSE file.
  5. //@copyright Copyright (c) 2022, DedeBIZ.COM
  6. //@license https://www.dedebiz.com/license
  7. //@link https://www.dedebiz.com
  8. /*
  9. The MIT License (MIT)
  10. Copyright (c) 2014-2019 British Columbia Institute of Technology
  11. Copyright (c) 2019-2020 CodeIgniter Foundation
  12. */
  13. function is_cli()
  14. {
  15. return (PHP_SAPI === 'cli' || defined('STDIN'));
  16. }
  17. class DedeCli
  18. {
  19. public static $readline_support = false;
  20. protected static $initialized = false;
  21. protected static $wait_msg = "Press any key to continue";
  22. protected static $segments = [];
  23. protected static $options = [];
  24. protected static $foreground_colors = [
  25. 'black' => '0;30',
  26. 'dark_gray' => '1;30',
  27. 'blue' => '0;34',
  28. 'dark_blue' => '1;34',
  29. 'light_blue' => '1;34',
  30. 'green' => '0;32',
  31. 'light_green' => '1;32',
  32. 'cyan' => '0;36',
  33. 'light_cyan' => '1;36',
  34. 'red' => '0;31',
  35. 'light_red' => '1;31',
  36. 'purple' => '0;35',
  37. 'light_purple' => '1;35',
  38. 'light_yellow' => '0;33',
  39. 'yellow' => '1;33',
  40. 'light_gray' => '0;37',
  41. 'white' => '1;37',
  42. ];
  43. protected static $background_colors = [
  44. 'black' => '40',
  45. 'red' => '41',
  46. 'green' => '42',
  47. 'yellow' => '43',
  48. 'blue' => '44',
  49. 'magenta' => '45',
  50. 'cyan' => '46',
  51. 'light_gray' => '47',
  52. ];
  53. public static function init()
  54. {
  55. if (is_cli())
  56. {
  57. static::$readline_support = extension_loaded('readline');
  58. static::parseCommandLine();
  59. static::$initialized = true;
  60. } else
  61. {
  62. define('STDOUT', 'php://output');
  63. }
  64. }
  65. private static function parseCommandLine()
  66. {
  67. $optionsFound = false;
  68. for ($i=1; $i < $_SERVER['argc']; $i++)
  69. {
  70. if (! $optionsFound && strpos($_SERVER['argv'][$i], '-') === false)
  71. {
  72. static::$segments[] = $_SERVER['argv'][$i];
  73. continue;
  74. }
  75. $optionsFound = true;
  76. if (substr($_SERVER['argv'][$i], 0, 1) != '-')
  77. {
  78. continue;
  79. }
  80. $arg = str_replace('-', '', $_SERVER['argv'][$i]);
  81. $value = null;
  82. if (isset($_SERVER['argv'][$i+1]) && substr($_SERVER['argv'][$i+1], 0, 1) != '-')
  83. {
  84. $value = $_SERVER['argv'][$i+1];
  85. $i++;
  86. }
  87. static::$options[$arg] = $value;
  88. $optionsFound = false;
  89. }
  90. }
  91. public static function getOption(string $name)
  92. {
  93. if (! array_key_exists($name, static::$options))
  94. {
  95. return null;
  96. }
  97. $val = static::$options[$name] === null
  98. ? true
  99. : static::$options[$name];
  100. return $val;
  101. }
  102. public static function getOptions()
  103. {
  104. return static::$options;
  105. }
  106. public static function getOptionString(): string
  107. {
  108. if (! count(static::$options))
  109. {
  110. return '';
  111. }
  112. $out = '';
  113. foreach (static::$options as $name => $value)
  114. {
  115. if (mb_strpos($value, ' ') !== false)
  116. {
  117. $value = '"'.$value.'"';
  118. }
  119. $out .= "-{$name} $value ";
  120. }
  121. return $out;
  122. }
  123. public static function newLine(int $num = 1)
  124. {
  125. for ($i = 0; $i < $num; $i++)
  126. {
  127. static::write('');
  128. }
  129. }
  130. public static function isWindows()
  131. {
  132. return 'win' === strtolower(substr(php_uname("s"), 0, 3));
  133. }
  134. public static function color(string $text, string $foreground, string $background = null, string $format = null)
  135. {
  136. if (static::isWindows() && ! isset($_SERVER['ANSICON']))
  137. {
  138. return $text;
  139. }
  140. if ( ! array_key_exists($foreground, static::$foreground_colors))
  141. {
  142. throw new \RuntimeException('Invalid CLI foreground color: '.$foreground);
  143. }
  144. if ($background !== null && ! array_key_exists($background, static::$background_colors))
  145. {
  146. throw new \RuntimeException('Invalid CLI background color: '.$background);
  147. }
  148. $string = "\033[".static::$foreground_colors[$foreground]."m";
  149. if ($background !== null)
  150. {
  151. $string .= "\033[".static::$background_colors[$background]."m";
  152. }
  153. if ($format === 'underline')
  154. {
  155. $string .= "\033[4m";
  156. }
  157. $string .= $text."\033[0m";
  158. return $string;
  159. }
  160. public static function getWidth(int $default = 80): int
  161. {
  162. if (static::isWindows())
  163. {
  164. return $default;
  165. }
  166. return (int)shell_exec('tput cols');
  167. }
  168. public static function getHeight(int $default = 32): int
  169. {
  170. if (static::isWindows())
  171. {
  172. return $default;
  173. }
  174. return (int)shell_exec('tput lines');
  175. }
  176. public static function showProgress($thisStep = 1, int $totalSteps = 10)
  177. {
  178. static $inProgress = false;
  179. if ($inProgress !== false && $inProgress <= $thisStep)
  180. {
  181. fwrite(STDOUT, "\033[1A");
  182. }
  183. $inProgress = $thisStep;
  184. if ($thisStep !== false)
  185. {
  186. $thisStep = abs($thisStep);
  187. $totalSteps = $totalSteps < 1 ? 1 : $totalSteps;
  188. $percent = intval(($thisStep / $totalSteps) * 100);
  189. $step = (int)round($percent / 10);
  190. fwrite(STDOUT, "[\033[32m".str_repeat('#', $step).str_repeat('.', 10 - $step)."\033[0m]");
  191. fwrite(STDOUT, sprintf(" %3d%% Complete", $percent).PHP_EOL);
  192. } else {
  193. fwrite(STDOUT, "\007");
  194. }
  195. }
  196. public static function wrap(string $string = null, int $max = 0, int $pad_left = 0): string
  197. {
  198. if (empty($string))
  199. {
  200. return '';
  201. }
  202. if ($max == 0)
  203. {
  204. $max = DedeCli::getWidth();
  205. }
  206. if (DedeCli::getWidth() < $max)
  207. {
  208. $max = DedeCli::getWidth();
  209. }
  210. $max = $max - $pad_left;
  211. $lines = wordwrap($string, $max);
  212. if ($pad_left > 0)
  213. {
  214. $lines = explode(PHP_EOL, $lines);
  215. $first = true;
  216. array_walk($lines, function (&$line, $index) use ($max, $pad_left, &$first)
  217. {
  218. if ( ! $first)
  219. {
  220. $line = str_repeat(" ", $pad_left).$line;
  221. }
  222. else
  223. {
  224. $first = false;
  225. }
  226. });
  227. $lines = implode(PHP_EOL, $lines);
  228. }
  229. return $lines;
  230. }
  231. public static function clearScreen()
  232. {
  233. static::isWindows()
  234. ? static::newLine(40)
  235. : fwrite(STDOUT, chr(27)."[H".chr(27)."[2J");
  236. }
  237. public static function input(string $prefix = null): string
  238. {
  239. if (static::$readline_support)
  240. {
  241. return readline($prefix);
  242. }
  243. echo $prefix;
  244. return fgets(STDIN);
  245. }
  246. /**
  247. * 询问用户输入.这个可以1个或2个参数.
  248. *
  249. * 使用:
  250. *
  251. * //等待任何输入
  252. * DedeCli::prompt();
  253. *
  254. * $color = DedeCli::prompt('What is your favorite color?');
  255. *
  256. * $color = DedeCli::prompt('What is your favourite color?', 'white');
  257. *
  258. * $ready = DedeCli::prompt('Are you ready?', array('y','n'));
  259. *
  260. * @return string the user input
  261. */
  262. public static function prompt(): string
  263. {
  264. $args = func_get_args();
  265. $options = [];
  266. $output = '';
  267. $default = null;
  268. $arg_count = count($args);
  269. $required = end($args) === true;
  270. $required === true && --$arg_count;
  271. switch ($arg_count)
  272. {
  273. case 2:
  274. //E.g: $ready = DedeCli::prompt('Are you ready?', array('y','n'));
  275. if (is_array($args[1]))
  276. {
  277. list($output, $options) = $args;
  278. }
  279. //E.g: $color = DedeCli::prompt('What is your favourite color?', 'white');
  280. elseif (is_string($args[1]))
  281. {
  282. list($output, $default) = $args;
  283. }
  284. break;
  285. case 1:
  286. //E.g: $ready = DedeCli::prompt(array('y','n'));
  287. if (is_array($args[0]))
  288. {
  289. $options = $args[0];
  290. }
  291. //E.g: $ready = DedeCli::prompt('What did you do today?');
  292. elseif (is_string($args[0]))
  293. {
  294. $output = $args[0];
  295. }
  296. break;
  297. }
  298. if ($output !== '')
  299. {
  300. $extra_output = '';
  301. if ($default !== null)
  302. {
  303. $extra_output = ' [ Default: "'.$default.'" ]';
  304. }
  305. elseif ($options !== [])
  306. {
  307. $extra_output = ' [ '.implode(', ', $options).' ]';
  308. }
  309. fwrite(STDOUT, $output.$extra_output.': ');
  310. }
  311. $input = trim(static::input()) ? : $default;
  312. if (empty($input) && $required === true)
  313. {
  314. static::write('This is required.');
  315. static::newLine();
  316. $input = forward_static_call_array([__CLASS__, 'prompt'], $args);
  317. }
  318. if ( ! empty($options) && ! in_array($input, $options))
  319. {
  320. static::write('This is not a valid option. Please try again.');
  321. static::newLine();
  322. $input = forward_static_call_array([__CLASS__, 'prompt'], $args);
  323. }
  324. return empty($input) ? '' : $input;
  325. }
  326. public static function wait(int $seconds, bool $countdown = false)
  327. {
  328. if ($countdown === true)
  329. {
  330. $time = $seconds;
  331. while ($time > 0)
  332. {
  333. fwrite(STDOUT, $time.' ');
  334. sleep(1);
  335. $time--;
  336. }
  337. static::write();
  338. } else {
  339. if ($seconds > 0)
  340. {
  341. sleep($seconds);
  342. }
  343. else
  344. {
  345. static::write(static::$wait_msg);
  346. static::input();
  347. }
  348. }
  349. }
  350. public static function error(string $text, string $foreground = 'light_red', string $background = null)
  351. {
  352. if ($foreground || $background)
  353. {
  354. $text = static::color($text, $foreground, $background);
  355. }
  356. fwrite(STDERR, $text.PHP_EOL);
  357. }
  358. public static function write(string $text = '', string $foreground = null, string $background = null)
  359. {
  360. if ($foreground || $background)
  361. {
  362. $text = static::color($text, $foreground, $background);
  363. }
  364. fwrite(STDOUT, $text.PHP_EOL);
  365. }
  366. }
  367. DedeCli::init();