+ − <?php
+ −
+ − /**
+ − * Class for drawing progress bars in a vt100 console.
+ − * @author Dan Fuhry
+ − * @license Public domain
+ − */
+ −
+ − class ProgressBar
+ − {
+ − /**
+ − * Shell escape character.
+ − * @const string
+ − */
+ −
+ − const SHELL_ESCAPE = "\x1B";
+ −
+ − /**
+ − * Carriage return (0x0D)
+ − * @const string
+ − */
+ −
+ − const CARRIAGE_RETURN = "\r";
+ −
+ − /**
+ − * Colors of the foreground, background, foreground text, and background text, respectively
+ − * @var int
+ − * @var int
+ − * @var int
+ − * @var int
+ − */
+ −
+ − private $color_bar, $color_empty, $color_text, $color_emptytext;
+ −
+ − /**
+ − * Text to the left of the bar.
+ − * @var string
+ − */
+ −
+ − private $bar_left;
+ −
+ − /**
+ − * Text to the right of the bar.
+ − * @var string
+ − */
+ −
+ − private $bar_right;
+ −
+ − /**
+ − * Text in the middle of the bar.
+ − * @var string
+ − */
+ −
+ − private $bar_text;
+ −
+ − /**
+ − * The current location of the bar in %.
+ − * @var int
+ − */
+ −
+ − private $bar_pos = 0;
+ −
+ − /**
+ − * Position where the text should start.
+ − * @var int
+ − */
+ −
+ − private $text_pos = 0;
+ −
+ − /**
+ − * Width of the current terminal.
+ − * @var int
+ − */
+ −
+ − private $term_width = 80;
+ −
+ − /**
+ − * Width of the actual bar.
+ − * @var int
+ − */
+ −
+ − private $bar_width = 0;
+ −
+ − /**
+ − * State of the bar's color. Used to avoid echoing tons of color codes.
+ − * @var int
+ − */
+ −
+ − private $color_state = 0;
+ −
+ − /**
+ − * Color state constants
+ − * @const int
+ − * @const int
+ − * @const int
+ − * @const int
+ − * @const int
+ − */
+ −
+ − const COLOR_STATE_RESET = 0;
+ − const COLOR_STATE_FULL_HIDE = 1;
+ − const COLOR_STATE_FULL_SHOW = 2;
+ − const COLOR_STATE_EMPTY_HIDE = 3;
+ − const COLOR_STATE_EMPTY_SHOW = 4;
+ −
+ − /**
+ − * Constructor. All parameters are optional. Color choices are defined in color_to_code.
+ − * @param string $bar_left
+ − * @param string $bar_right
+ − * @param string $bar_text
+ − * @param string $color_bar
+ − * @param string $color_empty
+ − * @param string $color_text
+ − * @param string $color_emptytext
+ − */
+ −
+ − public function __construct($bar_left = '[', $bar_right = ']', $bar_text = '', $color_bar = 'red', $color_empty = 'black', $color_text = 'white', $color_emptytext = 'cyan')
+ − {
+ − $this->bar_left = $bar_left;
+ − $this->bar_right = $bar_right;
+ − $this->color_bar = $this->color_to_code($color_bar);
+ − $this->color_empty = $this->color_to_code($color_empty);
+ − $this->color_text = $this->color_to_code($color_text);
+ − $this->color_emptytext = $this->color_to_code($color_emptytext);
+ −
+ − if ( isset($_SERVER['COLUMNS']) )
+ − {
+ − $this->term_width = intval($_SERVER['COLUMNS']);
+ − }
+ − $this->bar_width = $this->term_width - strlen($this->bar_left) - strlen($this->bar_right);
+ −
+ − $this->update_text_quiet($bar_text);
+ − }
+ −
+ − /**
+ − * Updates the text on the progress bar and recalculates the position without redrawing.
+ − * @param string Text in the bar. If omitted, blanked.
+ − */
+ −
+ − public function update_text_quiet($bar_text = '')
+ − {
+ − $this->bar_text = strval($bar_text);
+ −
+ − if ( !empty($this->bar_text) )
+ − {
+ − $this->text_pos = round(( $this->bar_width / 2 ) - ( strlen($this->bar_text) / 2 ));
+ − }
+ − }
+ −
+ − /**
+ − * Updates the text on the progress bar, recalculates the position, and redraws.
+ − * @param string Text in the bar. If omitted, blanked.
+ − */
+ −
+ − function update_text($bar_text = '')
+ − {
+ − $this->update_text_quiet($bar_text);
+ − $this->set($this->bar_pos);
+ − }
+ −
+ − /**
+ − * Starts output of the bar.
+ − */
+ −
+ − function start()
+ − {
+ − echo self::CARRIAGE_RETURN;
+ − echo $this->bar_left;
+ − }
+ −
+ − /**
+ − * Closes the bar.
+ − */
+ −
+ − function end()
+ − {
+ − $this->set($this->bar_pos, $this->bar_width);
+ − echo "\n";
+ − }
+ −
+ − /**
+ − * Sets the position of the bar.
+ − * @param int Position in %. If a second parameter is set, this is treated as a numerator with the second parameter being the denominator and that is used to calculate position.
+ − * @param int Optional. Total number of units to allow fraction usage instead of percentage.
+ − */
+ −
+ − function set($pos, $max = 100)
+ − {
+ − // if our pos is higher than 100%, reduce it
+ − if ( $pos > $max )
+ − $pos = $max;
+ −
+ − // arithmetic one-liner
+ − // this is where we should stop showing the "full" color and instead use "empty"
+ − $bar_pos = round($this->bar_width * ( $pos / $max ));
+ − $this->bar_pos = 100 * ( $pos / $max );
+ −
+ − // reset the cursor
+ − echo self::CARRIAGE_RETURN . $this->bar_left;
+ −
+ − // print everything out
+ − for ( $i = 0; $i < $this->bar_width; $i++ )
+ − {
+ − $char = ' ';
+ − $hide = true;
+ − if ( !empty($this->bar_text) )
+ − {
+ − // we have some text to display in the middle; see where we are.
+ − $show_text = ( $i >= $this->text_pos && $i < ( $this->text_pos + strlen($this->bar_text) ) );
+ − if ( $show_text )
+ − {
+ − $char = substr($this->bar_text, $i - $this->text_pos, 1);
+ − if ( strlen($char) < 1 )
+ − $char = ' ';
+ − else
+ − $hide = false;
+ − }
+ − }
+ − // determine color
+ − if ( $i > $bar_pos )
+ − {
+ − $hide ? $this->set_color_empty_hide() : $this->set_color_empty_show();
+ − }
+ − else
+ − {
+ − $hide ? $this->set_color_full_hide() : $this->set_color_full_show();
+ − }
+ − echo $char;
+ − }
+ − $this->set_color_reset();
+ − echo $this->bar_right;
+ − }
+ −
+ − #
+ − # PRIVATE METHODS
+ − #
+ −
+ − function set_color_full_hide()
+ − {
+ − if ( $this->color_state == self::COLOR_STATE_FULL_HIDE )
+ − return;
+ − $this->color_state = self::COLOR_STATE_FULL_HIDE;
+ −
+ − $fgcolor = 30 + $this->color_bar;
+ − $bgcolor = $fgcolor + 10;
+ − echo self::SHELL_ESCAPE . "[0;{$fgcolor};{$bgcolor};8m";
+ − }
+ −
+ − function set_color_full_show()
+ − {
+ − if ( $this->color_state == self::COLOR_STATE_FULL_SHOW )
+ − return;
+ − $this->color_state = self::COLOR_STATE_FULL_SHOW;
+ −
+ − $fgcolor = 30 + $this->color_text;
+ − $bgcolor = 40 + $this->color_bar;
+ − echo self::SHELL_ESCAPE . "[0;1;{$fgcolor};{$bgcolor}m";
+ − }
+ −
+ − function set_color_empty_hide()
+ − {
+ − if ( $this->color_state == self::COLOR_STATE_EMPTY_HIDE )
+ − return;
+ − $this->color_state = self::COLOR_STATE_EMPTY_HIDE;
+ −
+ − $fgcolor = 30 + $this->color_empty;
+ − $bgcolor = $fgcolor + 10;
+ − echo self::SHELL_ESCAPE . "[0;{$fgcolor};{$bgcolor};8m";
+ − }
+ −
+ − function set_color_empty_show()
+ − {
+ − if ( $this->color_state == self::COLOR_STATE_EMPTY_SHOW )
+ − return;
+ − $this->color_state = self::COLOR_STATE_EMPTY_SHOW;
+ −
+ − $fgcolor = 30 + $this->color_emptytext;
+ − $bgcolor = 40 + $this->color_empty;
+ − echo self::SHELL_ESCAPE . "[0;1;{$fgcolor};{$bgcolor}m";
+ − }
+ −
+ − function set_color_reset()
+ − {
+ − if ( $this->color_state == self::COLOR_STATE_RESET )
+ − return;
+ − $this->color_state = self::COLOR_STATE_RESET;
+ −
+ − echo self::SHELL_ESCAPE . "[0m";
+ − }
+ −
+ − /**
+ − * Converts a color name to an ASCII color code. Valid color names are black, red, green, yellow, blue, magenta, cyan, and white.
+ − * @param string Color name
+ − * @return int
+ − */
+ −
+ − private function color_to_code($color)
+ − {
+ − static $colors = array(
+ − 'black' => 0,
+ − 'red' => 1,
+ − 'green' => 2,
+ − 'yellow' => 3,
+ − 'blue' => 4,
+ − 'magenta' => 5,
+ − 'cyan' => 6,
+ − 'white' => 7
+ − );
+ − return ( isset($colors[$color]) ) ? $colors[$color] : $colors['white'];
+ − }
+ − }