samedi 22 octobre 2011

A table printer for the Symfony2 console

Here is a custom class for printing nice tables in the Symfony2 console

<?php
namespace Acme\DemoBundle\Util;

use Symfony\Component\Console\Output\OutputInterface;

class ConsolePrinter
{
    
    static private $channel = null;
    
    // =========================================================================
    //                                  FUNCTIONS
    // =========================================================================
    
    /**
     * public static function printT($body, $head = null)
     * 
     * This function performs the full print of the table
     * 
     * @author      Antoine Durieux
     * 
     * @version     1.0
     * 
     * @param       array       $line           The line to be printed
     * @param       array       $columnWidths   The widths of the columns
     * @return      string                      The resulting string 
     */
    public static function printT($body, $head = null)
    {
        // ---------------------------------------------------------------------
        // 1. Find column widths to use
        // ---------------------------------------------------------------------
        $columnWidths = self::computeColumnWidths($body,$head);
        
        // ---------------------------------------------------------------------
        // 2. Print header
        // ---------------------------------------------------------------------
        if($head !== null)
        {
            self::printConsole(self::printBlankLine($columnWidths));
            self::printConsole(self::printLine($head,$columnWidths));
        }
        
        // ---------------------------------------------------------------------
        // 3. Print body
        // ---------------------------------------------------------------------
        self::printConsole(self::printBlankLine($columnWidths));
        foreach($body as $index => $row)
        {
            self::printConsole(self::printLine($row,$columnWidths));
        }
        self::printConsole(self::printBlankLine($columnWidths));
    }
    
    /**
     * private static function computeColumnWidths($body,$head = null)
     * 
     * This function computes the sizes of the columns depending on the size of
     * what they will contain.
     * 
     * @author      Antoine Durieux
     * 
     * @version     1.0
     * 
     * @param       array       $body           The body of the table
     * @param       array       $head           The header of the table
     * @return      array                       The maximum size of a columnt 
     */
    private static function computeColumnWidths($body,$head = null)
    {
        $columnWidths = array();
        // In case we have no head
        if($head!==null)
        {
            $columnWidths = array_map('mb_strlen',$head);
        }
        else
        {
            $columnWidths = array_map('mb_strlen',$body[key($body)]);
        }
        foreach($body as $index => $row)
        {
            foreach($row as $jndex => $value)
            {
                $columnWidths[$jndex] = max(mb_strlen($value),$columnWidths[$jndex]);
            }
        }
        return $columnWidths;
    }
    
    /**
     * private static function printBlankLine($columnWidths)
     * 
     * This function returns a string that corresponds to a decorating line.
     * 
     * @author      Antoine Durieux
     * 
     * @version     1.0
     * 
     * @param       array       $columnWidths   The widths of the columns
     * @return      string                      The resulting string 
     */
    private static function printBlankLine($columnWidths)
    {
        $line = '+';
        foreach($columnWidths as $index => $value)
        {
            $line .= str_repeat('-',$columnWidths[$index]+2).'+';
        }
        return $line;
    }
    
    /**
     * private static function printLine($line,$columnWidths)
     * 
     * This function returns a string that corresponds to a regular line of the 
     * table.
     * 
     * @author      Antoine Durieux
     * 
     * @version     1.0
     * 
     * @param       array       $line           The line to be printed
     * @param       array       $columnWidths   The widths of the columns
     * @return      string                      The resulting string 
     */
    private static function printLine($line,$columnWidths)
    {
        $string = '|';
        foreach($line as $index => $value)
        {
            $string .= ' '.$value.str_repeat(' ',$columnWidths[$index]-mb_strlen($value)).' |';
        }
        return $string;
    }
 
    /**
     * public static function printConsole($string)
     * 
     * This function prints a line in the console
     * 
     * @author      Antoine Durieux
     * 
     * @version     1.0
     * 
     * @param       string       $string           The string to print in the console
     */
    public static function printConsole($string)
    {
        self::$channel->writeln($string);
    }
    
    // =========================================================================
    //                                   SETTERS
    // =========================================================================
    
    /**
     * public static function setChannel(OutputInterface $channel)
     * 
     * This function sets the outputting channel.
     * 
     * @author      Antoine Durieux
     * 
     * @version     1.0
     * 
     * @param OutputInterface $channel 
     */
    public static function setChannel(OutputInterface $channel)
    {
        self::$channel = $channel;
    }
    
}



And here is a use example in a Command file of Symfony2 :
$head = array('ID', 'Name');
$body = array(
    array('1', 'John Doe'),
    array('2', 'Joe Smith'),
 );
ConsolePrinter::setChannel($output);
ConsolePrinter::printT($body, $head);
And its result :
+----+-----------+
| ID | Name      |
+----+-----------+
| 1  | John Doe  |
| 2  | Joe Smith |
+----+-----------+
Enjoy !

1 commentaire:

  1. Hey, nice helper here, I like it :)

    There is a problem although, when you want to print styled texts in the table and not lose the format.

    You can check a quick / dirty solution for that here: http://pastebin.com/zufnjsRG

    Hope that helps, cheers ;)

    RépondreSupprimer