Passed
Push — master ( ce4c49...96250d )
by Alec
02:39
created

Spinner::end()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

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