elementObj; // Close any open paragraph. $params->document->paragraphClose(); // Do additional actions if the parent element is a list. // In this case we need to finish the list and re-open it later // after the table has been closed! --> tables may not be part of a list item in ODT! $interrupted = false; if (!isset($tableStyleName)) { $tableStyleName = $params->document->getStyleName('table'); } $list_item = $params->document->state->getCurrentListItem(); if (isset($list_item)) { // We are in a list item. Query indentation settings. $list = $list_item->getList(); if (isset($list)) { $list_style_name = $list->getStyleName(); $list_style = $params->document->getStyle($list_style_name); if (isset($list_style)) { // The list level stored in the list item/from the parser // might not be correct. Count 'list' states to get level. $level = $params->document->state->countClass('list'); // Create a table style for indenting the table. // We try to achieve this by substracting the list indentation // from the width of the table and right align it! // (if not done yet, the name must be unique!) $count = $params->document->state->getElementCount('table')+1; $style_name = 'Table'.$count.'_Indentation_Level'.$level; if (!$params->document->styleExists($style_name)) { $style_obj = clone $params->document->getStyle($tableStyleName); $style_obj->setProperty('style-name', $style_name); if (isset($style_obj)) { $max = $params->document->getAbsWidthMindMargins(); $indent = 0 + ODTUnits::getDigits($list_style->getPropertyFromLevel($level, 'margin-left')); $style_obj->setProperty('margin-left', ($indent).'cm'); if ($style_obj->getProperty('width') == NULL && $style_obj->getProperty('rel-width')) { $style_obj->setProperty('width', ($max-$indent).'cm'); } $style_obj->setProperty('align', 'left'); $params->document->addAutomaticStyle($style_obj); } } $tableStyleName = $style_name; } } // Close all open lists and remember their style (may be nested!) $lists = array(); $first = true; $iterations = 0; $list = $params->document->state->getCurrentList(); while (isset($list)) { // Close list items if ($first == true) { $first = false; $params->document->listContentClose(); } $params->document->listItemClose(); // Now we are in the list state! // Get the lists style name before closing it. $lists [] = $list->getStyleName(); // Reset saved last paragraph position to -1 to prevent change of the paragraph style $list->setListLastParagraphPosition(-1); $params->document->listClose(); if (!isset($params->document->state) || $params->document->state->getCurrent()->getElementName() == 'root') { break; } // List has been closed (and removed from stack). Get next. $list = $params->document->state->getCurrentList(); // Just to prevent endless loops in case of an error! $iterations++; if ($iterations == 50) { $params->content .= 'Error: ENDLESS LOOP!'; break; } } $interrupted = true; } if (!isset($elementObj)) { $properties = array(); ODTUtility::openHTMLElement ($params, $properties, $element, $attributes); } $table = new ODTElementTable($tableStyleName, $maxcols, $numrows); $params->document->state->enter($table); if ($interrupted == true) { // Set marker that list has been interrupted $table->setListInterrupted(true); // Save the lists array as temporary data // in THIS state because this is the state that we get back // to in table_close!!! // (we closed the ODT list, we can't access its state info anymore! // So we use the table state to save the style name!) $table->setTemp($lists); } $table->setHTMLElement ($element); $params->content .= $table->getOpeningTag(); } /** * Close/finish a table */ public static function tableClose(ODTInternalParams $params){ $table = $params->document->state->getCurrentTable(); if (!isset($table)) { // ??? Error. Not table found. return; } if ($params->document->state->getInTableRow()) { // If we are still inside a table row then close it first, // to prevent an error or broken document. $params->document->tableRowClose(); } $interrupted = $table->getListInterrupted(); $lists = NULL; if ($interrupted) { $lists = $table->getTemp(); } // Eventually adjust table width. $table->adjustWidth ($params); // Close the table. ODTUtility::closeHTMLElement ($params, $params->document->state->getHTMLElement()); $params->content .= $table->getClosingTag($params->content); $params->document->state->leave(); // Do additional actions required if we interrupted a list, // see table_open() if ($interrupted) { // Re-open list(s) with original style! // (in revers order of lists array) $max = count($lists); for ($index = $max ; $index > 0 ; $index--) { $params->document->listOpen(true, $lists [$index-1]); // If this is not the most inner list then we need to open // a list item too! if ($index > 0) { $params->document->listItemOpen($max-$index); } } // DO NOT set marker that list is not interrupted anymore, yet! // The renderer will still call listcontent_close and listitem_close! // The marker will only be reset on the next call from the renderer to listitem_open!!! //$table->setListInterrupted(false); } } /** * @param array $properties */ public static function tableAddColumn (ODTInternalParams $params, $styleNameSet=NULL, &$styleNameGet=NULL){ // Create new column $column = new ODTElementTableColumn(); $params->document->state->enter($column); if (isset($styleNameSet)) { // Change automatically assigned style name. $column->setStyleName($styleNameSet); } // Return style name to caller. $styleNameGet = $column->getStyleName(); // Never create any new document content here!!! // Columns have already been added on table open or are // re-written on table close. $params->document->state->leave(); } /** * Open a table row */ public static function tableRowOpen(ODTInternalParams $params, $styleName=NULL, $element=NULL, $attributes=NULL){ if ($params->document->state->getInTableRow()) { // If we are still inside a table row then close it first, // to prevent an error or broken document. $params->document->tableRowClose(); } if (!isset($element)) { $element = 'tr'; } if (!isset($params->elementObj)) { $properties = array(); ODTUtility::openHTMLElement ($params, $properties, $element, $attributes); } $row = new ODTElementTableRow($styleName); $params->document->state->enter($row); $params->content .= $row->getOpeningTag(); $row->setHTMLElement ($element); } /** * Close a table row */ public static function tableRowClose(ODTInternalParams $params){ if ($params->document->state->getInTableCell()) { // If we are still inside a table cell then close it first, // to prevent an error or broken document. $params->document->tableCellClose(); } ODTUtility::closeHTMLElement ($params, $params->document->state->getHTMLElement()); $params->document->closeCurrentElement(); } /** * Open a table header cell * * @param int $colspan * @param int $rowspan * @param string $align left|center|right */ public static function tableHeaderOpen(ODTInternalParams $params, $colspan = 1, $rowspan = 1, $align = "left", $cellStyle=NULL, $paragraphStyle=NULL, $element=NULL, $attributes=NULL){ if (!isset($element)) { $element = 'th'; } // Are style names given? If not, use defaults. if (empty($cellStyle)) { $cellStyle = $params->document->getStyleName('table header'); } if (empty($paragraphStyle)) { $paragraphStyle = $params->document->getStyleName('table heading'); } if (!isset($params->elementObj)) { $properties = array(); ODTUtility::openHTMLElement ($params, $properties, $element, $attributes); } // ODT has no element for the table header. // We mark the state with a differnt class to be able // to differ between a normal cell and a header cell. $header_cell = new ODTElementTableHeaderCell ($cellStyle, $colspan, $rowspan); $params->document->state->enter($header_cell); $header_cell->setHTMLElement ($element); // Encode table (header) cell. $params->content .= $header_cell->getOpeningTag(); // Open new paragraph with table heading style. $params->document->paragraphOpen($paragraphStyle); } /** * Close a table header cell */ public static function tableHeaderClose(ODTInternalParams $params){ $params->document->paragraphClose(); ODTUtility::closeHTMLElement ($params, $params->document->state->getHTMLElement()); $params->document->closeCurrentElement(); } /** * Open a table cell * * @param int $colspan * @param int $rowspan * @param string $align left|center|right */ public static function tableCellOpen(ODTInternalParams $params, $colspan = 1, $rowspan = 1, $align = "left", $cellStyle=NULL, $paragraphStyle=NULL, $element=NULL, $attributes=NULL){ if (!isset($element)) { $element = 'td'; } if ($params->document->state->getInTableCell()) { // If we are still inside a table cell then close it first, // to prevent an error or broken document. $params->document->tableCellClose(); } // Are style names given? If not, use defaults. if (empty($cellStyle)) { $cellStyle = $params->document->getStyleName('table cell'); } if (empty($paragraphStyle)) { // Open paragraph with required alignment. if (!$align) $align = "left"; $paragraphStyle = $params->document->getStyleName('tablealign '.$align); } if (!isset($params->elementObj)) { $properties = array(); ODTUtility::openHTMLElement ($params, $properties, $element, $attributes); } $cell = new ODTElementTableCell ($cellStyle, $colspan, $rowspan); $params->document->state->enter($cell); $cell->setHTMLElement ($element); // Encode table cell. $params->content .= $cell->getOpeningTag(); // Open paragraph. $params->document->paragraphOpen($paragraphStyle); } /** * Close a table cell */ public static function tableCellClose(ODTInternalParams $params){ $params->document->paragraphClose(); ODTUtility::closeHTMLElement ($params, $params->document->state->getHTMLElement()); $params->document->closeCurrentElement(); } /** * This function opens a new table using the style as set in the imported CSS $import. * So, the function requires the helper class 'helper_plugin_odt_cssimport'. * The CSS style is selected by the element type 'td' and the specified classes in $classes. * * This function calls _odtTableOpenUseProperties. See the function description for supported properties. * * The table should be closed by calling 'table_close()'. * * @author LarsDW223 * * @param cssimportnew $import * @param $classes * @param null $baseURL * @param null $element * @param null $maxcols * @param null $numrows */ public static function tableOpenUseCSS(ODTInternalParams $params, $maxcols=NULL, $numrows=NULL, $element=NULL, $attributes=NULL){ if (!isset($element)) { $element = 'table'; } $properties = array(); ODTUtility::openHTMLElement ($params, $properties, $element, $attributes); $params->elementObj = $params->htmlStack->getCurrentElement(); self::tableOpenUseProperties($params, $properties, $maxcols, $numrows); } /** * This function opens a new table using the style as set in the assoziative array $properties. * The parameters in the array should be named as the CSS property names e.g. 'width'. * * The currently supported properties are: * width, border-collapse, background-color * * The table must be closed by calling 'table_close'. * * @author LarsDW223 * * @param array $properties * @param null $maxcols * @param null $numrows */ public static function tableOpenUseProperties (ODTInternalParams $params, $properties, $maxcols = 0, $numrows = 0){ $elementObj = $params->elementObj; // Eventually adjust table width. if ( !empty ($properties ['width']) ) { if ( $properties ['width'] [strlen($properties ['width'])-1] != '%' ) { // Width has got an absolute value. // Some units are not supported by ODT for table width (e.g. 'px'). // So we better convert it to points. $properties ['width'] = $params->document->toPoints($properties ['width'], 'x'); } } // Create style. // FIXME: fix disabled_props, ask state for current max width... $style_obj = ODTTableStyle::createTableTableStyle($properties, NULL, 17); $params->document->addAutomaticStyle($style_obj); $style_name = $style_obj->getProperty('style-name'); // Open the table referencing our style. $params->elementObj = $elementObj; self::tableOpen($params, $maxcols, $numrows, $style_name); } /** * @param array $properties */ public static function tableAddColumnUseProperties (ODTInternalParams $params, array $properties = NULL){ // Add column and set/query assigned style name $styleName = $properties ['style-name']; $styleNameGet = ''; self::tableAddColumn ($params, $styleName, $styleNameGet); // Overwrite/Create column style for actual column $properties ['style-name'] = $styleNameGet; $style_obj = ODTTableColumnStyle::createTableColumnStyle ($properties); $params->document->addAutomaticStyle($style_obj); } /** * @param helper_plugin_odt_cssimport $import * @param $classes * @param null $baseURL * @param null $element * @param int $colspan * @param int $rowspan */ public static function tableHeaderOpenUseCSS(ODTInternalParams $params, $colspan = 1, $rowspan = 1, $element=NULL, $attributes=NULL){ if (!isset($element)) { $element = 'th'; } $properties = array(); ODTUtility::openHTMLElement ($params, $properties, $element, $attributes); $params->elementObj = $params->htmlStack->getCurrentElement(); self::tableHeaderOpenUseProperties($params, $properties, $colspan, $rowspan); } /** * @param null $properties * @param int $colspan * @param int $rowspan */ public static function tableHeaderOpenUseProperties (ODTInternalParams $params, $properties = NULL, $colspan = 1, $rowspan = 1){ // Open cell, second parameter MUST BE true to indicate we are in the header. self::tableCellOpenUsePropertiesInternal ($params, $properties, true, $colspan, $rowspan); } /** * This function opens a new table row using the style as set in the imported CSS $import. * So, the function requires the helper class 'helper_plugin_odt_cssimport'. * The CSS style is selected by the element type 'td' and the specified classes in $classes. * * This function calls _odtTableRowOpenUseProperties. See the function description for supported properties. * * The row should be closed by calling 'tablerow_close()'. * * @author LarsDW223 * @param helper_plugin_odt_cssimport $import * @param $classes * @param null $baseURL * @param null $element */ public static function tableRowOpenUseCSS(ODTInternalParams $params, $element=NULL, $attributes=NULL){ if (!isset($element)) { $element = 'tr'; } $properties = array(); ODTUtility::openHTMLElement ($params, $properties, $element, $attributes); $params->elementObj = $params->htmlStack->getCurrentElement(); self::tableRowOpenUseProperties($params, $properties); } /** * @param array $properties */ public static function tableRowOpenUseProperties (ODTInternalParams $params, $properties){ // Create style. $style_obj = ODTTableRowStyle::createTableRowStyle ($properties); $params->document->addAutomaticStyle($style_obj); $style_name = $style_obj->getProperty('style-name'); // Open table row with our new style. self::tableRowOpen($params, $style_name); } /** * This function opens a new table cell using the style as set in the imported CSS $import. * So, the function requires the helper class 'helper_plugin_odt_cssimport'. * The CSS style is selected by the element type 'td' and the specified classes in $classes. * * This function calls _odtTableCellOpenUseProperties. See the function description for supported properties. * * The cell should be closed by calling 'tablecell_close()'. * * @author LarsDW223 * * @param helper_plugin_odt_cssimport $import * @param $classes * @param null $baseURL * @param null $element */ public static function tableCellOpenUseCSS(ODTInternalParams $params, $element=NULL, $attributes=NULL, $colspan = 1, $rowspan = 1){ if (!isset($element)) { $element = 'td'; } $properties = array(); ODTUtility::openHTMLElement ($params, $properties, $element, $attributes); $params->elementObj = $params->htmlStack->getCurrentElement(); self::tableCellOpenUseProperties($params, $properties, $colspan, $rowspan); } /** * @param $properties */ public static function tableCellOpenUseProperties (ODTInternalParams $params, $properties = NULL, $colspan = 1, $rowspan = 1){ self::tableCellOpenUsePropertiesInternal ($params, $properties, false, $colspan, $rowspan); } /** * @param $properties * @param bool $inHeader * @param int $colspan * @param int $rowspan */ static protected function tableCellOpenUsePropertiesInternal (ODTInternalParams $params, $properties, $inHeader = false, $colspan = 1, $rowspan = 1){ $disabled = array (); // Create style name. (Re-enable background-color!) $style_obj = ODTTableCellStyle::createTableCellStyle ($properties); $params->document->addAutomaticStyle($style_obj); $style_name = $style_obj->getProperty('style-name'); // Create a paragraph style for the paragraph within the cell. // Disable properties that belong to the table cell style. $disabled ['border'] = 1; $disabled ['border-left'] = 1; $disabled ['border-right'] = 1; $disabled ['border-top'] = 1; $disabled ['border-bottom'] = 1; $disabled ['background-color'] = 1; $disabled ['background-image'] = 1; $disabled ['vertical-align'] = 1; $style_obj = ODTParagraphStyle::createParagraphStyle ($properties, $disabled); $params->document->addAutomaticStyle($style_obj); $style_name_paragraph = $style_obj->getProperty('style-name'); // Open header or normal cell. if ($inHeader) { self::tableHeaderOpen($params, $colspan, $rowspan, NULL, $style_name, $style_name_paragraph); } else { self::tableCellOpen($params, $colspan, $rowspan, NULL, $style_name, $style_name_paragraph); } // There might be properties in the table header cell/normal cell which in ODT belong to the // column, e.g. 'width'. So eventually adjust column style. self::adjustColumnStyle($params, $properties); } static protected function adjustColumnStyle(ODTInternalParams $params, array $properties) { $table = $params->document->state->getCurrentTable(); if (!isset($table)) { // ??? Error. Not table found. return; } $curr_column = $table->getTableCurrentColumn(); $table_column_styles = $table->getTableColumnStyles(); $style_name = $table_column_styles [$curr_column-1]; $style_obj = $params->document->getStyle($style_name); if (isset($style_obj)) { if (!empty($properties ['width'])) { $width = $properties ['width']; $length = strlen ($width); $width = $params->document->toPoints($width, 'x'); $style_obj->setProperty('column-width', $width); } } else { self::tableAddColumnUseProperties ($params, $properties); } } }