Passed
Push — master ( ee41d8...7baa1a )
by Alec
02:31
created

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