Passed
Push — master ( 2d89aa...dbaa53 )
by Alec
01:57
created

Spinner::refineSettings()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 7
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 5
CRAP Score 2

Importance

Changes 0
Metric Value
eloc 4
dl 0
loc 7
ccs 5
cts 5
cp 1
rs 10
c 0
b 0
f 0
cc 2
nc 2
nop 1
crap 2
1
<?php declare(strict_types=1);
2
3
namespace AlecRabbit\Spinner\Core;
4
5
use AlecRabbit\Accessories\Pretty;
6
use AlecRabbit\ConsoleColour\ConsoleColor;
7
use AlecRabbit\Control\Cursor;
8
use AlecRabbit\Spinner\Contracts\SettingsInterface;
9
use AlecRabbit\Spinner\Contracts\SpinnerInterface;
10
use function AlecRabbit\typeOf;
11
12
class Spinner implements SpinnerInterface
13
{
14
    protected const ERASING_SHIFT = 1;
15
    protected const INTERVAL = 0.1;
16
    protected const SYMBOLS = [''];
17
18
    /** @var string */
19
    protected $messageStr;
20
    /** @var string */
21
    protected $percentStr = '';
22
    /** @var string */
23
    protected $percentPrefix;
24
    /** @var string */
25
    protected $moveBackSequenceStr;
26
    /** @var string */
27
    protected $paddingStr;
28
    /** @var string */
29
    protected $eraseBySpacesStr;
30
    /** @var Styling */
31
    protected $styled;
32
33
    /**
34
     * AbstractSpinner constructor.
35
     * @param mixed $settings
36
     */
37 9
    public function __construct(
38
        $settings = null
39
    ) {
40 9
        $settings = $this->refineSettings($settings);
41 9
        $this->paddingStr = $settings->getPaddingStr() ?? SettingsInterface::EMPTY;
42 9
        $this->messageStr = $this->refineMessage($settings);
43 9
        $this->setFields();
44 9
        $this->styled = new Styling(static::SYMBOLS, $this->getStyles());
45 9
    }
46
47
    /**
48
     * @param mixed $settings
49
     * @return Settings
50
     */
51 9
    protected function refineSettings($settings): Settings
52
    {
53 9
        $this->assertSettings($settings);
54 9
        if (\is_string($settings)) {
55 8
            return (new Settings())->setMessage($settings);
56
        }
57 1
        return $settings ?? new Settings();
58
    }
59
60
    /**
61
     * @param mixed $settings
62
     */
63 9
    protected function assertSettings($settings): void
64
    {
65 9
        if (null !== $settings && !\is_string($settings) && !$settings instanceof SettingsInterface) {
66
            throw new \InvalidArgumentException(
67
                'Instance of SettingsInterface or string expected ' . typeOf($settings) . ' given.'
68
            );
69
        }
70 9
    }
71
72
    /**
73
     * @param Settings $settings
74
     * @return string
75
     */
76 9
    protected function refineMessage(Settings $settings): string
77
    {
78 9
        $message = ucfirst($settings->getMessage() ?? SettingsInterface::EMPTY);
79
        $prefix =
80 9
            empty($message) ?
81 1
                SettingsInterface::ONE_SPACE_SYMBOL :
82 9
                $settings->getPrefix() ?? SettingsInterface::ONE_SPACE_SYMBOL;
83
        $suffix =
84 9
            $settings->getSuffix() ??
85 9
            empty($message) ?
86 1
                SettingsInterface::EMPTY :
87 9
                SettingsInterface::DEFAULT_SUFFIX;
88 9
        return $prefix . $message . $suffix;
89
    }
90
91 9
    protected function setFields(): void
92
    {
93 9
        $this->percentPrefix = $this->getPrefix();
94
        $strLen =
95 9
            strlen($this->message()) + strlen($this->percent()) + strlen($this->paddingStr) + static::ERASING_SHIFT;
96 9
        $this->moveBackSequenceStr = ConsoleColor::ESC_CHAR . "[{$strLen}D";
97 9
        $this->eraseBySpacesStr = str_repeat(SettingsInterface::ONE_SPACE_SYMBOL, $strLen);
98 9
    }
99
100
    /**
101
     * @return string
102
     */
103 9
    protected function getPrefix(): string
104
    {
105 9
        if (strpos($this->messageStr, SettingsInterface::DEFAULT_SUFFIX)) {
106 8
            return SettingsInterface::ONE_SPACE_SYMBOL;
107
        }
108 1
        return SettingsInterface::EMPTY;
109
    }
110
111
    /**
112
     * @return string
113
     */
114 9
    protected function message(): string
115
    {
116 9
        return $this->messageStr;
117
    }
118
119
    /**
120
     * @return string
121
     */
122 9
    protected function percent(): string
123
    {
124 9
        return $this->percentStr;
125
    }
126
127 3
    protected function getStyles(): array
128
    {
129
        return [
130 3
            Styling::COLOR256_SPINNER_STYLES => [
131
                '203',
132
                '209',
133
                '215',
134
                '221',
135
                '227',
136
                '191',
137
                '155',
138
                '119',
139
                '83',
140
                '84',
141
                '85',
142
                '86',
143
                '87',
144
                '81',
145
                '75',
146
                '69',
147
                '63',
148
                '99',
149
                '135',
150
                '171',
151
                '207',
152
                '206',
153
                '205',
154
                '204',
155
            ],
156 3
            Styling::COLOR_SPINNER_STYLES => ['96'],
157
        ];
158
    }
159
160 1
    public function interval(): float
161
    {
162 1
        return static::INTERVAL;
163
    }
164
165 2
    public function inline(bool $inline): SpinnerInterface
166
    {
167 2
        $this->paddingStr = $inline ? SettingsInterface::ONE_SPACE_SYMBOL : SettingsInterface::EMPTY;
168 2
        $this->setFields();
169 2
        return $this;
170
    }
171
172
    /** {@inheritDoc} */
173 8
    public function begin(): string
174
    {
175 8
        return Cursor::hide() . $this->spin();
176
    }
177
178
    /** {@inheritDoc} */
179 8
    public function spin(?float $percent = null): string
180
    {
181 8
        if (null !== $percent) {
182 1
            $this->updatePercent($percent);
183
        }
184
        return
185 8
            $this->paddingStr .
186 8
            $this->styled->spinner() .
187 8
            $this->styled->message(
188 8
                $this->message()
189
            ) .
190 8
            $this->styled->percent(
191 8
                $this->percent()
192
            ) .
193 8
            $this->moveBackSequenceStr;
194
    }
195
196
    /**
197
     * @param float $percent
198
     */
199 1
    protected function updatePercent(float $percent): void
200
    {
201 1
        if (0 === (int)($percent * 1000) % 10) {
202 1
            $this->percentStr = Pretty::percent($percent, 0, $this->percentPrefix);
203 1
            $this->setFields();
204
        }
205 1
    }
206
207
    /** {@inheritDoc} */
208 8
    public function end(): string
209
    {
210 8
        return $this->erase() . Cursor::show();
211
    }
212
213
    /** {@inheritDoc} */
214 8
    public function erase(): string
215
    {
216 8
        return $this->eraseBySpacesStr . $this->moveBackSequenceStr;
217
    }
218
}
219