| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404 | 
							- <?php
 
- /**
 
-  * @link http://www.yiiframework.com/
 
-  * @copyright Copyright (c) 2008 Yii Software LLC
 
-  * @license http://www.yiiframework.com/license/
 
-  */
 
- namespace yii\console\widgets;
 
- use Yii;
 
- use yii\base\Widget;
 
- use yii\helpers\ArrayHelper;
 
- use yii\helpers\Console;
 
- /**
 
-  * Table class displays a table in console.
 
-  *
 
-  * For example,
 
-  *
 
-  * ```php
 
-  * $table = new Table();
 
-  *
 
-  * echo $table
 
-  *     ->setHeaders(['test1', 'test2', 'test3'])
 
-  *     ->setRows([
 
-  *         ['col1', 'col2', 'col3'],
 
-  *         ['col1', 'col2', ['col3-0', 'col3-1', 'col3-2']],
 
-  *     ])
 
-  *     ->run();
 
-  * ```
 
-  *
 
-  * or
 
-  *
 
-  * ```php
 
-  * echo Table::widget([
 
-  *     'headers' => ['test1', 'test2', 'test3'],
 
-  *     'rows' => [
 
-  *         ['col1', 'col2', 'col3'],
 
-  *         ['col1', 'col2', ['col3-0', 'col3-1', 'col3-2']],
 
-  *     ],
 
-  * ]);
 
-  *
 
-  * @author Daniel Gomez Pan <pana_1990@hotmail.com>
 
-  * @since 2.0.13
 
-  */
 
- class Table extends Widget
 
- {
 
-     const DEFAULT_CONSOLE_SCREEN_WIDTH = 120;
 
-     const CONSOLE_SCROLLBAR_OFFSET = 3;
 
-     const CHAR_TOP = 'top';
 
-     const CHAR_TOP_MID = 'top-mid';
 
-     const CHAR_TOP_LEFT = 'top-left';
 
-     const CHAR_TOP_RIGHT = 'top-right';
 
-     const CHAR_BOTTOM = 'bottom';
 
-     const CHAR_BOTTOM_MID = 'bottom-mid';
 
-     const CHAR_BOTTOM_LEFT = 'bottom-left';
 
-     const CHAR_BOTTOM_RIGHT = 'bottom-right';
 
-     const CHAR_LEFT = 'left';
 
-     const CHAR_LEFT_MID = 'left-mid';
 
-     const CHAR_MID = 'mid';
 
-     const CHAR_MID_MID = 'mid-mid';
 
-     const CHAR_RIGHT = 'right';
 
-     const CHAR_RIGHT_MID = 'right-mid';
 
-     const CHAR_MIDDLE = 'middle';
 
-     /**
 
-      * @var array table headers
 
-      * @since 2.0.19
 
-      */
 
-     protected $headers = [];
 
-     /**
 
-      * @var array table rows
 
-      * @since 2.0.19
 
-      */
 
-     protected $rows = [];
 
-     /**
 
-      * @var array table chars
 
-      * @since 2.0.19
 
-      */
 
-     protected $chars = [
 
-         self::CHAR_TOP => '═',
 
-         self::CHAR_TOP_MID => '╤',
 
-         self::CHAR_TOP_LEFT => '╔',
 
-         self::CHAR_TOP_RIGHT => '╗',
 
-         self::CHAR_BOTTOM => '═',
 
-         self::CHAR_BOTTOM_MID => '╧',
 
-         self::CHAR_BOTTOM_LEFT => '╚',
 
-         self::CHAR_BOTTOM_RIGHT => '╝',
 
-         self::CHAR_LEFT => '║',
 
-         self::CHAR_LEFT_MID => '╟',
 
-         self::CHAR_MID => '─',
 
-         self::CHAR_MID_MID => '┼',
 
-         self::CHAR_RIGHT => '║',
 
-         self::CHAR_RIGHT_MID => '╢',
 
-         self::CHAR_MIDDLE => '│',
 
-     ];
 
-     /**
 
-      * @var array table column widths
 
-      * @since 2.0.19
 
-      */
 
-     protected $columnWidths = [];
 
-     /**
 
-      * @var int screen width
 
-      * @since 2.0.19
 
-      */
 
-     protected $screenWidth;
 
-     /**
 
-      * @var string list prefix
 
-      * @since 2.0.19
 
-      */
 
-     protected $listPrefix = '• ';
 
-     /**
 
-      * Set table headers.
 
-      *
 
-      * @param array $headers table headers
 
-      * @return $this
 
-      */
 
-     public function setHeaders(array $headers)
 
-     {
 
-         $this->headers = array_values($headers);
 
-         return $this;
 
-     }
 
-     /**
 
-      * Set table rows.
 
-      *
 
-      * @param array $rows table rows
 
-      * @return $this
 
-      */
 
-     public function setRows(array $rows)
 
-     {
 
-         $this->rows = array_map('array_values', $rows);
 
-         return $this;
 
-     }
 
-     /**
 
-      * Set table chars.
 
-      *
 
-      * @param array $chars table chars
 
-      * @return $this
 
-      */
 
-     public function setChars(array $chars)
 
-     {
 
-         $this->chars = $chars;
 
-         return $this;
 
-     }
 
-     /**
 
-      * Set screen width.
 
-      *
 
-      * @param int $width screen width
 
-      * @return $this
 
-      */
 
-     public function setScreenWidth($width)
 
-     {
 
-         $this->screenWidth = $width;
 
-         return $this;
 
-     }
 
-     /**
 
-      * Set list prefix.
 
-      *
 
-      * @param string $listPrefix list prefix
 
-      * @return $this
 
-      */
 
-     public function setListPrefix($listPrefix)
 
-     {
 
-         $this->listPrefix = $listPrefix;
 
-         return $this;
 
-     }
 
-     /**
 
-      * @return string the rendered table
 
-      */
 
-     public function run()
 
-     {
 
-         $this->calculateRowsSize();
 
-         $headerCount = count($this->headers);
 
-         $buffer = $this->renderSeparator(
 
-             $this->chars[self::CHAR_TOP_LEFT],
 
-             $this->chars[self::CHAR_TOP_MID],
 
-             $this->chars[self::CHAR_TOP],
 
-             $this->chars[self::CHAR_TOP_RIGHT]
 
-         );
 
-         // Header
 
-         if ($headerCount > 0) {
 
-             $buffer .= $this->renderRow($this->headers,
 
-                 $this->chars[self::CHAR_LEFT],
 
-                 $this->chars[self::CHAR_MIDDLE],
 
-                 $this->chars[self::CHAR_RIGHT]
 
-             );
 
-         }
 
-         // Content
 
-         foreach ($this->rows as $i => $row) {
 
-             if ($i > 0 || $headerCount > 0) {
 
-                 $buffer .= $this->renderSeparator(
 
-                     $this->chars[self::CHAR_LEFT_MID],
 
-                     $this->chars[self::CHAR_MID_MID],
 
-                     $this->chars[self::CHAR_MID],
 
-                     $this->chars[self::CHAR_RIGHT_MID]
 
-                 );
 
-             }
 
-             $buffer .= $this->renderRow($row,
 
-                 $this->chars[self::CHAR_LEFT],
 
-                 $this->chars[self::CHAR_MIDDLE],
 
-                 $this->chars[self::CHAR_RIGHT]);
 
-         }
 
-         $buffer .= $this->renderSeparator(
 
-             $this->chars[self::CHAR_BOTTOM_LEFT],
 
-             $this->chars[self::CHAR_BOTTOM_MID],
 
-             $this->chars[self::CHAR_BOTTOM],
 
-             $this->chars[self::CHAR_BOTTOM_RIGHT]
 
-         );
 
-         return $buffer;
 
-     }
 
-     /**
 
-      * Renders a row of data into a string.
 
-      *
 
-      * @param array $row row of data
 
-      * @param string $spanLeft character for left border
 
-      * @param string $spanMiddle character for middle border
 
-      * @param string $spanRight character for right border
 
-      * @return string
 
-      * @see \yii\console\widgets\Table::render()
 
-      */
 
-     protected function renderRow(array $row, $spanLeft, $spanMiddle, $spanRight)
 
-     {
 
-         $size = $this->columnWidths;
 
-         $buffer = '';
 
-         $arrayPointer = [];
 
-         $finalChunk = [];
 
-         for ($i = 0, ($max = $this->calculateRowHeight($row)) ?: $max = 1; $i < $max; $i++) {
 
-             $buffer .= $spanLeft . ' ';
 
-             foreach ($size as $index => $cellSize) {
 
-                 $cell = isset($row[$index]) ? $row[$index] : null;
 
-                 $prefix = '';
 
-                 if ($index !== 0) {
 
-                     $buffer .= $spanMiddle . ' ';
 
-                 }
 
-                 if (is_array($cell)) {
 
-                     if (empty($finalChunk[$index])) {
 
-                         $finalChunk[$index] = '';
 
-                         $start = 0;
 
-                         $prefix = $this->listPrefix;
 
-                         if (!isset($arrayPointer[$index])) {
 
-                             $arrayPointer[$index] = 0;
 
-                         }
 
-                     } else {
 
-                         $start = mb_strwidth($finalChunk[$index], Yii::$app->charset);
 
-                     }
 
-                     $chunk = mb_substr($cell[$arrayPointer[$index]], $start, $cellSize - 4, Yii::$app->charset);
 
-                     $finalChunk[$index] .= $chunk;
 
-                     if (isset($cell[$arrayPointer[$index] + 1]) && $finalChunk[$index] === $cell[$arrayPointer[$index]]) {
 
-                         $arrayPointer[$index]++;
 
-                         $finalChunk[$index] = '';
 
-                     }
 
-                 } else {
 
-                     $chunk = mb_substr($cell, ($cellSize * $i) - ($i * 2), $cellSize - 2, Yii::$app->charset);
 
-                 }
 
-                 $chunk = $prefix . $chunk;
 
-                 $repeat = $cellSize - mb_strwidth($chunk, Yii::$app->charset) - 1;
 
-                 $buffer .= $chunk;
 
-                 if ($repeat >= 0) {
 
-                     $buffer .= str_repeat(' ', $repeat);
 
-                 }
 
-             }
 
-             $buffer .= "$spanRight\n";
 
-         }
 
-         return $buffer;
 
-     }
 
-     /**
 
-      * Renders separator.
 
-      *
 
-      * @param string $spanLeft character for left border
 
-      * @param string $spanMid character for middle border
 
-      * @param string $spanMidMid character for middle-middle border
 
-      * @param string $spanRight character for right border
 
-      * @return string the generated separator row
 
-      * @see \yii\console\widgets\Table::render()
 
-      */
 
-     protected function renderSeparator($spanLeft, $spanMid, $spanMidMid, $spanRight)
 
-     {
 
-         $separator = $spanLeft;
 
-         foreach ($this->columnWidths as $index => $rowSize) {
 
-             if ($index !== 0) {
 
-                 $separator .= $spanMid;
 
-             }
 
-             $separator .= str_repeat($spanMidMid, $rowSize);
 
-         }
 
-         $separator .= $spanRight . "\n";
 
-         return $separator;
 
-     }
 
-     /**
 
-      * Calculate the size of rows to draw anchor of columns in console.
 
-      *
 
-      * @see \yii\console\widgets\Table::render()
 
-      */
 
-     protected function calculateRowsSize()
 
-     {
 
-         $this->columnWidths = $columns = [];
 
-         $totalWidth = 0;
 
-         $screenWidth = $this->getScreenWidth() - self::CONSOLE_SCROLLBAR_OFFSET;
 
-         $headerCount = count($this->headers);
 
-         if (empty($this->rows)) {
 
-             $rowColCount = 0;
 
-         } else {
 
-             $rowColCount = max(array_map('count', $this->rows));
 
-         }
 
-         $count = max($headerCount, $rowColCount);
 
-         for ($i = 0; $i < $count; $i++) {
 
-             $columns[] = ArrayHelper::getColumn($this->rows, $i);
 
-             if ($i < $headerCount) {
 
-                 $columns[$i][] = $this->headers[$i];
 
-             }
 
-         }
 
-         foreach ($columns as $column) {
 
-             $columnWidth = max(array_map(function ($val) {
 
-                 if (is_array($val)) {
 
-                     $encodings = array_fill(0, count($val), Yii::$app->charset);
 
-                     return max(array_map('mb_strwidth', $val, $encodings)) + mb_strwidth($this->listPrefix, Yii::$app->charset);
 
-                 }
 
-                 return mb_strwidth($val, Yii::$app->charset);
 
-             }, $column)) + 2;
 
-             $this->columnWidths[] = $columnWidth;
 
-             $totalWidth += $columnWidth;
 
-         }
 
-         $relativeWidth = $screenWidth / $totalWidth;
 
-         if ($totalWidth > $screenWidth) {
 
-             foreach ($this->columnWidths as $j => $width) {
 
-                 $this->columnWidths[$j] = (int) ($width * $relativeWidth);
 
-                 if ($j === count($this->columnWidths)) {
 
-                     $this->columnWidths = $totalWidth;
 
-                 }
 
-                 $totalWidth -= $this->columnWidths[$j];
 
-             }
 
-         }
 
-     }
 
-     /**
 
-      * Calculate the height of a row.
 
-      *
 
-      * @param array $row
 
-      * @return int maximum row per cell
 
-      * @see \yii\console\widgets\Table::render()
 
-      */
 
-     protected function calculateRowHeight($row)
 
-     {
 
-         $rowsPerCell = array_map(function ($size, $columnWidth) {
 
-             if (is_array($columnWidth)) {
 
-                 $rows = 0;
 
-                 foreach ($columnWidth as $width) {
 
-                     $rows += ceil($width / ($size - 2));
 
-                 }
 
-                 return $rows;
 
-             }
 
-             return ceil($columnWidth / ($size - 2));
 
-         }, $this->columnWidths, array_map(function ($val) {
 
-             if (is_array($val)) {
 
-                 $encodings = array_fill(0, count($val), Yii::$app->charset);
 
-                 return array_map('mb_strwidth', $val, $encodings);
 
-             }
 
-             return mb_strwidth($val, Yii::$app->charset);
 
-         }, $row)
 
-         );
 
-         return max($rowsPerCell);
 
-     }
 
-     /**
 
-      * Getting screen width.
 
-      * If it is not able to determine screen width, default value `123` will be set.
 
-      *
 
-      * @return int screen width
 
-      */
 
-     protected function getScreenWidth()
 
-     {
 
-         if (!$this->screenWidth) {
 
-             $size = Console::getScreenSize();
 
-             $this->screenWidth = isset($size[0])
 
-                 ? $size[0]
 
-                 : self::DEFAULT_CONSOLE_SCREEN_WIDTH + self::CONSOLE_SCROLLBAR_OFFSET;
 
-         }
 
-         return $this->screenWidth;
 
-     }
 
- }
 
 
  |