PageRenderTime 45ms CodeModel.GetById 15ms RepoModel.GetById 1ms app.codeStats 0ms

/yiiapp/mercadobtx/vendor/clio/src/Clio/Console.php

https://gitlab.com/NucleusStudios/Mercado-BTX
PHP | 473 lines | 293 code | 24 blank | 156 comment | 22 complexity | 66ad0878a291a2197be3c68aeb75236e MD5 | raw file
  1. <?php
  2. namespace Clio;
  3. class Console
  4. {
  5. /**
  6. * Text foreground colors.
  7. */
  8. protected static $FGCOLOR = array(
  9. 'black' => 30,
  10. 'red' => 31,
  11. 'green' => 32,
  12. 'brown' => 33,
  13. 'blue' => 34,
  14. 'purple' => 35,
  15. 'cyan' => 36,
  16. 'grey' => 37,
  17. 'yellow' => 33,
  18. );
  19. /**
  20. * Text styling.
  21. */
  22. protected static $STYLE = array(
  23. 'normal' => 0,
  24. 'bold' => 1,
  25. 'light' => 1,
  26. 'underscore' => 4,
  27. 'underline' => 4,
  28. 'blink' => 5,
  29. 'inverse' => 6,
  30. 'hidden' => 8,
  31. 'concealed' => 8,
  32. );
  33. /**
  34. * Text background color.
  35. */
  36. protected static $BGCOLOR = array(
  37. 'black' => 40,
  38. 'red' => 41,
  39. 'green' => 42,
  40. 'brown' => 43,
  41. 'yellow' => 43,
  42. 'blue' => 44,
  43. 'purple' => 45,
  44. 'cyan' => 46,
  45. 'grey' => 47,
  46. );
  47. /**
  48. * Color specifier conversion table. Taken from PEAR's Console_Color.
  49. */
  50. protected static $CONVERSIONS = array(
  51. '%y' => array('yellow', null, null),
  52. '%g' => array('green', null, null),
  53. '%b' => array('blue', null, null),
  54. '%r' => array('red', null, null),
  55. '%p' => array('purple', null, null),
  56. '%m' => array('purple', null, null),
  57. '%c' => array('cyan', null, null),
  58. '%w' => array('grey', null, null),
  59. '%k' => array('black', null, null),
  60. '%n' => array('reset', null, null),
  61. '%Y' => array('yellow', 'light', null),
  62. '%G' => array('green', 'light', null),
  63. '%B' => array('blue', 'light', null),
  64. '%R' => array('red', 'light', null),
  65. '%P' => array('purple', 'light', null),
  66. '%M' => array('purple', 'light', null),
  67. '%C' => array('cyan', 'light', null),
  68. '%W' => array('grey', 'light', null),
  69. '%K' => array('black', 'light', null),
  70. '%N' => array('reset', 'light', null),
  71. '%3' => array(null, null, 'yellow'),
  72. '%2' => array(null, null, 'green'),
  73. '%4' => array(null, null, 'blue'),
  74. '%1' => array(null, null, 'red'),
  75. '%5' => array(null, null, 'purple'),
  76. '%6' => array(null, null, 'cyan'),
  77. '%7' => array(null, null, 'grey'),
  78. '%0' => array(null, null, 'black'),
  79. // Don't use this, I can't stand flashing text
  80. '%F' => array(null, 'blink', null),
  81. '%U' => array(null, 'underline', null),
  82. '%8' => array(null, 'inverse', null),
  83. '%9' => array(null, 'bold', null),
  84. '%_' => array(null, 'bold', null),
  85. );
  86. /**
  87. * Create ANSI-control codes for text foreground and background colors, and
  88. * styling.
  89. *
  90. * @param string $fgcolor Text foreground color
  91. * @param string $style Text style
  92. * @param string $bgcolor Text background color
  93. *
  94. * @return string ANSI-control code
  95. */
  96. public static function color($fgcolor, $style, $bgcolor)
  97. {
  98. $code = array();
  99. if ($fgcolor == 'reset') {
  100. return "\033[0m";
  101. }
  102. if (isset(static::$FGCOLOR[$fgcolor])) {
  103. $code[] = static::$FGCOLOR[$fgcolor];
  104. }
  105. if (isset(static::$STYLE[$style])) {
  106. $code[] = static::$STYLE[$style];
  107. }
  108. if (isset(static::$BGCOLOR[$bgcolor])) {
  109. $code[] = static::$BGCOLOR[$bgcolor];
  110. }
  111. if (empty($code)) {
  112. $code[] = 0;
  113. }
  114. return "\033[" . implode(';', $code) . 'm';
  115. }
  116. /**
  117. * Taken from PEAR's Console_Color:
  118. *
  119. * Converts colorcodes in the format %y (for yellow) into ansi-control
  120. * codes. The conversion table is: ('bold' meaning 'light' on some
  121. * terminals). It's almost the same conversion table irssi uses.
  122. * <pre>
  123. * text text background
  124. * ------------------------------------------------
  125. * %k %K %0 black dark grey black
  126. * %r %R %1 red bold red red
  127. * %g %G %2 green bold green green
  128. * %y %Y %3 yellow bold yellow yellow
  129. * %b %B %4 blue bold blue blue
  130. * %m %M %5 magenta bold magenta magenta
  131. * %p %P magenta (think: purple)
  132. * %c %C %6 cyan bold cyan cyan
  133. * %w %W %7 white bold white white
  134. *
  135. * %F Blinking, Flashing
  136. * %U Underline
  137. * %8 Reverse
  138. * %_,%9 Bold
  139. *
  140. * %n Resets the color
  141. * %% A single %
  142. * </pre>
  143. * First param is the string to convert, second is an optional flag if
  144. * colors should be used. It defaults to true, if set to false, the
  145. * colorcodes will just be removed (And %% will be transformed into %)
  146. *
  147. * @param string $text String to color
  148. *
  149. * @return string
  150. */
  151. public static function colorize($text, $color = true)
  152. {
  153. $text = str_replace('%%', '% ', $text);
  154. foreach (static::$CONVERSIONS as $key => $value) {
  155. list($fgcolor, $style, $bgcolor) = $value;
  156. $text = str_replace(
  157. $key,
  158. $color ? static::color($fgcolor, $style, $bgcolor) : '',
  159. $text
  160. );
  161. }
  162. return str_replace('% ', '%', $text);
  163. }
  164. /**
  165. * Strips a string from color specifiers.
  166. *
  167. * @param string $text String to strip
  168. *
  169. * @return string
  170. */
  171. public static function decolorize($text)
  172. {
  173. return static::colorize($text, false);
  174. }
  175. /**
  176. * Strips a string of ansi-control codes.
  177. *
  178. * @param string $text String to strip
  179. *
  180. * @return string
  181. */
  182. public static function strip($text)
  183. {
  184. return preg_replace('/\033\[(\d+)(;\d+)*m/', '', $text);
  185. }
  186. /**
  187. * Gets input from STDIN and returns a string right-trimmed for EOLs.
  188. *
  189. * @param bool $raw If set to true, returns the raw string without trimming
  190. *
  191. * @return string
  192. */
  193. public static function stdin($raw = false)
  194. {
  195. return $raw ? fgets(STDIN) : rtrim(fgets(STDIN), PHP_EOL);
  196. }
  197. /**
  198. * Prints text to STDOUT.
  199. *
  200. * @param string $text
  201. * @param bool $raw
  202. *
  203. * @return int|false Number of bytes printed or false on error
  204. */
  205. public static function stdout($text, $raw = false)
  206. {
  207. if ($raw) {
  208. return fwrite(STDOUT, $text);
  209. } elseif (extension_loaded('posix') && posix_isatty(STDOUT)) {
  210. return fwrite(STDOUT, static::colorize($text));
  211. } else {
  212. return fwrite(STDOUT, static::decolorize($text));
  213. }
  214. }
  215. /**
  216. * Prints text to STDERR.
  217. *
  218. * @param string $text
  219. * @param bool $raw
  220. *
  221. * @return int|false Number of bytes printed or false on error
  222. */
  223. public static function stderr($text, $raw = false)
  224. {
  225. if ($raw) {
  226. return fwrite(STDERR, $text);
  227. } elseif (extension_loaded('posix') && posix_isatty(STDERR)) {
  228. return fwrite(STDERR, static::colorize($text));
  229. } else {
  230. return fwrite(STDERR, static::decolorize($text));
  231. }
  232. }
  233. /**
  234. * Prints text to STDERR appended with a PHP_EOL.
  235. *
  236. * @param string $text
  237. * @param bool $raw
  238. *
  239. * @return int|false Number of bytes printed or false on error
  240. */
  241. public static function error($text = null, $raw = false)
  242. {
  243. return static::stderr($text . PHP_EOL, $raw);
  244. }
  245. /**
  246. * Asks the user for input. Ends when the user types a PHP_EOL. Optionally
  247. * provide a prompt.
  248. *
  249. * @param string $prompt String prompt (optional)
  250. *
  251. * @return string User input
  252. */
  253. public static function input($prompt = null)
  254. {
  255. if (isset($prompt)) {
  256. static::stdout($prompt);
  257. }
  258. return static::stdin();
  259. }
  260. /**
  261. * Prints text to STDOUT appended with a PHP_EOL.
  262. *
  263. * @param string $text
  264. * @param bool $raw
  265. *
  266. * @return int|false Number of bytes printed or false on error
  267. */
  268. public static function output($text = null, $raw = false)
  269. {
  270. return static::stdout($text . PHP_EOL, $raw);
  271. }
  272. /**
  273. * Prompts the user for input
  274. *
  275. * @param string $text Prompt string
  276. * @param array $options Set of options
  277. *
  278. * @return string
  279. */
  280. public static function prompt($text, $options = array())
  281. {
  282. $options = $options + array(
  283. 'required' => false,
  284. 'default' => null,
  285. 'pattern' => null,
  286. 'validator' => null,
  287. 'error' => 'Input unacceptable.',
  288. );
  289. top:
  290. if ($options['default']) {
  291. $input = static::input("$text [" . $options['default'] . ']: ');
  292. } else {
  293. $input = static::input("$text: ");
  294. }
  295. if (!strlen($input)) {
  296. if (isset($options['default'])) {
  297. $input = $options['default'];
  298. } elseif ($options['required']) {
  299. static::output($options['error']);
  300. goto top;
  301. }
  302. } elseif ($options['pattern'] && !preg_match($options['pattern'], $input)) {
  303. static::output($options['error']);
  304. goto top;
  305. } elseif ($options['validator'] &&
  306. !call_user_func_array($options['validator'], array($input, &$error))) {
  307. static::output(isset($error) ? $error : $options['error']);
  308. goto top;
  309. }
  310. return $input;
  311. }
  312. /**
  313. * Asks the user for a simple yes/no confirmation.
  314. *
  315. * @param string $text Prompt string
  316. *
  317. * @return bool Either true or false
  318. */
  319. public static function confirm($text)
  320. {
  321. top:
  322. $input = strtolower(static::input("$text [y/n]: "));
  323. if (!in_array($input, array('y', 'n'))) goto top;
  324. return $input === 'y' ? true : false;
  325. }
  326. /**
  327. * Gives the user an option to choose from. Giving '?' as an input will show
  328. * a list of options to choose from and their explanations.
  329. *
  330. * @param string $text Prompt string
  331. * @param array $options Key-value array of options to choose from
  332. *
  333. * @return string An option character the user chose
  334. */
  335. public static function select($text, $options = array())
  336. {
  337. top:
  338. static::stdout("$text [" . implode(',', array_keys($options)) . ",?]: ");
  339. $input = static::stdin();
  340. if ($input === '?') {
  341. foreach ($options as $key => $value) {
  342. echo " $key - $value\n";
  343. }
  344. echo " ? - Show help\n";
  345. goto top;
  346. } elseif (!in_array($input, array_keys($options))) goto top;
  347. return $input;
  348. }
  349. /**
  350. * Execute a Closure as another process in the background while showing a
  351. * status update. The status update can be an indefinite spinner or a string
  352. * periodically sent from the background process, depending on whether the
  353. * provided Closure object has a $socket parameter or not. Messaging to the
  354. * main process is done by socket_* functions. The return value is either
  355. * the return value of the background process, or false if the process fork
  356. * failed.
  357. *
  358. * @param Closure $callable Closure object
  359. *
  360. * @return int|false Process exit status
  361. */
  362. public static function work(\Closure $callable)
  363. {
  364. if (!extension_loaded('pcntl')) {
  365. throw new \Exception('pcntl extension required');
  366. }
  367. if (!extension_loaded('sockets')) {
  368. throw new \Exception('sockets extension required');
  369. }
  370. $spinner = array('|', '/', '-', '\\');
  371. $i = 0; $l = count($spinner);
  372. $delay = 100000;
  373. $func = new \ReflectionFunction($callable);
  374. $socket = (bool)$func->getNumberOfParameters();
  375. if ($socket) {
  376. $sockets = array();
  377. if (socket_create_pair(AF_UNIX, SOCK_STREAM, 0, $sockets) === false) {
  378. return false;
  379. }
  380. }
  381. $pid = pcntl_fork();
  382. if ($pid > 0) {
  383. $done = false;
  384. $retval = 0;
  385. pcntl_signal(SIGCHLD, function() use ($pid, &$done, &$retval) {
  386. $child_pid = pcntl_waitpid($pid, $status);
  387. if (pcntl_wifexited($status)) {
  388. $retval = pcntl_wexitstatus($status);
  389. }
  390. $done = true;
  391. });
  392. if ($socket) {
  393. $text = '';
  394. while (!$done) {
  395. $r = array($sockets[1]);
  396. $w = null;
  397. $e = null;
  398. if ($status = socket_select($r, $w, $e, 0)) {
  399. $data = socket_read($sockets[1], 4096, PHP_NORMAL_READ);
  400. if ($data === false) {
  401. throw new \Exception(
  402. sprintf(
  403. 'socket write error %s',
  404. socket_strerror(socket_last_error($sockets[1]))
  405. )
  406. );
  407. }
  408. echo str_repeat(chr(8), strlen($text));
  409. $text = rtrim($data, "\n");
  410. Console::stdout($text);
  411. } else {
  412. pcntl_signal_dispatch();
  413. }
  414. usleep($delay);
  415. }
  416. echo str_repeat(chr(8), strlen($text));
  417. socket_close($sockets[0]);
  418. socket_close($sockets[1]);
  419. } else {
  420. while (!$done) {
  421. pcntl_signal_dispatch();
  422. echo $spinner[$i];
  423. usleep($delay);
  424. echo chr(8);
  425. $i = $i === $l - 1 ? 0 : $i + 1;
  426. }
  427. }
  428. return $retval;
  429. } elseif ($pid === 0) {
  430. if ($socket) {
  431. call_user_func($callable, $sockets[0]);
  432. } else {
  433. call_user_func($callable);
  434. }
  435. exit;
  436. } else {
  437. // Unable to fork process.
  438. return false;
  439. }
  440. }
  441. }