Completed
Push — master ( c8728b...09f7f1 )
by Denis
01:22
created

ArrayToTextTable::calcColumnsLength()   B

Complexity

Conditions 5
Paths 3

Size

Total Lines 20
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 20
rs 8.8571
c 0
b 0
f 0
cc 5
eloc 11
nc 3
nop 0
1
<?php
2
3
namespace Dekor;
4
5
/**
6
 * @author Denis Koronets
7
 */
8
class ArrayToTextTable
9
{
10
    /**
11
     * @var array
12
     */
13
    private $data;
14
15
    /**
16
     * @var array
17
     */
18
    private $columnsList = [];
19
20
    /**
21
     * @var int
22
     */
23
    private $maxLineLength = 40;
24
25
    /**
26
     * @var array
27
     */
28
    private $columnsLength = [];
29
30
    /**
31
     * @var array
32
     */
33
    private $result = [];
34
35
    /**
36
     * @var string
37
     */
38
    private $charset = 'UTF-8';
39
40
    /**
41
     * @var bool
42
     */
43
    private $renderHeader = true;
44
45
46
    public function __construct(array $data)
47
    {
48
        $this->data = $data;
49
    }
50
51
    /**
52
     * Calculates list of columns in data
53
     */
54
    protected function calcColumnsList()
55
    {
56
        $this->columnsList = array_keys($this->data[0]);
57
    }
58
59
    /**
60
     * Calculates length for string
61
     */
62
    protected function length($str)
63
    {
64
        return mb_strlen($str, $this->charset);
65
    }
66
67
    /**
68
     * Calculate maximum string length for each column
69
     */
70
    private function calcColumnsLength()
71
    {
72
        foreach ($this->data as $row) {
73
74
            if ($row === '---') {
75
                continue;
76
            }
77
78
            foreach ($this->columnsList as $column) {
79
80
                $this->columnsLength[$column] = max(
81
                    isset($this->columnsLength[$column])
82
                        ? $this->columnsLength[$column]
83
                        : 0,
84
                    $this->length($row[$column]),
85
                    $this->length($column)
86
                );
87
            }
88
        }
89
    }
90
91
    /**
92
     * Append a line separator to result
93
     */
94
    private function lineSeparator()
95
    {
96
        $tmp = '';
97
98
        foreach ($this->columnsList as $column) {
99
            $tmp .= '+' . str_repeat('-', $this->columnsLength[$column] + 2) . '+';
100
        }
101
102
        $this->result[] = $tmp;
103
    }
104
105
    /**
106
     * @return string
107
     */
108
    private function column($columnKey, $value)
109
    {
110
        return '| ' . $value . ' ' . str_repeat(' ', $this->columnsLength[$columnKey] - $this->length($value)) . '|';
111
    }
112
113
    /**
114
     * Render header part
115
     * @return void
116
     */
117
    private function renderHeader()
118
    {
119
        $this->lineSeparator();
120
121
        if (!$this->renderHeader) {
122
            return;
123
        }
124
125
        $tmp = '';
126
127
        foreach ($this->columnsList as $column) {
128
            $tmp .= $this->column($column, $column);
129
        }
130
131
        $this->result[] = $tmp;
132
133
        $this->lineSeparator();
134
    }
135
136
    /**
137
     * Render body section of table
138
     * @return void
139
     */
140
    private function renderBody()
141
    {
142
        foreach ($this->data as $row) {
143
144
            if ($row === '---') {
145
                $this->lineSeparator();
146
                continue;
147
            }
148
149
            $tmp = '';
150
151
            foreach ($this->columnsList as $column) {
152
                $tmp .= $this->column($column, $row[$column]);
153
            }
154
155
            $this->result[] = $tmp;
156
        }
157
    }
158
159
    /**
160
     * Set custom charset for columns values
161
     * @return self
162
     */
163
    public function charset($charset)
164
    {
165
        if (!in_array($charset, mb_list_encodings())) {
166
            throw new \Exception(
167
                'This charset `' . $charset . '` is not supported by mbstring.' .
168
                'Please check it: http://php.net/manual/ru/function.mb-list-encodings.php'
169
            );
170
        }
171
172
        $this->charset = $charset;
173
174
        return $this;
175
    }
176
177
    /**
178
     * Set mode to print no header in the table
179
     * @return self
180
     */
181
    public function noHeader()
182
    {
183
        $this->renderHeader = false;
184
185
        return $this;
186
    }
187
188
    /**
189
     * @param int $length
190
     * @return self
191
     * @throws Exception
192
     */
193
    public function maxLineLength($length)
194
    {
195
        if ($length < 3) {
196
            throw new \Exception('Minimum length for cropper is 3 sumbols');
197
        }
198
199
        $this->maxLineLength = $length;
200
201
        return $this;
202
    }
203
204
    /**
205
     * Build your ascii table and return the result
206
     * @return string
207
     */
208
    public function render()
209
    {
210
        if (empty($this->data)) {
211
            return 'Empty';
212
        }
213
214
        $this->calcColumnsList();
215
        $this->calcColumnsLength();
216
217
        /** render section **/
218
        $this->renderHeader();
219
        $this->renderBody();
220
        $this->lineSeparator();
221
        /** end render section **/
222
223
        return str_replace(
224
            ['++', '||'],
225
            ['+', '|'],
226
            implode(PHP_EOL, $this->result)
227
        );
228
    }
229
}