2012-03-05 00:02:59 +00:00
< ? php
/*
* This file is part of the Symfony package .
*
* ( c ) Fabien Potencier < fabien @ symfony . com >
*
* For the full copyright and license information , please view the LICENSE
* file that was distributed with this source code .
*/
namespace Symfony\Component\Console\Helper ;
2013-12-23 14:28:30 +00:00
use Symfony\Component\Console\Output\NullOutput ;
2015-09-14 17:17:21 +01:00
use Symfony\Component\Console\Output\ConsoleOutputInterface ;
2012-03-05 00:02:59 +00:00
use Symfony\Component\Console\Output\OutputInterface ;
/**
2012-12-15 15:08:23 +00:00
* The Progress class provides helpers to display progress output .
2012-03-05 00:02:59 +00:00
*
* @ author Chris Jones < leeked @ gmail . com >
2012-09-29 21:11:59 +01:00
* @ author Fabien Potencier < fabien @ symfony . com >
2014-03-01 04:11:27 +00:00
*
2014-12-29 23:26:56 +00:00
* @ deprecated since version 2.5 , to be removed in 3.0
* Use { @ link ProgressBar } instead .
2012-03-05 00:02:59 +00:00
*/
class ProgressHelper extends Helper
{
2014-10-22 19:27:13 +01:00
const FORMAT_QUIET = ' %percent%%' ;
const FORMAT_NORMAL = ' %current%/%max% [%bar%] %percent%%' ;
const FORMAT_VERBOSE = ' %current%/%max% [%bar%] %percent%% Elapsed: %elapsed%' ;
const FORMAT_QUIET_NOMAX = ' %current%' ;
const FORMAT_NORMAL_NOMAX = ' %current% [%bar%]' ;
2012-03-05 00:02:59 +00:00
const FORMAT_VERBOSE_NOMAX = ' %current% [%bar%] Elapsed: %elapsed%' ;
2012-09-29 21:11:59 +01:00
// options
2014-10-22 19:27:13 +01:00
private $barWidth = 28 ;
private $barChar = '=' ;
2012-09-29 21:11:59 +01:00
private $emptyBarChar = '-' ;
private $progressChar = '>' ;
2014-10-22 19:27:13 +01:00
private $format = null ;
private $redrawFreq = 1 ;
2012-03-05 00:02:59 +00:00
2012-12-11 13:31:22 +00:00
private $lastMessagesLength ;
2012-09-29 21:11:59 +01:00
private $barCharOriginal ;
2012-03-05 00:02:59 +00:00
/**
* @ var OutputInterface
*/
private $output ;
/**
2014-12-21 17:00:50 +00:00
* Current step .
2012-03-05 00:02:59 +00:00
*
2014-04-16 11:30:19 +01:00
* @ var int
2012-03-05 00:02:59 +00:00
*/
private $current ;
/**
2014-12-21 17:00:50 +00:00
* Maximum number of steps .
2012-03-05 00:02:59 +00:00
*
2014-04-16 11:30:19 +01:00
* @ var int
2012-03-05 00:02:59 +00:00
*/
private $max ;
/**
2014-12-21 17:00:50 +00:00
* Start time of the progress bar .
2012-03-05 00:02:59 +00:00
*
2014-04-16 11:30:19 +01:00
* @ var int
2012-03-05 00:02:59 +00:00
*/
private $startTime ;
/**
2014-12-21 17:00:50 +00:00
* List of formatting variables .
2012-03-05 00:02:59 +00:00
*
* @ var array
*/
private $defaultFormatVars = array (
'current' ,
'max' ,
'bar' ,
'percent' ,
'elapsed' ,
);
/**
2014-12-21 17:00:50 +00:00
* Available formatting variables .
2012-03-05 00:02:59 +00:00
*
* @ var array
*/
private $formatVars ;
/**
2014-12-21 17:00:50 +00:00
* Stored format part widths ( used for padding ) .
2012-03-05 00:02:59 +00:00
*
* @ var array
*/
private $widths = array (
2013-03-23 07:15:46 +00:00
'current' => 4 ,
2014-10-22 19:27:13 +01:00
'max' => 4 ,
2013-03-23 07:15:46 +00:00
'percent' => 3 ,
'elapsed' => 6 ,
2012-03-05 00:02:59 +00:00
);
/**
2014-12-21 17:00:50 +00:00
* Various time formats .
2012-03-05 00:02:59 +00:00
*
* @ var array
*/
private $timeFormats = array (
array ( 0 , '???' ),
array ( 2 , '1 sec' ),
array ( 59 , 'secs' , 1 ),
array ( 60 , '1 min' ),
array ( 3600 , 'mins' , 60 ),
array ( 5400 , '1 hr' ),
array ( 86400 , 'hrs' , 3600 ),
array ( 129600 , '1 day' ),
array ( 604800 , 'days' , 86400 ),
);
2014-12-01 19:40:50 +00:00
public function __construct ( $triggerDeprecationError = true )
{
if ( $triggerDeprecationError ) {
2015-06-07 07:33:05 +01:00
@ trigger_error ( 'The ' . __CLASS__ . ' class is deprecated since version 2.5 and will be removed in 3.0. Use the Symfony\Component\Console\Helper\ProgressBar class instead.' , E_USER_DEPRECATED );
2014-12-01 19:40:50 +00:00
}
}
2012-09-29 21:11:59 +01:00
/**
* Sets the progress bar width .
*
* @ param int $size The progress bar size
*/
public function setBarWidth ( $size )
{
$this -> barWidth = ( int ) $size ;
}
/**
* Sets the bar character .
*
* @ param string $char A character
*/
public function setBarCharacter ( $char )
{
$this -> barChar = $char ;
}
/**
* Sets the empty bar character .
*
* @ param string $char A character
*/
public function setEmptyBarCharacter ( $char )
{
$this -> emptyBarChar = $char ;
}
/**
* Sets the progress bar character .
*
* @ param string $char A character
*/
2012-09-29 22:20:12 +01:00
public function setProgressCharacter ( $char )
2012-09-29 21:11:59 +01:00
{
$this -> progressChar = $char ;
}
/**
* Sets the progress bar format .
*
* @ param string $format The format
*/
public function setFormat ( $format )
{
$this -> format = $format ;
}
/**
* Sets the redraw frequency .
*
2013-07-08 15:24:02 +01:00
* @ param int $freq The frequency in steps
2012-09-29 21:11:59 +01:00
*/
public function setRedrawFrequency ( $freq )
{
$this -> redrawFreq = ( int ) $freq ;
}
2012-03-05 00:02:59 +00:00
/**
* Starts the progress output .
*
2013-03-08 10:24:33 +00:00
* @ param OutputInterface $output An Output instance
2014-04-16 07:51:57 +01:00
* @ param int | null $max Maximum steps
2012-03-05 00:02:59 +00:00
*/
2012-09-29 21:11:59 +01:00
public function start ( OutputInterface $output , $max = null )
2012-03-05 00:02:59 +00:00
{
2015-09-14 17:17:21 +01:00
if ( $output instanceof ConsoleOutputInterface ) {
$output = $output -> getErrorOutput ();
}
2012-03-05 00:02:59 +00:00
$this -> startTime = time ();
2014-10-22 19:27:13 +01:00
$this -> current = 0 ;
$this -> max = ( int ) $max ;
2013-12-23 14:28:30 +00:00
// Disabling output when it does not support ANSI codes as it would result in a broken display anyway.
2014-10-26 07:41:27 +00:00
$this -> output = $output -> isDecorated () ? $output : new NullOutput ();
2013-06-12 15:52:32 +01:00
$this -> lastMessagesLength = 0 ;
$this -> barCharOriginal = '' ;
2012-03-05 00:02:59 +00:00
2012-09-29 22:20:12 +01:00
if ( null === $this -> format ) {
switch ( $output -> getVerbosity ()) {
case OutputInterface :: VERBOSITY_QUIET :
$this -> format = self :: FORMAT_QUIET_NOMAX ;
if ( $this -> max > 0 ) {
$this -> format = self :: FORMAT_QUIET ;
}
break ;
case OutputInterface :: VERBOSITY_VERBOSE :
2013-04-25 11:13:01 +01:00
case OutputInterface :: VERBOSITY_VERY_VERBOSE :
case OutputInterface :: VERBOSITY_DEBUG :
2012-09-29 22:20:12 +01:00
$this -> format = self :: FORMAT_VERBOSE_NOMAX ;
if ( $this -> max > 0 ) {
$this -> format = self :: FORMAT_VERBOSE ;
}
break ;
default :
2012-09-30 15:27:49 +01:00
$this -> format = self :: FORMAT_NORMAL_NOMAX ;
2012-09-29 22:20:12 +01:00
if ( $this -> max > 0 ) {
$this -> format = self :: FORMAT_NORMAL ;
}
break ;
}
2012-03-05 00:02:59 +00:00
}
2012-09-29 22:20:12 +01:00
$this -> initialize ();
2012-03-05 00:02:59 +00:00
}
/**
* Advances the progress output X steps .
*
2014-11-30 13:33:44 +00:00
* @ param int $step Number of steps to advance
* @ param bool $redraw Whether to redraw or not
2012-12-16 12:02:54 +00:00
*
* @ throws \LogicException
2012-03-05 00:02:59 +00:00
*/
public function advance ( $step = 1 , $redraw = false )
{
2013-11-09 16:01:12 +00:00
$this -> setCurrent ( $this -> current + $step , $redraw );
2012-03-05 00:02:59 +00:00
}
2013-03-08 10:24:33 +00:00
/**
* Sets the current progress .
*
2014-11-30 13:33:44 +00:00
* @ param int $current The current progress
* @ param bool $redraw Whether to redraw or not
2013-03-08 10:24:33 +00:00
*
* @ throws \LogicException
*/
public function setCurrent ( $current , $redraw = false )
{
if ( null === $this -> startTime ) {
throw new \LogicException ( 'You must start the progress bar before calling setCurrent().' );
}
$current = ( int ) $current ;
if ( $current < $this -> current ) {
throw new \LogicException ( 'You can\'t regress the progress bar' );
}
2013-03-23 07:15:46 +00:00
if ( 0 === $this -> current ) {
2013-03-08 10:24:33 +00:00
$redraw = true ;
}
2015-03-07 19:12:23 +00:00
$prevPeriod = ( int ) ( $this -> current / $this -> redrawFreq );
2013-10-30 13:45:24 +00:00
2013-03-08 10:24:33 +00:00
$this -> current = $current ;
2013-11-22 17:29:47 +00:00
2015-03-07 19:12:23 +00:00
$currPeriod = ( int ) ( $this -> current / $this -> redrawFreq );
2013-10-30 13:45:24 +00:00
if ( $redraw || $prevPeriod !== $currPeriod || $this -> max === $this -> current ) {
2013-03-08 10:24:33 +00:00
$this -> display ();
}
}
2012-03-05 00:02:59 +00:00
/**
* Outputs the current progress string .
*
2014-11-30 13:33:44 +00:00
* @ param bool $finish Forces the end result
2012-12-16 12:02:54 +00:00
*
* @ throws \LogicException
2012-03-05 00:02:59 +00:00
*/
public function display ( $finish = false )
{
2012-09-29 21:11:59 +01:00
if ( null === $this -> startTime ) {
throw new \LogicException ( 'You must start the progress bar before calling display().' );
}
$message = $this -> format ;
2012-03-05 00:02:59 +00:00
foreach ( $this -> generate ( $finish ) as $name => $value ) {
$message = str_replace ( " % { $name } % " , $value , $message );
}
$this -> overwrite ( $this -> output , $message );
}
2013-05-17 08:15:24 +01:00
/**
* Removes the progress bar from the current line .
*
* This is useful if you wish to write some output
* while a progress bar is running .
* Call display () to show the progress bar again .
*/
public function clear ()
{
$this -> overwrite ( $this -> output , '' );
}
2012-03-05 00:02:59 +00:00
/**
2012-09-29 21:11:59 +01:00
* Finishes the progress output .
2012-03-05 00:02:59 +00:00
*/
public function finish ()
{
2012-09-29 21:11:59 +01:00
if ( null === $this -> startTime ) {
throw new \LogicException ( 'You must start the progress bar before calling finish().' );
}
2013-03-23 07:15:46 +00:00
if ( null !== $this -> startTime ) {
2012-03-05 00:02:59 +00:00
if ( ! $this -> max ) {
2012-09-29 21:11:59 +01:00
$this -> barChar = $this -> barCharOriginal ;
2012-03-05 00:02:59 +00:00
$this -> display ( true );
}
$this -> startTime = null ;
$this -> output -> writeln ( '' );
$this -> output = null ;
}
}
/**
2012-09-29 21:11:59 +01:00
* Initializes the progress helper .
2012-03-05 00:02:59 +00:00
*/
2012-09-29 22:20:12 +01:00
private function initialize ()
2012-03-05 00:02:59 +00:00
{
$this -> formatVars = array ();
foreach ( $this -> defaultFormatVars as $var ) {
2013-03-23 07:15:46 +00:00
if ( false !== strpos ( $this -> format , " % { $var } % " )) {
2012-03-05 00:02:59 +00:00
$this -> formatVars [ $var ] = true ;
}
}
if ( $this -> max > 0 ) {
2014-10-22 19:27:13 +01:00
$this -> widths [ 'max' ] = $this -> strlen ( $this -> max );
2012-03-05 00:02:59 +00:00
$this -> widths [ 'current' ] = $this -> widths [ 'max' ];
} else {
2012-09-29 21:11:59 +01:00
$this -> barCharOriginal = $this -> barChar ;
2014-10-22 19:27:13 +01:00
$this -> barChar = $this -> emptyBarChar ;
2012-03-05 00:02:59 +00:00
}
}
/**
* Generates the array map of format variables to values .
*
2014-11-30 13:33:44 +00:00
* @ param bool $finish Forces the end result
2012-10-08 16:17:46 +01:00
*
2012-03-05 00:02:59 +00:00
* @ return array Array of format vars and values
*/
2012-09-29 21:11:59 +01:00
private function generate ( $finish = false )
2012-03-05 00:02:59 +00:00
{
2014-10-22 19:27:13 +01:00
$vars = array ();
2012-03-05 00:02:59 +00:00
$percent = 0 ;
if ( $this -> max > 0 ) {
2014-02-11 07:51:18 +00:00
$percent = ( float ) $this -> current / $this -> max ;
2012-03-05 00:02:59 +00:00
}
if ( isset ( $this -> formatVars [ 'bar' ])) {
if ( $this -> max > 0 ) {
2012-09-29 21:11:59 +01:00
$completeBars = floor ( $percent * $this -> barWidth );
2012-03-05 00:02:59 +00:00
} else {
if ( ! $finish ) {
2012-09-29 21:11:59 +01:00
$completeBars = floor ( $this -> current % $this -> barWidth );
2012-03-05 00:02:59 +00:00
} else {
2012-09-29 21:11:59 +01:00
$completeBars = $this -> barWidth ;
2012-03-05 00:02:59 +00:00
}
}
2012-12-15 15:08:23 +00:00
$emptyBars = $this -> barWidth - $completeBars - $this -> strlen ( $this -> progressChar );
2012-09-29 21:11:59 +01:00
$bar = str_repeat ( $this -> barChar , $completeBars );
if ( $completeBars < $this -> barWidth ) {
$bar .= $this -> progressChar ;
$bar .= str_repeat ( $this -> emptyBarChar , $emptyBars );
2012-03-05 00:02:59 +00:00
}
$vars [ 'bar' ] = $bar ;
}
if ( isset ( $this -> formatVars [ 'elapsed' ])) {
$elapsed = time () - $this -> startTime ;
$vars [ 'elapsed' ] = str_pad ( $this -> humaneTime ( $elapsed ), $this -> widths [ 'elapsed' ], ' ' , STR_PAD_LEFT );
}
if ( isset ( $this -> formatVars [ 'current' ])) {
$vars [ 'current' ] = str_pad ( $this -> current , $this -> widths [ 'current' ], ' ' , STR_PAD_LEFT );
}
if ( isset ( $this -> formatVars [ 'max' ])) {
$vars [ 'max' ] = $this -> max ;
}
if ( isset ( $this -> formatVars [ 'percent' ])) {
2013-07-08 15:34:53 +01:00
$vars [ 'percent' ] = str_pad ( floor ( $percent * 100 ), $this -> widths [ 'percent' ], ' ' , STR_PAD_LEFT );
2012-03-05 00:02:59 +00:00
}
return $vars ;
}
/**
* Converts seconds into human - readable format .
*
2014-11-30 13:33:44 +00:00
* @ param int $secs Number of seconds
2012-10-08 16:17:46 +01:00
*
2012-03-05 00:02:59 +00:00
* @ return string Time in readable format
*/
private function humaneTime ( $secs )
{
$text = '' ;
foreach ( $this -> timeFormats as $format ) {
if ( $secs < $format [ 0 ]) {
if ( count ( $format ) == 2 ) {
$text = $format [ 1 ];
break ;
} else {
2013-04-02 10:39:57 +01:00
$text = ceil ( $secs / $format [ 2 ]) . ' ' . $format [ 1 ];
2012-03-05 00:02:59 +00:00
break ;
}
}
}
2012-10-08 16:17:46 +01:00
2012-03-05 00:02:59 +00:00
return $text ;
}
/**
* Overwrites a previous message to the output .
*
2014-11-30 13:33:44 +00:00
* @ param OutputInterface $output An Output instance
* @ param string $message The message
2012-03-05 00:02:59 +00:00
*/
2013-03-08 10:24:33 +00:00
private function overwrite ( OutputInterface $output , $message )
2012-03-05 00:02:59 +00:00
{
2012-12-15 15:08:23 +00:00
$length = $this -> strlen ( $message );
2013-03-08 10:24:33 +00:00
// append whitespace to match the last line's length
2013-03-23 07:15:46 +00:00
if ( null !== $this -> lastMessagesLength && $this -> lastMessagesLength > $length ) {
2013-03-08 10:24:33 +00:00
$message = str_pad ( $message , $this -> lastMessagesLength , " \x20 " , STR_PAD_RIGHT );
}
2012-12-11 14:06:57 +00:00
// carriage return
$output -> write ( " \x0D " );
2013-03-08 10:24:33 +00:00
$output -> write ( $message );
2012-12-15 15:08:23 +00:00
$this -> lastMessagesLength = $this -> strlen ( $message );
2012-03-05 00:02:59 +00:00
}
/**
2014-04-15 06:57:34 +01:00
* { @ inheritdoc }
2012-03-05 00:02:59 +00:00
*/
public function getName ()
{
return 'progress' ;
}
}