1<?php 2/** 3 * CakePHP(tm) : Rapid Development Framework (https://cakephp.org) 4 * Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org) 5 * 6 * Licensed under The MIT License 7 * For full copyright and license information, please see the LICENSE.txt 8 * Redistributions of files must retain the above copyright notice. 9 * 10 * @copyright Copyright (c) Cake Software Foundation, Inc. (https://cakefoundation.org) 11 * @link https://cakephp.org CakePHP(tm) Project 12 * @since 2.8 13 * @license https://opensource.org/licenses/mit-license.php MIT License 14 */ 15App::uses("BaseShellHelper", "Console/Helper"); 16 17/** 18 * Create a visually pleasing ASCII art table 19 * from 2 dimensional array data. 20 */ 21class TableShellHelper extends BaseShellHelper { 22 23/** 24 * Default config for this helper. 25 * 26 * @var array 27 */ 28 protected $_defaultConfig = array( 29 'headers' => true, 30 'rowSeparator' => false, 31 'headerStyle' => 'info', 32 ); 33 34/** 35 * Calculate the column widths 36 * 37 * @param array $rows The rows on which the columns width will be calculated on. 38 * @return array 39 */ 40 protected function _calculateWidths($rows) { 41 $widths = array(); 42 foreach ($rows as $line) { 43 for ($i = 0, $len = count($line); $i < $len; $i++) { 44 $columnLength = mb_strlen($line[$i]); 45 if ($columnLength > (isset($widths[$i]) ? $widths[$i] : 0)) { 46 $widths[$i] = $columnLength; 47 } 48 } 49 } 50 return $widths; 51 } 52 53/** 54 * Output a row separator. 55 * 56 * @param array $widths The widths of each column to output. 57 * @return void 58 */ 59 protected function _rowSeparator($widths) { 60 $out = ''; 61 foreach ($widths as $column) { 62 $out .= '+' . str_repeat('-', $column + 2); 63 } 64 $out .= '+'; 65 $this->_consoleOutput->write($out); 66 } 67 68/** 69 * Output a row. 70 * 71 * @param array $row The row to output. 72 * @param array $widths The widths of each column to output. 73 * @param array $options Options to be passed. 74 * @return void 75 */ 76 protected function _render($row, $widths, $options = array()) { 77 $out = ''; 78 foreach ($row as $i => $column) { 79 $pad = $widths[$i] - mb_strlen($column); 80 if (!empty($options['style'])) { 81 $column = $this->_addStyle($column, $options['style']); 82 } 83 $out .= '| ' . $column . str_repeat(' ', $pad) . ' '; 84 } 85 $out .= '|'; 86 $this->_consoleOutput->write($out); 87 } 88 89/** 90 * Output a table. 91 * 92 * @param array $rows The data to render out. 93 * @return void 94 */ 95 public function output($rows) { 96 $config = $this->config(); 97 $widths = $this->_calculateWidths($rows); 98 $this->_rowSeparator($widths); 99 if ($config['headers'] === true) { 100 $this->_render(array_shift($rows), $widths, array('style' => $config['headerStyle'])); 101 $this->_rowSeparator($widths); 102 } 103 foreach ($rows as $line) { 104 $this->_render($line, $widths); 105 if ($config['rowSeparator'] === true) { 106 $this->_rowSeparator($widths); 107 } 108 } 109 if ($config['rowSeparator'] !== true) { 110 $this->_rowSeparator($widths); 111 } 112 } 113 114/** 115 * Add style tags 116 * 117 * @param string $text The text to be surrounded 118 * @param string $style The style to be applied 119 * @return string 120 */ 121 protected function _addStyle($text, $style) { 122 return '<' . $style . '>' . $text . '</' . $style . '>'; 123 } 124}