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