Yaffs site version 1.1
[yaffs-website] / vendor / symfony / console / Helper / ProgressHelper.php
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\NullOutput;
15 use Symfony\Component\Console\Output\ConsoleOutputInterface;
16 use Symfony\Component\Console\Output\OutputInterface;
17 use Symfony\Component\Console\Exception\LogicException;
18
19 /**
20  * The Progress class provides helpers to display progress output.
21  *
22  * @author Chris Jones <leeked@gmail.com>
23  * @author Fabien Potencier <fabien@symfony.com>
24  *
25  * @deprecated since version 2.5, to be removed in 3.0
26  *             Use {@link ProgressBar} instead.
27  */
28 class ProgressHelper extends Helper
29 {
30     const FORMAT_QUIET = ' %percent%%';
31     const FORMAT_NORMAL = ' %current%/%max% [%bar%] %percent%%';
32     const FORMAT_VERBOSE = ' %current%/%max% [%bar%] %percent%% Elapsed: %elapsed%';
33     const FORMAT_QUIET_NOMAX = ' %current%';
34     const FORMAT_NORMAL_NOMAX = ' %current% [%bar%]';
35     const FORMAT_VERBOSE_NOMAX = ' %current% [%bar%] Elapsed: %elapsed%';
36
37     // options
38     private $barWidth = 28;
39     private $barChar = '=';
40     private $emptyBarChar = '-';
41     private $progressChar = '>';
42     private $format = null;
43     private $redrawFreq = 1;
44
45     private $lastMessagesLength;
46     private $barCharOriginal;
47
48     /**
49      * @var OutputInterface
50      */
51     private $output;
52
53     /**
54      * Current step.
55      *
56      * @var int
57      */
58     private $current;
59
60     /**
61      * Maximum number of steps.
62      *
63      * @var int
64      */
65     private $max;
66
67     /**
68      * Start time of the progress bar.
69      *
70      * @var int
71      */
72     private $startTime;
73
74     /**
75      * List of formatting variables.
76      *
77      * @var array
78      */
79     private $defaultFormatVars = array(
80         'current',
81         'max',
82         'bar',
83         'percent',
84         'elapsed',
85     );
86
87     /**
88      * Available formatting variables.
89      *
90      * @var array
91      */
92     private $formatVars;
93
94     /**
95      * Stored format part widths (used for padding).
96      *
97      * @var array
98      */
99     private $widths = array(
100         'current' => 4,
101         'max' => 4,
102         'percent' => 3,
103         'elapsed' => 6,
104     );
105
106     /**
107      * Various time formats.
108      *
109      * @var array
110      */
111     private $timeFormats = array(
112         array(0, '???'),
113         array(2, '1 sec'),
114         array(59, 'secs', 1),
115         array(60, '1 min'),
116         array(3600, 'mins', 60),
117         array(5400, '1 hr'),
118         array(86400, 'hrs', 3600),
119         array(129600, '1 day'),
120         array(604800, 'days', 86400),
121     );
122
123     public function __construct($triggerDeprecationError = true)
124     {
125         if ($triggerDeprecationError) {
126             @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);
127         }
128     }
129
130     /**
131      * Sets the progress bar width.
132      *
133      * @param int $size The progress bar size
134      */
135     public function setBarWidth($size)
136     {
137         $this->barWidth = (int) $size;
138     }
139
140     /**
141      * Sets the bar character.
142      *
143      * @param string $char A character
144      */
145     public function setBarCharacter($char)
146     {
147         $this->barChar = $char;
148     }
149
150     /**
151      * Sets the empty bar character.
152      *
153      * @param string $char A character
154      */
155     public function setEmptyBarCharacter($char)
156     {
157         $this->emptyBarChar = $char;
158     }
159
160     /**
161      * Sets the progress bar character.
162      *
163      * @param string $char A character
164      */
165     public function setProgressCharacter($char)
166     {
167         $this->progressChar = $char;
168     }
169
170     /**
171      * Sets the progress bar format.
172      *
173      * @param string $format The format
174      */
175     public function setFormat($format)
176     {
177         $this->format = $format;
178     }
179
180     /**
181      * Sets the redraw frequency.
182      *
183      * @param int $freq The frequency in steps
184      */
185     public function setRedrawFrequency($freq)
186     {
187         $this->redrawFreq = (int) $freq;
188     }
189
190     /**
191      * Starts the progress output.
192      *
193      * @param OutputInterface $output An Output instance
194      * @param int|null        $max    Maximum steps
195      */
196     public function start(OutputInterface $output, $max = null)
197     {
198         if ($output instanceof ConsoleOutputInterface) {
199             $output = $output->getErrorOutput();
200         }
201
202         $this->startTime = time();
203         $this->current = 0;
204         $this->max = (int) $max;
205
206         // Disabling output when it does not support ANSI codes as it would result in a broken display anyway.
207         $this->output = $output->isDecorated() ? $output : new NullOutput();
208         $this->lastMessagesLength = 0;
209         $this->barCharOriginal = '';
210
211         if (null === $this->format) {
212             switch ($output->getVerbosity()) {
213                 case OutputInterface::VERBOSITY_QUIET:
214                     $this->format = self::FORMAT_QUIET_NOMAX;
215                     if ($this->max > 0) {
216                         $this->format = self::FORMAT_QUIET;
217                     }
218                     break;
219                 case OutputInterface::VERBOSITY_VERBOSE:
220                 case OutputInterface::VERBOSITY_VERY_VERBOSE:
221                 case OutputInterface::VERBOSITY_DEBUG:
222                     $this->format = self::FORMAT_VERBOSE_NOMAX;
223                     if ($this->max > 0) {
224                         $this->format = self::FORMAT_VERBOSE;
225                     }
226                     break;
227                 default:
228                     $this->format = self::FORMAT_NORMAL_NOMAX;
229                     if ($this->max > 0) {
230                         $this->format = self::FORMAT_NORMAL;
231                     }
232                     break;
233             }
234         }
235
236         $this->initialize();
237     }
238
239     /**
240      * Advances the progress output X steps.
241      *
242      * @param int  $step   Number of steps to advance
243      * @param bool $redraw Whether to redraw or not
244      *
245      * @throws LogicException
246      */
247     public function advance($step = 1, $redraw = false)
248     {
249         $this->setCurrent($this->current + $step, $redraw);
250     }
251
252     /**
253      * Sets the current progress.
254      *
255      * @param int  $current The current progress
256      * @param bool $redraw  Whether to redraw or not
257      *
258      * @throws LogicException
259      */
260     public function setCurrent($current, $redraw = false)
261     {
262         if (null === $this->startTime) {
263             throw new LogicException('You must start the progress bar before calling setCurrent().');
264         }
265
266         $current = (int) $current;
267
268         if ($current < $this->current) {
269             throw new LogicException('You can\'t regress the progress bar');
270         }
271
272         if (0 === $this->current) {
273             $redraw = true;
274         }
275
276         $prevPeriod = (int) ($this->current / $this->redrawFreq);
277
278         $this->current = $current;
279
280         $currPeriod = (int) ($this->current / $this->redrawFreq);
281         if ($redraw || $prevPeriod !== $currPeriod || $this->max === $this->current) {
282             $this->display();
283         }
284     }
285
286     /**
287      * Outputs the current progress string.
288      *
289      * @param bool $finish Forces the end result
290      *
291      * @throws LogicException
292      */
293     public function display($finish = false)
294     {
295         if (null === $this->startTime) {
296             throw new LogicException('You must start the progress bar before calling display().');
297         }
298
299         $message = $this->format;
300         foreach ($this->generate($finish) as $name => $value) {
301             $message = str_replace("%{$name}%", $value, $message);
302         }
303         $this->overwrite($this->output, $message);
304     }
305
306     /**
307      * Removes the progress bar from the current line.
308      *
309      * This is useful if you wish to write some output
310      * while a progress bar is running.
311      * Call display() to show the progress bar again.
312      */
313     public function clear()
314     {
315         $this->overwrite($this->output, '');
316     }
317
318     /**
319      * Finishes the progress output.
320      */
321     public function finish()
322     {
323         if (null === $this->startTime) {
324             throw new LogicException('You must start the progress bar before calling finish().');
325         }
326
327         if (null !== $this->startTime) {
328             if (!$this->max) {
329                 $this->barChar = $this->barCharOriginal;
330                 $this->display(true);
331             }
332             $this->startTime = null;
333             $this->output->writeln('');
334             $this->output = null;
335         }
336     }
337
338     /**
339      * Initializes the progress helper.
340      */
341     private function initialize()
342     {
343         $this->formatVars = array();
344         foreach ($this->defaultFormatVars as $var) {
345             if (false !== strpos($this->format, "%{$var}%")) {
346                 $this->formatVars[$var] = true;
347             }
348         }
349
350         if ($this->max > 0) {
351             $this->widths['max'] = $this->strlen($this->max);
352             $this->widths['current'] = $this->widths['max'];
353         } else {
354             $this->barCharOriginal = $this->barChar;
355             $this->barChar = $this->emptyBarChar;
356         }
357     }
358
359     /**
360      * Generates the array map of format variables to values.
361      *
362      * @param bool $finish Forces the end result
363      *
364      * @return array Array of format vars and values
365      */
366     private function generate($finish = false)
367     {
368         $vars = array();
369         $percent = 0;
370         if ($this->max > 0) {
371             $percent = (float) $this->current / $this->max;
372         }
373
374         if (isset($this->formatVars['bar'])) {
375             if ($this->max > 0) {
376                 $completeBars = floor($percent * $this->barWidth);
377             } else {
378                 if (!$finish) {
379                     $completeBars = floor($this->current % $this->barWidth);
380                 } else {
381                     $completeBars = $this->barWidth;
382                 }
383             }
384
385             $emptyBars = $this->barWidth - $completeBars - $this->strlen($this->progressChar);
386             $bar = str_repeat($this->barChar, $completeBars);
387             if ($completeBars < $this->barWidth) {
388                 $bar .= $this->progressChar;
389                 $bar .= str_repeat($this->emptyBarChar, $emptyBars);
390             }
391
392             $vars['bar'] = $bar;
393         }
394
395         if (isset($this->formatVars['elapsed'])) {
396             $elapsed = time() - $this->startTime;
397             $vars['elapsed'] = str_pad($this->humaneTime($elapsed), $this->widths['elapsed'], ' ', STR_PAD_LEFT);
398         }
399
400         if (isset($this->formatVars['current'])) {
401             $vars['current'] = str_pad($this->current, $this->widths['current'], ' ', STR_PAD_LEFT);
402         }
403
404         if (isset($this->formatVars['max'])) {
405             $vars['max'] = $this->max;
406         }
407
408         if (isset($this->formatVars['percent'])) {
409             $vars['percent'] = str_pad(floor($percent * 100), $this->widths['percent'], ' ', STR_PAD_LEFT);
410         }
411
412         return $vars;
413     }
414
415     /**
416      * Converts seconds into human-readable format.
417      *
418      * @param int $secs Number of seconds
419      *
420      * @return string Time in readable format
421      */
422     private function humaneTime($secs)
423     {
424         $text = '';
425         foreach ($this->timeFormats as $format) {
426             if ($secs < $format[0]) {
427                 if (count($format) == 2) {
428                     $text = $format[1];
429                     break;
430                 } else {
431                     $text = ceil($secs / $format[2]).' '.$format[1];
432                     break;
433                 }
434             }
435         }
436
437         return $text;
438     }
439
440     /**
441      * Overwrites a previous message to the output.
442      *
443      * @param OutputInterface $output  An Output instance
444      * @param string          $message The message
445      */
446     private function overwrite(OutputInterface $output, $message)
447     {
448         $length = $this->strlen($message);
449
450         // append whitespace to match the last line's length
451         if (null !== $this->lastMessagesLength && $this->lastMessagesLength > $length) {
452             $message = str_pad($message, $this->lastMessagesLength, "\x20", STR_PAD_RIGHT);
453         }
454
455         // carriage return
456         $output->write("\x0D");
457         $output->write($message);
458
459         $this->lastMessagesLength = $this->strlen($message);
460     }
461
462     /**
463      * {@inheritdoc}
464      */
465     public function getName()
466     {
467         return 'progress';
468     }
469 }