|
|
@@ -0,0 +1,124 @@
|
|
|
+<?php
|
|
|
+
|
|
|
+namespace Tools\View\Helper;
|
|
|
+
|
|
|
+use Cake\Core\Configure;
|
|
|
+use Cake\View\Helper;
|
|
|
+use Cake\View\View;
|
|
|
+use InvalidArgumentException;
|
|
|
+use Tools\Utility\Number;
|
|
|
+
|
|
|
+/**
|
|
|
+ * @author Mark Scherer
|
|
|
+ * @license MIT
|
|
|
+ * @property \Cake\View\Helper\HtmlHelper $Html
|
|
|
+ */
|
|
|
+class ProgressHelper extends Helper {
|
|
|
+
|
|
|
+ const LENGTH_MIN = 3;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * @var array
|
|
|
+ */
|
|
|
+ public $helpers = ['Html'];
|
|
|
+
|
|
|
+ /**
|
|
|
+ * @var array
|
|
|
+ */
|
|
|
+ protected $_defaults = [
|
|
|
+ 'empty' => '⬜',
|
|
|
+ 'full' => '⬛',
|
|
|
+ ];
|
|
|
+
|
|
|
+ /**
|
|
|
+ * @param \Cake\View\View $View
|
|
|
+ * @param array $config
|
|
|
+ */
|
|
|
+ public function __construct(View $View, array $config = []) {
|
|
|
+ $defaults = (array)Configure::read('Progress') + $this->_defaults;
|
|
|
+ $config += $defaults;
|
|
|
+
|
|
|
+ parent::__construct($View, $config);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * @param float $value Value 0...1
|
|
|
+ * @param int $length As char count
|
|
|
+ * @param array $attributes
|
|
|
+ * @return string
|
|
|
+ */
|
|
|
+ public function progressBar($value, $length, array $attributes = []) {
|
|
|
+ $bar = $this->draw($value, $length);
|
|
|
+
|
|
|
+ $attributes += [
|
|
|
+ 'title' => Number::toPercentage($this->calculatePercentage($value), 0, ['multiply' => true]),
|
|
|
+ ];
|
|
|
+
|
|
|
+ return $this->Html->tag('span', $bar, $attributes);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Render the progress bar based on the current state.
|
|
|
+ *
|
|
|
+ * @param float $complete
|
|
|
+ * @param int $length
|
|
|
+ * @return string
|
|
|
+ * @throws \InvalidArgumentException
|
|
|
+ */
|
|
|
+ public function draw($complete, $length) {
|
|
|
+ if ($complete < 0.0 || $complete > 1.0) {
|
|
|
+ throw new InvalidArgumentException('Min/Max overflow for value `' . $complete . '` (0...1)');
|
|
|
+ }
|
|
|
+ if ($length < static::LENGTH_MIN) {
|
|
|
+ throw new InvalidArgumentException('Min length for such a progress bar is ' . static::LENGTH_MIN);
|
|
|
+ }
|
|
|
+
|
|
|
+ $barLength = $this->calculateBarLength($complete, $length);
|
|
|
+
|
|
|
+ $bar = '';
|
|
|
+ if ($barLength > 0) {
|
|
|
+ $bar = str_repeat($this->getConfig('full'), $barLength);
|
|
|
+ }
|
|
|
+
|
|
|
+ $pad = $length - $barLength;
|
|
|
+ if ($pad > 0) {
|
|
|
+ $bar .= str_repeat($this->getConfig('empty'), $pad);
|
|
|
+ }
|
|
|
+
|
|
|
+ return $bar;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * @param float $percentage
|
|
|
+ * @return float
|
|
|
+ */
|
|
|
+ public function calculatePercentage($percentage) {
|
|
|
+ $percentageRounded = round($percentage, 2);
|
|
|
+ if ($percentageRounded === 0.00 && $percentage > 0.0) {
|
|
|
+ $percentage = 0.01;
|
|
|
+ }
|
|
|
+ if ($percentageRounded === 1.00 && $percentage < 1.0) {
|
|
|
+ $percentage = 0.99;
|
|
|
+ }
|
|
|
+
|
|
|
+ return $percentage;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * @param float $complete
|
|
|
+ * @param int $length
|
|
|
+ * @return int
|
|
|
+ */
|
|
|
+ protected function calculateBarLength($complete, $length) {
|
|
|
+ $barLength = (int)round($length * $complete, 0);
|
|
|
+ if ($barLength === 0 && $complete > 0.0) {
|
|
|
+ $barLength = 1;
|
|
|
+ }
|
|
|
+ if ($barLength === $length && $complete < 1.0) {
|
|
|
+ $barLength = $length - 1;
|
|
|
+ }
|
|
|
+
|
|
|
+ return $barLength;
|
|
|
+ }
|
|
|
+
|
|
|
+}
|