sseletskyy
7/31/2013 - 5:28 PM

Ordinarily, I would suggest use of PEAR's Console_Table package, this is just an example solution for the first test suggested at http://php

Ordinarily, I would suggest use of PEAR's Console_Table package, this is just an example solution for the first test suggested at http://phpixie.com/blog/test-tasks-for-php-interviews-that-developers-will-enjoy-solving/

<?php
/**
 * ArrayAsAcsiiTable.php
 * 31-Jul-2013
 *
 * Ordinarily, I would suggest use of PEAR's Console_Table package, this
 * is just an example solution for the first test suggested at
 * http://phpixie.com/blog/test-tasks-for-php-interviews-that-developers-will-enjoy-solving/
 *
 * PHP Version 5
 *
 * @category ConsoleTable
 * @package  ConsoleTable
 * @author   Ken Guest <ken@linux.ie>
 * @license  BSD http://www.opensource.org/licenses/bsd-license.php
 * @link     .
 */

/**
 * ConsoleTable class to print an associative array as an ASCII table.
 *
 * @category  ConsoleTable
 * @package   ConsoleTable
 * @author    Ken Guest <ken@linux.ie>
 * @copyright 2013 Ken Guest.
 * @license   BSD http://www.opensource.org/licenses/bsd-license.php
 * @link      .
 */
class ConsoleTable
{
    const CORNER = '+';
    const HORIZONTAL = '-';
    const VERTICAL = '|';

    public $color = false;

    /**
     * __construct
     *
     * @param array $config optional config array
     *
     * @return ConsoleTable
     */
    public function __construct(array $config = [])
    {
        $this->setConfig($config);
    }

    /**
     * Configure instance of this class according to given config array.
     *
     * Supported keys:
     * * color - enable color support (boolean)
     *
     * @param array $config Config array
     *
     * @return ConsoleTable
     */
    public function setConfig(array $config)
    {
        if (isset($config['color'])) {
            $this->color = (bool) $config['color'];
        }
        return $this;
    }

    /**
     * Given associative array of data, determine field lenghts required for
     * displaying the data in tabular form on the console.
     *
     * @param array $data Assoc. array
     *
     * @return array
     */
    private function _getColLengths($data)
    {
        $lengths = array_flip(array_keys($data[0]));
        foreach ($data as $datum) {
            $keys = array_keys($datum);
            foreach ($keys as $index=>$key) {
                $$key = strlen($datum[$key]);
                if ($$key > $lengths[$key]) {
                    $lengths[$key] = $$key;
                }
                if ($lengths[$key] < strlen($key)) {
                    $lengths[$key] = strlen($key);
                }
            }
        }
        return $lengths;
    }

    /**
     * Given associative array of field lenghts, return string
     * containing a horizontal bar for representing them.
     *
     * @param array $colLengths Assoc. Array
     *
     * @return string
     */
    private function _getBar(array $colLengths)
    {
        $bar = self::CORNER;
        foreach ($colLengths as $length) {
            $filler = str_pad('', $length + 2, self::HORIZONTAL);
            $bar = $bar . $filler . self::CORNER;
        }
        return $bar;
    }

    /**
     * Start ANSI color code sequence.
     *
     * @param string $color name of color
     *
     * @return void
     */
    private function _startColor($color)
    {
        if ($this->color == true) {
            switch(strtolower($color)) {
            case 'black':
                echo "\033[30m";
                break;
            case 'red':
                echo "\033[31m";
                break;
            case 'green':
                echo "\033[32m";
                break;
            case 'brown':
                echo "\033[33m";
            case 'blue':
                echo "\033[34m";
                break;
            case 'purple':
                echo "\033[35m";
                break;
            case 'cyan':
                echo "\033[36m";
                break;
            case 'white':
                echo "\033[37m";
                break;
            }
        }
    }

    /**
     * Terminiate ANSI color codes.
     *
     * @return void
     */
    private function _endColor()
    {
        if ($this->color == true) {
            echo "\033[37m";
        }
    }

    /**
     * draw table of data passed in associative array
     *
     * If a key is named 'color' or 'colour' and color support is enabled then
     * output that data in the named colour.
     *
     * @param array $data Associative array of data
     *
     * @return ConsoleTable
     */
    public function draw($data)
    {
        $colLengths = $this->_getColLengths($data);
        $bar = $this->_getBar($colLengths);
        echo $bar, "\n";
        $keys = array_keys($data[0]);
        foreach ($keys as $key) {
            echo self::VERTICAL . ' ' . str_pad($key, $colLengths[$key] + 1);
        }
        echo self::VERTICAL, "\n";
        echo $bar, "\n";
        foreach ($data as $datum) {
            foreach ($keys as $key) {
                echo self::VERTICAL . ' ';
                $lkey = strtolower($key);
                if ($lkey == 'color' || $lkey = 'colour') {
                    $this->_startColor($datum[$key]);
                }
                echo str_pad($datum[$key], $colLengths[$key] + 1);
                if ($lkey == 'color' || $lkey = 'colour') {
                    $this->_endColor();
                }
            }
            echo self::VERTICAL, "\n";
        }
        echo $bar, "\n";
        return $this;
    }
}

$data = array(
    array(
        'Name' => 'Trixie',
        'Color' => 'Green',
        'Element' => 'Earth',
        'Likes' => 'Flowers',
        ),
    array(
        'Name' => 'Tinkerbell',
        'Element' => 'Air',
        'Likes' => 'Singing',
        'Color' => 'Blue',
        ),
    array(
        'Element' => 'Water',
        'Likes' => 'Dancing',
        'Name' => 'Blum',
        'Color' => 'Pink',
        ),
);

$table = new ConsoleTable();
$table->setConfig(['color' => true])->draw($data);
?>