setOptions($options); } // If no decorator was given, use default unicode decorator if ($this->decorator === null) { if (static::getOutputCharset() === 'utf-8') { $this->setDecorator('unicode'); } else { $this->setDecorator('ascii'); } } } /** * Set options from array * * @param array $options Configuration for Table * @return 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 column widths * * @param array $columnWidths Widths of all columns * @throws Exception\InvalidArgumentException When no columns were supplied * @throws Exception\InvalidArgumentException When a column has an invalid width * @return Table */ public function setColumnWidths(array $columnWidths) { if (! $columnWidths) { throw new Exception\InvalidArgumentException('You must supply at least one column'); } foreach ($columnWidths as $columnNum => $columnWidth) { if (is_int($columnWidth) === false or $columnWidth < 1) { throw new Exception\InvalidArgumentException('Column ' . $columnNum . ' has an invalid column width'); } } $this->columnWidths = $columnWidths; return $this; } /** * Set auto separation mode * * @param int $autoSeparate Auto separation mode * @return Table */ public function setAutoSeparate($autoSeparate) { $this->autoSeparate = (int) $autoSeparate; return $this; } /** * Set decorator * * @param Decorator|string $decorator Decorator to use * @return Table */ public function setDecorator($decorator) { if (! $decorator instanceof Decorator) { $decorator = $this->getDecoratorManager()->get($decorator); } $this->decorator = $decorator; return $this; } /** * Set the column padding * * @param int $padding The padding for the columns * @return Table */ public function setPadding($padding) { $this->padding = max(0, (int) $padding); return $this; } /** * Get the plugin manager for decorators * * @return DecoratorManager */ public function getDecoratorManager() { if ($this->decoratorManager instanceof DecoratorManager) { return $this->decoratorManager; } $this->setDecoratorManager(new DecoratorManager(new ServiceManager())); return $this->decoratorManager; } /** * Set the plugin manager instance for decorators * * @param DecoratorManager $decoratorManager * @return Table */ public function setDecoratorManager(DecoratorManager $decoratorManager) { $this->decoratorManager = $decoratorManager; return $this; } /** * Set default column align for rows created by appendRow(array $data) * * @param int $columnNum * @param string $align * @return 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) { static::$inputCharset = strtolower($charset); } /** * Get the input charset for column contents * * @return string */ public static function getInputCharset() { return static::$inputCharset; } /** * Set the output charset for column contents * * @param string $charset */ public static function setOutputCharset($charset) { static::$outputCharset = strtolower($charset); } /** * Get the output charset for column contents * * @return string */ public static function getOutputCharset() { return static::$outputCharset; } /** * Append a row to the table * * @param array|Row $row The row to append to the table * @throws Exception\InvalidArgumentException When $row is neither an array nor Laminas\Text\Table\Row * @throws Exception\OverflowException When a row contains too many columns * @return Table */ public function appendRow($row) { if (! is_array($row) && ! ($row instanceof Row)) { throw new Exception\InvalidArgumentException('$row must be an array or instance of Laminas\Text\Table\Row'); } if (is_array($row)) { if (count($row) > count($this->columnWidths)) { throw new Exception\OverflowException('Row contains too many columns'); } $data = $row; $row = new Row(); $colNum = 0; foreach ($data as $columnData) { if (isset($this->defaultColumnAligns[$colNum])) { $align = $this->defaultColumnAligns[$colNum]; } else { $align = null; } $row->appendColumn(new Column($columnData, $align)); $colNum++; } } $this->rows[] = $row; return $this; } /** * Render the table * * @throws Exception\UnexpectedValueException When no rows were added to the table * @return string */ public function render() { // There should be at least one row if (! $this->rows) { throw new Exception\UnexpectedValueException('No rows were added to the table yet'); } // Initiate the result variable $result = ''; // Count total columns $totalNumColumns = count($this->columnWidths); // Check if we have a horizontal character defined $hasHorizontal = $this->decorator->getHorizontal() !== ''; // 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 && $hasHorizontal) { // 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 (! $hasHorizontal) { $drawSeparator = false; // there is no horizontal character; } elseif ($this->autoSeparate & self::AUTO_SEPARATE_ALL) { $drawSeparator = true; } elseif ($rowNum === 1 && $this->autoSeparate & self::AUTO_SEPARATE_HEADER) { $drawSeparator = true; } elseif ($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; // Add horizontal lines // 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 && $hasHorizontal) { $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); } } }