Completed
Pull Request — 6.0 (#1921)
by nhzex
04:55
created

Table   A

Complexity

Total Complexity 30

Size/Duplication

Total Lines 284
Duplicated Lines 0 %

Test Coverage

Coverage 0%

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 111
c 2
b 0
f 0
dl 0
loc 284
ccs 0
cts 76
cp 0
rs 10
wmc 30

10 Methods

Rating   Name   Duplication   Size   Complexity  
A setHeader() 0 6 1
A setRows() 0 7 2
A renderSeparator() 0 10 2
B render() 0 44 9
A renderHeader() 0 18 4
A setStyle() 0 3 2
A checkColWidth() 0 7 5
A addRow() 0 9 2
A getStyle() 0 9 2
A setCellAlign() 0 4 1
1
<?php
2
// +----------------------------------------------------------------------
3
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
4
// +----------------------------------------------------------------------
5
// | Copyright (c) 2006~2015 http://thinkphp.cn All rights reserved.
6
// +----------------------------------------------------------------------
7
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
8
// +----------------------------------------------------------------------
9
// | Author: yunwuxin <[email protected]>
10
// +----------------------------------------------------------------------
11
declare (strict_types = 1);
12
13
namespace think\console;
14
15
class Table
16
{
17
    const ALIGN_LEFT   = 1;
18
    const ALIGN_RIGHT  = 0;
19
    const ALIGN_CENTER = 2;
20
21
    /**
22
     * 头信息数据
23
     * @var array
24
     */
25
    protected $header = [];
26
27
    /**
28
     * 头部对齐方式 默认1 ALGIN_LEFT 0 ALIGN_RIGHT 2 ALIGN_CENTER
29
     * @var int
30
     */
31
    protected $headerAlign = 1;
32
33
    /**
34
     * 表格数据(二维数组)
35
     * @var array
36
     */
37
    protected $rows = [];
38
39
    /**
40
     * 单元格对齐方式 默认1 ALGIN_LEFT 0 ALIGN_RIGHT 2 ALIGN_CENTER
41
     * @var int
42
     */
43
    protected $cellAlign = 1;
44
45
    /**
46
     * 单元格宽度信息
47
     * @var array
48
     */
49
    protected $colWidth = [];
50
51
    /**
52
     * 表格输出样式
53
     * @var string
54
     */
55
    protected $style = 'default';
56
57
    /**
58
     * 表格样式定义
59
     * @var array
60
     */
61
    protected $format = [
62
        'compact'    => [],
63
        'default'    => [
64
            'top'          => ['+', '-', '+', '+'],
65
            'cell'         => ['|', ' ', '|', '|'],
66
            'middle'       => ['+', '-', '+', '+'],
67
            'bottom'       => ['+', '-', '+', '+'],
68
            'cross-top'    => ['+', '-', '-', '+'],
69
            'cross-bottom' => ['+', '-', '-', '+'],
70
        ],
71
        'markdown'   => [
72
            'top'          => [' ', ' ', ' ', ' '],
73
            'cell'         => ['|', ' ', '|', '|'],
74
            'middle'       => ['|', '-', '|', '|'],
75
            'bottom'       => [' ', ' ', ' ', ' '],
76
            'cross-top'    => ['|', ' ', ' ', '|'],
77
            'cross-bottom' => ['|', ' ', ' ', '|'],
78
        ],
79
        'borderless' => [
80
            'top'          => ['=', '=', ' ', '='],
81
            'cell'         => [' ', ' ', ' ', ' '],
82
            'middle'       => ['=', '=', ' ', '='],
83
            'bottom'       => ['=', '=', ' ', '='],
84
            'cross-top'    => ['=', '=', ' ', '='],
85
            'cross-bottom' => ['=', '=', ' ', '='],
86
        ],
87
        'box'        => [
88
            'top'          => ['┌', '─', '┬', '┐'],
89
            'cell'         => ['│', ' ', '│', '│'],
90
            'middle'       => ['├', '─', '┼', '┤'],
91
            'bottom'       => ['└', '─', '┴', '┘'],
92
            'cross-top'    => ['├', '─', '┴', '┤'],
93
            'cross-bottom' => ['├', '─', '┬', '┤'],
94
        ],
95
        'box-double' => [
96
            'top'          => ['╔', '═', '╤', '╗'],
97
            'cell'         => ['║', ' ', '│', '║'],
98
            'middle'       => ['╠', '─', '╪', '╣'],
99
            'bottom'       => ['╚', '═', '╧', '╝'],
100
            'cross-top'    => ['╠', '═', '╧', '╣'],
101
            'cross-bottom' => ['╠', '═', '╤', '╣'],
102
        ],
103
    ];
104
105
    /**
106
     * 设置表格头信息 以及对齐方式
107
     * @access public
108
     * @param array $header     要输出的Header信息
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 5 found
Loading history...
109
     * @param int   $align      对齐方式 默认1 ALGIN_LEFT 0 ALIGN_RIGHT 2 ALIGN_CENTER
0 ignored issues
show
Coding Style introduced by
Expected 2 spaces after parameter name; 6 found
Loading history...
110
     * @return void
111
     */
112
    public function setHeader(array $header, int $align = 1): void
113
    {
114
        $this->header      = $header;
115
        $this->headerAlign = $align;
116
117
        $this->checkColWidth($header);
118
    }
119
120
    /**
121
     * 设置输出表格数据 及对齐方式
122
     * @access public
123
     * @param array $rows       要输出的表格数据(二维数组)
0 ignored issues
show
Coding Style introduced by
Expected 2 spaces after parameter name; 7 found
Loading history...
124
     * @param int   $align      对齐方式 默认1 ALGIN_LEFT 0 ALIGN_RIGHT 2 ALIGN_CENTER
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 6 found
Loading history...
125
     * @return void
126
     */
127
    public function setRows(array $rows, int $align = 1): void
128
    {
129
        $this->rows      = $rows;
130
        $this->cellAlign = $align;
131
132
        foreach ($rows as $row) {
133
            $this->checkColWidth($row);
134
        }
135
    }
136
137
    /**
138
     * 设置全局单元格对齐方式
139
     * @param int $align 对齐方式 默认1 ALGIN_LEFT 0 ALIGN_RIGHT 2 ALIGN_CENTER
140
     * @return $this
141
     */
142
    public function setCellAlign(int $align = 1)
143
    {
144
        $this->cellAlign = $align;
145
        return $this;
146
    }
147
148
    /**
149
     * 检查列数据的显示宽度
150
     * @access public
151
     * @param  mixed $row       行数据
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 7 found
Loading history...
152
     * @return void
153
     */
154
    protected function checkColWidth($row): void
155
    {
156
        if (is_array($row)) {
157
            foreach ($row as $key => $cell) {
158
                $width = mb_strwidth((string) $cell);
159
                if (!isset($this->colWidth[$key]) || $width > $this->colWidth[$key]) {
160
                    $this->colWidth[$key] = $width;
161
                }
162
            }
163
        }
164
    }
165
166
    /**
167
     * 增加一行表格数据
168
     * @access public
169
     * @param  mixed $row       行数据
0 ignored issues
show
Coding Style introduced by
Expected 3 spaces after parameter name; 7 found
Loading history...
170
     * @param  bool  $first     是否在开头插入
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 5 found
Loading history...
171
     * @return void
172
     */
173
    public function addRow($row, bool $first = false): void
174
    {
175
        if ($first) {
176
            array_unshift($this->rows, $row);
177
        } else {
178
            $this->rows[] = $row;
179
        }
180
181
        $this->checkColWidth($row);
182
    }
183
184
    /**
185
     * 设置输出表格的样式
186
     * @access public
187
     * @param  string $style       样式名
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 7 found
Loading history...
188
     * @return void
189
     */
190
    public function setStyle(string $style): void
191
    {
192
        $this->style = isset($this->format[$style]) ? $style : 'default';
193
    }
194
195
    /**
196
     * 输出分隔行
197
     * @access public
198
     * @param  string $pos       位置
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 7 found
Loading history...
199
     * @return string
200
     */
201
    protected function renderSeparator(string $pos): string
202
    {
203
        $style = $this->getStyle($pos);
204
        $array = [];
205
206
        foreach ($this->colWidth as $width) {
207
            $array[] = str_repeat($style[1], $width + 2);
208
        }
209
210
        return $style[0] . implode($style[2], $array) . $style[3] . PHP_EOL;
211
    }
212
213
    /**
214
     * 输出表格头部
215
     * @access public
216
     * @return string
217
     */
218
    protected function renderHeader(): string
219
    {
220
        $style   = $this->getStyle('cell');
221
        $content = $this->renderSeparator('top');
222
223
        foreach ($this->header as $key => $header) {
224
            $array[] = ' ' . str_pad($header, $this->colWidth[$key], $style[1], $this->headerAlign);
225
        }
226
227
        if (!empty($array)) {
228
            $content .= $style[0] . implode(' ' . $style[2], $array) . ' ' . $style[3] . PHP_EOL;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $array seems to be defined by a foreach iteration on line 223. Are you sure the iterator is never empty, otherwise this variable is not defined?
Loading history...
229
230
            if (!empty($this->rows)) {
231
                $content .= $this->renderSeparator('middle');
232
            }
233
        }
234
235
        return $content;
236
    }
237
238
    protected function getStyle(string $style): array
0 ignored issues
show
Coding Style introduced by
Missing doc comment for function getStyle()
Loading history...
239
    {
240
        if ($this->format[$this->style]) {
241
            $style = $this->format[$this->style][$style];
242
        } else {
243
            $style = [' ', ' ', ' ', ' '];
244
        }
245
246
        return $style;
247
    }
248
249
    /**
250
     * 输出表格
251
     * @access public
252
     * @param  array $dataList       表格数据
0 ignored issues
show
Coding Style introduced by
Expected 1 spaces after parameter name; 7 found
Loading history...
253
     * @return string
254
     */
255
    public function render(array $dataList = []): string
256
    {
257
        if (!empty($dataList)) {
258
            $this->setRows($dataList);
259
        }
260
261
        // 输出头部
262
        $content = $this->renderHeader();
263
        $style   = $this->getStyle('cell');
264
265
        if (!empty($this->rows)) {
266
            foreach ($this->rows as $row) {
267
                if (is_string($row) && '-' === $row) {
268
                    $content .= $this->renderSeparator('middle');
269
                } elseif (is_scalar($row)) {
270
                    $content .= $this->renderSeparator('cross-top');
271
                    $width = 3 * (count($this->colWidth) - 1) + array_reduce($this->colWidth, function ($a, $b) {
0 ignored issues
show
Coding Style introduced by
The opening parenthesis of a multi-line function call should be the last content on the line.
Loading history...
272
                        return $a + $b;
273
                    });
0 ignored issues
show
Coding Style introduced by
For multi-line function calls, the closing parenthesis should be on a new line.

If a function call spawns multiple lines, the coding standard suggests to move the closing parenthesis to a new line:

someFunctionCall(
    $firstArgument,
    $secondArgument,
    $thirdArgument
); // Closing parenthesis on a new line.
Loading history...
274
                    $array = str_pad($row, $width);
275
276
                    $content .= $style[0] . ' ' . $array . ' ' . $style[3] . PHP_EOL;
277
                    $content .= $this->renderSeparator('cross-bottom');
278
                } else {
279
                    $array = [];
280
281
                    foreach ($row as $key => $val) {
282
                        $width = $this->colWidth[$key];
283
                        // form https://github.com/symfony/console/blob/20c9821c8d1c2189f287dcee709b2f86353ea08f/Helper/Table.php#L467
284
                        // str_pad won't work properly with multi-byte strings, we need to fix the padding
285
                        if (false !== $encoding = mb_detect_encoding((string) $val, null, true)) {
286
                            $width += strlen((string) $val) - mb_strwidth((string) $val, $encoding);
287
                        }
288
                        $array[] = ' ' . str_pad((string) $val, $width, ' ', $this->cellAlign);
289
                    }
290
291
                    $content .= $style[0] . implode(' ' . $style[2], $array) . ' ' . $style[3] . PHP_EOL;
292
                }
293
            }
294
        }
295
296
        $content .= $this->renderSeparator('bottom');
297
298
        return $content;
299
    }
300
}
301