Merge branch 'MDL-69930-39' of https://github.com/HuongNV13/moodle into MOODLE_39_STABLE
[moodle.git] / lib / clilib.php
blob63b5e4349cae2e44576764b743588addd063e4cd
1 <?php
3 // This file is part of Moodle - http://moodle.org/
4 //
5 // Moodle is free software: you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation, either version 3 of the License, or
8 // (at your option) any later version.
9 //
10 // Moodle is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
15 // You should have received a copy of the GNU General Public License
16 // along with Moodle. If not, see <http://www.gnu.org/licenses/>.
18 /**
19 * Command line utility functions and classes
21 * @package core
22 * @subpackage cli
23 * @copyright 2009 Petr Skoda (http://skodak.org)
24 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
27 // NOTE: no MOODLE_INTERNAL test here, sometimes we use this before requiring Moodle libs!
29 /**
30 * Write a text to the given stream
32 * @param string $text text to be written
33 * @param resource $stream output stream to be written to, defaults to STDOUT
35 function cli_write($text, $stream=STDOUT) {
36 fwrite($stream, $text);
39 /**
40 * Write a text followed by an end of line symbol to the given stream
42 * @param string $text text to be written
43 * @param resource $stream output stream to be written to, defaults to STDOUT
45 function cli_writeln($text, $stream=STDOUT) {
46 cli_write($text.PHP_EOL, $stream);
49 /**
50 * Get input from user
51 * @param string $prompt text prompt, should include possible options
52 * @param string $default default value when enter pressed
53 * @param array $options list of allowed options, empty means any text
54 * @param bool $casesensitive true if options are case sensitive
55 * @return string entered text
57 function cli_input($prompt, $default='', array $options=null, $casesensitiveoptions=false) {
58 cli_writeln($prompt);
59 cli_write(': ');
60 $input = fread(STDIN, 2048);
61 $input = trim($input);
62 if ($input === '') {
63 $input = $default;
65 if ($options) {
66 if (!$casesensitiveoptions) {
67 $input = strtolower($input);
69 if (!in_array($input, $options)) {
70 cli_writeln(get_string('cliincorrectvalueretry', 'admin'));
71 return cli_input($prompt, $default, $options, $casesensitiveoptions);
74 return $input;
77 /**
78 * Returns cli script parameters.
79 * @param array $longoptions array of --style options ex:('verbose'=>false)
80 * @param array $shortmapping array describing mapping of short to long style options ex:('h'=>'help', 'v'=>'verbose')
81 * @return array array of arrays, options, unrecognised as optionlongname=>value
83 function cli_get_params(array $longoptions, array $shortmapping=null) {
84 $shortmapping = (array)$shortmapping;
85 $options = array();
86 $unrecognized = array();
88 if (empty($_SERVER['argv'])) {
89 // bad luck, we can continue in interactive mode ;-)
90 return array($options, $unrecognized);
92 $rawoptions = $_SERVER['argv'];
94 //remove anything after '--', options can not be there
95 if (($key = array_search('--', $rawoptions)) !== false) {
96 $rawoptions = array_slice($rawoptions, 0, $key);
99 //remove script
100 unset($rawoptions[0]);
101 foreach ($rawoptions as $raw) {
102 if (substr($raw, 0, 2) === '--') {
103 $value = substr($raw, 2);
104 $parts = explode('=', $value);
105 if (count($parts) == 1) {
106 $key = reset($parts);
107 $value = true;
108 } else {
109 $key = array_shift($parts);
110 $value = implode('=', $parts);
112 if (array_key_exists($key, $longoptions)) {
113 $options[$key] = $value;
114 } else {
115 $unrecognized[] = $raw;
118 } else if (substr($raw, 0, 1) === '-') {
119 $value = substr($raw, 1);
120 $parts = explode('=', $value);
121 if (count($parts) == 1) {
122 $key = reset($parts);
123 $value = true;
124 } else {
125 $key = array_shift($parts);
126 $value = implode('=', $parts);
128 if (array_key_exists($key, $shortmapping)) {
129 $options[$shortmapping[$key]] = $value;
130 } else {
131 $unrecognized[] = $raw;
133 } else {
134 $unrecognized[] = $raw;
135 continue;
138 //apply defaults
139 foreach ($longoptions as $key=>$default) {
140 if (!array_key_exists($key, $options)) {
141 $options[$key] = $default;
144 // finished
145 return array($options, $unrecognized);
149 * Print or return section separator string
150 * @param bool $return false means print, true return as string
151 * @return mixed void or string
153 function cli_separator($return=false) {
154 $separator = str_repeat('-', 79).PHP_EOL;
155 if ($return) {
156 return $separator;
157 } else {
158 cli_write($separator);
163 * Print or return section heading string
164 * @param string $string text
165 * @param bool $return false means print, true return as string
166 * @return mixed void or string
168 function cli_heading($string, $return=false) {
169 $string = "== $string ==".PHP_EOL;
170 if ($return) {
171 return $string;
172 } else {
173 cli_write($string);
178 * Write error notification
179 * @param $text
180 * @return void
182 function cli_problem($text) {
183 cli_writeln($text, STDERR);
187 * Write to standard error output and exit with the given code
189 * @param string $text
190 * @param int $errorcode
191 * @return void (does not return)
193 function cli_error($text, $errorcode=1) {
194 cli_writeln($text.PHP_EOL, STDERR);
195 die($errorcode);
199 * Print an ASCII version of the Moodle logo.
201 * @param int $padding left padding of the logo
202 * @param bool $return should we print directly (false) or return the string (true)
203 * @return mixed void or string
205 function cli_logo($padding=2, $return=false) {
207 $lines = array(
208 ' .-..-. ',
209 ' _____ | || | ',
210 '/____/-.---_ .---. .---. .-.| || | .---. ',
211 '| | _ _ |/ _ \\/ _ \\/ _ || |/ __ \\',
212 '* | | | | | || |_| || |_| || |_| || || |___/',
213 ' |_| |_| |_|\\_____/\\_____/\\_____||_|\\_____)',
216 $logo = '';
218 foreach ($lines as $line) {
219 $logo .= str_repeat(' ', $padding);
220 $logo .= $line;
221 $logo .= PHP_EOL;
224 if ($return) {
225 return $logo;
226 } else {
227 cli_write($logo);
232 * Substitute cursor, colour, and bell placeholders in a CLI output to ANSI escape characters when ANSI is available.
234 * @param string $message
235 * @return string
237 function cli_ansi_format(string $message): string {
238 global $CFG;
240 $replacements = [
241 "<newline>" => "\n",
242 "<bell>" => "\007",
244 // Cursor movement: https://www.tldp.org/HOWTO/Bash-Prompt-HOWTO/x361.html.
245 "<cursor:save>" => "\033[s",
246 "<cursor:restore>" => "\033[u",
247 "<cursor:up>" => "\033[1A",
248 "<cursor:down>" => "\033[1B",
249 "<cursor:forward>" => "\033[1C",
250 "<cursor:back>" => "\033[1D",
253 $colours = [
254 'normal' => '0;0',
255 'black' => '0;30',
256 'darkGray' => '1;30',
257 'red' => '0;31',
258 'lightRed' => '1;31',
259 'green' => '0;32',
260 'lightGreen' => '1;32',
261 'brown' => '0;33',
262 'yellow' => '1;33',
263 'lightYellow' => '0;93',
264 'blue' => '0;34',
265 'lightBlue' => '1;34',
266 'purple' => '0;35',
267 'lightPurple' => '1;35',
268 'cyan' => '0;36',
269 'lightCyan' => '1;36',
270 'lightGray' => '0;37',
271 'white' => '1;37',
273 $bgcolours = [
274 'black' => '40',
275 'red' => '41',
276 'green' => '42',
277 'yellow' => '43',
278 'blue' => '44',
279 'magenta' => '45',
280 'cyan' => '46',
281 'white' => '47',
284 foreach ($colours as $colour => $code) {
285 $replacements["<colour:{$colour}>"] = "\033[{$code}m";
287 foreach ($bgcolours as $colour => $code) {
288 $replacements["<bgcolour:{$colour}>"] = "\033[{$code}m";
291 // Windows don't support ANSI code by default, but does if ANSICON is available.
292 $isansicon = getenv('ANSICON');
293 if (($CFG->ostype === 'WINDOWS') && empty($isansicon)) {
294 return str_replace(array_keys($replacements), '', $message);
297 return str_replace(array_keys($replacements), array_values($replacements), $message);