Complex classes like BaseConsole often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use BaseConsole, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
20 | class BaseConsole |
||
21 | { |
||
22 | // foreground color control codes |
||
23 | const FG_BLACK = 30; |
||
24 | const FG_RED = 31; |
||
25 | const FG_GREEN = 32; |
||
26 | const FG_YELLOW = 33; |
||
27 | const FG_BLUE = 34; |
||
28 | const FG_PURPLE = 35; |
||
29 | const FG_CYAN = 36; |
||
30 | const FG_GREY = 37; |
||
31 | // background color control codes |
||
32 | const BG_BLACK = 40; |
||
33 | const BG_RED = 41; |
||
34 | const BG_GREEN = 42; |
||
35 | const BG_YELLOW = 43; |
||
36 | const BG_BLUE = 44; |
||
37 | const BG_PURPLE = 45; |
||
38 | const BG_CYAN = 46; |
||
39 | const BG_GREY = 47; |
||
40 | // fonts style control codes |
||
41 | const RESET = 0; |
||
42 | const NORMAL = 0; |
||
43 | const BOLD = 1; |
||
44 | const ITALIC = 3; |
||
45 | const UNDERLINE = 4; |
||
46 | const BLINK = 5; |
||
47 | const NEGATIVE = 7; |
||
48 | const CONCEALED = 8; |
||
49 | const CROSSED_OUT = 9; |
||
50 | const FRAMED = 51; |
||
51 | const ENCIRCLED = 52; |
||
52 | const OVERLINED = 53; |
||
53 | |||
54 | |||
55 | /** |
||
56 | * Moves the terminal cursor up by sending ANSI control code CUU to the terminal. |
||
57 | * If the cursor is already at the edge of the screen, this has no effect. |
||
58 | * @param int $rows number of rows the cursor should be moved up |
||
59 | */ |
||
60 | 1 | public static function moveCursorUp($rows = 1) |
|
64 | |||
65 | /** |
||
66 | * Moves the terminal cursor down by sending ANSI control code CUD to the terminal. |
||
67 | * If the cursor is already at the edge of the screen, this has no effect. |
||
68 | * @param int $rows number of rows the cursor should be moved down |
||
69 | */ |
||
70 | 1 | public static function moveCursorDown($rows = 1) |
|
74 | |||
75 | /** |
||
76 | * Moves the terminal cursor forward by sending ANSI control code CUF to the terminal. |
||
77 | * If the cursor is already at the edge of the screen, this has no effect. |
||
78 | * @param int $steps number of steps the cursor should be moved forward |
||
79 | */ |
||
80 | 1 | public static function moveCursorForward($steps = 1) |
|
84 | |||
85 | /** |
||
86 | * Moves the terminal cursor backward by sending ANSI control code CUB to the terminal. |
||
87 | * If the cursor is already at the edge of the screen, this has no effect. |
||
88 | * @param int $steps number of steps the cursor should be moved backward |
||
89 | */ |
||
90 | 1 | public static function moveCursorBackward($steps = 1) |
|
94 | |||
95 | /** |
||
96 | * Moves the terminal cursor to the beginning of the next line by sending ANSI control code CNL to the terminal. |
||
97 | * @param int $lines number of lines the cursor should be moved down |
||
98 | */ |
||
99 | 1 | public static function moveCursorNextLine($lines = 1) |
|
103 | |||
104 | /** |
||
105 | * Moves the terminal cursor to the beginning of the previous line by sending ANSI control code CPL to the terminal. |
||
106 | * @param int $lines number of lines the cursor should be moved up |
||
107 | */ |
||
108 | 1 | public static function moveCursorPrevLine($lines = 1) |
|
112 | |||
113 | /** |
||
114 | * Moves the cursor to an absolute position given as column and row by sending ANSI control code CUP or CHA to the terminal. |
||
115 | * @param int $column 1-based column number, 1 is the left edge of the screen. |
||
116 | * @param int|null $row 1-based row number, 1 is the top edge of the screen. if not set, will move cursor only in current line. |
||
117 | */ |
||
118 | 1 | public static function moveCursorTo($column, $row = null) |
|
119 | { |
||
120 | 1 | if ($row === null) { |
|
121 | 1 | echo "\033[" . (int) $column . 'G'; |
|
122 | } else { |
||
123 | 1 | echo "\033[" . (int) $row . ';' . (int) $column . 'H'; |
|
124 | } |
||
125 | 1 | } |
|
126 | |||
127 | /** |
||
128 | * Scrolls whole page up by sending ANSI control code SU to the terminal. |
||
129 | * New lines are added at the bottom. This is not supported by ANSI.SYS used in windows. |
||
130 | * @param int $lines number of lines to scroll up |
||
131 | */ |
||
132 | 1 | public static function scrollUp($lines = 1) |
|
136 | |||
137 | /** |
||
138 | * Scrolls whole page down by sending ANSI control code SD to the terminal. |
||
139 | * New lines are added at the top. This is not supported by ANSI.SYS used in windows. |
||
140 | * @param int $lines number of lines to scroll down |
||
141 | */ |
||
142 | 1 | public static function scrollDown($lines = 1) |
|
146 | |||
147 | /** |
||
148 | * Saves the current cursor position by sending ANSI control code SCP to the terminal. |
||
149 | * Position can then be restored with [[restoreCursorPosition()]]. |
||
150 | */ |
||
151 | 1 | public static function saveCursorPosition() |
|
155 | |||
156 | /** |
||
157 | * Restores the cursor position saved with [[saveCursorPosition()]] by sending ANSI control code RCP to the terminal. |
||
158 | */ |
||
159 | 1 | public static function restoreCursorPosition() |
|
163 | |||
164 | /** |
||
165 | * Hides the cursor by sending ANSI DECTCEM code ?25l to the terminal. |
||
166 | * Use [[showCursor()]] to bring it back. |
||
167 | * Do not forget to show cursor when your application exits. Cursor might stay hidden in terminal after exit. |
||
168 | */ |
||
169 | 1 | public static function hideCursor() |
|
173 | |||
174 | /** |
||
175 | * Will show a cursor again when it has been hidden by [[hideCursor()]] by sending ANSI DECTCEM code ?25h to the terminal. |
||
176 | */ |
||
177 | 1 | public static function showCursor() |
|
181 | |||
182 | /** |
||
183 | * Clears entire screen content by sending ANSI control code ED with argument 2 to the terminal. |
||
184 | * Cursor position will not be changed. |
||
185 | * **Note:** ANSI.SYS implementation used in windows will reset cursor position to upper left corner of the screen. |
||
186 | */ |
||
187 | 1 | public static function clearScreen() |
|
191 | |||
192 | /** |
||
193 | * Clears text from cursor to the beginning of the screen by sending ANSI control code ED with argument 1 to the terminal. |
||
194 | * Cursor position will not be changed. |
||
195 | */ |
||
196 | 1 | public static function clearScreenBeforeCursor() |
|
200 | |||
201 | /** |
||
202 | * Clears text from cursor to the end of the screen by sending ANSI control code ED with argument 0 to the terminal. |
||
203 | * Cursor position will not be changed. |
||
204 | */ |
||
205 | 1 | public static function clearScreenAfterCursor() |
|
209 | |||
210 | /** |
||
211 | * Clears the line, the cursor is currently on by sending ANSI control code EL with argument 2 to the terminal. |
||
212 | * Cursor position will not be changed. |
||
213 | */ |
||
214 | 1 | public static function clearLine() |
|
218 | |||
219 | /** |
||
220 | * Clears text from cursor position to the beginning of the line by sending ANSI control code EL with argument 1 to the terminal. |
||
221 | * Cursor position will not be changed. |
||
222 | */ |
||
223 | 1 | public static function clearLineBeforeCursor() |
|
227 | |||
228 | /** |
||
229 | * Clears text from cursor position to the end of the line by sending ANSI control code EL with argument 0 to the terminal. |
||
230 | * Cursor position will not be changed. |
||
231 | */ |
||
232 | 1 | public static function clearLineAfterCursor() |
|
236 | |||
237 | /** |
||
238 | * Returns the ANSI format code. |
||
239 | * |
||
240 | * @param array $format An array containing formatting values. |
||
241 | * You can pass any of the `FG_*`, `BG_*` and `TEXT_*` constants |
||
242 | * and also [[xtermFgColor]] and [[xtermBgColor]] to specify a format. |
||
243 | * @return string The ANSI format code according to the given formatting constants. |
||
244 | */ |
||
245 | 2 | public static function ansiFormatCode($format) |
|
246 | { |
||
247 | 2 | return "\033[" . implode(';', $format) . 'm'; |
|
248 | } |
||
249 | |||
250 | /** |
||
251 | * Echoes an ANSI format code that affects the formatting of any text that is printed afterwards. |
||
252 | * |
||
253 | * @param array $format An array containing formatting values. |
||
254 | * You can pass any of the `FG_*`, `BG_*` and `TEXT_*` constants |
||
255 | * and also [[xtermFgColor]] and [[xtermBgColor]] to specify a format. |
||
256 | * @see ansiFormatCode() |
||
257 | * @see endAnsiFormat() |
||
258 | */ |
||
259 | 1 | public static function beginAnsiFormat($format) |
|
263 | |||
264 | /** |
||
265 | * Resets any ANSI format set by previous method [[beginAnsiFormat()]] |
||
266 | * Any output after this will have default text format. |
||
267 | * This is equal to calling |
||
268 | * |
||
269 | * ```php |
||
270 | * echo Console::ansiFormatCode([Console::RESET]) |
||
271 | * ``` |
||
272 | */ |
||
273 | 1 | public static function endAnsiFormat() |
|
277 | |||
278 | /** |
||
279 | * Will return a string formatted with the given ANSI style |
||
280 | * |
||
281 | * @param string $string the string to be formatted |
||
282 | * @param array $format An array containing formatting values. |
||
283 | * You can pass any of the `FG_*`, `BG_*` and `TEXT_*` constants |
||
284 | * and also [[xtermFgColor]] and [[xtermBgColor]] to specify a format. |
||
285 | * @return string |
||
286 | */ |
||
287 | 16 | public static function ansiFormat($string, $format = []) |
|
293 | |||
294 | /** |
||
295 | * Returns the ansi format code for xterm foreground color. |
||
296 | * You can pass the return value of this to one of the formatting methods: |
||
297 | * [[ansiFormat]], [[ansiFormatCode]], [[beginAnsiFormat]] |
||
298 | * |
||
299 | * @param int $colorCode xterm color code |
||
300 | * @return string |
||
301 | * @see http://en.wikipedia.org/wiki/Talk:ANSI_escape_code#xterm-256colors |
||
302 | */ |
||
303 | 1 | public static function xtermFgColor($colorCode) |
|
307 | |||
308 | /** |
||
309 | * Returns the ansi format code for xterm background color. |
||
310 | * You can pass the return value of this to one of the formatting methods: |
||
311 | * [[ansiFormat]], [[ansiFormatCode]], [[beginAnsiFormat]] |
||
312 | * |
||
313 | * @param int $colorCode xterm color code |
||
314 | * @return string |
||
315 | * @see http://en.wikipedia.org/wiki/Talk:ANSI_escape_code#xterm-256colors |
||
316 | */ |
||
317 | 1 | public static function xtermBgColor($colorCode) |
|
321 | |||
322 | /** |
||
323 | * Strips ANSI control codes from a string |
||
324 | * |
||
325 | * @param string $string String to strip |
||
326 | * @return string |
||
327 | */ |
||
328 | 7 | public static function stripAnsiFormat($string) |
|
332 | |||
333 | /** |
||
334 | * Returns the length of the string without ANSI color codes. |
||
335 | * @param string $string the string to measure |
||
336 | * @return int the length of the string not counting ANSI format characters |
||
337 | */ |
||
338 | public static function ansiStrlen($string) |
||
342 | |||
343 | /** |
||
344 | * Converts an ANSI formatted string to HTML |
||
345 | * |
||
346 | * Note: xTerm 256 bit colors are currently not supported. |
||
347 | * |
||
348 | * @param string $string the string to convert. |
||
349 | * @param array $styleMap an optional mapping of ANSI control codes such as |
||
350 | * FG\_*COLOR* or [[BOLD]] to a set of css style definitions. |
||
351 | * The CSS style definitions are represented as an array where the array keys correspond |
||
352 | * to the css style attribute names and the values are the css values. |
||
353 | * values may be arrays that will be merged and imploded with `' '` when rendered. |
||
354 | * @return string HTML representation of the ANSI formatted string |
||
355 | */ |
||
356 | 15 | public static function ansiToHtml($string, $styleMap = []) |
|
357 | { |
||
358 | $styleMap = [ |
||
359 | // http://www.w3.org/TR/CSS2/syndata.html#value-def-color |
||
360 | 15 | self::FG_BLACK => ['color' => 'black'], |
|
361 | 15 | self::FG_BLUE => ['color' => 'blue'], |
|
362 | 15 | self::FG_CYAN => ['color' => 'aqua'], |
|
363 | 15 | self::FG_GREEN => ['color' => 'lime'], |
|
364 | 15 | self::FG_GREY => ['color' => 'silver'], |
|
365 | // http://meyerweb.com/eric/thoughts/2014/06/19/rebeccapurple/ |
||
366 | // http://dev.w3.org/csswg/css-color/#valuedef-rebeccapurple |
||
367 | 15 | self::FG_PURPLE => ['color' => 'rebeccapurple'], |
|
368 | 15 | self::FG_RED => ['color' => 'red'], |
|
369 | 15 | self::FG_YELLOW => ['color' => 'yellow'], |
|
370 | 15 | self::BG_BLACK => ['background-color' => 'black'], |
|
371 | 15 | self::BG_BLUE => ['background-color' => 'blue'], |
|
372 | 15 | self::BG_CYAN => ['background-color' => 'aqua'], |
|
373 | 15 | self::BG_GREEN => ['background-color' => 'lime'], |
|
374 | 15 | self::BG_GREY => ['background-color' => 'silver'], |
|
375 | 15 | self::BG_PURPLE => ['background-color' => 'rebeccapurple'], |
|
376 | 15 | self::BG_RED => ['background-color' => 'red'], |
|
377 | 15 | self::BG_YELLOW => ['background-color' => 'yellow'], |
|
378 | 15 | self::BOLD => ['font-weight' => 'bold'], |
|
379 | 15 | self::ITALIC => ['font-style' => 'italic'], |
|
380 | 15 | self::UNDERLINE => ['text-decoration' => ['underline']], |
|
381 | 15 | self::OVERLINED => ['text-decoration' => ['overline']], |
|
382 | 15 | self::CROSSED_OUT => ['text-decoration' => ['line-through']], |
|
383 | 15 | self::BLINK => ['text-decoration' => ['blink']], |
|
384 | 15 | self::CONCEALED => ['visibility' => 'hidden'], |
|
385 | 15 | ] + $styleMap; |
|
386 | |||
387 | 15 | $tags = 0; |
|
388 | 15 | $result = preg_replace_callback( |
|
389 | 15 | '/\033\[([\d;]+)m/', |
|
390 | 15 | function ($ansi) use (&$tags, $styleMap) { |
|
391 | 14 | $style = []; |
|
392 | 14 | $reset = false; |
|
393 | 14 | $negative = false; |
|
394 | 14 | foreach (explode(';', $ansi[1]) as $controlCode) { |
|
395 | 14 | if ($controlCode == 0) { |
|
396 | 14 | $style = []; |
|
397 | 14 | $reset = true; |
|
398 | 11 | } elseif ($controlCode == self::NEGATIVE) { |
|
399 | 2 | $negative = true; |
|
400 | 10 | } elseif (isset($styleMap[$controlCode])) { |
|
401 | 14 | $style[] = $styleMap[$controlCode]; |
|
402 | } |
||
403 | } |
||
404 | |||
405 | 14 | $return = ''; |
|
406 | 14 | while ($reset && $tags > 0) { |
|
407 | 10 | $return .= '</span>'; |
|
408 | 10 | $tags--; |
|
409 | } |
||
410 | 14 | if (empty($style)) { |
|
411 | 14 | return $return; |
|
412 | } |
||
413 | |||
414 | 10 | $currentStyle = []; |
|
415 | 10 | foreach ($style as $content) { |
|
416 | 10 | $currentStyle = ArrayHelper::merge($currentStyle, $content); |
|
417 | } |
||
418 | |||
419 | // if negative is set, invert background and foreground |
||
420 | 10 | if ($negative) { |
|
421 | 1 | if (isset($currentStyle['color'])) { |
|
422 | 1 | $fgColor = $currentStyle['color']; |
|
423 | 1 | unset($currentStyle['color']); |
|
424 | } |
||
425 | 1 | if (isset($currentStyle['background-color'])) { |
|
426 | 1 | $bgColor = $currentStyle['background-color']; |
|
427 | 1 | unset($currentStyle['background-color']); |
|
428 | } |
||
429 | 1 | if (isset($fgColor)) { |
|
430 | 1 | $currentStyle['background-color'] = $fgColor; |
|
431 | } |
||
432 | 1 | if (isset($bgColor)) { |
|
433 | 1 | $currentStyle['color'] = $bgColor; |
|
434 | } |
||
435 | } |
||
436 | |||
437 | 10 | $styleString = ''; |
|
438 | 10 | foreach ($currentStyle as $name => $value) { |
|
439 | 10 | if (is_array($value)) { |
|
440 | 1 | $value = implode(' ', $value); |
|
441 | } |
||
442 | 10 | $styleString .= "$name: $value;"; |
|
443 | } |
||
444 | 10 | $tags++; |
|
445 | 10 | return "$return<span style=\"$styleString\">"; |
|
446 | 15 | }, |
|
447 | 15 | $string |
|
448 | ); |
||
449 | 15 | while ($tags > 0) { |
|
450 | $result .= '</span>'; |
||
451 | $tags--; |
||
452 | } |
||
453 | 15 | return $result; |
|
454 | } |
||
455 | |||
456 | /** |
||
457 | * Converts Markdown to be better readable in console environments by applying some ANSI format |
||
458 | * @param string $markdown the markdown string. |
||
459 | * @return string the parsed result as ANSI formatted string. |
||
460 | */ |
||
461 | 2 | public static function markdownToAnsi($markdown) |
|
466 | |||
467 | /** |
||
468 | * Converts a string to ansi formatted by replacing patterns like %y (for yellow) with ansi control codes |
||
469 | * |
||
470 | * Uses almost the same syntax as https://github.com/pear/Console_Color2/blob/master/Console/Color2.php |
||
471 | * The conversion table is: ('bold' meaning 'light' on some |
||
472 | * terminals). It's almost the same conversion table irssi uses. |
||
473 | * <pre> |
||
474 | * text text background |
||
475 | * ------------------------------------------------ |
||
476 | * %k %K %0 black dark grey black |
||
477 | * %r %R %1 red bold red red |
||
478 | * %g %G %2 green bold green green |
||
479 | * %y %Y %3 yellow bold yellow yellow |
||
480 | * %b %B %4 blue bold blue blue |
||
481 | * %m %M %5 magenta bold magenta magenta |
||
482 | * %p %P magenta (think: purple) |
||
483 | * %c %C %6 cyan bold cyan cyan |
||
484 | * %w %W %7 white bold white white |
||
485 | * |
||
486 | * %F Blinking, Flashing |
||
487 | * %U Underline |
||
488 | * %8 Reverse |
||
489 | * %_,%9 Bold |
||
490 | * |
||
491 | * %n Resets the color |
||
492 | * %% A single % |
||
493 | * </pre> |
||
494 | * First param is the string to convert, second is an optional flag if |
||
495 | * colors should be used. It defaults to true, if set to false, the |
||
496 | * color codes will just be removed (And %% will be transformed into %) |
||
497 | * |
||
498 | * @param string $string String to convert |
||
499 | * @param bool $colored Should the string be colored? |
||
500 | * @return string |
||
501 | */ |
||
502 | 2 | public static function renderColoredString($string, $colored = true) |
|
503 | { |
||
504 | // TODO rework/refactor according to https://github.com/yiisoft/yii2/issues/746 |
||
505 | 2 | static $conversions = [ |
|
506 | '%y' => [self::FG_YELLOW], |
||
507 | '%g' => [self::FG_GREEN], |
||
508 | '%b' => [self::FG_BLUE], |
||
509 | '%r' => [self::FG_RED], |
||
510 | '%p' => [self::FG_PURPLE], |
||
511 | '%m' => [self::FG_PURPLE], |
||
512 | '%c' => [self::FG_CYAN], |
||
513 | '%w' => [self::FG_GREY], |
||
514 | '%k' => [self::FG_BLACK], |
||
515 | '%n' => [0], // reset |
||
516 | '%Y' => [self::FG_YELLOW, self::BOLD], |
||
517 | '%G' => [self::FG_GREEN, self::BOLD], |
||
518 | '%B' => [self::FG_BLUE, self::BOLD], |
||
519 | '%R' => [self::FG_RED, self::BOLD], |
||
520 | '%P' => [self::FG_PURPLE, self::BOLD], |
||
521 | '%M' => [self::FG_PURPLE, self::BOLD], |
||
522 | '%C' => [self::FG_CYAN, self::BOLD], |
||
523 | '%W' => [self::FG_GREY, self::BOLD], |
||
524 | '%K' => [self::FG_BLACK, self::BOLD], |
||
525 | '%N' => [0, self::BOLD], |
||
526 | '%3' => [self::BG_YELLOW], |
||
527 | '%2' => [self::BG_GREEN], |
||
528 | '%4' => [self::BG_BLUE], |
||
529 | '%1' => [self::BG_RED], |
||
530 | '%5' => [self::BG_PURPLE], |
||
531 | '%6' => [self::BG_CYAN], |
||
532 | '%7' => [self::BG_GREY], |
||
533 | '%0' => [self::BG_BLACK], |
||
534 | '%F' => [self::BLINK], |
||
535 | '%U' => [self::UNDERLINE], |
||
536 | '%8' => [self::NEGATIVE], |
||
537 | '%9' => [self::BOLD], |
||
538 | '%_' => [self::BOLD], |
||
539 | ]; |
||
540 | |||
541 | 2 | if ($colored) { |
|
542 | 2 | $string = str_replace('%%', '% ', $string); |
|
543 | 2 | foreach ($conversions as $key => $value) { |
|
544 | 2 | $string = str_replace( |
|
545 | 2 | $key, |
|
546 | 2 | static::ansiFormatCode($value), |
|
547 | 2 | $string |
|
548 | ); |
||
549 | } |
||
550 | 2 | $string = str_replace('% ', '%', $string); |
|
551 | } else { |
||
552 | $string = preg_replace('/%((%)|.)/', '$2', $string); |
||
553 | } |
||
554 | |||
555 | 2 | return $string; |
|
556 | } |
||
557 | |||
558 | /** |
||
559 | * Escapes % so they don't get interpreted as color codes when |
||
560 | * the string is parsed by [[renderColoredString]] |
||
561 | * |
||
562 | * @param string $string String to escape |
||
563 | * |
||
564 | * @return string |
||
565 | */ |
||
566 | public static function escape($string) |
||
571 | |||
572 | /** |
||
573 | * Returns true if the stream supports colorization. ANSI colors are disabled if not supported by the stream. |
||
574 | * |
||
575 | * - windows without ansicon |
||
576 | * - not tty consoles |
||
577 | * |
||
578 | * @param mixed $stream |
||
579 | * @return bool true if the stream supports ANSI colors, otherwise false. |
||
580 | */ |
||
581 | 4 | public static function streamSupportsAnsiColors($stream) |
|
587 | |||
588 | /** |
||
589 | * Returns true if the console is running on windows |
||
590 | * @return bool |
||
591 | */ |
||
592 | 1 | public static function isRunningOnWindows() |
|
596 | |||
597 | /** |
||
598 | * Usage: [$width, $height] = ConsoleHelper::getScreenSize(); |
||
599 | * |
||
600 | * @param bool $refresh whether to force checking and not re-use cached size value. |
||
601 | * This is useful to detect changing window size while the application is running but may |
||
602 | * not get up to date values on every terminal. |
||
603 | * @return array|bool An array of ($width, $height) or false when it was not able to determine size. |
||
604 | */ |
||
605 | 1 | public static function getScreenSize($refresh = false) |
|
648 | |||
649 | /** |
||
650 | * Word wrap text with indentation to fit the screen size |
||
651 | * |
||
652 | * If screen size could not be detected, or the indentation is greater than the screen size, the text will not be wrapped. |
||
653 | * |
||
654 | * The first line will **not** be indented, so `Console::wrapText("Lorem ipsum dolor sit amet.", 4)` will result in the |
||
655 | * following output, given the screen width is 16 characters: |
||
656 | * |
||
657 | * ``` |
||
658 | * Lorem ipsum |
||
659 | * dolor sit |
||
660 | * amet. |
||
661 | * ``` |
||
662 | * |
||
663 | * @param string $text the text to be wrapped |
||
664 | * @param int $indent number of spaces to use for indentation. |
||
665 | * @param bool $refresh whether to force refresh of screen size. |
||
666 | * This will be passed to [[getScreenSize()]]. |
||
667 | * @return string the wrapped text. |
||
668 | * @since 2.0.4 |
||
669 | */ |
||
670 | 1 | public static function wrapText($text, $indent = 0, $refresh = false) |
|
688 | |||
689 | /** |
||
690 | * Gets input from STDIN and returns a string right-trimmed for EOLs. |
||
691 | * |
||
692 | * @param bool $raw If set to true, returns the raw string without trimming |
||
693 | * @return string the string read from stdin |
||
694 | */ |
||
695 | public static function stdin($raw = false) |
||
699 | |||
700 | /** |
||
701 | * Prints a string to STDOUT. |
||
702 | * |
||
703 | * @param string $string the string to print |
||
704 | * @return int|bool Number of bytes printed or false on error |
||
705 | */ |
||
706 | public static function stdout($string) |
||
710 | |||
711 | /** |
||
712 | * Prints a string to STDERR. |
||
713 | * |
||
714 | * @param string $string the string to print |
||
715 | * @return int|bool Number of bytes printed or false on error |
||
716 | */ |
||
717 | public static function stderr($string) |
||
721 | |||
722 | /** |
||
723 | * Asks the user for input. Ends when the user types a carriage return (PHP_EOL). Optionally, It also provides a |
||
724 | * prompt. |
||
725 | * |
||
726 | * @param string $prompt the prompt to display before waiting for input (optional) |
||
727 | * @return string the user's input |
||
728 | */ |
||
729 | public static function input($prompt = null) |
||
737 | |||
738 | /** |
||
739 | * Prints text to STDOUT appended with a carriage return (PHP_EOL). |
||
740 | * |
||
741 | * @param string $string the text to print |
||
742 | * @return int|bool number of bytes printed or false on error. |
||
743 | */ |
||
744 | public static function output($string = null) |
||
748 | |||
749 | /** |
||
750 | * Prints text to STDERR appended with a carriage return (PHP_EOL). |
||
751 | * |
||
752 | * @param string $string the text to print |
||
753 | * @return int|bool number of bytes printed or false on error. |
||
754 | */ |
||
755 | public static function error($string = null) |
||
759 | |||
760 | /** |
||
761 | * Prompts the user for input and validates it |
||
762 | * |
||
763 | * @param string $text prompt string |
||
764 | * @param array $options the options to validate the input: |
||
765 | * |
||
766 | * - `required`: whether it is required or not |
||
767 | * - `default`: default value if no input is inserted by the user |
||
768 | * - `pattern`: regular expression pattern to validate user input |
||
769 | * - `validator`: a callable function to validate input. The function must accept two parameters: |
||
770 | * - `input`: the user input to validate |
||
771 | * - `error`: the error value passed by reference if validation failed. |
||
772 | * |
||
773 | * @return string the user input |
||
774 | */ |
||
775 | public static function prompt($text, $options = []) |
||
776 | { |
||
777 | $options = ArrayHelper::merge( |
||
778 | [ |
||
779 | 'required' => false, |
||
780 | 'default' => null, |
||
781 | 'pattern' => null, |
||
782 | 'validator' => null, |
||
783 | 'error' => 'Invalid input.', |
||
784 | ], |
||
785 | $options |
||
786 | ); |
||
787 | $error = null; |
||
788 | |||
789 | top: |
||
790 | $input = $options['default'] |
||
791 | ? static::input("$text [" . $options['default'] . '] ') |
||
792 | : static::input("$text "); |
||
793 | |||
794 | if ($input === '') { |
||
795 | if (isset($options['default'])) { |
||
796 | $input = $options['default']; |
||
797 | } elseif ($options['required']) { |
||
798 | static::output($options['error']); |
||
799 | goto top; |
||
800 | } |
||
801 | } elseif ($options['pattern'] && !preg_match($options['pattern'], $input)) { |
||
802 | static::output($options['error']); |
||
803 | goto top; |
||
804 | } elseif ($options['validator'] && |
||
805 | !call_user_func_array($options['validator'], [$input, &$error]) |
||
806 | ) { |
||
807 | static::output(isset($error) ? $error : $options['error']); |
||
808 | goto top; |
||
809 | } |
||
810 | |||
811 | return $input; |
||
812 | } |
||
813 | |||
814 | /** |
||
815 | * Asks user to confirm by typing y or n. |
||
816 | * |
||
817 | * A typical usage looks like the following: |
||
818 | * |
||
819 | * ```php |
||
820 | * if (Console::confirm("Are you sure?")) { |
||
821 | * echo "user typed yes\n"; |
||
822 | * } else { |
||
823 | * echo "user typed no\n"; |
||
824 | * } |
||
825 | * ``` |
||
826 | * |
||
827 | * @param string $message to print out before waiting for user input |
||
828 | * @param bool $default this value is returned if no selection is made. |
||
829 | * @return bool whether user confirmed |
||
830 | */ |
||
831 | public static function confirm($message, $default = false) |
||
832 | { |
||
833 | while (true) { |
||
834 | static::stdout($message . ' (yes|no) [' . ($default ? 'yes' : 'no') . ']:'); |
||
835 | $input = trim(static::stdin()); |
||
836 | |||
837 | if (empty($input)) { |
||
838 | return $default; |
||
839 | } |
||
840 | |||
841 | if (!strcasecmp($input, 'y') || !strcasecmp($input, 'yes')) { |
||
842 | return true; |
||
843 | } |
||
844 | |||
845 | if (!strcasecmp($input, 'n') || !strcasecmp($input, 'no')) { |
||
846 | return false; |
||
847 | } |
||
848 | } |
||
849 | } |
||
850 | |||
851 | /** |
||
852 | * Gives the user an option to choose from. Giving '?' as an input will show |
||
853 | * a list of options to choose from and their explanations. |
||
854 | * |
||
855 | * @param string $prompt the prompt message |
||
856 | * @param array $options Key-value array of options to choose from |
||
857 | * |
||
858 | * @return string An option character the user chose |
||
859 | */ |
||
860 | public static function select($prompt, $options = []) |
||
877 | |||
878 | private static $_progressStart; |
||
879 | private static $_progressWidth; |
||
880 | private static $_progressPrefix; |
||
881 | private static $_progressEta; |
||
882 | private static $_progressEtaLastDone = 0; |
||
883 | private static $_progressEtaLastUpdate; |
||
884 | |||
885 | /** |
||
886 | * Starts display of a progress bar on screen. |
||
887 | * |
||
888 | * This bar will be updated by [[updateProgress()]] and my be ended by [[endProgress()]]. |
||
889 | * |
||
890 | * The following example shows a simple usage of a progress bar: |
||
891 | * |
||
892 | * ```php |
||
893 | * Console::startProgress(0, 1000); |
||
894 | * for ($n = 1; $n <= 1000; $n++) { |
||
895 | * usleep(1000); |
||
896 | * Console::updateProgress($n, 1000); |
||
897 | * } |
||
898 | * Console::endProgress(); |
||
899 | * ``` |
||
900 | * |
||
901 | * Git clone like progress (showing only status information): |
||
902 | * ```php |
||
903 | * Console::startProgress(0, 1000, 'Counting objects: ', false); |
||
904 | * for ($n = 1; $n <= 1000; $n++) { |
||
905 | * usleep(1000); |
||
906 | * Console::updateProgress($n, 1000); |
||
907 | * } |
||
908 | * Console::endProgress("done." . PHP_EOL); |
||
909 | * ``` |
||
910 | * |
||
911 | * @param int $done the number of items that are completed. |
||
912 | * @param int $total the total value of items that are to be done. |
||
913 | * @param string $prefix an optional string to display before the progress bar. |
||
914 | * Default to empty string which results in no prefix to be displayed. |
||
915 | * @param int|bool $width optional width of the progressbar. This can be an integer representing |
||
916 | * the number of characters to display for the progress bar or a float between 0 and 1 representing the |
||
917 | * percentage of screen with the progress bar may take. It can also be set to false to disable the |
||
918 | * bar and only show progress information like percent, number of items and ETA. |
||
919 | * If not set, the bar will be as wide as the screen. Screen size will be detected using [[getScreenSize()]]. |
||
920 | * @see startProgress |
||
921 | * @see updateProgress |
||
922 | * @see endProgress |
||
923 | */ |
||
924 | public static function startProgress($done, $total, $prefix = '', $width = null) |
||
935 | |||
936 | /** |
||
937 | * Updates a progress bar that has been started by [[startProgress()]]. |
||
938 | * |
||
939 | * @param int $done the number of items that are completed. |
||
940 | * @param int $total the total value of items that are to be done. |
||
941 | * @param string $prefix an optional string to display before the progress bar. |
||
942 | * Defaults to null meaning the prefix specified by [[startProgress()]] will be used. |
||
943 | * If prefix is specified it will update the prefix that will be used by later calls. |
||
944 | * @see startProgress |
||
945 | * @see endProgress |
||
946 | */ |
||
947 | public static function updateProgress($done, $total, $prefix = null) |
||
1013 | |||
1014 | /** |
||
1015 | * Ends a progress bar that has been started by [[startProgress()]]. |
||
1016 | * |
||
1017 | * @param string|bool $remove This can be `false` to leave the progress bar on screen and just print a newline. |
||
1018 | * If set to `true`, the line of the progress bar will be cleared. This may also be a string to be displayed instead |
||
1019 | * of the progress bar. |
||
1020 | * @param bool $keepPrefix whether to keep the prefix that has been specified for the progressbar when progressbar |
||
1021 | * gets removed. Defaults to true. |
||
1022 | * @see startProgress |
||
1023 | * @see updateProgress |
||
1024 | */ |
||
1025 | public static function endProgress($remove = false, $keepPrefix = true) |
||
1044 | } |
||
1045 |