Passed
Push — master ( 7baa1a...55e3ff )
by Alec
02:56
created

AbstractSpinner::getPrefix()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 4
CRAP Score 2

Importance

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