Overview

Namespaces

  • Contrib
    • Bundle
      • CoverallsBundle
        • Console
        • Entity
      • CoverallsV1Bundle
        • Api
        • Collector
        • Command
        • Config
        • Entity
          • Git
    • Component
      • File
      • Log
      • System
        • Git
  • Guzzle
    • Batch
      • Exception
    • Cache
    • Common
      • Exception
    • Http
      • Curl
      • Exception
      • Message
      • QueryAggregator
    • Inflection
    • Iterator
    • Log
    • Parser
      • Cookie
      • Message
      • UriTemplate
      • Url
    • Plugin
      • Async
      • Backoff
      • Cache
      • Cookie
        • CookieJar
        • Exception
      • CurlAuth
      • ErrorResponse
        • Exception
      • History
      • Log
      • Md5
      • Mock
      • Oauth
    • Service
      • Builder
      • Command
        • Factory
        • LocationVisitor
          • Request
          • Response
      • Description
      • Exception
      • Resource
    • Stream
  • PHP
  • Psr
    • Log
  • Symfony
    • Component
      • Config
        • Definition
          • Builder
          • Exception
        • Exception
        • Loader
        • Resource
        • Util
      • Console
        • Command
        • Formatter
        • Helper
        • Input
        • Output
        • Tester
      • EventDispatcher
        • Debug
      • Finder
        • Adapter
        • Comparator
        • Exception
        • Expression
        • Iterator
        • Shell
      • Stopwatch
      • Yaml
        • Exception

Classes

  • DialogHelper
  • FormatterHelper
  • Helper
  • HelperSet
  • ProgressHelper

Interfaces

  • HelperInterface
  • Overview
  • Namespace
  • Class
  • Tree
  • Todo
  1: <?php
  2: 
  3: /*
  4:  * This file is part of the Symfony package.
  5:  *
  6:  * (c) Fabien Potencier <fabien@symfony.com>
  7:  *
  8:  * For the full copyright and license information, please view the LICENSE
  9:  * file that was distributed with this source code.
 10:  */
 11: 
 12: namespace Symfony\Component\Console\Helper;
 13: 
 14: use Symfony\Component\Console\Output\OutputInterface;
 15: 
 16: /**
 17:  * The Progress class providers helpers to display progress output.
 18:  *
 19:  * @author Chris Jones <leeked@gmail.com>
 20:  * @author Fabien Potencier <fabien@symfony.com>
 21:  */
 22: class ProgressHelper extends Helper
 23: {
 24:     const FORMAT_QUIET         = ' %percent%%';
 25:     const FORMAT_NORMAL        = ' %current%/%max% [%bar%] %percent%%';
 26:     const FORMAT_VERBOSE       = ' %current%/%max% [%bar%] %percent%% Elapsed: %elapsed%';
 27:     const FORMAT_QUIET_NOMAX   = ' %current%';
 28:     const FORMAT_NORMAL_NOMAX  = ' %current% [%bar%]';
 29:     const FORMAT_VERBOSE_NOMAX = ' %current% [%bar%] Elapsed: %elapsed%';
 30: 
 31:     // options
 32:     private $barWidth     = 28;
 33:     private $barChar      = '=';
 34:     private $emptyBarChar = '-';
 35:     private $progressChar = '>';
 36:     private $format       = null;
 37:     private $redrawFreq   = 1;
 38: 
 39:     private $lastMessagesLength;
 40:     private $barCharOriginal;
 41: 
 42:     /**
 43:      * @var OutputInterface
 44:      */
 45:     private $output;
 46: 
 47:     /**
 48:      * Current step
 49:      *
 50:      * @var integer
 51:      */
 52:     private $current;
 53: 
 54:     /**
 55:      * Maximum number of steps
 56:      *
 57:      * @var integer
 58:      */
 59:     private $max;
 60: 
 61:     /**
 62:      * Start time of the progress bar
 63:      *
 64:      * @var integer
 65:      */
 66:     private $startTime;
 67: 
 68:     /**
 69:      * List of formatting variables
 70:      *
 71:      * @var array
 72:      */
 73:     private $defaultFormatVars = array(
 74:         'current',
 75:         'max',
 76:         'bar',
 77:         'percent',
 78:         'elapsed',
 79:     );
 80: 
 81:     /**
 82:      * Available formatting variables
 83:      *
 84:      * @var array
 85:      */
 86:     private $formatVars;
 87: 
 88:     /**
 89:      * Stored format part widths (used for padding)
 90:      *
 91:      * @var array
 92:      */
 93:     private $widths = array(
 94:         'current'   => 4,
 95:         'max'       => 4,
 96:         'percent'   => 3,
 97:         'elapsed'   => 6,
 98:     );
 99: 
100:     /**
101:      * Various time formats
102:      *
103:      * @var array
104:      */
105:     private $timeFormats = array(
106:         array(0, '???'),
107:         array(2, '1 sec'),
108:         array(59, 'secs', 1),
109:         array(60, '1 min'),
110:         array(3600, 'mins', 60),
111:         array(5400, '1 hr'),
112:         array(86400, 'hrs', 3600),
113:         array(129600, '1 day'),
114:         array(604800, 'days', 86400),
115:     );
116: 
117:     /**
118:      * Sets the progress bar width.
119:      *
120:      * @param int $size The progress bar size
121:      */
122:     public function setBarWidth($size)
123:     {
124:         $this->barWidth = (int) $size;
125:     }
126: 
127:     /**
128:      * Sets the bar character.
129:      *
130:      * @param string $char A character
131:      */
132:     public function setBarCharacter($char)
133:     {
134:         $this->barChar = $char;
135:     }
136: 
137:     /**
138:      * Sets the empty bar character.
139:      *
140:      * @param string $char A character
141:      */
142:     public function setEmptyBarCharacter($char)
143:     {
144:         $this->emptyBarChar = $char;
145:     }
146: 
147:     /**
148:      * Sets the progress bar character.
149:      *
150:      * @param string $char A character
151:      */
152:     public function setProgressCharacter($char)
153:     {
154:         $this->progressChar = $char;
155:     }
156: 
157:     /**
158:      * Sets the progress bar format.
159:      *
160:      * @param string $format The format
161:      */
162:     public function setFormat($format)
163:     {
164:         $this->format = $format;
165:     }
166: 
167:     /**
168:      * Sets the redraw frequency.
169:      *
170:      * @param int $freq The frequency in seconds
171:      */
172:     public function setRedrawFrequency($freq)
173:     {
174:         $this->redrawFreq = (int) $freq;
175:     }
176: 
177:     /**
178:      * Starts the progress output.
179:      *
180:      * @param OutputInterface $output  An Output instance
181:      * @param integer         $max     Maximum steps
182:      */
183:     public function start(OutputInterface $output, $max = null)
184:     {
185:         $this->startTime = time();
186:         $this->current   = 0;
187:         $this->max       = (int) $max;
188:         $this->output    = $output;
189: 
190:         if (null === $this->format) {
191:             switch ($output->getVerbosity()) {
192:                 case OutputInterface::VERBOSITY_QUIET:
193:                     $this->format = self::FORMAT_QUIET_NOMAX;
194:                     if ($this->max > 0) {
195:                         $this->format = self::FORMAT_QUIET;
196:                     }
197:                     break;
198:                 case OutputInterface::VERBOSITY_VERBOSE:
199:                     $this->format = self::FORMAT_VERBOSE_NOMAX;
200:                     if ($this->max > 0) {
201:                         $this->format = self::FORMAT_VERBOSE;
202:                     }
203:                     break;
204:                 default:
205:                     $this->format = self::FORMAT_NORMAL_NOMAX;
206:                     if ($this->max > 0) {
207:                         $this->format = self::FORMAT_NORMAL;
208:                     }
209:                     break;
210:             }
211:         }
212: 
213:         $this->initialize();
214:     }
215: 
216:     /**
217:      * Advances the progress output X steps.
218:      *
219:      * @param integer $step   Number of steps to advance
220:      * @param Boolean $redraw Whether to redraw or not
221:      *
222:      * @throws \LogicException
223:      */
224:     public function advance($step = 1, $redraw = false)
225:     {
226:         if (null === $this->startTime) {
227:             throw new \LogicException('You must start the progress bar before calling advance().');
228:         }
229: 
230:         if ($this->current === 0) {
231:             $redraw = true;
232:         }
233:         $this->current += $step;
234:         if ($redraw || $this->current % $this->redrawFreq === 0) {
235:             $this->display();
236:         }
237:     }
238: 
239:     /**
240:      * Outputs the current progress string.
241:      *
242:      * @param Boolean $finish Forces the end result
243:      *
244:      * @throws \LogicException
245:      */
246:     public function display($finish = false)
247:     {
248:         if (null === $this->startTime) {
249:             throw new \LogicException('You must start the progress bar before calling display().');
250:         }
251: 
252:         $message = $this->format;
253:         foreach ($this->generate($finish) as $name => $value) {
254:             $message = str_replace("%{$name}%", $value, $message);
255:         }
256:         $this->overwrite($this->output, $message);
257:     }
258: 
259:     /**
260:      * Finishes the progress output.
261:      */
262:     public function finish()
263:     {
264:         if (null === $this->startTime) {
265:             throw new \LogicException('You must start the progress bar before calling finish().');
266:         }
267: 
268:         if ($this->startTime !== null) {
269:             if (!$this->max) {
270:                 $this->barChar = $this->barCharOriginal;
271:                 $this->display(true);
272:             }
273:             $this->startTime = null;
274:             $this->output->writeln('');
275:             $this->output = null;
276:         }
277:     }
278: 
279:     /**
280:      * Initializes the progress helper.
281:      */
282:     private function initialize()
283:     {
284:         $this->formatVars = array();
285:         foreach ($this->defaultFormatVars as $var) {
286:             if (strpos($this->format, "%{$var}%") !== false) {
287:                 $this->formatVars[$var] = true;
288:             }
289:         }
290: 
291:         if ($this->max > 0) {
292:             $this->widths['max']     = strlen($this->max);
293:             $this->widths['current'] = $this->widths['max'];
294:         } else {
295:             $this->barCharOriginal = $this->barChar;
296:             $this->barChar         = $this->emptyBarChar;
297:         }
298:     }
299: 
300:     /**
301:      * Generates the array map of format variables to values.
302:      *
303:      * @param Boolean $finish Forces the end result
304:      *
305:      * @return array Array of format vars and values
306:      */
307:     private function generate($finish = false)
308:     {
309:         $vars    = array();
310:         $percent = 0;
311:         if ($this->max > 0) {
312:             $percent = (double) round($this->current / $this->max, 2);
313:         }
314: 
315:         if (isset($this->formatVars['bar'])) {
316:             $completeBars = 0;
317:             $emptyBars    = 0;
318:             if ($this->max > 0) {
319:                 $completeBars = floor($percent * $this->barWidth);
320:             } else {
321:                 if (!$finish) {
322:                     $completeBars = floor($this->current % $this->barWidth);
323:                 } else {
324:                     $completeBars = $this->barWidth;
325:                 }
326:             }
327: 
328:             $emptyBars = $this->barWidth - $completeBars - strlen($this->progressChar);
329:             $bar = str_repeat($this->barChar, $completeBars);
330:             if ($completeBars < $this->barWidth) {
331:                 $bar .= $this->progressChar;
332:                 $bar .= str_repeat($this->emptyBarChar, $emptyBars);
333:             }
334: 
335:             $vars['bar'] = $bar;
336:         }
337: 
338:         if (isset($this->formatVars['elapsed'])) {
339:             $elapsed = time() - $this->startTime;
340:             $vars['elapsed'] = str_pad($this->humaneTime($elapsed), $this->widths['elapsed'], ' ', STR_PAD_LEFT);
341:         }
342: 
343:         if (isset($this->formatVars['current'])) {
344:             $vars['current'] = str_pad($this->current, $this->widths['current'], ' ', STR_PAD_LEFT);
345:         }
346: 
347:         if (isset($this->formatVars['max'])) {
348:             $vars['max'] = $this->max;
349:         }
350: 
351:         if (isset($this->formatVars['percent'])) {
352:             $vars['percent'] = str_pad($percent * 100, $this->widths['percent'], ' ', STR_PAD_LEFT);
353:         }
354: 
355:         return $vars;
356:     }
357: 
358:     /**
359:      * Converts seconds into human-readable format.
360:      *
361:      * @param integer $secs Number of seconds
362:      *
363:      * @return string Time in readable format
364:      */
365:     private function humaneTime($secs)
366:     {
367:         $text = '';
368:         foreach ($this->timeFormats as $format) {
369:             if ($secs < $format[0]) {
370:                 if (count($format) == 2) {
371:                     $text = $format[1];
372:                     break;
373:                 } else {
374:                     $text = ceil($secs / $format[2]) . ' ' . $format[1];
375:                     break;
376:                 }
377:             }
378:         }
379: 
380:         return $text;
381:     }
382: 
383:     /**
384:      * Overwrites a previous message to the output.
385:      *
386:      * @param OutputInterface $output   An Output instance
387:      * @param string|array    $messages The message as an array of lines or a single string
388:      */
389:     private function overwrite(OutputInterface $output, $messages)
390:     {
391:         // carriage return
392:         $output->write("\x0D");
393:         if ($this->lastMessagesLength!==null) {
394:             // clear the line with the length of the last message
395:             $output->write(str_repeat("\x20", $this->lastMessagesLength));
396:             // carriage return
397:             $output->write("\x0D");
398:         }
399:         $output->write($messages);
400: 
401:         $this->lastMessagesLength=strlen($messages);
402:     }
403: 
404:     /**
405:      * {@inheritDoc}
406:      */
407:     public function getName()
408:     {
409:         return 'progress';
410:     }
411: }
412: 
php-coveralls API documentation generated by ApiGen 2.8.0