| <?php |
| /** |
| * File containing the ezcDocumentDocbookToRstTableHandler class. |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| * @package Document |
| * @version //autogen// |
| * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0 |
| */ |
| |
| /** |
| * Visit tables |
| * |
| * The RST table rendering algorithm tries losely to fit a table in the |
| * provided document dimensions. This may not always work for over long words, |
| * or if the table cells contain literal blocks which can not be wrapped. |
| * |
| * For this the algorithm estiamtes the available width per column, equally |
| * distributes this available width over all columns (which might be far from |
| * optimal), and extends the total table width if some cell content exceeds the |
| * column width. |
| * |
| * The initial table cell estiation happens inside the function |
| * estimateColumnWidths() which you might want to extend to fit your needs |
| * better. |
| * |
| * @package Document |
| * @version //autogen// |
| */ |
| class ezcDocumentDocbookToRstTableHandler extends ezcDocumentDocbookToRstBaseHandler |
| { |
| /** |
| * Estimation of table column widths |
| * |
| * Returns an spoecification array with the column widths for the tables, |
| * which will be generated by this class. The array should contain as many |
| * values as the table contains columns, each specifying the width of the |
| * respective column. |
| * |
| * This basic implementation just divides the document width (specified by |
| * the wordwrap option in the converter class) by the amount of columns |
| * found in the given table. This might be far from optimal. |
| * |
| * @param ezcDocumentElementVisitorConverter $converter |
| * @param DOMElement $table |
| * @return array |
| */ |
| protected function estimateColumnWidths( ezcDocumentElementVisitorConverter $converter, DOMElement $table ) |
| { |
| // Get some row from the table |
| $row = $table->getElementsByTagName( 'row' )->item( 0 ); |
| $columns = 0; |
| foreach ( $row->childNodes as $child ) |
| { |
| if ( ( $child->nodeType === XML_ELEMENT_NODE ) && |
| ( $child->tagName === 'entry' ) ) |
| { |
| ++$columns; |
| } |
| } |
| |
| $columnWidth = floor( ( $converter->options->wordWrap - ( 2 * ( $columns - 1 ) ) ) / $columns ); |
| return array_fill( 0, $columns, $columnWidth ); |
| } |
| |
| /** |
| * Get maximum line length |
| * |
| * Calculate the maximum line length from an array of textual lines. |
| * |
| * @param array $lines |
| * @return int |
| */ |
| protected function getMaxLineLength( array $lines ) |
| { |
| $maxLength = 0; |
| foreach ( $lines as $line ) |
| { |
| $maxLength = max( $maxLength, strlen( $line ) ); |
| } |
| |
| return $maxLength; |
| } |
| |
| /** |
| * Handle a node |
| * |
| * Handle / transform a given node, and return the result of the |
| * conversion. |
| * |
| * @param ezcDocumentElementVisitorConverter $converter |
| * @param DOMElement $node |
| * @param mixed $root |
| * @return mixed |
| */ |
| public function handle( ezcDocumentElementVisitorConverter $converter, DOMElement $node, $root ) |
| { |
| $columns = $this->estimateColumnWidths( $converter, $node ); |
| $rows = $node->getElementsByTagName( 'row' ); |
| $table = array(); |
| $rowLines = array(); |
| $rowNr = 0; |
| $oldWidth = $converter->options->wordWrap; |
| |
| // Create contents from tables cells recursively and calculate their |
| // content width, extending the column width, if necessary. |
| foreach ( $rows as $row ) |
| { |
| $cellNr = 0; |
| $rowLines[$rowNr] = 1; |
| foreach ( $row->childNodes as $cell ) |
| { |
| if ( ( $cell->nodeType === XML_ELEMENT_NODE ) && |
| ( $cell->tagName === 'entry' ) ) |
| { |
| ezcDocumentDocbookToRstConverter::$wordWrap = $columns[$cellNr]; |
| $table[$rowNr][$cellNr] = $cellContent = explode( "\n", trim( $converter->visitChildren( $cell, '' ) ) ); |
| $rowLines[$rowNr] = max( $rowLines[$rowNr], count( $cellContent ) ); |
| $columns[$cellNr] = max( $columns[$cellNr], $this->getMaxLineLength( $cellContent ) ); |
| ++$cellNr; |
| } |
| } |
| ++$rowNr; |
| } |
| ezcDocumentDocbookToRstConverter::$wordWrap = $converter->options->wordWrap; |
| |
| // Build table row seperator |
| $separator = ''; |
| foreach ( $columns as $width ) |
| { |
| $separator .= str_repeat( '-', $width ) . ' '; |
| } |
| $separator = rtrim( $separator ) . "\n"; |
| |
| // Check if table has a header. RST does only support the foirst row as |
| // a header row, so we will only check for this, and render all |
| // subsequent header lines as plain contents. |
| $hasHeader = (bool) $node->getElementsByTagName( 'thead' )->length; |
| |
| // Draw table |
| $cellCount = count( $columns ); |
| $root .= str_replace( '-', '=', $separator ); |
| foreach ( $table as $rowNr => $row ) |
| { |
| for ( $line = 0; $line < $rowLines[$rowNr]; ++$line ) |
| { |
| for ( $cellNr = 0; $cellNr < $cellCount; ++$cellNr ) |
| { |
| $last = ( $cellNr >= ( $cellCount - 1 ) ); |
| $width = $columns[$cellNr] + ( $last ? 0 : 2 ); |
| $lineContent = isset( $table[$rowNr][$cellNr][$line] ) ? $table[$rowNr][$cellNr][$line] : ''; |
| $root .= $last ? $lineContent . "\n" : str_pad( rtrim( $lineContent ), $width, ' ' ); |
| } |
| } |
| |
| // Always add row seperator |
| if ( ( $hasHeader && |
| ( $rowNr === 0 ) ) || |
| ( $rowNr >= ( count( $table ) - 1 ) ) ) |
| { |
| $root .= str_replace( '-', '=', $separator ); |
| } |
| else |
| { |
| $root .= $separator; |
| } |
| } |
| |
| $root .= "\n"; |
| |
| return $root; |
| } |
| } |
| |
| ?> |