web/Zend/Text/Table.php
changeset 0 4eba9c11703f
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/web/Zend/Text/Table.php	Mon Dec 13 18:29:26 2010 +0100
@@ -0,0 +1,532 @@
+<?php
+/**
+ * Zend Framework
+ *
+ * LICENSE
+ *
+ * This source file is subject to the new BSD license that is bundled
+ * with this package in the file LICENSE.txt.
+ * It is also available through the world-wide-web at this URL:
+ * http://framework.zend.com/license/new-bsd
+ * If you did not receive a copy of the license and are unable to
+ * obtain it through the world-wide-web, please send an email
+ * to license@zend.com so we can send you a copy immediately.
+ *
+ * @category  Zend
+ * @package   Zend_Text_Table
+ * @copyright  Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license   http://framework.zend.com/license/new-bsd     New BSD License
+ * @version   $Id: Table.php 20096 2010-01-06 02:05:09Z bkarwin $
+ */
+
+/**
+ * Zend_Text_Table enables developers to create tables out of characters
+ *
+ * @category  Zend
+ * @package   Zend_Text_Table
+ * @copyright  Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com)
+ * @license   http://framework.zend.com/license/new-bsd     New BSD License
+ */
+class Zend_Text_Table
+{
+    /**
+     * Auto seperator settings
+     */
+    const AUTO_SEPARATE_NONE   = 0x0;
+    const AUTO_SEPARATE_HEADER = 0x1;
+    const AUTO_SEPARATE_FOOTER = 0x2;
+    const AUTO_SEPARATE_ALL    = 0x4;
+
+    /**
+     * Decorator used for the table borders
+     *
+     * @var Zend_Text_Table_Decorator_Interface
+     */
+    protected $_decorator = null;
+
+    /**
+     * List of all column widths
+     *
+     * @var array
+     */
+    protected $_columnWidths = null;
+
+    /**
+     * Rows of the table
+     *
+     * @var array
+     */
+    protected $_rows = array();
+
+    /**
+     * Auto separation mode
+     *
+     * @var integer
+     */
+    protected $_autoSeparate = self::AUTO_SEPARATE_ALL;
+
+    /**
+     * Padding for columns
+     *
+     * @var integer
+     */
+    protected $_padding = 0;
+
+    /**
+     * Default column aligns for rows created by appendRow(array $data)
+     *
+     * @var array
+     */
+    protected $_defaultColumnAligns = array();
+
+    /**
+     * Plugin loader for decorators
+     *
+     * @var string
+     */
+    protected $_pluginLoader = null;
+
+    /**
+     * Charset which is used for input by default
+     *
+     * @var string
+     */
+    protected static $_inputCharset = 'utf-8';
+
+    /**
+     * Charset which is used internally
+     *
+     * @var string
+     */
+    protected static $_outputCharset = 'utf-8';
+
+    /**
+     * Option keys to skip when calling setOptions()
+     *
+     * @var array
+     */
+    protected $_skipOptions = array(
+        'options',
+        'config',
+        'defaultColumnAlign',
+    );
+
+    /**
+     * Create a basic table object
+     *
+     * @param  array             $columnsWidths List of all column widths
+     * @param  Zend_Config|array $options       Configuration options
+     * @throws Zend_Text_Table_Exception When no columns widths were set
+     */
+    public function __construct($options = null)
+    {
+        // Set options
+        if (is_array($options)) {
+            $this->setOptions($options);
+        } else if ($options instanceof Zend_Config) {
+            $this->setConfig($options);
+        }
+
+        // Check if column widths were set
+        // @todo When column widths were not set, assume auto-sizing
+        if ($this->_columnWidths === null) {
+            require_once 'Zend/Text/Table/Exception.php';
+            throw new Zend_Text_Table_Exception('You must define the column widths');
+        }
+
+        // If no decorator was given, use default unicode decorator
+        if ($this->_decorator === null) {
+            if (self::getOutputCharset() === 'utf-8') {
+                $this->setDecorator('unicode');
+            } else {
+                $this->setDecorator('ascii');
+            }
+        }
+    }
+
+    /**
+     * Set options from array
+     *
+     * @param  array $options Configuration for Zend_Text_Table
+     * @return Zend_Text_Table
+     */
+    public function setOptions(array $options)
+    {
+        foreach ($options as $key => $value) {
+            if (in_array(strtolower($key), $this->_skipOptions)) {
+                continue;
+            }
+
+            $method = 'set' . ucfirst($key);
+            if (method_exists($this, $method)) {
+                $this->$method($value);
+            }
+        }
+
+        return $this;
+    }
+
+    /**
+     * Set options from config object
+     *
+     * @param  Zend_Config $config Configuration for Zend_Text_Table
+     * @return Zend_Text_Table
+     */
+    public function setConfig(Zend_Config $config)
+    {
+        return $this->setOptions($config->toArray());
+    }
+
+    /**
+     * Set column widths
+     *
+     * @param  array $columnWidths Widths of all columns
+     * @throws Zend_Text_Table_Exception When no columns were supplied
+     * @throws Zend_Text_Table_Exception When a column has an invalid width
+     * @return Zend_Text_Table
+     */
+    public function setColumnWidths(array $columnWidths)
+    {
+        if (count($columnWidths) === 0) {
+            require_once 'Zend/Text/Table/Exception.php';
+            throw new Zend_Text_Table_Exception('You must supply at least one column');
+        }
+
+        foreach ($columnWidths as $columnNum => $columnWidth) {
+            if (is_int($columnWidth) === false or $columnWidth < 1) {
+                require_once 'Zend/Text/Table/Exception.php';
+                throw new Zend_Text_Table_Exception('Column ' . $columnNum . ' has an invalid'
+                                                    . ' column width');
+            }
+        }
+
+        $this->_columnWidths = $columnWidths;
+
+        return $this;
+    }
+
+    /**
+     * Set auto separation mode
+     *
+     * @param  integer $autoSeparate Auto separation mode
+     * @return Zend_Text_Table
+     */
+    public function setAutoSeparate($autoSeparate)
+    {
+        $this->_autoSeparate = (int) $autoSeparate;
+        return $this;
+    }
+
+    /**
+     * Set decorator
+     *
+     * @param  Zend_Text_Table_Decorator_Interface|string $decorator Decorator to use
+     * @return Zend_Text_Table
+     */
+    public function setDecorator($decorator)
+    {
+        if ($decorator instanceof Zend_Text_Table_Decorator_Interface) {
+            $this->_decorator = $decorator;
+        } else {
+            $classname        = $this->getPluginLoader()->load($decorator);
+            $this->_decorator = new $classname;
+        }
+
+        return $this;
+    }
+
+    /**
+     * Set the column padding
+     *
+     * @param  integer $padding The padding for the columns
+     * @return Zend_Text_Table
+     */
+    public function setPadding($padding)
+    {
+        $this->_padding = max(0, (int) $padding);
+        return $this;
+    }
+
+    /**
+     * Get the plugin loader for decorators
+     *
+     * @return Zend_Loader_PluginLoader
+     */
+    public function getPluginLoader()
+    {
+        if ($this->_pluginLoader === null) {
+            $prefix     = 'Zend_Text_Table_Decorator_';
+            $pathPrefix = 'Zend/Text/Table/Decorator/';
+
+            require_once 'Zend/Loader/PluginLoader.php';
+            $this->_pluginLoader = new Zend_Loader_PluginLoader(array($prefix => $pathPrefix));
+        }
+
+        return $this->_pluginLoader;
+    }
+
+    /**
+     * Set default column align for rows created by appendRow(array $data)
+     *
+     * @param  integer $columnNum
+     * @param  string  $align
+     * @return Zend_Text_Table
+     */
+    public function setDefaultColumnAlign($columnNum, $align)
+    {
+        $this->_defaultColumnAligns[$columnNum] = $align;
+
+        return $this;
+    }
+
+    /**
+     * Set the input charset for column contents
+     *
+     * @param string $charset
+     */
+    public static function setInputCharset($charset)
+    {
+        self::$_inputCharset = strtolower($charset);
+    }
+
+    /**
+     * Get the input charset for column contents
+     *
+     * @param string $charset
+     */
+    public static function getInputCharset()
+    {
+        return self::$_inputCharset;
+    }
+
+    /**
+     * Set the output charset for column contents
+     *
+     * @param string $charset
+     */
+    public static function setOutputCharset($charset)
+    {
+        self::$_outputCharset = strtolower($charset);
+    }
+
+    /**
+     * Get the output charset for column contents
+     *
+     * @param string $charset
+     */
+    public static function getOutputCharset()
+    {
+        return self::$_outputCharset;
+    }
+
+    /**
+     * Append a row to the table
+     *
+     * @param  array|Zend_Text_Table_Row $row The row to append to the table
+     * @throws Zend_Text_Table_Exception When $row is neither an array nor Zend_Zext_Table_Row
+     * @throws Zend_Text_Table_Exception When a row contains too many columns
+     * @return Zend_Text_Table
+     */
+    public function appendRow($row)
+    {
+        if (!is_array($row) && !($row instanceof Zend_Text_Table_Row)) {
+            require_once 'Zend/Text/Table/Exception.php';
+            throw new Zend_Text_Table_Exception('$row must be an array or instance of Zend_Text_Table_Row');
+        }
+
+        if (is_array($row)) {
+            if (count($row) > count($this->_columnWidths)) {
+                require_once 'Zend/Text/Table/Exception.php';
+                throw new Zend_Text_Table_Exception('Row contains too many columns');
+            }
+
+            require_once 'Zend/Text/Table/Row.php';
+
+            $data   = $row;
+            $row    = new Zend_Text_Table_Row();
+            $colNum = 0;
+            foreach ($data as $columnData) {
+                if (isset($this->_defaultColumnAligns[$colNum])) {
+                    $align = $this->_defaultColumnAligns[$colNum];
+                } else {
+                    $align = null;
+                }
+
+                $row->appendColumn(new Zend_Text_Table_Column($columnData, $align));
+                $colNum++;
+            }
+        }
+
+        $this->_rows[] = $row;
+
+        return $this;
+    }
+
+    /**
+     * Render the table
+     *
+     * @throws Zend_Text_Table_Exception When no rows were added to the table
+     * @return string
+     */
+    public function render()
+    {
+        // There should be at least one row
+        if (count($this->_rows) === 0) {
+            require_once 'Zend/Text/Table/Exception.php';
+            throw new Zend_Text_Table_Exception('No rows were added to the table yet');
+        }
+
+        // Initiate the result variable
+        $result = '';
+
+        // Count total columns
+        $totalNumColumns = count($this->_columnWidths);
+
+        // Now render all rows, starting from the first one
+        $numRows = count($this->_rows);
+        foreach ($this->_rows as $rowNum => $row) {
+            // Get all column widths
+            if (isset($columnWidths) === true) {
+                $lastColumnWidths = $columnWidths;
+            }
+
+            $renderedRow  = $row->render($this->_columnWidths, $this->_decorator, $this->_padding);
+            $columnWidths = $row->getColumnWidths();
+            $numColumns   = count($columnWidths);
+
+            // Check what we have to draw
+            if ($rowNum === 0) {
+                // If this is the first row, draw the table top
+                $result .= $this->_decorator->getTopLeft();
+
+                foreach ($columnWidths as $columnNum => $columnWidth) {
+                    $result .= str_repeat($this->_decorator->getHorizontal(),
+                                          $columnWidth);
+
+                    if (($columnNum + 1) === $numColumns) {
+                        $result .= $this->_decorator->getTopRight();
+                    } else {
+                        $result .= $this->_decorator->getHorizontalDown();
+                    }
+                }
+
+                $result .= "\n";
+            } else {
+                // Else check if we have to draw the row separator
+                if ($this->_autoSeparate & self::AUTO_SEPARATE_ALL) {
+                    $drawSeparator = true;
+                } else if ($rowNum === 1 && $this->_autoSeparate & self::AUTO_SEPARATE_HEADER) {
+                    $drawSeparator = true;
+                } else if ($rowNum === ($numRows - 1) && $this->_autoSeparate & self::AUTO_SEPARATE_FOOTER) {
+                    $drawSeparator = true;
+                } else {
+                    $drawSeparator = false;
+                }
+
+                if ($drawSeparator) {
+                    $result .= $this->_decorator->getVerticalRight();
+
+                    $currentUpperColumn = 0;
+                    $currentLowerColumn = 0;
+                    $currentUpperWidth  = 0;
+                    $currentLowerWidth  = 0;
+
+                    // Loop through all column widths
+                    foreach ($this->_columnWidths as $columnNum => $columnWidth) {
+                        // Add the horizontal line
+                        $result .= str_repeat($this->_decorator->getHorizontal(),
+                                              $columnWidth);
+
+                        // If this is the last line, break out
+                        if (($columnNum + 1) === $totalNumColumns) {
+                            break;
+                        }
+
+                        // Else check, which connector style has to be used
+                        $connector          = 0x0;
+                        $currentUpperWidth += $columnWidth;
+                        $currentLowerWidth += $columnWidth;
+
+                        if ($lastColumnWidths[$currentUpperColumn] === $currentUpperWidth) {
+                            $connector          |= 0x1;
+                            $currentUpperColumn += 1;
+                            $currentUpperWidth   = 0;
+                        } else {
+                            $currentUpperWidth += 1;
+                        }
+
+                        if ($columnWidths[$currentLowerColumn] === $currentLowerWidth) {
+                            $connector          |= 0x2;
+                            $currentLowerColumn += 1;
+                            $currentLowerWidth   = 0;
+                        } else {
+                            $currentLowerWidth += 1;
+                        }
+
+                        switch ($connector) {
+                            case 0x0:
+                                $result .= $this->_decorator->getHorizontal();
+                                break;
+
+                            case 0x1:
+                                $result .= $this->_decorator->getHorizontalUp();
+                                break;
+
+                            case 0x2:
+                                $result .= $this->_decorator->getHorizontalDown();
+                                break;
+
+                            case 0x3:
+                                $result .= $this->_decorator->getCross();
+                                break;
+
+                            default:
+                                // This can never happen, but the CS tells I have to have it ...
+                                break;
+                        }
+                    }
+
+                    $result .= $this->_decorator->getVerticalLeft() . "\n";
+                }
+            }
+
+            // Add the rendered row to the result
+            $result .= $renderedRow;
+
+            // If this is the last row, draw the table bottom
+            if (($rowNum + 1) === $numRows) {
+                $result .= $this->_decorator->getBottomLeft();
+
+                foreach ($columnWidths as $columnNum => $columnWidth) {
+                    $result .= str_repeat($this->_decorator->getHorizontal(),
+                                          $columnWidth);
+
+                    if (($columnNum + 1) === $numColumns) {
+                        $result .= $this->_decorator->getBottomRight();
+                    } else {
+                        $result .= $this->_decorator->getHorizontalUp();
+                    }
+                }
+
+                $result .= "\n";
+            }
+        }
+
+        return $result;
+    }
+
+    /**
+     * Magic method which returns the rendered table
+     *
+     * @return string
+     */
+    public function __toString()
+    {
+        try {
+            return $this->render();
+        } catch (Exception $e) {
+            trigger_error($e->getMessage(), E_USER_ERROR);
+        }
+
+    }
+}