Console_Table
[ class tree: Console_Table ] [ index: Console_Table ] [ all elements ]

Source for file Table.php

Documentation is available at Table.php

  1. <?php
  2. /**
  3.  * Utility for printing tables from commandline scripts.
  4.  *
  5.  * PHP versions 4 and 5
  6.  *
  7.  * All rights reserved.
  8.  *
  9.  * Redistribution and use in source and binary forms, with or without
  10.  * modification, are permitted provided that the following conditions are met:
  11.  *
  12.  * o Redistributions of source code must retain the above copyright notice,
  13.  *   this list of conditions and the following disclaimer.
  14.  * o Redistributions in binary form must reproduce the above copyright notice,
  15.  *   this list of conditions and the following disclaimer in the documentation
  16.  *   and/or other materials provided with the distribution.
  17.  * o The names of the authors may not be used to endorse or promote products
  18.  *   derived from this software without specific prior written permission.
  19.  *
  20.  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
  21.  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  22.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  23.  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  24.  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  25.  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  26.  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  27.  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  28.  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  29.  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  30.  * POSSIBILITY OF SUCH DAMAGE.
  31.  *
  32.  * @category  Console
  33.  * @package   Console_Table
  34.  * @author    Richard Heyes <richard@phpguru.org>
  35.  * @author    Jan Schneider <jan@horde.org>
  36.  * @copyright 2002-2005 Richard Heyes
  37.  * @copyright 2006-2008 Jan Schneider
  38.  * @license   http://www.debian.org/misc/bsd.license  BSD License (3 Clause)
  39.  * @version   CVS: $Id$
  40.  * @link      http://pear.php.net/package/Console_Table
  41.  */
  42.  
  43. define('CONSOLE_TABLE_HORIZONTAL_RULE'1);
  44. define('CONSOLE_TABLE_ALIGN_LEFT'-1);
  45. define('CONSOLE_TABLE_ALIGN_CENTER'0);
  46. define('CONSOLE_TABLE_ALIGN_RIGHT'1);
  47. define('CONSOLE_TABLE_BORDER_ASCII'-1);
  48.  
  49. /**
  50.  * The main class.
  51.  *
  52.  * @category Console
  53.  * @package  Console_Table
  54.  * @author   Jan Schneider <jan@horde.org>
  55.  * @license  http://www.debian.org/misc/bsd.license  BSD License (3 Clause)
  56.  * @link     http://pear.php.net/package/Console_Table
  57.  */
  58. {
  59.     /**
  60.      * The table headers.
  61.      *
  62.      * @var array 
  63.      */
  64.     var $_headers = array();
  65.  
  66.     /**
  67.      * The data of the table.
  68.      *
  69.      * @var array 
  70.      */
  71.     var $_data = array();
  72.  
  73.     /**
  74.      * The maximum number of columns in a row.
  75.      *
  76.      * @var integer 
  77.      */
  78.     var $_max_cols = 0;
  79.  
  80.     /**
  81.      * The maximum number of rows in the table.
  82.      *
  83.      * @var integer 
  84.      */
  85.     var $_max_rows = 0;
  86.  
  87.     /**
  88.      * Lengths of the columns, calculated when rows are added to the table.
  89.      *
  90.      * @var array 
  91.      */
  92.     var $_cell_lengths = array();
  93.  
  94.     /**
  95.      * Heights of the rows.
  96.      *
  97.      * @var array 
  98.      */
  99.     var $_row_heights = array();
  100.  
  101.     /**
  102.      * How many spaces to use to pad the table.
  103.      *
  104.      * @var integer 
  105.      */
  106.     var $_padding = 1;
  107.  
  108.     /**
  109.      * Column filters.
  110.      *
  111.      * @var array 
  112.      */
  113.     var $_filters = array();
  114.  
  115.     /**
  116.      * Columns to calculate totals for.
  117.      *
  118.      * @var array 
  119.      */
  120.     var $_calculateTotals;
  121.  
  122.     /**
  123.      * Alignment of the columns.
  124.      *
  125.      * @var array 
  126.      */
  127.     var $_col_align = array();
  128.  
  129.     /**
  130.      * Default alignment of columns.
  131.      *
  132.      * @var integer 
  133.      */
  134.     var $_defaultAlign;
  135.  
  136.     /**
  137.      * Character set of the data.
  138.      *
  139.      * @var string 
  140.      */
  141.     var $_charset 'utf-8';
  142.  
  143.     /**
  144.      * Border character.
  145.      *
  146.      * @var string 
  147.      */
  148.     var $_border = CONSOLE_TABLE_BORDER_ASCII;
  149.  
  150.     /**
  151.      * Whether the data has ANSI colors.
  152.      *
  153.      * @var boolean 
  154.      */
  155.     var $_ansiColor = false;
  156.  
  157.     /**
  158.      * Constructor.
  159.      *
  160.      * @param integer $align   Default alignment. One of
  161.      *                          CONSOLE_TABLE_ALIGN_LEFT,
  162.      *                          CONSOLE_TABLE_ALIGN_CENTER or
  163.      *                          CONSOLE_TABLE_ALIGN_RIGHT.
  164.      * @param string  $border  The character used for table borders or
  165.      *                          CONSOLE_TABLE_BORDER_ASCII.
  166.      * @param integer $padding How many spaces to use to pad the table.
  167.      * @param string  $charset A charset supported by the mbstring PHP
  168.      *                          extension.
  169.      * @param boolean $color   Whether the data contains ansi color codes.
  170.      */
  171.     function Console_Table($align = CONSOLE_TABLE_ALIGN_LEFT,
  172.                            $border = CONSOLE_TABLE_BORDER_ASCII$padding = 1,
  173.                            $charset = null$color = false)
  174.     {
  175.         $this->_defaultAlign $align;
  176.         $this->_border       $border;
  177.         $this->_padding      $padding;
  178.         $this->_ansiColor    $color;
  179.         if ($this->_ansiColor{
  180.             include_once 'Console/Color.php';
  181.         }
  182.         if (!empty($charset)) {
  183.             $this->setCharset($charset);
  184.         }
  185.     }
  186.  
  187.     /**
  188.      * Converts an array to a table.
  189.      *
  190.      * @param array   $headers      Headers for the table.
  191.      * @param array   $data         A two dimensional array with the table
  192.      *                               data.
  193.      * @param boolean $returnObject Whether to return the Console_Table object
  194.      *                               instead of the rendered table.
  195.      *
  196.      * @static
  197.      *
  198.      * @return Console_Table|string A Console_Table object or the generated
  199.      *                                table.
  200.      */
  201.     function fromArray($headers$data$returnObject = false)
  202.     {
  203.         if (!is_array($headers|| !is_array($data)) {
  204.             return false;
  205.         }
  206.  
  207.         $table = new Console_Table();
  208.         $table->setHeaders($headers);
  209.  
  210.         foreach ($data as $row{
  211.             $table->addRow($row);
  212.         }
  213.  
  214.         return $returnObject $table $table->getTable();
  215.     }
  216.  
  217.     /**
  218.      * Adds a filter to a column.
  219.      *
  220.      * Filters are standard PHP callbacks which are run on the data before
  221.      * table generation is performed. Filters are applied in the order they
  222.      * are added. The callback function must accept a single argument, which
  223.      * is a single table cell.
  224.      *
  225.      * @param integer $col       Column to apply filter to.
  226.      * @param mixed   &$callback PHP callback to apply.
  227.      *
  228.      * @return void 
  229.      */
  230.     function addFilter($col&$callback)
  231.     {
  232.         $this->_filters[= array($col&$callback);
  233.     }
  234.  
  235.     /**
  236.      * Sets the charset of the provided table data.
  237.      *
  238.      * @param string $charset A charset supported by the mbstring PHP
  239.      *                         extension.
  240.      *
  241.      * @return void 
  242.      */
  243.     function setCharset($charset)
  244.     {
  245.         $locale setlocale(LC_CTYPE0);
  246.         setlocale(LC_CTYPE'en_US');
  247.         $this->_charset strtolower($charset);
  248.         setlocale(LC_CTYPE$locale);
  249.     }
  250.  
  251.     /**
  252.      * Sets the alignment for the columns.
  253.      *
  254.      * @param integer $col_id The column number.
  255.      * @param integer $align  Alignment to set for this column. One of
  256.      *                         CONSOLE_TABLE_ALIGN_LEFT
  257.      *                         CONSOLE_TABLE_ALIGN_CENTER
  258.      *                         CONSOLE_TABLE_ALIGN_RIGHT.
  259.      *
  260.      * @return void 
  261.      */
  262.     function setAlign($col_id$align = CONSOLE_TABLE_ALIGN_LEFT)
  263.     {
  264.         switch ($align{
  265.         case CONSOLE_TABLE_ALIGN_CENTER:
  266.             $pad = STR_PAD_BOTH;
  267.             break;
  268.         case CONSOLE_TABLE_ALIGN_RIGHT:
  269.             $pad = STR_PAD_LEFT;
  270.             break;
  271.         default:
  272.             $pad = STR_PAD_RIGHT;
  273.             break;
  274.         }
  275.         $this->_col_align[$col_id$pad;
  276.     }
  277.  
  278.     /**
  279.      * Specifies which columns are to have totals calculated for them and
  280.      * added as a new row at the bottom.
  281.      *
  282.      * @param array $cols Array of column numbers (starting with 0).
  283.      *
  284.      * @return void 
  285.      */
  286.     function calculateTotalsFor($cols)
  287.     {
  288.         $this->_calculateTotals $cols;
  289.     }
  290.  
  291.     /**
  292.      * Sets the headers for the columns.
  293.      *
  294.      * @param array $headers The column headers.
  295.      *
  296.      * @return void 
  297.      */
  298.     function setHeaders($headers)
  299.     {
  300.         $this->_headers = array(array_values($headers));
  301.         $this->_updateRowsCols($headers);
  302.     }
  303.  
  304.     /**
  305.      * Adds a row to the table.
  306.      *
  307.      * @param array   $row    The row data to add.
  308.      * @param boolean $append Whether to append or prepend the row.
  309.      *
  310.      * @return void 
  311.      */
  312.     function addRow($row$append = true)
  313.     {
  314.         if ($append{
  315.             $this->_data[array_values($row);
  316.         else {
  317.             array_unshift($this->_dataarray_values($row));
  318.         }
  319.  
  320.         $this->_updateRowsCols($row);
  321.     }
  322.  
  323.     /**
  324.      * Inserts a row after a given row number in the table.
  325.      *
  326.      * If $row_id is not given it will prepend the row.
  327.      *
  328.      * @param array   $row    The data to insert.
  329.      * @param integer $row_id Row number to insert before.
  330.      *
  331.      * @return void 
  332.      */
  333.     function insertRow($row$row_id = 0)
  334.     {
  335.         array_splice($this->_data$row_id0array($row));
  336.  
  337.         $this->_updateRowsCols($row);
  338.     }
  339.  
  340.     /**
  341.      * Adds a column to the table.
  342.      *
  343.      * @param array   $col_data The data of the column.
  344.      * @param integer $col_id   The column index to populate.
  345.      * @param integer $row_id   If starting row is not zero, specify it here.
  346.      *
  347.      * @return void 
  348.      */
  349.     function addCol($col_data$col_id = 0$row_id = 0)
  350.     {
  351.         foreach ($col_data as $col_cell{
  352.             $this->_data[$row_id++][$col_id$col_cell;
  353.         }
  354.  
  355.         $this->_updateRowsCols();
  356.         $this->_max_cols max($this->_max_cols$col_id + 1);
  357.     }
  358.  
  359.     /**
  360.      * Adds data to the table.
  361.      *
  362.      * @param array   $data   A two dimensional array with the table data.
  363.      * @param integer $col_id Starting column number.
  364.      * @param integer $row_id Starting row number.
  365.      *
  366.      * @return void 
  367.      */
  368.     function addData($data$col_id = 0$row_id = 0)
  369.     {
  370.         foreach ($data as $row{
  371.             if ($row === CONSOLE_TABLE_HORIZONTAL_RULE{
  372.                 $this->_data[$row_idCONSOLE_TABLE_HORIZONTAL_RULE;
  373.                 $row_id++;
  374.                 continue;
  375.             }
  376.             $starting_col $col_id;
  377.             foreach ($row as $cell{
  378.                 $this->_data[$row_id][$starting_col++$cell;
  379.             }
  380.             $this->_updateRowsCols();
  381.             $this->_max_cols max($this->_max_cols$starting_col);
  382.             $row_id++;
  383.         }
  384.     }
  385.  
  386.     /**
  387.      * Adds a horizontal seperator to the table.
  388.      *
  389.      * @return void 
  390.      */
  391.     function addSeparator()
  392.     {
  393.         $this->_data[CONSOLE_TABLE_HORIZONTAL_RULE;
  394.     }
  395.  
  396.     /**
  397.      * Returns the generated table.
  398.      *
  399.      * @return string  The generated table.
  400.      */
  401.     function getTable()
  402.     {
  403.         $this->_applyFilters();
  404.         $this->_calculateTotals();
  405.         $this->_validateTable();
  406.  
  407.         return $this->_buildTable();
  408.     }
  409.  
  410.     /**
  411.      * Calculates totals for columns.
  412.      *
  413.      * @return void 
  414.      */
  415.     function _calculateTotals()
  416.     {
  417.         if (empty($this->_calculateTotals)) {
  418.             return;
  419.         }
  420.  
  421.         $this->addSeparator();
  422.  
  423.         $totals = array();
  424.         foreach ($this->_data as $row{
  425.             if (is_array($row)) {
  426.                 foreach ($this->_calculateTotals as $columnID{
  427.                     $totals[$columnID+= $row[$columnID];
  428.                 }
  429.             }
  430.         }
  431.  
  432.         $this->_data[$totals;
  433.         $this->_updateRowsCols();
  434.     }
  435.  
  436.     /**
  437.      * Applies any column filters to the data.
  438.      *
  439.      * @return void 
  440.      */
  441.     function _applyFilters()
  442.     {
  443.         if (empty($this->_filters)) {
  444.             return;
  445.         }
  446.  
  447.         foreach ($this->_filters as $filter{
  448.             $column   $filter[0];
  449.             $callback $filter[1];
  450.  
  451.             foreach ($this->_data as $row_id => $row_data{
  452.                 if ($row_data !== CONSOLE_TABLE_HORIZONTAL_RULE{
  453.                     $this->_data[$row_id][$column=
  454.                         call_user_func($callback$row_data[$column]);
  455.                 }
  456.             }
  457.         }
  458.     }
  459.  
  460.     /**
  461.      * Ensures that column and row counts are correct.
  462.      *
  463.      * @return void 
  464.      */
  465.     function _validateTable()
  466.     {
  467.         if (!empty($this->_headers)) {
  468.             $this->_calculateRowHeight(-1$this->_headers[0]);
  469.         }
  470.  
  471.         for ($i = 0; $i $this->_max_rows$i++{
  472.             for ($j = 0; $j $this->_max_cols$j++{
  473.                 if (!isset($this->_data[$i][$j]&&
  474.                     (!isset($this->_data[$i]||
  475.                      $this->_data[$i!== CONSOLE_TABLE_HORIZONTAL_RULE)) {
  476.                     $this->_data[$i][$j'';
  477.                 }
  478.  
  479.             }
  480.             $this->_calculateRowHeight($i$this->_data[$i]);
  481.  
  482.             if ($this->_data[$i!== CONSOLE_TABLE_HORIZONTAL_RULE{
  483.                  ksort($this->_data[$i]);
  484.             }
  485.  
  486.         }
  487.  
  488.         $this->_splitMultilineRows();
  489.  
  490.         // Update cell lengths.
  491.         for ($i = 0; $i count($this->_headers)$i++{
  492.             $this->_calculateCellLengths($this->_headers[$i]);
  493.         }
  494.         for ($i = 0; $i $this->_max_rows$i++{
  495.             $this->_calculateCellLengths($this->_data[$i]);
  496.         }
  497.  
  498.         ksort($this->_data);
  499.     }
  500.  
  501.     /**
  502.      * Splits multiline rows into many smaller one-line rows.
  503.      *
  504.      * @return void 
  505.      */
  506.     function _splitMultilineRows()
  507.     {
  508.         ksort($this->_data);
  509.         $sections          = array(&$this->_headers&$this->_data);
  510.         $max_rows          = array(count($this->_headers)$this->_max_rows);
  511.         $row_height_offset = array(-10);
  512.  
  513.         for ($s = 0; $s <= 1; $s++{
  514.             $inserted = 0;
  515.             $new_data $sections[$s];
  516.  
  517.             for ($i = 0; $i $max_rows[$s]$i++{
  518.                 // Process only rows that have many lines.
  519.                 $height $this->_row_heights[$i $row_height_offset[$s]];
  520.                 if ($height > 1{
  521.                     // Split column data into one-liners.
  522.                     $split = array();
  523.                     for ($j = 0; $j $this->_max_cols$j++{
  524.                         $split[$jpreg_split('/\r?\n|\r/',
  525.                                                 $sections[$s][$i][$j]);
  526.                     }
  527.  
  528.                     $new_rows = array();
  529.                     // Construct new 'virtual' rows - insert empty strings for
  530.                     // columns that have less lines that the highest one.
  531.                     for ($i2 = 0; $i2 $height$i2++{
  532.                         for ($j = 0; $j $this->_max_cols$j++{
  533.                             $new_rows[$i2][$j!isset($split[$j][$i2])
  534.                                 ? ''
  535.                                 : $split[$j][$i2];
  536.                         }
  537.                     }
  538.  
  539.                     // Replace current row with smaller rows.  $inserted is
  540.                     // used to take account of bigger array because of already
  541.                     // inserted rows.
  542.                     array_splice($new_data$i $inserted1$new_rows);
  543.                     $inserted += count($new_rows- 1;
  544.                 }
  545.             }
  546.  
  547.             // Has the data been modified?
  548.             if ($inserted > 0{
  549.                 $sections[$s$new_data;
  550.                 $this->_updateRowsCols();
  551.             }
  552.         }
  553.     }
  554.  
  555.     /**
  556.      * Builds the table.
  557.      *
  558.      * @return string  The generated table string.
  559.      */
  560.     function _buildTable()
  561.     {
  562.         if (!count($this->_data)) {
  563.             return '';
  564.         }
  565.  
  566.         $rule      $this->_border == CONSOLE_TABLE_BORDER_ASCII
  567.             ? '|'
  568.             : $this->_border;
  569.         $separator $this->_getSeparator();
  570.  
  571.         $return = array();
  572.         for ($i = 0; $i count($this->_data)$i++{
  573.             for ($j = 0; $j count($this->_data[$i])$j++{
  574.                 if ($this->_data[$i!== CONSOLE_TABLE_HORIZONTAL_RULE &&
  575.                     $this->_strlen($this->_data[$i][$j]<
  576.                     $this->_cell_lengths[$j]{
  577.                     $this->_data[$i][$j$this->_strpad($this->_data[$i][$j],
  578.                                                           $this->_cell_lengths[$j],
  579.                                                           ' ',
  580.                                                           $this->_col_align[$j]);
  581.                 }
  582.             }
  583.  
  584.             if ($this->_data[$i!== CONSOLE_TABLE_HORIZONTAL_RULE{
  585.                 $row_begin    $rule str_repeat(' '$this->_padding);
  586.                 $row_end      str_repeat(' '$this->_padding$rule;
  587.                 $implode_char str_repeat(' '$this->_padding$rule
  588.                     . str_repeat(' '$this->_padding);
  589.                 $return[]     $row_begin
  590.                     . implode($implode_char$this->_data[$i]$row_end;
  591.             elseif (!empty($separator)) {
  592.                 $return[$separator;
  593.             }
  594.  
  595.         }
  596.  
  597.         $return implode("\r\n"$return);
  598.         if (!empty($separator)) {
  599.             $return $separator "\r\n" $return "\r\n" $separator;
  600.         }
  601.         $return .= "\r\n";
  602.  
  603.         if (!empty($this->_headers)) {
  604.             $return $this->_getHeaderLine(.  "\r\n" $return;
  605.         }
  606.  
  607.         return $return;
  608.     }
  609.  
  610.     /**
  611.      * Creates a horizontal separator for header separation and table
  612.      * start/end etc.
  613.      *
  614.      * @return string  The horizontal separator.
  615.      */
  616.     function _getSeparator()
  617.     {
  618.         if (!$this->_border{
  619.             return;
  620.         }
  621.  
  622.         if ($this->_border == CONSOLE_TABLE_BORDER_ASCII{
  623.             $rule '-';
  624.             $sect '+';
  625.         else {
  626.             $rule $sect $this->_border;
  627.         }
  628.  
  629.         $return = array();
  630.         foreach ($this->_cell_lengths as $cl{
  631.             $return[str_repeat($rule$cl);
  632.         }
  633.  
  634.         $row_begin    $sect str_repeat($rule$this->_padding);
  635.         $row_end      str_repeat($rule$this->_padding$sect;
  636.         $implode_char str_repeat($rule$this->_padding$sect
  637.             . str_repeat($rule$this->_padding);
  638.  
  639.         return $row_begin implode($implode_char$return$row_end;
  640.     }
  641.  
  642.     /**
  643.      * Returns the header line for the table.
  644.      *
  645.      * @return string  The header line of the table.
  646.      */
  647.     function _getHeaderLine()
  648.     {
  649.         // Make sure column count is correct
  650.         for ($j = 0; $j count($this->_headers)$j++{
  651.             for ($i = 0; $i $this->_max_cols$i++{
  652.                 if (!isset($this->_headers[$j][$i])) {
  653.                     $this->_headers[$j][$i'';
  654.                 }
  655.             }
  656.         }
  657.  
  658.         for ($j = 0; $j count($this->_headers)$j++{
  659.             for ($i = 0; $i count($this->_headers[$j])$i++{
  660.                 if ($this->_strlen($this->_headers[$j][$i]<
  661.                     $this->_cell_lengths[$i]{
  662.                     $this->_headers[$j][$i=
  663.                         $this->_strpad($this->_headers[$j][$i],
  664.                                        $this->_cell_lengths[$i],
  665.                                        ' ',
  666.                                        $this->_col_align[$i]);
  667.                 }
  668.             }
  669.         }
  670.  
  671.         $rule         $this->_border == CONSOLE_TABLE_BORDER_ASCII
  672.             ? '|'
  673.             : $this->_border;
  674.         $row_begin    $rule str_repeat(' '$this->_padding);
  675.         $row_end      str_repeat(' '$this->_padding$rule;
  676.         $implode_char str_repeat(' '$this->_padding$rule
  677.             . str_repeat(' '$this->_padding);
  678.  
  679.         $separator $this->_getSeparator();
  680.         if (!empty($separator)) {
  681.             $return[$separator;
  682.         }
  683.         for ($j = 0; $j count($this->_headers)$j++{
  684.             $return[$row_begin
  685.                 . implode($implode_char$this->_headers[$j]$row_end;
  686.         }
  687.  
  688.         return implode("\r\n"$return);
  689.     }
  690.  
  691.     /**
  692.      * Updates values for maximum columns and rows.
  693.      *
  694.      * @param array $rowdata Data array of a single row.
  695.      *
  696.      * @return void 
  697.      */
  698.     function _updateRowsCols($rowdata = null)
  699.     {
  700.         // Update maximum columns.
  701.         $this->_max_cols max($this->_max_colscount($rowdata));
  702.  
  703.         // Update maximum rows.
  704.         ksort($this->_data);
  705.         $keys            array_keys($this->_data);
  706.         $this->_max_rows end($keys+ 1;
  707.  
  708.         switch ($this->_defaultAlign{
  709.         case CONSOLE_TABLE_ALIGN_CENTER:
  710.             $pad = STR_PAD_BOTH;
  711.             break;
  712.         case CONSOLE_TABLE_ALIGN_RIGHT:
  713.             $pad = STR_PAD_LEFT;
  714.             break;
  715.         default:
  716.             $pad = STR_PAD_RIGHT;
  717.             break;
  718.         }
  719.  
  720.         // Set default column alignments
  721.         for ($i count($this->_col_align)$i $this->_max_cols$i++{
  722.             $this->_col_align[$i$pad;
  723.         }
  724.     }
  725.  
  726.     /**
  727.      * Calculates the maximum length for each column of a row.
  728.      *
  729.      * @param array $row The row data.
  730.      *
  731.      * @return void 
  732.      */
  733.     function _calculateCellLengths($row)
  734.     {
  735.         for ($i = 0; $i count($row)$i++{
  736.             if (!isset($this->_cell_lengths[$i])) {
  737.                 $this->_cell_lengths[$i= 0;
  738.             }
  739.             $this->_cell_lengths[$imax($this->_cell_lengths[$i],
  740.                                            $this->_strlen($row[$i]));
  741.         }
  742.     }
  743.  
  744.     /**
  745.      * Calculates the maximum height for all columns of a row.
  746.      *
  747.      * @param integer $row_number The row number.
  748.      * @param array   $row        The row data.
  749.      *
  750.      * @return void 
  751.      */
  752.     function _calculateRowHeight($row_number$row)
  753.     {
  754.         if (!isset($this->_row_heights[$row_number])) {
  755.             $this->_row_heights[$row_number= 1;
  756.         }
  757.  
  758.         // Do not process horizontal rule rows.
  759.         if ($row === CONSOLE_TABLE_HORIZONTAL_RULE{
  760.             return;
  761.         }
  762.  
  763.         for ($i = 0$c count($row)$i $c; ++$i{
  764.             $lines                           preg_split('/\r?\n|\r/'$row[$i]);
  765.             $this->_row_heights[$row_numbermax($this->_row_heights[$row_number],
  766.                                                    count($lines));
  767.         }
  768.     }
  769.  
  770.     /**
  771.      * Returns the character length of a string.
  772.      *
  773.      * @param string $str A multibyte or singlebyte string.
  774.      *
  775.      * @return integer  The string length.
  776.      */
  777.     function _strlen($str)
  778.     {
  779.         static $mbstring;
  780.  
  781.         // Strip ANSI color codes if requested.
  782.         if ($this->_ansiColor{
  783.             $str = Console_Color::strip($str);
  784.         }
  785.  
  786.         // Cache expensive function_exists() calls.
  787.         if (!isset($mbstring)) {
  788.             $mbstring function_exists('mb_strwidth');
  789.         }
  790.  
  791.         if ($mbstring{
  792.             return mb_strwidth($str$this->_charset);
  793.         }
  794.  
  795.         return strlen($str);
  796.     }
  797.  
  798.     /**
  799.      * Returns part of a string.
  800.      *
  801.      * @param string  $string The string to be converted.
  802.      * @param integer $start  The part's start position, zero based.
  803.      * @param integer $length The part's length.
  804.      *
  805.      * @return string  The string's part.
  806.      */
  807.     function _substr($string$start$length = null)
  808.     {
  809.         static $mbstring;
  810.  
  811.         // Cache expensive function_exists() calls.
  812.         if (!isset($mbstring)) {
  813.             $mbstring function_exists('mb_substr');
  814.         }
  815.  
  816.         if (is_null($length)) {
  817.             $length $this->_strlen($string);
  818.         }
  819.         if ($mbstring{
  820.             $ret @mb_substr($string$start$length$this->_charset);
  821.             if (!empty($ret)) {
  822.                 return $ret;
  823.             }
  824.         }
  825.         return substr($string$start$length);
  826.     }
  827.  
  828.     /**
  829.      * Returns a string padded to a certain length with another string.
  830.      *
  831.      * This method behaves exactly like str_pad but is multibyte safe.
  832.      *
  833.      * @param string  $input  The string to be padded.
  834.      * @param integer $length The length of the resulting string.
  835.      * @param string  $pad    The string to pad the input string with. Must
  836.      *                         be in the same charset like the input string.
  837.      * @param const   $type   The padding type. One of STR_PAD_LEFT,
  838.      *                         STR_PAD_RIGHT, or STR_PAD_BOTH.
  839.      *
  840.      * @return string  The padded string.
  841.      */
  842.     function _strpad($input$length$pad ' '$type = STR_PAD_RIGHT)
  843.     {
  844.         $mb_length  $this->_strlen($input);
  845.         $sb_length  strlen($input);
  846.         $pad_length $this->_strlen($pad);
  847.  
  848.         /* Return if we already have the length. */
  849.         if ($mb_length >= $length{
  850.             return $input;
  851.         }
  852.  
  853.         /* Shortcut for single byte strings. */
  854.         if ($mb_length == $sb_length && $pad_length == strlen($pad)) {
  855.             return str_pad($input$length$pad$type);
  856.         }
  857.  
  858.         switch ($type{
  859.         case STR_PAD_LEFT:
  860.             $left   $length $mb_length;
  861.             $output $this->_substr(str_repeat($padceil($left $pad_length)),
  862.                                      0$left$this->_charset$input;
  863.             break;
  864.         case STR_PAD_BOTH:
  865.             $left   floor(($length $mb_length/ 2);
  866.             $right  ceil(($length $mb_length/ 2);
  867.             $output $this->_substr(str_repeat($padceil($left $pad_length)),
  868.                                      0$left$this->_charset.
  869.                 $input .
  870.                 $this->_substr(str_repeat($padceil($right $pad_length)),
  871.                                0$right$this->_charset);
  872.             break;
  873.         case STR_PAD_RIGHT:
  874.             $right  $length $mb_length;
  875.             $output $input .
  876.                 $this->_substr(str_repeat($padceil($right $pad_length)),
  877.                                0$right$this->_charset);
  878.             break;
  879.         }
  880.  
  881.         return $output;
  882.     }
  883.  
  884. }

Documentation generated on Fri, 07 Dec 2012 15:00:03 +0000 by phpDocumentor 1.4.3. PEAR Logo Copyright © PHP Group 2004.