Apache Zeta Components Manual :: File Source for table.php

Source for file table.php

Documentation is available at table.php

  1. <?php
  2. /**
  3.  * File containing the ezcConsoleTable class.
  4.  *
  5.  * Licensed to the Apache Software Foundation (ASF) under one
  6.  * or more contributor license agreements.  See the NOTICE file
  7.  * distributed with this work for additional information
  8.  * regarding copyright ownership.  The ASF licenses this file
  9.  * to you under the Apache License, Version 2.0 (the
  10.  * "License"); you may not use this file except in compliance
  11.  * with the License.  You may obtain a copy of the License at
  12.  * 
  13.  *   http://www.apache.org/licenses/LICENSE-2.0
  14.  * 
  15.  * Unless required by applicable law or agreed to in writing,
  16.  * software distributed under the License is distributed on an
  17.  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  18.  * KIND, either express or implied.  See the License for the
  19.  * specific language governing permissions and limitations
  20.  * under the License.
  21.  *
  22.  * @package ConsoleTools
  23.  * @version //autogentag//
  24.  * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0
  25.  * @filesource
  26.  */
  27.  
  28. /**
  29.  * Creating tables to be printed to the console.
  30.  *
  31.  * Every ezcConsoleTable object can be accessed as if it was a multidimensional,
  32.  * numerically indexed array. The first dimension represents the rows of the
  33.  * table, so $table[0] gives you access to the first row of the table, which is
  34.  * represented by a {@link ezcConsoleTableRow} object. You can access its
  35.  * properties directly, using e.g. $table[0]->format. The second dimension gives
  36.  * you direct access to the cells of your table, like $table[0][0] accesses the
  37.  * first cell in the first row of your table. You can access its properties
  38.  * diretly here, too. This works like e.g. $table[0][0]->format. Table row and
  39.  * cell objects are created on the fly, when you access them for the first time.
  40.  * You can also create them as if you simply create new array elements. E.g.
  41.  * $table[] creates a new row in the table.
  42.  *
  43.  * <code>
  44.  * // Initialize the console output handler
  45.  * $out = new ezcConsoleOutput();
  46.  * // Define a new format "headline"
  47.  * $out->formats->headline->color = 'red';
  48.  * $out->formats->headline->style = array( 'bold' );
  49.  * // Define a new format "sum"
  50.  * $out->formats->sum->color = 'blue';
  51.  * $out->formats->sum->style = array( 'negative' );
  52.  * 
  53.  * // Create a new table
  54.  * $table = new ezcConsoleTable( $out, 60 );
  55.  * 
  56.  * // Create first row and in it the first cell
  57.  * $table[0][0]->content = 'Headline 1';
  58.  * 
  59.  * // Create 3 more cells in row 0
  60.  * for ( $i = 2; $i < 5; $i++ )
  61.  * {
  62.  *      $table[0][]->content = "Headline $i";
  63.  * }
  64.  * 
  65.  * $data = array( 1, 2, 3, 4 );
  66.  * 
  67.  * // Create some more data in the table...
  68.  * foreach ( $data as $value )
  69.  * {
  70.  *      // Create a new row each time and set it's contents to the actual value
  71.  *      $table[][0]->content = $value;
  72.  * }
  73.  * 
  74.  * // Set another border format for our headline row
  75.  * $table[0]->borderFormat = 'headline';
  76.  * 
  77.  * // Set the content format for all cells of the 3rd row to "sum"
  78.  * $table[2]->format = 'sum';
  79.  * 
  80.  * $table->outputTable();
  81.  * </code>
  82.  * 
  83.  * @property ezcConsoleTableOptions $options 
  84.  *            Contains the options for this class.
  85.  * @property int $width 
  86.  *            Width of the table.
  87.  *
  88.  * @see ezcConsoleOutput
  89.  * @package ConsoleTools
  90.  * @version //autogen//
  91.  * @mainclass
  92.  */
  93. class ezcConsoleTable implements CountableIteratorArrayAccess
  94. {
  95.     /**
  96.      * Automatically wrap text to fit into a column.
  97.      * @see ezcConsoleTable::$options
  98.      */
  99.     const WRAP_AUTO 1;
  100.  
  101.     /**
  102.      * Do not wrap text. Columns will be extended to fit the largest text.
  103.      * ATTENTION: This is risky!
  104.      * @see ezcConsoleTable::$options
  105.      */
  106.     const WRAP_NONE 2;
  107.  
  108.     /**
  109.      * Text will be cut to fit into a column.
  110.      * @see ezcConsoleTable::$options
  111.      */
  112.     const WRAP_CUT  3;
  113.     
  114.     /**
  115.      * Align text in the default direction.
  116.      */
  117.     const ALIGN_DEFAULT = -1;
  118.     /**
  119.      * Align text in cells to the right.
  120.      */
  121.     const ALIGN_LEFT   STR_PAD_RIGHT;
  122.     /**
  123.      * Align text in cells to the left.
  124.      */
  125.     const ALIGN_RIGHT  STR_PAD_LEFT;
  126.     /**
  127.      * Align text in cells to the center.
  128.      */
  129.     const ALIGN_CENTER STR_PAD_BOTH;
  130.  
  131.     /**
  132.      * The width given by settings must be used even if the data allows it smaller.
  133.      */
  134.     const WIDTH_FIXED 1;
  135.     /**
  136.      * The width given by settings is a maximum value, if data allows it, the table gets smaller.
  137.      */
  138.     const WIDTH_MAX 2;
  139.  
  140.     /**
  141.      * Container to hold the properties
  142.      *
  143.      * @var array(string=>mixed) 
  144.      */
  145.     protected $properties;
  146.  
  147.     /**
  148.      * The ezcConsoleOutput object to use.
  149.      *
  150.      * @var ezcConsoleOutput 
  151.      */
  152.     protected $outputHandler;
  153.  
  154.     /**
  155.      * Collection of the rows that are contained in the table.
  156.      * 
  157.      * @var array(ezcConsoleTableRow) 
  158.      */
  159.     protected $rows;
  160.  
  161.     /**
  162.      * Tool object for multi-byte encoding safe string operations.
  163.      * 
  164.      * @var ezcConsoleStringTool 
  165.      */
  166.     private $stringTool;
  167.  
  168.     /**
  169.      * Creates a new table.
  170.      *
  171.      * @param ezcConsoleOutput $outHandler Output handler to utilize
  172.      * @param int $width                   Overall width of the table (chars).
  173.      * @param array $options               Options
  174.      *
  175.      * @see ezcConsoleTable::$options
  176.      *
  177.      * @throws ezcBaseValueException On an invalid setting.
  178.      */
  179.     public function __constructezcConsoleOutput $outHandler$width$options array() ) 
  180.     {
  181.         $this->rows = array();
  182.         $this->outputHandler = $outHandler;
  183.         $this->stringTool new ezcConsoleStringTool();
  184.  
  185.         $this->__set'width'$width );
  186.         if $options instanceof ezcConsoleTableOptions )
  187.         {
  188.             $this->properties['options'$options;
  189.         }
  190.         else if is_array$options ) )
  191.         {
  192.             $this->properties['options'new ezcConsoleTableOptions$options );
  193.         }
  194.         else
  195.         {
  196.             throw new ezcBaseValueException"options"$options"array" );
  197.         }
  198.     }
  199.  
  200.     /**
  201.      * Set new options.
  202.      * This method allows you to change the options of the table.
  203.      *
  204.      * @param ezcConsoleTableOptions $options The options to set.
  205.      *
  206.      * @throws ezcBaseSettingNotFoundException
  207.      *          If you tried to set a non-existent option value.
  208.      * @throws ezcBaseSettingValueException
  209.      *          If the value is not valid for the desired option.
  210.      * @throws ezcBaseValueException
  211.      *          If you submit neither an array nor an instance of
  212.      *          ezcConsoleTableOptions.
  213.      */
  214.     public function setOptions$options array() ) 
  215.     {
  216.         if is_array$options ) ) 
  217.         {
  218.             $this->properties['options']->merge$options );
  219.         
  220.         else if $options instanceof ezcConsoleTableOptions 
  221.         {
  222.             $this->properties['options'$options;
  223.         }
  224.         else
  225.         {
  226.             throw new ezcBaseValueException"options"$options"instance of ezcConsoleTableOptions" );
  227.         }
  228.     }
  229.  
  230.     /**
  231.      * Returns the current options.
  232.      * Returns the options currently set for this table.
  233.      * 
  234.      * @return ezcConsoleTableOptions The current options.
  235.      */
  236.     public function getOptions()
  237.     {
  238.         return $this->properties['options'];
  239.     }
  240.  
  241.     /**
  242.      * Returns the table in an array.
  243.      *
  244.      * Returns the entire table as an array of printable lines. Each element of
  245.      * the array represents a physical line of the drawn table, including all
  246.      * borders and stuff, so you can simply print the table using
  247.      * <code>
  248.      * echo implode( "\n" , $table->getTable() ):
  249.      * </code>
  250.      * which is basically what {@link ezcConsoleTable::outputTable()} does.
  251.      *
  252.      * @return array An array representation of the table.
  253.      */
  254.     public function getTable()
  255.     {
  256.         return $this->generateTable();
  257.     }
  258.  
  259.     /**
  260.      * Output the table.
  261.      * Prints the complete table to the console.
  262.      *
  263.      * @return void 
  264.      */
  265.     public function outputTable(
  266.     {
  267.         echo implodePHP_EOL$this->generateTable() );
  268.     }
  269.  
  270.     /**
  271.      * Returns the table in a string.
  272.      *
  273.      * @return string 
  274.      */
  275.     public function __toString()
  276.     {
  277.         return implodePHP_EOL$this->generateTable() );
  278.     }
  279.  
  280.     /**
  281.      * Returns if the given offset exists.
  282.      * This method is part of the ArrayAccess interface to allow access to the
  283.      * data of this object as if it was an array.
  284.      * 
  285.      * @param int $offset The offset to check.
  286.      * @return bool True when the offset exists, otherwise false.
  287.      * 
  288.      * @throws ezcBaseValueException
  289.      *          If a non numeric row ID is requested.
  290.      */
  291.     public function offsetExists$offset )
  292.     {
  293.         if !is_int$offset || $offset )
  294.         {
  295.             throw new ezcBaseValueException'offset'$offset'int >= 0' );
  296.         }
  297.         return isset$this->rows[$offset);
  298.     }
  299.  
  300.     // From here only interface method implementations follow, which are not intended for direct usage
  301.  
  302.     /**
  303.      * Returns the element with the given offset.
  304.      * This method is part of the ArrayAccess interface to allow access to the
  305.      * data of this object as if it was an array. In case of the
  306.      * ezcConsoleTable class this method always returns a valid row object
  307.      * since it creates them on the fly, if a given item does not exist.
  308.      * 
  309.      * @param int $offset The offset to check.
  310.      * @return ezcConsoleTableCell 
  311.      *
  312.      * @throws ezcBaseValueException
  313.      *          If a non numeric row ID is requested.
  314.      */
  315.     public function offsetGet$offset )
  316.     {
  317.         $offset $offset === null count$this->rows $offset;
  318.         if !is_int$offset || $offset 0  )
  319.         {
  320.             throw new ezcBaseValueException'offset'$offset'int >= 0 or null' );
  321.         }
  322.         if !isset$this->rows[$offset) )
  323.         {
  324.             $this->rows[$offsetnew ezcConsoleTableRow();
  325.         }
  326.         return $this->rows[$offset];
  327.     }
  328.  
  329.     /**
  330.      * Set the element with the given offset.
  331.      * This method is part of the ArrayAccess interface to allow access to the
  332.      * data of this object as if it was an array.
  333.      * 
  334.      * @param int $offset               The offset to assign an item to.
  335.      * @param ezcConsoleTableRow $value The row to assign.
  336.      * @return void 
  337.      *
  338.      * @throws ezcBaseValueException
  339.      *          If a non numeric row ID is requested.
  340.      * @throws ezcBaseValueException
  341.      *          If the provided value is not of type {@link ezcConsoleTableRow}.
  342.      */
  343.     public function offsetSet$offset$value )
  344.     {
  345.         if !$value instanceof ezcConsoleTableRow ) )
  346.         {
  347.             throw new ezcBaseValueException'value'$value'ezcConsoleTableRow' );
  348.         }
  349.         if !isset$offset ) )
  350.         {
  351.             $offset count$this );
  352.         }
  353.         if !is_int$offset || $offset )
  354.         {
  355.             throw new ezcBaseValueException'offset'$offset'int >= 0' );
  356.         }
  357.         $this->rows[$offset$value;
  358.     }
  359.  
  360.     /**
  361.      * Unset the element with the given offset.
  362.      * This method is part of the ArrayAccess interface to allow access to the
  363.      * data of this object as if it was an array.
  364.      * 
  365.      * @param int $offset The offset to unset the value for.
  366.      * @return void 
  367.      *
  368.      * @throws ezcBaseValueException
  369.      *          If a non numeric row ID is requested.
  370.      */
  371.     public function offsetUnset$offset )
  372.     {
  373.         if !is_int$offset || $offset )
  374.         {
  375.             throw new ezcBaseValueException'offset'$offset'int >= 0' );
  376.         }
  377.         if isset$this->rows[$offset) )
  378.         {
  379.             unset$this->rows[$offset);
  380.         }
  381.     }
  382.  
  383.     /**
  384.      * Returns the number of cells in the row.
  385.      * This method is part of the Countable interface to allow the usage of
  386.      * PHP's count() function to check how many cells this row has.
  387.      *
  388.      * @return int Number of cells in this row.
  389.      */
  390.     public function count()
  391.     {
  392.         $keys array_keys$this->rows );
  393.         return count$keys end$keys 0;
  394.     }
  395.  
  396.     /**
  397.      * Returns the currently selected cell.
  398.      * This method is part of the Iterator interface to allow access to the
  399.      * cells of this row by iterating over it like an array (e.g. using
  400.      * foreach).
  401.      * 
  402.      * @return ezcConsoleTableCell The currently selected cell.
  403.      */
  404.     public function current()
  405.     {
  406.         return current$this->rows );
  407.     }
  408.  
  409.     /**
  410.      * Returns the key of the currently selected cell.
  411.      * This method is part of the Iterator interface to allow access to the
  412.      * cells of this row by iterating over it like an array (e.g. using
  413.      * foreach).
  414.      * 
  415.      * @return int The key of the currently selected cell.
  416.      */
  417.     public function key()
  418.     {
  419.         return key$this->rows );
  420.     }
  421.  
  422.     /**
  423.      * Returns the next cell and selects it or false on the last cell.
  424.      * This method is part of the Iterator interface to allow access to the
  425.      * cells of this row by iterating over it like an array (e.g. using
  426.      * foreach).
  427.      *
  428.      * @return mixed ezcConsoleTableCell if the next cell exists, or false.
  429.      */
  430.     public function next()
  431.     {
  432.         return next$this->rows );
  433.     }
  434.  
  435.     /**
  436.      * Selects the very first cell and returns it.
  437.      * This method is part of the Iterator interface to allow access to the
  438.      * cells of this row by iterating over it like an array (e.g. using
  439.      * foreach).
  440.      *
  441.      * @return ezcConsoleTableCell The very first cell of this row.
  442.      */
  443.     public function rewind()
  444.     {
  445.         return reset$this->rows );
  446.     }
  447.  
  448.     /**
  449.      * Returns if the current cell is valid.
  450.      * This method is part of the Iterator interface to allow access to the
  451.      * cells of this row by iterating over it like an array (e.g. using
  452.      * foreach).
  453.      *
  454.      * @return ezcConsoleTableCell The very first cell of this row.
  455.      */
  456.     public function valid()
  457.     {
  458.         return current$this->rows !== false;
  459.     }
  460.  
  461.     /**
  462.      * Property read access.
  463.      * 
  464.      * @param string $key Name of the property.
  465.      * @return mixed Value of the property or null.
  466.      *
  467.      * @throws ezcBasePropertyNotFoundException
  468.      *          If the the desired property is not found.
  469.      * @ignore
  470.      */
  471.     public function __get$key )
  472.     {
  473.         switch $key )
  474.         {
  475.             case 'options':
  476.             case 'width':
  477.                 return $this->properties[$key];
  478.             default:
  479.                 break;
  480.         }
  481.         throw new ezcBasePropertyNotFoundException$key );
  482.     }
  483.  
  484.     /**
  485.      * Property write access.
  486.      * 
  487.      * @param string $key Name of the property.
  488.      * @param mixed $val  The value for the property.
  489.      *
  490.      * @throws ezcBasePropertyNotFoundException
  491.      *          If a the value for the property options is not an instance of
  492.      * @throws ezcBaseValueException
  493.      *          If a the value for a property is out of range.
  494.      * @ignore
  495.      */
  496.     public function __set$key$val )
  497.     {
  498.         switch $key )
  499.         {
  500.             case 'options':
  501.                 if !$val instanceof ezcConsoleTableOptions ) )
  502.                 {
  503.                     throw new ezcBaseValueException$key$val'ezcConsoleTableOptions' );
  504.                 }
  505.                 $this->properties['options'$val;
  506.                 return;
  507.             case 'width':
  508.                 if $val )
  509.                 {
  510.                     throw new ezcBaseValueException$key$val'int > 0' );
  511.                 }
  512.                 $this->properties[$key$val
  513.                 return;
  514.             default:
  515.                 break;
  516.         }
  517.         throw new ezcBasePropertyNotFoundException$key );
  518.     }
  519.  
  520.     /**
  521.      * Property isset access.
  522.      * 
  523.      * @param string $key Name of the property.
  524.      * @return bool True is the property is set, otherwise false.
  525.      * @ignore
  526.      */
  527.     public function __isset$key )
  528.     {
  529.         switch $key )
  530.         {
  531.             case 'options':
  532.             case 'width':
  533.             case 'cols':
  534.                 return true;
  535.         }
  536.         return false;
  537.     }
  538.  
  539.     /**
  540.      * Generate the complete table as an array.
  541.      * 
  542.      * @return array(string) The table.
  543.      */
  544.     private function generateTable()
  545.     {
  546.         $colWidth $this->getColWidths();
  547.         $table array();
  548.         
  549.         if $this->options->lineVertical !== null )
  550.         {
  551.             $table[$this->generateBorder(
  552.                 $colWidth,
  553.                 isset$this[0$this[0]->borderFormat 'default' )
  554.             );
  555.         }
  556.  
  557.         // Rows submitted by the user
  558.         for $i 0;  $i count$this->rows )$i++ )
  559.         {
  560.             // Auto broken rows
  561.             foreach $this->breakRows$this->rows[$i]$colWidth as $brkRow => $brkCells )
  562.             {
  563.                 $table[$this->generateRow$brkCells$colWidth$this->rows[$i);
  564.             }
  565.             $afterBorderFormat = isset$this->rows[$i 1&& $this->rows[$i 1]->borderFormat != 'default' $this->rows[$i 1]->borderFormat $this->rows[$i]->borderFormat;
  566.             if $this->options->lineVertical !== null )
  567.             {
  568.                 $table[$this->generateBorder$colWidth$afterBorderFormat );
  569.             }
  570.         }
  571.  
  572.         // Empty tables need closing border
  573.         if $this->options->lineVertical !== null && count$this->rows == null )
  574.         {
  575.             $table[$this->generateBorder$colWidth'default' );
  576.         }
  577.  
  578.         return $table
  579.     }
  580.  
  581.     /**
  582.      * Generate top/bottom borders of rows.
  583.      * 
  584.      * @param array(int) $colWidth Array of column width.
  585.      * @param string $format            Format name.
  586.      * @return string The Border string.
  587.      */
  588.     private function generateBorder$colWidth$format )
  589.     {
  590.         $border '';
  591.         foreach $colWidth as $col => $width )
  592.         {
  593.             $border .= $this->options->lineHorizontal !== null $this->properties['options']->corner '' )
  594.                     . str_repeat(
  595.                         $this->properties['options']->lineVertical,
  596.                         $width (
  597.                             iconv_strlen$this->properties['options']->colPadding'UTF-8' )
  598.                         )
  599.             );
  600.         }
  601.         $border .= $this->options->lineHorizontal !== null $this->properties['options']->corner '' );
  602.  
  603.         return $this->formatText$border$format );
  604.     }
  605.  
  606.     /**
  607.      * Generate a single physical row.
  608.      * This method generates the string for a single physical table row.
  609.      * 
  610.      * @param array(string) $cells Cells of the row.
  611.      * @param array(int) $colWidth Calculated columns widths.
  612.      * @param ezcConsoleTableRow $row   The row to generate.
  613.      * @return string The row.
  614.      */
  615.     private function generateRow$cells$colWidth$row )
  616.     {
  617.         $rowData '';
  618.         for $cell 0$cell count$colWidth )$cell++ )
  619.         {
  620.             $align $this->determineAlign$row$cell );
  621.             $format $this->determineFormat$row$cell );
  622.             $borderFormat $this->determineBorderFormat$row );
  623.             
  624.             $data = isset$cells[$cell$cells[$cell'';
  625.             $rowData .= $this->formatText
  626.                             $this->properties['options']->lineHorizontal
  627.                             $borderFormat
  628.                         );
  629.             $rowData .= $this->properties['options']->colPadding;
  630.             $rowData .= $this->formatText(
  631.                             $this->stringTool->strPad$data$colWidth[$cell]' '$align ),
  632.                             $format
  633.                         );
  634.             $rowData .= $this->properties['options']->colPadding;
  635.         }
  636.         $rowData .= $this->formatText$this->properties['options']->lineHorizontal$row->borderFormat );
  637.         return $rowData;
  638.     }
  639.  
  640.     /**
  641.      * Determine the alignment of a cell.
  642.      * Walks the inheritance path upwards to determine the alignment of a
  643.      * cell. Checks first, if the cell has it's own alignment (apart from
  644.      * ezcConsoleTable::ALIGN_DEFAULT). If not, checks the row for an
  645.      * alignment setting and uses the default alignment if not found.
  646.      * 
  647.      * @param ezcConsoleTableRow $row The row this cell belongs to.
  648.      * @param int $cellId             Index of the desired cell.
  649.      * @return int An alignement constant (ezcConsoleTable::ALIGN_*).
  650.      */
  651.     private function determineAlign$row$cellId )
  652.     {
  653.         return $row[$cellId]->align !== ezcConsoleTable::ALIGN_DEFAULT 
  654.             ? $row[$cellId]->align
  655.             : $row->align !== ezcConsoleTable::ALIGN_DEFAULT
  656.                 ? $row->align
  657.                 : $this->properties['options']->defaultAlign !== ezcConsoleTable::ALIGN_DEFAULT
  658.                     ? $this->properties['options']->defaultAlign
  659.                     : ezcConsoleTable::ALIGN_LEFT ) ) );
  660.     }
  661.  
  662.     /**
  663.      * Determine the format of a cells content.
  664.      * Walks the inheritance path upwards to determine the format of a
  665.      * cells content. Checks first, if the cell has it's own format (apart
  666.      * from 'default'). If not, checks the row for a format setting and
  667.      * uses the default format if not found.
  668.      * 
  669.      * @param ezcConsoleTableRow $row The row this cell belongs to.
  670.      * @param int $cellId             Index of the desired cell.
  671.      * @return string A format name.
  672.      */
  673.     private function determineFormat$row$cellId )
  674.     {
  675.         return $row[$cellId]->format != 'default'
  676.             ? $row[$cellId]->format
  677.             : $row->format !== 'default'
  678.                 ? $row->format
  679.                 : $this->properties['options']->defaultFormat ) );
  680.     }
  681.  
  682.     /**
  683.      * Determine the format of a rows border.
  684.      * Walks the inheritance path upwards to determine the format of a
  685.      * rows border. Checks first, if the row has it's own format (apart
  686.      * from 'default'). If not, uses the default format.
  687.      * 
  688.      * @param ezcConsoleTableRow $row   The row this cell belongs to.
  689.      * @return string A format name.
  690.      */
  691.     private function determineBorderFormat$row )
  692.     {
  693.         return $row->borderFormat !== 'default'
  694.             ? $row->borderFormat
  695.             : $this->properties['options']->defaultBorderFormat;
  696.     }
  697.  
  698.     /**
  699.      * Returns auto broken rows from an array of cells.
  700.      * The data provided by a user may not fit into a cell calculated by the
  701.      * class. In this case, the data can be automatically wrapped. The table
  702.      * row then spans over multiple physical console lines.
  703.      * 
  704.      * @param array(string) $cells Array of cells in one row.
  705.      * @param array(int) $colWidth Columns widths array.
  706.      * @return array(string) Physical rows generated out of this row.
  707.      */
  708.     private function breakRows$cells$colWidth 
  709.     {
  710.         $rows array();
  711.         // Iterate through cells of the row
  712.         foreach $colWidth as $cell => $width 
  713.         {
  714.             $data $cells[$cell]->content;
  715.             // Physical row id, start with 0 for each row
  716.             $row 0;
  717.             // Split into multiple physical rows if manual breaks exist
  718.             $dataLines explode"\n"$data );
  719.             foreach $dataLines as $dataLine 
  720.             {
  721.                 // Does the physical row fit?
  722.                 if iconv_strlen$dataLine'UTF-8' $colWidth[$cell) )
  723.                 {
  724.                     switch $this->properties['options']->colWrap )
  725.                     {
  726.                         case ezcConsoleTable::WRAP_AUTO:
  727.                             $subLines explode(
  728.                                 "\n",
  729.                                 $this->stringTool->wordwrap$dataLine$colWidth[$cell]"\n"true )
  730.                             );
  731.                             foreach $subLines as $lineNo => $line )
  732.                             {
  733.                                 $rows[$row++][$cell$line;
  734.                             }
  735.                             break;
  736.                         case ezcConsoleTable::WRAP_CUT:
  737.                             $rows[$row++][$celliconv_substr$dataLine0$colWidth[$cell]'UTF-8' );
  738.                             break;
  739.                         case ezcConsoleTable::WRAP_NONE:
  740.                         default:
  741.                             $rows[$row++][$cell$dataLine;
  742.                             break;
  743.                     }
  744.                 }
  745.                 else
  746.                 {
  747.                     $rows[$row++][$cell$dataLine;
  748.                 }
  749.             }
  750.         }
  751.         return $rows;
  752.     }
  753.  
  754.     /**
  755.      * Determine width of each single column.
  756.      *
  757.      * @return void 
  758.      */
  759.     private function getColWidths()
  760.     {
  761.         if is_array$this->properties['options']->colWidth ) )
  762.         {
  763.             return $this->properties['options']->colWidth;
  764.         }
  765.  
  766.         // Determine number of columns:
  767.         $colCount 0;
  768.         foreach $this->rows as $row )
  769.         {
  770.             $colCount maxsizeof$row )$colCount );
  771.         }
  772.  
  773.         if $colCount === )
  774.         {
  775.             return array$this->width );
  776.         }
  777.  
  778.         $borderWidth iconv_strlen(
  779.             $this->properties['options']->lineHorizontal,
  780.             'UTF-8'
  781.         );
  782.  
  783.         // Subtract border and padding chars from global width
  784.         $globalWidth $this->width
  785.             - 
  786.                 // Per column: 2 * border padding + 1 border
  787.                 $colCount (
  788.                     iconv_strlen$this->properties['options']->colPadding'UTF-8' )
  789.                     + $borderWidth 
  790.                 
  791.               // 1 Additional border
  792.               $borderWidth;
  793.         
  794.         // Width of a column if each is made equal
  795.         $colNormWidth round$globalWidth $colCount );
  796.         $colMaxWidth array();
  797.         
  798.         // Determine the longest data for each column
  799.         foreach $this->rows as $row => $cells )
  800.         {
  801.             foreach $cells as $col => $cell )
  802.             {
  803.                 $contentLength 0;
  804.                 foreach explodePHP_EOL$cell->content as $contentRow )
  805.                 {
  806.                     $contentLength max(
  807.                         $contentLength,
  808.                         iconv_strlen$contentRow'UTF-8' )
  809.                     );
  810.                 }
  811.                 $colMaxWidth[$col= isset$colMaxWidth[$colmax$colMaxWidth[$col]$contentLength $contentLength;
  812.             }
  813.         }
  814.         $colWidth array();
  815.         $colWidthOverflow array();
  816.         $spareWidth 0;
  817.         
  818.         // Make columns best fit
  819.         foreach $colMaxWidth as $col => $maxWidth )
  820.         {
  821.             // Does the largest data of the column fit into the average size 
  822.             // + what we have in spare from earlier columns?
  823.             if $maxWidth <= $colNormWidth $spareWidth ) ) 
  824.             {
  825.                 // We fit in, make the column as large as necessary
  826.                 $colWidth[$col$maxWidth;
  827.                 $spareWidth += $colNormWidth $maxWidth );
  828.             }
  829.             else
  830.             {
  831.                 // Does not fit, use maximal possible width
  832.                 $colWidth[$col]  $colNormWidth $spareWidth;
  833.                 $spareWidth 0;
  834.                 // Store overflow for second processing step
  835.                 $colWidthOverflow[$col$maxWidth $colWidth[$col];
  836.             }
  837.         }
  838.         
  839.         // Do we have spare to give to the columns again?
  840.         if $spareWidth )
  841.         {
  842.             // Second processing step
  843.             if count$colWidthOverflow 0  )
  844.             {
  845.                 $overflowSum array_sum$colWidthOverflow );
  846.                 foreach $colWidthOverflow as $col => $overflow );
  847.                 {
  848.                     $colWidth[$col+= floor$overflow $overflowSum $spareWidth );
  849.                 }
  850.             }
  851.             elseif $this->properties['options']->widthType === ezcConsoleTable::WIDTH_FIXED )
  852.             {
  853.                 $widthSum array_sum$colWidth );
  854.                 foreach $colWidth as $col => $width )
  855.                 {
  856.                     $colWidth[$col+= floor$width $widthSum $spareWidth );
  857.                 }
  858.             }
  859.         }
  860.         
  861.         // Finally sanitize values from rounding issues, if necessary
  862.         if ( ( $colSum array_sum$colWidth ) ) != $globalWidth && $this->properties['options']->widthType === ezcConsoleTable::WIDTH_FIXED )
  863.         {
  864.             $colWidth[count$colWidth 1-= $colSum $globalWidth;
  865.         }
  866.         return $colWidth;
  867.     }
  868.  
  869.     /**
  870.      * Returns the given $text formatted with $format.
  871.      *
  872.      * In case $useFormats is set to false in the output handler, the text is
  873.      * returned as given, without any formatting.
  874.      * 
  875.      * @param string $text 
  876.      * @param string $format 
  877.      * @return string 
  878.      */
  879.     private function formatText$text$format )
  880.     {
  881.         if $this->outputHandler->options->useFormats )
  882.         {
  883.             return $this->outputHandler->formatText$text$format );
  884.         }
  885.         else
  886.         {
  887.             return $text;
  888.         }
  889.     }
  890. }
  891. ?>
Documentation generated by phpDocumentor 1.4.3