Passed
Push — master ( 37cb73...caafef )
by Alec
02:31
created

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