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. // | Copyright (c) 2002-2003 Richard Heyes                                 |
  4. // | All rights reserved.                                                  |
  5. // |                                                                       |
  6. // | Redistribution and use in source and binary forms, with or without    |
  7. // | modification, are permitted provided that the following conditions    |
  8. // | are met:                                                              |
  9. // |                                                                       |
  10. // | o Redistributions of source code must retain the above copyright      |
  11. // |   notice, this list of conditions and the following disclaimer.       |
  12. // | o Redistributions in binary form must reproduce the above copyright   |
  13. // |   notice, this list of conditions and the following disclaimer in the |
  14. // |   documentation and/or other materials provided with the distribution.|
  15. // | o The names of the authors may not be used to endorse or promote      |
  16. // |   products derived from this software without specific prior written  |
  17. // |   permission.                                                         |
  18. // |                                                                       |
  19. // | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   |
  20. // | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT     |
  21. // | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
  22. // | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT  |
  23. // | OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
  24. // | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT      |
  25. // | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
  26. // | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
  27. // | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT   |
  28. // | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
  29. // | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  |
  30. // |                                                                       |
  31. // +-----------------------------------------------------------------------+
  32. // | Author: Richard Heyes <richard@phpguru.org>                           |
  33. // +-----------------------------------------------------------------------+
  34. //
  35. // $Id: Table.php,v 1.8 2005/07/16 16:54:44 richard Exp $
  36. //
  37. // Utility for printing tables from cmdline scripts
  38. //
  39.  
  40. define('CONSOLE_TABLE_HORIZONTAL_RULE'1);
  41. define('CONSOLE_TABLE_ALIGN_LEFT'-1);
  42. define('CONSOLE_TABLE_ALIGN_CENTER'0);
  43. define('CONSOLE_TABLE_ALIGN_RIGHT'1);
  44.  
  45. class Console_Table
  46. {
  47.     /**
  48.     * The table headers
  49.     * @var array 
  50.     */
  51.     var $_headers;
  52.  
  53.  
  54.     /**
  55.     * The data of the table
  56.     * @var array 
  57.     */
  58.     var $_data;
  59.  
  60.  
  61.     /**
  62.     * The max number of columns in a row
  63.     * @var integer 
  64.     */
  65.     var $_max_cols;
  66.  
  67.  
  68.     /**
  69.     * The max number of rows in the table
  70.     * @var integer 
  71.     */
  72.     var $_max_rows;
  73.  
  74.  
  75.     /**
  76.     * Lengths of the columns, calculated
  77.     * when rows are added to the table.
  78.     * @var array 
  79.     */
  80.     var $_cell_lengths;
  81.  
  82.  
  83.     /**
  84.     * Some options that configure various
  85.     * things
  86.     * @var array; 
  87.     */
  88.     var $_options;
  89.  
  90.  
  91.     /**
  92.     * How many spaces to use to pad the table
  93.     * @var integer 
  94.     */
  95.     var $_padding;
  96.  
  97.  
  98.     /**
  99.     * Column filters
  100.     * @var array 
  101.     */
  102.     var $_filters;
  103.  
  104.  
  105.     /**
  106.     * Columns to calculate totals for
  107.     * @var array 
  108.     */
  109.     var $_calculateTotals;
  110.  
  111.  
  112.     /**
  113.     * Alignment of the columns
  114.     * @var array 
  115.     */
  116.     var $_col_align;
  117.  
  118.  
  119.     /**
  120.     * Default alignment of columns
  121.     * @var int 
  122.     */
  123.     var $_defaultAlign;
  124.  
  125.  
  126.     /**
  127.     * Constructor
  128.     *
  129.     * @param int $align Default alignment
  130.     */
  131.     function Console_Table($align = CONSOLE_TABLE_ALIGN_LEFT)
  132.     {
  133.         $this->_headers      = array();
  134.         $this->_data         = array();
  135.         $this->_cell_lengths = array();
  136.         $this->_max_cols     = 0;
  137.         $this->_max_rows     = 0;
  138.         $this->_padding      = 1;
  139.         $this->_filters      = array();
  140.         $this->_col_align    = array();
  141.         $this->_defaultAlign $align;
  142.     }
  143.  
  144.  
  145.     /**
  146.     * Converts an array to a table. Must be a two dimensional array.
  147.     * (Static)
  148.     *
  149.     * @param array $headers      Headers for the table
  150.     * @param array $data         Data for the table
  151.     * @param bool  $returnObject Whether to return the Console_Table object (default: No)
  152.     */
  153.     function fromArray($headers$data$returnObject = false)
  154.     {
  155.         if (!is_array($headersOR !is_array($data)) {
  156.             return false;
  157.         }
  158.  
  159.         $table &new Console_Table();
  160.         $table->setHeaders($headers);
  161.  
  162.         foreach ($data as $row{
  163.             $table->addRow(array_values($row));
  164.         }
  165.  
  166.         return $returnObject $table $table->getTable();
  167.     }
  168.  
  169.  
  170.     /**
  171.     * Adds a filter to the object. Filters are standard php callbacks which are
  172.     * run on the data before table generation is performed. Filters are applied
  173.     * in the order they're added. the callback function must accept a single
  174.     * argument, which is a single table cell.
  175.     *
  176.     * @param int      $col      Column to apply filter to
  177.     * @param callback $callback PHP callback to apply
  178.     */
  179.     function addFilter($col&$callback)
  180.     {
  181.         $this->_filters[= array($col&$callback);
  182.     }
  183.  
  184.  
  185.     /**
  186.     * Sets the alignment for the columns
  187.     * @param integer $col_id Column ID
  188.     * @param integer $align  Alignment to set for this column
  189.     *                         -1 = left, 0 = center, 1 = right
  190.     *                        OR use the constants:
  191.     *                       CONSOLE_TABLE_ALIGN_LEFT
  192.     *                       CONSOLE_TABLE_ALIGN_CENTER
  193.     *                       CONSOLE_TABLE_ALIGN_RIGHT
  194.     */
  195.     function setAlign($col_id$align = CONSOLE_TABLE_ALIGN_LEFT)
  196.     {
  197.         // -1 = left, 0 = center, 1 = right
  198.         if ($align == CONSOLE_TABLE_ALIGN_CENTER{
  199.             $pad = STR_PAD_BOTH;
  200.  
  201.         elseif ($align == CONSOLE_TABLE_ALIGN_RIGHT{
  202.             $pad = STR_PAD_LEFT;
  203.  
  204.         else {
  205.             $pad = STR_PAD_RIGHT;
  206.         }
  207.         $this->_col_align[$col_id$pad;
  208.     }
  209.  
  210.  
  211.     /**
  212.     * Specifies which columns are to have totals calculated for them and
  213.     * added as a new row at the bottom.
  214.     *
  215.     * @param array $cols Array of column IDs (0 is first column, 1 is second etc)
  216.     */
  217.     function calculateTotalsFor($cols)
  218.     {
  219.         $this->_calculateTotals $cols;
  220.     }
  221.  
  222.  
  223.     /**
  224.     * Sets the headers for the columns
  225.     *
  226.     * @param array $headers The column headers
  227.     */
  228.     function setHeaders($headers)
  229.     {
  230.         $this->_headers $headers;
  231.         $this->_updateRowsCols($headers);
  232.     }
  233.  
  234.  
  235.     /**
  236.     * Adds a row to the table
  237.     *
  238.     * @param array $row    The row data to add
  239.     * @param array $append Whether to append or prepend the row
  240.     */
  241.     function addRow($row$append = true)
  242.     {
  243.         $append $this->_data[array_values($rowarray_unshift($this->_dataarray_values($row));
  244.  
  245.         $this->_updateRowsCols($row);
  246.     }
  247.  
  248.  
  249.     /**
  250.     * Inserts a row after a given row number in the table. If $row_id
  251.     * is not given it will prepend the row.
  252.     *
  253.     * @param array   $row    The data to insert
  254.     * @param integer $row_id Row number to insert before
  255.     */
  256.     function insertRow($row$row_id = 0)
  257.     {
  258.         array_splice($this->_data$row_id0array($row));
  259.  
  260.         $this->_updateRowsCols($row);
  261.     }
  262.  
  263.  
  264.     /**
  265.     * Adds a column to the table
  266.     *
  267.     * @param array   $col_data The data of the column. Can be numeric or associative array
  268.     * @param integer $col_id   The column index to populate
  269.     * @param integer $row_id   If starting row is not zero, specify it here
  270.     */
  271.     function addCol($col_data$col_id = 0$row_id = 0)
  272.     {
  273.         foreach ($col_data as $col_cell{
  274.             $this->_data[$row_id++][$col_id$col_cell;
  275.         }
  276.  
  277.         $this->_updateRowsCols();
  278.         $this->_max_cols max($this->_max_cols$col_id + 1);
  279.     }
  280.  
  281.  
  282.     /**
  283.     * Adds data to the table. Argument should be
  284.     * a two dimensional array containing the data
  285.     * to be added.
  286.     *
  287.     * @param array   $data   The data to add to the table
  288.     * @param integer $col_id Optional starting column ID
  289.     * @param integer $row_id Optional starting row ID
  290.     */
  291.     function addData($data$col_id = 0$row_id = 0)
  292.     {
  293.         foreach ($data as $row{
  294.             $starting_col $col_id;
  295.             foreach ($row as $cell{
  296.                 $this->_data[$row_id][$starting_col++$cell;
  297.             }
  298.             $this->_updateRowsCols();
  299.             $this->_max_cols max($this->_max_cols$starting_col);
  300.             $row_id++;
  301.         }
  302.     }
  303.  
  304.  
  305.     /**
  306.     * Adds a Horizontal Seperator to the table
  307.     */
  308.     function addSeparator()
  309.     {
  310.         $this->_data[CONSOLE_TABLE_HORIZONTAL_RULE;
  311.     }
  312.  
  313.  
  314.     /**
  315.     * Returns the table in wonderful
  316.     * ASCII art
  317.     */
  318.     function getTable()
  319.     {
  320.         $this->_applyFilters();
  321.         $this->_calculateTotals();
  322.         $this->_validateTable();
  323.  
  324.         return $this->_buildTable();
  325.     }
  326.  
  327.  
  328.     /**
  329.     * Calculates totals for columns
  330.     */
  331.     function _calculateTotals()
  332.     {
  333.         if (!empty($this->_calculateTotals)) {
  334.  
  335.             $this->addSeparator();
  336.  
  337.             $totals = array();
  338.  
  339.             foreach ($this->_data as $row{
  340.                 if (is_array($row)) {
  341.                     foreach ($this->_calculateTotals as $columnID{
  342.                         $totals[$columnID+= $row[$columnID];
  343.                     }
  344.                 }
  345.             }
  346.  
  347.             $this->_data[$totals;
  348.             $this->_updateRowsCols();
  349.         }
  350.     }
  351.  
  352.  
  353.     /**
  354.     * Applies any column filters to the data
  355.     */
  356.     function _applyFilters()
  357.     {
  358.         if (!empty($this->_filters)) {
  359.             foreach ($this->_filters as $filter{
  360.                 $column   $filter[0];
  361.                 $callback $filter[1];
  362.  
  363.                 foreach ($this->_data as $row_id => $row_data{
  364.                     $this->_data[$row_id][$columncall_user_func($callback$row_data[$column]);
  365.                 }
  366.             }
  367.         }
  368.     }
  369.  
  370.  
  371.     /**
  372.     * Ensures column and row counts are correct
  373.     */
  374.     function _validateTable()
  375.     {
  376.         for ($i=0; $i<$this->_max_rows$i++{
  377.             for ($j=0; $j<$this->_max_cols$j++{
  378.                 if (!isset($this->_data[$i][$j]AND $this->_data[$i!= CONSOLE_TABLE_HORIZONTAL_RULE{
  379.                     $this->_data[$i][$j'';
  380.                 }
  381.  
  382.                 // Update cell lengths
  383.                 $this->_calculateCellLengths($this->_data[$i]);
  384.             }
  385.  
  386.             if ($this->_data[$i!= CONSOLE_TABLE_HORIZONTAL_RULE{
  387.                  ksort($this->_data[$i]);
  388.             }
  389.  
  390.         }
  391.  
  392.         ksort($this->_data);
  393.     }
  394.  
  395.  
  396.     /**
  397.     * Builds the table
  398.     */
  399.     function _buildTable()
  400.     {
  401.         $return = array();
  402.         $rows   $this->_data;
  403.  
  404.         for ($i=0; $i<count($rows)$i++{
  405.             for ($j=0; $j<count($rows[$i])$j++{
  406.                 if ($rows[$i!= CONSOLE_TABLE_HORIZONTAL_RULE AND strlen($rows[$i][$j]$this->_cell_lengths[$j]{
  407.                     $rows[$i][$jstr_pad($rows[$i][$j]$this->_cell_lengths[$j]' '$this->_col_align[$j]);
  408.                 }
  409.             }
  410.  
  411.             if ($rows[$i!= CONSOLE_TABLE_HORIZONTAL_RULE{
  412.                 $row_begin    '|' str_repeat(' '$this->_padding);
  413.                 $row_end      str_repeat(' '$this->_padding'|';
  414.                 $implode_char str_repeat(' '$this->_padding'|' str_repeat(' '$this->_padding);
  415.                 $return[$row_begin implode($implode_char$rows[$i]$row_end;
  416.             else {
  417.                 $return[$this->_getSeparator();
  418.             }
  419.  
  420.         }
  421.  
  422.         $return $this->_getSeparator("\r\n" implode("\n"$return"\r\n" $this->_getSeparator("\r\n";
  423.  
  424.         if (!empty($this->_headers)) {
  425.             $return $this->_getHeaderLine(.  "\r\n" $return;
  426.         }
  427.  
  428.         return $return;
  429.     }
  430.  
  431.  
  432.     /**
  433.     * Creates a horizontal separator for header
  434.     * separation and table start/end etc
  435.     *
  436.     */
  437.     function _getSeparator()
  438.     {
  439.         foreach ($this->_cell_lengths as $cl{
  440.             $return[str_repeat('-'$cl);
  441.         }
  442.  
  443.         $row_begin    '+' str_repeat('-'$this->_padding);
  444.         $row_end      str_repeat('-'$this->_padding'+';
  445.         $implode_char str_repeat('-'$this->_padding'+' str_repeat('-'$this->_padding);
  446.  
  447.         $return $row_begin implode($implode_char$return$row_end;
  448.  
  449.         return $return;
  450.     }
  451.  
  452.  
  453.     /**
  454.     * Returns header line for the table
  455.     */
  456.     function _getHeaderLine()
  457.     {
  458.         // Make sure column count is correct
  459.         for ($i=0;  $i<$this->_max_cols$i++{
  460.             if (!isset($this->_headers[$i])) {
  461.                 $this->_headers[$i'';
  462.             }
  463.         }
  464.  
  465.         for ($i=0; $i<count($this->_headers)$i++{
  466.             if (strlen($this->_headers[$i]$this->_cell_lengths[$i]{
  467.                 $this->_headers[$istr_pad($this->_headers[$i]$this->_cell_lengths[$i]' '$this->_col_align[$i]);
  468.             }
  469.         }
  470.  
  471.         $row_begin    '|' str_repeat(' '$this->_padding);
  472.         $row_end      str_repeat(' '$this->_padding'|';
  473.         $implode_char str_repeat(' '$this->_padding'|' str_repeat(' '$this->_padding);
  474.  
  475.         $return[$this->_getSeparator();
  476.         $return[$row_begin implode($implode_char$this->_headers$row_end;
  477.  
  478.         return implode("\r\n"$return);
  479.     }
  480.  
  481.  
  482.     /**
  483.     * Update max cols/rows
  484.     */
  485.     function _updateRowsCols($rowdata = null)
  486.     {
  487.         // Update max cols
  488.         $this->_max_cols max($this->_max_colscount($rowdata));
  489.  
  490.         // Update max rows
  491.         ksort($this->_data);
  492.         $this->_max_rows end(array_keys($this->_data)) + 1;
  493.  
  494.         switch ($this->_defaultAlign{
  495.             case CONSOLE_TABLE_ALIGN_CENTER$pad = STR_PAD_BOTH; break;
  496.             case CONSOLE_TABLE_ALIGN_RIGHT:  $pad = STR_PAD_LEFT; break;
  497.             default:
  498.             case CONSOLE_TABLE_ALIGN_LEFT:   $pad = STR_PAD_RIGHT; break;
  499.         }
  500.  
  501.         // Set default column alignments
  502.         for ($i count($this->_col_align)$i<$this->_max_cols$i++{
  503.             $this->_col_align[$i$pad;
  504.         }
  505.  
  506.     }
  507.  
  508.  
  509.     /**
  510.     * This function given a row of data will
  511.     * calculate the max length for each column
  512.     * and store it in the _cell_lengths array.
  513.     *
  514.     * @param array $row The row data
  515.     */
  516.     function _calculateCellLengths($row)
  517.     {
  518.         for ($i=0; $i<count($row)$i++{
  519.             $this->_cell_lengths[$imax(strlen(@$this->_headers[$i])@$this->_cell_lengths[$i]strlen(@$row[$i]));
  520.         }
  521.     }
  522. }
  523. ?>

Documentation generated on Mon, 11 Mar 2019 14:17:10 -0400 by phpDocumentor 1.4.4. PEAR Logo Copyright © PHP Group 2004.