Passed
Pull Request — master (#4418)
by Owen
12:11
created

TextGrid::renderRows()   A

Complexity

Conditions 4
Paths 5

Size

Total Lines 10
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 4

Importance

Changes 0
Metric Value
eloc 7
dl 0
loc 10
ccs 6
cts 6
cp 1
rs 10
c 0
b 0
f 0
cc 4
nc 5
nop 2
crap 4
1
<?php
2
3
namespace PhpOffice\PhpSpreadsheet\Helper;
4
5
use PhpOffice\PhpSpreadsheet\Shared\StringHelper;
6
7
class TextGrid
8
{
9
    private bool $isCli;
10
11
    protected array $matrix;
12
13
    protected array $rows;
14
15
    protected array $columns;
16
17 36
    private string $gridDisplay;
18
19 36
    private bool $rowDividers = false;
20 36
21
    private bool $rowHeaders = true;
22 36
23 36
    private bool $columnHeaders = true;
24 36
25 36
    public function __construct(array $matrix, bool $isCli = true, bool $rowDividers = false, bool $rowHeaders = true, bool $columnHeaders = true)
26 36
    {
27 36
        $this->rows = array_keys($matrix);
28 36
        $this->columns = array_keys($matrix[$this->rows[0]]);
29
30 36
        $matrix = array_values($matrix);
31 36
        array_walk(
32
            $matrix,
33
            function (&$row): void {
34 36
                $row = array_values($row);
35
            }
36 36
        );
37
38 36
        $this->matrix = $matrix;
39 36
        $this->isCli = $isCli;
40 36
        $this->rowDividers = $rowDividers;
41 36
        $this->rowHeaders = $rowHeaders;
42
        $this->columnHeaders = $columnHeaders;
43 36
    }
44 36
45 36
    public function render(): string
46
    {
47
        $this->gridDisplay = $this->isCli ? '' : ('<pre>' . PHP_EOL);
48 36
49
        if (!empty($this->rows)) {
50 36
            $maxRow = max($this->rows);
51
            $maxRowLength = strlen((string) $maxRow) + 1;
52
            $columnWidths = $this->getColumnWidths();
53 36
54
            $this->renderColumnHeader($maxRowLength, $columnWidths);
55 36
            $this->renderRows($maxRowLength, $columnWidths);
56 36
            if (!$this->rowDividers) {
57 36
                $this->renderFooter($maxRowLength, $columnWidths);
58 36
            }
59
        }
60
61
        $this->gridDisplay .= $this->isCli ? '' : '</pre>';
62 36
63
        return $this->gridDisplay;
64 36
    }
65 36
66 36
    private function renderRows(int $maxRowLength, array $columnWidths): void
67 36
    {
68
        foreach ($this->matrix as $row => $rowData) {
69
            if ($this->rowHeaders) {
70
                $this->gridDisplay .= '|' . str_pad((string) $this->rows[$row], $maxRowLength, ' ', STR_PAD_LEFT) . ' ';
71 36
            }
72
            $this->renderCells($rowData, $columnWidths);
73 36
            $this->gridDisplay .= '|' . PHP_EOL;
74 36
            if ($this->rowDividers) {
75 36
                $this->renderFooter($maxRowLength, $columnWidths);
76
            }
77 36
        }
78
    }
79 36
80 36
    private function renderCells(array $rowData, array $columnWidths): void
81 36
    {
82
        foreach ($rowData as $column => $cell) {
83 36
            $valueForLength = $this->getString($cell);
84
            $displayCell = $this->isCli ? $valueForLength : htmlentities($valueForLength);
85 36
            $this->gridDisplay .= '| ';
86
            $this->gridDisplay .= $displayCell . str_repeat(' ', $columnWidths[$column] - $this->strlen($valueForLength) + 1);
87
        }
88 36
    }
89
90 36
    private function renderColumnHeader(int $maxRowLength, array &$columnWidths): void
91 36
    {
92 36
        if (!$this->columnHeaders) {
93 36
            $this->renderFooter($maxRowLength, $columnWidths);
94
95 36
            return;
96
        }
97
        foreach ($this->columns as $column => $reference) {
98 36
            $columnWidths[$column] = max($columnWidths[$column], $this->strlen($reference));
99
        }
100 36
        if ($this->rowHeaders) {
101 36
            $this->gridDisplay .= str_repeat(' ', $maxRowLength + 2);
102 36
        }
103 36
        foreach ($this->columns as $column => $reference) {
104
            $this->gridDisplay .= '+-' . str_repeat('-', $columnWidths[$column] + 1);
105
        }
106 36
        $this->gridDisplay .= '+' . PHP_EOL;
107
108
        if ($this->rowHeaders) {
109 36
            $this->gridDisplay .= str_repeat(' ', $maxRowLength + 2);
110
        }
111 36
        foreach ($this->columns as $column => $reference) {
112 36
            $this->gridDisplay .= '| ' . str_pad((string) $reference, $columnWidths[$column] + 1, ' ');
113
        }
114 36
        $this->gridDisplay .= '|' . PHP_EOL;
115 36
116 36
        $this->renderFooter($maxRowLength, $columnWidths);
117 22
    }
118
119
    private function renderFooter(int $maxRowLength, array $columnWidths): void
120
    {
121 36
        if ($this->rowHeaders) {
122
            $this->gridDisplay .= '+' . str_repeat('-', $maxRowLength + 1);
123
        }
124 36
        foreach ($this->columns as $column => $reference) {
125
            $this->gridDisplay .= '+-';
126
            $this->gridDisplay .= str_pad((string) '', $columnWidths[$column] + 1, '-');
127
        }
128
        $this->gridDisplay .= '+' . PHP_EOL;
129
    }
130
131
    private function getColumnWidths(): array
132
    {
133
        $columnCount = count($this->matrix, COUNT_RECURSIVE) / count($this->matrix);
134
        $columnWidths = [];
135
        for ($column = 0; $column < $columnCount; ++$column) {
136
            $columnWidths[] = $this->getColumnWidth(array_column($this->matrix, $column));
137
        }
138
139
        return $columnWidths;
140
    }
141
142
    private function getColumnWidth(array $columnData): int
143
    {
144
        $columnWidth = 0;
145
        $columnData = array_values($columnData);
146
147
        foreach ($columnData as $columnValue) {
148
            $columnWidth = max($columnWidth, $this->strlen($this->getString($columnValue)));
149
        }
150
151
        return $columnWidth;
152
    }
153
154
    protected function getString(mixed $value): string
155
    {
156
        return StringHelper::convertToString($value, convertBool: true);
157
    }
158
159
    protected function strlen(string $value): int
160
    {
161
        return mb_strlen($value);
162
    }
163
}
164