Passed
Push — main ( 52f862...f41333 )
by ANDREY
02:25
created

Table1D::getAutoColumnsNum()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 26
Code Lines 22

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 6

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
eloc 22
nc 2
nop 0
dl 0
loc 26
ccs 0
cts 22
cp 0
crap 6
rs 9.568
c 1
b 0
f 0
1
<?php
2
3
namespace VPA\Console\Components;
4
5
use VPA\Console\FrameConfigInterface;
6
use VPA\Console\Glyphs\Glyph;
7
use VPA\Console\Glyphs\GlyphBlock;
8
use VPA\Console\TableDisplayMode;
9
10
class Table1D extends GlyphBlock
11
{
12
    private string $firstColumnTitle;
13
    private string $secondColumnTitle;
14
    private bool $haveHeader = false;
15
    private int|string $firstWidth;
16
    private int|string $secondWidth;
17
    private int|string $firstMaxWidth;
18
    private int|string $secondMaxWidth;
19
    private array $data = [];
20
    private int $columns = 1;
21
    private const PADDING_X = 1;
22
23
    public function __construct(protected FrameConfigInterface $globalConfig)
24
    {
25
        parent::__construct($globalConfig);
26
        $this->config = array_merge(
27
            parent::getConfig(),
28
            [
29
                'type' => TableDisplayMode::Slim,
30
                'columns' => '1',
31
                'firstColumnWidth' => 'auto',
32
                'firstColumnMaxWidth' => 'auto',
33
                'secondColumnWidth' => 'auto',
34
                'secondColumnMaxWidth' => 'auto',
35
            ]
36
        );
37
        $this->documentWidth = $this->gc('shell')->getDocumentWidthFromOS();
38
    }
39
40
    public function setHeader(string|array $firstTitle, ?string $secondTitle): Glyph
41
    {
42
        $this->haveHeader = true;
43
        if (is_array($firstTitle) && count($firstTitle) == 2) {
44
            $this->firstColumnTitle = reset($firstTitle);
45
            $this->secondColumnTitle = end($firstTitle);
46
            return $this;
47
        }
48
        $this->firstColumnTitle = $firstTitle ?? '';
49
        $this->secondColumnTitle = $secondTitle ?? '';
50
        return $this;
51
    }
52
53
    private function getAutoColumnsNum(): int
54
    {
55
        $columns = intval($this->__get('columns'));
56
        $this->firstWidth = $this->__get('firstColumnWidth');
57
        $this->firstMaxWidth = $this->__get('firstColumnMaxWidth');
58
        $this->secondWidth = $this->__get('secondColumnWidth');
59
        $this->secondMaxWidth = $this->__get('secondColumnMaxWidth');
60
        $type = $this->__get('type');
61
        $deltaWidth = self::PADDING_X * 4;
62
        $deltaWidth += match ($type) {
63
            TableDisplayMode::Slim, TableDisplayMode::Frame => 3,
64
            default => 0,
65
        };
66
        if ($columns == 0) {
67
            $valueWidth = max(array_map(function ($it) {
68
                return strlen($it);
69
            }, $this->data));
70
            $keyWidth = max(array_map(function ($it) {
71
                return strlen($it);
72
            }, array_keys($this->data)));
73
            $keyRealWidth = min([$keyWidth, $this->firstWidth, $this->firstMaxWidth]);
74
            $valueRealWidth = min([$valueWidth, $this->secondWidth, $this->secondMaxWidth]);
75
            $width = $keyRealWidth + $valueRealWidth + $deltaWidth;
76
            return floor($this->getDocumentWidth() / $width);
0 ignored issues
show
Bug Best Practice introduced by
The expression return floor($this->getDocumentWidth() / $width) returns the type double which is incompatible with the type-hinted return integer.
Loading history...
77
        }
78
        return $columns;
79
    }
80
81
    public function output($data): Glyph
82
    {
83
        $this->data = $data;
84
        $table = $this->addTable();
85
        $type = $this->__get('type');
86
        $this->columns = $this->getAutoColumnsNum();
87
88
        $borderHead = $borderV = $borderH = 0;
89
        switch ($type) {
90
            case TableDisplayMode::Slim:
91
                $borderV = 1;
92
                $borderHead = 1;
93
                $table->setBorder(1, 1, 1, 1);
94
                break;
95
            case TableDisplayMode::Frame:
96
                $borderV = 1;
97
                $borderH = 1;
98
                $borderHead = 1;
99
                $table->setBorder(1, 1, 1, 0);
100
                break;
101
        }
102
103
        if ($this->haveHeader) {
104
            $header = $table->addRow();
105
            for ($i = 0; $i < $this->columns; $i++) {
106
                $this->addCells($header, $this->firstColumnTitle, $this->secondColumnTitle, $borderHead, $borderV, $i);
107
            }
108
        }
109
        $value = current($data);
110
        $key = key($data);
111
        do {
112
            $row = $table->addRow();
113
            for ($i = 0; $i < $this->columns; $i++) {
114
                if ($key) {
115
                    $this->addCells($row, $key, $value, $borderH, $borderV, $i);
116
                    $value = next($data);
117
                    $key = key($data);
118
                } else {
119
                    $this->addCells($row, '', '', $borderH, $borderV, $i);
120
                }
121
122
            }
123
        } while ($value);
124
        $this->display();
125
        return $this;
126
    }
127
128
    private function addCells(
129
        Glyph $row,
130
        string $first,
131
        string $second,
132
        int $borderBottom = 0,
133
        int $borderV = 1,
134
        int $column = 1
135
    ): array
136
    {
137
        $firstCell = $row->addCell()
0 ignored issues
show
Bug introduced by
The method addCell() does not exist on VPA\Console\Glyphs\Glyph. It seems like you code against a sub-type of VPA\Console\Glyphs\Glyph such as VPA\Console\Glyphs\Row. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

137
        $firstCell = $row->/** @scrutinizer ignore-call */ addCell()
Loading history...
138
            ->setPadding(self::PADDING_X, self::PADDING_X, 0, 0)->setBorder(0, $borderV, 0, $borderBottom);
139
        $this->firstWidth !== 'auto' && $firstCell = $firstCell->setWidth(intval($this->firstWidth));
140
        $firstText = $firstCell->addText();
141
        $this->firstMaxWidth != 'auto' && $firstText = $firstText->setConfig(['maxWidth' => $this->firstMaxWidth]);
142
        $firstText->setValue($first);
143
        $secondCell = $row->addCell()
144
            ->setPadding(self::PADDING_X, self::PADDING_X, 0, 0)
145
            ->setBorder(0, $this->columns - 1 == $column ? 0 : $borderV, 0, $borderBottom);
146
        $this->secondWidth !== 'auto' && $firstCell = $secondCell->setWidth(intval($this->secondWidth));
147
        $secondText = $secondCell->addText();
148
        $this->secondMaxWidth != 'auto' && $secondText = $secondText->setConfig(['maxWidth' => $this->secondMaxWidth]);
149
        $secondText->setValue($second);
150
        return [&$firstCell, &$secondCell];
151
    }
152
}
153