mirror of
https://github.com/moodle/moodle.git
synced 2025-01-29 19:50:14 +01:00
MDL-70583 cli: Allow progress bars to be rendered in cli scripts
This commit is contained in:
parent
9dabd071fe
commit
ded82b7f5b
@ -4916,6 +4916,14 @@ class progress_bar implements renderable, templatable {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Getter for ID
|
||||
* @return string id
|
||||
*/
|
||||
public function get_id() : string {
|
||||
return $this->html_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new progress bar, this function will output html.
|
||||
*
|
||||
@ -4925,9 +4933,6 @@ class progress_bar implements renderable, templatable {
|
||||
global $OUTPUT;
|
||||
|
||||
$this->time_start = microtime(true);
|
||||
if (CLI_SCRIPT) {
|
||||
return; // Temporary solution for cli scripts.
|
||||
}
|
||||
|
||||
flush();
|
||||
echo $OUTPUT->render($this);
|
||||
@ -4943,15 +4948,13 @@ class progress_bar implements renderable, templatable {
|
||||
* @throws coding_exception
|
||||
*/
|
||||
private function _update($percent, $msg) {
|
||||
global $OUTPUT;
|
||||
|
||||
if (empty($this->time_start)) {
|
||||
throw new coding_exception('You must call create() (or use the $autostart ' .
|
||||
'argument to the constructor) before you try updating the progress bar.');
|
||||
}
|
||||
|
||||
if (CLI_SCRIPT) {
|
||||
return; // Temporary solution for cli scripts.
|
||||
}
|
||||
|
||||
$estimate = $this->estimate($percent);
|
||||
|
||||
if ($estimate === null) {
|
||||
@ -4965,16 +4968,15 @@ class progress_bar implements renderable, templatable {
|
||||
return;
|
||||
}
|
||||
|
||||
$estimatemsg = null;
|
||||
if (is_numeric($estimate)) {
|
||||
$estimatemsg = get_string('secondsleft', 'moodle', round($estimate, 2));
|
||||
$estimatemsg = '';
|
||||
if ($estimate != 0 && is_numeric($estimate)) {
|
||||
$estimatemsg = format_time(round($estimate));
|
||||
}
|
||||
|
||||
$this->percent = round($percent, 2);
|
||||
$this->percent = $percent;
|
||||
$this->lastupdate = microtime(true);
|
||||
|
||||
echo html_writer::script(js_writer::function_call('updateProgressBar',
|
||||
array($this->html_id, $this->percent, $msg, $estimatemsg)));
|
||||
echo $OUTPUT->render_progress_bar_update($this->html_id, sprintf("%.1f", $this->percent), $msg, $estimatemsg);
|
||||
flush();
|
||||
}
|
||||
|
||||
|
@ -4776,6 +4776,22 @@ EOD;
|
||||
return $this->render_from_template('core/progress_bar', $data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders an update to a progress bar.
|
||||
*
|
||||
* Note: This does not cleanly map to a renderable class and should
|
||||
* never be used directly.
|
||||
*
|
||||
* @param string $id
|
||||
* @param float $percent
|
||||
* @param string $msg Message
|
||||
* @param string $estimate time remaining message
|
||||
* @return string ascii fragment
|
||||
*/
|
||||
public function render_progress_bar_update(string $id, float $percent, string $msg, string $estimate) : string {
|
||||
return html_writer::script(js_writer::function_call('updateProgressBar', [$id, $percent, $msg, $estimate]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders element for a toggle-all checkbox.
|
||||
*
|
||||
@ -4800,6 +4816,12 @@ EOD;
|
||||
*/
|
||||
class core_renderer_cli extends core_renderer {
|
||||
|
||||
/**
|
||||
* @var array $progressmaximums stores the largest percentage for a progress bar.
|
||||
* @return string ascii fragment
|
||||
*/
|
||||
private $progressmaximums = [];
|
||||
|
||||
/**
|
||||
* Returns the page header.
|
||||
*
|
||||
@ -4844,6 +4866,99 @@ class core_renderer_cli extends core_renderer {
|
||||
return $this->render_check_result($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders a progress bar.
|
||||
*
|
||||
* Do not use $OUTPUT->render($bar), instead use progress_bar::create().
|
||||
*
|
||||
* @param progress_bar $bar The bar.
|
||||
* @return string ascii fragment
|
||||
*/
|
||||
public function render_progress_bar(progress_bar $bar) {
|
||||
global $CFG;
|
||||
|
||||
$size = 55; // The width of the progress bar in chars.
|
||||
$ascii = "\n";
|
||||
|
||||
if (stream_isatty(STDOUT)) {
|
||||
require_once($CFG->libdir.'/clilib.php');
|
||||
|
||||
$ascii .= "[" . str_repeat(' ', $size) . "] 0% \n";
|
||||
return cli_ansi_format($ascii);
|
||||
}
|
||||
|
||||
$this->progressmaximums[$bar->get_id()] = 0;
|
||||
$ascii .= '[';
|
||||
return $ascii;
|
||||
}
|
||||
|
||||
/**
|
||||
* Renders an update to a progress bar.
|
||||
*
|
||||
* Note: This does not cleanly map to a renderable class and should
|
||||
* never be used directly.
|
||||
*
|
||||
* @param string $id
|
||||
* @param float $percent
|
||||
* @param string $msg Message
|
||||
* @param string $estimate time remaining message
|
||||
* @return string ascii fragment
|
||||
*/
|
||||
public function render_progress_bar_update(string $id, float $percent, string $msg, string $estimate) : string {
|
||||
$size = 55; // The width of the progress bar in chars.
|
||||
$ascii = '';
|
||||
|
||||
// If we are rendering to a terminal then we can safely use ansii codes
|
||||
// to move the cursor and redraw the complete progress bar each time
|
||||
// it is updated.
|
||||
if (stream_isatty(STDOUT)) {
|
||||
$colour = $percent == 100 ? 'green' : 'blue';
|
||||
|
||||
$done = $percent * $size * 0.01;
|
||||
$whole = floor($done);
|
||||
$bar = "<colour:$colour>";
|
||||
$bar .= str_repeat('█', $whole);
|
||||
|
||||
if ($whole < $size) {
|
||||
// By using unicode chars for partial blocks we can have higher
|
||||
// precision progress bar.
|
||||
$fraction = floor(($done - $whole) * 8);
|
||||
$bar .= core_text::substr(' ▏▎▍▌▋▊▉', $fraction, 1);
|
||||
|
||||
// Fill the rest of the empty bar.
|
||||
$bar .= str_repeat(' ', $size - $whole - 1);
|
||||
}
|
||||
|
||||
$bar .= '<colour:normal>';
|
||||
|
||||
if ($estimate) {
|
||||
$estimate = "- $estimate";
|
||||
}
|
||||
|
||||
$ascii .= '<cursor:up>';
|
||||
$ascii .= '<cursor:up>';
|
||||
$ascii .= sprintf("[$bar] %3.1f%% %-22s\n", $percent, $estimate);
|
||||
$ascii .= sprintf("%-80s\n", $msg);
|
||||
if ($percent == 100) {
|
||||
$ascii .= "\n";
|
||||
}
|
||||
return cli_ansi_format($ascii);
|
||||
}
|
||||
|
||||
// If we are not rendering to a tty, ie when piped to another command
|
||||
// or on windows we need to progressively render the progress bar
|
||||
// which can only ever go forwards.
|
||||
$done = round($percent * $size * 0.01);
|
||||
$delta = max(0, $done - $this->progressmaximums[$id]);
|
||||
$this->progressmaximums[$id] += $delta;
|
||||
|
||||
$ascii .= str_repeat('#', $delta);
|
||||
if ($percent >= 100) {
|
||||
$ascii .= sprintf("] %3.1f%%\n$msg\n", $percent);
|
||||
}
|
||||
return $ascii;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a template fragment representing a Heading.
|
||||
*
|
||||
|
Loading…
x
Reference in New Issue
Block a user