Skip to content

HTTPS clone URL

Subversion checkout URL

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