ProgressHelper.php 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. <?php
  2. /**
  3. * CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
  4. * Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
  5. *
  6. * Licensed under The MIT License
  7. * For full copyright and license information, please see the LICENSE.txt
  8. * Redistributions of files must retain the above copyright notice.
  9. *
  10. * @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
  11. * @link http://book.cakephp.org/2.0/en/development/testing.html CakePHP(tm) Tests
  12. * @since 3.1.0
  13. * @license http://www.opensource.org/licenses/mit-license.php MIT License
  14. */
  15. namespace Cake\Shell\Helper;
  16. use Cake\Console\Helper;
  17. use RuntimeException;
  18. /**
  19. * Create a progress bar using a supplied callback.
  20. */
  21. class ProgressHelper extends Helper
  22. {
  23. /**
  24. * The current progress.
  25. *
  26. * @var int
  27. */
  28. protected $_progress = 0;
  29. /**
  30. * The total number of 'items' to progress through.
  31. *
  32. * @var int
  33. */
  34. protected $_total = 0;
  35. /**
  36. * The width of the bar.
  37. *
  38. * @var int
  39. */
  40. protected $_width = 0;
  41. /**
  42. * Output a progress bar.
  43. *
  44. * Takes a number of options to customize the behavior:
  45. *
  46. * - `total` The total number of items in the progress bar. Defaults
  47. * to 100.
  48. * - `width` The width of the progress bar. Defaults to 80.
  49. * - `callback` The callback that will be called in a loop to advance the progress bar.
  50. *
  51. * @param array $args The arguments/options to use when outputing the progress bar.
  52. * @return void
  53. */
  54. public function output($args)
  55. {
  56. $args += ['callback' => null];
  57. if (isset($args[0])) {
  58. $args['callback'] = $args[0];
  59. }
  60. if (!$args['callback'] || !is_callable($args[0])) {
  61. throw new RuntimeException('Callback option must be a callable.');
  62. }
  63. $this->init($args);
  64. $callback = $args['callback'];
  65. while ($this->_progress < $this->_total) {
  66. $callback($this);
  67. $this->draw();
  68. }
  69. }
  70. /**
  71. * Initialize the progress bar for use.
  72. *
  73. * - `total` The total number of items in the progress bar. Defaults
  74. * to 100.
  75. * - `width` The width of the progress bar. Defaults to 80.
  76. *
  77. * @param array $args The initialization data.
  78. * @return void
  79. */
  80. public function init(array $args = [])
  81. {
  82. $args += ['total' => 100, 'width' => 80];
  83. $this->_progress = 0;
  84. $this->_width = $args['width'];
  85. $this->_total = $args['total'];
  86. }
  87. /**
  88. * Increment the progress bar.
  89. *
  90. * @param int $num The amount of progress to advance by.
  91. * @return void
  92. */
  93. public function increment($num = 1)
  94. {
  95. $this->_progress = max(0, $this->_progress + $num);
  96. }
  97. /**
  98. * Render the progress bar based on the current state.
  99. *
  100. * @return void
  101. */
  102. public function draw()
  103. {
  104. $numberLen = strlen(' 100%');
  105. $complete = ($this->_progress / $this->_total);
  106. $barLen = floor(($this->_width - $numberLen) * ($this->_progress / $this->_total));
  107. $bar = '';
  108. if ($barLen > 1) {
  109. $bar = str_repeat('=', $barLen - 1) . '>';
  110. }
  111. $pad = $this->_width - $numberLen - $barLen;
  112. if ($pad > 0) {
  113. $bar .= str_repeat(' ', $pad);
  114. }
  115. $percent = ($complete * 100) . '%';
  116. $bar .= str_pad($percent, $numberLen, ' ', STR_PAD_LEFT);
  117. $this->_io->overwrite($bar, 0);
  118. }
  119. }