Passed
Push — master ( 079212...632fb9 )
by Alec
02:27
created

Spinner::assertSettings()   A

Complexity

Conditions 4
Paths 2

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 4

Importance

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