Passed
Branch main (337636)
by ANDREY
02:26
created

Glyph::ifFirstSibling()   A

Complexity

Conditions 4
Paths 3

Size

Total Lines 12
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 4

Importance

Changes 0
Metric Value
cc 4
eloc 7
c 0
b 0
f 0
nc 3
nop 1
dl 0
loc 12
ccs 8
cts 8
cp 1
crap 4
rs 10
1
<?php
2
3
namespace VPA\Console\Glyphs;
4
5
use VPA\Console\FrameConfigInterface;
6
use VPA\Console\FrameSymbol;
7
use VPA\Console\Nodes;
8
use VPA\Console\Symbol;
9
use VPA\DI\Injectable;
10
11
#[Injectable]
12
abstract class Glyph
13
{
14
    use Nodes;
15
16
    protected array $children = [];
17
    protected array $config = [];
18
    protected ?Glyph $parent = null;
19
    protected int $documentWidth = 80;
20
    protected int $width = 0;
21
    protected int $height = 0;
22
    protected ?bool $isFirstSibling = null;
23
    protected ?bool $isLastSibling = null;
24
    protected bool $isRendered = false;
25
    protected array $renderMap = [];
26
    protected array $cachedRenderMap = [];
27
    protected int $X = 0;
28
    protected int $Y = 0;
29
    protected int $offsetX = 0;
30
    protected int $offsetY = 0;
31
    protected bool $renderedWidth = false;
32
    protected bool $renderedHeight = false;
33
    protected int $contentWidth = 0;
34
    protected int $contentHeight = 0;
35
36
37 54
    public function __construct(protected FrameConfigInterface $globalConfig)
38
    {
39 54
        $this->config = [
40
            'overflowX' => 'none',
41
            'overflowY' => 'none',
42
            'paddingLeft' => 0,
43
            'paddingRight' => 0,
44
            'paddingTop' => 0,
45
            'paddingBottom' => 0,
46
            'width' => 'auto',
47
            'maxWidth' => 100,
48
        ];
49
    }
50
51 39
    public function __isset(string $name): bool
52
    {
53 39
        return array_key_exists($name, $this->config);
54
    }
55
56 38
    public function __set(string $name, mixed $value): void
57
    {
58 38
        if ($this->__isset($name)) {
59 37
            $this->config[$name] = $value;
60 37
            return;
61
        }
62 1
        throw new \Exception(
63 1
            sprintf(
64
                "The property %s not exists for the %s element.",
65
                $name,
66 1
                get_class($this)
67
            )
68
        );
69
    }
70
71 51
    public function __get(string $name): mixed
72
    {
73 51
        return $this->config[$name] ?? null;
74
    }
75
76 37
    public function setConfig(array $config): Glyph
77
    {
78 37
        $this->config = array_merge($this->config, $config);
79 37
        return $this;
80
    }
81
82 46
    public function getConfig(): array
83
    {
84 46
        return $this->config;
85
    }
86
87 28
    protected function addChild(Glyph $child): Glyph
88
    {
89 28
        $this->children[] = $child;
90 28
        $child->setParent($this);
91 28
        return $child;
92
    }
93
94 26
    public function getChildren(): array
95
    {
96 26
        return $this->children;
97
    }
98
99 14
    public function assign(): array
100
    {
101 14
        if ($this->isRendered) {
102 1
            return $this->renderMap;
103
        }
104 14
        $this->isRendered = true;
105 14
        $width = $this->getWidth();
106 14
        $height = $this->getHeight();
107 14
        for ($i = 0; $i < $height; $i++) {
108 1
            $this->renderMap[$i] = array_fill(0, $width, $this->globalConfig->__get('space'));
109
        }
110 14
        $this->render();
111 14
        return $this->renderMap;
112
    }
113
114 3
    public function display(): void
115
    {
116 3
        $this->assign();
117 3
        $this->printMap();
118
    }
119
120 14
    public function render(): Glyph
121
    {
122 14
        foreach ($this->children as $child) {
123 13
            $this->mergeMaps($child->render());
124
        }
125 14
        return $this;
126
    }
127
128 1
    public function isFirstSibling(Glyph $child): bool
129
    {
130 1
        $first = reset($this->children);
131 1
        return $first !== false && $first === $child;
132
    }
133
134 1
    public function isLastSibling(Glyph $child): bool
135
    {
136 1
        $last = end($this->children);
137 1
        return $last !== false && $last === $child;
138
    }
139
140 2
    public function ifFirstSibling(array $config): Glyph
141
    {
142 2
        if (!$this->parent) {
143 1
            return $this;
144
        }
145 1
        $first = $this->parent->isFirstSibling($this);
146 1
        if ($first) {
147 1
            foreach ($config as $property => $value) {
148 1
                $this->__set($property, $value);
149
            }
150
        }
151 1
        return $this;
152
    }
153
154 2
    public function ifLastSibling(array $config): Glyph
155
    {
156 2
        if (!$this->parent) {
157 1
            return $this;
158
        }
159 1
        $last = $this->parent->isLastSibling($this);
160 1
        if ($last) {
161 1
            foreach ($config as $property => $value) {
162 1
                $this->__set($property, $value);
163
            }
164
        }
165 1
        return $this;
166
    }
167
168 2
    public function getDocumentWidth(): int
169
    {
170 2
        if (is_null($this->parent)) {
171 1
            return $this->documentWidth;
172
        } else {
173 1
            return $this->parent->getDocumentWidth();
174
        }
175
    }
176
177 3
    protected function printMap(): void
178
    {
179 3
        foreach ($this->renderMap as $y => $list) {
180 3
            echo implode("", $list) . "\n";
181
        }
182
    }
183
184 17
    public function getWidthByContent(int $endOfPreviousSibling = 0): int
185
    {
186 17
        $this->X = $endOfPreviousSibling;
187 17
        foreach ($this->children as $child) {
188
            $this->width = $child->getWidthByContent(0);
189
        }
190 17
        return $this->width;
191
    }
192
193 23
    public function getHeightByContent(int $endOfPreviousSibling = 0): int
194
    {
195 23
        $this->Y = $endOfPreviousSibling;
196 23
        foreach ($this->children as $child) {
197
            $this->height = $child->getHeightByContent();
198
        }
199 23
        return $this->height;
200
    }
201
202 24
    protected function gc(string $name): object
203
    {
204 24
        return $this->globalConfig->__get($name);
205
    }
206
207
208 34
    public function getWidth(): int
209
    {
210 34
        return $this->width;
211
    }
212
213 18
    public function setX(int $x): void
214
    {
215 18
        $this->X = $x;
216
    }
217
218 23
    public function setY(int $y): void
219
    {
220 23
        $this->Y = $y;
221
    }
222
223 13
    public function setWidth(int $width): Glyph
224
    {
225 13
        $configWidth = $this->__get('width');
226 13
        if ($configWidth == 'auto') {
227 12
            $this->width = $width;
228
        } else {
229 1
            $this->width = intval($configWidth);
230
        }
231 13
        foreach ($this->getChildren() as $child) {
232 9
            $child->__set('maxWidth', $width);
233
        }
234 13
        $this->renderedWidth = true;
235 13
        return $this;
236
    }
237
238 18
    public function getHeight(): int
239
    {
240 18
        return $this->height;
241
    }
242
243 10
    public function setHeight(int $height): Glyph
244
    {
245 10
        $this->height = $height;
246 10
        $this->renderedHeight = true;
247 10
        return $this;
248
    }
249
250 28
    public function setParent(Glyph $parent): void
251
    {
252 28
        $this->parent = $parent;
253
    }
254
255 31
    public function getParent(): Glyph|null
256
    {
257 31
        return $this->parent;
258
    }
259
260 13
    private function mergeMaps(Glyph $render): void
261
    {
262 13
        foreach ($render->renderMap as $y => $line) {
263 13
            foreach ($line as $x => $item) {
264 13
                $coordX = $render->X + $this->offsetX + $x;
265 13
                $coordY = $render->Y + $this->offsetY + intval($y);
266 13
                $this->renderMap[$coordY][$coordX] = $item;
267
            }
268
        }
269
    }
270
}
271