Passed
Push — master ( 613d69...d5255e )
by Alexander
02:26
created

ProgressBar::build()   A

Complexity

Conditions 5
Paths 12

Size

Total Lines 24
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 11
CRAP Score 5

Importance

Changes 0
Metric Value
cc 5
eloc 11
nc 12
nop 1
dl 0
loc 24
ccs 11
cts 11
cp 1
crap 5
rs 9.6111
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Yiisoft\Yii\Bulma;
6
7
use InvalidArgumentException;
8
use Yiisoft\Html\Html;
9
use Yiisoft\Html\Tag\CustomTag;
10
use Yiisoft\Widget\Widget;
0 ignored issues
show
Bug introduced by
This use statement conflicts with another class in this namespace, Yiisoft\Yii\Bulma\Widget. Consider defining an alias.

Let?s assume that you have a directory layout like this:

.
|-- OtherDir
|   |-- Bar.php
|   `-- Foo.php
`-- SomeDir
    `-- Foo.php

and let?s assume the following content of Bar.php:

// Bar.php
namespace OtherDir;

use SomeDir\Foo; // This now conflicts the class OtherDir\Foo

If both files OtherDir/Foo.php and SomeDir/Foo.php are loaded in the same runtime, you will see a PHP error such as the following:

PHP Fatal error:  Cannot use SomeDir\Foo as Foo because the name is already in use in OtherDir/Foo.php

However, as OtherDir/Foo.php does not necessarily have to be loaded and the error is only triggered if it is loaded before OtherDir/Bar.php, this problem might go unnoticed for a while. In order to prevent this error from surfacing, you must import the namespace with a different alias:

// Bar.php
namespace OtherDir;

use SomeDir\Foo as SomeDirFoo; // There is no conflict anymore.
Loading history...
11
12
use function implode;
13
use function in_array;
14
15
/**
16
 * Progress Bar widget.
17
 * Native HTML progress bar.
18
 *
19
 * ```php
20
 * echo ProgressBar::widget()->value(75);
21
 * ```
22
 *
23
 * @link https://bulma.io/documentation/elements/progress/
24
 */
25
final class ProgressBar extends Widget
26
{
27
    public const SIZE_SMALL = 'is-small';
28
    public const SIZE_MEDIUM = 'is-medium';
29
    public const SIZE_LARGE = 'is-large';
30
    private const SIZE_ALL = [
31
        self::SIZE_SMALL,
32
        self::SIZE_MEDIUM,
33
        self::SIZE_LARGE,
34
    ];
35
36
    public const COLOR_PRIMARY = 'is-primary';
37
    public const COLOR_LINK = 'is-link';
38
    public const COLOR_INFO = 'is-info';
39
    public const COLOR_SUCCESS = 'is-success';
40
    public const COLOR_WARNING = 'is-warning';
41
    public const COLOR_DANGER = 'is-danger';
42
    public const COLOR_DARK = 'is-dark';
43
    private const COLOR_ALL = [
44
        self::COLOR_PRIMARY,
45
        self::COLOR_LINK,
46
        self::COLOR_INFO,
47
        self::COLOR_SUCCESS,
48
        self::COLOR_WARNING,
49
        self::COLOR_DANGER,
50
        self::COLOR_DARK,
51
    ];
52
53
    private array $attributes = [];
54
    private string $autoIdPrefix = 'w';
55
    private string $color = '';
56
    private string $size = '';
57
58
    /**
59
     * The HTML attributes.
60
     *
61
     * @param array $values Attribute values indexed by attribute names.
62
     *
63
     * @return self
64
     *
65
     * See {@see \Yiisoft\Html\Html::renderTagAttributes()} for details on how attributes are being rendered.
66
     */
67 2
    public function attributes(array $values): self
68
    {
69 2
        $new = clone $this;
70 2
        $new->attributes = $values;
71 2
        return $new;
72
    }
73
74
    /**
75
     * Returns a new instance with the specified prefix to the automatically generated widget IDs.
76
     *
77
     * @param string $value The prefix to the automatically generated widget IDs.
78
     *
79
     * @return self
80
     */
81 1
    public function autoIdPrefix(string $value): self
82
    {
83 1
        $new = clone $this;
84 1
        $new->autoIdPrefix = $value;
85 1
        return $new;
86
    }
87
88
    /**
89
     * Returns a new instance with the specified progress bar color.
90
     *
91
     * @param string $value The progress bar color. By default there is no color.
92
     * Possible values: ProgressBar::COLOR_PRIMARY, ProgressBar::COLOR_LINK, ProgressBar::COLOR_INFO,
93
     * ProgressBar::COLOR_SUCCESS, ProgressBar::COLOR_WARNING, ProgressBar::COLOR_DANGER, ProgressBar::COLOR_DARK.
94
     *
95
     * @return self
96
     */
97 3
    public function color(string $value): self
98
    {
99 3
        if (!in_array($value, self::COLOR_ALL, true)) {
100 1
            $values = implode('", "', self::COLOR_ALL);
101 1
            throw new InvalidArgumentException("Invalid color. Valid values are: \"$values\".");
102
        }
103
104 2
        $new = clone $this;
105 2
        $new->color = $value;
106
107 2
        return $new;
108
    }
109
110
    /**
111
     * Returns a new instance with the specified ID of the widget.
112
     *
113
     * @param string $value The ID of the widget.
114
     *
115
     * @return self
116
     */
117 1
    public function id(string $value): self
118
    {
119 1
        $new = clone $this;
120 1
        $new->attributes['id'] = $value;
121 1
        return $new;
122
    }
123
124
    /**
125
     * Returns a new instance with the specified maximum progress value.
126
     *
127
     * @param int|null $value Maximum progress value. Set `0` for no maximum.
128
     *
129
     * @return self
130
     */
131 5
    public function maxValue(?int $value): self
132
    {
133 5
        if ($value < 0 || $value > 100) {
134 1
            throw new InvalidArgumentException('Invalid max value. It must be between 0 and 100.');
135
        }
136
137 4
        $new = clone $this;
138 4
        $new->attributes['max'] = $value;
139
140 4
        return $new;
141
    }
142
143
    /**
144
     * Returns a new instance with the specified progress bar size class.
145
     *
146
     * @param string $value The progress bar size class. Default setting is "normal".
147
     * Possible values: ProgressBar::SIZE_SMALL, ProgressBar::SIZE_MEDIUM, Model::SIZE_LARGE.
148
     *
149
     * @return self
150
     */
151 3
    public function size(string $value): self
152
    {
153 3
        if (!in_array($value, self::SIZE_ALL, true)) {
154 1
            $values = implode('", "', self::SIZE_ALL);
155 1
            throw new InvalidArgumentException("Invalid size. Valid values are: \"$values\".");
156
        }
157
158 2
        $new = clone $this;
159 2
        $new->size = $value;
160
161 2
        return $new;
162
    }
163
164
    /**
165
     * Returns a new instance with the specified value of the progress.
166
     *
167
     * @param float|null $value The value of the progress. Set `0` to display loading animation.
168
     *
169
     * @return self
170
     */
171 5
    public function value(?float $value): self
172
    {
173 5
        if ($value < 0 || $value > 100) {
174 1
            throw new InvalidArgumentException('Invalid value. It must be between 0 and 100.');
175
        }
176
177 4
        $new = clone $this;
178 4
        $new->attributes['value'] = $value;
179
180 4
        return $new;
181
    }
182
183 8
    protected function run(): string
184
    {
185 8
        $attributes = $this->build($this->attributes);
186 8
        $content = '';
187
188 8
        if (array_key_exists('value', $attributes)) {
189
            /** @var float|null */
190 3
            $attributes['value'] = $attributes['value'] === 0.0 ? null : $attributes['value'];
191 3
            $content = $attributes['value'] > 0 ? (string)$attributes['value'] . '%' : '';
192
        }
193
194 8
        return CustomTag::name('progress')->attributes($attributes)->content($content)->render();
195
    }
196
197 8
    private function build(array $attributes): array
198
    {
199
        /** @var string */
200 8
        $attributes['id'] ??= (Html::generateId($this->autoIdPrefix) . '-progressbar');
201
202 8
        if (array_key_exists('max', $attributes)) {
203
            /** @var int|null */
204 3
            $attributes['max'] = $attributes['max'] === 0 ? null : $attributes['max'];
205
        } else {
206
            /** @var int|null */
207 5
            $attributes['max'] ??= 100;
208
        }
209
210 8
        Html::addCssClass($attributes, 'progress');
211
212 8
        if ($this->size !== '') {
213 1
            Html::addCssClass($attributes, $this->size);
214
        }
215
216 8
        if ($this->color !== '') {
217 1
            Html::addCssClass($attributes, $this->color);
218
        }
219
220 8
        return $attributes;
221
    }
222
}
223