Skip to content

Instantly share code, notes, and snippets.

@anon5r
Last active May 26, 2020
Embed
What would you like to do?
Progressbar
<?php
class Progressbar
{
//private $cursor = ['|', '/', '-', '\\'];
private $cursor = ['⠋','⠙','⠹','⠸','⠼','⠴','⠦','⠧','⠇','⠏'];
private $spacer = '░';
private $indicator = "\033[7m \033[0m";
private $total = 0;
private $fulfilled = 100;
private $width = 0;
private $_callCount = 0;
private $progressUnit = '';
private $processLabel = 'Process';
private $msgStart = null;
private $msgProcessing = null;
private $msgComplete = null;
private $taskComplete = null;
private $useTaskByBytes = false;
private $useCursor = false;
private $_format = null;
/**
* Progressbar constructor.
* @param int $total Total value
* @param int $width Progress bar width
* @param int $fulfilled progress fulfilled value like 100%
* @param string $progressUnit with unit label likes '%'
*/
public function __construct($total, $width, $fulfilled, $progressUnit = '')
{
$this->total = $total;
$this->width = $width;
$this->fulfilled = $fulfilled;
$this->progressUnit = $progressUnit;
}
/**
* set process message
* Default:
* - when starting, label with "start"
* - when processing, label with "ing..."
* - when complete, label with " complete!"
* @param string $label processing label message
* @return $this
*/
public function setProcessingLabel(string $label)
{
$this->processLabel = $label;
return $this;
}
/**
* @param string $unit
* @return $this
*/
public function setProgressUnit(string $unit)
{
$this->progressUnit = $unit;
return $this;
}
/**
*
* @param string $label
* @return $this
*/
public function setLabelStart(string $label)
{
$this->msgStart = $label;
return $this;
}
/**
* @param string $label
* @return $this
*/
public function setLabelProcessing(string $label)
{
$this->msgProcessing = $label;
return $this;
}
/**
* @param string $label
* @return $this
*/
public function setLabelComplete(string $label)
{
$this->msgComplete = $label;
return $this;
}
/**
* @param string $complete
* @return $this
*/
public function setTaskComplete($complete)
{
$this->taskComplete = $complete;
return $this;
}
/**
* @param bool $bool
* @return $this
*/
public function setUseTasksByBytes(bool $bool)
{
$this->useTaskByBytes = (bool)$bool;
return $this;
}
/**
* @param bool $bool
* @return $this
*/
public function setUseCursor(bool $bool)
{
$this->useCursor = (bool)$bool;
return $this;
}
/**
* Default cursor is ⠋⠙⠹⠸⠼⠴⠦⠧⠇⠏
* @param array $cursor ['|', '/', '-', '\\']
* @return $this
*/
public function setCustomCursors(array $cursor)
{
$this->cursor = $cursor;
return $this;
}
private function _generateFormat()
{
if (!$this->processLabel)
$this->processLabel = 'Process';
$this->msgStart = $this->msgStart ?? $this->processLabel . ' start';
$this->msgProcessing = $this->msgProcessing ?? $this->processLabel . 'ing...';
$this->msgComplete = $this->msgComplete ?? $this->processLabel . ' complete!';
$labelLength = strlen($this->processLabel);
$labelLength = $labelLength < strlen($this->msgStart) ? strlen($this->msgStart) : $labelLength;
$labelLength = $labelLength < strlen($this->msgProcessing) ? strlen($this->msgProcessing) : $labelLength;
$labelLength = $labelLength < strlen($this->msgComplete) ? strlen($this->msgComplete) : $labelLength;
$labelLength += 1;
$maxMargin = strlen($this->fulfilled) + 1;
$this->progressUnit = str_replace('%', '%%', $this->progressUnit);
// Label
$format = '%-' . $labelLength . 's ';
// Cursor
if ($this->useCursor)
$format .= '%s ';
// Indicator with process
//$format .= '[%-' . $this->width . 's]%' . $maxMargin . 'd' . $this->progressUnit;
$format .= '[%s%s]%' . $maxMargin . 'd' . $this->progressUnit;
// Task
if ($this->taskComplete != null) {
$taskMargin = $this->useTaskByBytes ? 7 : strlen($this->taskComplete);
$format .= ' (%' . $taskMargin . 's/%' . $taskMargin . 's)';
}
$this->_format = $format;
}
/**
* @param int $current value like progress percentage
* @param int $currentTask task complete of current
*/
public function drawProgressBar($current = null, $currentTask = null)
{
if ($this->_format == null)
$this->_generateFormat();
$progress = (floor(($current / $this->fulfilled) * $this->width));
$indicator = str_repeat($this->indicator, $progress);
$spacer = str_repeat($this->spacer, ($this->width - $progress));
$params = [];
// Label
if ($current < 1)
$params[] = $this->msgStart;
elseif ($this->fulfilled <= $current)
$params[] = $this->msgComplete;
else
$params[] = $this->msgProcessing;
// Cursor
if ($this->useCursor) {
$cNum = count($this->cursor);
$params[] = $this->cursor[$this->_callCount % $cNum];
$this->_callCount++;
}
// Indicator with progress
$params[] = $indicator;
// Spacer
$params[] = $spacer;
$params[] = $current;
// Task
if ($this->taskComplete !== null && $currentTask !== null) {
$params[] = $this->useTaskByBytes ? self::convertBytesToHumanReadable($currentTask) : $currentTask;
$params[] = $this->useTaskByBytes ? self::convertBytesToHumanReadable($this->taskComplete) : $this->taskComplete;
}
echo "\r"; // Return the drawing cursor to the line head
vprintf($this->_format, $params);
flush();
}
/**
* Convert string of byte size to bytes integer.
* @param string $val
* @return int|string
*/
public static function convertToBytes($val)
{
$val = trim($val);
$last = strtolower($val[strlen($val) - 1]);
$val = intval(substr($val, 0, -1));
switch ($last) {
case 't':
$val *= 1024;
// no break
case 'g':
$val *= 1024;
// no break
case 'm':
$val *= 1024;
// no break
case 'k':
$val *= 1024;
}
return $val;
}
/**
* @param int $size
* @param int $precision
* @return string
*/
public static function convertBytesToHumanReadable($size, $precision = 2) {
for($i = 0; ($size / 1024) > 0.9; $i++, $size /= 1024) {}
return round($size, $precision).['B','kB','MB','GB','TB','PB','EB','ZB','YB'][$i];
}
}
<?php
$total = 3000;
$barWidth = 50;
$max = 100;
$unit = '%';
$progress = new Progressbar($total, $barWidth, $max, $unit);
$progress
->setLabelStart('Start!')
->setLabelProcessing('Loading...')
->setLabelComplete('Complete!')
->setProgressUnit('%')
->setUseCursor(true)
->setUseTasksByBytes(false)
->setTaskComplete($total)
;
$progress->drawProgressBar(0, 0);
// Start! ⠋ [ ] 0% ( 0/128)
for ($i = 0; $i < $total; $i++) {
$progress->drawProgressBar(floor(($i / $total) * 100), $i);
usleep(1000);
}
// Loading... ⠹ [ ░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░░] 24% ( 31/128)
$progress->drawProgressBar(100, $i);
// Complete! ⠏ [ ] 100% (128/128)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment