1: <?php
2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13:
14: namespace Cake\Shell\Helper;
15:
16: use Cake\Console\Helper;
17:
18: 19: 20: 21:
22: class TableHelper extends Helper
23: {
24: 25: 26: 27: 28:
29: protected $_defaultConfig = [
30: 'headers' => true,
31: 'rowSeparator' => false,
32: 'headerStyle' => 'info',
33: ];
34:
35: 36: 37: 38: 39: 40:
41: protected function _calculateWidths($rows)
42: {
43: $widths = [];
44: foreach ($rows as $line) {
45: foreach (array_values($line) as $k => $v) {
46: $columnLength = $this->_cellWidth($v);
47: if ($columnLength >= (isset($widths[$k]) ? $widths[$k] : 0)) {
48: $widths[$k] = $columnLength;
49: }
50: }
51: }
52:
53: return $widths;
54: }
55:
56: 57: 58: 59: 60: 61:
62: protected function _cellWidth($text)
63: {
64: if (strpos($text, '<') === false && strpos($text, '>') === false) {
65: return mb_strwidth($text);
66: }
67:
68:
69: $styles = $this->_io->styles();
70: $tags = implode('|', array_keys($styles));
71: $text = preg_replace('#</?(?:' . $tags . ')>#', '', $text);
72:
73: return mb_strwidth($text);
74: }
75:
76: 77: 78: 79: 80: 81:
82: protected function _rowSeparator($widths)
83: {
84: $out = '';
85: foreach ($widths as $column) {
86: $out .= '+' . str_repeat('-', $column + 2);
87: }
88: $out .= '+';
89: $this->_io->out($out);
90: }
91:
92: 93: 94: 95: 96: 97: 98: 99:
100: protected function _render(array $row, $widths, $options = [])
101: {
102: if (count($row) === 0) {
103: return;
104: }
105:
106: $out = '';
107: foreach (array_values($row) as $i => $column) {
108: $pad = $widths[$i] - $this->_cellWidth($column);
109: if (!empty($options['style'])) {
110: $column = $this->_addStyle($column, $options['style']);
111: }
112: $out .= '| ' . $column . str_repeat(' ', $pad) . ' ';
113: }
114: $out .= '|';
115: $this->_io->out($out);
116: }
117:
118: 119: 120: 121: 122: 123: 124: 125: 126:
127: public function output($rows)
128: {
129: if (!is_array($rows) || count($rows) === 0) {
130: return;
131: }
132:
133: $config = $this->getConfig();
134: $widths = $this->_calculateWidths($rows);
135:
136: $this->_rowSeparator($widths);
137: if ($config['headers'] === true) {
138: $this->_render(array_shift($rows), $widths, ['style' => $config['headerStyle']]);
139: $this->_rowSeparator($widths);
140: }
141:
142: if (!$rows) {
143: return;
144: }
145:
146: foreach ($rows as $line) {
147: $this->_render($line, $widths);
148: if ($config['rowSeparator'] === true) {
149: $this->_rowSeparator($widths);
150: }
151: }
152: if ($config['rowSeparator'] !== true) {
153: $this->_rowSeparator($widths);
154: }
155: }
156:
157: 158: 159: 160: 161: 162: 163:
164: protected function _addStyle($text, $style)
165: {
166: return '<' . $style . '>' . $text . '</' . $style . '>';
167: }
168: }
169: