CLI.php 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315
  1. <?php
  2. /**
  3. * @package Kohana/Minion
  4. * @author Kohana Team
  5. * @copyright (c) 2015 Kohana Team
  6. * @copyright (c) 2016-2018 Koseven Team
  7. * @license https://koseven.ga/LICENSE.md
  8. */
  9. class Kohana_Minion_CLI {
  10. public static $wait_msg = 'Press any key to continue...';
  11. protected static $foreground_colors = [
  12. 'black' => '0;30',
  13. 'dark_gray' => '1;30',
  14. 'blue' => '0;34',
  15. 'light_blue' => '1;34',
  16. 'green' => '0;32',
  17. 'light_green' => '1;32',
  18. 'cyan' => '0;36',
  19. 'light_cyan' => '1;36',
  20. 'red' => '0;31',
  21. 'light_red' => '1;31',
  22. 'purple' => '0;35',
  23. 'light_purple' => '1;35',
  24. 'brown' => '0;33',
  25. 'yellow' => '1;33',
  26. 'light_gray' => '0;37',
  27. 'white' => '1;37',
  28. ];
  29. protected static $background_colors = [
  30. 'black' => '40',
  31. 'red' => '41',
  32. 'green' => '42',
  33. 'yellow' => '43',
  34. 'blue' => '44',
  35. 'magenta' => '45',
  36. 'cyan' => '46',
  37. 'light_gray' => '47',
  38. ];
  39. /**
  40. * Returns one or more command-line options. Options are specified using
  41. * standard CLI syntax:
  42. *
  43. * php index.php --username=john.smith --password=secret --var="some value with spaces"
  44. *
  45. * // Get the values of "username" and "password"
  46. * $auth = Minion_CLI::options('username', 'password');
  47. *
  48. * @param string $options,... option name
  49. * @return array
  50. */
  51. public static function options($options = NULL)
  52. {
  53. // Get all of the requested options
  54. $options = func_get_args();
  55. // Found option values
  56. $values = [];
  57. // Skip the first option, it is always the file executed
  58. for ($i = 1; $i < $_SERVER['argc']; ++$i)
  59. {
  60. if ( ! isset($_SERVER['argv'][$i]))
  61. {
  62. // No more args left
  63. break;
  64. }
  65. // Get the option
  66. $opt = $_SERVER['argv'][$i];
  67. if (substr($opt, 0, 2) !== '--')
  68. {
  69. // This is a positional argument
  70. $values[] = $opt;
  71. continue;
  72. }
  73. // Remove the "--" prefix
  74. $opt = substr($opt, 2);
  75. if (strpos($opt, '='))
  76. {
  77. // Separate the name and value
  78. list ($opt, $value) = explode('=', $opt, 2);
  79. }
  80. else
  81. {
  82. $value = NULL;
  83. }
  84. $values[$opt] = $value;
  85. }
  86. if ($options)
  87. {
  88. foreach ($values as $opt => $value)
  89. {
  90. if ( ! in_array($opt, $options))
  91. {
  92. // Set the given value
  93. unset($values[$opt]);
  94. }
  95. }
  96. }
  97. return count($options) == 1 ? array_pop($values) : $values;
  98. }
  99. /**
  100. * Reads input from the user. This can have either 1 or 2 arguments.
  101. *
  102. * Usage:
  103. *
  104. * // Waits for any key press
  105. * Minion_CLI::read();
  106. *
  107. * // Takes any input
  108. * $color = Minion_CLI::read('What is your favorite color?');
  109. *
  110. * // Will only accept the options in the array
  111. * $ready = Minion_CLI::read('Are you ready?', array('y','n'));
  112. *
  113. * @param string $text text to show user before waiting for input
  114. * @param array $options array of options the user is shown
  115. * @return string the user input
  116. */
  117. public static function read($text = '', array $options = NULL)
  118. {
  119. // If a question has been asked with the read
  120. $options_output = '';
  121. if ( ! empty($options))
  122. {
  123. $options_output = ' [ '.implode(', ', $options).' ]';
  124. }
  125. fwrite(STDOUT, $text.$options_output.': ');
  126. // Read the input from keyboard.
  127. $input = trim(fgets(STDIN));
  128. // If options are provided and the choice is not in the array, tell them to try again
  129. if ( ! empty($options) && ! in_array($input, $options))
  130. {
  131. Minion_CLI::write('This is not a valid option. Please try again.');
  132. $input = Minion_CLI::read($text, $options);
  133. }
  134. // Read the input
  135. return $input;
  136. }
  137. /**
  138. * Experimental feature.
  139. *
  140. * Reads hidden input from the user
  141. *
  142. * Usage:
  143. *
  144. * $password = Minion_CLI::password('Enter your password');
  145. *
  146. * @author Mathew Davies.
  147. * @return string
  148. */
  149. public static function password($text = '')
  150. {
  151. $text .= ': ';
  152. if (Kohana::$is_windows)
  153. {
  154. $vbscript = sys_get_temp_dir().'Minion_CLI_Password.vbs';
  155. // Create temporary file
  156. file_put_contents($vbscript, 'wscript.echo(InputBox("'.addslashes($text).'"))');
  157. $password = shell_exec('cscript //nologo '.escapeshellarg($vbscript));
  158. // Remove temporary file.
  159. unlink($vbscript);
  160. }
  161. else
  162. {
  163. $password = shell_exec('/usr/bin/env bash -c \'read -s -p "'.escapeshellcmd($text).'" var && echo $var\'');
  164. }
  165. Minion_CLI::write();
  166. return trim($password);
  167. }
  168. /**
  169. * Outputs a string to the cli. If you send an array it will implode them
  170. * with a line break.
  171. *
  172. * @param string|array $text the text to output, or array of lines
  173. */
  174. public static function write($text = '')
  175. {
  176. if (is_array($text))
  177. {
  178. foreach ($text as $line)
  179. {
  180. Minion_CLI::write($line);
  181. }
  182. }
  183. else
  184. {
  185. fwrite(STDOUT, $text.PHP_EOL);
  186. }
  187. }
  188. /**
  189. * Outputs a replacable line to the cli. You can continue replacing the
  190. * line until `TRUE` is passed as the second parameter in order to indicate
  191. * you are done modifying the line.
  192. *
  193. * // Sample progress indicator
  194. * Minion_CLI::write_replace('0%');
  195. * Minion_CLI::write_replace('25%');
  196. * Minion_CLI::write_replace('50%');
  197. * Minion_CLI::write_replace('75%');
  198. * // Done writing this line
  199. * Minion_CLI::write_replace('100%', TRUE);
  200. *
  201. * @param string $text the text to output
  202. * @param boolean $end_line whether the line is done being replaced
  203. */
  204. public static function write_replace($text = '', $end_line = FALSE)
  205. {
  206. // Append a newline if $end_line is TRUE
  207. $text = $end_line ? $text.PHP_EOL : $text;
  208. fwrite(STDOUT, "\r\033[K".$text);
  209. }
  210. /**
  211. * Waits a certain number of seconds, optionally showing a wait message and
  212. * waiting for a key press.
  213. *
  214. * @author Fuel Development Team
  215. * @license MIT License
  216. * @copyright 2010 - 2011 Fuel Development Team
  217. * @link http://fuelphp.com
  218. * @param int $seconds number of seconds
  219. * @param bool $countdown show a countdown or not
  220. */
  221. public static function wait($seconds = 0, $countdown = false)
  222. {
  223. if ($countdown === TRUE)
  224. {
  225. $time = $seconds;
  226. while ($time > 0)
  227. {
  228. fwrite(STDOUT, $time.'... ');
  229. sleep(1);
  230. --$time;
  231. }
  232. Minion_CLI::write();
  233. }
  234. else
  235. {
  236. if ($seconds > 0)
  237. {
  238. sleep($seconds);
  239. }
  240. else
  241. {
  242. Minion_CLI::write(Minion_CLI::$wait_msg);
  243. Minion_CLI::read();
  244. }
  245. }
  246. }
  247. /**
  248. * Returns the given text with the correct color codes for a foreground and
  249. * optionally a background color.
  250. *
  251. * @author Fuel Development Team
  252. * @license MIT License
  253. * @copyright 2010 - 2011 Fuel Development Team
  254. * @link http://fuelphp.com
  255. * @param string $text the text to color
  256. * @param string $foreground the foreground color
  257. * @param string $background the background color
  258. * @return string the color coded string
  259. */
  260. public static function color($text, $foreground, $background = null)
  261. {
  262. if (Kohana::$is_windows)
  263. return $text;
  264. if ( ! array_key_exists($foreground, Minion_CLI::$foreground_colors))
  265. throw new Kohana_Exception('Invalid CLI foreground color: '.$foreground);
  266. if ($background !== NULL AND ! array_key_exists($background, Minion_CLI::$background_colors))
  267. throw new Kohana_Exception('Invalid CLI background color: '.$background);
  268. $string = "\033[".Minion_CLI::$foreground_colors[$foreground]."m";
  269. if ($background !== NULL)
  270. {
  271. $string .= "\033[".Minion_CLI::$background_colors[$background]."m";
  272. }
  273. $string .= $text."\033[0m";
  274. return $string;
  275. }
  276. }