mirror of
https://github.com/kamilwylegala/cakephp2-php8.git
synced 2024-11-15 11:28:25 +00:00
Add progress helper
This commit is contained in:
parent
e580ad813e
commit
788c57dd4b
4 changed files with 446 additions and 0 deletions
113
lib/Cake/Console/Helper/ProgressHelper.php
Normal file
113
lib/Cake/Console/Helper/ProgressHelper.php
Normal file
|
@ -0,0 +1,113 @@
|
||||||
|
<?php
|
||||||
|
App::uses("ShellHelper", "Console/Helper");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a progress bar using a supplied callback.
|
||||||
|
*/
|
||||||
|
class ProgressHelper extends ShellHelper
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* The current progress.
|
||||||
|
*
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
protected $_progress = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The total number of 'items' to progress through.
|
||||||
|
*
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
protected $_total = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The width of the bar.
|
||||||
|
*
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
protected $_width = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Output a progress bar.
|
||||||
|
*
|
||||||
|
* Takes a number of options to customize the behavior:
|
||||||
|
*
|
||||||
|
* - `total` The total number of items in the progress bar. Defaults
|
||||||
|
* to 100.
|
||||||
|
* - `width` The width of the progress bar. Defaults to 80.
|
||||||
|
* - `callback` The callback that will be called in a loop to advance the progress bar.
|
||||||
|
*
|
||||||
|
* @param array $args The arguments/options to use when outputing the progress bar.
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function output($args)
|
||||||
|
{
|
||||||
|
$args += ['callback' => null];
|
||||||
|
if (isset($args[0])) {
|
||||||
|
$args['callback'] = $args[0];
|
||||||
|
}
|
||||||
|
if (!$args['callback'] || !is_callable($args['callback'])) {
|
||||||
|
throw new RuntimeException('Callback option must be a callable.');
|
||||||
|
}
|
||||||
|
$this->init($args);
|
||||||
|
$callback = $args['callback'];
|
||||||
|
while ($this->_progress < $this->_total) {
|
||||||
|
$callback($this);
|
||||||
|
$this->draw();
|
||||||
|
}
|
||||||
|
$this->_consoleOutput->write('');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize the progress bar for use.
|
||||||
|
*
|
||||||
|
* - `total` The total number of items in the progress bar. Defaults
|
||||||
|
* to 100.
|
||||||
|
* - `width` The width of the progress bar. Defaults to 80.
|
||||||
|
*
|
||||||
|
* @param array $args The initialization data.
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function init(array $args = [])
|
||||||
|
{
|
||||||
|
$args += ['total' => 100, 'width' => 80];
|
||||||
|
$this->_progress = 0;
|
||||||
|
$this->_width = $args['width'];
|
||||||
|
$this->_total = $args['total'];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Increment the progress bar.
|
||||||
|
*
|
||||||
|
* @param int $num The amount of progress to advance by.
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function increment($num = 1)
|
||||||
|
{
|
||||||
|
$this->_progress = min(max(0, $this->_progress + $num), $this->_total);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Render the progress bar based on the current state.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function draw()
|
||||||
|
{
|
||||||
|
$numberLen = strlen(' 100%');
|
||||||
|
$complete = round($this->_progress / $this->_total, 2);
|
||||||
|
$barLen = ($this->_width - $numberLen) * ($this->_progress / $this->_total);
|
||||||
|
$bar = '';
|
||||||
|
if ($barLen > 1) {
|
||||||
|
$bar = str_repeat('=', $barLen - 1) . '>';
|
||||||
|
}
|
||||||
|
$pad = ceil($this->_width - $numberLen - $barLen);
|
||||||
|
if ($pad > 0) {
|
||||||
|
$bar .= str_repeat(' ', $pad);
|
||||||
|
}
|
||||||
|
$percent = ($complete * 100) . '%';
|
||||||
|
$bar .= str_pad($percent, $numberLen, ' ', STR_PAD_LEFT);
|
||||||
|
$this->_consoleOutput->overwrite($bar, 0);
|
||||||
|
}
|
||||||
|
}
|
37
lib/Cake/Console/Helper/ShellHelper.php
Normal file
37
lib/Cake/Console/Helper/ShellHelper.php
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
abstract class ShellHelper
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Default config for this helper.
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $_defaultConfig = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ConsoleOutput instance.
|
||||||
|
*
|
||||||
|
* @var ConsoleOutput
|
||||||
|
*/
|
||||||
|
protected $_consoleOutput;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor.
|
||||||
|
*
|
||||||
|
* @param ConsoleOutput $consoleOutput The ConsoleOutput instance to use.
|
||||||
|
* @param array $config The settings for this helper.
|
||||||
|
*/
|
||||||
|
public function __construct(ConsoleOutput $consoleOutput)
|
||||||
|
{
|
||||||
|
$this->_consoleOutput = $consoleOutput;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method should output content using `$this->_consoleOutput`.
|
||||||
|
*
|
||||||
|
* @param array $args The arguments for the helper.
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
abstract public function output($args);
|
||||||
|
}
|
217
lib/Cake/Test/Case/Console/Helper/ProgressHelperTest.php
Normal file
217
lib/Cake/Test/Case/Console/Helper/ProgressHelperTest.php
Normal file
|
@ -0,0 +1,217 @@
|
||||||
|
<?php
|
||||||
|
App::uses("ProgressHelper", "Console/Helper");
|
||||||
|
App::uses("ConsoleOutputStub", "TestSuite/Stub");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ProgressHelper test.
|
||||||
|
* @property ConsoleOutputStub $consoleOutput
|
||||||
|
* @property ProgressHelper $helper
|
||||||
|
*/
|
||||||
|
class ProgressHelperTest extends CakeTestCase
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* setUp method
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function setUp()
|
||||||
|
{
|
||||||
|
parent::setUp();
|
||||||
|
|
||||||
|
$this->consoleOutput = new ConsoleOutputStub();
|
||||||
|
$this->helper = new ProgressHelper($this->consoleOutput);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test that a callback is required.*
|
||||||
|
* @expectedException \RuntimeException
|
||||||
|
*/
|
||||||
|
public function testOutputFailure()
|
||||||
|
{
|
||||||
|
$this->helper->output(['not a callback']);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test that the callback is invoked until 100 is reached.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function testOutputSuccess()
|
||||||
|
{
|
||||||
|
$this->helper->output([function ($progress) {
|
||||||
|
$progress->increment(20);
|
||||||
|
}]);
|
||||||
|
$expected = [
|
||||||
|
'',
|
||||||
|
'==============> 20%',
|
||||||
|
'',
|
||||||
|
'=============================> 40%',
|
||||||
|
'',
|
||||||
|
'============================================> 60%',
|
||||||
|
'',
|
||||||
|
'===========================================================> 80%',
|
||||||
|
'',
|
||||||
|
'==========================================================================> 100%',
|
||||||
|
'',
|
||||||
|
];
|
||||||
|
$this->assertEquals($expected, $this->consoleOutput->messages());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test output with options
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function testOutputSuccessOptions()
|
||||||
|
{
|
||||||
|
$this->helper->output([
|
||||||
|
'total' => 10,
|
||||||
|
'width' => 20,
|
||||||
|
'callback' => function ($progress) {
|
||||||
|
$progress->increment(2);
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
$expected = [
|
||||||
|
'',
|
||||||
|
'==> 20%',
|
||||||
|
'',
|
||||||
|
'=====> 40%',
|
||||||
|
'',
|
||||||
|
'========> 60%',
|
||||||
|
'',
|
||||||
|
'===========> 80%',
|
||||||
|
'',
|
||||||
|
'==============> 100%',
|
||||||
|
'',
|
||||||
|
];
|
||||||
|
$this->assertEquals($expected, $this->consoleOutput->messages());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test using the helper manually.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function testIncrementAndRender()
|
||||||
|
{
|
||||||
|
$this->helper->init();
|
||||||
|
$this->helper->increment(20);
|
||||||
|
$this->helper->draw();
|
||||||
|
$this->helper->increment(40);
|
||||||
|
$this->helper->draw();
|
||||||
|
$this->helper->increment(40);
|
||||||
|
$this->helper->draw();
|
||||||
|
$expected = [
|
||||||
|
'',
|
||||||
|
'==============> 20%',
|
||||||
|
'',
|
||||||
|
'============================================> 60%',
|
||||||
|
'',
|
||||||
|
'==========================================================================> 100%',
|
||||||
|
];
|
||||||
|
$this->assertEquals($expected, $this->consoleOutput->messages());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test negative numbers
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function testIncrementWithNegatives()
|
||||||
|
{
|
||||||
|
$this->helper->init();
|
||||||
|
$this->helper->increment(40);
|
||||||
|
$this->helper->draw();
|
||||||
|
$this->helper->increment(-60);
|
||||||
|
$this->helper->draw();
|
||||||
|
$this->helper->increment(80);
|
||||||
|
$this->helper->draw();
|
||||||
|
$expected = [
|
||||||
|
'',
|
||||||
|
'=============================> 40%',
|
||||||
|
'',
|
||||||
|
' 0%',
|
||||||
|
'',
|
||||||
|
'===========================================================> 80%',
|
||||||
|
];
|
||||||
|
$this->assertEquals($expected, $this->consoleOutput->messages());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test increment and draw with options
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function testIncrementWithOptions()
|
||||||
|
{
|
||||||
|
$this->helper->init([
|
||||||
|
'total' => 10,
|
||||||
|
'width' => 20,
|
||||||
|
]);
|
||||||
|
$this->helper->increment(4);
|
||||||
|
$this->helper->draw();
|
||||||
|
$this->helper->increment(4);
|
||||||
|
$this->helper->draw();
|
||||||
|
$this->helper->increment(4);
|
||||||
|
$this->helper->draw();
|
||||||
|
|
||||||
|
$expected = [
|
||||||
|
'',
|
||||||
|
'=====> 40%',
|
||||||
|
'',
|
||||||
|
'===========> 80%',
|
||||||
|
'',
|
||||||
|
'==============> 100%',
|
||||||
|
];
|
||||||
|
$this->assertEquals($expected, $this->consoleOutput->messages());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test increment and draw with value that makes the pad
|
||||||
|
* be a float
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function testIncrementFloatPad()
|
||||||
|
{
|
||||||
|
$this->helper->init([
|
||||||
|
'total' => 50
|
||||||
|
]);
|
||||||
|
$this->helper->increment(7);
|
||||||
|
$this->helper->draw();
|
||||||
|
$this->helper->increment(7);
|
||||||
|
$this->helper->draw();
|
||||||
|
$this->helper->increment(7);
|
||||||
|
$this->helper->draw();
|
||||||
|
$this->helper->increment(7);
|
||||||
|
$this->helper->draw();
|
||||||
|
$this->helper->increment(7);
|
||||||
|
$this->helper->draw();
|
||||||
|
$this->helper->increment(3);
|
||||||
|
$this->helper->draw();
|
||||||
|
$this->helper->increment(4);
|
||||||
|
$this->helper->draw();
|
||||||
|
$this->helper->increment(8);
|
||||||
|
$this->helper->draw();
|
||||||
|
$expected = [
|
||||||
|
'',
|
||||||
|
'=========> 14%',
|
||||||
|
'',
|
||||||
|
'====================> 28%',
|
||||||
|
'',
|
||||||
|
'==============================> 42%',
|
||||||
|
'',
|
||||||
|
'=========================================> 56%',
|
||||||
|
'',
|
||||||
|
'===================================================> 70%',
|
||||||
|
'',
|
||||||
|
'========================================================> 76%',
|
||||||
|
'',
|
||||||
|
'==============================================================> 84%',
|
||||||
|
'',
|
||||||
|
'==========================================================================> 100%',
|
||||||
|
];
|
||||||
|
$this->assertEquals($expected, $this->consoleOutput->messages());
|
||||||
|
}
|
||||||
|
}
|
79
lib/Cake/TestSuite/Stub/ConsoleOutputStub.php
Normal file
79
lib/Cake/TestSuite/Stub/ConsoleOutputStub.php
Normal file
|
@ -0,0 +1,79 @@
|
||||||
|
<?php
|
||||||
|
App::uses("ConsoleOutput", "Console");
|
||||||
|
|
||||||
|
/**
|
||||||
|
* StubOutput makes testing shell commands/shell helpers easier.
|
||||||
|
*
|
||||||
|
* You can use this class by injecting it into a Helper instance:
|
||||||
|
*
|
||||||
|
* ```
|
||||||
|
* App::uses("ConsoleOutputStub", "TestSuite/Stub");
|
||||||
|
*
|
||||||
|
* $output = new ConsoleOutputStub();
|
||||||
|
* $helper = new ProgressHelper($output);
|
||||||
|
* ```
|
||||||
|
*/
|
||||||
|
class ConsoleOutputStub extends ConsoleOutput
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Buffered messages.
|
||||||
|
*
|
||||||
|
* @var array
|
||||||
|
*/
|
||||||
|
protected $_out = [];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The number of bytes written by last call to write
|
||||||
|
*
|
||||||
|
* @var int
|
||||||
|
*/
|
||||||
|
protected $_lastWritten = 0;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write output to the buffer.
|
||||||
|
*
|
||||||
|
* @param string|array $message A string or an array of strings to output
|
||||||
|
* @param int $newlines Number of newlines to append
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function write($message, $newlines = 1)
|
||||||
|
{
|
||||||
|
foreach ((array)$message as $line) {
|
||||||
|
$this->_out[] = $line;
|
||||||
|
$this->_lastWritten = strlen($line);
|
||||||
|
}
|
||||||
|
$newlines--;
|
||||||
|
while ($newlines > 0) {
|
||||||
|
$this->_out[] = '';
|
||||||
|
$this->_lastWritten = 0;
|
||||||
|
$newlines--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Overwrite output already written to the buffer.
|
||||||
|
*
|
||||||
|
* @param array|string $message The message to output.
|
||||||
|
* @param int $newlines Number of newlines to append.
|
||||||
|
* @param int $size The number of bytes to overwrite. Defaults to the
|
||||||
|
* length of the last message output.
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function overwrite($message, $newlines = 1, $size = null)
|
||||||
|
{
|
||||||
|
//insert an empty array to mock deletion of existing output
|
||||||
|
$this->_out[] = "";
|
||||||
|
//append new message to output
|
||||||
|
$this->write($message, $newlines);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the buffered output.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function messages()
|
||||||
|
{
|
||||||
|
return $this->_out;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue